diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pcmcia/Kconfig | 6 | ||||
-rw-r--r-- | drivers/pcmcia/Makefile | 1 | ||||
-rw-r--r-- | drivers/pcmcia/max1600.c | 122 | ||||
-rw-r--r-- | drivers/pcmcia/max1600.h | 32 | ||||
-rw-r--r-- | drivers/pcmcia/pxa2xx_mainstone.c | 113 | ||||
-rw-r--r-- | drivers/pcmcia/sa1100_simpad.c | 4 | ||||
-rw-r--r-- | drivers/pcmcia/sa1111_jornada720.c | 83 | ||||
-rw-r--r-- | drivers/pcmcia/sa1111_lubbock.c | 110 | ||||
-rw-r--r-- | drivers/pcmcia/sa1111_neponset.c | 79 |
9 files changed, 290 insertions, 260 deletions
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index c9bdbb463a7e..fab92ba8e566 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -64,6 +64,9 @@ config CARDBUS If unsure, say Y. +config PCMCIA_MAX1600 + tristate + comment "PC-card bridges" config YENTA @@ -192,6 +195,8 @@ config PCMCIA_SA1111 select PCMCIA_SOC_COMMON select PCMCIA_SA11XX_BASE if ARCH_SA1100 select PCMCIA_PXA2XX if ARCH_LUBBOCK && SA1111 + select PCMCIA_MAX1600 if ASSABET_NEPONSET + select PCMCIA_MAX1600 if ARCH_LUBBOCK && SA1111 help Say Y here to include support for SA1111-based PCMCIA or CF sockets, found on the Jornada 720, Graphicsmaster and other @@ -208,6 +213,7 @@ config PCMCIA_PXA2XX || MACH_VPAC270 || MACH_BALLOON3 || MACH_COLIBRI \ || MACH_COLIBRI320 || MACH_H4700) select PCMCIA_SOC_COMMON + select PCMCIA_MAX1600 if MACH_MAINSTONE help Say Y here to include support for the PXA2xx PCMCIA controller diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 28502bd159e0..01779c5c45f3 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_OMAP_CF) += omap_cf.o obj-$(CONFIG_AT91_CF) += at91_cf.o obj-$(CONFIG_ELECTRA_CF) += electra_cf.o obj-$(CONFIG_PCMCIA_ALCHEMY_DEVBOARD) += db1xxx_ss.o +obj-$(CONFIG_PCMCIA_MAX1600) += max1600.o sa1111_cs-y += sa1111_generic.o sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1111_neponset.o diff --git a/drivers/pcmcia/max1600.c b/drivers/pcmcia/max1600.c new file mode 100644 index 000000000000..379875a5e7cd --- /dev/null +++ b/drivers/pcmcia/max1600.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MAX1600 PCMCIA power switch library + * + * Copyright (C) 2016 Russell King + */ +#include <linux/device.h> +#include <linux/module.h> +#include <linux/gpio/consumer.h> +#include <linux/slab.h> +#include "max1600.h" + +static const char *max1600_gpio_name[2][MAX1600_GPIO_MAX] = { + { "a0vcc", "a1vcc", "a0vpp", "a1vpp" }, + { "b0vcc", "b1vcc", "b0vpp", "b1vpp" }, +}; + +int max1600_init(struct device *dev, struct max1600 **ptr, + unsigned int channel, unsigned int code) +{ + struct max1600 *m; + int chan; + int i; + + switch (channel) { + case MAX1600_CHAN_A: + chan = 0; + break; + case MAX1600_CHAN_B: + chan = 1; + break; + default: + return -EINVAL; + } + + if (code != MAX1600_CODE_LOW && code != MAX1600_CODE_HIGH) + return -EINVAL; + + m = devm_kzalloc(dev, sizeof(*m), GFP_KERNEL); + if (!m) + return -ENOMEM; + + m->dev = dev; + m->code = code; + + for (i = 0; i < MAX1600_GPIO_MAX; i++) { + const char *name; + + name = max1600_gpio_name[chan][i]; + if (i != MAX1600_GPIO_0VPP) { + m->gpio[i] = devm_gpiod_get(dev, name, GPIOD_OUT_LOW); + } else { + m->gpio[i] = devm_gpiod_get_optional(dev, name, + GPIOD_OUT_LOW); + if (!m->gpio[i]) + break; + } + if (IS_ERR(m->gpio[i])) + return PTR_ERR(m->gpio[i]); + } + + *ptr = m; + + return 0; +} +EXPORT_SYMBOL_GPL(max1600_init); + +int max1600_configure(struct max1600 *m, unsigned int vcc, unsigned int vpp) +{ + DECLARE_BITMAP(values, MAX1600_GPIO_MAX) = { 0, }; + int n = MAX1600_GPIO_0VPP; + + if (m->gpio[MAX1600_GPIO_0VPP]) { + if (vpp == 0) { + __assign_bit(MAX1600_GPIO_0VPP, values, 0); + __assign_bit(MAX1600_GPIO_1VPP, values, 0); + } else if (vpp == 120) { + __assign_bit(MAX1600_GPIO_0VPP, values, 0); + __assign_bit(MAX1600_GPIO_1VPP, values, 1); + } else if (vpp == vcc) { + __assign_bit(MAX1600_GPIO_0VPP, values, 1); + __assign_bit(MAX1600_GPIO_1VPP, values, 0); + } else { + dev_err(m->dev, "unrecognised Vpp %u.%uV\n", + vpp / 10, vpp % 10); + return -EINVAL; + } + n = MAX1600_GPIO_MAX; + } else if (vpp != vcc && vpp != 0) { + dev_err(m->dev, "no VPP control\n"); + return -EINVAL; + } + + if (vcc == 0) { + __assign_bit(MAX1600_GPIO_0VCC, values, 0); + __assign_bit(MAX1600_GPIO_1VCC, values, 0); + } else if (vcc == 33) { /* VY */ + __assign_bit(MAX1600_GPIO_0VCC, values, 1); + __assign_bit(MAX1600_GPIO_1VCC, values, 0); + } else if (vcc == 50) { /* VX */ + __assign_bit(MAX1600_GPIO_0VCC, values, 0); + __assign_bit(MAX1600_GPIO_1VCC, values, 1); + } else { + dev_err(m->dev, "unrecognised Vcc %u.%uV\n", + vcc / 10, vcc % 10); + return -EINVAL; + } + + if (m->code == MAX1600_CODE_HIGH) { + /* + * Cirrus mode appears to be the same as Intel mode, + * except the VCC pins are inverted. + */ + __change_bit(MAX1600_GPIO_0VCC, values); + __change_bit(MAX1600_GPIO_1VCC, values); + } + + return gpiod_set_array_value_cansleep(n, m->gpio, NULL, values); +} +EXPORT_SYMBOL_GPL(max1600_configure); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pcmcia/max1600.h b/drivers/pcmcia/max1600.h new file mode 100644 index 000000000000..00bf1a09464f --- /dev/null +++ b/drivers/pcmcia/max1600.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef MAX1600_H +#define MAX1600_H + +struct gpio_desc; + +enum { + MAX1600_GPIO_0VCC = 0, + MAX1600_GPIO_1VCC, + MAX1600_GPIO_0VPP, + MAX1600_GPIO_1VPP, + MAX1600_GPIO_MAX, + + MAX1600_CHAN_A, + MAX1600_CHAN_B, + + MAX1600_CODE_LOW, + MAX1600_CODE_HIGH, +}; + +struct max1600 { + struct gpio_desc *gpio[MAX1600_GPIO_MAX]; + struct device *dev; + unsigned int code; +}; + +int max1600_init(struct device *dev, struct max1600 **ptr, + unsigned int channel, unsigned int code); + +int max1600_configure(struct max1600 *, unsigned int vcc, unsigned int vpp); + +#endif diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c index 7e32e25cdcb2..770c7bf0171d 100644 --- a/drivers/pcmcia/pxa2xx_mainstone.c +++ b/drivers/pcmcia/pxa2xx_mainstone.c @@ -11,56 +11,55 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ - +#include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/interrupt.h> #include <linux/platform_device.h> #include <pcmcia/ss.h> #include <asm/mach-types.h> -#include <asm/irq.h> - -#include <mach/pxa2xx-regs.h> -#include <mach/mainstone.h> #include "soc_common.h" - +#include "max1600.h" static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { - /* - * Setup default state of GPIO outputs - * before we enable them as outputs. - */ - if (skt->nr == 0) { - skt->socket.pci_irq = MAINSTONE_S0_IRQ; - skt->stat[SOC_STAT_CD].irq = MAINSTONE_S0_CD_IRQ; - skt->stat[SOC_STAT_CD].name = "PCMCIA0 CD"; - skt->stat[SOC_STAT_BVD1].irq = MAINSTONE_S0_STSCHG_IRQ; - skt->stat[SOC_STAT_BVD1].name = "PCMCIA0 STSCHG"; - } else { - skt->socket.pci_irq = MAINSTONE_S1_IRQ; - skt->stat[SOC_STAT_CD].irq = MAINSTONE_S1_CD_IRQ; - skt->stat[SOC_STAT_CD].name = "PCMCIA1 CD"; - skt->stat[SOC_STAT_BVD1].irq = MAINSTONE_S1_STSCHG_IRQ; - skt->stat[SOC_STAT_BVD1].name = "PCMCIA1 STSCHG"; - } - return 0; + struct device *dev = skt->socket.dev.parent; + struct max1600 *m; + int ret; + + skt->stat[SOC_STAT_CD].name = skt->nr ? "bdetect" : "adetect"; + skt->stat[SOC_STAT_BVD1].name = skt->nr ? "bbvd1" : "abvd1"; + skt->stat[SOC_STAT_BVD2].name = skt->nr ? "bbvd2" : "abvd2"; + skt->stat[SOC_STAT_RDY].name = skt->nr ? "bready" : "aready"; + skt->stat[SOC_STAT_VS1].name = skt->nr ? "bvs1" : "avs1"; + skt->stat[SOC_STAT_VS2].name = skt->nr ? "bvs2" : "avs2"; + + skt->gpio_reset = devm_gpiod_get(dev, skt->nr ? "breset" : "areset", + GPIOD_OUT_HIGH); + if (IS_ERR(skt->gpio_reset)) + return PTR_ERR(skt->gpio_reset); + + ret = max1600_init(dev, &m, skt->nr ? MAX1600_CHAN_B : MAX1600_CHAN_A, + MAX1600_CODE_HIGH); + if (ret) + return ret; + + skt->driver_data = m; + + return soc_pcmcia_request_gpiods(skt); } -static unsigned long mst_pcmcia_status[2]; +static unsigned int mst_pcmcia_bvd1_status[2]; static void mst_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { - unsigned long status, flip; - - status = (skt->nr == 0) ? MST_PCMCIA0 : MST_PCMCIA1; - flip = (status ^ mst_pcmcia_status[skt->nr]) & MST_PCMCIA_nSTSCHG_BVD1; + unsigned int flip = mst_pcmcia_bvd1_status[skt->nr] ^ state->bvd1; /* * Workaround for STSCHG which can't be deasserted: @@ -68,62 +67,18 @@ static void mst_pcmcia_socket_state(struct soc_pcmcia_socket *skt, * as needed to avoid IRQ locks. */ if (flip) { - mst_pcmcia_status[skt->nr] = status; - if (status & MST_PCMCIA_nSTSCHG_BVD1) - enable_irq( (skt->nr == 0) ? MAINSTONE_S0_STSCHG_IRQ - : MAINSTONE_S1_STSCHG_IRQ ); + mst_pcmcia_bvd1_status[skt->nr] = state->bvd1; + if (state->bvd1) + enable_irq(skt->stat[SOC_STAT_BVD1].irq); else - disable_irq( (skt->nr == 0) ? MAINSTONE_S0_STSCHG_IRQ - : MAINSTONE_S1_STSCHG_IRQ ); + disable_irq(skt->stat[SOC_STAT_BVD2].irq); } - - state->detect = (status & MST_PCMCIA_nCD) ? 0 : 1; - state->ready = (status & MST_PCMCIA_nIRQ) ? 1 : 0; - state->bvd1 = (status & MST_PCMCIA_nSTSCHG_BVD1) ? 1 : 0; - state->bvd2 = (status & MST_PCMCIA_nSPKR_BVD2) ? 1 : 0; - state->vs_3v = (status & MST_PCMCIA_nVS1) ? 0 : 1; - state->vs_Xv = (status & MST_PCMCIA_nVS2) ? 0 : 1; } static int mst_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) { - unsigned long power = 0; - int ret = 0; - - switch (state->Vcc) { - case 0: power |= MST_PCMCIA_PWR_VCC_0; break; - case 33: power |= MST_PCMCIA_PWR_VCC_33; break; - case 50: power |= MST_PCMCIA_PWR_VCC_50; break; - default: - printk(KERN_ERR "%s(): bad Vcc %u\n", - __func__, state->Vcc); - ret = -1; - } - - switch (state->Vpp) { - case 0: power |= MST_PCMCIA_PWR_VPP_0; break; - case 120: power |= MST_PCMCIA_PWR_VPP_120; break; - default: - if(state->Vpp == state->Vcc) { - power |= MST_PCMCIA_PWR_VPP_VCC; - } else { - printk(KERN_ERR "%s(): bad Vpp %u\n", - __func__, state->Vpp); - ret = -1; - } - } - - if (state->flags & SS_RESET) - power |= MST_PCMCIA_RESET; - - switch (skt->nr) { - case 0: MST_PCMCIA0 = power; break; - case 1: MST_PCMCIA1 = power; break; - default: ret = -1; - } - - return ret; + return max1600_configure(skt->driver_data, state->Vcc, state->Vpp); } static struct pcmcia_low_level mst_pcmcia_ops __initdata = { diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c index e235ee14eaa6..e2e8729afd9d 100644 --- a/drivers/pcmcia/sa1100_simpad.c +++ b/drivers/pcmcia/sa1100_simpad.c @@ -39,8 +39,8 @@ simpad_pcmcia_socket_state(struct soc_pcmcia_socket *skt, { long cs3reg = simpad_get_cs3_ro(); - state->bvd1 = 1; /* Might be cs3reg & PCMCIA_BVD1 */ - state->bvd2 = 1; /* Might be cs3reg & PCMCIA_BVD2 */ + /* bvd1 might be cs3reg & PCMCIA_BVD1 */ + /* bvd2 might be cs3reg & PCMCIA_BVD2 */ if ((cs3reg & (PCMCIA_VS1|PCMCIA_VS2)) == (PCMCIA_VS1|PCMCIA_VS2)) { diff --git a/drivers/pcmcia/sa1111_jornada720.c b/drivers/pcmcia/sa1111_jornada720.c index 3d4ca87ca76c..1083e1b4f25d 100644 --- a/drivers/pcmcia/sa1111_jornada720.c +++ b/drivers/pcmcia/sa1111_jornada720.c @@ -6,29 +6,62 @@ * */ #include <linux/module.h> -#include <linux/kernel.h> #include <linux/device.h> #include <linux/errno.h> +#include <linux/gpio/consumer.h> #include <linux/init.h> #include <linux/io.h> #include <mach/hardware.h> -#include <asm/hardware/sa1111.h> #include <asm/mach-types.h> #include "sa1111_generic.h" -/* Does SOCKET1_3V actually do anything? */ -#define SOCKET0_POWER GPIO_GPIO0 -#define SOCKET0_3V GPIO_GPIO2 -#define SOCKET1_POWER (GPIO_GPIO1 | GPIO_GPIO3) -#define SOCKET1_3V GPIO_GPIO3 +/* + * Socket 0 power: GPIO A0 + * Socket 0 3V: GPIO A2 + * Socket 1 power: GPIO A1 & GPIO A3 + * Socket 1 3V: GPIO A3 + * Does Socket 1 3V actually do anything? + */ +enum { + J720_GPIO_PWR, + J720_GPIO_3V, + J720_GPIO_MAX, +}; +struct jornada720_data { + struct gpio_desc *gpio[J720_GPIO_MAX]; +}; + +static int jornada720_pcmcia_hw_init(struct soc_pcmcia_socket *skt) +{ + struct device *dev = skt->socket.dev.parent; + struct jornada720_data *j; + + j = devm_kzalloc(dev, sizeof(*j), GFP_KERNEL); + if (!j) + return -ENOMEM; + + j->gpio[J720_GPIO_PWR] = devm_gpiod_get(dev, skt->nr ? "s1-power" : + "s0-power", GPIOD_OUT_LOW); + if (IS_ERR(j->gpio[J720_GPIO_PWR])) + return PTR_ERR(j->gpio[J720_GPIO_PWR]); + + j->gpio[J720_GPIO_3V] = devm_gpiod_get(dev, skt->nr ? "s1-3v" : + "s0-3v", GPIOD_OUT_LOW); + if (IS_ERR(j->gpio[J720_GPIO_3V])) + return PTR_ERR(j->gpio[J720_GPIO_3V]); + + skt->driver_data = j; + + return 0; +} static int jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) { - struct sa1111_pcmcia_socket *s = to_skt(skt); - unsigned int pa_dwr_mask, pa_dwr_set; + struct jornada720_data *j = skt->driver_data; + DECLARE_BITMAP(values, J720_GPIO_MAX) = { 0, }; int ret; printk(KERN_INFO "%s(): config socket %d vcc %d vpp %d\n", __func__, @@ -36,35 +69,34 @@ jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_s switch (skt->nr) { case 0: - pa_dwr_mask = SOCKET0_POWER | SOCKET0_3V; - switch (state->Vcc) { default: case 0: - pa_dwr_set = 0; + __assign_bit(J720_GPIO_PWR, values, 0); + __assign_bit(J720_GPIO_3V, values, 0); break; case 33: - pa_dwr_set = SOCKET0_POWER | SOCKET0_3V; + __assign_bit(J720_GPIO_PWR, values, 1); + __assign_bit(J720_GPIO_3V, values, 1); break; case 50: - pa_dwr_set = SOCKET0_POWER; + __assign_bit(J720_GPIO_PWR, values, 1); + __assign_bit(J720_GPIO_3V, values, 0); break; } break; case 1: - pa_dwr_mask = SOCKET1_POWER; - switch (state->Vcc) { default: case 0: - pa_dwr_set = 0; + __assign_bit(J720_GPIO_PWR, values, 0); + __assign_bit(J720_GPIO_3V, values, 0); break; case 33: - pa_dwr_set = SOCKET1_POWER; - break; case 50: - pa_dwr_set = SOCKET1_POWER; + __assign_bit(J720_GPIO_PWR, values, 1); + __assign_bit(J720_GPIO_3V, values, 1); break; } break; @@ -81,13 +113,15 @@ jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_s ret = sa1111_pcmcia_configure_socket(skt, state); if (ret == 0) - sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set); + ret = gpiod_set_array_value_cansleep(J720_GPIO_MAX, j->gpio, + NULL, values); return ret; } static struct pcmcia_low_level jornada720_pcmcia_ops = { .owner = THIS_MODULE, + .hw_init = jornada720_pcmcia_hw_init, .configure_socket = jornada720_pcmcia_configure_socket, .first = 0, .nr = 2, @@ -95,16 +129,9 @@ static struct pcmcia_low_level jornada720_pcmcia_ops = { int pcmcia_jornada720_init(struct sa1111_dev *sadev) { - unsigned int pin = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3; - /* Fixme: why messing around with SA11x0's GPIO1? */ GRER |= 0x00000002; - /* Set GPIO_A<3:1> to be outputs for PCMCIA/CF power controller: */ - sa1111_set_io_dir(sadev, pin, 0, 0); - sa1111_set_io(sadev, pin, 0); - sa1111_set_sleep_io(sadev, pin, 0); - sa11xx_drv_pcmcia_ops(&jornada720_pcmcia_ops); return sa1111_pcmcia_add(sadev, &jornada720_pcmcia_ops, sa11xx_drv_pcmcia_add_one); diff --git a/drivers/pcmcia/sa1111_lubbock.c b/drivers/pcmcia/sa1111_lubbock.c index e741f499c875..e3fc14cfb42b 100644 --- a/drivers/pcmcia/sa1111_lubbock.c +++ b/drivers/pcmcia/sa1111_lubbock.c @@ -24,20 +24,31 @@ #include <mach/hardware.h> #include <asm/hardware/sa1111.h> #include <asm/mach-types.h> -#include <mach/lubbock.h> #include "sa1111_generic.h" +#include "max1600.h" + +static int lubbock_pcmcia_hw_init(struct soc_pcmcia_socket *skt) +{ + struct max1600 *m; + int ret; + + ret = max1600_init(skt->socket.dev.parent, &m, + skt->nr ? MAX1600_CHAN_B : MAX1600_CHAN_A, + MAX1600_CODE_HIGH); + if (ret == 0) + skt->driver_data = m; + + return ret; +} static int lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) { - struct sa1111_pcmcia_socket *s = to_skt(skt); - unsigned int pa_dwr_mask, pa_dwr_set, misc_mask, misc_set; + struct max1600 *m = skt->driver_data; int ret = 0; - pa_dwr_mask = pa_dwr_set = misc_mask = misc_set = 0; - /* Lubbock uses the Maxim MAX1602, with the following connections: * * Socket 0 (PCMCIA): @@ -71,74 +82,7 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, again: switch (skt->nr) { case 0: - pa_dwr_mask = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3; - - switch (state->Vcc) { - case 0: /* Hi-Z */ - break; - - case 33: /* VY */ - pa_dwr_set |= GPIO_A3; - break; - - case 50: /* VX */ - pa_dwr_set |= GPIO_A2; - break; - - default: - printk(KERN_ERR "%s(): unrecognized Vcc %u\n", - __func__, state->Vcc); - ret = -1; - } - - switch (state->Vpp) { - case 0: /* Hi-Z */ - break; - - case 120: /* 12IN */ - pa_dwr_set |= GPIO_A1; - break; - - default: /* VCC */ - if (state->Vpp == state->Vcc) - pa_dwr_set |= GPIO_A0; - else { - printk(KERN_ERR "%s(): unrecognized Vpp %u\n", - __func__, state->Vpp); - ret = -1; - break; - } - } - break; - case 1: - misc_mask = (1 << 15) | (1 << 14); - - switch (state->Vcc) { - case 0: /* Hi-Z */ - break; - - case 33: /* VY */ - misc_set |= 1 << 15; - break; - - case 50: /* VX */ - misc_set |= 1 << 14; - break; - - default: - printk(KERN_ERR "%s(): unrecognized Vcc %u\n", - __func__, state->Vcc); - ret = -1; - break; - } - - if (state->Vpp != state->Vcc && state->Vpp != 0) { - printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", - __func__, state->Vpp); - ret = -1; - break; - } break; default: @@ -147,11 +91,8 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, if (ret == 0) ret = sa1111_pcmcia_configure_socket(skt, state); - - if (ret == 0) { - lubbock_set_misc_wr(misc_mask, misc_set); - sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set); - } + if (ret == 0) + ret = max1600_configure(m, state->Vcc, state->Vpp); #if 1 if (ret == 0 && state->Vcc == 33) { @@ -175,8 +116,7 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, /* * Switch to 5V, Configure socket with 5V voltage */ - lubbock_set_misc_wr(misc_mask, 0); - sa1111_set_io(s->dev, pa_dwr_mask, 0); + max1600_configure(m, 0, 0); /* * It takes about 100ms to turn off Vcc. @@ -201,6 +141,7 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, static struct pcmcia_low_level lubbock_pcmcia_ops = { .owner = THIS_MODULE, + .hw_init = lubbock_pcmcia_hw_init, .configure_socket = lubbock_pcmcia_configure_socket, .first = 0, .nr = 2, @@ -210,17 +151,6 @@ static struct pcmcia_low_level lubbock_pcmcia_ops = { int pcmcia_lubbock_init(struct sa1111_dev *sadev) { - /* - * Set GPIO_A<3:0> to be outputs for the MAX1600, - * and switch to standby mode. - */ - sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0); - sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); - sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); - - /* Set CF Socket 1 power to standby mode. */ - lubbock_set_misc_wr((1 << 15) | (1 << 14), 0); - pxa2xx_drv_pcmcia_ops(&lubbock_pcmcia_ops); pxa2xx_configure_sockets(&sadev->dev, &lubbock_pcmcia_ops); return sa1111_pcmcia_add(sadev, &lubbock_pcmcia_ops, diff --git a/drivers/pcmcia/sa1111_neponset.c b/drivers/pcmcia/sa1111_neponset.c index 0ccf05a28a4b..de0ce13355b4 100644 --- a/drivers/pcmcia/sa1111_neponset.c +++ b/drivers/pcmcia/sa1111_neponset.c @@ -10,12 +10,10 @@ #include <linux/errno.h> #include <linux/init.h> -#include <mach/hardware.h> #include <asm/mach-types.h> -#include <mach/neponset.h> -#include <asm/hardware/sa1111.h> #include "sa1111_generic.h" +#include "max1600.h" /* * Neponset uses the Maxim MAX1600, with the following connections: @@ -40,70 +38,36 @@ * "Standard Intel code" mode. Refer to the Maxim data sheet for * the corresponding truth table. */ - -static int -neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) +static int neponset_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { - struct sa1111_pcmcia_socket *s = to_skt(skt); - unsigned int ncr_mask, ncr_set, pa_dwr_mask, pa_dwr_set; + struct max1600 *m; int ret; - switch (skt->nr) { - case 0: - pa_dwr_mask = GPIO_A0 | GPIO_A1; - ncr_mask = NCR_A0VPP | NCR_A1VPP; - - if (state->Vpp == 0) - ncr_set = 0; - else if (state->Vpp == 120) - ncr_set = NCR_A1VPP; - else if (state->Vpp == state->Vcc) - ncr_set = NCR_A0VPP; - else { - printk(KERN_ERR "%s(): unrecognized VPP %u\n", - __func__, state->Vpp); - return -1; - } - break; - - case 1: - pa_dwr_mask = GPIO_A2 | GPIO_A3; - ncr_mask = 0; - ncr_set = 0; - - if (state->Vpp != state->Vcc && state->Vpp != 0) { - printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n", - __func__, state->Vpp); - return -1; - } - break; + ret = max1600_init(skt->socket.dev.parent, &m, + skt->nr ? MAX1600_CHAN_B : MAX1600_CHAN_A, + MAX1600_CODE_LOW); + if (ret == 0) + skt->driver_data = m; - default: - return -1; - } + return ret; +} - /* - * pa_dwr_set is the mask for selecting Vcc on both sockets. - * pa_dwr_mask selects which bits (and therefore socket) we change. - */ - switch (state->Vcc) { - default: - case 0: pa_dwr_set = 0; break; - case 33: pa_dwr_set = GPIO_A1|GPIO_A2; break; - case 50: pa_dwr_set = GPIO_A0|GPIO_A3; break; - } +static int +neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) +{ + struct max1600 *m = skt->driver_data; + int ret; ret = sa1111_pcmcia_configure_socket(skt, state); - if (ret == 0) { - neponset_ncr_frob(ncr_mask, ncr_set); - sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set); - } + if (ret == 0) + ret = max1600_configure(m, state->Vcc, state->Vpp); return ret; } static struct pcmcia_low_level neponset_pcmcia_ops = { .owner = THIS_MODULE, + .hw_init = neponset_pcmcia_hw_init, .configure_socket = neponset_pcmcia_configure_socket, .first = 0, .nr = 2, @@ -111,13 +75,6 @@ static struct pcmcia_low_level neponset_pcmcia_ops = { int pcmcia_neponset_init(struct sa1111_dev *sadev) { - /* - * Set GPIO_A<3:0> to be outputs for the MAX1600, - * and switch to standby mode. - */ - sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0); - sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); - sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); sa11xx_drv_pcmcia_ops(&neponset_pcmcia_ops); return sa1111_pcmcia_add(sadev, &neponset_pcmcia_ops, sa11xx_drv_pcmcia_add_one); |