Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'for-4.21' of git://git.armlinux.org.uk/~rmk/linux-arm

Pull ARM updates from Russell King:
"Included in this update:

- Florian Fainelli noticed that userspace segfaults caused by the
lack of kernel-userspace helpers was hard to diagnose; we now issue
a warning when userspace tries to use the helpers but the kernel
has them disabled.

- Ben Dooks wants compatibility for the old ATAG serial number with
DT systems.

- Some cleanup of assembly by Nicolas Pitre.

- User accessors optimisation from Vincent Whitchurch.

- More robust kdump on SMP systems from Yufen Wang.

- Sebastian Andrzej Siewior noticed problems with the SMP "boot_lock"
on RT kernels, and so we convert the Versatile series of platforms
to use a raw spinlock instead, consolidating the Versatile
implementation. We entirely remove the boot_lock on OMAP systems,
where it's unnecessary. Further patches for other systems will be
submitted for the following merge window.

- Start switching old StrongARM-11x0 systems to use gpiolib rather
than their private GPIO implementation - mostly PCMCIA bits.

- ARM Kconfig cleanups.

- Cleanup a mostly harmless mistake in the recent Spectre patch in
4.20 (which had the effect that data that can be placed into the
init sections was incorrectly always placed in the rodata section)"

* tag 'for-4.21' of git://git.armlinux.org.uk/~rmk/linux-arm: (25 commits)
ARM: omap2: remove unnecessary boot_lock
ARM: versatile: rename and comment SMP implementation
ARM: versatile: convert boot_lock to raw
ARM: vexpress/realview: consolidate immitation CPU hotplug
ARM: fix the cockup in the previous patch
ARM: sa1100/cerf: switch to using gpio_led_register_device()
ARM: sa1100/assabet: switch to using gpio leds
ARM: sa1100/assabet: add gpio keys support for right-hand two buttons
ARM: sa1111: remove legacy GPIO interfaces
pcmcia: sa1100*: remove redundant bvd1/bvd2 setting
ARM: pxa/lubbock: switch PCMCIA to MAX1600 library
ARM: pxa/mainstone: switch PCMCIA to MAX1600 library and gpiod APIs
ARM: sa1100/neponset: switch PCMCIA to MAX1600 library and gpiod APIs
ARM: sa1100/jornada720: switch PCMCIA to gpiod APIs
pcmcia: add MAX1600 library
ARM: sa1100: explicitly register sa11x0-pcmcia devices
ARM: 8813/1: Make aligned 2-byte getuser()/putuser() atomic on ARMv6+
ARM: 8812/1: Optimise copy_{from/to}_user for !CPU_USE_DOMAINS
ARM: 8811/1: always list both ldrd/strd registers explicitly
ARM: 8808/1: kexec:offline panic_smp_self_stop CPU
...

