diff options
author | Marek Vasut <marek.vasut@gmail.com> | 2010-07-27 15:48:10 -0400 |
---|---|---|
committer | Eric Miao <eric.y.miao@gmail.com> | 2010-08-05 02:32:45 -0400 |
commit | a9c0629cdefd9c26746ece510fcc88357869685e (patch) | |
tree | 196d0c32e643ee1ce89907ba5d90be94dfcd5e81 | |
parent | 12a2449c79686964a36b17175970a8e1c19b4cf7 (diff) |
[ARM] pxa/balloon3: PCMCIA Support
This driver adds support for the on-board CF socket.
Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
-rw-r--r-- | arch/arm/mach-pxa/balloon3.c | 13 | ||||
-rw-r--r-- | arch/arm/mach-pxa/include/mach/balloon3.h | 36 | ||||
-rw-r--r-- | drivers/pcmcia/Kconfig | 2 | ||||
-rw-r--r-- | drivers/pcmcia/Makefile | 1 | ||||
-rw-r--r-- | drivers/pcmcia/pxa2xx_balloon3.c | 158 |
5 files changed, 191 insertions, 19 deletions
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c index 572525c26cac..91ad56d6e929 100644 --- a/arch/arm/mach-pxa/balloon3.c +++ b/arch/arm/mach-pxa/balloon3.c | |||
@@ -88,6 +88,18 @@ static unsigned long balloon3_pin_config[] __initdata = { | |||
88 | /* USB Host */ | 88 | /* USB Host */ |
89 | GPIO88_USBH1_PWR, | 89 | GPIO88_USBH1_PWR, |
90 | GPIO89_USBH1_PEN, | 90 | GPIO89_USBH1_PEN, |
91 | |||
92 | /* PC Card */ | ||
93 | GPIO48_nPOE, | ||
94 | GPIO49_nPWE, | ||
95 | GPIO50_nPIOR, | ||
96 | GPIO51_nPIOW, | ||
97 | GPIO85_nPCE_1, | ||
98 | GPIO54_nPCE_2, | ||
99 | GPIO79_PSKTSEL, | ||
100 | GPIO55_nPREG, | ||
101 | GPIO56_nPWAIT, | ||
102 | GPIO57_nIOIS16, | ||
91 | }; | 103 | }; |
92 | 104 | ||
93 | /****************************************************************************** | 105 | /****************************************************************************** |
@@ -405,7 +417,6 @@ static void balloon3_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
405 | { | 417 | { |
406 | unsigned long pending = __raw_readl(BALLOON3_INT_CONTROL_REG) & | 418 | unsigned long pending = __raw_readl(BALLOON3_INT_CONTROL_REG) & |
407 | balloon3_irq_enabled; | 419 | balloon3_irq_enabled; |
408 | |||
409 | do { | 420 | do { |
410 | /* clear useless edge notification */ | 421 | /* clear useless edge notification */ |
411 | if (desc->chip->ack) | 422 | if (desc->chip->ack) |
diff --git a/arch/arm/mach-pxa/include/mach/balloon3.h b/arch/arm/mach-pxa/include/mach/balloon3.h index 1a741065045f..d5dcf750c1ef 100644 --- a/arch/arm/mach-pxa/include/mach/balloon3.h +++ b/arch/arm/mach-pxa/include/mach/balloon3.h | |||
@@ -26,10 +26,12 @@ enum balloon3_features { | |||
26 | #define BALLOON3_FPGA_VIRT (0xf1000000) /* as per balloon2 */ | 26 | #define BALLOON3_FPGA_VIRT (0xf1000000) /* as per balloon2 */ |
27 | #define BALLOON3_FPGA_LENGTH 0x01000000 | 27 | #define BALLOON3_FPGA_LENGTH 0x01000000 |
28 | 28 | ||
29 | /* FPGA/CPLD registers */ | 29 | /* FPGA / CPLD registers for CF socket */ |
30 | #define BALLOON3_PCMCIA0_REG (BALLOON3_FPGA_VIRT + 0x00e00008) | 30 | #define BALLOON3_CF_STATUS_REG (BALLOON3_FPGA_VIRT + 0x00e00008) |
31 | /* fixme - same for now */ | 31 | #define BALLOON3_CF_CONTROL_REG (BALLOON3_FPGA_VIRT + 0x00e00008) |
32 | #define BALLOON3_PCMCIA1_REG (BALLOON3_FPGA_VIRT + 0x00e00008) | 32 | /* FPGA / CPLD version register */ |
33 | #define BALLOON3_FPGA_VER (BALLOON3_FPGA_VIRT + 0x00e0001c) | ||
34 | |||
33 | #define BALLOON3_NANDIO_IO_REG (BALLOON3_FPGA_VIRT + 0x00e00000) | 35 | #define BALLOON3_NANDIO_IO_REG (BALLOON3_FPGA_VIRT + 0x00e00000) |
34 | /* fpga/cpld interrupt control register */ | 36 | /* fpga/cpld interrupt control register */ |
35 | #define BALLOON3_INT_CONTROL_REG (BALLOON3_FPGA_VIRT + 0x00e0000C) | 37 | #define BALLOON3_INT_CONTROL_REG (BALLOON3_FPGA_VIRT + 0x00e0000C) |
@@ -41,6 +43,19 @@ enum balloon3_features { | |||
41 | #define BALLOON3_SAMOSA_DATA_REG (BALLOON3_FPGA_VIRT + 0x00c00004) | 43 | #define BALLOON3_SAMOSA_DATA_REG (BALLOON3_FPGA_VIRT + 0x00c00004) |
42 | #define BALLOON3_SAMOSA_STATUS_REG (BALLOON3_FPGA_VIRT + 0x00c0001c) | 44 | #define BALLOON3_SAMOSA_STATUS_REG (BALLOON3_FPGA_VIRT + 0x00c0001c) |
43 | 45 | ||
46 | /* CF Status Register bits (read-only) bits */ | ||
47 | #define BALLOON3_CF_nIRQ (1 << 0) | ||
48 | #define BALLOON3_CF_nSTSCHG_BVD1 (1 << 1) | ||
49 | |||
50 | /* CF Control Set Register bits / CF Control Clear Register bits (write-only) */ | ||
51 | #define BALLOON3_CF_RESET (1 << 0) | ||
52 | #define BALLOON3_CF_ENABLE (1 << 1) | ||
53 | #define BALLOON3_CF_ADD_ENABLE (1 << 2) | ||
54 | |||
55 | /* CF Interrupt sources */ | ||
56 | #define BALLOON3_BP_CF_NRDY_IRQ BALLOON3_IRQ(0) | ||
57 | #define BALLOON3_BP_NSTSCHG_IRQ BALLOON3_IRQ(1) | ||
58 | |||
44 | /* GPIOs for irqs */ | 59 | /* GPIOs for irqs */ |
45 | #define BALLOON3_GPIO_AUX_NIRQ (94) | 60 | #define BALLOON3_GPIO_AUX_NIRQ (94) |
46 | #define BALLOON3_GPIO_CODEC_IRQ (95) | 61 | #define BALLOON3_GPIO_CODEC_IRQ (95) |
@@ -58,16 +73,6 @@ enum balloon3_features { | |||
58 | #define BALLOON3_INT_S0_IRQ (1 << 0) /* PCMCIA 0 IRQ */ | 73 | #define BALLOON3_INT_S0_IRQ (1 << 0) /* PCMCIA 0 IRQ */ |
59 | #define BALLOON3_INT_S0_STSCHG (1 << 1) /* PCMCIA 0 status changed */ | 74 | #define BALLOON3_INT_S0_STSCHG (1 << 1) /* PCMCIA 0 status changed */ |
60 | 75 | ||
61 | /* CF Status Register */ | ||
62 | #define BALLOON3_PCMCIA_nIRQ (1 << 0) /* IRQ / ready signal */ | ||
63 | #define BALLOON3_PCMCIA_nSTSCHG_BVD1 (1 << 1) | ||
64 | /* VDD sense / card status changed */ | ||
65 | |||
66 | /* CF control register (write) */ | ||
67 | #define BALLOON3_PCMCIA_RESET (1 << 0) /* Card reset signal */ | ||
68 | #define BALLOON3_PCMCIA_ENABLE (1 << 1) | ||
69 | #define BALLOON3_PCMCIA_ADD_ENABLE (1 << 2) | ||
70 | |||
71 | /* CPLD (and FPGA) interface definitions */ | 76 | /* CPLD (and FPGA) interface definitions */ |
72 | #define CPLD_LCD0_DATA_SET 0x00 | 77 | #define CPLD_LCD0_DATA_SET 0x00 |
73 | #define CPLD_LCD0_DATA_CLR 0x10 | 78 | #define CPLD_LCD0_DATA_CLR 0x10 |
@@ -132,9 +137,6 @@ enum balloon3_features { | |||
132 | /* Balloon3 Interrupts */ | 137 | /* Balloon3 Interrupts */ |
133 | #define BALLOON3_IRQ(x) (IRQ_BOARD_START + (x)) | 138 | #define BALLOON3_IRQ(x) (IRQ_BOARD_START + (x)) |
134 | 139 | ||
135 | #define BALLOON3_BP_CF_NRDY_IRQ BALLOON3_IRQ(0) | ||
136 | #define BALLOON3_BP_NSTSCHG_IRQ BALLOON3_IRQ(1) | ||
137 | |||
138 | #define BALLOON3_AUX_NIRQ IRQ_GPIO(BALLOON3_GPIO_AUX_NIRQ) | 140 | #define BALLOON3_AUX_NIRQ IRQ_GPIO(BALLOON3_GPIO_AUX_NIRQ) |
139 | #define BALLOON3_CODEC_IRQ IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ) | 141 | #define BALLOON3_CODEC_IRQ IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ) |
140 | #define BALLOON3_S0_CD_IRQ IRQ_GPIO(BALLOON3_GPIO_S0_CD) | 142 | #define BALLOON3_S0_CD_IRQ IRQ_GPIO(BALLOON3_GPIO_S0_CD) |
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index d0f5ad306078..ef2f659ca161 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
@@ -215,7 +215,7 @@ config PCMCIA_PXA2XX | |||
215 | depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ | 215 | depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ |
216 | || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ | 216 | || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ |
217 | || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \ | 217 | || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \ |
218 | || MACH_VPAC270) | 218 | || MACH_VPAC270 || MACH_BALLOON3) |
219 | select PCMCIA_SOC_COMMON | 219 | select PCMCIA_SOC_COMMON |
220 | help | 220 | help |
221 | Say Y here to include support for the PXA2xx PCMCIA controller | 221 | Say Y here to include support for the PXA2xx PCMCIA controller |
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index d006e8beab9c..6a6077325527 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile | |||
@@ -70,6 +70,7 @@ pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o | |||
70 | pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o | 70 | pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o |
71 | pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o | 71 | pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o |
72 | pxa2xx-obj-$(CONFIG_MACH_VPAC270) += pxa2xx_vpac270.o | 72 | pxa2xx-obj-$(CONFIG_MACH_VPAC270) += pxa2xx_vpac270.o |
73 | pxa2xx-obj-$(CONFIG_MACH_BALLOON3) += pxa2xx_balloon3.o | ||
73 | 74 | ||
74 | obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y) | 75 | obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y) |
75 | 76 | ||
diff --git a/drivers/pcmcia/pxa2xx_balloon3.c b/drivers/pcmcia/pxa2xx_balloon3.c new file mode 100644 index 000000000000..dbbdd0063202 --- /dev/null +++ b/drivers/pcmcia/pxa2xx_balloon3.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * linux/drivers/pcmcia/pxa2xx_balloon3.c | ||
3 | * | ||
4 | * Balloon3 PCMCIA specific routines. | ||
5 | * | ||
6 | * Author: Nick Bane | ||
7 | * Created: June, 2006 | ||
8 | * Copyright: Toby Churchill Ltd | ||
9 | * Derived from pxa2xx_mainstone.c, by Nico Pitre | ||
10 | * | ||
11 | * Various modification by Marek Vasut <marek.vasut@gmail.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/gpio.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/irq.h> | ||
24 | #include <linux/io.h> | ||
25 | |||
26 | #include <mach/balloon3.h> | ||
27 | |||
28 | #include "soc_common.h" | ||
29 | |||
30 | /* | ||
31 | * These are a list of interrupt sources that provokes a polled | ||
32 | * check of status | ||
33 | */ | ||
34 | static struct pcmcia_irqs irqs[] = { | ||
35 | { 0, BALLOON3_S0_CD_IRQ, "PCMCIA0 CD" }, | ||
36 | { 0, BALLOON3_BP_NSTSCHG_IRQ, "PCMCIA0 STSCHG" }, | ||
37 | }; | ||
38 | |||
39 | static int balloon3_pcmcia_hw_init(struct soc_pcmcia_socket *skt) | ||
40 | { | ||
41 | uint16_t ver; | ||
42 | int ret; | ||
43 | static void __iomem *fpga_ver; | ||
44 | |||
45 | ver = __raw_readw(BALLOON3_FPGA_VER); | ||
46 | if (ver > 0x0201) | ||
47 | pr_warn("The FPGA code, version 0x%04x, is newer than rel-0.3. " | ||
48 | "PCMCIA/CF support might be broken in this version!", | ||
49 | ver); | ||
50 | |||
51 | skt->socket.pci_irq = BALLOON3_BP_CF_NRDY_IRQ; | ||
52 | return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); | ||
53 | } | ||
54 | |||
55 | static void balloon3_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) | ||
56 | { | ||
57 | soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); | ||
58 | } | ||
59 | |||
60 | static unsigned long balloon3_pcmcia_status[2] = { | ||
61 | BALLOON3_CF_nSTSCHG_BVD1, | ||
62 | BALLOON3_CF_nSTSCHG_BVD1 | ||
63 | }; | ||
64 | |||
65 | static void balloon3_pcmcia_socket_state(struct soc_pcmcia_socket *skt, | ||
66 | struct pcmcia_state *state) | ||
67 | { | ||
68 | uint16_t status; | ||
69 | int flip; | ||
70 | |||
71 | /* This actually reads the STATUS register */ | ||
72 | status = __raw_readw(BALLOON3_CF_STATUS_REG); | ||
73 | flip = (status ^ balloon3_pcmcia_status[skt->nr]) | ||
74 | & BALLOON3_CF_nSTSCHG_BVD1; | ||
75 | /* | ||
76 | * Workaround for STSCHG which can't be deasserted: | ||
77 | * We therefore disable/enable corresponding IRQs | ||
78 | * as needed to avoid IRQ locks. | ||
79 | */ | ||
80 | if (flip) { | ||
81 | balloon3_pcmcia_status[skt->nr] = status; | ||
82 | if (status & BALLOON3_CF_nSTSCHG_BVD1) | ||
83 | enable_irq(BALLOON3_BP_NSTSCHG_IRQ); | ||
84 | else | ||
85 | disable_irq(BALLOON3_BP_NSTSCHG_IRQ); | ||
86 | } | ||
87 | |||
88 | state->detect = !gpio_get_value(BALLOON3_GPIO_S0_CD); | ||
89 | state->ready = !!(status & BALLOON3_CF_nIRQ); | ||
90 | state->bvd1 = !!(status & BALLOON3_CF_nSTSCHG_BVD1); | ||
91 | state->bvd2 = 0; /* not available */ | ||
92 | state->vs_3v = 1; /* Always true its a CF card */ | ||
93 | state->vs_Xv = 0; /* not available */ | ||
94 | state->wrprot = 0; /* not available */ | ||
95 | } | ||
96 | |||
97 | static int balloon3_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, | ||
98 | const socket_state_t *state) | ||
99 | { | ||
100 | __raw_writew((state->flags & SS_RESET) ? BALLOON3_CF_RESET : 0, | ||
101 | BALLOON3_CF_CONTROL_REG); | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static void balloon3_pcmcia_socket_init(struct soc_pcmcia_socket *skt) | ||
106 | { | ||
107 | } | ||
108 | |||
109 | static void balloon3_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) | ||
110 | { | ||
111 | } | ||
112 | |||
113 | static struct pcmcia_low_level balloon3_pcmcia_ops = { | ||
114 | .owner = THIS_MODULE, | ||
115 | .hw_init = balloon3_pcmcia_hw_init, | ||
116 | .hw_shutdown = balloon3_pcmcia_hw_shutdown, | ||
117 | .socket_state = balloon3_pcmcia_socket_state, | ||
118 | .configure_socket = balloon3_pcmcia_configure_socket, | ||
119 | .socket_init = balloon3_pcmcia_socket_init, | ||
120 | .socket_suspend = balloon3_pcmcia_socket_suspend, | ||
121 | .first = 0, | ||
122 | .nr = 1, | ||
123 | }; | ||
124 | |||
125 | static struct platform_device *balloon3_pcmcia_device; | ||
126 | |||
127 | static int __init balloon3_pcmcia_init(void) | ||
128 | { | ||
129 | int ret; | ||
130 | |||
131 | balloon3_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); | ||
132 | if (!balloon3_pcmcia_device) | ||
133 | return -ENOMEM; | ||
134 | |||
135 | ret = platform_device_add_data(balloon3_pcmcia_device, | ||
136 | &balloon3_pcmcia_ops, sizeof(balloon3_pcmcia_ops)); | ||
137 | |||
138 | if (!ret) | ||
139 | ret = platform_device_add(balloon3_pcmcia_device); | ||
140 | |||
141 | if (ret) | ||
142 | platform_device_put(balloon3_pcmcia_device); | ||
143 | |||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | static void __exit balloon3_pcmcia_exit(void) | ||
148 | { | ||
149 | platform_device_unregister(balloon3_pcmcia_device); | ||
150 | } | ||
151 | |||
152 | module_init(balloon3_pcmcia_init); | ||
153 | module_exit(balloon3_pcmcia_exit); | ||
154 | |||
155 | MODULE_LICENSE("GPL"); | ||
156 | MODULE_AUTHOR("Nick Bane <nick@cecomputing.co.uk>"); | ||
157 | MODULE_ALIAS("platform:pxa2xx-pcmcia"); | ||
158 | MODULE_DESCRIPTION("Balloon3 board CF/PCMCIA driver"); | ||