summaryrefslogtreecommitdiff
path: root/drivers/pcmcia
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r--drivers/pcmcia/Kconfig6
-rw-r--r--drivers/pcmcia/Makefile1
-rw-r--r--drivers/pcmcia/max1600.c122
-rw-r--r--drivers/pcmcia/max1600.h32
-rw-r--r--drivers/pcmcia/pxa2xx_mainstone.c113
-rw-r--r--drivers/pcmcia/sa1100_simpad.c4
-rw-r--r--drivers/pcmcia/sa1111_jornada720.c83
-rw-r--r--drivers/pcmcia/sa1111_lubbock.c110
-rw-r--r--drivers/pcmcia/sa1111_neponset.c79
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);