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

ARM: sa1100/neponset: switch PCMCIA to MAX1600 library and gpiod APIs

Convert Neponset to use the gpiod API to specify which GPIOs are used
for PCMCIA, and use the MAX1600 power switch library for Neponset,
simplifying the neponset pcmcia driver as a result.

Acked-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

+38 -61
+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
drivers/pcmcia/Kconfig
··· 194 194 select PCMCIA_SOC_COMMON 195 195 select PCMCIA_SA11XX_BASE if ARCH_SA1100 196 196 select PCMCIA_PXA2XX if ARCH_LUBBOCK && SA1111 197 + select PCMCIA_MAX1600 if ASSABET_NEPONSET 197 198 help 198 199 Say Y here to include support for SA1111-based PCMCIA or CF 199 200 sockets, found on the Jornada 720, Graphicsmaster and other
+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);