summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig25
-rw-r--r--arch/arm/boot/compressed/atags_to_fdt.c23
-rw-r--r--arch/arm/common/sa1111.c59
-rw-r--r--arch/arm/include/asm/assembler.h6
-rw-r--r--arch/arm/include/asm/cputype.h1
-rw-r--r--arch/arm/include/asm/hardware/sa1111.h4
-rw-r--r--arch/arm/include/asm/proc-fns.h61
-rw-r--r--arch/arm/include/asm/uaccess.h18
-rw-r--r--arch/arm/kernel/bugs.c4
-rw-r--r--arch/arm/kernel/head-common.S6
-rw-r--r--arch/arm/kernel/head.S2
-rw-r--r--arch/arm/kernel/setup.c40
-rw-r--r--arch/arm/kernel/smp.c46
-rw-r--r--arch/arm/lib/copy_from_user.S23
-rw-r--r--arch/arm/lib/copy_to_user.S27
-rw-r--r--arch/arm/lib/getuser.S11
-rw-r--r--arch/arm/lib/putuser.S20
-rw-r--r--arch/arm/mach-omap2/Kconfig1
-rw-r--r--arch/arm/mach-pxa/Kconfig2
-rw-r--r--arch/arm/mach-pxa/include/mach/mainstone.h4
-rw-r--r--arch/arm/mach-pxa/lubbock.c16
-rw-r--r--arch/arm/mach-pxa/mainstone.c53
-rw-r--r--arch/arm/mach-sa1100/Kconfig2
-rw-r--r--arch/arm/mach-sa1100/assabet.c143
-rw-r--r--arch/arm/mach-sa1100/cerf.c11
-rw-r--r--arch/arm/mach-sa1100/generic.c10
-rw-r--r--arch/arm/mach-sa1100/h3100.c1
-rw-r--r--arch/arm/mach-sa1100/jornada720.c12
-rw-r--r--arch/arm/mach-sa1100/neponset.c19
-rw-r--r--arch/arm/mm/copypage-fa.c35
-rw-r--r--arch/arm/mm/copypage-feroceon.c98
-rw-r--r--arch/arm/mm/copypage-v4mc.c19
-rw-r--r--arch/arm/mm/copypage-v4wb.c41
-rw-r--r--arch/arm/mm/copypage-v4wt.c37
-rw-r--r--arch/arm/mm/copypage-xsc3.c79
-rw-r--r--arch/arm/mm/copypage-xscale.c79
-rw-r--r--arch/arm/mm/fault.c6
-rw-r--r--arch/arm/mm/proc-macros.S10
-rw-r--r--arch/arm/mm/proc-v7-bugs.c17
-rw-r--r--arch/arm/mm/proc-v7.S2
-rw-r--r--arch/arm/mm/pv-fixup-asm.S16
-rw-r--r--arch/arm/plat-omap/Kconfig1
-rw-r--r--arch/arm/vfp/vfpmodule.c2
-rw-r--r--drivers/pcmcia/Kconfig6
-rw-r--r--drivers/pcmcia/Makefile1
-rw-r--r--drivers/pcmcia/max1600.c122
-rw-r--r--drivers/pcmcia/max1600.h32
-rw-r--r--drivers/pcmcia/pxa2xx_mainstone.c113
-rw-r--r--drivers/pcmcia/sa1100_simpad.c4
-rw-r--r--drivers/pcmcia/sa1111_jornada720.c83
-rw-r--r--drivers/pcmcia/sa1111_lubbock.c110
-rw-r--r--drivers/pcmcia/sa1111_neponset.c79
52 files changed, 919 insertions, 723 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 91be74d8df65..a37ee58c6cf3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -27,14 +27,14 @@ config ARM
select ARCH_WANT_IPC_PARSE_VERSION
select BUILDTIME_EXTABLE_SORT if MMU
select CLONE_BACKWARDS
- select CPU_PM if (SUSPEND || CPU_IDLE)
+ select CPU_PM if SUSPEND || CPU_IDLE
select DCACHE_WORD_ACCESS if HAVE_EFFICIENT_UNALIGNED_ACCESS
select DMA_DIRECT_OPS if !MMU
select EDAC_SUPPORT
select EDAC_ATOMIC_SCRUB
select GENERIC_ALLOCATOR
select GENERIC_ARCH_TOPOLOGY if ARM_CPU_TOPOLOGY
- select GENERIC_ATOMIC64 if (CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI)
+ select GENERIC_ATOMIC64 if CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
select GENERIC_CPU_AUTOPROBE
select GENERIC_EARLY_IOREMAP
@@ -49,12 +49,12 @@ config ARM
select GENERIC_STRNLEN_USER
select HANDLE_DOMAIN_IRQ
select HARDIRQS_SW_RESEND
- select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT)
+ select HAVE_ARCH_AUDITSYSCALL if AEABI && !OABI_COMPAT
select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU
select HAVE_ARCH_KGDB if !CPU_ENDIAN_BE32 && MMU
select HAVE_ARCH_MMAP_RND_BITS if MMU
- select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT)
+ select HAVE_ARCH_SECCOMP_FILTER if AEABI && !OABI_COMPAT
select HAVE_ARCH_THREAD_STRUCT_WHITELIST
select HAVE_ARCH_TRACEHOOK
select HAVE_ARM_SMCCC if CPU_V7
@@ -63,16 +63,16 @@ config ARM
select HAVE_C_RECORDMCOUNT
select HAVE_DEBUG_KMEMLEAK
select HAVE_DMA_CONTIGUOUS if MMU
- select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) && !CPU_ENDIAN_BE32 && MMU
+ select HAVE_DYNAMIC_FTRACE if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU
select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE
select HAVE_EFFICIENT_UNALIGNED_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && MMU
select HAVE_EXIT_THREAD
- select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
- select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL)
- select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
+ select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL
+ select HAVE_FUNCTION_GRAPH_TRACER if !THUMB2_KERNEL
+ select HAVE_FUNCTION_TRACER if !XIP_KERNEL
select HAVE_GCC_PLUGINS
select HAVE_GENERIC_DMA_COHERENT
- select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7))
+ select HAVE_HW_BREAKPOINT if PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7)
select HAVE_IDE if PCI || ISA || PCMCIA
select HAVE_IRQ_TIME_ACCOUNTING
select HAVE_KERNEL_GZIP
@@ -81,15 +81,15 @@ config ARM
select HAVE_KERNEL_LZO
select HAVE_KERNEL_XZ
select HAVE_KPROBES if !XIP_KERNEL && !CPU_ENDIAN_BE32 && !CPU_V7M
- select HAVE_KRETPROBES if (HAVE_KPROBES)
+ select HAVE_KRETPROBES if HAVE_KPROBES
select HAVE_MOD_ARCH_SPECIFIC
select HAVE_NMI
- select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
+ select HAVE_OPROFILE if HAVE_PERF_EVENTS
select HAVE_OPTPROBES if !THUMB2_KERNEL
select HAVE_PERF_EVENTS
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
- select HAVE_RCU_TABLE_FREE if (SMP && ARM_LPAE)
+ select HAVE_RCU_TABLE_FREE if SMP && ARM_LPAE
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RSEQ
select HAVE_STACKPROTECTOR
@@ -1783,7 +1783,6 @@ config PARAVIRT
config PARAVIRT_TIME_ACCOUNTING
bool "Paravirtual steal time accounting"
select PARAVIRT
- default n
help
Select this option to enable fine granularity task steal time
accounting. Time spent executing other tasks in parallel with
diff --git a/arch/arm/boot/compressed/atags_to_fdt.c b/arch/arm/boot/compressed/atags_to_fdt.c
index 41fa7316c52b..330cd3c2eae5 100644
--- a/arch/arm/boot/compressed/atags_to_fdt.c
+++ b/arch/arm/boot/compressed/atags_to_fdt.c
@@ -98,6 +98,24 @@ static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline)
setprop_string(fdt, "/chosen", "bootargs", cmdline);
}
+static void hex_str(char *out, uint32_t value)
+{
+ uint32_t digit;
+ int idx;
+
+ for (idx = 7; idx >= 0; idx--) {
+ digit = value >> 28;
+ value <<= 4;
+ digit &= 0xf;
+ if (digit < 10)
+ digit += '0';
+ else
+ digit += 'A'-10;
+ *out++ = digit;
+ }
+ *out = '\0';
+}
+
/*
* Convert and fold provided ATAGs into the provided FDT.
*
@@ -180,6 +198,11 @@ int atags_to_fdt(void *atag_list, void *fdt, int total_space)
initrd_start);
setprop_cell(fdt, "/chosen", "linux,initrd-end",
initrd_start + initrd_size);
+ } else if (atag->hdr.tag == ATAG_SERIAL) {
+ char serno[16+2];
+ hex_str(serno, atag->u.serialnr.high);
+ hex_str(serno+8, atag->u.serialnr.low);
+ setprop_string(fdt, "/", "serial-number", serno);
}
}
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index a2c878769eaf..45412d21aa6b 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -1282,65 +1282,6 @@ int sa1111_get_audio_rate(struct sa1111_dev *sadev)
}
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.
*/
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 88286dd483ff..28a48e0d4cca 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -243,13 +243,15 @@
.endm
#endif
-#define USER(x...) \
+#define USERL(l, x...) \
9999: x; \
.pushsection __ex_table,"a"; \
.align 3; \
- .long 9999b,9001f; \
+ .long 9999b,l; \
.popsection
+#define USER(x...) USERL(9001f, x)
+
#ifdef CONFIG_SMP
#define ALT_SMP(instr...) \
9998: instr
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index 0d289240b6ca..775cac3c02bb 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -111,6 +111,7 @@
#include <linux/kernel.h>
extern unsigned int processor_id;
+struct proc_info_list *lookup_processor(u32 midr);
#ifdef CONFIG_CPU_CP15
#define read_cpuid(reg) \
diff --git a/arch/arm/include/asm/hardware/sa1111.h b/arch/arm/include/asm/hardware/sa1111.h
index 798e520e8a49..d134b9a5ff94 100644
--- a/arch/arm/include/asm/hardware/sa1111.h
+++ b/arch/arm/include/asm/hardware/sa1111.h
@@ -433,10 +433,6 @@ int sa1111_check_dma_bug(dma_addr_t addr);
int sa1111_driver_register(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 {
int irq_base; /* base for cascaded on-chip IRQs */
unsigned disable_devs;
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index e25f4392e1b2..e1b6f280ab08 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -23,7 +23,7 @@ struct mm_struct;
/*
* Don't change this structure - ASM code relies on it.
*/
-extern struct processor {
+struct processor {
/* MISC
* get data abort address/flags
*/
@@ -79,9 +79,13 @@ extern struct processor {
unsigned int suspend_size;
void (*do_suspend)(void *);
void (*do_resume)(void *);
-} processor;
+};
#ifndef MULTI_CPU
+static inline void init_proc_vtable(const struct processor *p)
+{
+}
+
extern void cpu_proc_init(void);
extern void cpu_proc_fin(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_resume(void *);
#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 */
-#define cpu_do_suspend processor.do_suspend
-#define cpu_do_resume processor.do_resume
+extern struct processor processor;
+#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
+#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
extern void cpu_resume(void);
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index c136eef8f690..6390a40f16e7 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -349,6 +349,13 @@ do { \
#define __get_user_asm_byte(x, addr, err) \
__get_user_asm(x, addr, err, ldrb)
+#if __LINUX_ARM_ARCH__ >= 6
+
+#define __get_user_asm_half(x, addr, err) \
+ __get_user_asm(x, addr, err, ldrh)
+
+#else
+
#ifndef __ARMEB__
#define __get_user_asm_half(x, __gu_addr, err) \
({ \
@@ -367,6 +374,8 @@ do { \
})
#endif
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
#define __get_user_asm_word(x, addr, err) \
__get_user_asm(x, addr, err, ldr)
#endif
@@ -442,6 +451,13 @@ do { \
#define __put_user_asm_byte(x, __pu_addr, err) \
__put_user_asm(x, __pu_addr, err, strb)
+#if __LINUX_ARM_ARCH__ >= 6
+
+#define __put_user_asm_half(x, __pu_addr, err) \
+ __put_user_asm(x, __pu_addr, err, strh)
+
+#else
+
#ifndef __ARMEB__
#define __put_user_asm_half(x, __pu_addr, err) \
({ \
@@ -458,6 +474,8 @@ do { \
})
#endif
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
#define __put_user_asm_word(x, __pu_addr, err) \
__put_user_asm(x, __pu_addr, err, str)
diff --git a/arch/arm/kernel/bugs.c b/arch/arm/kernel/bugs.c
index 7be511310191..d41d3598e5e5 100644
--- a/arch/arm/kernel/bugs.c
+++ b/arch/arm/kernel/bugs.c
@@ -6,8 +6,8 @@
void check_other_bugs(void)
{
#ifdef MULTI_CPU
- if (processor.check_bugs)
- processor.check_bugs();
+ if (cpu_check_bugs)
+ cpu_check_bugs();
#endif
}
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 6e0375e7db05..997b02302c31 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -145,6 +145,9 @@ __mmap_switched_data:
#endif
.size __mmap_switched_data, . - __mmap_switched_data
+ __FINIT
+ .text
+
/*
* This provides a C-API version of __lookup_processor_type
*/
@@ -156,9 +159,6 @@ ENTRY(lookup_processor_type)
ldmfd sp!, {r4 - r6, r9, pc}
ENDPROC(lookup_processor_type)
- __FINIT
- .text
-
/*
* 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
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 6b1148cafffd..4485d0404514 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -398,7 +398,7 @@ ENTRY(secondary_startup)
ldmia r4, {r5, r7, r12} @ address to jump to after
sub lr, r4, r5 @ mmu has been enabled
add r3, r7, lr
- ldrd r4, [r3, #0] @ get secondary_data.pgdir
+ ldrd r4, r5, [r3, #0] @ get secondary_data.pgdir
ARM_BE8(eor r4, r4, r5) @ Swap r5 and r4 in BE:
ARM_BE8(eor r5, r4, r5) @ it can be done in 3 steps
ARM_BE8(eor r4, r4, r5) @ without using a temp reg.
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index ac7e08886863..375b13f7e780 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -114,6 +114,11 @@ EXPORT_SYMBOL(elf_hwcap2);
#ifdef MULTI_CPU
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
#ifdef MULTI_TLB
struct cpu_tlb_fns cpu_tlb __ro_after_init;
@@ -666,28 +671,33 @@ static void __init smp_build_mpidr_hash(void)
}
#endif
-static void __init setup_processor(void)
+/*
+ * 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;
+ struct proc_info_list *list = lookup_processor_type(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);
+ 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)
+{
+ unsigned int midr = read_cpuid_id();
+ struct proc_info_list *list = lookup_processor(midr);
+
cpu_name = list->cpu_name;
__cpu_architecture = __get_cpu_architecture();
-#ifdef MULTI_CPU
- processor = *list->proc;
-#endif
+ init_proc_vtable(list->proc);
#ifdef MULTI_TLB
cpu_tlb = *list->tlb;
#endif
@@ -699,7 +709,7 @@ static void __init setup_processor(void)
#endif
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());
snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 0978282d5fc2..3bf82232b1be 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -42,6 +42,7 @@
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
+#include <asm/procinfo.h>
#include <asm/processor.h>
#include <asm/sections.h>
#include <asm/tlbflush.h>
@@ -102,6 +103,30 @@ static unsigned long get_arch_pgd(pgd_t *pgd)
#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 ret;
@@ -109,6 +134,10 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
if (!smp_ops.smp_boot_secondary)
return -ENOSYS;
+ ret = secondary_biglittle_prepare(cpu);
+ if (ret)
+ return ret;
+
/*
* We need to tell the secondary core where to find
* its stack and the page tables.
@@ -359,6 +388,8 @@ asmlinkage void secondary_start_kernel(void)
struct mm_struct *mm = &init_mm;
unsigned int cpu;
+ secondary_biglittle_init();
+
/*
* The identity mapping is uncached (strongly ordered), so
* switch away from it before attempting any exclusive accesses.
@@ -693,6 +724,21 @@ void smp_send_stop(void)
pr_warn("SMP: failed to stop secondary CPUs\n");
}
+/* In case panic() and panic() called at the same time on CPU1 and CPU2,
+ * and CPU 1 calls panic_smp_self_stop() before crash_smp_send_stop()
+ * CPU1 can't receive the ipi irqs from CPU2, CPU1 will be always online,
+ * kdump fails. So split out the panic_smp_self_stop() and add
+ * set_cpu_online(smp_processor_id(), false).
+ */
+void panic_smp_self_stop(void)
+{
+ pr_debug("CPU %u will stop doing anything useful since another CPU has paniced\n",
+ smp_processor_id());
+ set_cpu_online(smp_processor_id(), false);
+ while (1)
+ cpu_relax();
+}
+
/*
* not supported here
*/
diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S
index 6709a8d33963..0d4c189c7f4f 100644
--- a/arch/arm/lib/copy_from_user.S
+++ b/arch/arm/lib/copy_from_user.S
@@ -34,12 +34,13 @@
* Number of bytes NOT copied.
*/
+#ifdef CONFIG_CPU_USE_DOMAINS
+
#ifndef CONFIG_THUMB2_KERNEL
#define LDR1W_SHIFT 0
#else
#define LDR1W_SHIFT 1
#endif
-#define STR1W_SHIFT 0
.macro ldr1w ptr reg abort
ldrusr \reg, \ptr, 4, abort=\abort
@@ -57,10 +58,30 @@
ldr4w \ptr, \reg5, \reg6, \reg7, \reg8, \abort
.endm
+#else
+
+#define LDR1W_SHIFT 0
+
+ .macro ldr1w ptr reg abort
+ USERL(\abort, W(ldr) \reg, [\ptr], #4)
+ .endm
+
+ .macro ldr4w ptr reg1 reg2 reg3 reg4 abort
+ USERL(\abort, ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4})
+ .endm
+
+ .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+ USERL(\abort, ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8})
+ .endm
+
+#endif /* CONFIG_CPU_USE_DOMAINS */
+
.macro ldr1b ptr reg cond=al abort
ldrusr \reg, \ptr, 1, \cond, abort=\abort
.endm
+#define STR1W_SHIFT 0
+
.macro str1w ptr reg abort
W(str) \reg, [\ptr], #4
.endm
diff --git a/arch/arm/lib/copy_to_user.S b/arch/arm/lib/copy_to_user.S
index 970abe521197..97a6ff4b7e3c 100644
--- a/arch/arm/lib/copy_to_user.S
+++ b/arch/arm/lib/copy_to_user.S
@@ -35,11 +35,6 @@
*/
#define LDR1W_SHIFT 0
-#ifndef CONFIG_THUMB2_KERNEL
-#define STR1W_SHIFT 0
-#else
-#define STR1W_SHIFT 1
-#endif
.macro ldr1w ptr reg abort
W(ldr) \reg, [\ptr], #4
@@ -57,6 +52,14 @@
ldr\cond\()b \reg, [\ptr], #1
.endm
+#ifdef CONFIG_CPU_USE_DOMAINS
+
+#ifndef CONFIG_THUMB2_KERNEL
+#define STR1W_SHIFT 0
+#else
+#define STR1W_SHIFT 1
+#endif
+
.macro str1w ptr reg abort
strusr \reg, \ptr, 4, abort=\abort
.endm
@@ -72,6 +75,20 @@
str1w \ptr, \reg8, \abort
.endm
+#else
+
+#define STR1W_SHIFT 0
+
+ .macro str1w ptr reg abort
+ USERL(\abort, W(str) \reg, [\ptr], #4)
+ .endm
+
+ .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+ USERL(\abort, stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8})
+ .endm
+
+#endif /* CONFIG_CPU_USE_DOMAINS */
+
.macro str1b ptr reg cond=al abort
strusr \reg, \ptr, 1, \cond, abort=\abort
.endm
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
index 746e7801dcdf..b2e4bc3a635e 100644
--- a/arch/arm/lib/getuser.S
+++ b/arch/arm/lib/getuser.S
@@ -42,6 +42,12 @@ _ASM_NOKPROBE(__get_user_1)
ENTRY(__get_user_2)
check_uaccess r0, 2, r1, r2, __get_user_bad
+#if __LINUX_ARM_ARCH__ >= 6
+
+2: TUSER(ldrh) r2, [r0]
+
+#else
+
#ifdef CONFIG_CPU_USE_DOMAINS
rb .req ip
2: ldrbt r2, [r0], #1
@@ -56,6 +62,9 @@ rb .req r0
#else
orr r2, rb, r2, lsl #8
#endif
+
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
mov r0, #0
ret lr
ENDPROC(__get_user_2)
@@ -145,7 +154,9 @@ _ASM_NOKPROBE(__get_user_bad8)
.pushsection __ex_table, "a"
.long 1b, __get_user_bad
.long 2b, __get_user_bad
+#if __LINUX_ARM_ARCH__ < 6
.long 3b, __get_user_bad
+#endif
.long 4b, __get_user_bad
.long 5b, __get_user_bad8
.long 6b, __get_user_bad8
diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S
index 38d660d3705f..515eeaa9975c 100644
--- a/arch/arm/lib/putuser.S
+++ b/arch/arm/lib/putuser.S
@@ -41,16 +41,13 @@ ENDPROC(__put_user_1)
ENTRY(__put_user_2)
check_uaccess r0, 2, r1, ip, __put_user_bad
- mov ip, r2, lsr #8
-#ifdef CONFIG_THUMB2_KERNEL
-#ifndef __ARMEB__
-2: TUSER(strb) r2, [r0]
-3: TUSER(strb) ip, [r0, #1]
+#if __LINUX_ARM_ARCH__ >= 6
+
+2: TUSER(strh) r2, [r0]
+
#else
-2: TUSER(strb) ip, [r0]
-3: TUSER(strb) r2, [r0, #1]
-#endif
-#else /* !CONFIG_THUMB2_KERNEL */
+
+ mov ip, r2, lsr #8
#ifndef __ARMEB__
2: TUSER(strb) r2, [r0], #1
3: TUSER(strb) ip, [r0]
@@ -58,7 +55,8 @@ ENTRY(__put_user_2)
2: TUSER(strb) ip, [r0], #1
3: TUSER(strb) r2, [r0]
#endif
-#endif /* CONFIG_THUMB2_KERNEL */
+
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
mov r0, #0
ret lr
ENDPROC(__put_user_2)
@@ -91,7 +89,9 @@ ENDPROC(__put_user_bad)
.pushsection __ex_table, "a"
.long 1b, __put_user_bad
.long 2b, __put_user_bad
+#if __LINUX_ARM_ARCH__ < 6
.long 3b, __put_user_bad
+#endif
.long 4b, __put_user_bad
.long 5b, __put_user_bad
.long 6b, __put_user_bad
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 9f27b486a536..5e33d1a90664 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -223,7 +223,6 @@ config MACH_NOKIA_N8X0
config OMAP3_SDRC_AC_TIMING
bool "Enable SDRC AC timing register changes"
depends on ARCH_OMAP3
- default n
help
If you know that none of your system initiators will attempt to
access SDRAM during CORE DVFS, select Y here. This should boost
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index a68b34183107..7298d07a9f71 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -46,6 +46,7 @@ config ARCH_LUBBOCK
config MACH_MAINSTONE
bool "Intel HCDDBBVA0 Development Platform (aka Mainstone)"
+ select GPIO_REG
select PXA27x
config MACH_ZYLONITE
@@ -551,7 +552,6 @@ config TOSA_BT
config TOSA_USE_EXT_KEYCODES
bool "Tosa keyboard: use extended keycodes"
depends on MACH_TOSA
- default n
help
Say Y here to enable the tosa keyboard driver to generate extended
(>= 127) keycodes. Be aware, that they can't be correctly interpreted
diff --git a/arch/arm/mach-pxa/include/mach/mainstone.h b/arch/arm/mach-pxa/include/mach/mainstone.h
index e82a7d31104e..474041a83d80 100644
--- a/arch/arm/mach-pxa/include/mach/mainstone.h
+++ b/arch/arm/mach-pxa/include/mach/mainstone.h
@@ -119,6 +119,10 @@
#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_INPUTS \
+ (MST_PCMCIA_nIRQ | MST_PCMCIA_nSPKR_BVD2 | MST_PCMCIA_nSTSCHG_BVD1 | \
+ MST_PCMCIA_nVS2 | MST_PCMCIA_nVS1 | MST_PCMCIA_nCD)
+
/* board specific IRQs */
#define MAINSTONE_NR_IRQS IRQ_BOARD_START
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index fe2ef9b78602..8e24455facd8 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -136,10 +136,26 @@ static struct pxa2xx_udc_mach_info udc_info __initdata = {
// 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)
{
struct clk *clk;
+ gpiod_add_lookup_table(&sa1111_pcmcia_gpio_table);
+
/* Add an alias for the SA1111 PCMCIA clock */
clk = clk_get_sys("pxa2xx-pcmcia", NULL);
if (!IS_ERR(clk)) {
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index afd62a94fdbf..d40de190d630 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -13,6 +13,7 @@
* published by the Free Software Foundation.
*/
#include <linux/gpio.h>
+#include <linux/gpio/gpio-reg.h>
#include <linux/gpio/machine.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -507,12 +508,64 @@ static void __init mainstone_init_keypad(void)
static inline void mainstone_init_keypad(void) {}
#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)
{
int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
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_btuart_info(NULL);
pxa_set_stuart_info(NULL);
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
index fde7ef1ab192..af15ae50b5a2 100644
--- a/arch/arm/mach-sa1100/Kconfig
+++ b/arch/arm/mach-sa1100/Kconfig
@@ -6,6 +6,7 @@ config SA1100_ASSABET
bool "Assabet"
select ARM_SA1110_CPUFREQ
select GPIO_REG
+ select LEDS_GPIO_REGISTER
select REGULATOR
select REGULATOR_FIXED_VOLTAGE
help
@@ -24,6 +25,7 @@ config ASSABET_NEPONSET
config SA1100_CERF
bool "CerfBoard"
select ARM_SA1110_CPUFREQ
+ select LEDS_GPIO_REGISTER
help
The Intrinsyc CerfBoard is based on the StrongARM 1110 (Discontinued).
More information is available at:
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index 3e8c0948abcc..dfa42496ec27 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -15,6 +15,7 @@
#include <linux/errno.h>
#include <linux/gpio/gpio-reg.h>
#include <linux/gpio/machine.h>
+#include <linux/gpio_keys.h>
#include <linux/ioport.h>
#include <linux/platform_data/sa11x0-serial.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;
- 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)
{
/*
@@ -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
sa11x0_register_lcd(&lq039q2ds54_info);
#else
@@ -726,92 +777,9 @@ static void __init assabet_map_io(void)
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)
{
+ unsigned int assabet_gpio_base;
u32 def_val;
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().
*/
- 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")
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
index b2a4b41626ef..88e526561a24 100644
--- a/arch/arm/mach-sa1100/cerf.c
+++ b/arch/arm/mach-sa1100/cerf.c
@@ -89,18 +89,8 @@ static struct gpio_led_platform_data cerf_gpio_led_info = {
.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 = {
&cerfuart2_device,
- &cerf_leds,
};
#ifdef CONFIG_SA1100_CERF_FLASH_32MB
@@ -176,6 +166,7 @@ static void __init cerf_init(void)
{
sa11x0_ppc_configure_mcp();
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_mcp(&cerf_mcp_data);
sa11x0_register_pcmcia(1, &cerf_cf_gpio_table);
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 800321c6cbd8..755290bf658b 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -235,18 +235,11 @@ void sa11x0_register_lcd(struct sa1100fb_mach_info *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)
{
if (table)
gpiod_add_lookup_table(table);
platform_device_register_simple("sa11x0-pcmcia", socket, NULL, 0);
- sa11x0pcmcia_legacy = false;
}
static struct platform_device sa11x0mtd_device = {
@@ -331,9 +324,6 @@ static int __init sa1100_init(void)
{
pm_power_off = sa1100_power_off;
- if (sa11x0pcmcia_legacy)
- platform_device_register(&sa11x0pcmcia_device);
-
regulator_has_full_constraints();
return platform_add_devices(sa11x0_devices, ARRAY_SIZE(sa11x0_devices));
diff --git a/arch/arm/mach-sa1100/h3100.c b/arch/arm/mach-sa1100/h3100.c
index c6b412054a3c..9dc5bcb7326b 100644
--- a/arch/arm/mach-sa1100/h3100.c
+++ b/arch/arm/mach-sa1100/h3100.c
@@ -126,6 +126,7 @@ static void __init h3100_mach_init(void)
{
h3xxx_mach_init();
+ sa11x0_register_pcmcia(-1, NULL);
sa11x0_register_lcd(&h3100_lcd_info);
sa11x0_register_irda(&h3100_irda_data);
}
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index 0a2ca9be00e6..6298bad09ef3 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -190,6 +190,17 @@ static struct platform_device s1d13xxxfb_device = {
.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[] = {
[0] = DEFINE_RES_MEM(SA1111REGSTART, SA1111REGLEN),
[1] = DEFINE_RES_IRQ(IRQ_GPIO1),
@@ -265,6 +276,7 @@ static int __init jornada720_init(void)
udelay(20); /* give it some time to restart */
gpiod_add_lookup_table(&jornada_ts_gpiod_table);
+ gpiod_add_lookup_table(&jornada_pcmcia_gpiod_table);
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index b1823f445358..eb60a71cf125 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -5,6 +5,7 @@
#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/gpio-reg.h>
+#include <linux/gpio/machine.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/irq.h>
@@ -96,6 +97,19 @@ struct neponset_drvdata {
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;
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,
neponset_aud_names);
+ gpiod_add_lookup_table(&neponset_pcmcia_table);
+
/*
* We would set IRQ_GPIO25 to be a wake-up IRQ, but unfortunately
* 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);
if (!IS_ERR(d->smc91x))
platform_device_unregister(d->smc91x);
+
+ gpiod_remove_lookup_table(&neponset_pcmcia_table);
+
irq_set_chained_handler(irq, NULL);
irq_free_descs(d->irq_base, NEP_IRQ_NR);
nep = NULL;
diff --git a/arch/arm/mm/copypage-fa.c b/arch/arm/mm/copypage-fa.c
index d130a5ece5d5..bf24690ec83a 100644
--- a/arch/arm/mm/copypage-fa.c
+++ b/arch/arm/mm/copypage-fa.c
@@ -17,26 +17,25 @@
/*
* Faraday optimised copy_user_page
*/
-static void __naked
-fa_copy_user_page(void *kto, const void *kfrom)
+static void fa_copy_user_page(void *kto, const void *kfrom)
{
- asm("\
- stmfd sp!, {r4, lr} @ 2\n\
- mov r2, %0 @ 1\n\
-1: ldmia r1!, {r3, r4, ip, lr} @ 4\n\
- stmia r0, {r3, r4, ip, lr} @ 4\n\
- mcr p15, 0, r0, c7, c14, 1 @ 1 clean and invalidate D line\n\
- add r0, r0, #16 @ 1\n\
- ldmia r1!, {r3, r4, ip, lr} @ 4\n\
- stmia r0, {r3, r4, ip, lr} @ 4\n\
- mcr p15, 0, r0, c7, c14, 1 @ 1 clean and invalidate D line\n\
- add r0, r0, #16 @ 1\n\
- subs r2, r2, #1 @ 1\n\
+ int tmp;
+
+ asm volatile ("\
+1: ldmia %1!, {r3, r4, ip, lr} @ 4\n\
+ stmia %0, {r3, r4, ip, lr} @ 4\n\
+ mcr p15, 0, %0, c7, c14, 1 @ 1 clean and invalidate D line\n\
+ add %0, %0, #16 @ 1\n\
+ ldmia %1!, {r3, r4, ip, lr} @ 4\n\
+ stmia %0, {r3, r4, ip, lr} @ 4\n\
+ mcr p15, 0, %0, c7, c14, 1 @ 1 clean and invalidate D line\n\
+ add %0, %0, #16 @ 1\n\
+ subs %2, %2, #1 @ 1\n\
bne 1b @ 1\n\
- mcr p15, 0, r2, c7, c10, 4 @ 1 drain WB\n\
- ldmfd sp!, {r4, pc} @ 3"
- :
- : "I" (PAGE_SIZE / 32));
+ mcr p15, 0, %2, c7, c10, 4 @ 1 drain WB"
+ : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp)
+ : "2" (PAGE_SIZE / 32)
+ : "r3", "r4", "ip", "lr");
}
void fa_copy_user_highpage(struct page *to, struct page *from,
diff --git a/arch/arm/mm/copypage-feroceon.c b/arch/arm/mm/copypage-feroceon.c
index 49ee0c1a7209..cc819732d9b8 100644
--- a/arch/arm/mm/copypage-feroceon.c
+++ b/arch/arm/mm/copypage-feroceon.c
@@ -13,58 +13,56 @@
#include <linux/init.h>
#include <linux/highmem.h>
-static void __naked
-feroceon_copy_user_page(void *kto, const void *kfrom)
+static void feroceon_copy_user_page(void *kto, const void *kfrom)
{
- asm("\
- stmfd sp!, {r4-r9, lr} \n\
- mov ip, %2 \n\
-1: mov lr, r1 \n\
- ldmia r1!, {r2 - r9} \n\
- pld [lr, #32] \n\
- pld [lr, #64] \n\
- pld [lr, #96] \n\
- pld [lr, #128] \n\
- pld [lr, #160] \n\
- pld [lr, #192] \n\
- pld [lr, #224] \n\
- stmia r0, {r2 - r9} \n\
- ldmia r1!, {r2 - r9} \n\
- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\
- add r0, r0, #32 \n\
- stmia r0, {r2 - r9} \n\
- ldmia r1!, {r2 - r9} \n\
- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\
- add r0, r0, #32 \n\
- stmia r0, {r2 - r9} \n\
- ldmia r1!, {r2 - r9} \n\
- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\
- add r0, r0, #32 \n\
- stmia r0, {r2 - r9} \n\
- ldmia r1!, {r2 - r9} \n\
- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\
- add r0, r0, #32 \n\
- stmia r0, {r2 - r9} \n\
- ldmia r1!, {r2 - r9} \n\
- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\
- add r0, r0, #32 \n\
- stmia r0, {r2 - r9} \n\
- ldmia r1!, {r2 - r9} \n\
- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\
- add r0, r0, #32 \n\
- stmia r0, {r2 - r9} \n\
- ldmia r1!, {r2 - r9} \n\
- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\
- add r0, r0, #32 \n\
- stmia r0, {r2 - r9} \n\
- subs ip, ip, #(32 * 8) \n\
- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\
- add r0, r0, #32 \n\
+ int tmp;
+
+ asm volatile ("\
+1: ldmia %1!, {r2 - r7, ip, lr} \n\
+ pld [%1, #0] \n\
+ pld [%1, #32] \n\
+ pld [%1, #64] \n\
+ pld [%1, #96] \n\
+ pld [%1, #128] \n\
+ pld [%1, #160] \n\
+ pld [%1, #192] \n\
+ stmia %0, {r2 - r7, ip, lr} \n\
+ ldmia %1!, {r2 - r7, ip, lr} \n\
+ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
+ add %0, %0, #32 \n\
+ stmia %0, {r2 - r7, ip, lr} \n\
+ ldmia %1!, {r2 - r7, ip, lr} \n\
+ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
+ add %0, %0, #32 \n\
+ stmia %0, {r2 - r7, ip, lr} \n\
+ ldmia %1!, {r2 - r7, ip, lr} \n\
+ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
+ add %0, %0, #32 \n\
+ stmia %0, {r2 - r7, ip, lr} \n\
+ ldmia %1!, {r2 - r7, ip, lr} \n\
+ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
+ add %0, %0, #32 \n\
+ stmia %0, {r2 - r7, ip, lr} \n\
+ ldmia %1!, {r2 - r7, ip, lr} \n\
+ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
+ add %0, %0, #32 \n\
+ stmia %0, {r2 - r7, ip, lr} \n\
+ ldmia %1!, {r2 - r7, ip, lr} \n\
+ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
+ add %0, %0, #32 \n\
+ stmia %0, {r2 - r7, ip, lr} \n\
+ ldmia %1!, {r2 - r7, ip, lr} \n\
+ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
+ add %0, %0, #32 \n\
+ stmia %0, {r2 - r7, ip, lr} \n\
+ subs %2, %2, #(32 * 8) \n\
+ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
+ add %0, %0, #32 \n\
bne 1b \n\
- mcr p15, 0, ip, c7, c10, 4 @ drain WB\n\
- ldmfd sp!, {r4-r9, pc}"
- :
- : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE));
+ mcr p15, 0, %2, c7, c10, 4 @ drain WB"
+ : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp)
+ : "2" (PAGE_SIZE)
+ : "r2", "r3", "r4", "r5", "r6", "r7", "ip", "lr");
}
void feroceon_copy_user_highpage(struct page *to, struct page *from,
diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c
index 0224416cba3c..b03202cddddb 100644
--- a/arch/arm/mm/copypage-v4mc.c
+++ b/arch/arm/mm/copypage-v4mc.c
@@ -40,12 +40,11 @@ static DEFINE_RAW_SPINLOCK(minicache_lock);
* instruction. If your processor does not supply this, you have to write your
* own copy_user_highpage that does the right thing.
*/
-static void __naked
-mc_copy_user_page(void *from, void *to)
+static void mc_copy_user_page(void *from, void *to)
{
- asm volatile(
- "stmfd sp!, {r4, lr} @ 2\n\
- mov r4, %2 @ 1\n\
+ int tmp;
+
+ asm volatile ("\
ldmia %0!, {r2, r3, ip, lr} @ 4\n\
1: mcr p15, 0, %1, c7, c6, 1 @ 1 invalidate D line\n\
stmia %1!, {r2, r3, ip, lr} @ 4\n\
@@ -55,13 +54,13 @@ mc_copy_user_page(void *from, void *to)
mcr p15, 0, %1, c7, c6, 1 @ 1 invalidate D line\n\
stmia %1!, {r2, r3, ip, lr} @ 4\n\
ldmia %0!, {r2, r3, ip, lr} @ 4\n\
- subs r4, r4, #1 @ 1\n\
+ subs %2, %2, #1 @ 1\n\
stmia %1!, {r2, r3, ip, lr} @ 4\n\
ldmneia %0!, {r2, r3, ip, lr} @ 4\n\
- bne 1b @ 1\n\
- ldmfd sp!, {r4, pc} @ 3"
- :
- : "r" (from), "r" (to), "I" (PAGE_SIZE / 64));
+ bne 1b @ "
+ : "+&r" (from), "+&r" (to), "=&r" (tmp)
+ : "2" (PAGE_SIZE / 64)
+ : "r2", "r3", "ip", "lr");
}
void v4_mc_copy_user_highpage(struct page *to, struct page *from,
diff --git a/arch/arm/mm/copypage-v4wb.c b/arch/arm/mm/copypage-v4wb.c
index 067d0fdd630c..cd3e165afeed 100644
--- a/arch/arm/mm/copypage-v4wb.c
+++ b/arch/arm/mm/copypage-v4wb.c
@@ -22,29 +22,28 @@
* instruction. If your processor does not supply this, you have to write your
* own copy_user_highpage that does the right thing.
*/
-static void __naked
-v4wb_copy_user_page(void *kto, const void *kfrom)
+static void v4wb_copy_user_page(void *kto, const void *kfrom)
{
- asm("\
- stmfd sp!, {r4, lr} @ 2\n\
- mov r2, %2 @ 1\n\
- ldmia r1!, {r3, r4, ip, lr} @ 4\n\
-1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\
- stmia r0!, {r3, r4, ip, lr} @ 4\n\
- ldmia r1!, {r3, r4, ip, lr} @ 4+1\n\
- stmia r0!, {r3, r4, ip, lr} @ 4\n\
- ldmia r1!, {r3, r4, ip, lr} @ 4\n\
- mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\
- stmia r0!, {r3, r4, ip, lr} @ 4\n\
- ldmia r1!, {r3, r4, ip, lr} @ 4\n\
- subs r2, r2, #1 @ 1\n\
- stmia r0!, {r3, r4, ip, lr} @ 4\n\
- ldmneia r1!, {r3, r4, ip, lr} @ 4\n\
+ int tmp;
+
+ asm volatile ("\
+ ldmia %1!, {r3, r4, ip, lr} @ 4\n\
+1: mcr p15, 0, %0, c7, c6, 1 @ 1 invalidate D line\n\
+ stmia %0!, {r3, r4, ip, lr} @ 4\n\
+ ldmia %1!, {r3, r4, ip, lr} @ 4+1\n\
+ stmia %0!, {r3, r4, ip, lr} @ 4\n\
+ ldmia %1!, {r3, r4, ip, lr} @ 4\n\
+ mcr p15, 0, %0, c7, c6, 1 @ 1 invalidate D line\n\
+ stmia %0!, {r3, r4, ip, lr} @ 4\n\
+ ldmia %1!, {r3, r4, ip, lr} @ 4\n\
+ subs %2, %2, #1 @ 1\n\
+ stmia %0!, {r3, r4, ip, lr} @ 4\n\
+ ldmneia %1!, {r3, r4, ip, lr} @ 4\n\
bne 1b @ 1\n\
- mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB\n\
- ldmfd sp!, {r4, pc} @ 3"
- :
- : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64));
+ mcr p15, 0, %1, c7, c10, 4 @ 1 drain WB"
+ : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp)
+ : "2" (PAGE_SIZE / 64)
+ : "r3", "r4", "ip", "lr");
}
void v4wb_copy_user_highpage(struct page *to, struct page *from,
diff --git a/arch/arm/mm/copypage-v4wt.c b/arch/arm/mm/copypage-v4wt.c
index b85c5da2e510..8614572e1296 100644
--- a/arch/arm/mm/copypage-v4wt.c
+++ b/arch/arm/mm/copypage-v4wt.c
@@ -20,27 +20,26 @@
* dirty data in the cache. However, we do have to ensure that
* subsequent reads are up to date.
*/
-static void __naked
-v4wt_copy_user_page(void *kto, const void *kfrom)
+static void v4wt_copy_user_page(void *kto, const void *kfrom)
{
- asm("\
- stmfd sp!, {r4, lr} @ 2\n\
- mov r2, %2 @ 1\n\
- ldmia r1!, {r3, r4, ip, lr} @ 4\n\
-1: stmia r0!, {r3, r4, ip, lr} @ 4\n\
- ldmia r1!, {r3, r4, ip, lr} @ 4+1\n\
- stmia r0!, {r3, r4, ip, lr} @ 4\n\
- ldmia r1!, {r3, r4, ip, lr} @ 4\n\
- stmia r0!, {r3, r4, ip, lr} @ 4\n\
- ldmia r1!, {r3, r4, ip, lr} @ 4\n\
- subs r2, r2, #1 @ 1\n\
- stmia r0!, {r3, r4, ip, lr} @ 4\n\
- ldmneia r1!, {r3, r4, ip, lr} @ 4\n\
+ int tmp;
+
+ asm volatile ("\
+ ldmia %1!, {r3, r4, ip, lr} @ 4\n\
+1: stmia %0!, {r3, r4, ip, lr} @ 4\n\
+ ldmia %1!, {r3, r4, ip, lr} @ 4+1\n\
+ stmia %0!, {r3, r4, ip, lr} @ 4\n\
+ ldmia %1!, {r3, r4, ip, lr} @ 4\n\
+ stmia %0!, {r3, r4, ip, lr} @ 4\n\
+ ldmia %1!, {r3, r4, ip, lr} @ 4\n\
+ subs %2, %2, #1 @ 1\n\
+ stmia %0!, {r3, r4, ip, lr} @ 4\n\
+ ldmneia %1!, {r3, r4, ip, lr} @ 4\n\
bne 1b @ 1\n\
- mcr p15, 0, r2, c7, c7, 0 @ flush ID cache\n\
- ldmfd sp!, {r4, pc} @ 3"
- :
- : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64));
+ mcr p15, 0, %2, c7, c7, 0 @ flush ID cache"
+ : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp)
+ : "2" (PAGE_SIZE / 64)
+ : "r3", "r4", "ip", "lr");
}
void v4wt_copy_user_highpage(struct page *to, struct page *from,
diff --git a/arch/arm/mm/copypage-xsc3.c b/arch/arm/mm/copypage-xsc3.c
index 03a2042aced5..a08158241ad1 100644
--- a/arch/arm/mm/copypage-xsc3.c
+++ b/arch/arm/mm/copypage-xsc3.c
@@ -21,53 +21,46 @@
/*
* XSC3 optimised copy_user_highpage
- * r0 = destination
- * r1 = source
*
* The source page may have some clean entries in the cache already, but we
* can safely ignore them - break_cow() will flush them out of the cache
* if we eventually end up using our copied page.
*
*/
-static void __naked
-xsc3_mc_copy_user_page(void *kto, const void *kfrom)
+static void xsc3_mc_copy_user_page(void *kto, const void *kfrom)
{
- asm("\
- stmfd sp!, {r4, r5, lr} \n\
- mov lr, %2 \n\
- \n\
- pld [r1, #0] \n\
- pld [r1, #32] \n\
-1: pld [r1, #64] \n\
- pld [r1, #96] \n\
+ int tmp;
+
+ asm volatile ("\
+ pld [%1, #0] \n\
+ pld [%1, #32] \n\
+1: pld [%1, #64] \n\
+ pld [%1, #96] \n\
\n\
-2: ldrd r2, [r1], #8 \n\
- mov ip, r0 \n\
- ldrd r4, [r1], #8 \n\
- mcr p15, 0, ip, c7, c6, 1 @ invalidate\n\
- strd r2, [r0], #8 \n\
- ldrd r2, [r1], #8 \n\
- strd r4, [r0], #8 \n\
- ldrd r4, [r1], #8 \n\
- strd r2, [r0], #8 \n\
- strd r4, [r0], #8 \n\
- ldrd r2, [r1], #8 \n\
- mov ip, r0 \n\
- ldrd r4, [r1], #8 \n\
- mcr p15, 0, ip, c7, c6, 1 @ invalidate\n\
- strd r2, [r0], #8 \n\
- ldrd r2, [r1], #8 \n\
- subs lr, lr, #1 \n\
- strd r4, [r0], #8 \n\
- ldrd r4, [r1], #8 \n\
- strd r2, [r0], #8 \n\
- strd r4, [r0], #8 \n\
+2: ldrd r2, r3, [%1], #8 \n\
+ ldrd r4, r5, [%1], #8 \n\
+ mcr p15, 0, %0, c7, c6, 1 @ invalidate\n\
+ strd r2, r3, [%0], #8 \n\
+ ldrd r2, r3, [%1], #8 \n\
+ strd r4, r5, [%0], #8 \n\
+ ldrd r4, r5, [%1], #8 \n\
+ strd r2, r3, [%0], #8 \n\
+ strd r4, r5, [%0], #8 \n\
+ ldrd r2, r3, [%1], #8 \n\
+ ldrd r4, r5, [%1], #8 \n\
+ mcr p15, 0, %0, c7, c6, 1 @ invalidate\n\
+ strd r2, r3, [%0], #8 \n\
+ ldrd r2, r3, [%1], #8 \n\
+ subs %2, %2, #1 \n\
+ strd r4, r5, [%0], #8 \n\
+ ldrd r4, r5, [%1], #8 \n\
+ strd r2, r3, [%0], #8 \n\
+ strd r4, r5, [%0], #8 \n\
bgt 1b \n\
- beq 2b \n\
- \n\
- ldmfd sp!, {r4, r5, pc}"
- :
- : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64 - 1));
+ beq 2b "
+ : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp)
+ : "2" (PAGE_SIZE / 64 - 1)
+ : "r2", "r3", "r4", "r5");
}
void xsc3_mc_copy_user_highpage(struct page *to, struct page *from,
@@ -85,8 +78,6 @@ void xsc3_mc_copy_user_highpage(struct page *to, struct page *from,
/*
* XScale optimised clear_user_page
- * r0 = destination
- * r1 = virtual user address of ultimate destination page
*/
void xsc3_mc_clear_user_highpage(struct page *page, unsigned long vaddr)
{
@@ -96,10 +87,10 @@ void xsc3_mc_clear_user_highpage(struct page *page, unsigned long vaddr)
mov r2, #0 \n\
mov r3, #0 \n\
1: mcr p15, 0, %0, c7, c6, 1 @ invalidate line\n\
- strd r2, [%0], #8 \n\
- strd r2, [%0], #8 \n\
- strd r2, [%0], #8 \n\
- strd r2, [%0], #8 \n\
+ strd r2, r3, [%0], #8 \n\
+ strd r2, r3, [%0], #8 \n\
+ strd r2, r3, [%0], #8 \n\
+ strd r2, r3, [%0], #8 \n\
subs r1, r1, #1 \n\
bne 1b"
: "=r" (ptr)
diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c
index 97972379f4d6..63b921936754 100644
--- a/arch/arm/mm/copypage-xscale.c
+++ b/arch/arm/mm/copypage-xscale.c
@@ -36,52 +36,51 @@ static DEFINE_RAW_SPINLOCK(minicache_lock);
* Dcache aliasing issue. The writes will be forwarded to the write buffer,
* and merged as appropriate.
*/
-static void __naked
-mc_copy_user_page(void *from, void *to)
+static void mc_copy_user_page(void *from, void *to)
{
+ int tmp;
+
/*
* Strangely enough, best performance is achieved
* when prefetching destination as well. (NP)
*/
- asm volatile(
- "stmfd sp!, {r4, r5, lr} \n\
- mov lr, %2 \n\
- pld [r0, #0] \n\
- pld [r0, #32] \n\
- pld [r1, #0] \n\
- pld [r1, #32] \n\
-1: pld [r0, #64] \n\
- pld [r0, #96] \n\
- pld [r1, #64] \n\
- pld [r1, #96] \n\
-2: ldrd r2, [r0], #8 \n\
- ldrd r4, [r0], #8 \n\
- mov ip, r1 \n\
- strd r2, [r1], #8 \n\
- ldrd r2, [r0], #8 \n\
- strd r4, [r1], #8 \n\
- ldrd r4, [r0], #8 \n\
- strd r2, [r1], #8 \n\
- strd r4, [r1], #8 \n\
+ asm volatile ("\
+ pld [%0, #0] \n\
+ pld [%0, #32] \n\
+ pld [%1, #0] \n\
+ pld [%1, #32] \n\
+1: pld [%0, #64] \n\
+ pld [%0, #96] \n\
+ pld [%1, #64] \n\
+ pld [%1, #96] \n\
+2: ldrd r2, r3, [%0], #8 \n\
+ ldrd r4, r5, [%0], #8 \n\
+ mov ip, %1 \n\
+ strd r2, r3, [%1], #8 \n\
+ ldrd r2, r3, [%0], #8 \n\
+ strd r4, r5, [%1], #8 \n\
+ ldrd r4, r5, [%0], #8 \n\
+ strd r2, r3, [%1], #8 \n\
+ strd r4, r5, [%1], #8 \n\
mcr p15, 0, ip, c7, c10, 1 @ clean D line\n\
- ldrd r2, [r0], #8 \n\
+ ldrd r2, r3, [%0], #8 \n\
mcr p15, 0, ip, c7, c6, 1 @ invalidate D line\n\
- ldrd r4, [r0], #8 \n\
- mov ip, r1 \n\
- strd r2, [r1], #8 \n\
- ldrd r2, [r0], #8 \n\
- strd r4, [r1], #8 \n\
- ldrd r4, [r0], #8 \n\
- strd r2, [r1], #8 \n\
- strd r4, [r1], #8 \n\
+ ldrd r4, r5, [%0], #8 \n\
+ mov ip, %1 \n\
+ strd r2, r3, [%1], #8 \n\
+ ldrd r2, r3, [%0], #8 \n\
+ strd r4, r5, [%1], #8 \n\
+ ldrd r4, r5, [%0], #8 \n\
+ strd r2, r3, [%1], #8 \n\
+ strd r4, r5, [%1], #8 \n\
mcr p15, 0, ip, c7, c10, 1 @ clean D line\n\
- subs lr, lr, #1 \n\
+ subs %2, %2, #1 \n\
mcr p15, 0, ip, c7, c6, 1 @ invalidate D line\n\
bgt 1b \n\
- beq 2b \n\
- ldmfd sp!, {r4, r5, pc} "
- :
- : "r" (from), "r" (to), "I" (PAGE_SIZE / 64 - 1));
+ beq 2b "
+ : "+&r" (from), "+&r" (to), "=&r" (tmp)
+ : "2" (PAGE_SIZE / 64 - 1)
+ : "r2", "r3", "r4", "r5", "ip");
}
void xscale_mc_copy_user_highpage(struct page *to, struct page *from,
@@ -115,10 +114,10 @@ xscale_mc_clear_user_highpage(struct page *page, unsigned long vaddr)
mov r2, #0 \n\
mov r3, #0 \n\
1: mov ip, %0 \n\
- strd r2, [%0], #8 \n\
- strd r2, [%0], #8 \n\
- strd r2, [%0], #8 \n\
- strd r2, [%0], #8 \n\
+ strd r2, r3, [%0], #8 \n\
+ strd r2, r3, [%0], #8 \n\
+ strd r2, r3, [%0], #8 \n\
+ strd r2, r3, [%0], #8 \n\
mcr p15, 0, ip, c7, c10, 1 @ clean D line\n\
subs r1, r1, #1 \n\
mcr p15, 0, ip, c7, c6, 1 @ invalidate D line\n\
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index f4ea4c62c613..58f69fa07df9 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -173,6 +173,12 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr,
show_regs(regs);
}
#endif
+#ifndef CONFIG_KUSER_HELPERS
+ if ((sig == SIGSEGV) && ((addr & PAGE_MASK) == 0xffff0000))
+ printk_ratelimited(KERN_DEBUG
+ "%s: CONFIG_KUSER_HELPERS disabled at 0x%08lx\n",
+ tsk->comm, addr);
+#endif
tsk->thread.address = addr;
tsk->thread.error_code = fsr;
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
index 81d0efb055c6..5461d589a1e2 100644
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -274,6 +274,13 @@
.endm
.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
.align 2
ENTRY(\name\()_processor_functions)
@@ -309,6 +316,9 @@ ENTRY(\name\()_processor_functions)
.endif
.size \name\()_processor_functions, . - \name\()_processor_functions
+#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
+ .previous
+#endif
.endm
.macro define_cache_functions name:req
diff --git a/arch/arm/mm/proc-v7-bugs.c b/arch/arm/mm/proc-v7-bugs.c
index 5544b82a2e7a..9a07916af8dd 100644
--- a/arch/arm/mm/proc-v7-bugs.c
+++ b/arch/arm/mm/proc-v7-bugs.c
@@ -52,8 +52,6 @@ static void cpu_v7_spectre_init(void)
case ARM_CPU_PART_CORTEX_A17:
case ARM_CPU_PART_CORTEX_A73:
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) =
harden_branch_predictor_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_BRAHMA_B15:
- if (processor.switch_mm != cpu_v7_iciallu_switch_mm)
- goto bl_error;
per_cpu(harden_branch_predictor_fn, cpu) =
harden_branch_predictor_iciallu;
spectre_v2_method = "ICIALLU";
@@ -88,11 +84,9 @@ static void cpu_v7_spectre_init(void)
ARM_SMCCC_ARCH_WORKAROUND_1, &res);
if ((int)res.a0 != 0)
break;
- if (processor.switch_mm != cpu_v7_hvc_switch_mm && cpu)
- goto bl_error;
per_cpu(harden_branch_predictor_fn, cpu) =
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";
break;
@@ -101,11 +95,9 @@ static void cpu_v7_spectre_init(void)
ARM_SMCCC_ARCH_WORKAROUND_1, &res);
if ((int)res.a0 != 0)
break;
- if (processor.switch_mm != cpu_v7_smc_switch_mm && cpu)
- goto bl_error;
per_cpu(harden_branch_predictor_fn, cpu) =
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";
break;
@@ -119,11 +111,6 @@ static void cpu_v7_spectre_init(void)
if (spectre_v2_method)
pr_info("CPU%u: Spectre v2: using %s workaround\n",
smp_processor_id(), spectre_v2_method);
- return;
-
-bl_error:
- pr_err("CPU%u: Spectre v2: incorrect context switching function, system vulnerable\n",
- cpu);
}
#else
static void cpu_v7_spectre_init(void)
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 6fe52819e014..339eb17c9808 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -112,7 +112,7 @@ ENTRY(cpu_v7_hvc_switch_mm)
hvc #0
ldmfd sp!, {r0 - r3}
b cpu_v7_switch_mm
-ENDPROC(cpu_v7_smc_switch_mm)
+ENDPROC(cpu_v7_hvc_switch_mm)
#endif
ENTRY(cpu_v7_iciallu_switch_mm)
mov r3, #0
diff --git a/arch/arm/mm/pv-fixup-asm.S b/arch/arm/mm/pv-fixup-asm.S
index 1867f3e43016..fd2ff9034d17 100644
--- a/arch/arm/mm/pv-fixup-asm.S
+++ b/arch/arm/mm/pv-fixup-asm.S
@@ -33,10 +33,10 @@ ENTRY(lpae_pgtables_remap_asm)
add r7, r2, #0x1000
add r6, r7, r6, lsr #SECTION_SHIFT - L2_ORDER
add r7, r7, #PAGE_OFFSET >> (SECTION_SHIFT - L2_ORDER)
-1: ldrd r4, [r7]
+1: ldrd r4, r5, [r7]
adds r4, r4, r0
adc r5, r5, r1
- strd r4, [r7], #1 << L2_ORDER
+ strd r4, r5, [r7], #1 << L2_ORDER
cmp r7, r6
bls 1b
@@ -44,22 +44,22 @@ ENTRY(lpae_pgtables_remap_asm)
add r7, r2, #0x1000
add r7, r7, r3, lsr #SECTION_SHIFT - L2_ORDER
bic r7, r7, #(1 << L2_ORDER) - 1
- ldrd r4, [r7]
+ ldrd r4, r5, [r7]
adds r4, r4, r0
adc r5, r5, r1
- strd r4, [r7], #1 << L2_ORDER
- ldrd r4, [r7]
+ strd r4, r5, [r7], #1 << L2_ORDER
+ ldrd r4, r5, [r7]
adds r4, r4, r0
adc r5, r5, r1
- strd r4, [r7]
+ strd r4, r5, [r7]
/* Update level 1 entries */
mov r6, #4
mov r7, r2
-2: ldrd r4, [r7]
+2: ldrd r4, r5, [r7]
adds r4, r4, r0
adc r5, r5, r1
- strd r4, [r7], #1 << L1_ORDER
+ strd r4, r5, [r7], #1 << L1_ORDER
subs r6, r6, #1
bne 2b
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index c0a242cae79a..93fd7fc537cf 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -92,7 +92,6 @@ config OMAP_32K_TIMER
config OMAP3_L2_AUX_SECURE_SAVE_RESTORE
bool "OMAP3 HS/EMU save and restore for L2 AUX control register"
depends on ARCH_OMAP3 && PM
- default n
help
Without this option, L2 Auxiliary control register contents are
lost during off-mode entry on HS/EMU devices. This feature
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index aff6e6eadc70..ee7b07938dd5 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -573,7 +573,7 @@ int vfp_preserve_user_clear_hwstate(struct user_vfp *ufp,
*/
ufp_exc->fpexc = hwstate->fpexc;
ufp_exc->fpinst = hwstate->fpinst;
- ufp_exc->fpinst2 = ufp_exc->fpinst2;
+ ufp_exc->fpinst2 = hwstate->fpinst2;
/* Ensure that VFP is disabled. */
vfp_flush_hwstate(thread);
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index cbbe4a285b48..d687a7640f6a 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -63,6 +63,9 @@ config CARDBUS
If unsure, say Y.
+config PCMCIA_MAX1600
+ tristate
+
comment "PC-card bridges"
config YENTA
@@ -191,6 +194,8 @@ config PCMCIA_SA1111
select PCMCIA_SOC_COMMON
select PCMCIA_SA11XX_BASE if ARCH_SA1100
select PCMCIA_PXA2XX if ARCH_LUBBOCK && SA1111
+ select PCMCIA_MAX1600 if ASSABET_NEPONSET
+ select PCMCIA_MAX1600 if ARCH_LUBBOCK && SA1111
help
Say Y here to include support for SA1111-based PCMCIA or CF
sockets, found on the Jornada 720, Graphicsmaster and other
@@ -207,6 +212,7 @@ config PCMCIA_PXA2XX
|| MACH_VPAC270 || MACH_BALLOON3 || MACH_COLIBRI \
|| MACH_COLIBRI320 || MACH_H4700)
select PCMCIA_SOC_COMMON
+ select PCMCIA_MAX1600 if MACH_MAINSTONE
help
Say Y here to include support for the PXA2xx PCMCIA controller
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 28502bd159e0..01779c5c45f3 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_OMAP_CF) += omap_cf.o
obj-$(CONFIG_AT91_CF) += at91_cf.o
obj-$(CONFIG_ELECTRA_CF) += electra_cf.o
obj-$(CONFIG_PCMCIA_ALCHEMY_DEVBOARD) += db1xxx_ss.o
+obj-$(CONFIG_PCMCIA_MAX1600) += max1600.o
sa1111_cs-y += sa1111_generic.o
sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1111_neponset.o
diff --git a/drivers/pcmcia/max1600.c b/drivers/pcmcia/max1600.c
new file mode 100644
index 000000000000..379875a5e7cd
--- /dev/null
+++ b/drivers/pcmcia/max1600.c
@@ -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");
diff --git a/drivers/pcmcia/max1600.h b/drivers/pcmcia/max1600.h
new file mode 100644
index 000000000000..00bf1a09464f
--- /dev/null
+++ b/drivers/pcmcia/max1600.h
@@ -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
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c
index 7e32e25cdcb2..770c7bf0171d 100644
--- a/drivers/pcmcia/pxa2xx_mainstone.c
+++ b/drivers/pcmcia/pxa2xx_mainstone.c
@@ -11,56 +11,55 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <pcmcia/ss.h>
#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <mach/pxa2xx-regs.h>
-#include <mach/mainstone.h>
#include "soc_common.h"
-
+#include "max1600.h"
static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
- /*
- * Setup default state of GPIO outputs
- * before we enable them as outputs.
- */
- if (skt->nr == 0) {
- skt->socket.pci_irq = MAINSTONE_S0_IRQ;
- skt->stat[SOC_STAT_CD].irq = MAINSTONE_S0_CD_IRQ;
- skt->stat[SOC_STAT_CD].name = "PCMCIA0 CD";
- skt->stat[SOC_STAT_BVD1].irq = MAINSTONE_S0_STSCHG_IRQ;
- skt->stat[SOC_STAT_BVD1].name = "PCMCIA0 STSCHG";
- } else {
- skt->socket.pci_irq = MAINSTONE_S1_IRQ;
- skt->stat[SOC_STAT_CD].irq = MAINSTONE_S1_CD_IRQ;
- skt->stat[SOC_STAT_CD].name = "PCMCIA1 CD";
- skt->stat[SOC_STAT_BVD1].irq = MAINSTONE_S1_STSCHG_IRQ;
- skt->stat[SOC_STAT_BVD1].name = "PCMCIA1 STSCHG";
- }
- return 0;
+ struct device *dev = skt->socket.dev.parent;
+ struct max1600 *m;
+ int ret;
+
+ skt->stat[SOC_STAT_CD].name = skt->nr ? "bdetect" : "adetect";
+ skt->stat[SOC_STAT_BVD1].name = skt->nr ? "bbvd1" : "abvd1";
+ skt->stat[SOC_STAT_BVD2].name = skt->nr ? "bbvd2" : "abvd2";
+ skt->stat[SOC_STAT_RDY].name = skt->nr ? "bready" : "aready";
+ skt->stat[SOC_STAT_VS1].name = skt->nr ? "bvs1" : "avs1";
+ skt->stat[SOC_STAT_VS2].name = skt->nr ? "bvs2" : "avs2";
+
+ skt->gpio_reset = devm_gpiod_get(dev, skt->nr ? "breset" : "areset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(skt->gpio_reset))
+ return PTR_ERR(skt->gpio_reset);
+
+ ret = max1600_init(dev, &m, skt->nr ? MAX1600_CHAN_B : MAX1600_CHAN_A,
+ 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,
struct pcmcia_state *state)
{
- unsigned long status, flip;
-
- status = (skt->nr == 0) ? MST_PCMCIA0 : MST_PCMCIA1;
- flip = (status ^ mst_pcmcia_status[skt->nr]) & MST_PCMCIA_nSTSCHG_BVD1;
+ unsigned int flip = mst_pcmcia_bvd1_status[skt->nr] ^ state->bvd1;
/*
* 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.
*/
if (flip) {
- mst_pcmcia_status[skt->nr] = status;
- if (status & MST_PCMCIA_nSTSCHG_BVD1)
- enable_irq( (skt->nr == 0) ? MAINSTONE_S0_STSCHG_IRQ
- : MAINSTONE_S1_STSCHG_IRQ );
+ mst_pcmcia_bvd1_status[skt->nr] = state->bvd1;
+ if (state->bvd1)
+ enable_irq(skt->stat[SOC_STAT_BVD1].irq);
else
- disable_irq( (skt->nr == 0) ? MAINSTONE_S0_STSCHG_IRQ
- : MAINSTONE_S1_STSCHG_IRQ );
+ disable_irq(skt->stat[SOC_STAT_BVD2].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,
const socket_state_t *state)
{
- unsigned long power = 0;
- 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;
+ return max1600_configure(skt->driver_data, state->Vcc, state->Vpp);
}
static struct pcmcia_low_level mst_pcmcia_ops __initdata = {
diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c
index e235ee14eaa6..e2e8729afd9d 100644
--- a/drivers/pcmcia/sa1100_simpad.c
+++ b/drivers/pcmcia/sa1100_simpad.c
@@ -39,8 +39,8 @@ simpad_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
{
long cs3reg = simpad_get_cs3_ro();
- state->bvd1 = 1; /* Might be cs3reg & PCMCIA_BVD1 */
- state->bvd2 = 1; /* Might be cs3reg & PCMCIA_BVD2 */
+ /* bvd1 might be cs3reg & PCMCIA_BVD1 */
+ /* bvd2 might be cs3reg & PCMCIA_BVD2 */
if ((cs3reg & (PCMCIA_VS1|PCMCIA_VS2)) ==
(PCMCIA_VS1|PCMCIA_VS2)) {
diff --git a/drivers/pcmcia/sa1111_jornada720.c b/drivers/pcmcia/sa1111_jornada720.c
index 3d4ca87ca76c..1083e1b4f25d 100644
--- a/drivers/pcmcia/sa1111_jornada720.c
+++ b/drivers/pcmcia/sa1111_jornada720.c
@@ -6,29 +6,62 @@
*
*/
#include <linux/module.h>
-#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/errno.h>
+#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/io.h>
#include <mach/hardware.h>
-#include <asm/hardware/sa1111.h>
#include <asm/mach-types.h>
#include "sa1111_generic.h"
-/* Does SOCKET1_3V actually do anything? */
-#define SOCKET0_POWER GPIO_GPIO0
-#define SOCKET0_3V GPIO_GPIO2
-#define SOCKET1_POWER (GPIO_GPIO1 | GPIO_GPIO3)
-#define SOCKET1_3V GPIO_GPIO3
+/*
+ * Socket 0 power: GPIO A0
+ * Socket 0 3V: GPIO A2
+ * Socket 1 power: GPIO A1 & GPIO A3
+ * 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
jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
{
- struct sa1111_pcmcia_socket *s = to_skt(skt);
- unsigned int pa_dwr_mask, pa_dwr_set;
+ struct jornada720_data *j = skt->driver_data;
+ DECLARE_BITMAP(values, J720_GPIO_MAX) = { 0, };
int ret;
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) {
case 0:
- pa_dwr_mask = SOCKET0_POWER | SOCKET0_3V;
-
switch (state->Vcc) {
default:
case 0:
- pa_dwr_set = 0;
+ __assign_bit(J720_GPIO_PWR, values, 0);
+ __assign_bit(J720_GPIO_3V, values, 0);
break;
case 33:
- pa_dwr_set = SOCKET0_POWER | SOCKET0_3V;
+ __assign_bit(J720_GPIO_PWR, values, 1);
+ __assign_bit(J720_GPIO_3V, values, 1);
break;
case 50:
- pa_dwr_set = SOCKET0_POWER;
+ __assign_bit(J720_GPIO_PWR, values, 1);
+ __assign_bit(J720_GPIO_3V, values, 0);
break;
}
break;
case 1:
- pa_dwr_mask = SOCKET1_POWER;
-
switch (state->Vcc) {
default:
case 0:
- pa_dwr_set = 0;
+ __assign_bit(J720_GPIO_PWR, values, 0);
+ __assign_bit(J720_GPIO_3V, values, 0);
break;
case 33:
- pa_dwr_set = SOCKET1_POWER;
- break;
case 50:
- pa_dwr_set = SOCKET1_POWER;
+ __assign_bit(J720_GPIO_PWR, values, 1);
+ __assign_bit(J720_GPIO_3V, values, 1);
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);
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;
}
static struct pcmcia_low_level jornada720_pcmcia_ops = {
.owner = THIS_MODULE,
+ .hw_init = jornada720_pcmcia_hw_init,
.configure_socket = jornada720_pcmcia_configure_socket,
.first = 0,
.nr = 2,
@@ -95,16 +129,9 @@ static struct pcmcia_low_level jornada720_pcmcia_ops = {
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? */
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);
return sa1111_pcmcia_add(sadev, &jornada720_pcmcia_ops,
sa11xx_drv_pcmcia_add_one);
diff --git a/drivers/pcmcia/sa1111_lubbock.c b/drivers/pcmcia/sa1111_lubbock.c
index e741f499c875..e3fc14cfb42b 100644
--- a/drivers/pcmcia/sa1111_lubbock.c
+++ b/drivers/pcmcia/sa1111_lubbock.c
@@ -24,20 +24,31 @@
#include <mach/hardware.h>
#include <asm/hardware/sa1111.h>
#include <asm/mach-types.h>
-#include <mach/lubbock.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
lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
const socket_state_t *state)
{
- struct sa1111_pcmcia_socket *s = to_skt(skt);
- unsigned int pa_dwr_mask, pa_dwr_set, misc_mask, misc_set;
+ struct max1600 *m = skt->driver_data;
int ret = 0;
- pa_dwr_mask = pa_dwr_set = misc_mask = misc_set = 0;
-
/* Lubbock uses the Maxim MAX1602, with the following connections:
*
* Socket 0 (PCMCIA):
@@ -71,74 +82,7 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
again:
switch (skt->nr) {
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:
- 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;
default:
@@ -147,11 +91,8 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
if (ret == 0)
ret = sa1111_pcmcia_configure_socket(skt, state);
-
- if (ret == 0) {
- lubbock_set_misc_wr(misc_mask, misc_set);
- sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);
- }
+ if (ret == 0)
+ ret = max1600_configure(m, state->Vcc, state->Vpp);
#if 1
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
*/
- lubbock_set_misc_wr(misc_mask, 0);
- sa1111_set_io(s->dev, pa_dwr_mask, 0);
+ max1600_configure(m, 0, 0);
/*
* 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 = {
.owner = THIS_MODULE,
+ .hw_init = lubbock_pcmcia_hw_init,
.configure_socket = lubbock_pcmcia_configure_socket,
.first = 0,
.nr = 2,
@@ -210,17 +151,6 @@ static struct pcmcia_low_level lubbock_pcmcia_ops = {
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_configure_sockets(&sadev->dev, &lubbock_pcmcia_ops);
return sa1111_pcmcia_add(sadev, &lubbock_pcmcia_ops,
diff --git a/drivers/pcmcia/sa1111_neponset.c b/drivers/pcmcia/sa1111_neponset.c
index 0ccf05a28a4b..de0ce13355b4 100644
--- a/drivers/pcmcia/sa1111_neponset.c
+++ b/drivers/pcmcia/sa1111_neponset.c
@@ -10,12 +10,10 @@
#include <linux/errno.h>
#include <linux/init.h>
-#include <mach/hardware.h>
#include <asm/mach-types.h>
-#include <mach/neponset.h>
-#include <asm/hardware/sa1111.h>
#include "sa1111_generic.h"
+#include "max1600.h"
/*
* Neponset uses the Maxim MAX1600, with the following connections:
@@ -40,70 +38,36 @@
* "Standard Intel code" mode. Refer to the Maxim data sheet for
* the corresponding truth table.
*/
-
-static int
-neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
+static int neponset_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
- struct sa1111_pcmcia_socket *s = to_skt(skt);
- unsigned int ncr_mask, ncr_set, pa_dwr_mask, pa_dwr_set;
+ struct max1600 *m;
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;
+ 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;
- default:
- return -1;
- }
+ return ret;
+}
- /*
- * 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;
- }
+static int
+neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
+{
+ struct max1600 *m = skt->driver_data;
+ int ret;
ret = sa1111_pcmcia_configure_socket(skt, state);
- if (ret == 0) {
- neponset_ncr_frob(ncr_mask, ncr_set);
- sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);
- }
+ if (ret == 0)
+ ret = max1600_configure(m, state->Vcc, state->Vpp);
return ret;
}
static struct pcmcia_low_level neponset_pcmcia_ops = {
.owner = THIS_MODULE,
+ .hw_init = neponset_pcmcia_hw_init,
.configure_socket = neponset_pcmcia_configure_socket,
.first = 0,
.nr = 2,
@@ -111,13 +75,6 @@ static struct pcmcia_low_level neponset_pcmcia_ops = {
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);
return sa1111_pcmcia_add(sadev, &neponset_pcmcia_ops,
sa11xx_drv_pcmcia_add_one);