+877 -861
+12 -13
arch/arm/Kconfig
··· 28 28 select ARCH_WANT_IPC_PARSE_VERSION 29 29 select BUILDTIME_EXTABLE_SORT if MMU 30 30 select CLONE_BACKWARDS 31 - select CPU_PM if (SUSPEND || CPU_IDLE) 31 + select CPU_PM if SUSPEND || CPU_IDLE 32 32 select DCACHE_WORD_ACCESS if HAVE_EFFICIENT_UNALIGNED_ACCESS 33 33 select DMA_REMAP if MMU 34 34 select EDAC_SUPPORT 35 35 select EDAC_ATOMIC_SCRUB 36 36 select GENERIC_ALLOCATOR 37 37 select GENERIC_ARCH_TOPOLOGY if ARM_CPU_TOPOLOGY 38 - select GENERIC_ATOMIC64 if (CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI) 38 + select GENERIC_ATOMIC64 if CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI 39 39 select GENERIC_CLOCKEVENTS_BROADCAST if SMP 40 40 select GENERIC_CPU_AUTOPROBE 41 41 select GENERIC_EARLY_IOREMAP ··· 50 50 select GENERIC_STRNLEN_USER 51 51 select HANDLE_DOMAIN_IRQ 52 52 select HARDIRQS_SW_RESEND 53 - select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT) 53 + select HAVE_ARCH_AUDITSYSCALL if AEABI && !OABI_COMPAT 54 54 select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6 55 55 select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU 56 56 select HAVE_ARCH_KGDB if !CPU_ENDIAN_BE32 && MMU 57 57 select HAVE_ARCH_MMAP_RND_BITS if MMU 58 - select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT) 58 + select HAVE_ARCH_SECCOMP_FILTER if AEABI && !OABI_COMPAT 59 59 select HAVE_ARCH_THREAD_STRUCT_WHITELIST 60 60 select HAVE_ARCH_TRACEHOOK 61 61 select HAVE_ARM_SMCCC if CPU_V7 ··· 64 64 select HAVE_C_RECORDMCOUNT 65 65 select HAVE_DEBUG_KMEMLEAK 66 66 select HAVE_DMA_CONTIGUOUS if MMU 67 - select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) && !CPU_ENDIAN_BE32 && MMU 67 + select HAVE_DYNAMIC_FTRACE if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU 68 68 select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE 69 69 select HAVE_EFFICIENT_UNALIGNED_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && MMU 70 70 select HAVE_EXIT_THREAD 71 - select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL) 72 - select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL) 73 - select HAVE_FUNCTION_TRACER if (!XIP_KERNEL) 71 + select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL 72 + select HAVE_FUNCTION_GRAPH_TRACER if !THUMB2_KERNEL 73 + select HAVE_FUNCTION_TRACER if !XIP_KERNEL 74 74 select HAVE_GCC_PLUGINS 75 75 select HAVE_GENERIC_DMA_COHERENT 76 - select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7)) 76 + select HAVE_HW_BREAKPOINT if PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7) 77 77 select HAVE_IDE if PCI || ISA || PCMCIA 78 78 select HAVE_IRQ_TIME_ACCOUNTING 79 79 select HAVE_KERNEL_GZIP ··· 82 82 select HAVE_KERNEL_LZO 83 83 select HAVE_KERNEL_XZ 84 84 select HAVE_KPROBES if !XIP_KERNEL && !CPU_ENDIAN_BE32 && !CPU_V7M 85 - select HAVE_KRETPROBES if (HAVE_KPROBES) 85 + select HAVE_KRETPROBES if HAVE_KPROBES 86 86 select HAVE_MOD_ARCH_SPECIFIC 87 87 select HAVE_NMI 88 - select HAVE_OPROFILE if (HAVE_PERF_EVENTS) 88 + select HAVE_OPROFILE if HAVE_PERF_EVENTS 89 89 select HAVE_OPTPROBES if !THUMB2_KERNEL 90 90 select HAVE_PERF_EVENTS 91 91 select HAVE_PERF_REGS 92 92 select HAVE_PERF_USER_STACK_DUMP 93 - select HAVE_RCU_TABLE_FREE if (SMP && ARM_LPAE) 93 + select HAVE_RCU_TABLE_FREE if SMP && ARM_LPAE 94 94 select HAVE_REGS_AND_STACK_ACCESS_API 95 95 select HAVE_RSEQ 96 96 select HAVE_STACKPROTECTOR ··· 1738 1738 config PARAVIRT_TIME_ACCOUNTING 1739 1739 bool "Paravirtual steal time accounting" 1740 1740 select PARAVIRT 1741 - default n 1742 1741 help 1743 1742 Select this option to enable fine granularity task steal time 1744 1743 accounting. Time spent executing other tasks in parallel with
+23
arch/arm/boot/compressed/atags_to_fdt.c
··· 98 98 setprop_string(fdt, "/chosen", "bootargs", cmdline); 99 99 } 100 100 101 + static void hex_str(char *out, uint32_t value) 102 + { 103 + uint32_t digit; 104 + int idx; 105 + 106 + for (idx = 7; idx >= 0; idx--) { 107 + digit = value >> 28; 108 + value <<= 4; 109 + digit &= 0xf; 110 + if (digit < 10) 111 + digit += '0'; 112 + else 113 + digit += 'A'-10; 114 + *out++ = digit; 115 + } 116 + *out = '\0'; 117 + } 118 + 101 119 /* 102 120 * Convert and fold provided ATAGs into the provided FDT. 103 121 * ··· 198 180 initrd_start); 199 181 setprop_cell(fdt, "/chosen", "linux,initrd-end", 200 182 initrd_start + initrd_size); 183 + } else if (atag->hdr.tag == ATAG_SERIAL) { 184 + char serno[16+2]; 185 + hex_str(serno, atag->u.serialnr.high); 186 + hex_str(serno+8, atag->u.serialnr.low); 187 + setprop_string(fdt, "/", "serial-number", serno); 201 188 } 202 189 } 203 190
-59
arch/arm/common/sa1111.c
··· 1282 1282 } 1283 1283 EXPORT_SYMBOL(sa1111_get_audio_rate); 1284 1284 1285 - void sa1111_set_io_dir(struct sa1111_dev *sadev, 1286 - unsigned int bits, unsigned int dir, 1287 - unsigned int sleep_dir) 1288 - { 1289 - struct sa1111 *sachip = sa1111_chip_driver(sadev); 1290 - unsigned long flags; 1291 - unsigned int val; 1292 - void __iomem *gpio = sachip->base + SA1111_GPIO; 1293 - 1294 - #define MODIFY_BITS(port, mask, dir) \ 1295 - if (mask) { \ 1296 - val = readl_relaxed(port); \ 1297 - val &= ~(mask); \ 1298 - val |= (dir) & (mask); \ 1299 - writel_relaxed(val, port); \ 1300 - } 1301 - 1302 - spin_lock_irqsave(&sachip->lock, flags); 1303 - MODIFY_BITS(gpio + SA1111_GPIO_PADDR, bits & 15, dir); 1304 - MODIFY_BITS(gpio + SA1111_GPIO_PBDDR, (bits >> 8) & 255, dir >> 8); 1305 - MODIFY_BITS(gpio + SA1111_GPIO_PCDDR, (bits >> 16) & 255, dir >> 16); 1306 - 1307 - MODIFY_BITS(gpio + SA1111_GPIO_PASDR, bits & 15, sleep_dir); 1308 - MODIFY_BITS(gpio + SA1111_GPIO_PBSDR, (bits >> 8) & 255, sleep_dir >> 8); 1309 - MODIFY_BITS(gpio + SA1111_GPIO_PCSDR, (bits >> 16) & 255, sleep_dir >> 16); 1310 - spin_unlock_irqrestore(&sachip->lock, flags); 1311 - } 1312 - EXPORT_SYMBOL(sa1111_set_io_dir); 1313 - 1314 - void sa1111_set_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v) 1315 - { 1316 - struct sa1111 *sachip = sa1111_chip_driver(sadev); 1317 - unsigned long flags; 1318 - unsigned int val; 1319 - void __iomem *gpio = sachip->base + SA1111_GPIO; 1320 - 1321 - spin_lock_irqsave(&sachip->lock, flags); 1322 - MODIFY_BITS(gpio + SA1111_GPIO_PADWR, bits & 15, v); 1323 - MODIFY_BITS(gpio + SA1111_GPIO_PBDWR, (bits >> 8) & 255, v >> 8); 1324 - MODIFY_BITS(gpio + SA1111_GPIO_PCDWR, (bits >> 16) & 255, v >> 16); 1325 - spin_unlock_irqrestore(&sachip->lock, flags); 1326 - } 1327 - EXPORT_SYMBOL(sa1111_set_io); 1328 - 1329 - void sa1111_set_sleep_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v) 1330 - { 1331 - struct sa1111 *sachip = sa1111_chip_driver(sadev); 1332 - unsigned long flags; 1333 - unsigned int val; 1334 - void __iomem *gpio = sachip->base + SA1111_GPIO; 1335 - 1336 - spin_lock_irqsave(&sachip->lock, flags); 1337 - MODIFY_BITS(gpio + SA1111_GPIO_PASSR, bits & 15, v); 1338 - MODIFY_BITS(gpio + SA1111_GPIO_PBSSR, (bits >> 8) & 255, v >> 8); 1339 - MODIFY_BITS(gpio + SA1111_GPIO_PCSSR, (bits >> 16) & 255, v >> 16); 1340 - spin_unlock_irqrestore(&sachip->lock, flags); 1341 - } 1342 - EXPORT_SYMBOL(sa1111_set_sleep_io); 1343 - 1344 1285 /* 1345 1286 * Individual device operations. 1346 1287 */
+4 -2
arch/arm/include/asm/assembler.h
··· 243 243 .endm 244 244 #endif 245 245 246 - #define USER(x...) \ 246 + #define USERL(l, x...) \ 247 247 9999: x; \ 248 248 .pushsection __ex_table,"a"; \ 249 249 .align 3; \ 250 - .long 9999b,9001f; \ 250 + .long 9999b,l; \ 251 251 .popsection 252 + 253 + #define USER(x...) USERL(9001f, x) 252 254 253 255 #ifdef CONFIG_SMP 254 256 #define ALT_SMP(instr...) \
-4
arch/arm/include/asm/hardware/sa1111.h
··· 433 433 int sa1111_driver_register(struct sa1111_driver *); 434 434 void sa1111_driver_unregister(struct sa1111_driver *); 435 435 436 - void sa1111_set_io_dir(struct sa1111_dev *sadev, unsigned int bits, unsigned int dir, unsigned int sleep_dir); 437 - void sa1111_set_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v); 438 - void sa1111_set_sleep_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v); 439 - 440 436 struct sa1111_platform_data { 441 437 int irq_base; /* base for cascaded on-chip IRQs */ 442 438 unsigned disable_devs;
+18
arch/arm/include/asm/uaccess.h
··· 349 349 #define __get_user_asm_byte(x, addr, err) \ 350 350 __get_user_asm(x, addr, err, ldrb) 351 351 352 + #if __LINUX_ARM_ARCH__ >= 6 353 + 354 + #define __get_user_asm_half(x, addr, err) \ 355 + __get_user_asm(x, addr, err, ldrh) 356 + 357 + #else 358 + 352 359 #ifndef __ARMEB__ 353 360 #define __get_user_asm_half(x, __gu_addr, err) \ 354 361 ({ \ ··· 373 366 (x) = (__b1 << 8) | __b2; \ 374 367 }) 375 368 #endif 369 + 370 + #endif /* __LINUX_ARM_ARCH__ >= 6 */ 376 371 377 372 #define __get_user_asm_word(x, addr, err) \ 378 373 __get_user_asm(x, addr, err, ldr) ··· 451 442 #define __put_user_asm_byte(x, __pu_addr, err) \ 452 443 __put_user_asm(x, __pu_addr, err, strb) 453 444 445 + #if __LINUX_ARM_ARCH__ >= 6 446 + 447 + #define __put_user_asm_half(x, __pu_addr, err) \ 448 + __put_user_asm(x, __pu_addr, err, strh) 449 + 450 + #else 451 + 454 452 #ifndef __ARMEB__ 455 453 #define __put_user_asm_half(x, __pu_addr, err) \ 456 454 ({ \ ··· 473 457 __put_user_asm_byte(__temp, __pu_addr + 1, err); \ 474 458 }) 475 459 #endif 460 + 461 + #endif /* __LINUX_ARM_ARCH__ >= 6 */ 476 462 477 463 #define __put_user_asm_word(x, __pu_addr, err) \ 478 464 __put_user_asm(x, __pu_addr, err, str)
+1 -1
arch/arm/kernel/head.S
··· 398 398 ldmia r4, {r5, r7, r12} @ address to jump to after 399 399 sub lr, r4, r5 @ mmu has been enabled 400 400 add r3, r7, lr 401 - ldrd r4, [r3, #0] @ get secondary_data.pgdir 401 + ldrd r4, r5, [r3, #0] @ get secondary_data.pgdir 402 402 ARM_BE8(eor r4, r4, r5) @ Swap r5 and r4 in BE: 403 403 ARM_BE8(eor r5, r4, r5) @ it can be done in 3 steps 404 404 ARM_BE8(eor r4, r4, r5) @ without using a temp reg.
+15
arch/arm/kernel/smp.c
··· 724 724 pr_warn("SMP: failed to stop secondary CPUs\n"); 725 725 } 726 726 727 + /* In case panic() and panic() called at the same time on CPU1 and CPU2, 728 + * and CPU 1 calls panic_smp_self_stop() before crash_smp_send_stop() 729 + * CPU1 can't receive the ipi irqs from CPU2, CPU1 will be always online, 730 + * kdump fails. So split out the panic_smp_self_stop() and add 731 + * set_cpu_online(smp_processor_id(), false). 732 + */ 733 + void panic_smp_self_stop(void) 734 + { 735 + pr_debug("CPU %u will stop doing anything useful since another CPU has paniced\n", 736 + smp_processor_id()); 737 + set_cpu_online(smp_processor_id(), false); 738 + while (1) 739 + cpu_relax(); 740 + } 741 + 727 742 /* 728 743 * not supported here 729 744 */
+22 -1
arch/arm/lib/copy_from_user.S
··· 34 34 * Number of bytes NOT copied. 35 35 */ 36 36 37 + #ifdef CONFIG_CPU_USE_DOMAINS 38 + 37 39 #ifndef CONFIG_THUMB2_KERNEL 38 40 #define LDR1W_SHIFT 0 39 41 #else 40 42 #define LDR1W_SHIFT 1 41 43 #endif 42 - #define STR1W_SHIFT 0 43 44 44 45 .macro ldr1w ptr reg abort 45 46 ldrusr \reg, \ptr, 4, abort=\abort ··· 58 57 ldr4w \ptr, \reg5, \reg6, \reg7, \reg8, \abort 59 58 .endm 60 59 60 + #else 61 + 62 + #define LDR1W_SHIFT 0 63 + 64 + .macro ldr1w ptr reg abort 65 + USERL(\abort, W(ldr) \reg, [\ptr], #4) 66 + .endm 67 + 68 + .macro ldr4w ptr reg1 reg2 reg3 reg4 abort 69 + USERL(\abort, ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4}) 70 + .endm 71 + 72 + .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort 73 + USERL(\abort, ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}) 74 + .endm 75 + 76 + #endif /* CONFIG_CPU_USE_DOMAINS */ 77 + 61 78 .macro ldr1b ptr reg cond=al abort 62 79 ldrusr \reg, \ptr, 1, \cond, abort=\abort 63 80 .endm 81 + 82 + #define STR1W_SHIFT 0 64 83 65 84 .macro str1w ptr reg abort 66 85 W(str) \reg, [\ptr], #4
+22 -5
arch/arm/lib/copy_to_user.S
··· 35 35 */ 36 36 37 37 #define LDR1W_SHIFT 0 38 - #ifndef CONFIG_THUMB2_KERNEL 39 - #define STR1W_SHIFT 0 40 - #else 41 - #define STR1W_SHIFT 1 42 - #endif 43 38 44 39 .macro ldr1w ptr reg abort 45 40 W(ldr) \reg, [\ptr], #4 ··· 52 57 ldr\cond\()b \reg, [\ptr], #1 53 58 .endm 54 59 60 + #ifdef CONFIG_CPU_USE_DOMAINS 61 + 62 + #ifndef CONFIG_THUMB2_KERNEL 63 + #define STR1W_SHIFT 0 64 + #else 65 + #define STR1W_SHIFT 1 66 + #endif 67 + 55 68 .macro str1w ptr reg abort 56 69 strusr \reg, \ptr, 4, abort=\abort 57 70 .endm ··· 74 71 str1w \ptr, \reg7, \abort 75 72 str1w \ptr, \reg8, \abort 76 73 .endm 74 + 75 + #else 76 + 77 + #define STR1W_SHIFT 0 78 + 79 + .macro str1w ptr reg abort 80 + USERL(\abort, W(str) \reg, [\ptr], #4) 81 + .endm 82 + 83 + .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort 84 + USERL(\abort, stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}) 85 + .endm 86 + 87 + #endif /* CONFIG_CPU_USE_DOMAINS */ 77 88 78 89 .macro str1b ptr reg cond=al abort 79 90 strusr \reg, \ptr, 1, \cond, abort=\abort
+11
arch/arm/lib/getuser.S
··· 42 42 43 43 ENTRY(__get_user_2) 44 44 check_uaccess r0, 2, r1, r2, __get_user_bad 45 + #if __LINUX_ARM_ARCH__ >= 6 46 + 47 + 2: TUSER(ldrh) r2, [r0] 48 + 49 + #else 50 + 45 51 #ifdef CONFIG_CPU_USE_DOMAINS 46 52 rb .req ip 47 53 2: ldrbt r2, [r0], #1 ··· 62 56 #else 63 57 orr r2, rb, r2, lsl #8 64 58 #endif 59 + 60 + #endif /* __LINUX_ARM_ARCH__ >= 6 */ 61 + 65 62 mov r0, #0 66 63 ret lr 67 64 ENDPROC(__get_user_2) ··· 154 145 .pushsection __ex_table, "a" 155 146 .long 1b, __get_user_bad 156 147 .long 2b, __get_user_bad 148 + #if __LINUX_ARM_ARCH__ < 6 157 149 .long 3b, __get_user_bad 150 + #endif 158 151 .long 4b, __get_user_bad 159 152 .long 5b, __get_user_bad8 160 153 .long 6b, __get_user_bad8
+10 -10
arch/arm/lib/putuser.S
··· 41 41 42 42 ENTRY(__put_user_2) 43 43 check_uaccess r0, 2, r1, ip, __put_user_bad 44 - mov ip, r2, lsr #8 45 - #ifdef CONFIG_THUMB2_KERNEL 46 - #ifndef __ARMEB__ 47 - 2: TUSER(strb) r2, [r0] 48 - 3: TUSER(strb) ip, [r0, #1] 44 + #if __LINUX_ARM_ARCH__ >= 6 45 + 46 + 2: TUSER(strh) r2, [r0] 47 + 49 48 #else 50 - 2: TUSER(strb) ip, [r0] 51 - 3: TUSER(strb) r2, [r0, #1] 52 - #endif 53 - #else /* !CONFIG_THUMB2_KERNEL */ 49 + 50 + mov ip, r2, lsr #8 54 51 #ifndef __ARMEB__ 55 52 2: TUSER(strb) r2, [r0], #1 56 53 3: TUSER(strb) ip, [r0] ··· 55 58 2: TUSER(strb) ip, [r0], #1 56 59 3: TUSER(strb) r2, [r0] 57 60 #endif 58 - #endif /* CONFIG_THUMB2_KERNEL */ 61 + 62 + #endif /* __LINUX_ARM_ARCH__ >= 6 */ 59 63 mov r0, #0 60 64 ret lr 61 65 ENDPROC(__put_user_2) ··· 89 91 .pushsection __ex_table, "a" 90 92 .long 1b, __put_user_bad 91 93 .long 2b, __put_user_bad 94 + #if __LINUX_ARM_ARCH__ < 6 92 95 .long 3b, __put_user_bad 96 + #endif 93 97 .long 4b, __put_user_bad 94 98 .long 5b, __put_user_bad 95 99 .long 6b, __put_user_bad
-1
arch/arm/mach-omap2/Kconfig
··· 223 223 config OMAP3_SDRC_AC_TIMING 224 224 bool "Enable SDRC AC timing register changes" 225 225 depends on ARCH_OMAP3 226 - default n 227 226 help 228 227 If you know that none of your system initiators will attempt to 229 228 access SDRAM during CORE DVFS, select Y here. This should boost
-20
arch/arm/mach-omap2/omap-smp.c
··· 69 69 .startup_addr = omap5_secondary_startup, 70 70 }; 71 71 72 - static DEFINE_SPINLOCK(boot_lock); 73 - 74 72 void __iomem *omap4_get_scu_base(void) 75 73 { 76 74 return cfg.scu_base; ··· 171 173 /* Enable ACR to allow for ICUALLU workaround */ 172 174 omap5_secondary_harden_predictor(); 173 175 } 174 - 175 - /* 176 - * Synchronise with the boot thread. 177 - */ 178 - spin_lock(&boot_lock); 179 - spin_unlock(&boot_lock); 180 176 } 181 177 182 178 static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle) ··· 178 186 static struct clockdomain *cpu1_clkdm; 179 187 static bool booted; 180 188 static struct powerdomain *cpu1_pwrdm; 181 - 182 - /* 183 - * Set synchronisation state between this boot processor 184 - * and the secondary one 185 - */ 186 - spin_lock(&boot_lock); 187 189 188 190 /* 189 191 * Update the AuxCoreBoot0 with boot state for secondary core. ··· 251 265 } 252 266 253 267 arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 254 - 255 - /* 256 - * Now the secondary core is starting up let it run its 257 - * calibrations, then wait for it to finish 258 - */ 259 - spin_unlock(&boot_lock); 260 268 261 269 return 0; 262 270 }
+1 -1
arch/arm/mach-pxa/Kconfig
··· 46 46 47 47 config MACH_MAINSTONE 48 48 bool "Intel HCDDBBVA0 Development Platform (aka Mainstone)" 49 + select GPIO_REG 49 50 select PXA27x 50 51 51 52 config MACH_ZYLONITE ··· 552 551 config TOSA_USE_EXT_KEYCODES 553 552 bool "Tosa keyboard: use extended keycodes" 554 553 depends on MACH_TOSA 555 - default n 556 554 help 557 555 Say Y here to enable the tosa keyboard driver to generate extended 558 556 (>= 127) keycodes. Be aware, that they can't be correctly interpreted
+4
arch/arm/mach-pxa/include/mach/mainstone.h
··· 119 119 #define MST_PCMCIA_PWR_VCC_33 0x8 /* voltage VCC = 3.3V */ 120 120 #define MST_PCMCIA_PWR_VCC_50 0x4 /* voltage VCC = 5.0V */ 121 121 122 + #define MST_PCMCIA_INPUTS \ 123 + (MST_PCMCIA_nIRQ | MST_PCMCIA_nSPKR_BVD2 | MST_PCMCIA_nSTSCHG_BVD1 | \ 124 + MST_PCMCIA_nVS2 | MST_PCMCIA_nVS1 | MST_PCMCIA_nCD) 125 + 122 126 /* board specific IRQs */ 123 127 #define MAINSTONE_NR_IRQS IRQ_BOARD_START 124 128
+16
arch/arm/mach-pxa/lubbock.c
··· 136 136 // no D+ pullup; lubbock can't connect/disconnect in software 137 137 }; 138 138 139 + /* GPIOs for SA1111 PCMCIA */ 140 + static struct gpiod_lookup_table sa1111_pcmcia_gpio_table = { 141 + .dev_id = "1800", 142 + .table = { 143 + { "sa1111", 0, "a0vpp", GPIO_ACTIVE_HIGH }, 144 + { "sa1111", 1, "a1vpp", GPIO_ACTIVE_HIGH }, 145 + { "sa1111", 2, "a0vcc", GPIO_ACTIVE_HIGH }, 146 + { "sa1111", 3, "a1vcc", GPIO_ACTIVE_HIGH }, 147 + { "lubbock", 14, "b0vcc", GPIO_ACTIVE_HIGH }, 148 + { "lubbock", 15, "b1vcc", GPIO_ACTIVE_HIGH }, 149 + { }, 150 + }, 151 + }; 152 + 139 153 static void lubbock_init_pcmcia(void) 140 154 { 141 155 struct clk *clk; 156 + 157 + gpiod_add_lookup_table(&sa1111_pcmcia_gpio_table); 142 158 143 159 /* Add an alias for the SA1111 PCMCIA clock */ 144 160 clk = clk_get_sys("pxa2xx-pcmcia", NULL);
+53
arch/arm/mach-pxa/mainstone.c
··· 13 13 * published by the Free Software Foundation. 14 14 */ 15 15 #include <linux/gpio.h> 16 + #include <linux/gpio/gpio-reg.h> 16 17 #include <linux/gpio/machine.h> 17 18 #include <linux/init.h> 18 19 #include <linux/platform_device.h> ··· 505 504 static inline void mainstone_init_keypad(void) {} 506 505 #endif 507 506 507 + static int mst_pcmcia0_irqs[11] = { 508 + [0 ... 10] = -1, 509 + [5] = MAINSTONE_S0_CD_IRQ, 510 + [8] = MAINSTONE_S0_STSCHG_IRQ, 511 + [10] = MAINSTONE_S0_IRQ, 512 + }; 513 + 514 + static int mst_pcmcia1_irqs[11] = { 515 + [0 ... 10] = -1, 516 + [5] = MAINSTONE_S1_CD_IRQ, 517 + [8] = MAINSTONE_S1_STSCHG_IRQ, 518 + [10] = MAINSTONE_S1_IRQ, 519 + }; 520 + 521 + static struct gpiod_lookup_table mainstone_pcmcia_gpio_table = { 522 + .dev_id = "pxa2xx-pcmcia", 523 + .table = { 524 + GPIO_LOOKUP("mst-pcmcia0", 0, "a0vpp", GPIO_ACTIVE_HIGH), 525 + GPIO_LOOKUP("mst-pcmcia0", 1, "a1vpp", GPIO_ACTIVE_HIGH), 526 + GPIO_LOOKUP("mst-pcmcia0", 2, "a0vcc", GPIO_ACTIVE_HIGH), 527 + GPIO_LOOKUP("mst-pcmcia0", 3, "a1vcc", GPIO_ACTIVE_HIGH), 528 + GPIO_LOOKUP("mst-pcmcia0", 4, "areset", GPIO_ACTIVE_HIGH), 529 + GPIO_LOOKUP("mst-pcmcia0", 5, "adetect", GPIO_ACTIVE_LOW), 530 + GPIO_LOOKUP("mst-pcmcia0", 6, "avs1", GPIO_ACTIVE_LOW), 531 + GPIO_LOOKUP("mst-pcmcia0", 7, "avs2", GPIO_ACTIVE_LOW), 532 + GPIO_LOOKUP("mst-pcmcia0", 8, "abvd1", GPIO_ACTIVE_HIGH), 533 + GPIO_LOOKUP("mst-pcmcia0", 9, "abvd2", GPIO_ACTIVE_HIGH), 534 + GPIO_LOOKUP("mst-pcmcia0", 10, "aready", GPIO_ACTIVE_HIGH), 535 + GPIO_LOOKUP("mst-pcmcia1", 0, "b0vpp", GPIO_ACTIVE_HIGH), 536 + GPIO_LOOKUP("mst-pcmcia1", 1, "b1vpp", GPIO_ACTIVE_HIGH), 537 + GPIO_LOOKUP("mst-pcmcia1", 2, "b0vcc", GPIO_ACTIVE_HIGH), 538 + GPIO_LOOKUP("mst-pcmcia1", 3, "b1vcc", GPIO_ACTIVE_HIGH), 539 + GPIO_LOOKUP("mst-pcmcia1", 4, "breset", GPIO_ACTIVE_HIGH), 540 + GPIO_LOOKUP("mst-pcmcia1", 5, "bdetect", GPIO_ACTIVE_LOW), 541 + GPIO_LOOKUP("mst-pcmcia1", 6, "bvs1", GPIO_ACTIVE_LOW), 542 + GPIO_LOOKUP("mst-pcmcia1", 7, "bvs2", GPIO_ACTIVE_LOW), 543 + GPIO_LOOKUP("mst-pcmcia1", 8, "bbvd1", GPIO_ACTIVE_HIGH), 544 + GPIO_LOOKUP("mst-pcmcia1", 9, "bbvd2", GPIO_ACTIVE_HIGH), 545 + GPIO_LOOKUP("mst-pcmcia1", 10, "bready", GPIO_ACTIVE_HIGH), 546 + { }, 547 + }, 548 + }; 549 + 508 550 static void __init mainstone_init(void) 509 551 { 510 552 int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */ 511 553 512 554 pxa2xx_mfp_config(ARRAY_AND_SIZE(mainstone_pin_config)); 555 + 556 + /* Register board control register(s) as GPIOs */ 557 + gpio_reg_init(NULL, (void __iomem *)&MST_PCMCIA0, -1, 11, 558 + "mst-pcmcia0", MST_PCMCIA_INPUTS, 0, NULL, 559 + NULL, mst_pcmcia0_irqs); 560 + gpio_reg_init(NULL, (void __iomem *)&MST_PCMCIA1, -1, 11, 561 + "mst-pcmcia1", MST_PCMCIA_INPUTS, 0, NULL, 562 + NULL, mst_pcmcia1_irqs); 563 + gpiod_add_lookup_table(&mainstone_pcmcia_gpio_table); 513 564 514 565 pxa_set_ffuart_info(NULL); 515 566 pxa_set_btuart_info(NULL);
-1
arch/arm/mach-realview/Makefile
··· 5 5 6 6 obj-y += realview-dt.o 7 7 obj-$(CONFIG_SMP) += platsmp-dt.o 8 - obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+30 -36
arch/arm/mach-realview/hotplug.c arch/arm/plat-versatile/hotplug.c
··· 1 1 /* 2 - * linux/arch/arm/mach-realview/hotplug.c 3 - * 4 2 * Copyright (C) 2002 ARM Ltd. 5 3 * All Rights Reserved 6 4 * 7 5 * This program is free software; you can redistribute it and/or modify 8 6 * it under the terms of the GNU General Public License version 2 as 9 7 * published by the Free Software Foundation. 8 + * 9 + * This hotplug implementation is _specific_ to the situation found on 10 + * ARM development platforms where there is _no_ possibility of actually 11 + * taking a CPU offline, resetting it, or otherwise. Real platforms must 12 + * NOT copy this code. 10 13 */ 11 14 #include <linux/kernel.h> 12 15 #include <linux/errno.h> 13 16 #include <linux/smp.h> 14 17 15 - #include <asm/cp15.h> 16 18 #include <asm/smp_plat.h> 19 + #include <asm/cp15.h> 17 20 18 - static inline void cpu_enter_lowpower(void) 21 + #include <plat/platsmp.h> 22 + 23 + static inline void versatile_immitation_enter_lowpower(unsigned int actrl_mask) 19 24 { 20 25 unsigned int v; 21 26 22 27 asm volatile( 23 - " mcr p15, 0, %1, c7, c5, 0\n" 28 + "mcr p15, 0, %1, c7, c5, 0\n" 24 29 " mcr p15, 0, %1, c7, c10, 4\n" 25 30 /* 26 31 * Turn off coherency 27 32 */ 28 33 " mrc p15, 0, %0, c1, c0, 1\n" 29 - " bic %0, %0, #0x20\n" 34 + " bic %0, %0, %3\n" 30 35 " mcr p15, 0, %0, c1, c0, 1\n" 31 36 " mrc p15, 0, %0, c1, c0, 0\n" 32 37 " bic %0, %0, %2\n" 33 38 " mcr p15, 0, %0, c1, c0, 0\n" 34 39 : "=&r" (v) 35 - : "r" (0), "Ir" (CR_C) 40 + : "r" (0), "Ir" (CR_C), "Ir" (actrl_mask) 36 41 : "cc"); 37 42 } 38 43 39 - static inline void cpu_leave_lowpower(void) 44 + static inline void versatile_immitation_leave_lowpower(unsigned int actrl_mask) 40 45 { 41 46 unsigned int v; 42 47 43 - asm volatile( "mrc p15, 0, %0, c1, c0, 0\n" 48 + asm volatile( 49 + "mrc p15, 0, %0, c1, c0, 0\n" 44 50 " orr %0, %0, %1\n" 45 51 " mcr p15, 0, %0, c1, c0, 0\n" 46 52 " mrc p15, 0, %0, c1, c0, 1\n" 47 - " orr %0, %0, #0x20\n" 53 + " orr %0, %0, %2\n" 48 54 " mcr p15, 0, %0, c1, c0, 1\n" 49 55 : "=&r" (v) 50 - : "Ir" (CR_C) 56 + : "Ir" (CR_C), "Ir" (actrl_mask) 51 57 : "cc"); 52 58 } 53 59 54 - static inline void platform_do_lowpower(unsigned int cpu, int *spurious) 60 + static inline void versatile_immitation_do_lowpower(unsigned int cpu, int *spurious) 55 61 { 56 62 /* 57 63 * there is no power-control hardware on this platform, so all 58 64 * we can do is put the core into WFI; this is safe as the calling 59 - * code will have already disabled interrupts 65 + * code will have already disabled interrupts. 66 + * 67 + * This code should not be used outside Versatile platforms. 60 68 */ 61 69 for (;;) { 62 - /* 63 - * here's the WFI 64 - */ 65 - asm(".word 0xe320f003\n" 66 - : 67 - : 68 - : "memory", "cc"); 70 + wfi(); 69 71 70 - if (pen_release == cpu_logical_map(cpu)) { 72 + if (versatile_cpu_release == cpu_logical_map(cpu)) { 71 73 /* 72 74 * OK, proper wakeup, we're done 73 75 */ ··· 88 86 } 89 87 90 88 /* 91 - * platform-specific code to shutdown a CPU 92 - * 93 - * Called with IRQs disabled 89 + * platform-specific code to shutdown a CPU. 90 + * This code supports immitation-style CPU hotplug for Versatile/Realview/ 91 + * Versatile Express platforms that are unable to do real CPU hotplug. 94 92 */ 95 - void realview_cpu_die(unsigned int cpu) 93 + void versatile_immitation_cpu_die(unsigned int cpu, unsigned int actrl_mask) 96 94 { 97 95 int spurious = 0; 98 96 99 - /* 100 - * we're ready for shutdown now, so do it 101 - */ 102 - cpu_enter_lowpower(); 103 - platform_do_lowpower(cpu, &spurious); 104 - 105 - /* 106 - * bring this CPU back into the world of cache 107 - * coherency, and then restore interrupts 108 - */ 109 - cpu_leave_lowpower(); 97 + versatile_immitation_enter_lowpower(actrl_mask); 98 + versatile_immitation_do_lowpower(cpu, &spurious); 99 + versatile_immitation_leave_lowpower(actrl_mask); 110 100 111 101 if (spurious) 112 102 pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
-1
arch/arm/mach-realview/hotplug.h
··· 1 - void realview_cpu_die(unsigned int cpu);
+7 -1
arch/arm/mach-realview/platsmp-dt.c
··· 17 17 #include <asm/smp_scu.h> 18 18 19 19 #include <plat/platsmp.h> 20 - #include "hotplug.h" 21 20 22 21 #define REALVIEW_SYS_FLAGSSET_OFFSET 0x30 23 22 ··· 77 78 regmap_write(map, REALVIEW_SYS_FLAGSSET_OFFSET, 78 79 __pa_symbol(versatile_secondary_startup)); 79 80 } 81 + 82 + #ifdef CONFIG_HOTPLUG_CPU 83 + static void realview_cpu_die(unsigned int cpu) 84 + { 85 + return versatile_immitation_cpu_die(cpu, 0x20); 86 + } 87 + #endif 80 88 81 89 static const struct smp_operations realview_dt_smp_ops __initconst = { 82 90 .smp_prepare_cpus = realview_smp_prepare_cpus,
+2
arch/arm/mach-sa1100/Kconfig
··· 6 6 bool "Assabet" 7 7 select ARM_SA1110_CPUFREQ 8 8 select GPIO_REG 9 + select LEDS_GPIO_REGISTER 9 10 select REGULATOR 10 11 select REGULATOR_FIXED_VOLTAGE 11 12 help ··· 25 24 config SA1100_CERF 26 25 bool "CerfBoard" 27 26 select ARM_SA1110_CPUFREQ 27 + select LEDS_GPIO_REGISTER 28 28 help 29 29 The Intrinsyc CerfBoard is based on the StrongARM 1110 (Discontinued). 30 30 More information is available at:
+57 -86
arch/arm/mach-sa1100/assabet.c
··· 15 15 #include <linux/errno.h> 16 16 #include <linux/gpio/gpio-reg.h> 17 17 #include <linux/gpio/machine.h> 18 + #include <linux/gpio_keys.h> 18 19 #include <linux/ioport.h> 19 20 #include <linux/platform_data/sa11x0-serial.h> 20 21 #include <linux/regulator/fixed.h> ··· 102 101 103 102 assabet_bcr_gc = gc; 104 103 105 - return 0; 104 + return gc->base; 106 105 } 107 106 108 107 /* ··· 480 479 }, 481 480 }; 482 481 482 + static struct gpio_led assabet_leds[] __initdata = { 483 + { 484 + .name = "assabet:red", 485 + .default_trigger = "cpu0", 486 + .active_low = 1, 487 + .default_state = LEDS_GPIO_DEFSTATE_KEEP, 488 + }, { 489 + .name = "assabet:green", 490 + .default_trigger = "heartbeat", 491 + .active_low = 1, 492 + .default_state = LEDS_GPIO_DEFSTATE_KEEP, 493 + }, 494 + }; 495 + 496 + static const struct gpio_led_platform_data assabet_leds_pdata __initconst = { 497 + .num_leds = ARRAY_SIZE(assabet_leds), 498 + .leds = assabet_leds, 499 + }; 500 + 501 + static struct gpio_keys_button assabet_keys_buttons[] = { 502 + { 503 + .gpio = 0, 504 + .irq = IRQ_GPIO0, 505 + .desc = "gpio0", 506 + .wakeup = 1, 507 + .can_disable = 1, 508 + .debounce_interval = 5, 509 + }, { 510 + .gpio = 1, 511 + .irq = IRQ_GPIO1, 512 + .desc = "gpio1", 513 + .wakeup = 1, 514 + .can_disable = 1, 515 + .debounce_interval = 5, 516 + }, 517 + }; 518 + 519 + static const struct gpio_keys_platform_data assabet_keys_pdata = { 520 + .buttons = assabet_keys_buttons, 521 + .nbuttons = ARRAY_SIZE(assabet_keys_buttons), 522 + .rep = 0, 523 + }; 524 + 483 525 static void __init assabet_init(void) 484 526 { 485 527 /* ··· 576 532 true); 577 533 578 534 } 535 + 536 + platform_device_register_resndata(NULL, "gpio-keys", 0, 537 + NULL, 0, 538 + &assabet_keys_pdata, 539 + sizeof(assabet_keys_pdata)); 540 + 541 + gpio_led_register_device(-1, &assabet_leds_pdata); 579 542 580 543 #ifndef ASSABET_PAL_VIDEO 581 544 sa11x0_register_lcd(&lq039q2ds54_info); ··· 777 726 sa1100_register_uart(2, 3); 778 727 } 779 728 780 - /* LEDs */ 781 - #if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) 782 - struct assabet_led { 783 - struct led_classdev cdev; 784 - u32 mask; 785 - }; 786 - 787 - /* 788 - * The triggers lines up below will only be used if the 789 - * LED triggers are compiled in. 790 - */ 791 - static const struct { 792 - const char *name; 793 - const char *trigger; 794 - } assabet_leds[] = { 795 - { "assabet:red", "cpu0",}, 796 - { "assabet:green", "heartbeat", }, 797 - }; 798 - 799 - /* 800 - * The LED control in Assabet is reversed: 801 - * - setting bit means turn off LED 802 - * - clearing bit means turn on LED 803 - */ 804 - static void assabet_led_set(struct led_classdev *cdev, 805 - enum led_brightness b) 806 - { 807 - struct assabet_led *led = container_of(cdev, 808 - struct assabet_led, cdev); 809 - 810 - if (b != LED_OFF) 811 - ASSABET_BCR_clear(led->mask); 812 - else 813 - ASSABET_BCR_set(led->mask); 814 - } 815 - 816 - static enum led_brightness assabet_led_get(struct led_classdev *cdev) 817 - { 818 - struct assabet_led *led = container_of(cdev, 819 - struct assabet_led, cdev); 820 - 821 - return (ASSABET_BCR & led->mask) ? LED_OFF : LED_FULL; 822 - } 823 - 824 - static int __init assabet_leds_init(void) 825 - { 826 - int i; 827 - 828 - if (!machine_is_assabet()) 829 - return -ENODEV; 830 - 831 - for (i = 0; i < ARRAY_SIZE(assabet_leds); i++) { 832 - struct assabet_led *led; 833 - 834 - led = kzalloc(sizeof(*led), GFP_KERNEL); 835 - if (!led) 836 - break; 837 - 838 - led->cdev.name = assabet_leds[i].name; 839 - led->cdev.brightness_set = assabet_led_set; 840 - led->cdev.brightness_get = assabet_led_get; 841 - led->cdev.default_trigger = assabet_leds[i].trigger; 842 - 843 - if (!i) 844 - led->mask = ASSABET_BCR_LED_RED; 845 - else 846 - led->mask = ASSABET_BCR_LED_GREEN; 847 - 848 - if (led_classdev_register(NULL, &led->cdev) < 0) { 849 - kfree(led); 850 - break; 851 - } 852 - } 853 - 854 - return 0; 855 - } 856 - 857 - /* 858 - * Since we may have triggers on any subsystem, defer registration 859 - * until after subsystem_init. 860 - */ 861 - fs_initcall(assabet_leds_init); 862 - #endif 863 - 864 729 void __init assabet_init_irq(void) 865 730 { 731 + unsigned int assabet_gpio_base; 866 732 u32 def_val; 867 733 868 734 sa1100_init_irq(); ··· 794 826 * 795 827 * This must precede any driver calls to BCR_set() or BCR_clear(). 796 828 */ 797 - assabet_init_gpio((void *)&ASSABET_BCR, def_val); 829 + assabet_gpio_base = assabet_init_gpio((void *)&ASSABET_BCR, def_val); 830 + 831 + assabet_leds[0].gpio = assabet_gpio_base + 13; 832 + assabet_leds[1].gpio = assabet_gpio_base + 14; 798 833 } 799 834 800 835 MACHINE_START(ASSABET, "Intel-Assabet")
+1 -10
arch/arm/mach-sa1100/cerf.c
··· 89 89 .num_leds = ARRAY_SIZE(cerf_gpio_leds), 90 90 }; 91 91 92 - static struct platform_device cerf_leds = { 93 - .name = "leds-gpio", 94 - .id = -1, 95 - .dev = { 96 - .platform_data = &cerf_gpio_led_info, 97 - } 98 - }; 99 - 100 - 101 92 static struct platform_device *cerf_devices[] __initdata = { 102 93 &cerfuart2_device, 103 - &cerf_leds, 104 94 }; 105 95 106 96 #ifdef CONFIG_SA1100_CERF_FLASH_32MB ··· 166 176 { 167 177 sa11x0_ppc_configure_mcp(); 168 178 platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices)); 179 + gpio_led_register_device(-1, &cerf_gpio_led_info); 169 180 sa11x0_register_mtd(&cerf_flash_data, &cerf_flash_resource, 1); 170 181 sa11x0_register_mcp(&cerf_mcp_data); 171 182 sa11x0_register_pcmcia(1, &cerf_cf_gpio_table);
-10
arch/arm/mach-sa1100/generic.c
··· 235 235 sa11x0_register_device(&sa11x0fb_device, inf); 236 236 } 237 237 238 - static bool sa11x0pcmcia_legacy = true; 239 - static struct platform_device sa11x0pcmcia_device = { 240 - .name = "sa11x0-pcmcia", 241 - .id = -1, 242 - }; 243 - 244 238 void sa11x0_register_pcmcia(int socket, struct gpiod_lookup_table *table) 245 239 { 246 240 if (table) 247 241 gpiod_add_lookup_table(table); 248 242 platform_device_register_simple("sa11x0-pcmcia", socket, NULL, 0); 249 - sa11x0pcmcia_legacy = false; 250 243 } 251 244 252 245 static struct platform_device sa11x0mtd_device = { ··· 323 330 static int __init sa1100_init(void) 324 331 { 325 332 pm_power_off = sa1100_power_off; 326 - 327 - if (sa11x0pcmcia_legacy) 328 - platform_device_register(&sa11x0pcmcia_device); 329 333 330 334 regulator_has_full_constraints(); 331 335
+1
arch/arm/mach-sa1100/h3100.c
··· 126 126 { 127 127 h3xxx_mach_init(); 128 128 129 + sa11x0_register_pcmcia(-1, NULL); 129 130 sa11x0_register_lcd(&h3100_lcd_info); 130 131 sa11x0_register_irda(&h3100_irda_data); 131 132 }
+12
arch/arm/mach-sa1100/jornada720.c
··· 190 190 .resource = s1d13xxxfb_resources, 191 191 }; 192 192 193 + static struct gpiod_lookup_table jornada_pcmcia_gpiod_table = { 194 + .dev_id = "1800", 195 + .table = { 196 + GPIO_LOOKUP("sa1111", 0, "s0-power", GPIO_ACTIVE_HIGH), 197 + GPIO_LOOKUP("sa1111", 1, "s1-power", GPIO_ACTIVE_HIGH), 198 + GPIO_LOOKUP("sa1111", 2, "s0-3v", GPIO_ACTIVE_HIGH), 199 + GPIO_LOOKUP("sa1111", 3, "s1-3v", GPIO_ACTIVE_HIGH), 200 + { }, 201 + }, 202 + }; 203 + 193 204 static struct resource sa1111_resources[] = { 194 205 [0] = DEFINE_RES_MEM(SA1111REGSTART, SA1111REGLEN), 195 206 [1] = DEFINE_RES_IRQ(IRQ_GPIO1), ··· 276 265 udelay(20); /* give it some time to restart */ 277 266 278 267 gpiod_add_lookup_table(&jornada_ts_gpiod_table); 268 + gpiod_add_lookup_table(&jornada_pcmcia_gpiod_table); 279 269 280 270 ret = platform_add_devices(devices, ARRAY_SIZE(devices)); 281 271 }
+19
arch/arm/mach-sa1100/neponset.c
··· 5 5 #include <linux/err.h> 6 6 #include <linux/gpio/driver.h> 7 7 #include <linux/gpio/gpio-reg.h> 8 + #include <linux/gpio/machine.h> 8 9 #include <linux/init.h> 9 10 #include <linux/ioport.h> 10 11 #include <linux/irq.h> ··· 95 94 struct platform_device *smc91x; 96 95 unsigned irq_base; 97 96 struct gpio_chip *gpio[4]; 97 + }; 98 + 99 + static struct gpiod_lookup_table neponset_pcmcia_table = { 100 + .dev_id = "1800", 101 + .table = { 102 + GPIO_LOOKUP("sa1111", 1, "a0vcc", GPIO_ACTIVE_HIGH), 103 + GPIO_LOOKUP("sa1111", 0, "a1vcc", GPIO_ACTIVE_HIGH), 104 + GPIO_LOOKUP("neponset-ncr", 5, "a0vpp", GPIO_ACTIVE_HIGH), 105 + GPIO_LOOKUP("neponset-ncr", 6, "a1vpp", GPIO_ACTIVE_HIGH), 106 + GPIO_LOOKUP("sa1111", 2, "b0vcc", GPIO_ACTIVE_HIGH), 107 + GPIO_LOOKUP("sa1111", 3, "b1vcc", GPIO_ACTIVE_HIGH), 108 + { }, 109 + }, 98 110 }; 99 111 100 112 static struct neponset_drvdata *nep; ··· 388 374 d->base + AUD_CTL, AUD_NGPIO, false, 389 375 neponset_aud_names); 390 376 377 + gpiod_add_lookup_table(&neponset_pcmcia_table); 378 + 391 379 /* 392 380 * We would set IRQ_GPIO25 to be a wake-up IRQ, but unfortunately 393 381 * something on the Neponset activates this IRQ on sleep (eth?) ··· 440 424 platform_device_unregister(d->sa1111); 441 425 if (!IS_ERR(d->smc91x)) 442 426 platform_device_unregister(d->smc91x); 427 + 428 + gpiod_remove_lookup_table(&neponset_pcmcia_table); 429 + 443 430 irq_set_chained_handler(irq, NULL); 444 431 irq_free_descs(d->irq_base, NEP_IRQ_NR); 445 432 nep = NULL;
-1
arch/arm/mach-vexpress/Makefile
··· 15 15 CFLAGS_tc2_pm.o += -march=armv7-a 16 16 CFLAGS_REMOVE_tc2_pm.o = -pg 17 17 obj-$(CONFIG_SMP) += platsmp.o 18 - obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 19 18 20 19 obj-$(CONFIG_ARCH_MPS2) += v2m-mps2.o
-2
arch/arm/mach-vexpress/core.h
··· 1 1 bool vexpress_smp_init_ops(void); 2 2 3 3 extern const struct smp_operations vexpress_smp_dt_ops; 4 - 5 - extern void vexpress_cpu_die(unsigned int cpu);
-108
arch/arm/mach-vexpress/hotplug.c
··· 1 - /* 2 - * linux/arch/arm/mach-realview/hotplug.c 3 - * 4 - * Copyright (C) 2002 ARM Ltd. 5 - * All Rights Reserved 6 - * 7 - * This program is free software; you can redistribute it and/or modify 8 - * it under the terms of the GNU General Public License version 2 as 9 - * published by the Free Software Foundation. 10 - */ 11 - #include <linux/kernel.h> 12 - #include <linux/errno.h> 13 - #include <linux/smp.h> 14 - 15 - #include <asm/smp_plat.h> 16 - #include <asm/cp15.h> 17 - 18 - #include "core.h" 19 - 20 - static inline void cpu_enter_lowpower(void) 21 - { 22 - unsigned int v; 23 - 24 - asm volatile( 25 - "mcr p15, 0, %1, c7, c5, 0\n" 26 - " mcr p15, 0, %1, c7, c10, 4\n" 27 - /* 28 - * Turn off coherency 29 - */ 30 - " mrc p15, 0, %0, c1, c0, 1\n" 31 - " bic %0, %0, %3\n" 32 - " mcr p15, 0, %0, c1, c0, 1\n" 33 - " mrc p15, 0, %0, c1, c0, 0\n" 34 - " bic %0, %0, %2\n" 35 - " mcr p15, 0, %0, c1, c0, 0\n" 36 - : "=&r" (v) 37 - : "r" (0), "Ir" (CR_C), "Ir" (0x40) 38 - : "cc"); 39 - } 40 - 41 - static inline void cpu_leave_lowpower(void) 42 - { 43 - unsigned int v; 44 - 45 - asm volatile( 46 - "mrc p15, 0, %0, c1, c0, 0\n" 47 - " orr %0, %0, %1\n" 48 - " mcr p15, 0, %0, c1, c0, 0\n" 49 - " mrc p15, 0, %0, c1, c0, 1\n" 50 - " orr %0, %0, %2\n" 51 - " mcr p15, 0, %0, c1, c0, 1\n" 52 - : "=&r" (v) 53 - : "Ir" (CR_C), "Ir" (0x40) 54 - : "cc"); 55 - } 56 - 57 - static inline void platform_do_lowpower(unsigned int cpu, int *spurious) 58 - { 59 - /* 60 - * there is no power-control hardware on this platform, so all 61 - * we can do is put the core into WFI; this is safe as the calling 62 - * code will have already disabled interrupts 63 - */ 64 - for (;;) { 65 - wfi(); 66 - 67 - if (pen_release == cpu_logical_map(cpu)) { 68 - /* 69 - * OK, proper wakeup, we're done 70 - */ 71 - break; 72 - } 73 - 74 - /* 75 - * Getting here, means that we have come out of WFI without 76 - * having been woken up - this shouldn't happen 77 - * 78 - * Just note it happening - when we're woken, we can report 79 - * its occurrence. 80 - */ 81 - (*spurious)++; 82 - } 83 - } 84 - 85 - /* 86 - * platform-specific code to shutdown a CPU 87 - * 88 - * Called with IRQs disabled 89 - */ 90 - void vexpress_cpu_die(unsigned int cpu) 91 - { 92 - int spurious = 0; 93 - 94 - /* 95 - * we're ready for shutdown now, so do it 96 - */ 97 - cpu_enter_lowpower(); 98 - platform_do_lowpower(cpu, &spurious); 99 - 100 - /* 101 - * bring this CPU back into the world of cache 102 - * coherency, and then restore interrupts 103 - */ 104 - cpu_leave_lowpower(); 105 - 106 - if (spurious) 107 - pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); 108 - }
+7
arch/arm/mach-vexpress/platsmp.c
··· 82 82 vexpress_flags_set(__pa_symbol(versatile_secondary_startup)); 83 83 } 84 84 85 + #ifdef CONFIG_HOTPLUG_CPU 86 + static void vexpress_cpu_die(unsigned int cpu) 87 + { 88 + versatile_immitation_cpu_die(cpu, 0x40); 89 + } 90 + #endif 91 + 85 92 const struct smp_operations vexpress_smp_dt_ops __initconst = { 86 93 .smp_prepare_cpus = vexpress_smp_dt_prepare_cpus, 87 94 .smp_secondary_init = versatile_secondary_init,
+17 -18
arch/arm/mm/copypage-fa.c
··· 17 17 /* 18 18 * Faraday optimised copy_user_page 19 19 */ 20 - static void __naked 21 - fa_copy_user_page(void *kto, const void *kfrom) 20 + static void fa_copy_user_page(void *kto, const void *kfrom) 22 21 { 23 - asm("\ 24 - stmfd sp!, {r4, lr} @ 2\n\ 25 - mov r2, %0 @ 1\n\ 26 - 1: ldmia r1!, {r3, r4, ip, lr} @ 4\n\ 27 - stmia r0, {r3, r4, ip, lr} @ 4\n\ 28 - mcr p15, 0, r0, c7, c14, 1 @ 1 clean and invalidate D line\n\ 29 - add r0, r0, #16 @ 1\n\ 30 - ldmia r1!, {r3, r4, ip, lr} @ 4\n\ 31 - stmia r0, {r3, r4, ip, lr} @ 4\n\ 32 - mcr p15, 0, r0, c7, c14, 1 @ 1 clean and invalidate D line\n\ 33 - add r0, r0, #16 @ 1\n\ 34 - subs r2, r2, #1 @ 1\n\ 22 + int tmp; 23 + 24 + asm volatile ("\ 25 + 1: ldmia %1!, {r3, r4, ip, lr} @ 4\n\ 26 + stmia %0, {r3, r4, ip, lr} @ 4\n\ 27 + mcr p15, 0, %0, c7, c14, 1 @ 1 clean and invalidate D line\n\ 28 + add %0, %0, #16 @ 1\n\ 29 + ldmia %1!, {r3, r4, ip, lr} @ 4\n\ 30 + stmia %0, {r3, r4, ip, lr} @ 4\n\ 31 + mcr p15, 0, %0, c7, c14, 1 @ 1 clean and invalidate D line\n\ 32 + add %0, %0, #16 @ 1\n\ 33 + subs %2, %2, #1 @ 1\n\ 35 34 bne 1b @ 1\n\ 36 - mcr p15, 0, r2, c7, c10, 4 @ 1 drain WB\n\ 37 - ldmfd sp!, {r4, pc} @ 3" 38 - : 39 - : "I" (PAGE_SIZE / 32)); 35 + mcr p15, 0, %2, c7, c10, 4 @ 1 drain WB" 36 + : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp) 37 + : "2" (PAGE_SIZE / 32) 38 + : "r3", "r4", "ip", "lr"); 40 39 } 41 40 42 41 void fa_copy_user_highpage(struct page *to, struct page *from,
+48 -50
arch/arm/mm/copypage-feroceon.c
··· 13 13 #include <linux/init.h> 14 14 #include <linux/highmem.h> 15 15 16 - static void __naked 17 - feroceon_copy_user_page(void *kto, const void *kfrom) 16 + static void feroceon_copy_user_page(void *kto, const void *kfrom) 18 17 { 19 - asm("\ 20 - stmfd sp!, {r4-r9, lr} \n\ 21 - mov ip, %2 \n\ 22 - 1: mov lr, r1 \n\ 23 - ldmia r1!, {r2 - r9} \n\ 24 - pld [lr, #32] \n\ 25 - pld [lr, #64] \n\ 26 - pld [lr, #96] \n\ 27 - pld [lr, #128] \n\ 28 - pld [lr, #160] \n\ 29 - pld [lr, #192] \n\ 30 - pld [lr, #224] \n\ 31 - stmia r0, {r2 - r9} \n\ 32 - ldmia r1!, {r2 - r9} \n\ 33 - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ 34 - add r0, r0, #32 \n\ 35 - stmia r0, {r2 - r9} \n\ 36 - ldmia r1!, {r2 - r9} \n\ 37 - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ 38 - add r0, r0, #32 \n\ 39 - stmia r0, {r2 - r9} \n\ 40 - ldmia r1!, {r2 - r9} \n\ 41 - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ 42 - add r0, r0, #32 \n\ 43 - stmia r0, {r2 - r9} \n\ 44 - ldmia r1!, {r2 - r9} \n\ 45 - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ 46 - add r0, r0, #32 \n\ 47 - stmia r0, {r2 - r9} \n\ 48 - ldmia r1!, {r2 - r9} \n\ 49 - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ 50 - add r0, r0, #32 \n\ 51 - stmia r0, {r2 - r9} \n\ 52 - ldmia r1!, {r2 - r9} \n\ 53 - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ 54 - add r0, r0, #32 \n\ 55 - stmia r0, {r2 - r9} \n\ 56 - ldmia r1!, {r2 - r9} \n\ 57 - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ 58 - add r0, r0, #32 \n\ 59 - stmia r0, {r2 - r9} \n\ 60 - subs ip, ip, #(32 * 8) \n\ 61 - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ 62 - add r0, r0, #32 \n\ 18 + int tmp; 19 + 20 + asm volatile ("\ 21 + 1: ldmia %1!, {r2 - r7, ip, lr} \n\ 22 + pld [%1, #0] \n\ 23 + pld [%1, #32] \n\ 24 + pld [%1, #64] \n\ 25 + pld [%1, #96] \n\ 26 + pld [%1, #128] \n\ 27 + pld [%1, #160] \n\ 28 + pld [%1, #192] \n\ 29 + stmia %0, {r2 - r7, ip, lr} \n\ 30 + ldmia %1!, {r2 - r7, ip, lr} \n\ 31 + mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ 32 + add %0, %0, #32 \n\ 33 + stmia %0, {r2 - r7, ip, lr} \n\ 34 + ldmia %1!, {r2 - r7, ip, lr} \n\ 35 + mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ 36 + add %0, %0, #32 \n\ 37 + stmia %0, {r2 - r7, ip, lr} \n\ 38 + ldmia %1!, {r2 - r7, ip, lr} \n\ 39 + mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ 40 + add %0, %0, #32 \n\ 41 + stmia %0, {r2 - r7, ip, lr} \n\ 42 + ldmia %1!, {r2 - r7, ip, lr} \n\ 43 + mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ 44 + add %0, %0, #32 \n\ 45 + stmia %0, {r2 - r7, ip, lr} \n\ 46 + ldmia %1!, {r2 - r7, ip, lr} \n\ 47 + mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ 48 + add %0, %0, #32 \n\ 49 + stmia %0, {r2 - r7, ip, lr} \n\ 50 + ldmia %1!, {r2 - r7, ip, lr} \n\ 51 + mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ 52 + add %0, %0, #32 \n\ 53 + stmia %0, {r2 - r7, ip, lr} \n\ 54 + ldmia %1!, {r2 - r7, ip, lr} \n\ 55 + mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ 56 + add %0, %0, #32 \n\ 57 + stmia %0, {r2 - r7, ip, lr} \n\ 58 + subs %2, %2, #(32 * 8) \n\ 59 + mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ 60 + add %0, %0, #32 \n\ 63 61 bne 1b \n\ 64 - mcr p15, 0, ip, c7, c10, 4 @ drain WB\n\ 65 - ldmfd sp!, {r4-r9, pc}" 66 - : 67 - : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE)); 62 + mcr p15, 0, %2, c7, c10, 4 @ drain WB" 63 + : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp) 64 + : "2" (PAGE_SIZE) 65 + : "r2", "r3", "r4", "r5", "r6", "r7", "ip", "lr"); 68 66 } 69 67 70 68 void feroceon_copy_user_highpage(struct page *to, struct page *from,
+9 -10
arch/arm/mm/copypage-v4mc.c
··· 40 40 * instruction. If your processor does not supply this, you have to write your 41 41 * own copy_user_highpage that does the right thing. 42 42 */ 43 - static void __naked 44 - mc_copy_user_page(void *from, void *to) 43 + static void mc_copy_user_page(void *from, void *to) 45 44 { 46 - asm volatile( 47 - "stmfd sp!, {r4, lr} @ 2\n\ 48 - mov r4, %2 @ 1\n\ 45 + int tmp; 46 + 47 + asm volatile ("\ 49 48 ldmia %0!, {r2, r3, ip, lr} @ 4\n\ 50 49 1: mcr p15, 0, %1, c7, c6, 1 @ 1 invalidate D line\n\ 51 50 stmia %1!, {r2, r3, ip, lr} @ 4\n\ ··· 54 55 mcr p15, 0, %1, c7, c6, 1 @ 1 invalidate D line\n\ 55 56 stmia %1!, {r2, r3, ip, lr} @ 4\n\ 56 57 ldmia %0!, {r2, r3, ip, lr} @ 4\n\ 57 - subs r4, r4, #1 @ 1\n\ 58 + subs %2, %2, #1 @ 1\n\ 58 59 stmia %1!, {r2, r3, ip, lr} @ 4\n\ 59 60 ldmneia %0!, {r2, r3, ip, lr} @ 4\n\ 60 - bne 1b @ 1\n\ 61 - ldmfd sp!, {r4, pc} @ 3" 62 - : 63 - : "r" (from), "r" (to), "I" (PAGE_SIZE / 64)); 61 + bne 1b @ " 62 + : "+&r" (from), "+&r" (to), "=&r" (tmp) 63 + : "2" (PAGE_SIZE / 64) 64 + : "r2", "r3", "ip", "lr"); 64 65 } 65 66 66 67 void v4_mc_copy_user_highpage(struct page *to, struct page *from,
+20 -21
arch/arm/mm/copypage-v4wb.c
··· 22 22 * instruction. If your processor does not supply this, you have to write your 23 23 * own copy_user_highpage that does the right thing. 24 24 */ 25 - static void __naked 26 - v4wb_copy_user_page(void *kto, const void *kfrom) 25 + static void v4wb_copy_user_page(void *kto, const void *kfrom) 27 26 { 28 - asm("\ 29 - stmfd sp!, {r4, lr} @ 2\n\ 30 - mov r2, %2 @ 1\n\ 31 - ldmia r1!, {r3, r4, ip, lr} @ 4\n\ 32 - 1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\ 33 - stmia r0!, {r3, r4, ip, lr} @ 4\n\ 34 - ldmia r1!, {r3, r4, ip, lr} @ 4+1\n\ 35 - stmia r0!, {r3, r4, ip, lr} @ 4\n\ 36 - ldmia r1!, {r3, r4, ip, lr} @ 4\n\ 37 - mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\ 38 - stmia r0!, {r3, r4, ip, lr} @ 4\n\ 39 - ldmia r1!, {r3, r4, ip, lr} @ 4\n\ 40 - subs r2, r2, #1 @ 1\n\ 41 - stmia r0!, {r3, r4, ip, lr} @ 4\n\ 42 - ldmneia r1!, {r3, r4, ip, lr} @ 4\n\ 27 + int tmp; 28 + 29 + asm volatile ("\ 30 + ldmia %1!, {r3, r4, ip, lr} @ 4\n\ 31 + 1: mcr p15, 0, %0, c7, c6, 1 @ 1 invalidate D line\n\ 32 + stmia %0!, {r3, r4, ip, lr} @ 4\n\ 33 + ldmia %1!, {r3, r4, ip, lr} @ 4+1\n\ 34 + stmia %0!, {r3, r4, ip, lr} @ 4\n\ 35 + ldmia %1!, {r3, r4, ip, lr} @ 4\n\ 36 + mcr p15, 0, %0, c7, c6, 1 @ 1 invalidate D line\n\ 37 + stmia %0!, {r3, r4, ip, lr} @ 4\n\ 38 + ldmia %1!, {r3, r4, ip, lr} @ 4\n\ 39 + subs %2, %2, #1 @ 1\n\ 40 + stmia %0!, {r3, r4, ip, lr} @ 4\n\ 41 + ldmneia %1!, {r3, r4, ip, lr} @ 4\n\ 43 42 bne 1b @ 1\n\ 44 - mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB\n\ 45 - ldmfd sp!, {r4, pc} @ 3" 46 - : 47 - : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64)); 43 + mcr p15, 0, %1, c7, c10, 4 @ 1 drain WB" 44 + : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp) 45 + : "2" (PAGE_SIZE / 64) 46 + : "r3", "r4", "ip", "lr"); 48 47 } 49 48 50 49 void v4wb_copy_user_highpage(struct page *to, struct page *from,
+18 -19
arch/arm/mm/copypage-v4wt.c
··· 20 20 * dirty data in the cache. However, we do have to ensure that 21 21 * subsequent reads are up to date. 22 22 */ 23 - static void __naked 24 - v4wt_copy_user_page(void *kto, const void *kfrom) 23 + static void v4wt_copy_user_page(void *kto, const void *kfrom) 25 24 { 26 - asm("\ 27 - stmfd sp!, {r4, lr} @ 2\n\ 28 - mov r2, %2 @ 1\n\ 29 - ldmia r1!, {r3, r4, ip, lr} @ 4\n\ 30 - 1: stmia r0!, {r3, r4, ip, lr} @ 4\n\ 31 - ldmia r1!, {r3, r4, ip, lr} @ 4+1\n\ 32 - stmia r0!, {r3, r4, ip, lr} @ 4\n\ 33 - ldmia r1!, {r3, r4, ip, lr} @ 4\n\ 34 - stmia r0!, {r3, r4, ip, lr} @ 4\n\ 35 - ldmia r1!, {r3, r4, ip, lr} @ 4\n\ 36 - subs r2, r2, #1 @ 1\n\ 37 - stmia r0!, {r3, r4, ip, lr} @ 4\n\ 38 - ldmneia r1!, {r3, r4, ip, lr} @ 4\n\ 25 + int tmp; 26 + 27 + asm volatile ("\ 28 + ldmia %1!, {r3, r4, ip, lr} @ 4\n\ 29 + 1: stmia %0!, {r3, r4, ip, lr} @ 4\n\ 30 + ldmia %1!, {r3, r4, ip, lr} @ 4+1\n\ 31 + stmia %0!, {r3, r4, ip, lr} @ 4\n\ 32 + ldmia %1!, {r3, r4, ip, lr} @ 4\n\ 33 + stmia %0!, {r3, r4, ip, lr} @ 4\n\ 34 + ldmia %1!, {r3, r4, ip, lr} @ 4\n\ 35 + subs %2, %2, #1 @ 1\n\ 36 + stmia %0!, {r3, r4, ip, lr} @ 4\n\ 37 + ldmneia %1!, {r3, r4, ip, lr} @ 4\n\ 39 38 bne 1b @ 1\n\ 40 - mcr p15, 0, r2, c7, c7, 0 @ flush ID cache\n\ 41 - ldmfd sp!, {r4, pc} @ 3" 42 - : 43 - : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64)); 39 + mcr p15, 0, %2, c7, c7, 0 @ flush ID cache" 40 + : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp) 41 + : "2" (PAGE_SIZE / 64) 42 + : "r3", "r4", "ip", "lr"); 44 43 } 45 44 46 45 void v4wt_copy_user_highpage(struct page *to, struct page *from,
+35 -44
arch/arm/mm/copypage-xsc3.c
··· 21 21 22 22 /* 23 23 * XSC3 optimised copy_user_highpage 24 - * r0 = destination 25 - * r1 = source 26 24 * 27 25 * The source page may have some clean entries in the cache already, but we 28 26 * can safely ignore them - break_cow() will flush them out of the cache 29 27 * if we eventually end up using our copied page. 30 28 * 31 29 */ 32 - static void __naked 33 - xsc3_mc_copy_user_page(void *kto, const void *kfrom) 30 + static void xsc3_mc_copy_user_page(void *kto, const void *kfrom) 34 31 { 35 - asm("\ 36 - stmfd sp!, {r4, r5, lr} \n\ 37 - mov lr, %2 \n\ 32 + int tmp; 33 + 34 + asm volatile ("\ 35 + pld [%1, #0] \n\ 36 + pld [%1, #32] \n\ 37 + 1: pld [%1, #64] \n\ 38 + pld [%1, #96] \n\ 38 39 \n\ 39 - pld [r1, #0] \n\ 40 - pld [r1, #32] \n\ 41 - 1: pld [r1, #64] \n\ 42 - pld [r1, #96] \n\ 43 - \n\ 44 - 2: ldrd r2, [r1], #8 \n\ 45 - mov ip, r0 \n\ 46 - ldrd r4, [r1], #8 \n\ 47 - mcr p15, 0, ip, c7, c6, 1 @ invalidate\n\ 48 - strd r2, [r0], #8 \n\ 49 - ldrd r2, [r1], #8 \n\ 50 - strd r4, [r0], #8 \n\ 51 - ldrd r4, [r1], #8 \n\ 52 - strd r2, [r0], #8 \n\ 53 - strd r4, [r0], #8 \n\ 54 - ldrd r2, [r1], #8 \n\ 55 - mov ip, r0 \n\ 56 - ldrd r4, [r1], #8 \n\ 57 - mcr p15, 0, ip, c7, c6, 1 @ invalidate\n\ 58 - strd r2, [r0], #8 \n\ 59 - ldrd r2, [r1], #8 \n\ 60 - subs lr, lr, #1 \n\ 61 - strd r4, [r0], #8 \n\ 62 - ldrd r4, [r1], #8 \n\ 63 - strd r2, [r0], #8 \n\ 64 - strd r4, [r0], #8 \n\ 40 + 2: ldrd r2, r3, [%1], #8 \n\ 41 + ldrd r4, r5, [%1], #8 \n\ 42 + mcr p15, 0, %0, c7, c6, 1 @ invalidate\n\ 43 + strd r2, r3, [%0], #8 \n\ 44 + ldrd r2, r3, [%1], #8 \n\ 45 + strd r4, r5, [%0], #8 \n\ 46 + ldrd r4, r5, [%1], #8 \n\ 47 + strd r2, r3, [%0], #8 \n\ 48 + strd r4, r5, [%0], #8 \n\ 49 + ldrd r2, r3, [%1], #8 \n\ 50 + ldrd r4, r5, [%1], #8 \n\ 51 + mcr p15, 0, %0, c7, c6, 1 @ invalidate\n\ 52 + strd r2, r3, [%0], #8 \n\ 53 + ldrd r2, r3, [%1], #8 \n\ 54 + subs %2, %2, #1 \n\ 55 + strd r4, r5, [%0], #8 \n\ 56 + ldrd r4, r5, [%1], #8 \n\ 57 + strd r2, r3, [%0], #8 \n\ 58 + strd r4, r5, [%0], #8 \n\ 65 59 bgt 1b \n\ 66 - beq 2b \n\ 67 - \n\ 68 - ldmfd sp!, {r4, r5, pc}" 69 - : 70 - : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64 - 1)); 60 + beq 2b " 61 + : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp) 62 + : "2" (PAGE_SIZE / 64 - 1) 63 + : "r2", "r3", "r4", "r5"); 71 64 } 72 65 73 66 void xsc3_mc_copy_user_highpage(struct page *to, struct page *from, ··· 78 85 79 86 /* 80 87 * XScale optimised clear_user_page 81 - * r0 = destination 82 - * r1 = virtual user address of ultimate destination page 83 88 */ 84 89 void xsc3_mc_clear_user_highpage(struct page *page, unsigned long vaddr) 85 90 { ··· 87 96 mov r2, #0 \n\ 88 97 mov r3, #0 \n\ 89 98 1: mcr p15, 0, %0, c7, c6, 1 @ invalidate line\n\ 90 - strd r2, [%0], #8 \n\ 91 - strd r2, [%0], #8 \n\ 92 - strd r2, [%0], #8 \n\ 93 - strd r2, [%0], #8 \n\ 99 + strd r2, r3, [%0], #8 \n\ 100 + strd r2, r3, [%0], #8 \n\ 101 + strd r2, r3, [%0], #8 \n\ 102 + strd r2, r3, [%0], #8 \n\ 94 103 subs r1, r1, #1 \n\ 95 104 bne 1b" 96 105 : "=r" (ptr)
+39 -40
arch/arm/mm/copypage-xscale.c
··· 36 36 * Dcache aliasing issue. The writes will be forwarded to the write buffer, 37 37 * and merged as appropriate. 38 38 */ 39 - static void __naked 40 - mc_copy_user_page(void *from, void *to) 39 + static void mc_copy_user_page(void *from, void *to) 41 40 { 41 + int tmp; 42 + 42 43 /* 43 44 * Strangely enough, best performance is achieved 44 45 * when prefetching destination as well. (NP) 45 46 */ 46 - asm volatile( 47 - "stmfd sp!, {r4, r5, lr} \n\ 48 - mov lr, %2 \n\ 49 - pld [r0, #0] \n\ 50 - pld [r0, #32] \n\ 51 - pld [r1, #0] \n\ 52 - pld [r1, #32] \n\ 53 - 1: pld [r0, #64] \n\ 54 - pld [r0, #96] \n\ 55 - pld [r1, #64] \n\ 56 - pld [r1, #96] \n\ 57 - 2: ldrd r2, [r0], #8 \n\ 58 - ldrd r4, [r0], #8 \n\ 59 - mov ip, r1 \n\ 60 - strd r2, [r1], #8 \n\ 61 - ldrd r2, [r0], #8 \n\ 62 - strd r4, [r1], #8 \n\ 63 - ldrd r4, [r0], #8 \n\ 64 - strd r2, [r1], #8 \n\ 65 - strd r4, [r1], #8 \n\ 47 + asm volatile ("\ 48 + pld [%0, #0] \n\ 49 + pld [%0, #32] \n\ 50 + pld [%1, #0] \n\ 51 + pld [%1, #32] \n\ 52 + 1: pld [%0, #64] \n\ 53 + pld [%0, #96] \n\ 54 + pld [%1, #64] \n\ 55 + pld [%1, #96] \n\ 56 + 2: ldrd r2, r3, [%0], #8 \n\ 57 + ldrd r4, r5, [%0], #8 \n\ 58 + mov ip, %1 \n\ 59 + strd r2, r3, [%1], #8 \n\ 60 + ldrd r2, r3, [%0], #8 \n\ 61 + strd r4, r5, [%1], #8 \n\ 62 + ldrd r4, r5, [%0], #8 \n\ 63 + strd r2, r3, [%1], #8 \n\ 64 + strd r4, r5, [%1], #8 \n\ 66 65 mcr p15, 0, ip, c7, c10, 1 @ clean D line\n\ 67 - ldrd r2, [r0], #8 \n\ 66 + ldrd r2, r3, [%0], #8 \n\ 68 67 mcr p15, 0, ip, c7, c6, 1 @ invalidate D line\n\ 69 - ldrd r4, [r0], #8 \n\ 70 - mov ip, r1 \n\ 71 - strd r2, [r1], #8 \n\ 72 - ldrd r2, [r0], #8 \n\ 73 - strd r4, [r1], #8 \n\ 74 - ldrd r4, [r0], #8 \n\ 75 - strd r2, [r1], #8 \n\ 76 - strd r4, [r1], #8 \n\ 68 + ldrd r4, r5, [%0], #8 \n\ 69 + mov ip, %1 \n\ 70 + strd r2, r3, [%1], #8 \n\ 71 + ldrd r2, r3, [%0], #8 \n\ 72 + strd r4, r5, [%1], #8 \n\ 73 + ldrd r4, r5, [%0], #8 \n\ 74 + strd r2, r3, [%1], #8 \n\ 75 + strd r4, r5, [%1], #8 \n\ 77 76 mcr p15, 0, ip, c7, c10, 1 @ clean D line\n\ 78 - subs lr, lr, #1 \n\ 77 + subs %2, %2, #1 \n\ 79 78 mcr p15, 0, ip, c7, c6, 1 @ invalidate D line\n\ 80 79 bgt 1b \n\ 81 - beq 2b \n\ 82 - ldmfd sp!, {r4, r5, pc} " 83 - : 84 - : "r" (from), "r" (to), "I" (PAGE_SIZE / 64 - 1)); 80 + beq 2b " 81 + : "+&r" (from), "+&r" (to), "=&r" (tmp) 82 + : "2" (PAGE_SIZE / 64 - 1) 83 + : "r2", "r3", "r4", "r5", "ip"); 85 84 } 86 85 87 86 void xscale_mc_copy_user_highpage(struct page *to, struct page *from, ··· 114 115 mov r2, #0 \n\ 115 116 mov r3, #0 \n\ 116 117 1: mov ip, %0 \n\ 117 - strd r2, [%0], #8 \n\ 118 - strd r2, [%0], #8 \n\ 119 - strd r2, [%0], #8 \n\ 120 - strd r2, [%0], #8 \n\ 118 + strd r2, r3, [%0], #8 \n\ 119 + strd r2, r3, [%0], #8 \n\ 120 + strd r2, r3, [%0], #8 \n\ 121 + strd r2, r3, [%0], #8 \n\ 121 122 mcr p15, 0, ip, c7, c10, 1 @ clean D line\n\ 122 123 subs r1, r1, #1 \n\ 123 124 mcr p15, 0, ip, c7, c6, 1 @ invalidate D line\n\
+6
arch/arm/mm/fault.c
··· 173 173 show_regs(regs); 174 174 } 175 175 #endif 176 + #ifndef CONFIG_KUSER_HELPERS 177 + if ((sig == SIGSEGV) && ((addr & PAGE_MASK) == 0xffff0000)) 178 + printk_ratelimited(KERN_DEBUG 179 + "%s: CONFIG_KUSER_HELPERS disabled at 0x%08lx\n", 180 + tsk->comm, addr); 181 + #endif 176 182 177 183 tsk->thread.address = addr; 178 184 tsk->thread.error_code = fsr;
+2 -2
arch/arm/mm/proc-macros.S
··· 278 278 * If we are building for big.Little with branch predictor hardening, 279 279 * we need the processor function tables to remain available after boot. 280 280 */ 281 - #if 1 // defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR) 281 + #if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR) 282 282 .section ".rodata" 283 283 #endif 284 284 .type \name\()_processor_functions, #object ··· 316 316 .endif 317 317 318 318 .size \name\()_processor_functions, . - \name\()_processor_functions 319 - #if 1 // defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR) 319 + #if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR) 320 320 .previous 321 321 #endif 322 322 .endm
+8 -8
arch/arm/mm/pv-fixup-asm.S
··· 33 33 add r7, r2, #0x1000 34 34 add r6, r7, r6, lsr #SECTION_SHIFT - L2_ORDER 35 35 add r7, r7, #PAGE_OFFSET >> (SECTION_SHIFT - L2_ORDER) 36 - 1: ldrd r4, [r7] 36 + 1: ldrd r4, r5, [r7] 37 37 adds r4, r4, r0 38 38 adc r5, r5, r1 39 - strd r4, [r7], #1 << L2_ORDER 39 + strd r4, r5, [r7], #1 << L2_ORDER 40 40 cmp r7, r6 41 41 bls 1b 42 42 ··· 44 44 add r7, r2, #0x1000 45 45 add r7, r7, r3, lsr #SECTION_SHIFT - L2_ORDER 46 46 bic r7, r7, #(1 << L2_ORDER) - 1 47 - ldrd r4, [r7] 47 + ldrd r4, r5, [r7] 48 48 adds r4, r4, r0 49 49 adc r5, r5, r1 50 - strd r4, [r7], #1 << L2_ORDER 51 - ldrd r4, [r7] 50 + strd r4, r5, [r7], #1 << L2_ORDER 51 + ldrd r4, r5, [r7] 52 52 adds r4, r4, r0 53 53 adc r5, r5, r1 54 - strd r4, [r7] 54 + strd r4, r5, [r7] 55 55 56 56 /* Update level 1 entries */ 57 57 mov r6, #4 58 58 mov r7, r2 59 - 2: ldrd r4, [r7] 59 + 2: ldrd r4, r5, [r7] 60 60 adds r4, r4, r0 61 61 adc r5, r5, r1 62 - strd r4, [r7], #1 << L1_ORDER 62 + strd r4, r5, [r7], #1 << L1_ORDER 63 63 subs r6, r6, #1 64 64 bne 2b 65 65
-1
arch/arm/plat-omap/Kconfig
··· 92 92 config OMAP3_L2_AUX_SECURE_SAVE_RESTORE 93 93 bool "OMAP3 HS/EMU save and restore for L2 AUX control register" 94 94 depends on ARCH_OMAP3 && PM 95 - default n 96 95 help 97 96 Without this option, L2 Auxiliary control register contents are 98 97 lost during off-mode entry on HS/EMU devices. This feature
+1
arch/arm/plat-versatile/Makefile
··· 2 2 3 3 obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o 4 4 obj-$(CONFIG_SMP) += headsmp.o platsmp.o 5 + obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+1 -1
arch/arm/plat-versatile/headsmp.S
··· 37 37 38 38 .align 39 39 1: .long . 40 - .long pen_release 40 + .long versatile_cpu_release 41 41 ENDPROC(versatile_secondary_startup)
+2
arch/arm/plat-versatile/include/plat/platsmp.h
··· 8 8 * it under the terms of the GNU General Public License version 2 as 9 9 * published by the Free Software Foundation. 10 10 */ 11 + extern volatile int versatile_cpu_release; 11 12 12 13 extern void versatile_secondary_startup(void); 13 14 extern void versatile_secondary_init(unsigned int cpu); 14 15 extern int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle); 16 + void versatile_immitation_cpu_die(unsigned int cpu, unsigned int actrl_mask);
+33 -14
arch/arm/plat-versatile/platsmp.c
··· 7 7 * This program is free software; you can redistribute it and/or modify 8 8 * it under the terms of the GNU General Public License version 2 as 9 9 * published by the Free Software Foundation. 10 + * 11 + * This code is specific to the hardware found on ARM Realview and 12 + * Versatile Express platforms where the CPUs are unable to be individually 13 + * woken, and where there is no way to hot-unplug CPUs. Real platforms 14 + * should not copy this code. 10 15 */ 11 16 #include <linux/init.h> 12 17 #include <linux/errno.h> ··· 26 21 #include <plat/platsmp.h> 27 22 28 23 /* 29 - * Write pen_release in a way that is guaranteed to be visible to all 30 - * observers, irrespective of whether they're taking part in coherency 24 + * versatile_cpu_release controls the release of CPUs from the holding 25 + * pen in headsmp.S, which exists because we are not always able to 26 + * control the release of individual CPUs from the board firmware. 27 + * Production platforms do not need this. 28 + */ 29 + volatile int versatile_cpu_release = -1; 30 + 31 + /* 32 + * Write versatile_cpu_release in a way that is guaranteed to be visible to 33 + * all observers, irrespective of whether they're taking part in coherency 31 34 * or not. This is necessary for the hotplug code to work reliably. 32 35 */ 33 - static void write_pen_release(int val) 36 + static void versatile_write_cpu_release(int val) 34 37 { 35 - pen_release = val; 38 + versatile_cpu_release = val; 36 39 smp_wmb(); 37 - sync_cache_w(&pen_release); 40 + sync_cache_w(&versatile_cpu_release); 38 41 } 39 42 40 - static DEFINE_SPINLOCK(boot_lock); 43 + /* 44 + * versatile_lock exists to avoid running the loops_per_jiffy delay loop 45 + * calibrations on the secondary CPU while the requesting CPU is using 46 + * the limited-bandwidth bus - which affects the calibration value. 47 + * Production platforms do not need this. 48 + */ 49 + static DEFINE_RAW_SPINLOCK(versatile_lock); 41 50 42 51 void versatile_secondary_init(unsigned int cpu) 43 52 { ··· 59 40 * let the primary processor know we're out of the 60 41 * pen, then head off into the C entry point 61 42 */ 62 - write_pen_release(-1); 43 + versatile_write_cpu_release(-1); 63 44 64 45 /* 65 46 * Synchronise with the boot thread. 66 47 */ 67 - spin_lock(&boot_lock); 68 - spin_unlock(&boot_lock); 48 + raw_spin_lock(&versatile_lock); 49 + raw_spin_unlock(&versatile_lock); 69 50 } 70 51 71 52 int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle) ··· 76 57 * Set synchronisation state between this boot processor 77 58 * and the secondary one 78 59 */ 79 - spin_lock(&boot_lock); 60 + raw_spin_lock(&versatile_lock); 80 61 81 62 /* 82 63 * This is really belt and braces; we hold unintended secondary ··· 84 65 * since we haven't sent them a soft interrupt, they shouldn't 85 66 * be there. 86 67 */ 87 - write_pen_release(cpu_logical_map(cpu)); 68 + versatile_write_cpu_release(cpu_logical_map(cpu)); 88 69 89 70 /* 90 71 * Send the secondary CPU a soft interrupt, thereby causing ··· 96 77 timeout = jiffies + (1 * HZ); 97 78 while (time_before(jiffies, timeout)) { 98 79 smp_rmb(); 99 - if (pen_release == -1) 80 + if (versatile_cpu_release == -1) 100 81 break; 101 82 102 83 udelay(10); ··· 106 87 * now the secondary core is starting up let it run its 107 88 * calibrations, then wait for it to finish 108 89 */ 109 - spin_unlock(&boot_lock); 90 + raw_spin_unlock(&versatile_lock); 110 91 111 - return pen_release != -1 ? -ENOSYS : 0; 92 + return versatile_cpu_release != -1 ? -ENOSYS : 0; 112 93 }
+6
drivers/pcmcia/Kconfig
··· 64 64 65 65 If unsure, say Y. 66 66 67 + config PCMCIA_MAX1600 68 + tristate 69 + 67 70 comment "PC-card bridges" 68 71 69 72 config YENTA ··· 195 192 select PCMCIA_SOC_COMMON 196 193 select PCMCIA_SA11XX_BASE if ARCH_SA1100 197 194 select PCMCIA_PXA2XX if ARCH_LUBBOCK && SA1111 195 + select PCMCIA_MAX1600 if ASSABET_NEPONSET 196 + select PCMCIA_MAX1600 if ARCH_LUBBOCK && SA1111 198 197 help 199 198 Say Y here to include support for SA1111-based PCMCIA or CF 200 199 sockets, found on the Jornada 720, Graphicsmaster and other ··· 213 208 || MACH_VPAC270 || MACH_BALLOON3 || MACH_COLIBRI \ 214 209 || MACH_COLIBRI320 || MACH_H4700) 215 210 select PCMCIA_SOC_COMMON 211 + select PCMCIA_MAX1600 if MACH_MAINSTONE 216 212 help 217 213 Say Y here to include support for the PXA2xx PCMCIA controller 218 214
+1
drivers/pcmcia/Makefile
··· 35 35 obj-$(CONFIG_AT91_CF) += at91_cf.o 36 36 obj-$(CONFIG_ELECTRA_CF) += electra_cf.o 37 37 obj-$(CONFIG_PCMCIA_ALCHEMY_DEVBOARD) += db1xxx_ss.o 38 + obj-$(CONFIG_PCMCIA_MAX1600) += max1600.o 38 39 39 40 sa1111_cs-y += sa1111_generic.o 40 41 sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1111_neponset.o
+122
drivers/pcmcia/max1600.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * MAX1600 PCMCIA power switch library 4 + * 5 + * Copyright (C) 2016 Russell King 6 + */ 7 + #include <linux/device.h> 8 + #include <linux/module.h> 9 + #include <linux/gpio/consumer.h> 10 + #include <linux/slab.h> 11 + #include "max1600.h" 12 + 13 + static const char *max1600_gpio_name[2][MAX1600_GPIO_MAX] = { 14 + { "a0vcc", "a1vcc", "a0vpp", "a1vpp" }, 15 + { "b0vcc", "b1vcc", "b0vpp", "b1vpp" }, 16 + }; 17 + 18 + int max1600_init(struct device *dev, struct max1600 **ptr, 19 + unsigned int channel, unsigned int code) 20 + { 21 + struct max1600 *m; 22 + int chan; 23 + int i; 24 + 25 + switch (channel) { 26 + case MAX1600_CHAN_A: 27 + chan = 0; 28 + break; 29 + case MAX1600_CHAN_B: 30 + chan = 1; 31 + break; 32 + default: 33 + return -EINVAL; 34 + } 35 + 36 + if (code != MAX1600_CODE_LOW && code != MAX1600_CODE_HIGH) 37 + return -EINVAL; 38 + 39 + m = devm_kzalloc(dev, sizeof(*m), GFP_KERNEL); 40 + if (!m) 41 + return -ENOMEM; 42 + 43 + m->dev = dev; 44 + m->code = code; 45 + 46 + for (i = 0; i < MAX1600_GPIO_MAX; i++) { 47 + const char *name; 48 + 49 + name = max1600_gpio_name[chan][i]; 50 + if (i != MAX1600_GPIO_0VPP) { 51 + m->gpio[i] = devm_gpiod_get(dev, name, GPIOD_OUT_LOW); 52 + } else { 53 + m->gpio[i] = devm_gpiod_get_optional(dev, name, 54 + GPIOD_OUT_LOW); 55 + if (!m->gpio[i]) 56 + break; 57 + } 58 + if (IS_ERR(m->gpio[i])) 59 + return PTR_ERR(m->gpio[i]); 60 + } 61 + 62 + *ptr = m; 63 + 64 + return 0; 65 + } 66 + EXPORT_SYMBOL_GPL(max1600_init); 67 + 68 + int max1600_configure(struct max1600 *m, unsigned int vcc, unsigned int vpp) 69 + { 70 + DECLARE_BITMAP(values, MAX1600_GPIO_MAX) = { 0, }; 71 + int n = MAX1600_GPIO_0VPP; 72 + 73 + if (m->gpio[MAX1600_GPIO_0VPP]) { 74 + if (vpp == 0) { 75 + __assign_bit(MAX1600_GPIO_0VPP, values, 0); 76 + __assign_bit(MAX1600_GPIO_1VPP, values, 0); 77 + } else if (vpp == 120) { 78 + __assign_bit(MAX1600_GPIO_0VPP, values, 0); 79 + __assign_bit(MAX1600_GPIO_1VPP, values, 1); 80 + } else if (vpp == vcc) { 81 + __assign_bit(MAX1600_GPIO_0VPP, values, 1); 82 + __assign_bit(MAX1600_GPIO_1VPP, values, 0); 83 + } else { 84 + dev_err(m->dev, "unrecognised Vpp %u.%uV\n", 85 + vpp / 10, vpp % 10); 86 + return -EINVAL; 87 + } 88 + n = MAX1600_GPIO_MAX; 89 + } else if (vpp != vcc && vpp != 0) { 90 + dev_err(m->dev, "no VPP control\n"); 91 + return -EINVAL; 92 + } 93 + 94 + if (vcc == 0) { 95 + __assign_bit(MAX1600_GPIO_0VCC, values, 0); 96 + __assign_bit(MAX1600_GPIO_1VCC, values, 0); 97 + } else if (vcc == 33) { /* VY */ 98 + __assign_bit(MAX1600_GPIO_0VCC, values, 1); 99 + __assign_bit(MAX1600_GPIO_1VCC, values, 0); 100 + } else if (vcc == 50) { /* VX */ 101 + __assign_bit(MAX1600_GPIO_0VCC, values, 0); 102 + __assign_bit(MAX1600_GPIO_1VCC, values, 1); 103 + } else { 104 + dev_err(m->dev, "unrecognised Vcc %u.%uV\n", 105 + vcc / 10, vcc % 10); 106 + return -EINVAL; 107 + } 108 + 109 + if (m->code == MAX1600_CODE_HIGH) { 110 + /* 111 + * Cirrus mode appears to be the same as Intel mode, 112 + * except the VCC pins are inverted. 113 + */ 114 + __change_bit(MAX1600_GPIO_0VCC, values); 115 + __change_bit(MAX1600_GPIO_1VCC, values); 116 + } 117 + 118 + return gpiod_set_array_value_cansleep(n, m->gpio, NULL, values); 119 + } 120 + EXPORT_SYMBOL_GPL(max1600_configure); 121 + 122 + MODULE_LICENSE("GPL v2");
+32
drivers/pcmcia/max1600.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef MAX1600_H 3 + #define MAX1600_H 4 + 5 + struct gpio_desc; 6 + 7 + enum { 8 + MAX1600_GPIO_0VCC = 0, 9 + MAX1600_GPIO_1VCC, 10 + MAX1600_GPIO_0VPP, 11 + MAX1600_GPIO_1VPP, 12 + MAX1600_GPIO_MAX, 13 + 14 + MAX1600_CHAN_A, 15 + MAX1600_CHAN_B, 16 + 17 + MAX1600_CODE_LOW, 18 + MAX1600_CODE_HIGH, 19 + }; 20 + 21 + struct max1600 { 22 + struct gpio_desc *gpio[MAX1600_GPIO_MAX]; 23 + struct device *dev; 24 + unsigned int code; 25 + }; 26 + 27 + int max1600_init(struct device *dev, struct max1600 **ptr, 28 + unsigned int channel, unsigned int code); 29 + 30 + int max1600_configure(struct max1600 *, unsigned int vcc, unsigned int vpp); 31 + 32 + #endif
+34 -79
drivers/pcmcia/pxa2xx_mainstone.c
··· 11 11 * it under the terms of the GNU General Public License version 2 as 12 12 * published by the Free Software Foundation. 13 13 */ 14 - 14 + #include <linux/gpio/consumer.h> 15 15 #include <linux/module.h> 16 16 #include <linux/init.h> 17 + #include <linux/interrupt.h> 17 18 #include <linux/kernel.h> 18 19 #include <linux/errno.h> 19 - #include <linux/interrupt.h> 20 20 #include <linux/platform_device.h> 21 21 22 22 #include <pcmcia/ss.h> 23 23 24 24 #include <asm/mach-types.h> 25 - #include <asm/irq.h> 26 - 27 - #include <mach/pxa2xx-regs.h> 28 - #include <mach/mainstone.h> 29 25 30 26 #include "soc_common.h" 31 - 27 + #include "max1600.h" 32 28 33 29 static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 34 30 { 35 - /* 36 - * Setup default state of GPIO outputs 37 - * before we enable them as outputs. 38 - */ 39 - if (skt->nr == 0) { 40 - skt->socket.pci_irq = MAINSTONE_S0_IRQ; 41 - skt->stat[SOC_STAT_CD].irq = MAINSTONE_S0_CD_IRQ; 42 - skt->stat[SOC_STAT_CD].name = "PCMCIA0 CD"; 43 - skt->stat[SOC_STAT_BVD1].irq = MAINSTONE_S0_STSCHG_IRQ; 44 - skt->stat[SOC_STAT_BVD1].name = "PCMCIA0 STSCHG"; 45 - } else { 46 - skt->socket.pci_irq = MAINSTONE_S1_IRQ; 47 - skt->stat[SOC_STAT_CD].irq = MAINSTONE_S1_CD_IRQ; 48 - skt->stat[SOC_STAT_CD].name = "PCMCIA1 CD"; 49 - skt->stat[SOC_STAT_BVD1].irq = MAINSTONE_S1_STSCHG_IRQ; 50 - skt->stat[SOC_STAT_BVD1].name = "PCMCIA1 STSCHG"; 51 - } 52 - return 0; 31 + struct device *dev = skt->socket.dev.parent; 32 + struct max1600 *m; 33 + int ret; 34 + 35 + skt->stat[SOC_STAT_CD].name = skt->nr ? "bdetect" : "adetect"; 36 + skt->stat[SOC_STAT_BVD1].name = skt->nr ? "bbvd1" : "abvd1"; 37 + skt->stat[SOC_STAT_BVD2].name = skt->nr ? "bbvd2" : "abvd2"; 38 + skt->stat[SOC_STAT_RDY].name = skt->nr ? "bready" : "aready"; 39 + skt->stat[SOC_STAT_VS1].name = skt->nr ? "bvs1" : "avs1"; 40 + skt->stat[SOC_STAT_VS2].name = skt->nr ? "bvs2" : "avs2"; 41 + 42 + skt->gpio_reset = devm_gpiod_get(dev, skt->nr ? "breset" : "areset", 43 + GPIOD_OUT_HIGH); 44 + if (IS_ERR(skt->gpio_reset)) 45 + return PTR_ERR(skt->gpio_reset); 46 + 47 + ret = max1600_init(dev, &m, skt->nr ? MAX1600_CHAN_B : MAX1600_CHAN_A, 48 + MAX1600_CODE_HIGH); 49 + if (ret) 50 + return ret; 51 + 52 + skt->driver_data = m; 53 + 54 + return soc_pcmcia_request_gpiods(skt); 53 55 } 54 56 55 - static unsigned long mst_pcmcia_status[2]; 57 + static unsigned int mst_pcmcia_bvd1_status[2]; 56 58 57 59 static void mst_pcmcia_socket_state(struct soc_pcmcia_socket *skt, 58 60 struct pcmcia_state *state) 59 61 { 60 - unsigned long status, flip; 61 - 62 - status = (skt->nr == 0) ? MST_PCMCIA0 : MST_PCMCIA1; 63 - flip = (status ^ mst_pcmcia_status[skt->nr]) & MST_PCMCIA_nSTSCHG_BVD1; 62 + unsigned int flip = mst_pcmcia_bvd1_status[skt->nr] ^ state->bvd1; 64 63 65 64 /* 66 65 * Workaround for STSCHG which can't be deasserted: ··· 67 68 * as needed to avoid IRQ locks. 68 69 */ 69 70 if (flip) { 70 - mst_pcmcia_status[skt->nr] = status; 71 - if (status & MST_PCMCIA_nSTSCHG_BVD1) 72 - enable_irq( (skt->nr == 0) ? MAINSTONE_S0_STSCHG_IRQ 73 - : MAINSTONE_S1_STSCHG_IRQ ); 71 + mst_pcmcia_bvd1_status[skt->nr] = state->bvd1; 72 + if (state->bvd1) 73 + enable_irq(skt->stat[SOC_STAT_BVD1].irq); 74 74 else 75 - disable_irq( (skt->nr == 0) ? MAINSTONE_S0_STSCHG_IRQ 76 - : MAINSTONE_S1_STSCHG_IRQ ); 75 + disable_irq(skt->stat[SOC_STAT_BVD2].irq); 77 76 } 78 - 79 - state->detect = (status & MST_PCMCIA_nCD) ? 0 : 1; 80 - state->ready = (status & MST_PCMCIA_nIRQ) ? 1 : 0; 81 - state->bvd1 = (status & MST_PCMCIA_nSTSCHG_BVD1) ? 1 : 0; 82 - state->bvd2 = (status & MST_PCMCIA_nSPKR_BVD2) ? 1 : 0; 83 - state->vs_3v = (status & MST_PCMCIA_nVS1) ? 0 : 1; 84 - state->vs_Xv = (status & MST_PCMCIA_nVS2) ? 0 : 1; 85 77 } 86 78 87 79 static int mst_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, 88 80 const socket_state_t *state) 89 81 { 90 - unsigned long power = 0; 91 - int ret = 0; 92 - 93 - switch (state->Vcc) { 94 - case 0: power |= MST_PCMCIA_PWR_VCC_0; break; 95 - case 33: power |= MST_PCMCIA_PWR_VCC_33; break; 96 - case 50: power |= MST_PCMCIA_PWR_VCC_50; break; 97 - default: 98 - printk(KERN_ERR "%s(): bad Vcc %u\n", 99 - __func__, state->Vcc); 100 - ret = -1; 101 - } 102 - 103 - switch (state->Vpp) { 104 - case 0: power |= MST_PCMCIA_PWR_VPP_0; break; 105 - case 120: power |= MST_PCMCIA_PWR_VPP_120; break; 106 - default: 107 - if(state->Vpp == state->Vcc) { 108 - power |= MST_PCMCIA_PWR_VPP_VCC; 109 - } else { 110 - printk(KERN_ERR "%s(): bad Vpp %u\n", 111 - __func__, state->Vpp); 112 - ret = -1; 113 - } 114 - } 115 - 116 - if (state->flags & SS_RESET) 117 - power |= MST_PCMCIA_RESET; 118 - 119 - switch (skt->nr) { 120 - case 0: MST_PCMCIA0 = power; break; 121 - case 1: MST_PCMCIA1 = power; break; 122 - default: ret = -1; 123 - } 124 - 125 - return ret; 82 + return max1600_configure(skt->driver_data, state->Vcc, state->Vpp); 126 83 } 127 84 128 85 static struct pcmcia_low_level mst_pcmcia_ops __initdata = {
+2 -2
drivers/pcmcia/sa1100_simpad.c
··· 39 39 { 40 40 long cs3reg = simpad_get_cs3_ro(); 41 41 42 - state->bvd1 = 1; /* Might be cs3reg & PCMCIA_BVD1 */ 43 - state->bvd2 = 1; /* Might be cs3reg & PCMCIA_BVD2 */ 42 + /* bvd1 might be cs3reg & PCMCIA_BVD1 */ 43 + /* bvd2 might be cs3reg & PCMCIA_BVD2 */ 44 44 45 45 if ((cs3reg & (PCMCIA_VS1|PCMCIA_VS2)) == 46 46 (PCMCIA_VS1|PCMCIA_VS2)) {
+55 -28
drivers/pcmcia/sa1111_jornada720.c
··· 6 6 * 7 7 */ 8 8 #include <linux/module.h> 9 - #include <linux/kernel.h> 10 9 #include <linux/device.h> 11 10 #include <linux/errno.h> 11 + #include <linux/gpio/consumer.h> 12 12 #include <linux/init.h> 13 13 #include <linux/io.h> 14 14 15 15 #include <mach/hardware.h> 16 - #include <asm/hardware/sa1111.h> 17 16 #include <asm/mach-types.h> 18 17 19 18 #include "sa1111_generic.h" 20 19 21 - /* Does SOCKET1_3V actually do anything? */ 22 - #define SOCKET0_POWER GPIO_GPIO0 23 - #define SOCKET0_3V GPIO_GPIO2 24 - #define SOCKET1_POWER (GPIO_GPIO1 | GPIO_GPIO3) 25 - #define SOCKET1_3V GPIO_GPIO3 20 + /* 21 + * Socket 0 power: GPIO A0 22 + * Socket 0 3V: GPIO A2 23 + * Socket 1 power: GPIO A1 & GPIO A3 24 + * Socket 1 3V: GPIO A3 25 + * Does Socket 1 3V actually do anything? 26 + */ 27 + enum { 28 + J720_GPIO_PWR, 29 + J720_GPIO_3V, 30 + J720_GPIO_MAX, 31 + }; 32 + struct jornada720_data { 33 + struct gpio_desc *gpio[J720_GPIO_MAX]; 34 + }; 35 + 36 + static int jornada720_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 37 + { 38 + struct device *dev = skt->socket.dev.parent; 39 + struct jornada720_data *j; 40 + 41 + j = devm_kzalloc(dev, sizeof(*j), GFP_KERNEL); 42 + if (!j) 43 + return -ENOMEM; 44 + 45 + j->gpio[J720_GPIO_PWR] = devm_gpiod_get(dev, skt->nr ? "s1-power" : 46 + "s0-power", GPIOD_OUT_LOW); 47 + if (IS_ERR(j->gpio[J720_GPIO_PWR])) 48 + return PTR_ERR(j->gpio[J720_GPIO_PWR]); 49 + 50 + j->gpio[J720_GPIO_3V] = devm_gpiod_get(dev, skt->nr ? "s1-3v" : 51 + "s0-3v", GPIOD_OUT_LOW); 52 + if (IS_ERR(j->gpio[J720_GPIO_3V])) 53 + return PTR_ERR(j->gpio[J720_GPIO_3V]); 54 + 55 + skt->driver_data = j; 56 + 57 + return 0; 58 + } 26 59 27 60 static int 28 61 jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) 29 62 { 30 - struct sa1111_pcmcia_socket *s = to_skt(skt); 31 - unsigned int pa_dwr_mask, pa_dwr_set; 63 + struct jornada720_data *j = skt->driver_data; 64 + DECLARE_BITMAP(values, J720_GPIO_MAX) = { 0, }; 32 65 int ret; 33 66 34 67 printk(KERN_INFO "%s(): config socket %d vcc %d vpp %d\n", __func__, ··· 69 36 70 37 switch (skt->nr) { 71 38 case 0: 72 - pa_dwr_mask = SOCKET0_POWER | SOCKET0_3V; 73 - 74 39 switch (state->Vcc) { 75 40 default: 76 41 case 0: 77 - pa_dwr_set = 0; 42 + __assign_bit(J720_GPIO_PWR, values, 0); 43 + __assign_bit(J720_GPIO_3V, values, 0); 78 44 break; 79 45 case 33: 80 - pa_dwr_set = SOCKET0_POWER | SOCKET0_3V; 46 + __assign_bit(J720_GPIO_PWR, values, 1); 47 + __assign_bit(J720_GPIO_3V, values, 1); 81 48 break; 82 49 case 50: 83 - pa_dwr_set = SOCKET0_POWER; 50 + __assign_bit(J720_GPIO_PWR, values, 1); 51 + __assign_bit(J720_GPIO_3V, values, 0); 84 52 break; 85 53 } 86 54 break; 87 55 88 56 case 1: 89 - pa_dwr_mask = SOCKET1_POWER; 90 - 91 57 switch (state->Vcc) { 92 58 default: 93 59 case 0: 94 - pa_dwr_set = 0; 60 + __assign_bit(J720_GPIO_PWR, values, 0); 61 + __assign_bit(J720_GPIO_3V, values, 0); 95 62 break; 96 63 case 33: 97 - pa_dwr_set = SOCKET1_POWER; 98 - break; 99 64 case 50: 100 - pa_dwr_set = SOCKET1_POWER; 65 + __assign_bit(J720_GPIO_PWR, values, 1); 66 + __assign_bit(J720_GPIO_3V, values, 1); 101 67 break; 102 68 } 103 69 break; ··· 113 81 114 82 ret = sa1111_pcmcia_configure_socket(skt, state); 115 83 if (ret == 0) 116 - sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set); 84 + ret = gpiod_set_array_value_cansleep(J720_GPIO_MAX, j->gpio, 85 + NULL, values); 117 86 118 87 return ret; 119 88 } 120 89 121 90 static struct pcmcia_low_level jornada720_pcmcia_ops = { 122 91 .owner = THIS_MODULE, 92 + .hw_init = jornada720_pcmcia_hw_init, 123 93 .configure_socket = jornada720_pcmcia_configure_socket, 124 94 .first = 0, 125 95 .nr = 2, ··· 129 95 130 96 int pcmcia_jornada720_init(struct sa1111_dev *sadev) 131 97 { 132 - unsigned int pin = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3; 133 - 134 98 /* Fixme: why messing around with SA11x0's GPIO1? */ 135 99 GRER |= 0x00000002; 136 - 137 - /* Set GPIO_A<3:1> to be outputs for PCMCIA/CF power controller: */ 138 - sa1111_set_io_dir(sadev, pin, 0, 0); 139 - sa1111_set_io(sadev, pin, 0); 140 - sa1111_set_sleep_io(sadev, pin, 0); 141 100 142 101 sa11xx_drv_pcmcia_ops(&jornada720_pcmcia_ops); 143 102 return sa1111_pcmcia_add(sadev, &jornada720_pcmcia_ops,
+20 -90
drivers/pcmcia/sa1111_lubbock.c
··· 24 24 #include <mach/hardware.h> 25 25 #include <asm/hardware/sa1111.h> 26 26 #include <asm/mach-types.h> 27 - #include <mach/lubbock.h> 28 27 29 28 #include "sa1111_generic.h" 29 + #include "max1600.h" 30 + 31 + static int lubbock_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 32 + { 33 + struct max1600 *m; 34 + int ret; 35 + 36 + ret = max1600_init(skt->socket.dev.parent, &m, 37 + skt->nr ? MAX1600_CHAN_B : MAX1600_CHAN_A, 38 + MAX1600_CODE_HIGH); 39 + if (ret == 0) 40 + skt->driver_data = m; 41 + 42 + return ret; 43 + } 30 44 31 45 static int 32 46 lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, 33 47 const socket_state_t *state) 34 48 { 35 - struct sa1111_pcmcia_socket *s = to_skt(skt); 36 - unsigned int pa_dwr_mask, pa_dwr_set, misc_mask, misc_set; 49 + struct max1600 *m = skt->driver_data; 37 50 int ret = 0; 38 - 39 - pa_dwr_mask = pa_dwr_set = misc_mask = misc_set = 0; 40 51 41 52 /* Lubbock uses the Maxim MAX1602, with the following connections: 42 53 * ··· 82 71 again: 83 72 switch (skt->nr) { 84 73 case 0: 85 - pa_dwr_mask = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3; 86 - 87 - switch (state->Vcc) { 88 - case 0: /* Hi-Z */ 89 - break; 90 - 91 - case 33: /* VY */ 92 - pa_dwr_set |= GPIO_A3; 93 - break; 94 - 95 - case 50: /* VX */ 96 - pa_dwr_set |= GPIO_A2; 97 - break; 98 - 99 - default: 100 - printk(KERN_ERR "%s(): unrecognized Vcc %u\n", 101 - __func__, state->Vcc); 102 - ret = -1; 103 - } 104 - 105 - switch (state->Vpp) { 106 - case 0: /* Hi-Z */ 107 - break; 108 - 109 - case 120: /* 12IN */ 110 - pa_dwr_set |= GPIO_A1; 111 - break; 112 - 113 - default: /* VCC */ 114 - if (state->Vpp == state->Vcc) 115 - pa_dwr_set |= GPIO_A0; 116 - else { 117 - printk(KERN_ERR "%s(): unrecognized Vpp %u\n", 118 - __func__, state->Vpp); 119 - ret = -1; 120 - break; 121 - } 122 - } 123 - break; 124 - 125 74 case 1: 126 - misc_mask = (1 << 15) | (1 << 14); 127 - 128 - switch (state->Vcc) { 129 - case 0: /* Hi-Z */ 130 - break; 131 - 132 - case 33: /* VY */ 133 - misc_set |= 1 << 15; 134 - break; 135 - 136 - case 50: /* VX */ 137 - misc_set |= 1 << 14; 138 - break; 139 - 140 - default: 141 - printk(KERN_ERR "%s(): unrecognized Vcc %u\n", 142 - __func__, state->Vcc); 143 - ret = -1; 144 - break; 145 - } 146 - 147 - if (state->Vpp != state->Vcc && state->Vpp != 0) { 148 - printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", 149 - __func__, state->Vpp); 150 - ret = -1; 151 - break; 152 - } 153 75 break; 154 76 155 77 default: ··· 91 147 92 148 if (ret == 0) 93 149 ret = sa1111_pcmcia_configure_socket(skt, state); 94 - 95 - if (ret == 0) { 96 - lubbock_set_misc_wr(misc_mask, misc_set); 97 - sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set); 98 - } 150 + if (ret == 0) 151 + ret = max1600_configure(m, state->Vcc, state->Vpp); 99 152 100 153 #if 1 101 154 if (ret == 0 && state->Vcc == 33) { ··· 116 175 /* 117 176 * Switch to 5V, Configure socket with 5V voltage 118 177 */ 119 - lubbock_set_misc_wr(misc_mask, 0); 120 - sa1111_set_io(s->dev, pa_dwr_mask, 0); 178 + max1600_configure(m, 0, 0); 121 179 122 180 /* 123 181 * It takes about 100ms to turn off Vcc. ··· 141 201 142 202 static struct pcmcia_low_level lubbock_pcmcia_ops = { 143 203 .owner = THIS_MODULE, 204 + .hw_init = lubbock_pcmcia_hw_init, 144 205 .configure_socket = lubbock_pcmcia_configure_socket, 145 206 .first = 0, 146 207 .nr = 2, ··· 151 210 152 211 int pcmcia_lubbock_init(struct sa1111_dev *sadev) 153 212 { 154 - /* 155 - * Set GPIO_A<3:0> to be outputs for the MAX1600, 156 - * and switch to standby mode. 157 - */ 158 - sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0); 159 - sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); 160 - sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); 161 - 162 - /* Set CF Socket 1 power to standby mode. */ 163 - lubbock_set_misc_wr((1 << 15) | (1 << 14), 0); 164 - 165 213 pxa2xx_drv_pcmcia_ops(&lubbock_pcmcia_ops); 166 214 pxa2xx_configure_sockets(&sadev->dev, &lubbock_pcmcia_ops); 167 215 return sa1111_pcmcia_add(sadev, &lubbock_pcmcia_ops,
+18 -61
drivers/pcmcia/sa1111_neponset.c
··· 10 10 #include <linux/errno.h> 11 11 #include <linux/init.h> 12 12 13 - #include <mach/hardware.h> 14 13 #include <asm/mach-types.h> 15 - #include <mach/neponset.h> 16 - #include <asm/hardware/sa1111.h> 17 14 18 15 #include "sa1111_generic.h" 16 + #include "max1600.h" 19 17 20 18 /* 21 19 * Neponset uses the Maxim MAX1600, with the following connections: ··· 38 40 * "Standard Intel code" mode. Refer to the Maxim data sheet for 39 41 * the corresponding truth table. 40 42 */ 43 + static int neponset_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 44 + { 45 + struct max1600 *m; 46 + int ret; 47 + 48 + ret = max1600_init(skt->socket.dev.parent, &m, 49 + skt->nr ? MAX1600_CHAN_B : MAX1600_CHAN_A, 50 + MAX1600_CODE_LOW); 51 + if (ret == 0) 52 + skt->driver_data = m; 53 + 54 + return ret; 55 + } 41 56 42 57 static int 43 58 neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) 44 59 { 45 - struct sa1111_pcmcia_socket *s = to_skt(skt); 46 - unsigned int ncr_mask, ncr_set, pa_dwr_mask, pa_dwr_set; 60 + struct max1600 *m = skt->driver_data; 47 61 int ret; 48 62 49 - switch (skt->nr) { 50 - case 0: 51 - pa_dwr_mask = GPIO_A0 | GPIO_A1; 52 - ncr_mask = NCR_A0VPP | NCR_A1VPP; 53 - 54 - if (state->Vpp == 0) 55 - ncr_set = 0; 56 - else if (state->Vpp == 120) 57 - ncr_set = NCR_A1VPP; 58 - else if (state->Vpp == state->Vcc) 59 - ncr_set = NCR_A0VPP; 60 - else { 61 - printk(KERN_ERR "%s(): unrecognized VPP %u\n", 62 - __func__, state->Vpp); 63 - return -1; 64 - } 65 - break; 66 - 67 - case 1: 68 - pa_dwr_mask = GPIO_A2 | GPIO_A3; 69 - ncr_mask = 0; 70 - ncr_set = 0; 71 - 72 - if (state->Vpp != state->Vcc && state->Vpp != 0) { 73 - printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n", 74 - __func__, state->Vpp); 75 - return -1; 76 - } 77 - break; 78 - 79 - default: 80 - return -1; 81 - } 82 - 83 - /* 84 - * pa_dwr_set is the mask for selecting Vcc on both sockets. 85 - * pa_dwr_mask selects which bits (and therefore socket) we change. 86 - */ 87 - switch (state->Vcc) { 88 - default: 89 - case 0: pa_dwr_set = 0; break; 90 - case 33: pa_dwr_set = GPIO_A1|GPIO_A2; break; 91 - case 50: pa_dwr_set = GPIO_A0|GPIO_A3; break; 92 - } 93 - 94 63 ret = sa1111_pcmcia_configure_socket(skt, state); 95 - if (ret == 0) { 96 - neponset_ncr_frob(ncr_mask, ncr_set); 97 - sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set); 98 - } 64 + if (ret == 0) 65 + ret = max1600_configure(m, state->Vcc, state->Vpp); 99 66 100 67 return ret; 101 68 } 102 69 103 70 static struct pcmcia_low_level neponset_pcmcia_ops = { 104 71 .owner = THIS_MODULE, 72 + .hw_init = neponset_pcmcia_hw_init, 105 73 .configure_socket = neponset_pcmcia_configure_socket, 106 74 .first = 0, 107 75 .nr = 2, ··· 75 111 76 112 int pcmcia_neponset_init(struct sa1111_dev *sadev) 77 113 { 78 - /* 79 - * Set GPIO_A<3:0> to be outputs for the MAX1600, 80 - * and switch to standby mode. 81 - */ 82 - sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0); 83 - sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); 84 - sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); 85 114 sa11xx_drv_pcmcia_ops(&neponset_pcmcia_ops); 86 115 return sa1111_pcmcia_add(sadev, &neponset_pcmcia_ops, 87 116 sa11xx_drv_pcmcia_add_one);