Merge branches 'misc', 'sa1100-for-next' and 'spectre' into for-linus
This commit is contained in:
commit
97b6f89f72
@ -1282,65 +1282,6 @@ int sa1111_get_audio_rate(struct sa1111_dev *sadev)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sa1111_get_audio_rate);
|
EXPORT_SYMBOL(sa1111_get_audio_rate);
|
||||||
|
|
||||||
void sa1111_set_io_dir(struct sa1111_dev *sadev,
|
|
||||||
unsigned int bits, unsigned int dir,
|
|
||||||
unsigned int sleep_dir)
|
|
||||||
{
|
|
||||||
struct sa1111 *sachip = sa1111_chip_driver(sadev);
|
|
||||||
unsigned long flags;
|
|
||||||
unsigned int val;
|
|
||||||
void __iomem *gpio = sachip->base + SA1111_GPIO;
|
|
||||||
|
|
||||||
#define MODIFY_BITS(port, mask, dir) \
|
|
||||||
if (mask) { \
|
|
||||||
val = readl_relaxed(port); \
|
|
||||||
val &= ~(mask); \
|
|
||||||
val |= (dir) & (mask); \
|
|
||||||
writel_relaxed(val, port); \
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_irqsave(&sachip->lock, flags);
|
|
||||||
MODIFY_BITS(gpio + SA1111_GPIO_PADDR, bits & 15, dir);
|
|
||||||
MODIFY_BITS(gpio + SA1111_GPIO_PBDDR, (bits >> 8) & 255, dir >> 8);
|
|
||||||
MODIFY_BITS(gpio + SA1111_GPIO_PCDDR, (bits >> 16) & 255, dir >> 16);
|
|
||||||
|
|
||||||
MODIFY_BITS(gpio + SA1111_GPIO_PASDR, bits & 15, sleep_dir);
|
|
||||||
MODIFY_BITS(gpio + SA1111_GPIO_PBSDR, (bits >> 8) & 255, sleep_dir >> 8);
|
|
||||||
MODIFY_BITS(gpio + SA1111_GPIO_PCSDR, (bits >> 16) & 255, sleep_dir >> 16);
|
|
||||||
spin_unlock_irqrestore(&sachip->lock, flags);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(sa1111_set_io_dir);
|
|
||||||
|
|
||||||
void sa1111_set_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v)
|
|
||||||
{
|
|
||||||
struct sa1111 *sachip = sa1111_chip_driver(sadev);
|
|
||||||
unsigned long flags;
|
|
||||||
unsigned int val;
|
|
||||||
void __iomem *gpio = sachip->base + SA1111_GPIO;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&sachip->lock, flags);
|
|
||||||
MODIFY_BITS(gpio + SA1111_GPIO_PADWR, bits & 15, v);
|
|
||||||
MODIFY_BITS(gpio + SA1111_GPIO_PBDWR, (bits >> 8) & 255, v >> 8);
|
|
||||||
MODIFY_BITS(gpio + SA1111_GPIO_PCDWR, (bits >> 16) & 255, v >> 16);
|
|
||||||
spin_unlock_irqrestore(&sachip->lock, flags);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(sa1111_set_io);
|
|
||||||
|
|
||||||
void sa1111_set_sleep_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v)
|
|
||||||
{
|
|
||||||
struct sa1111 *sachip = sa1111_chip_driver(sadev);
|
|
||||||
unsigned long flags;
|
|
||||||
unsigned int val;
|
|
||||||
void __iomem *gpio = sachip->base + SA1111_GPIO;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&sachip->lock, flags);
|
|
||||||
MODIFY_BITS(gpio + SA1111_GPIO_PASSR, bits & 15, v);
|
|
||||||
MODIFY_BITS(gpio + SA1111_GPIO_PBSSR, (bits >> 8) & 255, v >> 8);
|
|
||||||
MODIFY_BITS(gpio + SA1111_GPIO_PCSSR, (bits >> 16) & 255, v >> 16);
|
|
||||||
spin_unlock_irqrestore(&sachip->lock, flags);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(sa1111_set_sleep_io);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Individual device operations.
|
* Individual device operations.
|
||||||
*/
|
*/
|
||||||
|
@ -111,6 +111,7 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
|
||||||
extern unsigned int processor_id;
|
extern unsigned int processor_id;
|
||||||
|
struct proc_info_list *lookup_processor(u32 midr);
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_CP15
|
#ifdef CONFIG_CPU_CP15
|
||||||
#define read_cpuid(reg) \
|
#define read_cpuid(reg) \
|
||||||
|
@ -433,10 +433,6 @@ int sa1111_check_dma_bug(dma_addr_t addr);
|
|||||||
int sa1111_driver_register(struct sa1111_driver *);
|
int sa1111_driver_register(struct sa1111_driver *);
|
||||||
void sa1111_driver_unregister(struct sa1111_driver *);
|
void sa1111_driver_unregister(struct sa1111_driver *);
|
||||||
|
|
||||||
void sa1111_set_io_dir(struct sa1111_dev *sadev, unsigned int bits, unsigned int dir, unsigned int sleep_dir);
|
|
||||||
void sa1111_set_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v);
|
|
||||||
void sa1111_set_sleep_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v);
|
|
||||||
|
|
||||||
struct sa1111_platform_data {
|
struct sa1111_platform_data {
|
||||||
int irq_base; /* base for cascaded on-chip IRQs */
|
int irq_base; /* base for cascaded on-chip IRQs */
|
||||||
unsigned disable_devs;
|
unsigned disable_devs;
|
||||||
|
@ -23,7 +23,7 @@ struct mm_struct;
|
|||||||
/*
|
/*
|
||||||
* Don't change this structure - ASM code relies on it.
|
* Don't change this structure - ASM code relies on it.
|
||||||
*/
|
*/
|
||||||
extern struct processor {
|
struct processor {
|
||||||
/* MISC
|
/* MISC
|
||||||
* get data abort address/flags
|
* get data abort address/flags
|
||||||
*/
|
*/
|
||||||
@ -79,9 +79,13 @@ extern struct processor {
|
|||||||
unsigned int suspend_size;
|
unsigned int suspend_size;
|
||||||
void (*do_suspend)(void *);
|
void (*do_suspend)(void *);
|
||||||
void (*do_resume)(void *);
|
void (*do_resume)(void *);
|
||||||
} processor;
|
};
|
||||||
|
|
||||||
#ifndef MULTI_CPU
|
#ifndef MULTI_CPU
|
||||||
|
static inline void init_proc_vtable(const struct processor *p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
extern void cpu_proc_init(void);
|
extern void cpu_proc_init(void);
|
||||||
extern void cpu_proc_fin(void);
|
extern void cpu_proc_fin(void);
|
||||||
extern int cpu_do_idle(void);
|
extern int cpu_do_idle(void);
|
||||||
@ -98,17 +102,50 @@ extern void cpu_reset(unsigned long addr, bool hvc) __attribute__((noreturn));
|
|||||||
extern void cpu_do_suspend(void *);
|
extern void cpu_do_suspend(void *);
|
||||||
extern void cpu_do_resume(void *);
|
extern void cpu_do_resume(void *);
|
||||||
#else
|
#else
|
||||||
#define cpu_proc_init processor._proc_init
|
|
||||||
#define cpu_proc_fin processor._proc_fin
|
|
||||||
#define cpu_reset processor.reset
|
|
||||||
#define cpu_do_idle processor._do_idle
|
|
||||||
#define cpu_dcache_clean_area processor.dcache_clean_area
|
|
||||||
#define cpu_set_pte_ext processor.set_pte_ext
|
|
||||||
#define cpu_do_switch_mm processor.switch_mm
|
|
||||||
|
|
||||||
/* These three are private to arch/arm/kernel/suspend.c */
|
extern struct processor processor;
|
||||||
#define cpu_do_suspend processor.do_suspend
|
#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
|
||||||
#define cpu_do_resume processor.do_resume
|
#include <linux/smp.h>
|
||||||
|
/*
|
||||||
|
* This can't be a per-cpu variable because we need to access it before
|
||||||
|
* per-cpu has been initialised. We have a couple of functions that are
|
||||||
|
* called in a pre-emptible context, and so can't use smp_processor_id()
|
||||||
|
* there, hence PROC_TABLE(). We insist in init_proc_vtable() that the
|
||||||
|
* function pointers for these are identical across all CPUs.
|
||||||
|
*/
|
||||||
|
extern struct processor *cpu_vtable[];
|
||||||
|
#define PROC_VTABLE(f) cpu_vtable[smp_processor_id()]->f
|
||||||
|
#define PROC_TABLE(f) cpu_vtable[0]->f
|
||||||
|
static inline void init_proc_vtable(const struct processor *p)
|
||||||
|
{
|
||||||
|
unsigned int cpu = smp_processor_id();
|
||||||
|
*cpu_vtable[cpu] = *p;
|
||||||
|
WARN_ON_ONCE(cpu_vtable[cpu]->dcache_clean_area !=
|
||||||
|
cpu_vtable[0]->dcache_clean_area);
|
||||||
|
WARN_ON_ONCE(cpu_vtable[cpu]->set_pte_ext !=
|
||||||
|
cpu_vtable[0]->set_pte_ext);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define PROC_VTABLE(f) processor.f
|
||||||
|
#define PROC_TABLE(f) processor.f
|
||||||
|
static inline void init_proc_vtable(const struct processor *p)
|
||||||
|
{
|
||||||
|
processor = *p;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define cpu_proc_init PROC_VTABLE(_proc_init)
|
||||||
|
#define cpu_check_bugs PROC_VTABLE(check_bugs)
|
||||||
|
#define cpu_proc_fin PROC_VTABLE(_proc_fin)
|
||||||
|
#define cpu_reset PROC_VTABLE(reset)
|
||||||
|
#define cpu_do_idle PROC_VTABLE(_do_idle)
|
||||||
|
#define cpu_dcache_clean_area PROC_TABLE(dcache_clean_area)
|
||||||
|
#define cpu_set_pte_ext PROC_TABLE(set_pte_ext)
|
||||||
|
#define cpu_do_switch_mm PROC_VTABLE(switch_mm)
|
||||||
|
|
||||||
|
/* These two are private to arch/arm/kernel/suspend.c */
|
||||||
|
#define cpu_do_suspend PROC_VTABLE(do_suspend)
|
||||||
|
#define cpu_do_resume PROC_VTABLE(do_resume)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void cpu_resume(void);
|
extern void cpu_resume(void);
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
void check_other_bugs(void)
|
void check_other_bugs(void)
|
||||||
{
|
{
|
||||||
#ifdef MULTI_CPU
|
#ifdef MULTI_CPU
|
||||||
if (processor.check_bugs)
|
if (cpu_check_bugs)
|
||||||
processor.check_bugs();
|
cpu_check_bugs();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,6 +145,9 @@ __mmap_switched_data:
|
|||||||
#endif
|
#endif
|
||||||
.size __mmap_switched_data, . - __mmap_switched_data
|
.size __mmap_switched_data, . - __mmap_switched_data
|
||||||
|
|
||||||
|
__FINIT
|
||||||
|
.text
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This provides a C-API version of __lookup_processor_type
|
* This provides a C-API version of __lookup_processor_type
|
||||||
*/
|
*/
|
||||||
@ -156,9 +159,6 @@ ENTRY(lookup_processor_type)
|
|||||||
ldmfd sp!, {r4 - r6, r9, pc}
|
ldmfd sp!, {r4 - r6, r9, pc}
|
||||||
ENDPROC(lookup_processor_type)
|
ENDPROC(lookup_processor_type)
|
||||||
|
|
||||||
__FINIT
|
|
||||||
.text
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read processor ID register (CP#15, CR0), and look up in the linker-built
|
* Read processor ID register (CP#15, CR0), and look up in the linker-built
|
||||||
* supported processor list. Note that we can't use the absolute addresses
|
* supported processor list. Note that we can't use the absolute addresses
|
||||||
|
@ -114,6 +114,11 @@ EXPORT_SYMBOL(elf_hwcap2);
|
|||||||
|
|
||||||
#ifdef MULTI_CPU
|
#ifdef MULTI_CPU
|
||||||
struct processor processor __ro_after_init;
|
struct processor processor __ro_after_init;
|
||||||
|
#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
|
||||||
|
struct processor *cpu_vtable[NR_CPUS] = {
|
||||||
|
[0] = &processor,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef MULTI_TLB
|
#ifdef MULTI_TLB
|
||||||
struct cpu_tlb_fns cpu_tlb __ro_after_init;
|
struct cpu_tlb_fns cpu_tlb __ro_after_init;
|
||||||
@ -666,28 +671,33 @@ static void __init smp_build_mpidr_hash(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* locate processor in the list of supported processor types. The linker
|
||||||
|
* builds this table for us from the entries in arch/arm/mm/proc-*.S
|
||||||
|
*/
|
||||||
|
struct proc_info_list *lookup_processor(u32 midr)
|
||||||
|
{
|
||||||
|
struct proc_info_list *list = lookup_processor_type(midr);
|
||||||
|
|
||||||
|
if (!list) {
|
||||||
|
pr_err("CPU%u: configuration botched (ID %08x), CPU halted\n",
|
||||||
|
smp_processor_id(), midr);
|
||||||
|
while (1)
|
||||||
|
/* can't use cpu_relax() here as it may require MMU setup */;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
static void __init setup_processor(void)
|
static void __init setup_processor(void)
|
||||||
{
|
{
|
||||||
struct proc_info_list *list;
|
unsigned int midr = read_cpuid_id();
|
||||||
|
struct proc_info_list *list = lookup_processor(midr);
|
||||||
/*
|
|
||||||
* locate processor in the list of supported processor
|
|
||||||
* types. The linker builds this table for us from the
|
|
||||||
* entries in arch/arm/mm/proc-*.S
|
|
||||||
*/
|
|
||||||
list = lookup_processor_type(read_cpuid_id());
|
|
||||||
if (!list) {
|
|
||||||
pr_err("CPU configuration botched (ID %08x), unable to continue.\n",
|
|
||||||
read_cpuid_id());
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu_name = list->cpu_name;
|
cpu_name = list->cpu_name;
|
||||||
__cpu_architecture = __get_cpu_architecture();
|
__cpu_architecture = __get_cpu_architecture();
|
||||||
|
|
||||||
#ifdef MULTI_CPU
|
init_proc_vtable(list->proc);
|
||||||
processor = *list->proc;
|
|
||||||
#endif
|
|
||||||
#ifdef MULTI_TLB
|
#ifdef MULTI_TLB
|
||||||
cpu_tlb = *list->tlb;
|
cpu_tlb = *list->tlb;
|
||||||
#endif
|
#endif
|
||||||
@ -699,7 +709,7 @@ static void __init setup_processor(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
pr_info("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
|
pr_info("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
|
||||||
cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
|
list->cpu_name, midr, midr & 15,
|
||||||
proc_arch[cpu_architecture()], get_cr());
|
proc_arch[cpu_architecture()], get_cr());
|
||||||
|
|
||||||
snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
|
snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/pgalloc.h>
|
#include <asm/pgalloc.h>
|
||||||
|
#include <asm/procinfo.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
#include <asm/tlbflush.h>
|
#include <asm/tlbflush.h>
|
||||||
@ -102,6 +103,30 @@ static unsigned long get_arch_pgd(pgd_t *pgd)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
|
||||||
|
static int secondary_biglittle_prepare(unsigned int cpu)
|
||||||
|
{
|
||||||
|
if (!cpu_vtable[cpu])
|
||||||
|
cpu_vtable[cpu] = kzalloc(sizeof(*cpu_vtable[cpu]), GFP_KERNEL);
|
||||||
|
|
||||||
|
return cpu_vtable[cpu] ? 0 : -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secondary_biglittle_init(void)
|
||||||
|
{
|
||||||
|
init_proc_vtable(lookup_processor(read_cpuid_id())->proc);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int secondary_biglittle_prepare(unsigned int cpu)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void secondary_biglittle_init(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int __cpu_up(unsigned int cpu, struct task_struct *idle)
|
int __cpu_up(unsigned int cpu, struct task_struct *idle)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -109,6 +134,10 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
|
|||||||
if (!smp_ops.smp_boot_secondary)
|
if (!smp_ops.smp_boot_secondary)
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
|
|
||||||
|
ret = secondary_biglittle_prepare(cpu);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to tell the secondary core where to find
|
* We need to tell the secondary core where to find
|
||||||
* its stack and the page tables.
|
* its stack and the page tables.
|
||||||
@ -359,6 +388,8 @@ asmlinkage void secondary_start_kernel(void)
|
|||||||
struct mm_struct *mm = &init_mm;
|
struct mm_struct *mm = &init_mm;
|
||||||
unsigned int cpu;
|
unsigned int cpu;
|
||||||
|
|
||||||
|
secondary_biglittle_init();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The identity mapping is uncached (strongly ordered), so
|
* The identity mapping is uncached (strongly ordered), so
|
||||||
* switch away from it before attempting any exclusive accesses.
|
* switch away from it before attempting any exclusive accesses.
|
||||||
|
@ -46,6 +46,7 @@ config ARCH_LUBBOCK
|
|||||||
|
|
||||||
config MACH_MAINSTONE
|
config MACH_MAINSTONE
|
||||||
bool "Intel HCDDBBVA0 Development Platform (aka Mainstone)"
|
bool "Intel HCDDBBVA0 Development Platform (aka Mainstone)"
|
||||||
|
select GPIO_REG
|
||||||
select PXA27x
|
select PXA27x
|
||||||
|
|
||||||
config MACH_ZYLONITE
|
config MACH_ZYLONITE
|
||||||
|
@ -119,6 +119,10 @@
|
|||||||
#define MST_PCMCIA_PWR_VCC_33 0x8 /* voltage VCC = 3.3V */
|
#define MST_PCMCIA_PWR_VCC_33 0x8 /* voltage VCC = 3.3V */
|
||||||
#define MST_PCMCIA_PWR_VCC_50 0x4 /* voltage VCC = 5.0V */
|
#define MST_PCMCIA_PWR_VCC_50 0x4 /* voltage VCC = 5.0V */
|
||||||
|
|
||||||
|
#define MST_PCMCIA_INPUTS \
|
||||||
|
(MST_PCMCIA_nIRQ | MST_PCMCIA_nSPKR_BVD2 | MST_PCMCIA_nSTSCHG_BVD1 | \
|
||||||
|
MST_PCMCIA_nVS2 | MST_PCMCIA_nVS1 | MST_PCMCIA_nCD)
|
||||||
|
|
||||||
/* board specific IRQs */
|
/* board specific IRQs */
|
||||||
#define MAINSTONE_NR_IRQS IRQ_BOARD_START
|
#define MAINSTONE_NR_IRQS IRQ_BOARD_START
|
||||||
|
|
||||||
|
@ -136,10 +136,26 @@ static struct pxa2xx_udc_mach_info udc_info __initdata = {
|
|||||||
// no D+ pullup; lubbock can't connect/disconnect in software
|
// no D+ pullup; lubbock can't connect/disconnect in software
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* GPIOs for SA1111 PCMCIA */
|
||||||
|
static struct gpiod_lookup_table sa1111_pcmcia_gpio_table = {
|
||||||
|
.dev_id = "1800",
|
||||||
|
.table = {
|
||||||
|
{ "sa1111", 0, "a0vpp", GPIO_ACTIVE_HIGH },
|
||||||
|
{ "sa1111", 1, "a1vpp", GPIO_ACTIVE_HIGH },
|
||||||
|
{ "sa1111", 2, "a0vcc", GPIO_ACTIVE_HIGH },
|
||||||
|
{ "sa1111", 3, "a1vcc", GPIO_ACTIVE_HIGH },
|
||||||
|
{ "lubbock", 14, "b0vcc", GPIO_ACTIVE_HIGH },
|
||||||
|
{ "lubbock", 15, "b1vcc", GPIO_ACTIVE_HIGH },
|
||||||
|
{ },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static void lubbock_init_pcmcia(void)
|
static void lubbock_init_pcmcia(void)
|
||||||
{
|
{
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
|
||||||
|
gpiod_add_lookup_table(&sa1111_pcmcia_gpio_table);
|
||||||
|
|
||||||
/* Add an alias for the SA1111 PCMCIA clock */
|
/* Add an alias for the SA1111 PCMCIA clock */
|
||||||
clk = clk_get_sys("pxa2xx-pcmcia", NULL);
|
clk = clk_get_sys("pxa2xx-pcmcia", NULL);
|
||||||
if (!IS_ERR(clk)) {
|
if (!IS_ERR(clk)) {
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/gpio/gpio-reg.h>
|
||||||
#include <linux/gpio/machine.h>
|
#include <linux/gpio/machine.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
@ -507,12 +508,64 @@ static void __init mainstone_init_keypad(void)
|
|||||||
static inline void mainstone_init_keypad(void) {}
|
static inline void mainstone_init_keypad(void) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int mst_pcmcia0_irqs[11] = {
|
||||||
|
[0 ... 10] = -1,
|
||||||
|
[5] = MAINSTONE_S0_CD_IRQ,
|
||||||
|
[8] = MAINSTONE_S0_STSCHG_IRQ,
|
||||||
|
[10] = MAINSTONE_S0_IRQ,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int mst_pcmcia1_irqs[11] = {
|
||||||
|
[0 ... 10] = -1,
|
||||||
|
[5] = MAINSTONE_S1_CD_IRQ,
|
||||||
|
[8] = MAINSTONE_S1_STSCHG_IRQ,
|
||||||
|
[10] = MAINSTONE_S1_IRQ,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gpiod_lookup_table mainstone_pcmcia_gpio_table = {
|
||||||
|
.dev_id = "pxa2xx-pcmcia",
|
||||||
|
.table = {
|
||||||
|
GPIO_LOOKUP("mst-pcmcia0", 0, "a0vpp", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia0", 1, "a1vpp", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia0", 2, "a0vcc", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia0", 3, "a1vcc", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia0", 4, "areset", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia0", 5, "adetect", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia0", 6, "avs1", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia0", 7, "avs2", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia0", 8, "abvd1", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia0", 9, "abvd2", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia0", 10, "aready", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia1", 0, "b0vpp", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia1", 1, "b1vpp", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia1", 2, "b0vcc", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia1", 3, "b1vcc", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia1", 4, "breset", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia1", 5, "bdetect", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia1", 6, "bvs1", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia1", 7, "bvs2", GPIO_ACTIVE_LOW),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia1", 8, "bbvd1", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia1", 9, "bbvd2", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("mst-pcmcia1", 10, "bready", GPIO_ACTIVE_HIGH),
|
||||||
|
{ },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static void __init mainstone_init(void)
|
static void __init mainstone_init(void)
|
||||||
{
|
{
|
||||||
int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
|
int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
|
||||||
|
|
||||||
pxa2xx_mfp_config(ARRAY_AND_SIZE(mainstone_pin_config));
|
pxa2xx_mfp_config(ARRAY_AND_SIZE(mainstone_pin_config));
|
||||||
|
|
||||||
|
/* Register board control register(s) as GPIOs */
|
||||||
|
gpio_reg_init(NULL, (void __iomem *)&MST_PCMCIA0, -1, 11,
|
||||||
|
"mst-pcmcia0", MST_PCMCIA_INPUTS, 0, NULL,
|
||||||
|
NULL, mst_pcmcia0_irqs);
|
||||||
|
gpio_reg_init(NULL, (void __iomem *)&MST_PCMCIA1, -1, 11,
|
||||||
|
"mst-pcmcia1", MST_PCMCIA_INPUTS, 0, NULL,
|
||||||
|
NULL, mst_pcmcia1_irqs);
|
||||||
|
gpiod_add_lookup_table(&mainstone_pcmcia_gpio_table);
|
||||||
|
|
||||||
pxa_set_ffuart_info(NULL);
|
pxa_set_ffuart_info(NULL);
|
||||||
pxa_set_btuart_info(NULL);
|
pxa_set_btuart_info(NULL);
|
||||||
pxa_set_stuart_info(NULL);
|
pxa_set_stuart_info(NULL);
|
||||||
|
@ -6,6 +6,7 @@ config SA1100_ASSABET
|
|||||||
bool "Assabet"
|
bool "Assabet"
|
||||||
select ARM_SA1110_CPUFREQ
|
select ARM_SA1110_CPUFREQ
|
||||||
select GPIO_REG
|
select GPIO_REG
|
||||||
|
select LEDS_GPIO_REGISTER
|
||||||
select REGULATOR
|
select REGULATOR
|
||||||
select REGULATOR_FIXED_VOLTAGE
|
select REGULATOR_FIXED_VOLTAGE
|
||||||
help
|
help
|
||||||
@ -24,6 +25,7 @@ config ASSABET_NEPONSET
|
|||||||
config SA1100_CERF
|
config SA1100_CERF
|
||||||
bool "CerfBoard"
|
bool "CerfBoard"
|
||||||
select ARM_SA1110_CPUFREQ
|
select ARM_SA1110_CPUFREQ
|
||||||
|
select LEDS_GPIO_REGISTER
|
||||||
help
|
help
|
||||||
The Intrinsyc CerfBoard is based on the StrongARM 1110 (Discontinued).
|
The Intrinsyc CerfBoard is based on the StrongARM 1110 (Discontinued).
|
||||||
More information is available at:
|
More information is available at:
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/gpio/gpio-reg.h>
|
#include <linux/gpio/gpio-reg.h>
|
||||||
#include <linux/gpio/machine.h>
|
#include <linux/gpio/machine.h>
|
||||||
|
#include <linux/gpio_keys.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/platform_data/sa11x0-serial.h>
|
#include <linux/platform_data/sa11x0-serial.h>
|
||||||
#include <linux/regulator/fixed.h>
|
#include <linux/regulator/fixed.h>
|
||||||
@ -101,7 +102,7 @@ static int __init assabet_init_gpio(void __iomem *reg, u32 def_val)
|
|||||||
|
|
||||||
assabet_bcr_gc = gc;
|
assabet_bcr_gc = gc;
|
||||||
|
|
||||||
return 0;
|
return gc->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -479,6 +480,49 @@ static struct gpiod_lookup_table assabet_cf_vcc_gpio_table = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gpio_led assabet_leds[] __initdata = {
|
||||||
|
{
|
||||||
|
.name = "assabet:red",
|
||||||
|
.default_trigger = "cpu0",
|
||||||
|
.active_low = 1,
|
||||||
|
.default_state = LEDS_GPIO_DEFSTATE_KEEP,
|
||||||
|
}, {
|
||||||
|
.name = "assabet:green",
|
||||||
|
.default_trigger = "heartbeat",
|
||||||
|
.active_low = 1,
|
||||||
|
.default_state = LEDS_GPIO_DEFSTATE_KEEP,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct gpio_led_platform_data assabet_leds_pdata __initconst = {
|
||||||
|
.num_leds = ARRAY_SIZE(assabet_leds),
|
||||||
|
.leds = assabet_leds,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gpio_keys_button assabet_keys_buttons[] = {
|
||||||
|
{
|
||||||
|
.gpio = 0,
|
||||||
|
.irq = IRQ_GPIO0,
|
||||||
|
.desc = "gpio0",
|
||||||
|
.wakeup = 1,
|
||||||
|
.can_disable = 1,
|
||||||
|
.debounce_interval = 5,
|
||||||
|
}, {
|
||||||
|
.gpio = 1,
|
||||||
|
.irq = IRQ_GPIO1,
|
||||||
|
.desc = "gpio1",
|
||||||
|
.wakeup = 1,
|
||||||
|
.can_disable = 1,
|
||||||
|
.debounce_interval = 5,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct gpio_keys_platform_data assabet_keys_pdata = {
|
||||||
|
.buttons = assabet_keys_buttons,
|
||||||
|
.nbuttons = ARRAY_SIZE(assabet_keys_buttons),
|
||||||
|
.rep = 0,
|
||||||
|
};
|
||||||
|
|
||||||
static void __init assabet_init(void)
|
static void __init assabet_init(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -533,6 +577,13 @@ static void __init assabet_init(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
platform_device_register_resndata(NULL, "gpio-keys", 0,
|
||||||
|
NULL, 0,
|
||||||
|
&assabet_keys_pdata,
|
||||||
|
sizeof(assabet_keys_pdata));
|
||||||
|
|
||||||
|
gpio_led_register_device(-1, &assabet_leds_pdata);
|
||||||
|
|
||||||
#ifndef ASSABET_PAL_VIDEO
|
#ifndef ASSABET_PAL_VIDEO
|
||||||
sa11x0_register_lcd(&lq039q2ds54_info);
|
sa11x0_register_lcd(&lq039q2ds54_info);
|
||||||
#else
|
#else
|
||||||
@ -726,92 +777,9 @@ static void __init assabet_map_io(void)
|
|||||||
sa1100_register_uart(2, 3);
|
sa1100_register_uart(2, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* LEDs */
|
|
||||||
#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
|
|
||||||
struct assabet_led {
|
|
||||||
struct led_classdev cdev;
|
|
||||||
u32 mask;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The triggers lines up below will only be used if the
|
|
||||||
* LED triggers are compiled in.
|
|
||||||
*/
|
|
||||||
static const struct {
|
|
||||||
const char *name;
|
|
||||||
const char *trigger;
|
|
||||||
} assabet_leds[] = {
|
|
||||||
{ "assabet:red", "cpu0",},
|
|
||||||
{ "assabet:green", "heartbeat", },
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The LED control in Assabet is reversed:
|
|
||||||
* - setting bit means turn off LED
|
|
||||||
* - clearing bit means turn on LED
|
|
||||||
*/
|
|
||||||
static void assabet_led_set(struct led_classdev *cdev,
|
|
||||||
enum led_brightness b)
|
|
||||||
{
|
|
||||||
struct assabet_led *led = container_of(cdev,
|
|
||||||
struct assabet_led, cdev);
|
|
||||||
|
|
||||||
if (b != LED_OFF)
|
|
||||||
ASSABET_BCR_clear(led->mask);
|
|
||||||
else
|
|
||||||
ASSABET_BCR_set(led->mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum led_brightness assabet_led_get(struct led_classdev *cdev)
|
|
||||||
{
|
|
||||||
struct assabet_led *led = container_of(cdev,
|
|
||||||
struct assabet_led, cdev);
|
|
||||||
|
|
||||||
return (ASSABET_BCR & led->mask) ? LED_OFF : LED_FULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __init assabet_leds_init(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!machine_is_assabet())
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(assabet_leds); i++) {
|
|
||||||
struct assabet_led *led;
|
|
||||||
|
|
||||||
led = kzalloc(sizeof(*led), GFP_KERNEL);
|
|
||||||
if (!led)
|
|
||||||
break;
|
|
||||||
|
|
||||||
led->cdev.name = assabet_leds[i].name;
|
|
||||||
led->cdev.brightness_set = assabet_led_set;
|
|
||||||
led->cdev.brightness_get = assabet_led_get;
|
|
||||||
led->cdev.default_trigger = assabet_leds[i].trigger;
|
|
||||||
|
|
||||||
if (!i)
|
|
||||||
led->mask = ASSABET_BCR_LED_RED;
|
|
||||||
else
|
|
||||||
led->mask = ASSABET_BCR_LED_GREEN;
|
|
||||||
|
|
||||||
if (led_classdev_register(NULL, &led->cdev) < 0) {
|
|
||||||
kfree(led);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Since we may have triggers on any subsystem, defer registration
|
|
||||||
* until after subsystem_init.
|
|
||||||
*/
|
|
||||||
fs_initcall(assabet_leds_init);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void __init assabet_init_irq(void)
|
void __init assabet_init_irq(void)
|
||||||
{
|
{
|
||||||
|
unsigned int assabet_gpio_base;
|
||||||
u32 def_val;
|
u32 def_val;
|
||||||
|
|
||||||
sa1100_init_irq();
|
sa1100_init_irq();
|
||||||
@ -826,7 +794,10 @@ void __init assabet_init_irq(void)
|
|||||||
*
|
*
|
||||||
* This must precede any driver calls to BCR_set() or BCR_clear().
|
* This must precede any driver calls to BCR_set() or BCR_clear().
|
||||||
*/
|
*/
|
||||||
assabet_init_gpio((void *)&ASSABET_BCR, def_val);
|
assabet_gpio_base = assabet_init_gpio((void *)&ASSABET_BCR, def_val);
|
||||||
|
|
||||||
|
assabet_leds[0].gpio = assabet_gpio_base + 13;
|
||||||
|
assabet_leds[1].gpio = assabet_gpio_base + 14;
|
||||||
}
|
}
|
||||||
|
|
||||||
MACHINE_START(ASSABET, "Intel-Assabet")
|
MACHINE_START(ASSABET, "Intel-Assabet")
|
||||||
|
@ -89,18 +89,8 @@ static struct gpio_led_platform_data cerf_gpio_led_info = {
|
|||||||
.num_leds = ARRAY_SIZE(cerf_gpio_leds),
|
.num_leds = ARRAY_SIZE(cerf_gpio_leds),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct platform_device cerf_leds = {
|
|
||||||
.name = "leds-gpio",
|
|
||||||
.id = -1,
|
|
||||||
.dev = {
|
|
||||||
.platform_data = &cerf_gpio_led_info,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static struct platform_device *cerf_devices[] __initdata = {
|
static struct platform_device *cerf_devices[] __initdata = {
|
||||||
&cerfuart2_device,
|
&cerfuart2_device,
|
||||||
&cerf_leds,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_SA1100_CERF_FLASH_32MB
|
#ifdef CONFIG_SA1100_CERF_FLASH_32MB
|
||||||
@ -176,6 +166,7 @@ static void __init cerf_init(void)
|
|||||||
{
|
{
|
||||||
sa11x0_ppc_configure_mcp();
|
sa11x0_ppc_configure_mcp();
|
||||||
platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices));
|
platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices));
|
||||||
|
gpio_led_register_device(-1, &cerf_gpio_led_info);
|
||||||
sa11x0_register_mtd(&cerf_flash_data, &cerf_flash_resource, 1);
|
sa11x0_register_mtd(&cerf_flash_data, &cerf_flash_resource, 1);
|
||||||
sa11x0_register_mcp(&cerf_mcp_data);
|
sa11x0_register_mcp(&cerf_mcp_data);
|
||||||
sa11x0_register_pcmcia(1, &cerf_cf_gpio_table);
|
sa11x0_register_pcmcia(1, &cerf_cf_gpio_table);
|
||||||
|
@ -235,18 +235,11 @@ void sa11x0_register_lcd(struct sa1100fb_mach_info *inf)
|
|||||||
sa11x0_register_device(&sa11x0fb_device, inf);
|
sa11x0_register_device(&sa11x0fb_device, inf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sa11x0pcmcia_legacy = true;
|
|
||||||
static struct platform_device sa11x0pcmcia_device = {
|
|
||||||
.name = "sa11x0-pcmcia",
|
|
||||||
.id = -1,
|
|
||||||
};
|
|
||||||
|
|
||||||
void sa11x0_register_pcmcia(int socket, struct gpiod_lookup_table *table)
|
void sa11x0_register_pcmcia(int socket, struct gpiod_lookup_table *table)
|
||||||
{
|
{
|
||||||
if (table)
|
if (table)
|
||||||
gpiod_add_lookup_table(table);
|
gpiod_add_lookup_table(table);
|
||||||
platform_device_register_simple("sa11x0-pcmcia", socket, NULL, 0);
|
platform_device_register_simple("sa11x0-pcmcia", socket, NULL, 0);
|
||||||
sa11x0pcmcia_legacy = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_device sa11x0mtd_device = {
|
static struct platform_device sa11x0mtd_device = {
|
||||||
@ -331,9 +324,6 @@ static int __init sa1100_init(void)
|
|||||||
{
|
{
|
||||||
pm_power_off = sa1100_power_off;
|
pm_power_off = sa1100_power_off;
|
||||||
|
|
||||||
if (sa11x0pcmcia_legacy)
|
|
||||||
platform_device_register(&sa11x0pcmcia_device);
|
|
||||||
|
|
||||||
regulator_has_full_constraints();
|
regulator_has_full_constraints();
|
||||||
|
|
||||||
return platform_add_devices(sa11x0_devices, ARRAY_SIZE(sa11x0_devices));
|
return platform_add_devices(sa11x0_devices, ARRAY_SIZE(sa11x0_devices));
|
||||||
|
@ -126,6 +126,7 @@ static void __init h3100_mach_init(void)
|
|||||||
{
|
{
|
||||||
h3xxx_mach_init();
|
h3xxx_mach_init();
|
||||||
|
|
||||||
|
sa11x0_register_pcmcia(-1, NULL);
|
||||||
sa11x0_register_lcd(&h3100_lcd_info);
|
sa11x0_register_lcd(&h3100_lcd_info);
|
||||||
sa11x0_register_irda(&h3100_irda_data);
|
sa11x0_register_irda(&h3100_irda_data);
|
||||||
}
|
}
|
||||||
|
@ -190,6 +190,17 @@ static struct platform_device s1d13xxxfb_device = {
|
|||||||
.resource = s1d13xxxfb_resources,
|
.resource = s1d13xxxfb_resources,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gpiod_lookup_table jornada_pcmcia_gpiod_table = {
|
||||||
|
.dev_id = "1800",
|
||||||
|
.table = {
|
||||||
|
GPIO_LOOKUP("sa1111", 0, "s0-power", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("sa1111", 1, "s1-power", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("sa1111", 2, "s0-3v", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("sa1111", 3, "s1-3v", GPIO_ACTIVE_HIGH),
|
||||||
|
{ },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static struct resource sa1111_resources[] = {
|
static struct resource sa1111_resources[] = {
|
||||||
[0] = DEFINE_RES_MEM(SA1111REGSTART, SA1111REGLEN),
|
[0] = DEFINE_RES_MEM(SA1111REGSTART, SA1111REGLEN),
|
||||||
[1] = DEFINE_RES_IRQ(IRQ_GPIO1),
|
[1] = DEFINE_RES_IRQ(IRQ_GPIO1),
|
||||||
@ -265,6 +276,7 @@ static int __init jornada720_init(void)
|
|||||||
udelay(20); /* give it some time to restart */
|
udelay(20); /* give it some time to restart */
|
||||||
|
|
||||||
gpiod_add_lookup_table(&jornada_ts_gpiod_table);
|
gpiod_add_lookup_table(&jornada_ts_gpiod_table);
|
||||||
|
gpiod_add_lookup_table(&jornada_pcmcia_gpiod_table);
|
||||||
|
|
||||||
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
|
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/gpio/driver.h>
|
#include <linux/gpio/driver.h>
|
||||||
#include <linux/gpio/gpio-reg.h>
|
#include <linux/gpio/gpio-reg.h>
|
||||||
|
#include <linux/gpio/machine.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
@ -96,6 +97,19 @@ struct neponset_drvdata {
|
|||||||
struct gpio_chip *gpio[4];
|
struct gpio_chip *gpio[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gpiod_lookup_table neponset_pcmcia_table = {
|
||||||
|
.dev_id = "1800",
|
||||||
|
.table = {
|
||||||
|
GPIO_LOOKUP("sa1111", 1, "a0vcc", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("sa1111", 0, "a1vcc", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("neponset-ncr", 5, "a0vpp", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("neponset-ncr", 6, "a1vpp", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("sa1111", 2, "b0vcc", GPIO_ACTIVE_HIGH),
|
||||||
|
GPIO_LOOKUP("sa1111", 3, "b1vcc", GPIO_ACTIVE_HIGH),
|
||||||
|
{ },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static struct neponset_drvdata *nep;
|
static struct neponset_drvdata *nep;
|
||||||
|
|
||||||
void neponset_ncr_frob(unsigned int mask, unsigned int val)
|
void neponset_ncr_frob(unsigned int mask, unsigned int val)
|
||||||
@ -374,6 +388,8 @@ static int neponset_probe(struct platform_device *dev)
|
|||||||
d->base + AUD_CTL, AUD_NGPIO, false,
|
d->base + AUD_CTL, AUD_NGPIO, false,
|
||||||
neponset_aud_names);
|
neponset_aud_names);
|
||||||
|
|
||||||
|
gpiod_add_lookup_table(&neponset_pcmcia_table);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We would set IRQ_GPIO25 to be a wake-up IRQ, but unfortunately
|
* We would set IRQ_GPIO25 to be a wake-up IRQ, but unfortunately
|
||||||
* something on the Neponset activates this IRQ on sleep (eth?)
|
* something on the Neponset activates this IRQ on sleep (eth?)
|
||||||
@ -424,6 +440,9 @@ static int neponset_remove(struct platform_device *dev)
|
|||||||
platform_device_unregister(d->sa1111);
|
platform_device_unregister(d->sa1111);
|
||||||
if (!IS_ERR(d->smc91x))
|
if (!IS_ERR(d->smc91x))
|
||||||
platform_device_unregister(d->smc91x);
|
platform_device_unregister(d->smc91x);
|
||||||
|
|
||||||
|
gpiod_remove_lookup_table(&neponset_pcmcia_table);
|
||||||
|
|
||||||
irq_set_chained_handler(irq, NULL);
|
irq_set_chained_handler(irq, NULL);
|
||||||
irq_free_descs(d->irq_base, NEP_IRQ_NR);
|
irq_free_descs(d->irq_base, NEP_IRQ_NR);
|
||||||
nep = NULL;
|
nep = NULL;
|
||||||
|
@ -274,6 +274,13 @@
|
|||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro define_processor_functions name:req, dabort:req, pabort:req, nommu=0, suspend=0, bugs=0
|
.macro define_processor_functions name:req, dabort:req, pabort:req, nommu=0, suspend=0, bugs=0
|
||||||
|
/*
|
||||||
|
* If we are building for big.Little with branch predictor hardening,
|
||||||
|
* we need the processor function tables to remain available after boot.
|
||||||
|
*/
|
||||||
|
#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
|
||||||
|
.section ".rodata"
|
||||||
|
#endif
|
||||||
.type \name\()_processor_functions, #object
|
.type \name\()_processor_functions, #object
|
||||||
.align 2
|
.align 2
|
||||||
ENTRY(\name\()_processor_functions)
|
ENTRY(\name\()_processor_functions)
|
||||||
@ -309,6 +316,9 @@ ENTRY(\name\()_processor_functions)
|
|||||||
.endif
|
.endif
|
||||||
|
|
||||||
.size \name\()_processor_functions, . - \name\()_processor_functions
|
.size \name\()_processor_functions, . - \name\()_processor_functions
|
||||||
|
#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
|
||||||
|
.previous
|
||||||
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro define_cache_functions name:req
|
.macro define_cache_functions name:req
|
||||||
|
@ -52,8 +52,6 @@ static void cpu_v7_spectre_init(void)
|
|||||||
case ARM_CPU_PART_CORTEX_A17:
|
case ARM_CPU_PART_CORTEX_A17:
|
||||||
case ARM_CPU_PART_CORTEX_A73:
|
case ARM_CPU_PART_CORTEX_A73:
|
||||||
case ARM_CPU_PART_CORTEX_A75:
|
case ARM_CPU_PART_CORTEX_A75:
|
||||||
if (processor.switch_mm != cpu_v7_bpiall_switch_mm)
|
|
||||||
goto bl_error;
|
|
||||||
per_cpu(harden_branch_predictor_fn, cpu) =
|
per_cpu(harden_branch_predictor_fn, cpu) =
|
||||||
harden_branch_predictor_bpiall;
|
harden_branch_predictor_bpiall;
|
||||||
spectre_v2_method = "BPIALL";
|
spectre_v2_method = "BPIALL";
|
||||||
@ -61,8 +59,6 @@ static void cpu_v7_spectre_init(void)
|
|||||||
|
|
||||||
case ARM_CPU_PART_CORTEX_A15:
|
case ARM_CPU_PART_CORTEX_A15:
|
||||||
case ARM_CPU_PART_BRAHMA_B15:
|
case ARM_CPU_PART_BRAHMA_B15:
|
||||||
if (processor.switch_mm != cpu_v7_iciallu_switch_mm)
|
|
||||||
goto bl_error;
|
|
||||||
per_cpu(harden_branch_predictor_fn, cpu) =
|
per_cpu(harden_branch_predictor_fn, cpu) =
|
||||||
harden_branch_predictor_iciallu;
|
harden_branch_predictor_iciallu;
|
||||||
spectre_v2_method = "ICIALLU";
|
spectre_v2_method = "ICIALLU";
|
||||||
@ -88,11 +84,9 @@ static void cpu_v7_spectre_init(void)
|
|||||||
ARM_SMCCC_ARCH_WORKAROUND_1, &res);
|
ARM_SMCCC_ARCH_WORKAROUND_1, &res);
|
||||||
if ((int)res.a0 != 0)
|
if ((int)res.a0 != 0)
|
||||||
break;
|
break;
|
||||||
if (processor.switch_mm != cpu_v7_hvc_switch_mm && cpu)
|
|
||||||
goto bl_error;
|
|
||||||
per_cpu(harden_branch_predictor_fn, cpu) =
|
per_cpu(harden_branch_predictor_fn, cpu) =
|
||||||
call_hvc_arch_workaround_1;
|
call_hvc_arch_workaround_1;
|
||||||
processor.switch_mm = cpu_v7_hvc_switch_mm;
|
cpu_do_switch_mm = cpu_v7_hvc_switch_mm;
|
||||||
spectre_v2_method = "hypervisor";
|
spectre_v2_method = "hypervisor";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -101,11 +95,9 @@ static void cpu_v7_spectre_init(void)
|
|||||||
ARM_SMCCC_ARCH_WORKAROUND_1, &res);
|
ARM_SMCCC_ARCH_WORKAROUND_1, &res);
|
||||||
if ((int)res.a0 != 0)
|
if ((int)res.a0 != 0)
|
||||||
break;
|
break;
|
||||||
if (processor.switch_mm != cpu_v7_smc_switch_mm && cpu)
|
|
||||||
goto bl_error;
|
|
||||||
per_cpu(harden_branch_predictor_fn, cpu) =
|
per_cpu(harden_branch_predictor_fn, cpu) =
|
||||||
call_smc_arch_workaround_1;
|
call_smc_arch_workaround_1;
|
||||||
processor.switch_mm = cpu_v7_smc_switch_mm;
|
cpu_do_switch_mm = cpu_v7_smc_switch_mm;
|
||||||
spectre_v2_method = "firmware";
|
spectre_v2_method = "firmware";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -119,11 +111,6 @@ static void cpu_v7_spectre_init(void)
|
|||||||
if (spectre_v2_method)
|
if (spectre_v2_method)
|
||||||
pr_info("CPU%u: Spectre v2: using %s workaround\n",
|
pr_info("CPU%u: Spectre v2: using %s workaround\n",
|
||||||
smp_processor_id(), spectre_v2_method);
|
smp_processor_id(), spectre_v2_method);
|
||||||
return;
|
|
||||||
|
|
||||||
bl_error:
|
|
||||||
pr_err("CPU%u: Spectre v2: incorrect context switching function, system vulnerable\n",
|
|
||||||
cpu);
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void cpu_v7_spectre_init(void)
|
static void cpu_v7_spectre_init(void)
|
||||||
|
@ -112,7 +112,7 @@ ENTRY(cpu_v7_hvc_switch_mm)
|
|||||||
hvc #0
|
hvc #0
|
||||||
ldmfd sp!, {r0 - r3}
|
ldmfd sp!, {r0 - r3}
|
||||||
b cpu_v7_switch_mm
|
b cpu_v7_switch_mm
|
||||||
ENDPROC(cpu_v7_smc_switch_mm)
|
ENDPROC(cpu_v7_hvc_switch_mm)
|
||||||
#endif
|
#endif
|
||||||
ENTRY(cpu_v7_iciallu_switch_mm)
|
ENTRY(cpu_v7_iciallu_switch_mm)
|
||||||
mov r3, #0
|
mov r3, #0
|
||||||
|
@ -573,7 +573,7 @@ int vfp_preserve_user_clear_hwstate(struct user_vfp *ufp,
|
|||||||
*/
|
*/
|
||||||
ufp_exc->fpexc = hwstate->fpexc;
|
ufp_exc->fpexc = hwstate->fpexc;
|
||||||
ufp_exc->fpinst = hwstate->fpinst;
|
ufp_exc->fpinst = hwstate->fpinst;
|
||||||
ufp_exc->fpinst2 = ufp_exc->fpinst2;
|
ufp_exc->fpinst2 = hwstate->fpinst2;
|
||||||
|
|
||||||
/* Ensure that VFP is disabled. */
|
/* Ensure that VFP is disabled. */
|
||||||
vfp_flush_hwstate(thread);
|
vfp_flush_hwstate(thread);
|
||||||
|
@ -63,6 +63,9 @@ config CARDBUS
|
|||||||
|
|
||||||
If unsure, say Y.
|
If unsure, say Y.
|
||||||
|
|
||||||
|
config PCMCIA_MAX1600
|
||||||
|
tristate
|
||||||
|
|
||||||
comment "PC-card bridges"
|
comment "PC-card bridges"
|
||||||
|
|
||||||
config YENTA
|
config YENTA
|
||||||
@ -191,6 +194,8 @@ config PCMCIA_SA1111
|
|||||||
select PCMCIA_SOC_COMMON
|
select PCMCIA_SOC_COMMON
|
||||||
select PCMCIA_SA11XX_BASE if ARCH_SA1100
|
select PCMCIA_SA11XX_BASE if ARCH_SA1100
|
||||||
select PCMCIA_PXA2XX if ARCH_LUBBOCK && SA1111
|
select PCMCIA_PXA2XX if ARCH_LUBBOCK && SA1111
|
||||||
|
select PCMCIA_MAX1600 if ASSABET_NEPONSET
|
||||||
|
select PCMCIA_MAX1600 if ARCH_LUBBOCK && SA1111
|
||||||
help
|
help
|
||||||
Say Y here to include support for SA1111-based PCMCIA or CF
|
Say Y here to include support for SA1111-based PCMCIA or CF
|
||||||
sockets, found on the Jornada 720, Graphicsmaster and other
|
sockets, found on the Jornada 720, Graphicsmaster and other
|
||||||
@ -207,6 +212,7 @@ config PCMCIA_PXA2XX
|
|||||||
|| MACH_VPAC270 || MACH_BALLOON3 || MACH_COLIBRI \
|
|| MACH_VPAC270 || MACH_BALLOON3 || MACH_COLIBRI \
|
||||||
|| MACH_COLIBRI320 || MACH_H4700)
|
|| MACH_COLIBRI320 || MACH_H4700)
|
||||||
select PCMCIA_SOC_COMMON
|
select PCMCIA_SOC_COMMON
|
||||||
|
select PCMCIA_MAX1600 if MACH_MAINSTONE
|
||||||
help
|
help
|
||||||
Say Y here to include support for the PXA2xx PCMCIA controller
|
Say Y here to include support for the PXA2xx PCMCIA controller
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ obj-$(CONFIG_OMAP_CF) += omap_cf.o
|
|||||||
obj-$(CONFIG_AT91_CF) += at91_cf.o
|
obj-$(CONFIG_AT91_CF) += at91_cf.o
|
||||||
obj-$(CONFIG_ELECTRA_CF) += electra_cf.o
|
obj-$(CONFIG_ELECTRA_CF) += electra_cf.o
|
||||||
obj-$(CONFIG_PCMCIA_ALCHEMY_DEVBOARD) += db1xxx_ss.o
|
obj-$(CONFIG_PCMCIA_ALCHEMY_DEVBOARD) += db1xxx_ss.o
|
||||||
|
obj-$(CONFIG_PCMCIA_MAX1600) += max1600.o
|
||||||
|
|
||||||
sa1111_cs-y += sa1111_generic.o
|
sa1111_cs-y += sa1111_generic.o
|
||||||
sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1111_neponset.o
|
sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1111_neponset.o
|
||||||
|
122
drivers/pcmcia/max1600.c
Normal file
122
drivers/pcmcia/max1600.c
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/*
|
||||||
|
* MAX1600 PCMCIA power switch library
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Russell King
|
||||||
|
*/
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/gpio/consumer.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include "max1600.h"
|
||||||
|
|
||||||
|
static const char *max1600_gpio_name[2][MAX1600_GPIO_MAX] = {
|
||||||
|
{ "a0vcc", "a1vcc", "a0vpp", "a1vpp" },
|
||||||
|
{ "b0vcc", "b1vcc", "b0vpp", "b1vpp" },
|
||||||
|
};
|
||||||
|
|
||||||
|
int max1600_init(struct device *dev, struct max1600 **ptr,
|
||||||
|
unsigned int channel, unsigned int code)
|
||||||
|
{
|
||||||
|
struct max1600 *m;
|
||||||
|
int chan;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
switch (channel) {
|
||||||
|
case MAX1600_CHAN_A:
|
||||||
|
chan = 0;
|
||||||
|
break;
|
||||||
|
case MAX1600_CHAN_B:
|
||||||
|
chan = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code != MAX1600_CODE_LOW && code != MAX1600_CODE_HIGH)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
m = devm_kzalloc(dev, sizeof(*m), GFP_KERNEL);
|
||||||
|
if (!m)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
m->dev = dev;
|
||||||
|
m->code = code;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX1600_GPIO_MAX; i++) {
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
name = max1600_gpio_name[chan][i];
|
||||||
|
if (i != MAX1600_GPIO_0VPP) {
|
||||||
|
m->gpio[i] = devm_gpiod_get(dev, name, GPIOD_OUT_LOW);
|
||||||
|
} else {
|
||||||
|
m->gpio[i] = devm_gpiod_get_optional(dev, name,
|
||||||
|
GPIOD_OUT_LOW);
|
||||||
|
if (!m->gpio[i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (IS_ERR(m->gpio[i]))
|
||||||
|
return PTR_ERR(m->gpio[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
*ptr = m;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(max1600_init);
|
||||||
|
|
||||||
|
int max1600_configure(struct max1600 *m, unsigned int vcc, unsigned int vpp)
|
||||||
|
{
|
||||||
|
DECLARE_BITMAP(values, MAX1600_GPIO_MAX) = { 0, };
|
||||||
|
int n = MAX1600_GPIO_0VPP;
|
||||||
|
|
||||||
|
if (m->gpio[MAX1600_GPIO_0VPP]) {
|
||||||
|
if (vpp == 0) {
|
||||||
|
__assign_bit(MAX1600_GPIO_0VPP, values, 0);
|
||||||
|
__assign_bit(MAX1600_GPIO_1VPP, values, 0);
|
||||||
|
} else if (vpp == 120) {
|
||||||
|
__assign_bit(MAX1600_GPIO_0VPP, values, 0);
|
||||||
|
__assign_bit(MAX1600_GPIO_1VPP, values, 1);
|
||||||
|
} else if (vpp == vcc) {
|
||||||
|
__assign_bit(MAX1600_GPIO_0VPP, values, 1);
|
||||||
|
__assign_bit(MAX1600_GPIO_1VPP, values, 0);
|
||||||
|
} else {
|
||||||
|
dev_err(m->dev, "unrecognised Vpp %u.%uV\n",
|
||||||
|
vpp / 10, vpp % 10);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
n = MAX1600_GPIO_MAX;
|
||||||
|
} else if (vpp != vcc && vpp != 0) {
|
||||||
|
dev_err(m->dev, "no VPP control\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vcc == 0) {
|
||||||
|
__assign_bit(MAX1600_GPIO_0VCC, values, 0);
|
||||||
|
__assign_bit(MAX1600_GPIO_1VCC, values, 0);
|
||||||
|
} else if (vcc == 33) { /* VY */
|
||||||
|
__assign_bit(MAX1600_GPIO_0VCC, values, 1);
|
||||||
|
__assign_bit(MAX1600_GPIO_1VCC, values, 0);
|
||||||
|
} else if (vcc == 50) { /* VX */
|
||||||
|
__assign_bit(MAX1600_GPIO_0VCC, values, 0);
|
||||||
|
__assign_bit(MAX1600_GPIO_1VCC, values, 1);
|
||||||
|
} else {
|
||||||
|
dev_err(m->dev, "unrecognised Vcc %u.%uV\n",
|
||||||
|
vcc / 10, vcc % 10);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m->code == MAX1600_CODE_HIGH) {
|
||||||
|
/*
|
||||||
|
* Cirrus mode appears to be the same as Intel mode,
|
||||||
|
* except the VCC pins are inverted.
|
||||||
|
*/
|
||||||
|
__change_bit(MAX1600_GPIO_0VCC, values);
|
||||||
|
__change_bit(MAX1600_GPIO_1VCC, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
return gpiod_set_array_value_cansleep(n, m->gpio, NULL, values);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(max1600_configure);
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL v2");
|
32
drivers/pcmcia/max1600.h
Normal file
32
drivers/pcmcia/max1600.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
#ifndef MAX1600_H
|
||||||
|
#define MAX1600_H
|
||||||
|
|
||||||
|
struct gpio_desc;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MAX1600_GPIO_0VCC = 0,
|
||||||
|
MAX1600_GPIO_1VCC,
|
||||||
|
MAX1600_GPIO_0VPP,
|
||||||
|
MAX1600_GPIO_1VPP,
|
||||||
|
MAX1600_GPIO_MAX,
|
||||||
|
|
||||||
|
MAX1600_CHAN_A,
|
||||||
|
MAX1600_CHAN_B,
|
||||||
|
|
||||||
|
MAX1600_CODE_LOW,
|
||||||
|
MAX1600_CODE_HIGH,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct max1600 {
|
||||||
|
struct gpio_desc *gpio[MAX1600_GPIO_MAX];
|
||||||
|
struct device *dev;
|
||||||
|
unsigned int code;
|
||||||
|
};
|
||||||
|
|
||||||
|
int max1600_init(struct device *dev, struct max1600 **ptr,
|
||||||
|
unsigned int channel, unsigned int code);
|
||||||
|
|
||||||
|
int max1600_configure(struct max1600 *, unsigned int vcc, unsigned int vpp);
|
||||||
|
|
||||||
|
#endif
|
@ -11,56 +11,55 @@
|
|||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
|
#include <linux/gpio/consumer.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/interrupt.h>
|
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
#include <pcmcia/ss.h>
|
#include <pcmcia/ss.h>
|
||||||
|
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <asm/irq.h>
|
|
||||||
|
|
||||||
#include <mach/pxa2xx-regs.h>
|
|
||||||
#include <mach/mainstone.h>
|
|
||||||
|
|
||||||
#include "soc_common.h"
|
#include "soc_common.h"
|
||||||
|
#include "max1600.h"
|
||||||
|
|
||||||
static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
|
static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
|
||||||
{
|
{
|
||||||
/*
|
struct device *dev = skt->socket.dev.parent;
|
||||||
* Setup default state of GPIO outputs
|
struct max1600 *m;
|
||||||
* before we enable them as outputs.
|
int ret;
|
||||||
*/
|
|
||||||
if (skt->nr == 0) {
|
skt->stat[SOC_STAT_CD].name = skt->nr ? "bdetect" : "adetect";
|
||||||
skt->socket.pci_irq = MAINSTONE_S0_IRQ;
|
skt->stat[SOC_STAT_BVD1].name = skt->nr ? "bbvd1" : "abvd1";
|
||||||
skt->stat[SOC_STAT_CD].irq = MAINSTONE_S0_CD_IRQ;
|
skt->stat[SOC_STAT_BVD2].name = skt->nr ? "bbvd2" : "abvd2";
|
||||||
skt->stat[SOC_STAT_CD].name = "PCMCIA0 CD";
|
skt->stat[SOC_STAT_RDY].name = skt->nr ? "bready" : "aready";
|
||||||
skt->stat[SOC_STAT_BVD1].irq = MAINSTONE_S0_STSCHG_IRQ;
|
skt->stat[SOC_STAT_VS1].name = skt->nr ? "bvs1" : "avs1";
|
||||||
skt->stat[SOC_STAT_BVD1].name = "PCMCIA0 STSCHG";
|
skt->stat[SOC_STAT_VS2].name = skt->nr ? "bvs2" : "avs2";
|
||||||
} else {
|
|
||||||
skt->socket.pci_irq = MAINSTONE_S1_IRQ;
|
skt->gpio_reset = devm_gpiod_get(dev, skt->nr ? "breset" : "areset",
|
||||||
skt->stat[SOC_STAT_CD].irq = MAINSTONE_S1_CD_IRQ;
|
GPIOD_OUT_HIGH);
|
||||||
skt->stat[SOC_STAT_CD].name = "PCMCIA1 CD";
|
if (IS_ERR(skt->gpio_reset))
|
||||||
skt->stat[SOC_STAT_BVD1].irq = MAINSTONE_S1_STSCHG_IRQ;
|
return PTR_ERR(skt->gpio_reset);
|
||||||
skt->stat[SOC_STAT_BVD1].name = "PCMCIA1 STSCHG";
|
|
||||||
}
|
ret = max1600_init(dev, &m, skt->nr ? MAX1600_CHAN_B : MAX1600_CHAN_A,
|
||||||
return 0;
|
MAX1600_CODE_HIGH);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
skt->driver_data = m;
|
||||||
|
|
||||||
|
return soc_pcmcia_request_gpiods(skt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long mst_pcmcia_status[2];
|
static unsigned int mst_pcmcia_bvd1_status[2];
|
||||||
|
|
||||||
static void mst_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
|
static void mst_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
|
||||||
struct pcmcia_state *state)
|
struct pcmcia_state *state)
|
||||||
{
|
{
|
||||||
unsigned long status, flip;
|
unsigned int flip = mst_pcmcia_bvd1_status[skt->nr] ^ state->bvd1;
|
||||||
|
|
||||||
status = (skt->nr == 0) ? MST_PCMCIA0 : MST_PCMCIA1;
|
|
||||||
flip = (status ^ mst_pcmcia_status[skt->nr]) & MST_PCMCIA_nSTSCHG_BVD1;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Workaround for STSCHG which can't be deasserted:
|
* Workaround for STSCHG which can't be deasserted:
|
||||||
@ -68,62 +67,18 @@ static void mst_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
|
|||||||
* as needed to avoid IRQ locks.
|
* as needed to avoid IRQ locks.
|
||||||
*/
|
*/
|
||||||
if (flip) {
|
if (flip) {
|
||||||
mst_pcmcia_status[skt->nr] = status;
|
mst_pcmcia_bvd1_status[skt->nr] = state->bvd1;
|
||||||
if (status & MST_PCMCIA_nSTSCHG_BVD1)
|
if (state->bvd1)
|
||||||
enable_irq( (skt->nr == 0) ? MAINSTONE_S0_STSCHG_IRQ
|
enable_irq(skt->stat[SOC_STAT_BVD1].irq);
|
||||||
: MAINSTONE_S1_STSCHG_IRQ );
|
|
||||||
else
|
else
|
||||||
disable_irq( (skt->nr == 0) ? MAINSTONE_S0_STSCHG_IRQ
|
disable_irq(skt->stat[SOC_STAT_BVD2].irq);
|
||||||
: MAINSTONE_S1_STSCHG_IRQ );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state->detect = (status & MST_PCMCIA_nCD) ? 0 : 1;
|
|
||||||
state->ready = (status & MST_PCMCIA_nIRQ) ? 1 : 0;
|
|
||||||
state->bvd1 = (status & MST_PCMCIA_nSTSCHG_BVD1) ? 1 : 0;
|
|
||||||
state->bvd2 = (status & MST_PCMCIA_nSPKR_BVD2) ? 1 : 0;
|
|
||||||
state->vs_3v = (status & MST_PCMCIA_nVS1) ? 0 : 1;
|
|
||||||
state->vs_Xv = (status & MST_PCMCIA_nVS2) ? 0 : 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mst_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
|
static int mst_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
|
||||||
const socket_state_t *state)
|
const socket_state_t *state)
|
||||||
{
|
{
|
||||||
unsigned long power = 0;
|
return max1600_configure(skt->driver_data, state->Vcc, state->Vpp);
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
switch (state->Vcc) {
|
|
||||||
case 0: power |= MST_PCMCIA_PWR_VCC_0; break;
|
|
||||||
case 33: power |= MST_PCMCIA_PWR_VCC_33; break;
|
|
||||||
case 50: power |= MST_PCMCIA_PWR_VCC_50; break;
|
|
||||||
default:
|
|
||||||
printk(KERN_ERR "%s(): bad Vcc %u\n",
|
|
||||||
__func__, state->Vcc);
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state->Vpp) {
|
|
||||||
case 0: power |= MST_PCMCIA_PWR_VPP_0; break;
|
|
||||||
case 120: power |= MST_PCMCIA_PWR_VPP_120; break;
|
|
||||||
default:
|
|
||||||
if(state->Vpp == state->Vcc) {
|
|
||||||
power |= MST_PCMCIA_PWR_VPP_VCC;
|
|
||||||
} else {
|
|
||||||
printk(KERN_ERR "%s(): bad Vpp %u\n",
|
|
||||||
__func__, state->Vpp);
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state->flags & SS_RESET)
|
|
||||||
power |= MST_PCMCIA_RESET;
|
|
||||||
|
|
||||||
switch (skt->nr) {
|
|
||||||
case 0: MST_PCMCIA0 = power; break;
|
|
||||||
case 1: MST_PCMCIA1 = power; break;
|
|
||||||
default: ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pcmcia_low_level mst_pcmcia_ops __initdata = {
|
static struct pcmcia_low_level mst_pcmcia_ops __initdata = {
|
||||||
|
@ -39,8 +39,8 @@ simpad_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
|
|||||||
{
|
{
|
||||||
long cs3reg = simpad_get_cs3_ro();
|
long cs3reg = simpad_get_cs3_ro();
|
||||||
|
|
||||||
state->bvd1 = 1; /* Might be cs3reg & PCMCIA_BVD1 */
|
/* bvd1 might be cs3reg & PCMCIA_BVD1 */
|
||||||
state->bvd2 = 1; /* Might be cs3reg & PCMCIA_BVD2 */
|
/* bvd2 might be cs3reg & PCMCIA_BVD2 */
|
||||||
|
|
||||||
if ((cs3reg & (PCMCIA_VS1|PCMCIA_VS2)) ==
|
if ((cs3reg & (PCMCIA_VS1|PCMCIA_VS2)) ==
|
||||||
(PCMCIA_VS1|PCMCIA_VS2)) {
|
(PCMCIA_VS1|PCMCIA_VS2)) {
|
||||||
|
@ -6,29 +6,62 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
#include <linux/gpio/consumer.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
|
||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
#include <asm/hardware/sa1111.h>
|
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
|
|
||||||
#include "sa1111_generic.h"
|
#include "sa1111_generic.h"
|
||||||
|
|
||||||
/* Does SOCKET1_3V actually do anything? */
|
/*
|
||||||
#define SOCKET0_POWER GPIO_GPIO0
|
* Socket 0 power: GPIO A0
|
||||||
#define SOCKET0_3V GPIO_GPIO2
|
* Socket 0 3V: GPIO A2
|
||||||
#define SOCKET1_POWER (GPIO_GPIO1 | GPIO_GPIO3)
|
* Socket 1 power: GPIO A1 & GPIO A3
|
||||||
#define SOCKET1_3V GPIO_GPIO3
|
* Socket 1 3V: GPIO A3
|
||||||
|
* Does Socket 1 3V actually do anything?
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
J720_GPIO_PWR,
|
||||||
|
J720_GPIO_3V,
|
||||||
|
J720_GPIO_MAX,
|
||||||
|
};
|
||||||
|
struct jornada720_data {
|
||||||
|
struct gpio_desc *gpio[J720_GPIO_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
static int jornada720_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
|
||||||
|
{
|
||||||
|
struct device *dev = skt->socket.dev.parent;
|
||||||
|
struct jornada720_data *j;
|
||||||
|
|
||||||
|
j = devm_kzalloc(dev, sizeof(*j), GFP_KERNEL);
|
||||||
|
if (!j)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
j->gpio[J720_GPIO_PWR] = devm_gpiod_get(dev, skt->nr ? "s1-power" :
|
||||||
|
"s0-power", GPIOD_OUT_LOW);
|
||||||
|
if (IS_ERR(j->gpio[J720_GPIO_PWR]))
|
||||||
|
return PTR_ERR(j->gpio[J720_GPIO_PWR]);
|
||||||
|
|
||||||
|
j->gpio[J720_GPIO_3V] = devm_gpiod_get(dev, skt->nr ? "s1-3v" :
|
||||||
|
"s0-3v", GPIOD_OUT_LOW);
|
||||||
|
if (IS_ERR(j->gpio[J720_GPIO_3V]))
|
||||||
|
return PTR_ERR(j->gpio[J720_GPIO_3V]);
|
||||||
|
|
||||||
|
skt->driver_data = j;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
|
jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
|
||||||
{
|
{
|
||||||
struct sa1111_pcmcia_socket *s = to_skt(skt);
|
struct jornada720_data *j = skt->driver_data;
|
||||||
unsigned int pa_dwr_mask, pa_dwr_set;
|
DECLARE_BITMAP(values, J720_GPIO_MAX) = { 0, };
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
printk(KERN_INFO "%s(): config socket %d vcc %d vpp %d\n", __func__,
|
printk(KERN_INFO "%s(): config socket %d vcc %d vpp %d\n", __func__,
|
||||||
@ -36,35 +69,34 @@ jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_s
|
|||||||
|
|
||||||
switch (skt->nr) {
|
switch (skt->nr) {
|
||||||
case 0:
|
case 0:
|
||||||
pa_dwr_mask = SOCKET0_POWER | SOCKET0_3V;
|
|
||||||
|
|
||||||
switch (state->Vcc) {
|
switch (state->Vcc) {
|
||||||
default:
|
default:
|
||||||
case 0:
|
case 0:
|
||||||
pa_dwr_set = 0;
|
__assign_bit(J720_GPIO_PWR, values, 0);
|
||||||
|
__assign_bit(J720_GPIO_3V, values, 0);
|
||||||
break;
|
break;
|
||||||
case 33:
|
case 33:
|
||||||
pa_dwr_set = SOCKET0_POWER | SOCKET0_3V;
|
__assign_bit(J720_GPIO_PWR, values, 1);
|
||||||
|
__assign_bit(J720_GPIO_3V, values, 1);
|
||||||
break;
|
break;
|
||||||
case 50:
|
case 50:
|
||||||
pa_dwr_set = SOCKET0_POWER;
|
__assign_bit(J720_GPIO_PWR, values, 1);
|
||||||
|
__assign_bit(J720_GPIO_3V, values, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
pa_dwr_mask = SOCKET1_POWER;
|
|
||||||
|
|
||||||
switch (state->Vcc) {
|
switch (state->Vcc) {
|
||||||
default:
|
default:
|
||||||
case 0:
|
case 0:
|
||||||
pa_dwr_set = 0;
|
__assign_bit(J720_GPIO_PWR, values, 0);
|
||||||
|
__assign_bit(J720_GPIO_3V, values, 0);
|
||||||
break;
|
break;
|
||||||
case 33:
|
case 33:
|
||||||
pa_dwr_set = SOCKET1_POWER;
|
|
||||||
break;
|
|
||||||
case 50:
|
case 50:
|
||||||
pa_dwr_set = SOCKET1_POWER;
|
__assign_bit(J720_GPIO_PWR, values, 1);
|
||||||
|
__assign_bit(J720_GPIO_3V, values, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -81,13 +113,15 @@ jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_s
|
|||||||
|
|
||||||
ret = sa1111_pcmcia_configure_socket(skt, state);
|
ret = sa1111_pcmcia_configure_socket(skt, state);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);
|
ret = gpiod_set_array_value_cansleep(J720_GPIO_MAX, j->gpio,
|
||||||
|
NULL, values);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pcmcia_low_level jornada720_pcmcia_ops = {
|
static struct pcmcia_low_level jornada720_pcmcia_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
.hw_init = jornada720_pcmcia_hw_init,
|
||||||
.configure_socket = jornada720_pcmcia_configure_socket,
|
.configure_socket = jornada720_pcmcia_configure_socket,
|
||||||
.first = 0,
|
.first = 0,
|
||||||
.nr = 2,
|
.nr = 2,
|
||||||
@ -95,16 +129,9 @@ static struct pcmcia_low_level jornada720_pcmcia_ops = {
|
|||||||
|
|
||||||
int pcmcia_jornada720_init(struct sa1111_dev *sadev)
|
int pcmcia_jornada720_init(struct sa1111_dev *sadev)
|
||||||
{
|
{
|
||||||
unsigned int pin = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3;
|
|
||||||
|
|
||||||
/* Fixme: why messing around with SA11x0's GPIO1? */
|
/* Fixme: why messing around with SA11x0's GPIO1? */
|
||||||
GRER |= 0x00000002;
|
GRER |= 0x00000002;
|
||||||
|
|
||||||
/* Set GPIO_A<3:1> to be outputs for PCMCIA/CF power controller: */
|
|
||||||
sa1111_set_io_dir(sadev, pin, 0, 0);
|
|
||||||
sa1111_set_io(sadev, pin, 0);
|
|
||||||
sa1111_set_sleep_io(sadev, pin, 0);
|
|
||||||
|
|
||||||
sa11xx_drv_pcmcia_ops(&jornada720_pcmcia_ops);
|
sa11xx_drv_pcmcia_ops(&jornada720_pcmcia_ops);
|
||||||
return sa1111_pcmcia_add(sadev, &jornada720_pcmcia_ops,
|
return sa1111_pcmcia_add(sadev, &jornada720_pcmcia_ops,
|
||||||
sa11xx_drv_pcmcia_add_one);
|
sa11xx_drv_pcmcia_add_one);
|
||||||
|
@ -24,20 +24,31 @@
|
|||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
#include <asm/hardware/sa1111.h>
|
#include <asm/hardware/sa1111.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <mach/lubbock.h>
|
|
||||||
|
|
||||||
#include "sa1111_generic.h"
|
#include "sa1111_generic.h"
|
||||||
|
#include "max1600.h"
|
||||||
|
|
||||||
|
static int lubbock_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
|
||||||
|
{
|
||||||
|
struct max1600 *m;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = max1600_init(skt->socket.dev.parent, &m,
|
||||||
|
skt->nr ? MAX1600_CHAN_B : MAX1600_CHAN_A,
|
||||||
|
MAX1600_CODE_HIGH);
|
||||||
|
if (ret == 0)
|
||||||
|
skt->driver_data = m;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
|
lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
|
||||||
const socket_state_t *state)
|
const socket_state_t *state)
|
||||||
{
|
{
|
||||||
struct sa1111_pcmcia_socket *s = to_skt(skt);
|
struct max1600 *m = skt->driver_data;
|
||||||
unsigned int pa_dwr_mask, pa_dwr_set, misc_mask, misc_set;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
pa_dwr_mask = pa_dwr_set = misc_mask = misc_set = 0;
|
|
||||||
|
|
||||||
/* Lubbock uses the Maxim MAX1602, with the following connections:
|
/* Lubbock uses the Maxim MAX1602, with the following connections:
|
||||||
*
|
*
|
||||||
* Socket 0 (PCMCIA):
|
* Socket 0 (PCMCIA):
|
||||||
@ -71,74 +82,7 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
|
|||||||
again:
|
again:
|
||||||
switch (skt->nr) {
|
switch (skt->nr) {
|
||||||
case 0:
|
case 0:
|
||||||
pa_dwr_mask = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3;
|
|
||||||
|
|
||||||
switch (state->Vcc) {
|
|
||||||
case 0: /* Hi-Z */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 33: /* VY */
|
|
||||||
pa_dwr_set |= GPIO_A3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 50: /* VX */
|
|
||||||
pa_dwr_set |= GPIO_A2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
|
|
||||||
__func__, state->Vcc);
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state->Vpp) {
|
|
||||||
case 0: /* Hi-Z */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 120: /* 12IN */
|
|
||||||
pa_dwr_set |= GPIO_A1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: /* VCC */
|
|
||||||
if (state->Vpp == state->Vcc)
|
|
||||||
pa_dwr_set |= GPIO_A0;
|
|
||||||
else {
|
|
||||||
printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
|
|
||||||
__func__, state->Vpp);
|
|
||||||
ret = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
misc_mask = (1 << 15) | (1 << 14);
|
|
||||||
|
|
||||||
switch (state->Vcc) {
|
|
||||||
case 0: /* Hi-Z */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 33: /* VY */
|
|
||||||
misc_set |= 1 << 15;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 50: /* VX */
|
|
||||||
misc_set |= 1 << 14;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
|
|
||||||
__func__, state->Vcc);
|
|
||||||
ret = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state->Vpp != state->Vcc && state->Vpp != 0) {
|
|
||||||
printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n",
|
|
||||||
__func__, state->Vpp);
|
|
||||||
ret = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -147,11 +91,8 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
|
|||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
ret = sa1111_pcmcia_configure_socket(skt, state);
|
ret = sa1111_pcmcia_configure_socket(skt, state);
|
||||||
|
if (ret == 0)
|
||||||
if (ret == 0) {
|
ret = max1600_configure(m, state->Vcc, state->Vpp);
|
||||||
lubbock_set_misc_wr(misc_mask, misc_set);
|
|
||||||
sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if (ret == 0 && state->Vcc == 33) {
|
if (ret == 0 && state->Vcc == 33) {
|
||||||
@ -175,8 +116,7 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
|
|||||||
/*
|
/*
|
||||||
* Switch to 5V, Configure socket with 5V voltage
|
* Switch to 5V, Configure socket with 5V voltage
|
||||||
*/
|
*/
|
||||||
lubbock_set_misc_wr(misc_mask, 0);
|
max1600_configure(m, 0, 0);
|
||||||
sa1111_set_io(s->dev, pa_dwr_mask, 0);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It takes about 100ms to turn off Vcc.
|
* It takes about 100ms to turn off Vcc.
|
||||||
@ -201,6 +141,7 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
|
|||||||
|
|
||||||
static struct pcmcia_low_level lubbock_pcmcia_ops = {
|
static struct pcmcia_low_level lubbock_pcmcia_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
.hw_init = lubbock_pcmcia_hw_init,
|
||||||
.configure_socket = lubbock_pcmcia_configure_socket,
|
.configure_socket = lubbock_pcmcia_configure_socket,
|
||||||
.first = 0,
|
.first = 0,
|
||||||
.nr = 2,
|
.nr = 2,
|
||||||
@ -210,17 +151,6 @@ static struct pcmcia_low_level lubbock_pcmcia_ops = {
|
|||||||
|
|
||||||
int pcmcia_lubbock_init(struct sa1111_dev *sadev)
|
int pcmcia_lubbock_init(struct sa1111_dev *sadev)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* Set GPIO_A<3:0> to be outputs for the MAX1600,
|
|
||||||
* and switch to standby mode.
|
|
||||||
*/
|
|
||||||
sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0);
|
|
||||||
sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
|
|
||||||
sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
|
|
||||||
|
|
||||||
/* Set CF Socket 1 power to standby mode. */
|
|
||||||
lubbock_set_misc_wr((1 << 15) | (1 << 14), 0);
|
|
||||||
|
|
||||||
pxa2xx_drv_pcmcia_ops(&lubbock_pcmcia_ops);
|
pxa2xx_drv_pcmcia_ops(&lubbock_pcmcia_ops);
|
||||||
pxa2xx_configure_sockets(&sadev->dev, &lubbock_pcmcia_ops);
|
pxa2xx_configure_sockets(&sadev->dev, &lubbock_pcmcia_ops);
|
||||||
return sa1111_pcmcia_add(sadev, &lubbock_pcmcia_ops,
|
return sa1111_pcmcia_add(sadev, &lubbock_pcmcia_ops,
|
||||||
|
@ -10,12 +10,10 @@
|
|||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
|
||||||
#include <mach/hardware.h>
|
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <mach/neponset.h>
|
|
||||||
#include <asm/hardware/sa1111.h>
|
|
||||||
|
|
||||||
#include "sa1111_generic.h"
|
#include "sa1111_generic.h"
|
||||||
|
#include "max1600.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Neponset uses the Maxim MAX1600, with the following connections:
|
* Neponset uses the Maxim MAX1600, with the following connections:
|
||||||
@ -40,70 +38,36 @@
|
|||||||
* "Standard Intel code" mode. Refer to the Maxim data sheet for
|
* "Standard Intel code" mode. Refer to the Maxim data sheet for
|
||||||
* the corresponding truth table.
|
* the corresponding truth table.
|
||||||
*/
|
*/
|
||||||
|
static int neponset_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
|
||||||
|
{
|
||||||
|
struct max1600 *m;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = max1600_init(skt->socket.dev.parent, &m,
|
||||||
|
skt->nr ? MAX1600_CHAN_B : MAX1600_CHAN_A,
|
||||||
|
MAX1600_CODE_LOW);
|
||||||
|
if (ret == 0)
|
||||||
|
skt->driver_data = m;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
|
neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
|
||||||
{
|
{
|
||||||
struct sa1111_pcmcia_socket *s = to_skt(skt);
|
struct max1600 *m = skt->driver_data;
|
||||||
unsigned int ncr_mask, ncr_set, pa_dwr_mask, pa_dwr_set;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
switch (skt->nr) {
|
|
||||||
case 0:
|
|
||||||
pa_dwr_mask = GPIO_A0 | GPIO_A1;
|
|
||||||
ncr_mask = NCR_A0VPP | NCR_A1VPP;
|
|
||||||
|
|
||||||
if (state->Vpp == 0)
|
|
||||||
ncr_set = 0;
|
|
||||||
else if (state->Vpp == 120)
|
|
||||||
ncr_set = NCR_A1VPP;
|
|
||||||
else if (state->Vpp == state->Vcc)
|
|
||||||
ncr_set = NCR_A0VPP;
|
|
||||||
else {
|
|
||||||
printk(KERN_ERR "%s(): unrecognized VPP %u\n",
|
|
||||||
__func__, state->Vpp);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
pa_dwr_mask = GPIO_A2 | GPIO_A3;
|
|
||||||
ncr_mask = 0;
|
|
||||||
ncr_set = 0;
|
|
||||||
|
|
||||||
if (state->Vpp != state->Vcc && state->Vpp != 0) {
|
|
||||||
printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n",
|
|
||||||
__func__, state->Vpp);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* pa_dwr_set is the mask for selecting Vcc on both sockets.
|
|
||||||
* pa_dwr_mask selects which bits (and therefore socket) we change.
|
|
||||||
*/
|
|
||||||
switch (state->Vcc) {
|
|
||||||
default:
|
|
||||||
case 0: pa_dwr_set = 0; break;
|
|
||||||
case 33: pa_dwr_set = GPIO_A1|GPIO_A2; break;
|
|
||||||
case 50: pa_dwr_set = GPIO_A0|GPIO_A3; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = sa1111_pcmcia_configure_socket(skt, state);
|
ret = sa1111_pcmcia_configure_socket(skt, state);
|
||||||
if (ret == 0) {
|
if (ret == 0)
|
||||||
neponset_ncr_frob(ncr_mask, ncr_set);
|
ret = max1600_configure(m, state->Vcc, state->Vpp);
|
||||||
sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pcmcia_low_level neponset_pcmcia_ops = {
|
static struct pcmcia_low_level neponset_pcmcia_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
.hw_init = neponset_pcmcia_hw_init,
|
||||||
.configure_socket = neponset_pcmcia_configure_socket,
|
.configure_socket = neponset_pcmcia_configure_socket,
|
||||||
.first = 0,
|
.first = 0,
|
||||||
.nr = 2,
|
.nr = 2,
|
||||||
@ -111,13 +75,6 @@ static struct pcmcia_low_level neponset_pcmcia_ops = {
|
|||||||
|
|
||||||
int pcmcia_neponset_init(struct sa1111_dev *sadev)
|
int pcmcia_neponset_init(struct sa1111_dev *sadev)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* Set GPIO_A<3:0> to be outputs for the MAX1600,
|
|
||||||
* and switch to standby mode.
|
|
||||||
*/
|
|
||||||
sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0);
|
|
||||||
sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
|
|
||||||
sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
|
|
||||||
sa11xx_drv_pcmcia_ops(&neponset_pcmcia_ops);
|
sa11xx_drv_pcmcia_ops(&neponset_pcmcia_ops);
|
||||||
return sa1111_pcmcia_add(sadev, &neponset_pcmcia_ops,
|
return sa1111_pcmcia_add(sadev, &neponset_pcmcia_ops,
|
||||||
sa11xx_drv_pcmcia_add_one);
|
sa11xx_drv_pcmcia_add_one);
|
||||||
|
Loading…
Reference in New Issue
Block a user