Commit 0178a7a54d408d2c5b7bbe7eee9450bffbec0989
1 parent
32182cd39d
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
pcmcia: remove DEFINE_PCI_DEVICE_TABLE usage
It's not needed, just use the "real" structure definition instead. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 5 changed files with 5 additions and 5 deletions Inline Diff
drivers/pcmcia/bcm63xx_pcmcia.c
1 | /* | 1 | /* |
2 | * This file is subject to the terms and conditions of the GNU General Public | 2 | * This file is subject to the terms and conditions of the GNU General Public |
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> | 6 | * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/ioport.h> | 11 | #include <linux/ioport.h> |
12 | #include <linux/timer.h> | 12 | #include <linux/timer.h> |
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <linux/pci.h> | 16 | #include <linux/pci.h> |
17 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
18 | 18 | ||
19 | #include <bcm63xx_regs.h> | 19 | #include <bcm63xx_regs.h> |
20 | #include <bcm63xx_io.h> | 20 | #include <bcm63xx_io.h> |
21 | #include "bcm63xx_pcmcia.h" | 21 | #include "bcm63xx_pcmcia.h" |
22 | 22 | ||
23 | #define PFX "bcm63xx_pcmcia: " | 23 | #define PFX "bcm63xx_pcmcia: " |
24 | 24 | ||
25 | #ifdef CONFIG_CARDBUS | 25 | #ifdef CONFIG_CARDBUS |
26 | /* if cardbus is used, platform device needs reference to actual pci | 26 | /* if cardbus is used, platform device needs reference to actual pci |
27 | * device */ | 27 | * device */ |
28 | static struct pci_dev *bcm63xx_cb_dev; | 28 | static struct pci_dev *bcm63xx_cb_dev; |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | /* | 31 | /* |
32 | * read/write helper for pcmcia regs | 32 | * read/write helper for pcmcia regs |
33 | */ | 33 | */ |
34 | static inline u32 pcmcia_readl(struct bcm63xx_pcmcia_socket *skt, u32 off) | 34 | static inline u32 pcmcia_readl(struct bcm63xx_pcmcia_socket *skt, u32 off) |
35 | { | 35 | { |
36 | return bcm_readl(skt->base + off); | 36 | return bcm_readl(skt->base + off); |
37 | } | 37 | } |
38 | 38 | ||
39 | static inline void pcmcia_writel(struct bcm63xx_pcmcia_socket *skt, | 39 | static inline void pcmcia_writel(struct bcm63xx_pcmcia_socket *skt, |
40 | u32 val, u32 off) | 40 | u32 val, u32 off) |
41 | { | 41 | { |
42 | bcm_writel(val, skt->base + off); | 42 | bcm_writel(val, skt->base + off); |
43 | } | 43 | } |
44 | 44 | ||
45 | /* | 45 | /* |
46 | * This callback should (re-)initialise the socket, turn on status | 46 | * This callback should (re-)initialise the socket, turn on status |
47 | * interrupts and PCMCIA bus, and wait for power to stabilise so that | 47 | * interrupts and PCMCIA bus, and wait for power to stabilise so that |
48 | * the card status signals report correctly. | 48 | * the card status signals report correctly. |
49 | * | 49 | * |
50 | * Hardware cannot do that. | 50 | * Hardware cannot do that. |
51 | */ | 51 | */ |
52 | static int bcm63xx_pcmcia_sock_init(struct pcmcia_socket *sock) | 52 | static int bcm63xx_pcmcia_sock_init(struct pcmcia_socket *sock) |
53 | { | 53 | { |
54 | return 0; | 54 | return 0; |
55 | } | 55 | } |
56 | 56 | ||
57 | /* | 57 | /* |
58 | * This callback should remove power on the socket, disable IRQs from | 58 | * This callback should remove power on the socket, disable IRQs from |
59 | * the card, turn off status interrupts, and disable the PCMCIA bus. | 59 | * the card, turn off status interrupts, and disable the PCMCIA bus. |
60 | * | 60 | * |
61 | * Hardware cannot do that. | 61 | * Hardware cannot do that. |
62 | */ | 62 | */ |
63 | static int bcm63xx_pcmcia_suspend(struct pcmcia_socket *sock) | 63 | static int bcm63xx_pcmcia_suspend(struct pcmcia_socket *sock) |
64 | { | 64 | { |
65 | return 0; | 65 | return 0; |
66 | } | 66 | } |
67 | 67 | ||
68 | /* | 68 | /* |
69 | * Implements the set_socket() operation for the in-kernel PCMCIA | 69 | * Implements the set_socket() operation for the in-kernel PCMCIA |
70 | * service (formerly SS_SetSocket in Card Services). We more or | 70 | * service (formerly SS_SetSocket in Card Services). We more or |
71 | * less punt all of this work and let the kernel handle the details | 71 | * less punt all of this work and let the kernel handle the details |
72 | * of power configuration, reset, &c. We also record the value of | 72 | * of power configuration, reset, &c. We also record the value of |
73 | * `state' in order to regurgitate it to the PCMCIA core later. | 73 | * `state' in order to regurgitate it to the PCMCIA core later. |
74 | */ | 74 | */ |
75 | static int bcm63xx_pcmcia_set_socket(struct pcmcia_socket *sock, | 75 | static int bcm63xx_pcmcia_set_socket(struct pcmcia_socket *sock, |
76 | socket_state_t *state) | 76 | socket_state_t *state) |
77 | { | 77 | { |
78 | struct bcm63xx_pcmcia_socket *skt; | 78 | struct bcm63xx_pcmcia_socket *skt; |
79 | unsigned long flags; | 79 | unsigned long flags; |
80 | u32 val; | 80 | u32 val; |
81 | 81 | ||
82 | skt = sock->driver_data; | 82 | skt = sock->driver_data; |
83 | 83 | ||
84 | spin_lock_irqsave(&skt->lock, flags); | 84 | spin_lock_irqsave(&skt->lock, flags); |
85 | 85 | ||
86 | /* note: hardware cannot control socket power, so we will | 86 | /* note: hardware cannot control socket power, so we will |
87 | * always report SS_POWERON */ | 87 | * always report SS_POWERON */ |
88 | 88 | ||
89 | /* apply socket reset */ | 89 | /* apply socket reset */ |
90 | val = pcmcia_readl(skt, PCMCIA_C1_REG); | 90 | val = pcmcia_readl(skt, PCMCIA_C1_REG); |
91 | if (state->flags & SS_RESET) | 91 | if (state->flags & SS_RESET) |
92 | val |= PCMCIA_C1_RESET_MASK; | 92 | val |= PCMCIA_C1_RESET_MASK; |
93 | else | 93 | else |
94 | val &= ~PCMCIA_C1_RESET_MASK; | 94 | val &= ~PCMCIA_C1_RESET_MASK; |
95 | 95 | ||
96 | /* reverse reset logic for cardbus card */ | 96 | /* reverse reset logic for cardbus card */ |
97 | if (skt->card_detected && (skt->card_type & CARD_CARDBUS)) | 97 | if (skt->card_detected && (skt->card_type & CARD_CARDBUS)) |
98 | val ^= PCMCIA_C1_RESET_MASK; | 98 | val ^= PCMCIA_C1_RESET_MASK; |
99 | 99 | ||
100 | pcmcia_writel(skt, val, PCMCIA_C1_REG); | 100 | pcmcia_writel(skt, val, PCMCIA_C1_REG); |
101 | 101 | ||
102 | /* keep requested state for event reporting */ | 102 | /* keep requested state for event reporting */ |
103 | skt->requested_state = *state; | 103 | skt->requested_state = *state; |
104 | 104 | ||
105 | spin_unlock_irqrestore(&skt->lock, flags); | 105 | spin_unlock_irqrestore(&skt->lock, flags); |
106 | 106 | ||
107 | return 0; | 107 | return 0; |
108 | } | 108 | } |
109 | 109 | ||
110 | /* | 110 | /* |
111 | * identity cardtype from VS[12] input, CD[12] input while only VS2 is | 111 | * identity cardtype from VS[12] input, CD[12] input while only VS2 is |
112 | * floating, and CD[12] input while only VS1 is floating | 112 | * floating, and CD[12] input while only VS1 is floating |
113 | */ | 113 | */ |
114 | enum { | 114 | enum { |
115 | IN_VS1 = (1 << 0), | 115 | IN_VS1 = (1 << 0), |
116 | IN_VS2 = (1 << 1), | 116 | IN_VS2 = (1 << 1), |
117 | IN_CD1_VS2H = (1 << 2), | 117 | IN_CD1_VS2H = (1 << 2), |
118 | IN_CD2_VS2H = (1 << 3), | 118 | IN_CD2_VS2H = (1 << 3), |
119 | IN_CD1_VS1H = (1 << 4), | 119 | IN_CD1_VS1H = (1 << 4), |
120 | IN_CD2_VS1H = (1 << 5), | 120 | IN_CD2_VS1H = (1 << 5), |
121 | }; | 121 | }; |
122 | 122 | ||
123 | static const u8 vscd_to_cardtype[] = { | 123 | static const u8 vscd_to_cardtype[] = { |
124 | 124 | ||
125 | /* VS1 float, VS2 float */ | 125 | /* VS1 float, VS2 float */ |
126 | [IN_VS1 | IN_VS2] = (CARD_PCCARD | CARD_5V), | 126 | [IN_VS1 | IN_VS2] = (CARD_PCCARD | CARD_5V), |
127 | 127 | ||
128 | /* VS1 grounded, VS2 float */ | 128 | /* VS1 grounded, VS2 float */ |
129 | [IN_VS2] = (CARD_PCCARD | CARD_5V | CARD_3V), | 129 | [IN_VS2] = (CARD_PCCARD | CARD_5V | CARD_3V), |
130 | 130 | ||
131 | /* VS1 grounded, VS2 grounded */ | 131 | /* VS1 grounded, VS2 grounded */ |
132 | [0] = (CARD_PCCARD | CARD_5V | CARD_3V | CARD_XV), | 132 | [0] = (CARD_PCCARD | CARD_5V | CARD_3V | CARD_XV), |
133 | 133 | ||
134 | /* VS1 tied to CD1, VS2 float */ | 134 | /* VS1 tied to CD1, VS2 float */ |
135 | [IN_VS1 | IN_VS2 | IN_CD1_VS1H] = (CARD_CARDBUS | CARD_3V), | 135 | [IN_VS1 | IN_VS2 | IN_CD1_VS1H] = (CARD_CARDBUS | CARD_3V), |
136 | 136 | ||
137 | /* VS1 grounded, VS2 tied to CD2 */ | 137 | /* VS1 grounded, VS2 tied to CD2 */ |
138 | [IN_VS2 | IN_CD2_VS2H] = (CARD_CARDBUS | CARD_3V | CARD_XV), | 138 | [IN_VS2 | IN_CD2_VS2H] = (CARD_CARDBUS | CARD_3V | CARD_XV), |
139 | 139 | ||
140 | /* VS1 tied to CD2, VS2 grounded */ | 140 | /* VS1 tied to CD2, VS2 grounded */ |
141 | [IN_VS1 | IN_CD2_VS1H] = (CARD_CARDBUS | CARD_3V | CARD_XV | CARD_YV), | 141 | [IN_VS1 | IN_CD2_VS1H] = (CARD_CARDBUS | CARD_3V | CARD_XV | CARD_YV), |
142 | 142 | ||
143 | /* VS1 float, VS2 grounded */ | 143 | /* VS1 float, VS2 grounded */ |
144 | [IN_VS1] = (CARD_PCCARD | CARD_XV), | 144 | [IN_VS1] = (CARD_PCCARD | CARD_XV), |
145 | 145 | ||
146 | /* VS1 float, VS2 tied to CD2 */ | 146 | /* VS1 float, VS2 tied to CD2 */ |
147 | [IN_VS1 | IN_VS2 | IN_CD2_VS2H] = (CARD_CARDBUS | CARD_3V), | 147 | [IN_VS1 | IN_VS2 | IN_CD2_VS2H] = (CARD_CARDBUS | CARD_3V), |
148 | 148 | ||
149 | /* VS1 float, VS2 tied to CD1 */ | 149 | /* VS1 float, VS2 tied to CD1 */ |
150 | [IN_VS1 | IN_VS2 | IN_CD1_VS2H] = (CARD_CARDBUS | CARD_XV | CARD_YV), | 150 | [IN_VS1 | IN_VS2 | IN_CD1_VS2H] = (CARD_CARDBUS | CARD_XV | CARD_YV), |
151 | 151 | ||
152 | /* VS1 tied to CD2, VS2 float */ | 152 | /* VS1 tied to CD2, VS2 float */ |
153 | [IN_VS1 | IN_VS2 | IN_CD2_VS1H] = (CARD_CARDBUS | CARD_YV), | 153 | [IN_VS1 | IN_VS2 | IN_CD2_VS1H] = (CARD_CARDBUS | CARD_YV), |
154 | 154 | ||
155 | /* VS2 grounded, VS1 is tied to CD1, CD2 is grounded */ | 155 | /* VS2 grounded, VS1 is tied to CD1, CD2 is grounded */ |
156 | [IN_VS1 | IN_CD1_VS1H] = 0, /* ignore cardbay */ | 156 | [IN_VS1 | IN_CD1_VS1H] = 0, /* ignore cardbay */ |
157 | }; | 157 | }; |
158 | 158 | ||
159 | /* | 159 | /* |
160 | * poll hardware to check card insertion status | 160 | * poll hardware to check card insertion status |
161 | */ | 161 | */ |
162 | static unsigned int __get_socket_status(struct bcm63xx_pcmcia_socket *skt) | 162 | static unsigned int __get_socket_status(struct bcm63xx_pcmcia_socket *skt) |
163 | { | 163 | { |
164 | unsigned int stat; | 164 | unsigned int stat; |
165 | u32 val; | 165 | u32 val; |
166 | 166 | ||
167 | stat = 0; | 167 | stat = 0; |
168 | 168 | ||
169 | /* check CD for card presence */ | 169 | /* check CD for card presence */ |
170 | val = pcmcia_readl(skt, PCMCIA_C1_REG); | 170 | val = pcmcia_readl(skt, PCMCIA_C1_REG); |
171 | 171 | ||
172 | if (!(val & PCMCIA_C1_CD1_MASK) && !(val & PCMCIA_C1_CD2_MASK)) | 172 | if (!(val & PCMCIA_C1_CD1_MASK) && !(val & PCMCIA_C1_CD2_MASK)) |
173 | stat |= SS_DETECT; | 173 | stat |= SS_DETECT; |
174 | 174 | ||
175 | /* if new insertion, detect cardtype */ | 175 | /* if new insertion, detect cardtype */ |
176 | if ((stat & SS_DETECT) && !skt->card_detected) { | 176 | if ((stat & SS_DETECT) && !skt->card_detected) { |
177 | unsigned int stat = 0; | 177 | unsigned int stat = 0; |
178 | 178 | ||
179 | /* float VS1, float VS2 */ | 179 | /* float VS1, float VS2 */ |
180 | val |= PCMCIA_C1_VS1OE_MASK; | 180 | val |= PCMCIA_C1_VS1OE_MASK; |
181 | val |= PCMCIA_C1_VS2OE_MASK; | 181 | val |= PCMCIA_C1_VS2OE_MASK; |
182 | pcmcia_writel(skt, val, PCMCIA_C1_REG); | 182 | pcmcia_writel(skt, val, PCMCIA_C1_REG); |
183 | 183 | ||
184 | /* wait for output to stabilize and read VS[12] */ | 184 | /* wait for output to stabilize and read VS[12] */ |
185 | udelay(10); | 185 | udelay(10); |
186 | val = pcmcia_readl(skt, PCMCIA_C1_REG); | 186 | val = pcmcia_readl(skt, PCMCIA_C1_REG); |
187 | stat |= (val & PCMCIA_C1_VS1_MASK) ? IN_VS1 : 0; | 187 | stat |= (val & PCMCIA_C1_VS1_MASK) ? IN_VS1 : 0; |
188 | stat |= (val & PCMCIA_C1_VS2_MASK) ? IN_VS2 : 0; | 188 | stat |= (val & PCMCIA_C1_VS2_MASK) ? IN_VS2 : 0; |
189 | 189 | ||
190 | /* drive VS1 low, float VS2 */ | 190 | /* drive VS1 low, float VS2 */ |
191 | val &= ~PCMCIA_C1_VS1OE_MASK; | 191 | val &= ~PCMCIA_C1_VS1OE_MASK; |
192 | val |= PCMCIA_C1_VS2OE_MASK; | 192 | val |= PCMCIA_C1_VS2OE_MASK; |
193 | pcmcia_writel(skt, val, PCMCIA_C1_REG); | 193 | pcmcia_writel(skt, val, PCMCIA_C1_REG); |
194 | 194 | ||
195 | /* wait for output to stabilize and read CD[12] */ | 195 | /* wait for output to stabilize and read CD[12] */ |
196 | udelay(10); | 196 | udelay(10); |
197 | val = pcmcia_readl(skt, PCMCIA_C1_REG); | 197 | val = pcmcia_readl(skt, PCMCIA_C1_REG); |
198 | stat |= (val & PCMCIA_C1_CD1_MASK) ? IN_CD1_VS2H : 0; | 198 | stat |= (val & PCMCIA_C1_CD1_MASK) ? IN_CD1_VS2H : 0; |
199 | stat |= (val & PCMCIA_C1_CD2_MASK) ? IN_CD2_VS2H : 0; | 199 | stat |= (val & PCMCIA_C1_CD2_MASK) ? IN_CD2_VS2H : 0; |
200 | 200 | ||
201 | /* float VS1, drive VS2 low */ | 201 | /* float VS1, drive VS2 low */ |
202 | val |= PCMCIA_C1_VS1OE_MASK; | 202 | val |= PCMCIA_C1_VS1OE_MASK; |
203 | val &= ~PCMCIA_C1_VS2OE_MASK; | 203 | val &= ~PCMCIA_C1_VS2OE_MASK; |
204 | pcmcia_writel(skt, val, PCMCIA_C1_REG); | 204 | pcmcia_writel(skt, val, PCMCIA_C1_REG); |
205 | 205 | ||
206 | /* wait for output to stabilize and read CD[12] */ | 206 | /* wait for output to stabilize and read CD[12] */ |
207 | udelay(10); | 207 | udelay(10); |
208 | val = pcmcia_readl(skt, PCMCIA_C1_REG); | 208 | val = pcmcia_readl(skt, PCMCIA_C1_REG); |
209 | stat |= (val & PCMCIA_C1_CD1_MASK) ? IN_CD1_VS1H : 0; | 209 | stat |= (val & PCMCIA_C1_CD1_MASK) ? IN_CD1_VS1H : 0; |
210 | stat |= (val & PCMCIA_C1_CD2_MASK) ? IN_CD2_VS1H : 0; | 210 | stat |= (val & PCMCIA_C1_CD2_MASK) ? IN_CD2_VS1H : 0; |
211 | 211 | ||
212 | /* guess cardtype from all this */ | 212 | /* guess cardtype from all this */ |
213 | skt->card_type = vscd_to_cardtype[stat]; | 213 | skt->card_type = vscd_to_cardtype[stat]; |
214 | if (!skt->card_type) | 214 | if (!skt->card_type) |
215 | dev_err(&skt->socket.dev, "unsupported card type\n"); | 215 | dev_err(&skt->socket.dev, "unsupported card type\n"); |
216 | 216 | ||
217 | /* drive both VS pin to 0 again */ | 217 | /* drive both VS pin to 0 again */ |
218 | val &= ~(PCMCIA_C1_VS1OE_MASK | PCMCIA_C1_VS2OE_MASK); | 218 | val &= ~(PCMCIA_C1_VS1OE_MASK | PCMCIA_C1_VS2OE_MASK); |
219 | 219 | ||
220 | /* enable correct logic */ | 220 | /* enable correct logic */ |
221 | val &= ~(PCMCIA_C1_EN_PCMCIA_MASK | PCMCIA_C1_EN_CARDBUS_MASK); | 221 | val &= ~(PCMCIA_C1_EN_PCMCIA_MASK | PCMCIA_C1_EN_CARDBUS_MASK); |
222 | if (skt->card_type & CARD_PCCARD) | 222 | if (skt->card_type & CARD_PCCARD) |
223 | val |= PCMCIA_C1_EN_PCMCIA_MASK; | 223 | val |= PCMCIA_C1_EN_PCMCIA_MASK; |
224 | else | 224 | else |
225 | val |= PCMCIA_C1_EN_CARDBUS_MASK; | 225 | val |= PCMCIA_C1_EN_CARDBUS_MASK; |
226 | 226 | ||
227 | pcmcia_writel(skt, val, PCMCIA_C1_REG); | 227 | pcmcia_writel(skt, val, PCMCIA_C1_REG); |
228 | } | 228 | } |
229 | skt->card_detected = (stat & SS_DETECT) ? 1 : 0; | 229 | skt->card_detected = (stat & SS_DETECT) ? 1 : 0; |
230 | 230 | ||
231 | /* report card type/voltage */ | 231 | /* report card type/voltage */ |
232 | if (skt->card_type & CARD_CARDBUS) | 232 | if (skt->card_type & CARD_CARDBUS) |
233 | stat |= SS_CARDBUS; | 233 | stat |= SS_CARDBUS; |
234 | if (skt->card_type & CARD_3V) | 234 | if (skt->card_type & CARD_3V) |
235 | stat |= SS_3VCARD; | 235 | stat |= SS_3VCARD; |
236 | if (skt->card_type & CARD_XV) | 236 | if (skt->card_type & CARD_XV) |
237 | stat |= SS_XVCARD; | 237 | stat |= SS_XVCARD; |
238 | stat |= SS_POWERON; | 238 | stat |= SS_POWERON; |
239 | 239 | ||
240 | if (gpio_get_value(skt->pd->ready_gpio)) | 240 | if (gpio_get_value(skt->pd->ready_gpio)) |
241 | stat |= SS_READY; | 241 | stat |= SS_READY; |
242 | 242 | ||
243 | return stat; | 243 | return stat; |
244 | } | 244 | } |
245 | 245 | ||
246 | /* | 246 | /* |
247 | * core request to get current socket status | 247 | * core request to get current socket status |
248 | */ | 248 | */ |
249 | static int bcm63xx_pcmcia_get_status(struct pcmcia_socket *sock, | 249 | static int bcm63xx_pcmcia_get_status(struct pcmcia_socket *sock, |
250 | unsigned int *status) | 250 | unsigned int *status) |
251 | { | 251 | { |
252 | struct bcm63xx_pcmcia_socket *skt; | 252 | struct bcm63xx_pcmcia_socket *skt; |
253 | 253 | ||
254 | skt = sock->driver_data; | 254 | skt = sock->driver_data; |
255 | 255 | ||
256 | spin_lock_bh(&skt->lock); | 256 | spin_lock_bh(&skt->lock); |
257 | *status = __get_socket_status(skt); | 257 | *status = __get_socket_status(skt); |
258 | spin_unlock_bh(&skt->lock); | 258 | spin_unlock_bh(&skt->lock); |
259 | 259 | ||
260 | return 0; | 260 | return 0; |
261 | } | 261 | } |
262 | 262 | ||
263 | /* | 263 | /* |
264 | * socket polling timer callback | 264 | * socket polling timer callback |
265 | */ | 265 | */ |
266 | static void bcm63xx_pcmcia_poll(unsigned long data) | 266 | static void bcm63xx_pcmcia_poll(unsigned long data) |
267 | { | 267 | { |
268 | struct bcm63xx_pcmcia_socket *skt; | 268 | struct bcm63xx_pcmcia_socket *skt; |
269 | unsigned int stat, events; | 269 | unsigned int stat, events; |
270 | 270 | ||
271 | skt = (struct bcm63xx_pcmcia_socket *)data; | 271 | skt = (struct bcm63xx_pcmcia_socket *)data; |
272 | 272 | ||
273 | spin_lock_bh(&skt->lock); | 273 | spin_lock_bh(&skt->lock); |
274 | 274 | ||
275 | stat = __get_socket_status(skt); | 275 | stat = __get_socket_status(skt); |
276 | 276 | ||
277 | /* keep only changed bits, and mask with required one from the | 277 | /* keep only changed bits, and mask with required one from the |
278 | * core */ | 278 | * core */ |
279 | events = (stat ^ skt->old_status) & skt->requested_state.csc_mask; | 279 | events = (stat ^ skt->old_status) & skt->requested_state.csc_mask; |
280 | skt->old_status = stat; | 280 | skt->old_status = stat; |
281 | spin_unlock_bh(&skt->lock); | 281 | spin_unlock_bh(&skt->lock); |
282 | 282 | ||
283 | if (events) | 283 | if (events) |
284 | pcmcia_parse_events(&skt->socket, events); | 284 | pcmcia_parse_events(&skt->socket, events); |
285 | 285 | ||
286 | mod_timer(&skt->timer, | 286 | mod_timer(&skt->timer, |
287 | jiffies + msecs_to_jiffies(BCM63XX_PCMCIA_POLL_RATE)); | 287 | jiffies + msecs_to_jiffies(BCM63XX_PCMCIA_POLL_RATE)); |
288 | } | 288 | } |
289 | 289 | ||
290 | static int bcm63xx_pcmcia_set_io_map(struct pcmcia_socket *sock, | 290 | static int bcm63xx_pcmcia_set_io_map(struct pcmcia_socket *sock, |
291 | struct pccard_io_map *map) | 291 | struct pccard_io_map *map) |
292 | { | 292 | { |
293 | /* this doesn't seem to be called by pcmcia layer if static | 293 | /* this doesn't seem to be called by pcmcia layer if static |
294 | * mapping is used */ | 294 | * mapping is used */ |
295 | return 0; | 295 | return 0; |
296 | } | 296 | } |
297 | 297 | ||
298 | static int bcm63xx_pcmcia_set_mem_map(struct pcmcia_socket *sock, | 298 | static int bcm63xx_pcmcia_set_mem_map(struct pcmcia_socket *sock, |
299 | struct pccard_mem_map *map) | 299 | struct pccard_mem_map *map) |
300 | { | 300 | { |
301 | struct bcm63xx_pcmcia_socket *skt; | 301 | struct bcm63xx_pcmcia_socket *skt; |
302 | struct resource *res; | 302 | struct resource *res; |
303 | 303 | ||
304 | skt = sock->driver_data; | 304 | skt = sock->driver_data; |
305 | if (map->flags & MAP_ATTRIB) | 305 | if (map->flags & MAP_ATTRIB) |
306 | res = skt->attr_res; | 306 | res = skt->attr_res; |
307 | else | 307 | else |
308 | res = skt->common_res; | 308 | res = skt->common_res; |
309 | 309 | ||
310 | map->static_start = res->start + map->card_start; | 310 | map->static_start = res->start + map->card_start; |
311 | return 0; | 311 | return 0; |
312 | } | 312 | } |
313 | 313 | ||
314 | static struct pccard_operations bcm63xx_pcmcia_operations = { | 314 | static struct pccard_operations bcm63xx_pcmcia_operations = { |
315 | .init = bcm63xx_pcmcia_sock_init, | 315 | .init = bcm63xx_pcmcia_sock_init, |
316 | .suspend = bcm63xx_pcmcia_suspend, | 316 | .suspend = bcm63xx_pcmcia_suspend, |
317 | .get_status = bcm63xx_pcmcia_get_status, | 317 | .get_status = bcm63xx_pcmcia_get_status, |
318 | .set_socket = bcm63xx_pcmcia_set_socket, | 318 | .set_socket = bcm63xx_pcmcia_set_socket, |
319 | .set_io_map = bcm63xx_pcmcia_set_io_map, | 319 | .set_io_map = bcm63xx_pcmcia_set_io_map, |
320 | .set_mem_map = bcm63xx_pcmcia_set_mem_map, | 320 | .set_mem_map = bcm63xx_pcmcia_set_mem_map, |
321 | }; | 321 | }; |
322 | 322 | ||
323 | /* | 323 | /* |
324 | * register pcmcia socket to core | 324 | * register pcmcia socket to core |
325 | */ | 325 | */ |
326 | static int bcm63xx_drv_pcmcia_probe(struct platform_device *pdev) | 326 | static int bcm63xx_drv_pcmcia_probe(struct platform_device *pdev) |
327 | { | 327 | { |
328 | struct bcm63xx_pcmcia_socket *skt; | 328 | struct bcm63xx_pcmcia_socket *skt; |
329 | struct pcmcia_socket *sock; | 329 | struct pcmcia_socket *sock; |
330 | struct resource *res, *irq_res; | 330 | struct resource *res, *irq_res; |
331 | unsigned int regmem_size = 0, iomem_size = 0; | 331 | unsigned int regmem_size = 0, iomem_size = 0; |
332 | u32 val; | 332 | u32 val; |
333 | int ret; | 333 | int ret; |
334 | 334 | ||
335 | skt = kzalloc(sizeof(*skt), GFP_KERNEL); | 335 | skt = kzalloc(sizeof(*skt), GFP_KERNEL); |
336 | if (!skt) | 336 | if (!skt) |
337 | return -ENOMEM; | 337 | return -ENOMEM; |
338 | spin_lock_init(&skt->lock); | 338 | spin_lock_init(&skt->lock); |
339 | sock = &skt->socket; | 339 | sock = &skt->socket; |
340 | sock->driver_data = skt; | 340 | sock->driver_data = skt; |
341 | 341 | ||
342 | /* make sure we have all resources we need */ | 342 | /* make sure we have all resources we need */ |
343 | skt->common_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 343 | skt->common_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
344 | skt->attr_res = platform_get_resource(pdev, IORESOURCE_MEM, 2); | 344 | skt->attr_res = platform_get_resource(pdev, IORESOURCE_MEM, 2); |
345 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 345 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
346 | skt->pd = pdev->dev.platform_data; | 346 | skt->pd = pdev->dev.platform_data; |
347 | if (!skt->common_res || !skt->attr_res || !irq_res || !skt->pd) { | 347 | if (!skt->common_res || !skt->attr_res || !irq_res || !skt->pd) { |
348 | ret = -EINVAL; | 348 | ret = -EINVAL; |
349 | goto err; | 349 | goto err; |
350 | } | 350 | } |
351 | 351 | ||
352 | /* remap pcmcia registers */ | 352 | /* remap pcmcia registers */ |
353 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 353 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
354 | regmem_size = resource_size(res); | 354 | regmem_size = resource_size(res); |
355 | if (!request_mem_region(res->start, regmem_size, "bcm63xx_pcmcia")) { | 355 | if (!request_mem_region(res->start, regmem_size, "bcm63xx_pcmcia")) { |
356 | ret = -EINVAL; | 356 | ret = -EINVAL; |
357 | goto err; | 357 | goto err; |
358 | } | 358 | } |
359 | skt->reg_res = res; | 359 | skt->reg_res = res; |
360 | 360 | ||
361 | skt->base = ioremap(res->start, regmem_size); | 361 | skt->base = ioremap(res->start, regmem_size); |
362 | if (!skt->base) { | 362 | if (!skt->base) { |
363 | ret = -ENOMEM; | 363 | ret = -ENOMEM; |
364 | goto err; | 364 | goto err; |
365 | } | 365 | } |
366 | 366 | ||
367 | /* remap io registers */ | 367 | /* remap io registers */ |
368 | res = platform_get_resource(pdev, IORESOURCE_MEM, 3); | 368 | res = platform_get_resource(pdev, IORESOURCE_MEM, 3); |
369 | iomem_size = resource_size(res); | 369 | iomem_size = resource_size(res); |
370 | skt->io_base = ioremap(res->start, iomem_size); | 370 | skt->io_base = ioremap(res->start, iomem_size); |
371 | if (!skt->io_base) { | 371 | if (!skt->io_base) { |
372 | ret = -ENOMEM; | 372 | ret = -ENOMEM; |
373 | goto err; | 373 | goto err; |
374 | } | 374 | } |
375 | 375 | ||
376 | /* resources are static */ | 376 | /* resources are static */ |
377 | sock->resource_ops = &pccard_static_ops; | 377 | sock->resource_ops = &pccard_static_ops; |
378 | sock->ops = &bcm63xx_pcmcia_operations; | 378 | sock->ops = &bcm63xx_pcmcia_operations; |
379 | sock->owner = THIS_MODULE; | 379 | sock->owner = THIS_MODULE; |
380 | sock->dev.parent = &pdev->dev; | 380 | sock->dev.parent = &pdev->dev; |
381 | sock->features = SS_CAP_STATIC_MAP | SS_CAP_PCCARD; | 381 | sock->features = SS_CAP_STATIC_MAP | SS_CAP_PCCARD; |
382 | sock->io_offset = (unsigned long)skt->io_base; | 382 | sock->io_offset = (unsigned long)skt->io_base; |
383 | sock->pci_irq = irq_res->start; | 383 | sock->pci_irq = irq_res->start; |
384 | 384 | ||
385 | #ifdef CONFIG_CARDBUS | 385 | #ifdef CONFIG_CARDBUS |
386 | sock->cb_dev = bcm63xx_cb_dev; | 386 | sock->cb_dev = bcm63xx_cb_dev; |
387 | if (bcm63xx_cb_dev) | 387 | if (bcm63xx_cb_dev) |
388 | sock->features |= SS_CAP_CARDBUS; | 388 | sock->features |= SS_CAP_CARDBUS; |
389 | #endif | 389 | #endif |
390 | 390 | ||
391 | /* assume common & attribute memory have the same size */ | 391 | /* assume common & attribute memory have the same size */ |
392 | sock->map_size = resource_size(skt->common_res); | 392 | sock->map_size = resource_size(skt->common_res); |
393 | 393 | ||
394 | /* initialize polling timer */ | 394 | /* initialize polling timer */ |
395 | setup_timer(&skt->timer, bcm63xx_pcmcia_poll, (unsigned long)skt); | 395 | setup_timer(&skt->timer, bcm63xx_pcmcia_poll, (unsigned long)skt); |
396 | 396 | ||
397 | /* initialize pcmcia control register, drive VS[12] to 0, | 397 | /* initialize pcmcia control register, drive VS[12] to 0, |
398 | * leave CB IDSEL to the old value since it is set by the PCI | 398 | * leave CB IDSEL to the old value since it is set by the PCI |
399 | * layer */ | 399 | * layer */ |
400 | val = pcmcia_readl(skt, PCMCIA_C1_REG); | 400 | val = pcmcia_readl(skt, PCMCIA_C1_REG); |
401 | val &= PCMCIA_C1_CBIDSEL_MASK; | 401 | val &= PCMCIA_C1_CBIDSEL_MASK; |
402 | val |= PCMCIA_C1_EN_PCMCIA_GPIO_MASK; | 402 | val |= PCMCIA_C1_EN_PCMCIA_GPIO_MASK; |
403 | pcmcia_writel(skt, val, PCMCIA_C1_REG); | 403 | pcmcia_writel(skt, val, PCMCIA_C1_REG); |
404 | 404 | ||
405 | /* | 405 | /* |
406 | * Hardware has only one set of timings registers, not one for | 406 | * Hardware has only one set of timings registers, not one for |
407 | * each memory access type, so we configure them for the | 407 | * each memory access type, so we configure them for the |
408 | * slowest one: attribute memory. | 408 | * slowest one: attribute memory. |
409 | */ | 409 | */ |
410 | val = PCMCIA_C2_DATA16_MASK; | 410 | val = PCMCIA_C2_DATA16_MASK; |
411 | val |= 10 << PCMCIA_C2_RWCOUNT_SHIFT; | 411 | val |= 10 << PCMCIA_C2_RWCOUNT_SHIFT; |
412 | val |= 6 << PCMCIA_C2_INACTIVE_SHIFT; | 412 | val |= 6 << PCMCIA_C2_INACTIVE_SHIFT; |
413 | val |= 3 << PCMCIA_C2_SETUP_SHIFT; | 413 | val |= 3 << PCMCIA_C2_SETUP_SHIFT; |
414 | val |= 3 << PCMCIA_C2_HOLD_SHIFT; | 414 | val |= 3 << PCMCIA_C2_HOLD_SHIFT; |
415 | pcmcia_writel(skt, val, PCMCIA_C2_REG); | 415 | pcmcia_writel(skt, val, PCMCIA_C2_REG); |
416 | 416 | ||
417 | ret = pcmcia_register_socket(sock); | 417 | ret = pcmcia_register_socket(sock); |
418 | if (ret) | 418 | if (ret) |
419 | goto err; | 419 | goto err; |
420 | 420 | ||
421 | /* start polling socket */ | 421 | /* start polling socket */ |
422 | mod_timer(&skt->timer, | 422 | mod_timer(&skt->timer, |
423 | jiffies + msecs_to_jiffies(BCM63XX_PCMCIA_POLL_RATE)); | 423 | jiffies + msecs_to_jiffies(BCM63XX_PCMCIA_POLL_RATE)); |
424 | 424 | ||
425 | platform_set_drvdata(pdev, skt); | 425 | platform_set_drvdata(pdev, skt); |
426 | return 0; | 426 | return 0; |
427 | 427 | ||
428 | err: | 428 | err: |
429 | if (skt->io_base) | 429 | if (skt->io_base) |
430 | iounmap(skt->io_base); | 430 | iounmap(skt->io_base); |
431 | if (skt->base) | 431 | if (skt->base) |
432 | iounmap(skt->base); | 432 | iounmap(skt->base); |
433 | if (skt->reg_res) | 433 | if (skt->reg_res) |
434 | release_mem_region(skt->reg_res->start, regmem_size); | 434 | release_mem_region(skt->reg_res->start, regmem_size); |
435 | kfree(skt); | 435 | kfree(skt); |
436 | return ret; | 436 | return ret; |
437 | } | 437 | } |
438 | 438 | ||
439 | static int bcm63xx_drv_pcmcia_remove(struct platform_device *pdev) | 439 | static int bcm63xx_drv_pcmcia_remove(struct platform_device *pdev) |
440 | { | 440 | { |
441 | struct bcm63xx_pcmcia_socket *skt; | 441 | struct bcm63xx_pcmcia_socket *skt; |
442 | struct resource *res; | 442 | struct resource *res; |
443 | 443 | ||
444 | skt = platform_get_drvdata(pdev); | 444 | skt = platform_get_drvdata(pdev); |
445 | del_timer_sync(&skt->timer); | 445 | del_timer_sync(&skt->timer); |
446 | iounmap(skt->base); | 446 | iounmap(skt->base); |
447 | iounmap(skt->io_base); | 447 | iounmap(skt->io_base); |
448 | res = skt->reg_res; | 448 | res = skt->reg_res; |
449 | release_mem_region(res->start, resource_size(res)); | 449 | release_mem_region(res->start, resource_size(res)); |
450 | kfree(skt); | 450 | kfree(skt); |
451 | return 0; | 451 | return 0; |
452 | } | 452 | } |
453 | 453 | ||
454 | struct platform_driver bcm63xx_pcmcia_driver = { | 454 | struct platform_driver bcm63xx_pcmcia_driver = { |
455 | .probe = bcm63xx_drv_pcmcia_probe, | 455 | .probe = bcm63xx_drv_pcmcia_probe, |
456 | .remove = bcm63xx_drv_pcmcia_remove, | 456 | .remove = bcm63xx_drv_pcmcia_remove, |
457 | .driver = { | 457 | .driver = { |
458 | .name = "bcm63xx_pcmcia", | 458 | .name = "bcm63xx_pcmcia", |
459 | .owner = THIS_MODULE, | 459 | .owner = THIS_MODULE, |
460 | }, | 460 | }, |
461 | }; | 461 | }; |
462 | 462 | ||
463 | #ifdef CONFIG_CARDBUS | 463 | #ifdef CONFIG_CARDBUS |
464 | static int bcm63xx_cb_probe(struct pci_dev *dev, | 464 | static int bcm63xx_cb_probe(struct pci_dev *dev, |
465 | const struct pci_device_id *id) | 465 | const struct pci_device_id *id) |
466 | { | 466 | { |
467 | /* keep pci device */ | 467 | /* keep pci device */ |
468 | bcm63xx_cb_dev = dev; | 468 | bcm63xx_cb_dev = dev; |
469 | return platform_driver_register(&bcm63xx_pcmcia_driver); | 469 | return platform_driver_register(&bcm63xx_pcmcia_driver); |
470 | } | 470 | } |
471 | 471 | ||
472 | static void bcm63xx_cb_exit(struct pci_dev *dev) | 472 | static void bcm63xx_cb_exit(struct pci_dev *dev) |
473 | { | 473 | { |
474 | platform_driver_unregister(&bcm63xx_pcmcia_driver); | 474 | platform_driver_unregister(&bcm63xx_pcmcia_driver); |
475 | bcm63xx_cb_dev = NULL; | 475 | bcm63xx_cb_dev = NULL; |
476 | } | 476 | } |
477 | 477 | ||
478 | static DEFINE_PCI_DEVICE_TABLE(bcm63xx_cb_table) = { | 478 | static const struct pci_device_id bcm63xx_cb_table[] = { |
479 | { | 479 | { |
480 | .vendor = PCI_VENDOR_ID_BROADCOM, | 480 | .vendor = PCI_VENDOR_ID_BROADCOM, |
481 | .device = BCM6348_CPU_ID, | 481 | .device = BCM6348_CPU_ID, |
482 | .subvendor = PCI_VENDOR_ID_BROADCOM, | 482 | .subvendor = PCI_VENDOR_ID_BROADCOM, |
483 | .subdevice = PCI_ANY_ID, | 483 | .subdevice = PCI_ANY_ID, |
484 | .class = PCI_CLASS_BRIDGE_CARDBUS << 8, | 484 | .class = PCI_CLASS_BRIDGE_CARDBUS << 8, |
485 | .class_mask = ~0, | 485 | .class_mask = ~0, |
486 | }, | 486 | }, |
487 | 487 | ||
488 | { | 488 | { |
489 | .vendor = PCI_VENDOR_ID_BROADCOM, | 489 | .vendor = PCI_VENDOR_ID_BROADCOM, |
490 | .device = BCM6358_CPU_ID, | 490 | .device = BCM6358_CPU_ID, |
491 | .subvendor = PCI_VENDOR_ID_BROADCOM, | 491 | .subvendor = PCI_VENDOR_ID_BROADCOM, |
492 | .subdevice = PCI_ANY_ID, | 492 | .subdevice = PCI_ANY_ID, |
493 | .class = PCI_CLASS_BRIDGE_CARDBUS << 8, | 493 | .class = PCI_CLASS_BRIDGE_CARDBUS << 8, |
494 | .class_mask = ~0, | 494 | .class_mask = ~0, |
495 | }, | 495 | }, |
496 | 496 | ||
497 | { }, | 497 | { }, |
498 | }; | 498 | }; |
499 | 499 | ||
500 | MODULE_DEVICE_TABLE(pci, bcm63xx_cb_table); | 500 | MODULE_DEVICE_TABLE(pci, bcm63xx_cb_table); |
501 | 501 | ||
502 | static struct pci_driver bcm63xx_cardbus_driver = { | 502 | static struct pci_driver bcm63xx_cardbus_driver = { |
503 | .name = "bcm63xx_cardbus", | 503 | .name = "bcm63xx_cardbus", |
504 | .id_table = bcm63xx_cb_table, | 504 | .id_table = bcm63xx_cb_table, |
505 | .probe = bcm63xx_cb_probe, | 505 | .probe = bcm63xx_cb_probe, |
506 | .remove = bcm63xx_cb_exit, | 506 | .remove = bcm63xx_cb_exit, |
507 | }; | 507 | }; |
508 | #endif | 508 | #endif |
509 | 509 | ||
510 | /* | 510 | /* |
511 | * if cardbus support is enabled, register our platform device after | 511 | * if cardbus support is enabled, register our platform device after |
512 | * our fake cardbus bridge has been registered | 512 | * our fake cardbus bridge has been registered |
513 | */ | 513 | */ |
514 | static int __init bcm63xx_pcmcia_init(void) | 514 | static int __init bcm63xx_pcmcia_init(void) |
515 | { | 515 | { |
516 | #ifdef CONFIG_CARDBUS | 516 | #ifdef CONFIG_CARDBUS |
517 | return pci_register_driver(&bcm63xx_cardbus_driver); | 517 | return pci_register_driver(&bcm63xx_cardbus_driver); |
518 | #else | 518 | #else |
519 | return platform_driver_register(&bcm63xx_pcmcia_driver); | 519 | return platform_driver_register(&bcm63xx_pcmcia_driver); |
520 | #endif | 520 | #endif |
521 | } | 521 | } |
522 | 522 | ||
523 | static void __exit bcm63xx_pcmcia_exit(void) | 523 | static void __exit bcm63xx_pcmcia_exit(void) |
524 | { | 524 | { |
525 | #ifdef CONFIG_CARDBUS | 525 | #ifdef CONFIG_CARDBUS |
526 | return pci_unregister_driver(&bcm63xx_cardbus_driver); | 526 | return pci_unregister_driver(&bcm63xx_cardbus_driver); |
527 | #else | 527 | #else |
528 | platform_driver_unregister(&bcm63xx_pcmcia_driver); | 528 | platform_driver_unregister(&bcm63xx_pcmcia_driver); |
529 | #endif | 529 | #endif |
530 | } | 530 | } |
531 | 531 | ||
532 | module_init(bcm63xx_pcmcia_init); | 532 | module_init(bcm63xx_pcmcia_init); |
533 | module_exit(bcm63xx_pcmcia_exit); | 533 | module_exit(bcm63xx_pcmcia_exit); |
534 | 534 | ||
535 | MODULE_LICENSE("GPL"); | 535 | MODULE_LICENSE("GPL"); |
536 | MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>"); | 536 | MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>"); |
537 | MODULE_DESCRIPTION("Linux PCMCIA Card Services: bcm63xx Socket Controller"); | 537 | MODULE_DESCRIPTION("Linux PCMCIA Card Services: bcm63xx Socket Controller"); |
538 | 538 |
drivers/pcmcia/i82092.c
1 | /* | 1 | /* |
2 | * Driver for Intel I82092AA PCI-PCMCIA bridge. | 2 | * Driver for Intel I82092AA PCI-PCMCIA bridge. |
3 | * | 3 | * |
4 | * (C) 2001 Red Hat, Inc. | 4 | * (C) 2001 Red Hat, Inc. |
5 | * | 5 | * |
6 | * Author: Arjan Van De Ven <arjanv@redhat.com> | 6 | * Author: Arjan Van De Ven <arjanv@redhat.com> |
7 | * Loosly based on i82365.c from the pcmcia-cs package | 7 | * Loosly based on i82365.c from the pcmcia-cs package |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/pci.h> | 12 | #include <linux/pci.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/workqueue.h> | 14 | #include <linux/workqueue.h> |
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | 17 | ||
18 | #include <pcmcia/ss.h> | 18 | #include <pcmcia/ss.h> |
19 | 19 | ||
20 | #include <asm/io.h> | 20 | #include <asm/io.h> |
21 | 21 | ||
22 | #include "i82092aa.h" | 22 | #include "i82092aa.h" |
23 | #include "i82365.h" | 23 | #include "i82365.h" |
24 | 24 | ||
25 | MODULE_LICENSE("GPL"); | 25 | MODULE_LICENSE("GPL"); |
26 | 26 | ||
27 | /* PCI core routines */ | 27 | /* PCI core routines */ |
28 | static DEFINE_PCI_DEVICE_TABLE(i82092aa_pci_ids) = { | 28 | static const struct pci_device_id i82092aa_pci_ids[] = { |
29 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82092AA_0) }, | 29 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82092AA_0) }, |
30 | { } | 30 | { } |
31 | }; | 31 | }; |
32 | MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids); | 32 | MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids); |
33 | 33 | ||
34 | static struct pci_driver i82092aa_pci_driver = { | 34 | static struct pci_driver i82092aa_pci_driver = { |
35 | .name = "i82092aa", | 35 | .name = "i82092aa", |
36 | .id_table = i82092aa_pci_ids, | 36 | .id_table = i82092aa_pci_ids, |
37 | .probe = i82092aa_pci_probe, | 37 | .probe = i82092aa_pci_probe, |
38 | .remove = i82092aa_pci_remove, | 38 | .remove = i82092aa_pci_remove, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | 41 | ||
42 | /* the pccard structure and its functions */ | 42 | /* the pccard structure and its functions */ |
43 | static struct pccard_operations i82092aa_operations = { | 43 | static struct pccard_operations i82092aa_operations = { |
44 | .init = i82092aa_init, | 44 | .init = i82092aa_init, |
45 | .get_status = i82092aa_get_status, | 45 | .get_status = i82092aa_get_status, |
46 | .set_socket = i82092aa_set_socket, | 46 | .set_socket = i82092aa_set_socket, |
47 | .set_io_map = i82092aa_set_io_map, | 47 | .set_io_map = i82092aa_set_io_map, |
48 | .set_mem_map = i82092aa_set_mem_map, | 48 | .set_mem_map = i82092aa_set_mem_map, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | /* The card can do up to 4 sockets, allocate a structure for each of them */ | 51 | /* The card can do up to 4 sockets, allocate a structure for each of them */ |
52 | 52 | ||
53 | struct socket_info { | 53 | struct socket_info { |
54 | int number; | 54 | int number; |
55 | int card_state; /* 0 = no socket, | 55 | int card_state; /* 0 = no socket, |
56 | 1 = empty socket, | 56 | 1 = empty socket, |
57 | 2 = card but not initialized, | 57 | 2 = card but not initialized, |
58 | 3 = operational card */ | 58 | 3 = operational card */ |
59 | unsigned int io_base; /* base io address of the socket */ | 59 | unsigned int io_base; /* base io address of the socket */ |
60 | 60 | ||
61 | struct pcmcia_socket socket; | 61 | struct pcmcia_socket socket; |
62 | struct pci_dev *dev; /* The PCI device for the socket */ | 62 | struct pci_dev *dev; /* The PCI device for the socket */ |
63 | }; | 63 | }; |
64 | 64 | ||
65 | #define MAX_SOCKETS 4 | 65 | #define MAX_SOCKETS 4 |
66 | static struct socket_info sockets[MAX_SOCKETS]; | 66 | static struct socket_info sockets[MAX_SOCKETS]; |
67 | static int socket_count; /* shortcut */ | 67 | static int socket_count; /* shortcut */ |
68 | 68 | ||
69 | 69 | ||
70 | static int i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | 70 | static int i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) |
71 | { | 71 | { |
72 | unsigned char configbyte; | 72 | unsigned char configbyte; |
73 | int i, ret; | 73 | int i, ret; |
74 | 74 | ||
75 | enter("i82092aa_pci_probe"); | 75 | enter("i82092aa_pci_probe"); |
76 | 76 | ||
77 | if ((ret = pci_enable_device(dev))) | 77 | if ((ret = pci_enable_device(dev))) |
78 | return ret; | 78 | return ret; |
79 | 79 | ||
80 | pci_read_config_byte(dev, 0x40, &configbyte); /* PCI Configuration Control */ | 80 | pci_read_config_byte(dev, 0x40, &configbyte); /* PCI Configuration Control */ |
81 | switch(configbyte&6) { | 81 | switch(configbyte&6) { |
82 | case 0: | 82 | case 0: |
83 | socket_count = 2; | 83 | socket_count = 2; |
84 | break; | 84 | break; |
85 | case 2: | 85 | case 2: |
86 | socket_count = 1; | 86 | socket_count = 1; |
87 | break; | 87 | break; |
88 | case 4: | 88 | case 4: |
89 | case 6: | 89 | case 6: |
90 | socket_count = 4; | 90 | socket_count = 4; |
91 | break; | 91 | break; |
92 | 92 | ||
93 | default: | 93 | default: |
94 | printk(KERN_ERR "i82092aa: Oops, you did something we didn't think of.\n"); | 94 | printk(KERN_ERR "i82092aa: Oops, you did something we didn't think of.\n"); |
95 | ret = -EIO; | 95 | ret = -EIO; |
96 | goto err_out_disable; | 96 | goto err_out_disable; |
97 | } | 97 | } |
98 | printk(KERN_INFO "i82092aa: configured as a %d socket device.\n", socket_count); | 98 | printk(KERN_INFO "i82092aa: configured as a %d socket device.\n", socket_count); |
99 | 99 | ||
100 | if (!request_region(pci_resource_start(dev, 0), 2, "i82092aa")) { | 100 | if (!request_region(pci_resource_start(dev, 0), 2, "i82092aa")) { |
101 | ret = -EBUSY; | 101 | ret = -EBUSY; |
102 | goto err_out_disable; | 102 | goto err_out_disable; |
103 | } | 103 | } |
104 | 104 | ||
105 | for (i = 0;i<socket_count;i++) { | 105 | for (i = 0;i<socket_count;i++) { |
106 | sockets[i].card_state = 1; /* 1 = present but empty */ | 106 | sockets[i].card_state = 1; /* 1 = present but empty */ |
107 | sockets[i].io_base = pci_resource_start(dev, 0); | 107 | sockets[i].io_base = pci_resource_start(dev, 0); |
108 | sockets[i].socket.features |= SS_CAP_PCCARD; | 108 | sockets[i].socket.features |= SS_CAP_PCCARD; |
109 | sockets[i].socket.map_size = 0x1000; | 109 | sockets[i].socket.map_size = 0x1000; |
110 | sockets[i].socket.irq_mask = 0; | 110 | sockets[i].socket.irq_mask = 0; |
111 | sockets[i].socket.pci_irq = dev->irq; | 111 | sockets[i].socket.pci_irq = dev->irq; |
112 | sockets[i].socket.cb_dev = dev; | 112 | sockets[i].socket.cb_dev = dev; |
113 | sockets[i].socket.owner = THIS_MODULE; | 113 | sockets[i].socket.owner = THIS_MODULE; |
114 | 114 | ||
115 | sockets[i].number = i; | 115 | sockets[i].number = i; |
116 | 116 | ||
117 | if (card_present(i)) { | 117 | if (card_present(i)) { |
118 | sockets[i].card_state = 3; | 118 | sockets[i].card_state = 3; |
119 | dprintk(KERN_DEBUG "i82092aa: slot %i is occupied\n",i); | 119 | dprintk(KERN_DEBUG "i82092aa: slot %i is occupied\n",i); |
120 | } else { | 120 | } else { |
121 | dprintk(KERN_DEBUG "i82092aa: slot %i is vacant\n",i); | 121 | dprintk(KERN_DEBUG "i82092aa: slot %i is vacant\n",i); |
122 | } | 122 | } |
123 | } | 123 | } |
124 | 124 | ||
125 | /* Now, specifiy that all interrupts are to be done as PCI interrupts */ | 125 | /* Now, specifiy that all interrupts are to be done as PCI interrupts */ |
126 | configbyte = 0xFF; /* bitmask, one bit per event, 1 = PCI interrupt, 0 = ISA interrupt */ | 126 | configbyte = 0xFF; /* bitmask, one bit per event, 1 = PCI interrupt, 0 = ISA interrupt */ |
127 | pci_write_config_byte(dev, 0x50, configbyte); /* PCI Interrupt Routing Register */ | 127 | pci_write_config_byte(dev, 0x50, configbyte); /* PCI Interrupt Routing Register */ |
128 | 128 | ||
129 | /* Register the interrupt handler */ | 129 | /* Register the interrupt handler */ |
130 | dprintk(KERN_DEBUG "Requesting interrupt %i \n",dev->irq); | 130 | dprintk(KERN_DEBUG "Requesting interrupt %i \n",dev->irq); |
131 | if ((ret = request_irq(dev->irq, i82092aa_interrupt, IRQF_SHARED, "i82092aa", i82092aa_interrupt))) { | 131 | if ((ret = request_irq(dev->irq, i82092aa_interrupt, IRQF_SHARED, "i82092aa", i82092aa_interrupt))) { |
132 | printk(KERN_ERR "i82092aa: Failed to register IRQ %d, aborting\n", dev->irq); | 132 | printk(KERN_ERR "i82092aa: Failed to register IRQ %d, aborting\n", dev->irq); |
133 | goto err_out_free_res; | 133 | goto err_out_free_res; |
134 | } | 134 | } |
135 | 135 | ||
136 | for (i = 0; i<socket_count; i++) { | 136 | for (i = 0; i<socket_count; i++) { |
137 | sockets[i].socket.dev.parent = &dev->dev; | 137 | sockets[i].socket.dev.parent = &dev->dev; |
138 | sockets[i].socket.ops = &i82092aa_operations; | 138 | sockets[i].socket.ops = &i82092aa_operations; |
139 | sockets[i].socket.resource_ops = &pccard_nonstatic_ops; | 139 | sockets[i].socket.resource_ops = &pccard_nonstatic_ops; |
140 | ret = pcmcia_register_socket(&sockets[i].socket); | 140 | ret = pcmcia_register_socket(&sockets[i].socket); |
141 | if (ret) { | 141 | if (ret) { |
142 | goto err_out_free_sockets; | 142 | goto err_out_free_sockets; |
143 | } | 143 | } |
144 | } | 144 | } |
145 | 145 | ||
146 | leave("i82092aa_pci_probe"); | 146 | leave("i82092aa_pci_probe"); |
147 | return 0; | 147 | return 0; |
148 | 148 | ||
149 | err_out_free_sockets: | 149 | err_out_free_sockets: |
150 | if (i) { | 150 | if (i) { |
151 | for (i--;i>=0;i--) { | 151 | for (i--;i>=0;i--) { |
152 | pcmcia_unregister_socket(&sockets[i].socket); | 152 | pcmcia_unregister_socket(&sockets[i].socket); |
153 | } | 153 | } |
154 | } | 154 | } |
155 | free_irq(dev->irq, i82092aa_interrupt); | 155 | free_irq(dev->irq, i82092aa_interrupt); |
156 | err_out_free_res: | 156 | err_out_free_res: |
157 | release_region(pci_resource_start(dev, 0), 2); | 157 | release_region(pci_resource_start(dev, 0), 2); |
158 | err_out_disable: | 158 | err_out_disable: |
159 | pci_disable_device(dev); | 159 | pci_disable_device(dev); |
160 | return ret; | 160 | return ret; |
161 | } | 161 | } |
162 | 162 | ||
163 | static void i82092aa_pci_remove(struct pci_dev *dev) | 163 | static void i82092aa_pci_remove(struct pci_dev *dev) |
164 | { | 164 | { |
165 | int i; | 165 | int i; |
166 | 166 | ||
167 | enter("i82092aa_pci_remove"); | 167 | enter("i82092aa_pci_remove"); |
168 | 168 | ||
169 | free_irq(dev->irq, i82092aa_interrupt); | 169 | free_irq(dev->irq, i82092aa_interrupt); |
170 | 170 | ||
171 | for (i = 0; i < socket_count; i++) | 171 | for (i = 0; i < socket_count; i++) |
172 | pcmcia_unregister_socket(&sockets[i].socket); | 172 | pcmcia_unregister_socket(&sockets[i].socket); |
173 | 173 | ||
174 | leave("i82092aa_pci_remove"); | 174 | leave("i82092aa_pci_remove"); |
175 | } | 175 | } |
176 | 176 | ||
177 | static DEFINE_SPINLOCK(port_lock); | 177 | static DEFINE_SPINLOCK(port_lock); |
178 | 178 | ||
179 | /* basic value read/write functions */ | 179 | /* basic value read/write functions */ |
180 | 180 | ||
181 | static unsigned char indirect_read(int socket, unsigned short reg) | 181 | static unsigned char indirect_read(int socket, unsigned short reg) |
182 | { | 182 | { |
183 | unsigned short int port; | 183 | unsigned short int port; |
184 | unsigned char val; | 184 | unsigned char val; |
185 | unsigned long flags; | 185 | unsigned long flags; |
186 | spin_lock_irqsave(&port_lock,flags); | 186 | spin_lock_irqsave(&port_lock,flags); |
187 | reg += socket * 0x40; | 187 | reg += socket * 0x40; |
188 | port = sockets[socket].io_base; | 188 | port = sockets[socket].io_base; |
189 | outb(reg,port); | 189 | outb(reg,port); |
190 | val = inb(port+1); | 190 | val = inb(port+1); |
191 | spin_unlock_irqrestore(&port_lock,flags); | 191 | spin_unlock_irqrestore(&port_lock,flags); |
192 | return val; | 192 | return val; |
193 | } | 193 | } |
194 | 194 | ||
195 | #if 0 | 195 | #if 0 |
196 | static unsigned short indirect_read16(int socket, unsigned short reg) | 196 | static unsigned short indirect_read16(int socket, unsigned short reg) |
197 | { | 197 | { |
198 | unsigned short int port; | 198 | unsigned short int port; |
199 | unsigned short tmp; | 199 | unsigned short tmp; |
200 | unsigned long flags; | 200 | unsigned long flags; |
201 | spin_lock_irqsave(&port_lock,flags); | 201 | spin_lock_irqsave(&port_lock,flags); |
202 | reg = reg + socket * 0x40; | 202 | reg = reg + socket * 0x40; |
203 | port = sockets[socket].io_base; | 203 | port = sockets[socket].io_base; |
204 | outb(reg,port); | 204 | outb(reg,port); |
205 | tmp = inb(port+1); | 205 | tmp = inb(port+1); |
206 | reg++; | 206 | reg++; |
207 | outb(reg,port); | 207 | outb(reg,port); |
208 | tmp = tmp | (inb(port+1)<<8); | 208 | tmp = tmp | (inb(port+1)<<8); |
209 | spin_unlock_irqrestore(&port_lock,flags); | 209 | spin_unlock_irqrestore(&port_lock,flags); |
210 | return tmp; | 210 | return tmp; |
211 | } | 211 | } |
212 | #endif | 212 | #endif |
213 | 213 | ||
214 | static void indirect_write(int socket, unsigned short reg, unsigned char value) | 214 | static void indirect_write(int socket, unsigned short reg, unsigned char value) |
215 | { | 215 | { |
216 | unsigned short int port; | 216 | unsigned short int port; |
217 | unsigned long flags; | 217 | unsigned long flags; |
218 | spin_lock_irqsave(&port_lock,flags); | 218 | spin_lock_irqsave(&port_lock,flags); |
219 | reg = reg + socket * 0x40; | 219 | reg = reg + socket * 0x40; |
220 | port = sockets[socket].io_base; | 220 | port = sockets[socket].io_base; |
221 | outb(reg,port); | 221 | outb(reg,port); |
222 | outb(value,port+1); | 222 | outb(value,port+1); |
223 | spin_unlock_irqrestore(&port_lock,flags); | 223 | spin_unlock_irqrestore(&port_lock,flags); |
224 | } | 224 | } |
225 | 225 | ||
226 | static void indirect_setbit(int socket, unsigned short reg, unsigned char mask) | 226 | static void indirect_setbit(int socket, unsigned short reg, unsigned char mask) |
227 | { | 227 | { |
228 | unsigned short int port; | 228 | unsigned short int port; |
229 | unsigned char val; | 229 | unsigned char val; |
230 | unsigned long flags; | 230 | unsigned long flags; |
231 | spin_lock_irqsave(&port_lock,flags); | 231 | spin_lock_irqsave(&port_lock,flags); |
232 | reg = reg + socket * 0x40; | 232 | reg = reg + socket * 0x40; |
233 | port = sockets[socket].io_base; | 233 | port = sockets[socket].io_base; |
234 | outb(reg,port); | 234 | outb(reg,port); |
235 | val = inb(port+1); | 235 | val = inb(port+1); |
236 | val |= mask; | 236 | val |= mask; |
237 | outb(reg,port); | 237 | outb(reg,port); |
238 | outb(val,port+1); | 238 | outb(val,port+1); |
239 | spin_unlock_irqrestore(&port_lock,flags); | 239 | spin_unlock_irqrestore(&port_lock,flags); |
240 | } | 240 | } |
241 | 241 | ||
242 | 242 | ||
243 | static void indirect_resetbit(int socket, unsigned short reg, unsigned char mask) | 243 | static void indirect_resetbit(int socket, unsigned short reg, unsigned char mask) |
244 | { | 244 | { |
245 | unsigned short int port; | 245 | unsigned short int port; |
246 | unsigned char val; | 246 | unsigned char val; |
247 | unsigned long flags; | 247 | unsigned long flags; |
248 | spin_lock_irqsave(&port_lock,flags); | 248 | spin_lock_irqsave(&port_lock,flags); |
249 | reg = reg + socket * 0x40; | 249 | reg = reg + socket * 0x40; |
250 | port = sockets[socket].io_base; | 250 | port = sockets[socket].io_base; |
251 | outb(reg,port); | 251 | outb(reg,port); |
252 | val = inb(port+1); | 252 | val = inb(port+1); |
253 | val &= ~mask; | 253 | val &= ~mask; |
254 | outb(reg,port); | 254 | outb(reg,port); |
255 | outb(val,port+1); | 255 | outb(val,port+1); |
256 | spin_unlock_irqrestore(&port_lock,flags); | 256 | spin_unlock_irqrestore(&port_lock,flags); |
257 | } | 257 | } |
258 | 258 | ||
259 | static void indirect_write16(int socket, unsigned short reg, unsigned short value) | 259 | static void indirect_write16(int socket, unsigned short reg, unsigned short value) |
260 | { | 260 | { |
261 | unsigned short int port; | 261 | unsigned short int port; |
262 | unsigned char val; | 262 | unsigned char val; |
263 | unsigned long flags; | 263 | unsigned long flags; |
264 | spin_lock_irqsave(&port_lock,flags); | 264 | spin_lock_irqsave(&port_lock,flags); |
265 | reg = reg + socket * 0x40; | 265 | reg = reg + socket * 0x40; |
266 | port = sockets[socket].io_base; | 266 | port = sockets[socket].io_base; |
267 | 267 | ||
268 | outb(reg,port); | 268 | outb(reg,port); |
269 | val = value & 255; | 269 | val = value & 255; |
270 | outb(val,port+1); | 270 | outb(val,port+1); |
271 | 271 | ||
272 | reg++; | 272 | reg++; |
273 | 273 | ||
274 | outb(reg,port); | 274 | outb(reg,port); |
275 | val = value>>8; | 275 | val = value>>8; |
276 | outb(val,port+1); | 276 | outb(val,port+1); |
277 | spin_unlock_irqrestore(&port_lock,flags); | 277 | spin_unlock_irqrestore(&port_lock,flags); |
278 | } | 278 | } |
279 | 279 | ||
280 | /* simple helper functions */ | 280 | /* simple helper functions */ |
281 | /* External clock time, in nanoseconds. 120 ns = 8.33 MHz */ | 281 | /* External clock time, in nanoseconds. 120 ns = 8.33 MHz */ |
282 | static int cycle_time = 120; | 282 | static int cycle_time = 120; |
283 | 283 | ||
284 | static int to_cycles(int ns) | 284 | static int to_cycles(int ns) |
285 | { | 285 | { |
286 | if (cycle_time!=0) | 286 | if (cycle_time!=0) |
287 | return ns/cycle_time; | 287 | return ns/cycle_time; |
288 | else | 288 | else |
289 | return 0; | 289 | return 0; |
290 | } | 290 | } |
291 | 291 | ||
292 | 292 | ||
293 | /* Interrupt handler functionality */ | 293 | /* Interrupt handler functionality */ |
294 | 294 | ||
295 | static irqreturn_t i82092aa_interrupt(int irq, void *dev) | 295 | static irqreturn_t i82092aa_interrupt(int irq, void *dev) |
296 | { | 296 | { |
297 | int i; | 297 | int i; |
298 | int loopcount = 0; | 298 | int loopcount = 0; |
299 | int handled = 0; | 299 | int handled = 0; |
300 | 300 | ||
301 | unsigned int events, active=0; | 301 | unsigned int events, active=0; |
302 | 302 | ||
303 | /* enter("i82092aa_interrupt");*/ | 303 | /* enter("i82092aa_interrupt");*/ |
304 | 304 | ||
305 | while (1) { | 305 | while (1) { |
306 | loopcount++; | 306 | loopcount++; |
307 | if (loopcount>20) { | 307 | if (loopcount>20) { |
308 | printk(KERN_ERR "i82092aa: infinite eventloop in interrupt \n"); | 308 | printk(KERN_ERR "i82092aa: infinite eventloop in interrupt \n"); |
309 | break; | 309 | break; |
310 | } | 310 | } |
311 | 311 | ||
312 | active = 0; | 312 | active = 0; |
313 | 313 | ||
314 | for (i=0;i<socket_count;i++) { | 314 | for (i=0;i<socket_count;i++) { |
315 | int csc; | 315 | int csc; |
316 | if (sockets[i].card_state==0) /* Inactive socket, should not happen */ | 316 | if (sockets[i].card_state==0) /* Inactive socket, should not happen */ |
317 | continue; | 317 | continue; |
318 | 318 | ||
319 | csc = indirect_read(i,I365_CSC); /* card status change register */ | 319 | csc = indirect_read(i,I365_CSC); /* card status change register */ |
320 | 320 | ||
321 | if (csc==0) /* no events on this socket */ | 321 | if (csc==0) /* no events on this socket */ |
322 | continue; | 322 | continue; |
323 | handled = 1; | 323 | handled = 1; |
324 | events = 0; | 324 | events = 0; |
325 | 325 | ||
326 | if (csc & I365_CSC_DETECT) { | 326 | if (csc & I365_CSC_DETECT) { |
327 | events |= SS_DETECT; | 327 | events |= SS_DETECT; |
328 | printk("Card detected in socket %i!\n",i); | 328 | printk("Card detected in socket %i!\n",i); |
329 | } | 329 | } |
330 | 330 | ||
331 | if (indirect_read(i,I365_INTCTL) & I365_PC_IOCARD) { | 331 | if (indirect_read(i,I365_INTCTL) & I365_PC_IOCARD) { |
332 | /* For IO/CARDS, bit 0 means "read the card" */ | 332 | /* For IO/CARDS, bit 0 means "read the card" */ |
333 | events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; | 333 | events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; |
334 | } else { | 334 | } else { |
335 | /* Check for battery/ready events */ | 335 | /* Check for battery/ready events */ |
336 | events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0; | 336 | events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0; |
337 | events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; | 337 | events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; |
338 | events |= (csc & I365_CSC_READY) ? SS_READY : 0; | 338 | events |= (csc & I365_CSC_READY) ? SS_READY : 0; |
339 | } | 339 | } |
340 | 340 | ||
341 | if (events) { | 341 | if (events) { |
342 | pcmcia_parse_events(&sockets[i].socket, events); | 342 | pcmcia_parse_events(&sockets[i].socket, events); |
343 | } | 343 | } |
344 | active |= events; | 344 | active |= events; |
345 | } | 345 | } |
346 | 346 | ||
347 | if (active==0) /* no more events to handle */ | 347 | if (active==0) /* no more events to handle */ |
348 | break; | 348 | break; |
349 | 349 | ||
350 | } | 350 | } |
351 | return IRQ_RETVAL(handled); | 351 | return IRQ_RETVAL(handled); |
352 | /* leave("i82092aa_interrupt");*/ | 352 | /* leave("i82092aa_interrupt");*/ |
353 | } | 353 | } |
354 | 354 | ||
355 | 355 | ||
356 | 356 | ||
357 | /* socket functions */ | 357 | /* socket functions */ |
358 | 358 | ||
359 | static int card_present(int socketno) | 359 | static int card_present(int socketno) |
360 | { | 360 | { |
361 | unsigned int val; | 361 | unsigned int val; |
362 | enter("card_present"); | 362 | enter("card_present"); |
363 | 363 | ||
364 | if ((socketno<0) || (socketno >= MAX_SOCKETS)) | 364 | if ((socketno<0) || (socketno >= MAX_SOCKETS)) |
365 | return 0; | 365 | return 0; |
366 | if (sockets[socketno].io_base == 0) | 366 | if (sockets[socketno].io_base == 0) |
367 | return 0; | 367 | return 0; |
368 | 368 | ||
369 | 369 | ||
370 | val = indirect_read(socketno, 1); /* Interface status register */ | 370 | val = indirect_read(socketno, 1); /* Interface status register */ |
371 | if ((val&12)==12) { | 371 | if ((val&12)==12) { |
372 | leave("card_present 1"); | 372 | leave("card_present 1"); |
373 | return 1; | 373 | return 1; |
374 | } | 374 | } |
375 | 375 | ||
376 | leave("card_present 0"); | 376 | leave("card_present 0"); |
377 | return 0; | 377 | return 0; |
378 | } | 378 | } |
379 | 379 | ||
380 | static void set_bridge_state(int sock) | 380 | static void set_bridge_state(int sock) |
381 | { | 381 | { |
382 | enter("set_bridge_state"); | 382 | enter("set_bridge_state"); |
383 | indirect_write(sock, I365_GBLCTL,0x00); | 383 | indirect_write(sock, I365_GBLCTL,0x00); |
384 | indirect_write(sock, I365_GENCTL,0x00); | 384 | indirect_write(sock, I365_GENCTL,0x00); |
385 | 385 | ||
386 | indirect_setbit(sock, I365_INTCTL,0x08); | 386 | indirect_setbit(sock, I365_INTCTL,0x08); |
387 | leave("set_bridge_state"); | 387 | leave("set_bridge_state"); |
388 | } | 388 | } |
389 | 389 | ||
390 | 390 | ||
391 | 391 | ||
392 | 392 | ||
393 | 393 | ||
394 | 394 | ||
395 | static int i82092aa_init(struct pcmcia_socket *sock) | 395 | static int i82092aa_init(struct pcmcia_socket *sock) |
396 | { | 396 | { |
397 | int i; | 397 | int i; |
398 | struct resource res = { .start = 0, .end = 0x0fff }; | 398 | struct resource res = { .start = 0, .end = 0x0fff }; |
399 | pccard_io_map io = { 0, 0, 0, 0, 1 }; | 399 | pccard_io_map io = { 0, 0, 0, 0, 1 }; |
400 | pccard_mem_map mem = { .res = &res, }; | 400 | pccard_mem_map mem = { .res = &res, }; |
401 | 401 | ||
402 | enter("i82092aa_init"); | 402 | enter("i82092aa_init"); |
403 | 403 | ||
404 | for (i = 0; i < 2; i++) { | 404 | for (i = 0; i < 2; i++) { |
405 | io.map = i; | 405 | io.map = i; |
406 | i82092aa_set_io_map(sock, &io); | 406 | i82092aa_set_io_map(sock, &io); |
407 | } | 407 | } |
408 | for (i = 0; i < 5; i++) { | 408 | for (i = 0; i < 5; i++) { |
409 | mem.map = i; | 409 | mem.map = i; |
410 | i82092aa_set_mem_map(sock, &mem); | 410 | i82092aa_set_mem_map(sock, &mem); |
411 | } | 411 | } |
412 | 412 | ||
413 | leave("i82092aa_init"); | 413 | leave("i82092aa_init"); |
414 | return 0; | 414 | return 0; |
415 | } | 415 | } |
416 | 416 | ||
417 | static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value) | 417 | static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value) |
418 | { | 418 | { |
419 | unsigned int sock = container_of(socket, struct socket_info, socket)->number; | 419 | unsigned int sock = container_of(socket, struct socket_info, socket)->number; |
420 | unsigned int status; | 420 | unsigned int status; |
421 | 421 | ||
422 | enter("i82092aa_get_status"); | 422 | enter("i82092aa_get_status"); |
423 | 423 | ||
424 | status = indirect_read(sock,I365_STATUS); /* Interface Status Register */ | 424 | status = indirect_read(sock,I365_STATUS); /* Interface Status Register */ |
425 | *value = 0; | 425 | *value = 0; |
426 | 426 | ||
427 | if ((status & I365_CS_DETECT) == I365_CS_DETECT) { | 427 | if ((status & I365_CS_DETECT) == I365_CS_DETECT) { |
428 | *value |= SS_DETECT; | 428 | *value |= SS_DETECT; |
429 | } | 429 | } |
430 | 430 | ||
431 | /* IO cards have a different meaning of bits 0,1 */ | 431 | /* IO cards have a different meaning of bits 0,1 */ |
432 | /* Also notice the inverse-logic on the bits */ | 432 | /* Also notice the inverse-logic on the bits */ |
433 | if (indirect_read(sock, I365_INTCTL) & I365_PC_IOCARD) { | 433 | if (indirect_read(sock, I365_INTCTL) & I365_PC_IOCARD) { |
434 | /* IO card */ | 434 | /* IO card */ |
435 | if (!(status & I365_CS_STSCHG)) | 435 | if (!(status & I365_CS_STSCHG)) |
436 | *value |= SS_STSCHG; | 436 | *value |= SS_STSCHG; |
437 | } else { /* non I/O card */ | 437 | } else { /* non I/O card */ |
438 | if (!(status & I365_CS_BVD1)) | 438 | if (!(status & I365_CS_BVD1)) |
439 | *value |= SS_BATDEAD; | 439 | *value |= SS_BATDEAD; |
440 | if (!(status & I365_CS_BVD2)) | 440 | if (!(status & I365_CS_BVD2)) |
441 | *value |= SS_BATWARN; | 441 | *value |= SS_BATWARN; |
442 | 442 | ||
443 | } | 443 | } |
444 | 444 | ||
445 | if (status & I365_CS_WRPROT) | 445 | if (status & I365_CS_WRPROT) |
446 | (*value) |= SS_WRPROT; /* card is write protected */ | 446 | (*value) |= SS_WRPROT; /* card is write protected */ |
447 | 447 | ||
448 | if (status & I365_CS_READY) | 448 | if (status & I365_CS_READY) |
449 | (*value) |= SS_READY; /* card is not busy */ | 449 | (*value) |= SS_READY; /* card is not busy */ |
450 | 450 | ||
451 | if (status & I365_CS_POWERON) | 451 | if (status & I365_CS_POWERON) |
452 | (*value) |= SS_POWERON; /* power is applied to the card */ | 452 | (*value) |= SS_POWERON; /* power is applied to the card */ |
453 | 453 | ||
454 | 454 | ||
455 | leave("i82092aa_get_status"); | 455 | leave("i82092aa_get_status"); |
456 | return 0; | 456 | return 0; |
457 | } | 457 | } |
458 | 458 | ||
459 | 459 | ||
460 | static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state) | 460 | static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state) |
461 | { | 461 | { |
462 | unsigned int sock = container_of(socket, struct socket_info, socket)->number; | 462 | unsigned int sock = container_of(socket, struct socket_info, socket)->number; |
463 | unsigned char reg; | 463 | unsigned char reg; |
464 | 464 | ||
465 | enter("i82092aa_set_socket"); | 465 | enter("i82092aa_set_socket"); |
466 | 466 | ||
467 | /* First, set the global controller options */ | 467 | /* First, set the global controller options */ |
468 | 468 | ||
469 | set_bridge_state(sock); | 469 | set_bridge_state(sock); |
470 | 470 | ||
471 | /* Values for the IGENC register */ | 471 | /* Values for the IGENC register */ |
472 | 472 | ||
473 | reg = 0; | 473 | reg = 0; |
474 | if (!(state->flags & SS_RESET)) /* The reset bit has "inverse" logic */ | 474 | if (!(state->flags & SS_RESET)) /* The reset bit has "inverse" logic */ |
475 | reg = reg | I365_PC_RESET; | 475 | reg = reg | I365_PC_RESET; |
476 | if (state->flags & SS_IOCARD) | 476 | if (state->flags & SS_IOCARD) |
477 | reg = reg | I365_PC_IOCARD; | 477 | reg = reg | I365_PC_IOCARD; |
478 | 478 | ||
479 | indirect_write(sock,I365_INTCTL,reg); /* IGENC, Interrupt and General Control Register */ | 479 | indirect_write(sock,I365_INTCTL,reg); /* IGENC, Interrupt and General Control Register */ |
480 | 480 | ||
481 | /* Power registers */ | 481 | /* Power registers */ |
482 | 482 | ||
483 | reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */ | 483 | reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */ |
484 | 484 | ||
485 | if (state->flags & SS_PWR_AUTO) { | 485 | if (state->flags & SS_PWR_AUTO) { |
486 | printk("Auto power\n"); | 486 | printk("Auto power\n"); |
487 | reg |= I365_PWR_AUTO; /* automatic power mngmnt */ | 487 | reg |= I365_PWR_AUTO; /* automatic power mngmnt */ |
488 | } | 488 | } |
489 | if (state->flags & SS_OUTPUT_ENA) { | 489 | if (state->flags & SS_OUTPUT_ENA) { |
490 | printk("Power Enabled \n"); | 490 | printk("Power Enabled \n"); |
491 | reg |= I365_PWR_OUT; /* enable power */ | 491 | reg |= I365_PWR_OUT; /* enable power */ |
492 | } | 492 | } |
493 | 493 | ||
494 | switch (state->Vcc) { | 494 | switch (state->Vcc) { |
495 | case 0: | 495 | case 0: |
496 | break; | 496 | break; |
497 | case 50: | 497 | case 50: |
498 | printk("setting voltage to Vcc to 5V on socket %i\n",sock); | 498 | printk("setting voltage to Vcc to 5V on socket %i\n",sock); |
499 | reg |= I365_VCC_5V; | 499 | reg |= I365_VCC_5V; |
500 | break; | 500 | break; |
501 | default: | 501 | default: |
502 | printk("i82092aa: i82092aa_set_socket called with invalid VCC power value: %i ", state->Vcc); | 502 | printk("i82092aa: i82092aa_set_socket called with invalid VCC power value: %i ", state->Vcc); |
503 | leave("i82092aa_set_socket"); | 503 | leave("i82092aa_set_socket"); |
504 | return -EINVAL; | 504 | return -EINVAL; |
505 | } | 505 | } |
506 | 506 | ||
507 | 507 | ||
508 | switch (state->Vpp) { | 508 | switch (state->Vpp) { |
509 | case 0: | 509 | case 0: |
510 | printk("not setting Vpp on socket %i\n",sock); | 510 | printk("not setting Vpp on socket %i\n",sock); |
511 | break; | 511 | break; |
512 | case 50: | 512 | case 50: |
513 | printk("setting Vpp to 5.0 for socket %i\n",sock); | 513 | printk("setting Vpp to 5.0 for socket %i\n",sock); |
514 | reg |= I365_VPP1_5V | I365_VPP2_5V; | 514 | reg |= I365_VPP1_5V | I365_VPP2_5V; |
515 | break; | 515 | break; |
516 | case 120: | 516 | case 120: |
517 | printk("setting Vpp to 12.0\n"); | 517 | printk("setting Vpp to 12.0\n"); |
518 | reg |= I365_VPP1_12V | I365_VPP2_12V; | 518 | reg |= I365_VPP1_12V | I365_VPP2_12V; |
519 | break; | 519 | break; |
520 | default: | 520 | default: |
521 | printk("i82092aa: i82092aa_set_socket called with invalid VPP power value: %i ", state->Vcc); | 521 | printk("i82092aa: i82092aa_set_socket called with invalid VPP power value: %i ", state->Vcc); |
522 | leave("i82092aa_set_socket"); | 522 | leave("i82092aa_set_socket"); |
523 | return -EINVAL; | 523 | return -EINVAL; |
524 | } | 524 | } |
525 | 525 | ||
526 | if (reg != indirect_read(sock,I365_POWER)) /* only write if changed */ | 526 | if (reg != indirect_read(sock,I365_POWER)) /* only write if changed */ |
527 | indirect_write(sock,I365_POWER,reg); | 527 | indirect_write(sock,I365_POWER,reg); |
528 | 528 | ||
529 | /* Enable specific interrupt events */ | 529 | /* Enable specific interrupt events */ |
530 | 530 | ||
531 | reg = 0x00; | 531 | reg = 0x00; |
532 | if (state->csc_mask & SS_DETECT) { | 532 | if (state->csc_mask & SS_DETECT) { |
533 | reg |= I365_CSC_DETECT; | 533 | reg |= I365_CSC_DETECT; |
534 | } | 534 | } |
535 | if (state->flags & SS_IOCARD) { | 535 | if (state->flags & SS_IOCARD) { |
536 | if (state->csc_mask & SS_STSCHG) | 536 | if (state->csc_mask & SS_STSCHG) |
537 | reg |= I365_CSC_STSCHG; | 537 | reg |= I365_CSC_STSCHG; |
538 | } else { | 538 | } else { |
539 | if (state->csc_mask & SS_BATDEAD) | 539 | if (state->csc_mask & SS_BATDEAD) |
540 | reg |= I365_CSC_BVD1; | 540 | reg |= I365_CSC_BVD1; |
541 | if (state->csc_mask & SS_BATWARN) | 541 | if (state->csc_mask & SS_BATWARN) |
542 | reg |= I365_CSC_BVD2; | 542 | reg |= I365_CSC_BVD2; |
543 | if (state->csc_mask & SS_READY) | 543 | if (state->csc_mask & SS_READY) |
544 | reg |= I365_CSC_READY; | 544 | reg |= I365_CSC_READY; |
545 | 545 | ||
546 | } | 546 | } |
547 | 547 | ||
548 | /* now write the value and clear the (probably bogus) pending stuff by doing a dummy read*/ | 548 | /* now write the value and clear the (probably bogus) pending stuff by doing a dummy read*/ |
549 | 549 | ||
550 | indirect_write(sock,I365_CSCINT,reg); | 550 | indirect_write(sock,I365_CSCINT,reg); |
551 | (void)indirect_read(sock,I365_CSC); | 551 | (void)indirect_read(sock,I365_CSC); |
552 | 552 | ||
553 | leave("i82092aa_set_socket"); | 553 | leave("i82092aa_set_socket"); |
554 | return 0; | 554 | return 0; |
555 | } | 555 | } |
556 | 556 | ||
557 | static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io) | 557 | static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io) |
558 | { | 558 | { |
559 | unsigned int sock = container_of(socket, struct socket_info, socket)->number; | 559 | unsigned int sock = container_of(socket, struct socket_info, socket)->number; |
560 | unsigned char map, ioctl; | 560 | unsigned char map, ioctl; |
561 | 561 | ||
562 | enter("i82092aa_set_io_map"); | 562 | enter("i82092aa_set_io_map"); |
563 | 563 | ||
564 | map = io->map; | 564 | map = io->map; |
565 | 565 | ||
566 | /* Check error conditions */ | 566 | /* Check error conditions */ |
567 | if (map > 1) { | 567 | if (map > 1) { |
568 | leave("i82092aa_set_io_map with invalid map"); | 568 | leave("i82092aa_set_io_map with invalid map"); |
569 | return -EINVAL; | 569 | return -EINVAL; |
570 | } | 570 | } |
571 | if ((io->start > 0xffff) || (io->stop > 0xffff) || (io->stop < io->start)){ | 571 | if ((io->start > 0xffff) || (io->stop > 0xffff) || (io->stop < io->start)){ |
572 | leave("i82092aa_set_io_map with invalid io"); | 572 | leave("i82092aa_set_io_map with invalid io"); |
573 | return -EINVAL; | 573 | return -EINVAL; |
574 | } | 574 | } |
575 | 575 | ||
576 | /* Turn off the window before changing anything */ | 576 | /* Turn off the window before changing anything */ |
577 | if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_IO(map)) | 577 | if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_IO(map)) |
578 | indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_IO(map)); | 578 | indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_IO(map)); |
579 | 579 | ||
580 | /* printk("set_io_map: Setting range to %x - %x \n",io->start,io->stop); */ | 580 | /* printk("set_io_map: Setting range to %x - %x \n",io->start,io->stop); */ |
581 | 581 | ||
582 | /* write the new values */ | 582 | /* write the new values */ |
583 | indirect_write16(sock,I365_IO(map)+I365_W_START,io->start); | 583 | indirect_write16(sock,I365_IO(map)+I365_W_START,io->start); |
584 | indirect_write16(sock,I365_IO(map)+I365_W_STOP,io->stop); | 584 | indirect_write16(sock,I365_IO(map)+I365_W_STOP,io->stop); |
585 | 585 | ||
586 | ioctl = indirect_read(sock,I365_IOCTL) & ~I365_IOCTL_MASK(map); | 586 | ioctl = indirect_read(sock,I365_IOCTL) & ~I365_IOCTL_MASK(map); |
587 | 587 | ||
588 | if (io->flags & (MAP_16BIT|MAP_AUTOSZ)) | 588 | if (io->flags & (MAP_16BIT|MAP_AUTOSZ)) |
589 | ioctl |= I365_IOCTL_16BIT(map); | 589 | ioctl |= I365_IOCTL_16BIT(map); |
590 | 590 | ||
591 | indirect_write(sock,I365_IOCTL,ioctl); | 591 | indirect_write(sock,I365_IOCTL,ioctl); |
592 | 592 | ||
593 | /* Turn the window back on if needed */ | 593 | /* Turn the window back on if needed */ |
594 | if (io->flags & MAP_ACTIVE) | 594 | if (io->flags & MAP_ACTIVE) |
595 | indirect_setbit(sock,I365_ADDRWIN,I365_ENA_IO(map)); | 595 | indirect_setbit(sock,I365_ADDRWIN,I365_ENA_IO(map)); |
596 | 596 | ||
597 | leave("i82092aa_set_io_map"); | 597 | leave("i82092aa_set_io_map"); |
598 | return 0; | 598 | return 0; |
599 | } | 599 | } |
600 | 600 | ||
601 | static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem) | 601 | static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem) |
602 | { | 602 | { |
603 | struct socket_info *sock_info = container_of(socket, struct socket_info, socket); | 603 | struct socket_info *sock_info = container_of(socket, struct socket_info, socket); |
604 | unsigned int sock = sock_info->number; | 604 | unsigned int sock = sock_info->number; |
605 | struct pci_bus_region region; | 605 | struct pci_bus_region region; |
606 | unsigned short base, i; | 606 | unsigned short base, i; |
607 | unsigned char map; | 607 | unsigned char map; |
608 | 608 | ||
609 | enter("i82092aa_set_mem_map"); | 609 | enter("i82092aa_set_mem_map"); |
610 | 610 | ||
611 | pcibios_resource_to_bus(sock_info->dev->bus, ®ion, mem->res); | 611 | pcibios_resource_to_bus(sock_info->dev->bus, ®ion, mem->res); |
612 | 612 | ||
613 | map = mem->map; | 613 | map = mem->map; |
614 | if (map > 4) { | 614 | if (map > 4) { |
615 | leave("i82092aa_set_mem_map: invalid map"); | 615 | leave("i82092aa_set_mem_map: invalid map"); |
616 | return -EINVAL; | 616 | return -EINVAL; |
617 | } | 617 | } |
618 | 618 | ||
619 | 619 | ||
620 | if ( (mem->card_start > 0x3ffffff) || (region.start > region.end) || | 620 | if ( (mem->card_start > 0x3ffffff) || (region.start > region.end) || |
621 | (mem->speed > 1000) ) { | 621 | (mem->speed > 1000) ) { |
622 | leave("i82092aa_set_mem_map: invalid address / speed"); | 622 | leave("i82092aa_set_mem_map: invalid address / speed"); |
623 | printk("invalid mem map for socket %i: %llx to %llx with a " | 623 | printk("invalid mem map for socket %i: %llx to %llx with a " |
624 | "start of %x\n", | 624 | "start of %x\n", |
625 | sock, | 625 | sock, |
626 | (unsigned long long)region.start, | 626 | (unsigned long long)region.start, |
627 | (unsigned long long)region.end, | 627 | (unsigned long long)region.end, |
628 | mem->card_start); | 628 | mem->card_start); |
629 | return -EINVAL; | 629 | return -EINVAL; |
630 | } | 630 | } |
631 | 631 | ||
632 | /* Turn off the window before changing anything */ | 632 | /* Turn off the window before changing anything */ |
633 | if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_MEM(map)) | 633 | if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_MEM(map)) |
634 | indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_MEM(map)); | 634 | indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_MEM(map)); |
635 | 635 | ||
636 | 636 | ||
637 | /* printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i \n",map, region.start,region.end,sock,mem->speed,mem->flags & MAP_ACTIVE); */ | 637 | /* printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i \n",map, region.start,region.end,sock,mem->speed,mem->flags & MAP_ACTIVE); */ |
638 | 638 | ||
639 | /* write the start address */ | 639 | /* write the start address */ |
640 | base = I365_MEM(map); | 640 | base = I365_MEM(map); |
641 | i = (region.start >> 12) & 0x0fff; | 641 | i = (region.start >> 12) & 0x0fff; |
642 | if (mem->flags & MAP_16BIT) | 642 | if (mem->flags & MAP_16BIT) |
643 | i |= I365_MEM_16BIT; | 643 | i |= I365_MEM_16BIT; |
644 | if (mem->flags & MAP_0WS) | 644 | if (mem->flags & MAP_0WS) |
645 | i |= I365_MEM_0WS; | 645 | i |= I365_MEM_0WS; |
646 | indirect_write16(sock,base+I365_W_START,i); | 646 | indirect_write16(sock,base+I365_W_START,i); |
647 | 647 | ||
648 | /* write the stop address */ | 648 | /* write the stop address */ |
649 | 649 | ||
650 | i= (region.end >> 12) & 0x0fff; | 650 | i= (region.end >> 12) & 0x0fff; |
651 | switch (to_cycles(mem->speed)) { | 651 | switch (to_cycles(mem->speed)) { |
652 | case 0: | 652 | case 0: |
653 | break; | 653 | break; |
654 | case 1: | 654 | case 1: |
655 | i |= I365_MEM_WS0; | 655 | i |= I365_MEM_WS0; |
656 | break; | 656 | break; |
657 | case 2: | 657 | case 2: |
658 | i |= I365_MEM_WS1; | 658 | i |= I365_MEM_WS1; |
659 | break; | 659 | break; |
660 | default: | 660 | default: |
661 | i |= I365_MEM_WS1 | I365_MEM_WS0; | 661 | i |= I365_MEM_WS1 | I365_MEM_WS0; |
662 | break; | 662 | break; |
663 | } | 663 | } |
664 | 664 | ||
665 | indirect_write16(sock,base+I365_W_STOP,i); | 665 | indirect_write16(sock,base+I365_W_STOP,i); |
666 | 666 | ||
667 | /* card start */ | 667 | /* card start */ |
668 | 668 | ||
669 | i = ((mem->card_start - region.start) >> 12) & 0x3fff; | 669 | i = ((mem->card_start - region.start) >> 12) & 0x3fff; |
670 | if (mem->flags & MAP_WRPROT) | 670 | if (mem->flags & MAP_WRPROT) |
671 | i |= I365_MEM_WRPROT; | 671 | i |= I365_MEM_WRPROT; |
672 | if (mem->flags & MAP_ATTRIB) { | 672 | if (mem->flags & MAP_ATTRIB) { |
673 | /* printk("requesting attribute memory for socket %i\n",sock);*/ | 673 | /* printk("requesting attribute memory for socket %i\n",sock);*/ |
674 | i |= I365_MEM_REG; | 674 | i |= I365_MEM_REG; |
675 | } else { | 675 | } else { |
676 | /* printk("requesting normal memory for socket %i\n",sock);*/ | 676 | /* printk("requesting normal memory for socket %i\n",sock);*/ |
677 | } | 677 | } |
678 | indirect_write16(sock,base+I365_W_OFF,i); | 678 | indirect_write16(sock,base+I365_W_OFF,i); |
679 | 679 | ||
680 | /* Enable the window if necessary */ | 680 | /* Enable the window if necessary */ |
681 | if (mem->flags & MAP_ACTIVE) | 681 | if (mem->flags & MAP_ACTIVE) |
682 | indirect_setbit(sock, I365_ADDRWIN, I365_ENA_MEM(map)); | 682 | indirect_setbit(sock, I365_ADDRWIN, I365_ENA_MEM(map)); |
683 | 683 | ||
684 | leave("i82092aa_set_mem_map"); | 684 | leave("i82092aa_set_mem_map"); |
685 | return 0; | 685 | return 0; |
686 | } | 686 | } |
687 | 687 | ||
688 | static int i82092aa_module_init(void) | 688 | static int i82092aa_module_init(void) |
689 | { | 689 | { |
690 | return pci_register_driver(&i82092aa_pci_driver); | 690 | return pci_register_driver(&i82092aa_pci_driver); |
691 | } | 691 | } |
692 | 692 | ||
693 | static void i82092aa_module_exit(void) | 693 | static void i82092aa_module_exit(void) |
694 | { | 694 | { |
695 | enter("i82092aa_module_exit"); | 695 | enter("i82092aa_module_exit"); |
696 | pci_unregister_driver(&i82092aa_pci_driver); | 696 | pci_unregister_driver(&i82092aa_pci_driver); |
697 | if (sockets[0].io_base>0) | 697 | if (sockets[0].io_base>0) |
698 | release_region(sockets[0].io_base, 2); | 698 | release_region(sockets[0].io_base, 2); |
699 | leave("i82092aa_module_exit"); | 699 | leave("i82092aa_module_exit"); |
700 | } | 700 | } |
701 | 701 | ||
702 | module_init(i82092aa_module_init); | 702 | module_init(i82092aa_module_init); |
703 | module_exit(i82092aa_module_exit); | 703 | module_exit(i82092aa_module_exit); |
704 | 704 | ||
705 | 705 |
drivers/pcmcia/pd6729.c
1 | /* | 1 | /* |
2 | * Driver for the Cirrus PD6729 PCI-PCMCIA bridge. | 2 | * Driver for the Cirrus PD6729 PCI-PCMCIA bridge. |
3 | * | 3 | * |
4 | * Based on the i82092.c driver. | 4 | * Based on the i82092.c driver. |
5 | * | 5 | * |
6 | * This software may be used and distributed according to the terms of | 6 | * This software may be used and distributed according to the terms of |
7 | * the GNU General Public License, incorporated herein by reference. | 7 | * the GNU General Public License, incorporated herein by reference. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/pci.h> | 13 | #include <linux/pci.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/workqueue.h> | 15 | #include <linux/workqueue.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/device.h> | 17 | #include <linux/device.h> |
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | 19 | ||
20 | #include <pcmcia/ss.h> | 20 | #include <pcmcia/ss.h> |
21 | 21 | ||
22 | 22 | ||
23 | #include "pd6729.h" | 23 | #include "pd6729.h" |
24 | #include "i82365.h" | 24 | #include "i82365.h" |
25 | #include "cirrus.h" | 25 | #include "cirrus.h" |
26 | 26 | ||
27 | MODULE_LICENSE("GPL"); | 27 | MODULE_LICENSE("GPL"); |
28 | MODULE_DESCRIPTION("Driver for the Cirrus PD6729 PCI-PCMCIA bridge"); | 28 | MODULE_DESCRIPTION("Driver for the Cirrus PD6729 PCI-PCMCIA bridge"); |
29 | MODULE_AUTHOR("Jun Komuro <komurojun-mbn@nifty.com>"); | 29 | MODULE_AUTHOR("Jun Komuro <komurojun-mbn@nifty.com>"); |
30 | 30 | ||
31 | #define MAX_SOCKETS 2 | 31 | #define MAX_SOCKETS 2 |
32 | 32 | ||
33 | /* | 33 | /* |
34 | * simple helper functions | 34 | * simple helper functions |
35 | * External clock time, in nanoseconds. 120 ns = 8.33 MHz | 35 | * External clock time, in nanoseconds. 120 ns = 8.33 MHz |
36 | */ | 36 | */ |
37 | #define to_cycles(ns) ((ns)/120) | 37 | #define to_cycles(ns) ((ns)/120) |
38 | 38 | ||
39 | #ifndef NO_IRQ | 39 | #ifndef NO_IRQ |
40 | #define NO_IRQ ((unsigned int)(0)) | 40 | #define NO_IRQ ((unsigned int)(0)) |
41 | #endif | 41 | #endif |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * PARAMETERS | 44 | * PARAMETERS |
45 | * irq_mode=n | 45 | * irq_mode=n |
46 | * Specifies the interrupt delivery mode. The default (1) is to use PCI | 46 | * Specifies the interrupt delivery mode. The default (1) is to use PCI |
47 | * interrupts; a value of 0 selects ISA interrupts. This must be set for | 47 | * interrupts; a value of 0 selects ISA interrupts. This must be set for |
48 | * correct operation of PCI card readers. | 48 | * correct operation of PCI card readers. |
49 | */ | 49 | */ |
50 | 50 | ||
51 | static int irq_mode = 1; /* 0 = ISA interrupt, 1 = PCI interrupt */ | 51 | static int irq_mode = 1; /* 0 = ISA interrupt, 1 = PCI interrupt */ |
52 | 52 | ||
53 | module_param(irq_mode, int, 0444); | 53 | module_param(irq_mode, int, 0444); |
54 | MODULE_PARM_DESC(irq_mode, | 54 | MODULE_PARM_DESC(irq_mode, |
55 | "interrupt delivery mode. 0 = ISA, 1 = PCI. default is 1"); | 55 | "interrupt delivery mode. 0 = ISA, 1 = PCI. default is 1"); |
56 | 56 | ||
57 | static DEFINE_SPINLOCK(port_lock); | 57 | static DEFINE_SPINLOCK(port_lock); |
58 | 58 | ||
59 | /* basic value read/write functions */ | 59 | /* basic value read/write functions */ |
60 | 60 | ||
61 | static unsigned char indirect_read(struct pd6729_socket *socket, | 61 | static unsigned char indirect_read(struct pd6729_socket *socket, |
62 | unsigned short reg) | 62 | unsigned short reg) |
63 | { | 63 | { |
64 | unsigned long port; | 64 | unsigned long port; |
65 | unsigned char val; | 65 | unsigned char val; |
66 | unsigned long flags; | 66 | unsigned long flags; |
67 | 67 | ||
68 | spin_lock_irqsave(&port_lock, flags); | 68 | spin_lock_irqsave(&port_lock, flags); |
69 | reg += socket->number * 0x40; | 69 | reg += socket->number * 0x40; |
70 | port = socket->io_base; | 70 | port = socket->io_base; |
71 | outb(reg, port); | 71 | outb(reg, port); |
72 | val = inb(port + 1); | 72 | val = inb(port + 1); |
73 | spin_unlock_irqrestore(&port_lock, flags); | 73 | spin_unlock_irqrestore(&port_lock, flags); |
74 | 74 | ||
75 | return val; | 75 | return val; |
76 | } | 76 | } |
77 | 77 | ||
78 | static unsigned short indirect_read16(struct pd6729_socket *socket, | 78 | static unsigned short indirect_read16(struct pd6729_socket *socket, |
79 | unsigned short reg) | 79 | unsigned short reg) |
80 | { | 80 | { |
81 | unsigned long port; | 81 | unsigned long port; |
82 | unsigned short tmp; | 82 | unsigned short tmp; |
83 | unsigned long flags; | 83 | unsigned long flags; |
84 | 84 | ||
85 | spin_lock_irqsave(&port_lock, flags); | 85 | spin_lock_irqsave(&port_lock, flags); |
86 | reg = reg + socket->number * 0x40; | 86 | reg = reg + socket->number * 0x40; |
87 | port = socket->io_base; | 87 | port = socket->io_base; |
88 | outb(reg, port); | 88 | outb(reg, port); |
89 | tmp = inb(port + 1); | 89 | tmp = inb(port + 1); |
90 | reg++; | 90 | reg++; |
91 | outb(reg, port); | 91 | outb(reg, port); |
92 | tmp = tmp | (inb(port + 1) << 8); | 92 | tmp = tmp | (inb(port + 1) << 8); |
93 | spin_unlock_irqrestore(&port_lock, flags); | 93 | spin_unlock_irqrestore(&port_lock, flags); |
94 | 94 | ||
95 | return tmp; | 95 | return tmp; |
96 | } | 96 | } |
97 | 97 | ||
98 | static void indirect_write(struct pd6729_socket *socket, unsigned short reg, | 98 | static void indirect_write(struct pd6729_socket *socket, unsigned short reg, |
99 | unsigned char value) | 99 | unsigned char value) |
100 | { | 100 | { |
101 | unsigned long port; | 101 | unsigned long port; |
102 | unsigned long flags; | 102 | unsigned long flags; |
103 | 103 | ||
104 | spin_lock_irqsave(&port_lock, flags); | 104 | spin_lock_irqsave(&port_lock, flags); |
105 | reg = reg + socket->number * 0x40; | 105 | reg = reg + socket->number * 0x40; |
106 | port = socket->io_base; | 106 | port = socket->io_base; |
107 | outb(reg, port); | 107 | outb(reg, port); |
108 | outb(value, port + 1); | 108 | outb(value, port + 1); |
109 | spin_unlock_irqrestore(&port_lock, flags); | 109 | spin_unlock_irqrestore(&port_lock, flags); |
110 | } | 110 | } |
111 | 111 | ||
112 | static void indirect_setbit(struct pd6729_socket *socket, unsigned short reg, | 112 | static void indirect_setbit(struct pd6729_socket *socket, unsigned short reg, |
113 | unsigned char mask) | 113 | unsigned char mask) |
114 | { | 114 | { |
115 | unsigned long port; | 115 | unsigned long port; |
116 | unsigned char val; | 116 | unsigned char val; |
117 | unsigned long flags; | 117 | unsigned long flags; |
118 | 118 | ||
119 | spin_lock_irqsave(&port_lock, flags); | 119 | spin_lock_irqsave(&port_lock, flags); |
120 | reg = reg + socket->number * 0x40; | 120 | reg = reg + socket->number * 0x40; |
121 | port = socket->io_base; | 121 | port = socket->io_base; |
122 | outb(reg, port); | 122 | outb(reg, port); |
123 | val = inb(port + 1); | 123 | val = inb(port + 1); |
124 | val |= mask; | 124 | val |= mask; |
125 | outb(reg, port); | 125 | outb(reg, port); |
126 | outb(val, port + 1); | 126 | outb(val, port + 1); |
127 | spin_unlock_irqrestore(&port_lock, flags); | 127 | spin_unlock_irqrestore(&port_lock, flags); |
128 | } | 128 | } |
129 | 129 | ||
130 | static void indirect_resetbit(struct pd6729_socket *socket, unsigned short reg, | 130 | static void indirect_resetbit(struct pd6729_socket *socket, unsigned short reg, |
131 | unsigned char mask) | 131 | unsigned char mask) |
132 | { | 132 | { |
133 | unsigned long port; | 133 | unsigned long port; |
134 | unsigned char val; | 134 | unsigned char val; |
135 | unsigned long flags; | 135 | unsigned long flags; |
136 | 136 | ||
137 | spin_lock_irqsave(&port_lock, flags); | 137 | spin_lock_irqsave(&port_lock, flags); |
138 | reg = reg + socket->number * 0x40; | 138 | reg = reg + socket->number * 0x40; |
139 | port = socket->io_base; | 139 | port = socket->io_base; |
140 | outb(reg, port); | 140 | outb(reg, port); |
141 | val = inb(port + 1); | 141 | val = inb(port + 1); |
142 | val &= ~mask; | 142 | val &= ~mask; |
143 | outb(reg, port); | 143 | outb(reg, port); |
144 | outb(val, port + 1); | 144 | outb(val, port + 1); |
145 | spin_unlock_irqrestore(&port_lock, flags); | 145 | spin_unlock_irqrestore(&port_lock, flags); |
146 | } | 146 | } |
147 | 147 | ||
148 | static void indirect_write16(struct pd6729_socket *socket, unsigned short reg, | 148 | static void indirect_write16(struct pd6729_socket *socket, unsigned short reg, |
149 | unsigned short value) | 149 | unsigned short value) |
150 | { | 150 | { |
151 | unsigned long port; | 151 | unsigned long port; |
152 | unsigned char val; | 152 | unsigned char val; |
153 | unsigned long flags; | 153 | unsigned long flags; |
154 | 154 | ||
155 | spin_lock_irqsave(&port_lock, flags); | 155 | spin_lock_irqsave(&port_lock, flags); |
156 | reg = reg + socket->number * 0x40; | 156 | reg = reg + socket->number * 0x40; |
157 | port = socket->io_base; | 157 | port = socket->io_base; |
158 | 158 | ||
159 | outb(reg, port); | 159 | outb(reg, port); |
160 | val = value & 255; | 160 | val = value & 255; |
161 | outb(val, port + 1); | 161 | outb(val, port + 1); |
162 | 162 | ||
163 | reg++; | 163 | reg++; |
164 | 164 | ||
165 | outb(reg, port); | 165 | outb(reg, port); |
166 | val = value >> 8; | 166 | val = value >> 8; |
167 | outb(val, port + 1); | 167 | outb(val, port + 1); |
168 | spin_unlock_irqrestore(&port_lock, flags); | 168 | spin_unlock_irqrestore(&port_lock, flags); |
169 | } | 169 | } |
170 | 170 | ||
171 | /* Interrupt handler functionality */ | 171 | /* Interrupt handler functionality */ |
172 | 172 | ||
173 | static irqreturn_t pd6729_interrupt(int irq, void *dev) | 173 | static irqreturn_t pd6729_interrupt(int irq, void *dev) |
174 | { | 174 | { |
175 | struct pd6729_socket *socket = (struct pd6729_socket *)dev; | 175 | struct pd6729_socket *socket = (struct pd6729_socket *)dev; |
176 | int i; | 176 | int i; |
177 | int loopcount = 0; | 177 | int loopcount = 0; |
178 | int handled = 0; | 178 | int handled = 0; |
179 | unsigned int events, active = 0; | 179 | unsigned int events, active = 0; |
180 | 180 | ||
181 | while (1) { | 181 | while (1) { |
182 | loopcount++; | 182 | loopcount++; |
183 | if (loopcount > 20) { | 183 | if (loopcount > 20) { |
184 | printk(KERN_ERR "pd6729: infinite eventloop " | 184 | printk(KERN_ERR "pd6729: infinite eventloop " |
185 | "in interrupt\n"); | 185 | "in interrupt\n"); |
186 | break; | 186 | break; |
187 | } | 187 | } |
188 | 188 | ||
189 | active = 0; | 189 | active = 0; |
190 | 190 | ||
191 | for (i = 0; i < MAX_SOCKETS; i++) { | 191 | for (i = 0; i < MAX_SOCKETS; i++) { |
192 | unsigned int csc; | 192 | unsigned int csc; |
193 | 193 | ||
194 | /* card status change register */ | 194 | /* card status change register */ |
195 | csc = indirect_read(&socket[i], I365_CSC); | 195 | csc = indirect_read(&socket[i], I365_CSC); |
196 | if (csc == 0) /* no events on this socket */ | 196 | if (csc == 0) /* no events on this socket */ |
197 | continue; | 197 | continue; |
198 | 198 | ||
199 | handled = 1; | 199 | handled = 1; |
200 | events = 0; | 200 | events = 0; |
201 | 201 | ||
202 | if (csc & I365_CSC_DETECT) { | 202 | if (csc & I365_CSC_DETECT) { |
203 | events |= SS_DETECT; | 203 | events |= SS_DETECT; |
204 | dev_vdbg(&socket[i].socket.dev, | 204 | dev_vdbg(&socket[i].socket.dev, |
205 | "Card detected in socket %i!\n", i); | 205 | "Card detected in socket %i!\n", i); |
206 | } | 206 | } |
207 | 207 | ||
208 | if (indirect_read(&socket[i], I365_INTCTL) | 208 | if (indirect_read(&socket[i], I365_INTCTL) |
209 | & I365_PC_IOCARD) { | 209 | & I365_PC_IOCARD) { |
210 | /* For IO/CARDS, bit 0 means "read the card" */ | 210 | /* For IO/CARDS, bit 0 means "read the card" */ |
211 | events |= (csc & I365_CSC_STSCHG) | 211 | events |= (csc & I365_CSC_STSCHG) |
212 | ? SS_STSCHG : 0; | 212 | ? SS_STSCHG : 0; |
213 | } else { | 213 | } else { |
214 | /* Check for battery/ready events */ | 214 | /* Check for battery/ready events */ |
215 | events |= (csc & I365_CSC_BVD1) | 215 | events |= (csc & I365_CSC_BVD1) |
216 | ? SS_BATDEAD : 0; | 216 | ? SS_BATDEAD : 0; |
217 | events |= (csc & I365_CSC_BVD2) | 217 | events |= (csc & I365_CSC_BVD2) |
218 | ? SS_BATWARN : 0; | 218 | ? SS_BATWARN : 0; |
219 | events |= (csc & I365_CSC_READY) | 219 | events |= (csc & I365_CSC_READY) |
220 | ? SS_READY : 0; | 220 | ? SS_READY : 0; |
221 | } | 221 | } |
222 | 222 | ||
223 | if (events) | 223 | if (events) |
224 | pcmcia_parse_events(&socket[i].socket, events); | 224 | pcmcia_parse_events(&socket[i].socket, events); |
225 | 225 | ||
226 | active |= events; | 226 | active |= events; |
227 | } | 227 | } |
228 | 228 | ||
229 | if (active == 0) /* no more events to handle */ | 229 | if (active == 0) /* no more events to handle */ |
230 | break; | 230 | break; |
231 | } | 231 | } |
232 | return IRQ_RETVAL(handled); | 232 | return IRQ_RETVAL(handled); |
233 | } | 233 | } |
234 | 234 | ||
235 | /* socket functions */ | 235 | /* socket functions */ |
236 | 236 | ||
237 | static void pd6729_interrupt_wrapper(unsigned long data) | 237 | static void pd6729_interrupt_wrapper(unsigned long data) |
238 | { | 238 | { |
239 | struct pd6729_socket *socket = (struct pd6729_socket *) data; | 239 | struct pd6729_socket *socket = (struct pd6729_socket *) data; |
240 | 240 | ||
241 | pd6729_interrupt(0, (void *)socket); | 241 | pd6729_interrupt(0, (void *)socket); |
242 | mod_timer(&socket->poll_timer, jiffies + HZ); | 242 | mod_timer(&socket->poll_timer, jiffies + HZ); |
243 | } | 243 | } |
244 | 244 | ||
245 | static int pd6729_get_status(struct pcmcia_socket *sock, u_int *value) | 245 | static int pd6729_get_status(struct pcmcia_socket *sock, u_int *value) |
246 | { | 246 | { |
247 | struct pd6729_socket *socket | 247 | struct pd6729_socket *socket |
248 | = container_of(sock, struct pd6729_socket, socket); | 248 | = container_of(sock, struct pd6729_socket, socket); |
249 | unsigned int status; | 249 | unsigned int status; |
250 | unsigned int data; | 250 | unsigned int data; |
251 | struct pd6729_socket *t; | 251 | struct pd6729_socket *t; |
252 | 252 | ||
253 | /* Interface Status Register */ | 253 | /* Interface Status Register */ |
254 | status = indirect_read(socket, I365_STATUS); | 254 | status = indirect_read(socket, I365_STATUS); |
255 | *value = 0; | 255 | *value = 0; |
256 | 256 | ||
257 | if ((status & I365_CS_DETECT) == I365_CS_DETECT) | 257 | if ((status & I365_CS_DETECT) == I365_CS_DETECT) |
258 | *value |= SS_DETECT; | 258 | *value |= SS_DETECT; |
259 | 259 | ||
260 | /* | 260 | /* |
261 | * IO cards have a different meaning of bits 0,1 | 261 | * IO cards have a different meaning of bits 0,1 |
262 | * Also notice the inverse-logic on the bits | 262 | * Also notice the inverse-logic on the bits |
263 | */ | 263 | */ |
264 | if (indirect_read(socket, I365_INTCTL) & I365_PC_IOCARD) { | 264 | if (indirect_read(socket, I365_INTCTL) & I365_PC_IOCARD) { |
265 | /* IO card */ | 265 | /* IO card */ |
266 | if (!(status & I365_CS_STSCHG)) | 266 | if (!(status & I365_CS_STSCHG)) |
267 | *value |= SS_STSCHG; | 267 | *value |= SS_STSCHG; |
268 | } else { | 268 | } else { |
269 | /* non I/O card */ | 269 | /* non I/O card */ |
270 | if (!(status & I365_CS_BVD1)) | 270 | if (!(status & I365_CS_BVD1)) |
271 | *value |= SS_BATDEAD; | 271 | *value |= SS_BATDEAD; |
272 | if (!(status & I365_CS_BVD2)) | 272 | if (!(status & I365_CS_BVD2)) |
273 | *value |= SS_BATWARN; | 273 | *value |= SS_BATWARN; |
274 | } | 274 | } |
275 | 275 | ||
276 | if (status & I365_CS_WRPROT) | 276 | if (status & I365_CS_WRPROT) |
277 | *value |= SS_WRPROT; /* card is write protected */ | 277 | *value |= SS_WRPROT; /* card is write protected */ |
278 | 278 | ||
279 | if (status & I365_CS_READY) | 279 | if (status & I365_CS_READY) |
280 | *value |= SS_READY; /* card is not busy */ | 280 | *value |= SS_READY; /* card is not busy */ |
281 | 281 | ||
282 | if (status & I365_CS_POWERON) | 282 | if (status & I365_CS_POWERON) |
283 | *value |= SS_POWERON; /* power is applied to the card */ | 283 | *value |= SS_POWERON; /* power is applied to the card */ |
284 | 284 | ||
285 | t = (socket->number) ? socket : socket + 1; | 285 | t = (socket->number) ? socket : socket + 1; |
286 | indirect_write(t, PD67_EXT_INDEX, PD67_EXTERN_DATA); | 286 | indirect_write(t, PD67_EXT_INDEX, PD67_EXTERN_DATA); |
287 | data = indirect_read16(t, PD67_EXT_DATA); | 287 | data = indirect_read16(t, PD67_EXT_DATA); |
288 | *value |= (data & PD67_EXD_VS1(socket->number)) ? 0 : SS_3VCARD; | 288 | *value |= (data & PD67_EXD_VS1(socket->number)) ? 0 : SS_3VCARD; |
289 | 289 | ||
290 | return 0; | 290 | return 0; |
291 | } | 291 | } |
292 | 292 | ||
293 | 293 | ||
294 | static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state) | 294 | static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state) |
295 | { | 295 | { |
296 | struct pd6729_socket *socket | 296 | struct pd6729_socket *socket |
297 | = container_of(sock, struct pd6729_socket, socket); | 297 | = container_of(sock, struct pd6729_socket, socket); |
298 | unsigned char reg, data; | 298 | unsigned char reg, data; |
299 | 299 | ||
300 | /* First, set the global controller options */ | 300 | /* First, set the global controller options */ |
301 | indirect_write(socket, I365_GBLCTL, 0x00); | 301 | indirect_write(socket, I365_GBLCTL, 0x00); |
302 | indirect_write(socket, I365_GENCTL, 0x00); | 302 | indirect_write(socket, I365_GENCTL, 0x00); |
303 | 303 | ||
304 | /* Values for the IGENC register */ | 304 | /* Values for the IGENC register */ |
305 | socket->card_irq = state->io_irq; | 305 | socket->card_irq = state->io_irq; |
306 | 306 | ||
307 | reg = 0; | 307 | reg = 0; |
308 | /* The reset bit has "inverse" logic */ | 308 | /* The reset bit has "inverse" logic */ |
309 | if (!(state->flags & SS_RESET)) | 309 | if (!(state->flags & SS_RESET)) |
310 | reg |= I365_PC_RESET; | 310 | reg |= I365_PC_RESET; |
311 | if (state->flags & SS_IOCARD) | 311 | if (state->flags & SS_IOCARD) |
312 | reg |= I365_PC_IOCARD; | 312 | reg |= I365_PC_IOCARD; |
313 | 313 | ||
314 | /* IGENC, Interrupt and General Control Register */ | 314 | /* IGENC, Interrupt and General Control Register */ |
315 | indirect_write(socket, I365_INTCTL, reg); | 315 | indirect_write(socket, I365_INTCTL, reg); |
316 | 316 | ||
317 | /* Power registers */ | 317 | /* Power registers */ |
318 | 318 | ||
319 | reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */ | 319 | reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */ |
320 | 320 | ||
321 | if (state->flags & SS_PWR_AUTO) { | 321 | if (state->flags & SS_PWR_AUTO) { |
322 | dev_dbg(&sock->dev, "Auto power\n"); | 322 | dev_dbg(&sock->dev, "Auto power\n"); |
323 | reg |= I365_PWR_AUTO; /* automatic power mngmnt */ | 323 | reg |= I365_PWR_AUTO; /* automatic power mngmnt */ |
324 | } | 324 | } |
325 | if (state->flags & SS_OUTPUT_ENA) { | 325 | if (state->flags & SS_OUTPUT_ENA) { |
326 | dev_dbg(&sock->dev, "Power Enabled\n"); | 326 | dev_dbg(&sock->dev, "Power Enabled\n"); |
327 | reg |= I365_PWR_OUT; /* enable power */ | 327 | reg |= I365_PWR_OUT; /* enable power */ |
328 | } | 328 | } |
329 | 329 | ||
330 | switch (state->Vcc) { | 330 | switch (state->Vcc) { |
331 | case 0: | 331 | case 0: |
332 | break; | 332 | break; |
333 | case 33: | 333 | case 33: |
334 | dev_dbg(&sock->dev, | 334 | dev_dbg(&sock->dev, |
335 | "setting voltage to Vcc to 3.3V on socket %i\n", | 335 | "setting voltage to Vcc to 3.3V on socket %i\n", |
336 | socket->number); | 336 | socket->number); |
337 | reg |= I365_VCC_5V; | 337 | reg |= I365_VCC_5V; |
338 | indirect_setbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); | 338 | indirect_setbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); |
339 | break; | 339 | break; |
340 | case 50: | 340 | case 50: |
341 | dev_dbg(&sock->dev, | 341 | dev_dbg(&sock->dev, |
342 | "setting voltage to Vcc to 5V on socket %i\n", | 342 | "setting voltage to Vcc to 5V on socket %i\n", |
343 | socket->number); | 343 | socket->number); |
344 | reg |= I365_VCC_5V; | 344 | reg |= I365_VCC_5V; |
345 | indirect_resetbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); | 345 | indirect_resetbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); |
346 | break; | 346 | break; |
347 | default: | 347 | default: |
348 | dev_dbg(&sock->dev, | 348 | dev_dbg(&sock->dev, |
349 | "pd6729_set_socket called with invalid VCC power " | 349 | "pd6729_set_socket called with invalid VCC power " |
350 | "value: %i\n", state->Vcc); | 350 | "value: %i\n", state->Vcc); |
351 | return -EINVAL; | 351 | return -EINVAL; |
352 | } | 352 | } |
353 | 353 | ||
354 | switch (state->Vpp) { | 354 | switch (state->Vpp) { |
355 | case 0: | 355 | case 0: |
356 | dev_dbg(&sock->dev, "not setting Vpp on socket %i\n", | 356 | dev_dbg(&sock->dev, "not setting Vpp on socket %i\n", |
357 | socket->number); | 357 | socket->number); |
358 | break; | 358 | break; |
359 | case 33: | 359 | case 33: |
360 | case 50: | 360 | case 50: |
361 | dev_dbg(&sock->dev, "setting Vpp to Vcc for socket %i\n", | 361 | dev_dbg(&sock->dev, "setting Vpp to Vcc for socket %i\n", |
362 | socket->number); | 362 | socket->number); |
363 | reg |= I365_VPP1_5V; | 363 | reg |= I365_VPP1_5V; |
364 | break; | 364 | break; |
365 | case 120: | 365 | case 120: |
366 | dev_dbg(&sock->dev, "setting Vpp to 12.0\n"); | 366 | dev_dbg(&sock->dev, "setting Vpp to 12.0\n"); |
367 | reg |= I365_VPP1_12V; | 367 | reg |= I365_VPP1_12V; |
368 | break; | 368 | break; |
369 | default: | 369 | default: |
370 | dev_dbg(&sock->dev, "pd6729: pd6729_set_socket called with " | 370 | dev_dbg(&sock->dev, "pd6729: pd6729_set_socket called with " |
371 | "invalid VPP power value: %i\n", state->Vpp); | 371 | "invalid VPP power value: %i\n", state->Vpp); |
372 | return -EINVAL; | 372 | return -EINVAL; |
373 | } | 373 | } |
374 | 374 | ||
375 | /* only write if changed */ | 375 | /* only write if changed */ |
376 | if (reg != indirect_read(socket, I365_POWER)) | 376 | if (reg != indirect_read(socket, I365_POWER)) |
377 | indirect_write(socket, I365_POWER, reg); | 377 | indirect_write(socket, I365_POWER, reg); |
378 | 378 | ||
379 | if (irq_mode == 1) { | 379 | if (irq_mode == 1) { |
380 | /* all interrupts are to be done as PCI interrupts */ | 380 | /* all interrupts are to be done as PCI interrupts */ |
381 | data = PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ; | 381 | data = PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ; |
382 | } else | 382 | } else |
383 | data = 0; | 383 | data = 0; |
384 | 384 | ||
385 | indirect_write(socket, PD67_EXT_INDEX, PD67_EXT_CTL_1); | 385 | indirect_write(socket, PD67_EXT_INDEX, PD67_EXT_CTL_1); |
386 | indirect_write(socket, PD67_EXT_DATA, data); | 386 | indirect_write(socket, PD67_EXT_DATA, data); |
387 | 387 | ||
388 | /* Enable specific interrupt events */ | 388 | /* Enable specific interrupt events */ |
389 | 389 | ||
390 | reg = 0x00; | 390 | reg = 0x00; |
391 | if (state->csc_mask & SS_DETECT) | 391 | if (state->csc_mask & SS_DETECT) |
392 | reg |= I365_CSC_DETECT; | 392 | reg |= I365_CSC_DETECT; |
393 | 393 | ||
394 | if (state->flags & SS_IOCARD) { | 394 | if (state->flags & SS_IOCARD) { |
395 | if (state->csc_mask & SS_STSCHG) | 395 | if (state->csc_mask & SS_STSCHG) |
396 | reg |= I365_CSC_STSCHG; | 396 | reg |= I365_CSC_STSCHG; |
397 | } else { | 397 | } else { |
398 | if (state->csc_mask & SS_BATDEAD) | 398 | if (state->csc_mask & SS_BATDEAD) |
399 | reg |= I365_CSC_BVD1; | 399 | reg |= I365_CSC_BVD1; |
400 | if (state->csc_mask & SS_BATWARN) | 400 | if (state->csc_mask & SS_BATWARN) |
401 | reg |= I365_CSC_BVD2; | 401 | reg |= I365_CSC_BVD2; |
402 | if (state->csc_mask & SS_READY) | 402 | if (state->csc_mask & SS_READY) |
403 | reg |= I365_CSC_READY; | 403 | reg |= I365_CSC_READY; |
404 | } | 404 | } |
405 | if (irq_mode == 1) | 405 | if (irq_mode == 1) |
406 | reg |= 0x30; /* management IRQ: PCI INTA# = "irq 3" */ | 406 | reg |= 0x30; /* management IRQ: PCI INTA# = "irq 3" */ |
407 | indirect_write(socket, I365_CSCINT, reg); | 407 | indirect_write(socket, I365_CSCINT, reg); |
408 | 408 | ||
409 | reg = indirect_read(socket, I365_INTCTL); | 409 | reg = indirect_read(socket, I365_INTCTL); |
410 | if (irq_mode == 1) | 410 | if (irq_mode == 1) |
411 | reg |= 0x03; /* card IRQ: PCI INTA# = "irq 3" */ | 411 | reg |= 0x03; /* card IRQ: PCI INTA# = "irq 3" */ |
412 | else | 412 | else |
413 | reg |= socket->card_irq; | 413 | reg |= socket->card_irq; |
414 | indirect_write(socket, I365_INTCTL, reg); | 414 | indirect_write(socket, I365_INTCTL, reg); |
415 | 415 | ||
416 | /* now clear the (probably bogus) pending stuff by doing a dummy read */ | 416 | /* now clear the (probably bogus) pending stuff by doing a dummy read */ |
417 | (void)indirect_read(socket, I365_CSC); | 417 | (void)indirect_read(socket, I365_CSC); |
418 | 418 | ||
419 | return 0; | 419 | return 0; |
420 | } | 420 | } |
421 | 421 | ||
422 | static int pd6729_set_io_map(struct pcmcia_socket *sock, | 422 | static int pd6729_set_io_map(struct pcmcia_socket *sock, |
423 | struct pccard_io_map *io) | 423 | struct pccard_io_map *io) |
424 | { | 424 | { |
425 | struct pd6729_socket *socket | 425 | struct pd6729_socket *socket |
426 | = container_of(sock, struct pd6729_socket, socket); | 426 | = container_of(sock, struct pd6729_socket, socket); |
427 | unsigned char map, ioctl; | 427 | unsigned char map, ioctl; |
428 | 428 | ||
429 | map = io->map; | 429 | map = io->map; |
430 | 430 | ||
431 | /* Check error conditions */ | 431 | /* Check error conditions */ |
432 | if (map > 1) { | 432 | if (map > 1) { |
433 | dev_dbg(&sock->dev, "pd6729_set_io_map with invalid map\n"); | 433 | dev_dbg(&sock->dev, "pd6729_set_io_map with invalid map\n"); |
434 | return -EINVAL; | 434 | return -EINVAL; |
435 | } | 435 | } |
436 | 436 | ||
437 | /* Turn off the window before changing anything */ | 437 | /* Turn off the window before changing anything */ |
438 | if (indirect_read(socket, I365_ADDRWIN) & I365_ENA_IO(map)) | 438 | if (indirect_read(socket, I365_ADDRWIN) & I365_ENA_IO(map)) |
439 | indirect_resetbit(socket, I365_ADDRWIN, I365_ENA_IO(map)); | 439 | indirect_resetbit(socket, I365_ADDRWIN, I365_ENA_IO(map)); |
440 | 440 | ||
441 | /* dev_dbg(&sock->dev, "set_io_map: Setting range to %x - %x\n", | 441 | /* dev_dbg(&sock->dev, "set_io_map: Setting range to %x - %x\n", |
442 | io->start, io->stop);*/ | 442 | io->start, io->stop);*/ |
443 | 443 | ||
444 | /* write the new values */ | 444 | /* write the new values */ |
445 | indirect_write16(socket, I365_IO(map)+I365_W_START, io->start); | 445 | indirect_write16(socket, I365_IO(map)+I365_W_START, io->start); |
446 | indirect_write16(socket, I365_IO(map)+I365_W_STOP, io->stop); | 446 | indirect_write16(socket, I365_IO(map)+I365_W_STOP, io->stop); |
447 | 447 | ||
448 | ioctl = indirect_read(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map); | 448 | ioctl = indirect_read(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map); |
449 | 449 | ||
450 | if (io->flags & MAP_0WS) | 450 | if (io->flags & MAP_0WS) |
451 | ioctl |= I365_IOCTL_0WS(map); | 451 | ioctl |= I365_IOCTL_0WS(map); |
452 | if (io->flags & MAP_16BIT) | 452 | if (io->flags & MAP_16BIT) |
453 | ioctl |= I365_IOCTL_16BIT(map); | 453 | ioctl |= I365_IOCTL_16BIT(map); |
454 | if (io->flags & MAP_AUTOSZ) | 454 | if (io->flags & MAP_AUTOSZ) |
455 | ioctl |= I365_IOCTL_IOCS16(map); | 455 | ioctl |= I365_IOCTL_IOCS16(map); |
456 | 456 | ||
457 | indirect_write(socket, I365_IOCTL, ioctl); | 457 | indirect_write(socket, I365_IOCTL, ioctl); |
458 | 458 | ||
459 | /* Turn the window back on if needed */ | 459 | /* Turn the window back on if needed */ |
460 | if (io->flags & MAP_ACTIVE) | 460 | if (io->flags & MAP_ACTIVE) |
461 | indirect_setbit(socket, I365_ADDRWIN, I365_ENA_IO(map)); | 461 | indirect_setbit(socket, I365_ADDRWIN, I365_ENA_IO(map)); |
462 | 462 | ||
463 | return 0; | 463 | return 0; |
464 | } | 464 | } |
465 | 465 | ||
466 | static int pd6729_set_mem_map(struct pcmcia_socket *sock, | 466 | static int pd6729_set_mem_map(struct pcmcia_socket *sock, |
467 | struct pccard_mem_map *mem) | 467 | struct pccard_mem_map *mem) |
468 | { | 468 | { |
469 | struct pd6729_socket *socket | 469 | struct pd6729_socket *socket |
470 | = container_of(sock, struct pd6729_socket, socket); | 470 | = container_of(sock, struct pd6729_socket, socket); |
471 | unsigned short base, i; | 471 | unsigned short base, i; |
472 | unsigned char map; | 472 | unsigned char map; |
473 | 473 | ||
474 | map = mem->map; | 474 | map = mem->map; |
475 | if (map > 4) { | 475 | if (map > 4) { |
476 | dev_warn(&sock->dev, "invalid map requested\n"); | 476 | dev_warn(&sock->dev, "invalid map requested\n"); |
477 | return -EINVAL; | 477 | return -EINVAL; |
478 | } | 478 | } |
479 | 479 | ||
480 | if ((mem->res->start > mem->res->end) || (mem->speed > 1000)) { | 480 | if ((mem->res->start > mem->res->end) || (mem->speed > 1000)) { |
481 | dev_warn(&sock->dev, "invalid invalid address / speed\n"); | 481 | dev_warn(&sock->dev, "invalid invalid address / speed\n"); |
482 | return -EINVAL; | 482 | return -EINVAL; |
483 | } | 483 | } |
484 | 484 | ||
485 | /* Turn off the window before changing anything */ | 485 | /* Turn off the window before changing anything */ |
486 | if (indirect_read(socket, I365_ADDRWIN) & I365_ENA_MEM(map)) | 486 | if (indirect_read(socket, I365_ADDRWIN) & I365_ENA_MEM(map)) |
487 | indirect_resetbit(socket, I365_ADDRWIN, I365_ENA_MEM(map)); | 487 | indirect_resetbit(socket, I365_ADDRWIN, I365_ENA_MEM(map)); |
488 | 488 | ||
489 | /* write the start address */ | 489 | /* write the start address */ |
490 | base = I365_MEM(map); | 490 | base = I365_MEM(map); |
491 | i = (mem->res->start >> 12) & 0x0fff; | 491 | i = (mem->res->start >> 12) & 0x0fff; |
492 | if (mem->flags & MAP_16BIT) | 492 | if (mem->flags & MAP_16BIT) |
493 | i |= I365_MEM_16BIT; | 493 | i |= I365_MEM_16BIT; |
494 | if (mem->flags & MAP_0WS) | 494 | if (mem->flags & MAP_0WS) |
495 | i |= I365_MEM_0WS; | 495 | i |= I365_MEM_0WS; |
496 | indirect_write16(socket, base + I365_W_START, i); | 496 | indirect_write16(socket, base + I365_W_START, i); |
497 | 497 | ||
498 | /* write the stop address */ | 498 | /* write the stop address */ |
499 | 499 | ||
500 | i = (mem->res->end >> 12) & 0x0fff; | 500 | i = (mem->res->end >> 12) & 0x0fff; |
501 | switch (to_cycles(mem->speed)) { | 501 | switch (to_cycles(mem->speed)) { |
502 | case 0: | 502 | case 0: |
503 | break; | 503 | break; |
504 | case 1: | 504 | case 1: |
505 | i |= I365_MEM_WS0; | 505 | i |= I365_MEM_WS0; |
506 | break; | 506 | break; |
507 | case 2: | 507 | case 2: |
508 | i |= I365_MEM_WS1; | 508 | i |= I365_MEM_WS1; |
509 | break; | 509 | break; |
510 | default: | 510 | default: |
511 | i |= I365_MEM_WS1 | I365_MEM_WS0; | 511 | i |= I365_MEM_WS1 | I365_MEM_WS0; |
512 | break; | 512 | break; |
513 | } | 513 | } |
514 | 514 | ||
515 | indirect_write16(socket, base + I365_W_STOP, i); | 515 | indirect_write16(socket, base + I365_W_STOP, i); |
516 | 516 | ||
517 | /* Take care of high byte */ | 517 | /* Take care of high byte */ |
518 | indirect_write(socket, PD67_EXT_INDEX, PD67_MEM_PAGE(map)); | 518 | indirect_write(socket, PD67_EXT_INDEX, PD67_MEM_PAGE(map)); |
519 | indirect_write(socket, PD67_EXT_DATA, mem->res->start >> 24); | 519 | indirect_write(socket, PD67_EXT_DATA, mem->res->start >> 24); |
520 | 520 | ||
521 | /* card start */ | 521 | /* card start */ |
522 | 522 | ||
523 | i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff; | 523 | i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff; |
524 | if (mem->flags & MAP_WRPROT) | 524 | if (mem->flags & MAP_WRPROT) |
525 | i |= I365_MEM_WRPROT; | 525 | i |= I365_MEM_WRPROT; |
526 | if (mem->flags & MAP_ATTRIB) { | 526 | if (mem->flags & MAP_ATTRIB) { |
527 | /* dev_dbg(&sock->dev, "requesting attribute memory for " | 527 | /* dev_dbg(&sock->dev, "requesting attribute memory for " |
528 | "socket %i\n", socket->number);*/ | 528 | "socket %i\n", socket->number);*/ |
529 | i |= I365_MEM_REG; | 529 | i |= I365_MEM_REG; |
530 | } else { | 530 | } else { |
531 | /* dev_dbg(&sock->dev, "requesting normal memory for " | 531 | /* dev_dbg(&sock->dev, "requesting normal memory for " |
532 | "socket %i\n", socket->number);*/ | 532 | "socket %i\n", socket->number);*/ |
533 | } | 533 | } |
534 | indirect_write16(socket, base + I365_W_OFF, i); | 534 | indirect_write16(socket, base + I365_W_OFF, i); |
535 | 535 | ||
536 | /* Enable the window if necessary */ | 536 | /* Enable the window if necessary */ |
537 | if (mem->flags & MAP_ACTIVE) | 537 | if (mem->flags & MAP_ACTIVE) |
538 | indirect_setbit(socket, I365_ADDRWIN, I365_ENA_MEM(map)); | 538 | indirect_setbit(socket, I365_ADDRWIN, I365_ENA_MEM(map)); |
539 | 539 | ||
540 | return 0; | 540 | return 0; |
541 | } | 541 | } |
542 | 542 | ||
543 | static int pd6729_init(struct pcmcia_socket *sock) | 543 | static int pd6729_init(struct pcmcia_socket *sock) |
544 | { | 544 | { |
545 | int i; | 545 | int i; |
546 | struct resource res = { .end = 0x0fff }; | 546 | struct resource res = { .end = 0x0fff }; |
547 | pccard_io_map io = { 0, 0, 0, 0, 1 }; | 547 | pccard_io_map io = { 0, 0, 0, 0, 1 }; |
548 | pccard_mem_map mem = { .res = &res, }; | 548 | pccard_mem_map mem = { .res = &res, }; |
549 | 549 | ||
550 | pd6729_set_socket(sock, &dead_socket); | 550 | pd6729_set_socket(sock, &dead_socket); |
551 | for (i = 0; i < 2; i++) { | 551 | for (i = 0; i < 2; i++) { |
552 | io.map = i; | 552 | io.map = i; |
553 | pd6729_set_io_map(sock, &io); | 553 | pd6729_set_io_map(sock, &io); |
554 | } | 554 | } |
555 | for (i = 0; i < 5; i++) { | 555 | for (i = 0; i < 5; i++) { |
556 | mem.map = i; | 556 | mem.map = i; |
557 | pd6729_set_mem_map(sock, &mem); | 557 | pd6729_set_mem_map(sock, &mem); |
558 | } | 558 | } |
559 | 559 | ||
560 | return 0; | 560 | return 0; |
561 | } | 561 | } |
562 | 562 | ||
563 | 563 | ||
564 | /* the pccard structure and its functions */ | 564 | /* the pccard structure and its functions */ |
565 | static struct pccard_operations pd6729_operations = { | 565 | static struct pccard_operations pd6729_operations = { |
566 | .init = pd6729_init, | 566 | .init = pd6729_init, |
567 | .get_status = pd6729_get_status, | 567 | .get_status = pd6729_get_status, |
568 | .set_socket = pd6729_set_socket, | 568 | .set_socket = pd6729_set_socket, |
569 | .set_io_map = pd6729_set_io_map, | 569 | .set_io_map = pd6729_set_io_map, |
570 | .set_mem_map = pd6729_set_mem_map, | 570 | .set_mem_map = pd6729_set_mem_map, |
571 | }; | 571 | }; |
572 | 572 | ||
573 | static irqreturn_t pd6729_test(int irq, void *dev) | 573 | static irqreturn_t pd6729_test(int irq, void *dev) |
574 | { | 574 | { |
575 | pr_devel("-> hit on irq %d\n", irq); | 575 | pr_devel("-> hit on irq %d\n", irq); |
576 | return IRQ_HANDLED; | 576 | return IRQ_HANDLED; |
577 | } | 577 | } |
578 | 578 | ||
579 | static int pd6729_check_irq(int irq) | 579 | static int pd6729_check_irq(int irq) |
580 | { | 580 | { |
581 | int ret; | 581 | int ret; |
582 | 582 | ||
583 | ret = request_irq(irq, pd6729_test, IRQF_PROBE_SHARED, "x", | 583 | ret = request_irq(irq, pd6729_test, IRQF_PROBE_SHARED, "x", |
584 | pd6729_test); | 584 | pd6729_test); |
585 | if (ret) | 585 | if (ret) |
586 | return -1; | 586 | return -1; |
587 | 587 | ||
588 | free_irq(irq, pd6729_test); | 588 | free_irq(irq, pd6729_test); |
589 | return 0; | 589 | return 0; |
590 | } | 590 | } |
591 | 591 | ||
592 | static u_int pd6729_isa_scan(void) | 592 | static u_int pd6729_isa_scan(void) |
593 | { | 593 | { |
594 | u_int mask0, mask = 0; | 594 | u_int mask0, mask = 0; |
595 | int i; | 595 | int i; |
596 | 596 | ||
597 | if (irq_mode == 1) { | 597 | if (irq_mode == 1) { |
598 | printk(KERN_INFO "pd6729: PCI card interrupts, " | 598 | printk(KERN_INFO "pd6729: PCI card interrupts, " |
599 | "PCI status changes\n"); | 599 | "PCI status changes\n"); |
600 | return 0; | 600 | return 0; |
601 | } | 601 | } |
602 | 602 | ||
603 | mask0 = PD67_MASK; | 603 | mask0 = PD67_MASK; |
604 | 604 | ||
605 | /* just find interrupts that aren't in use */ | 605 | /* just find interrupts that aren't in use */ |
606 | for (i = 0; i < 16; i++) | 606 | for (i = 0; i < 16; i++) |
607 | if ((mask0 & (1 << i)) && (pd6729_check_irq(i) == 0)) | 607 | if ((mask0 & (1 << i)) && (pd6729_check_irq(i) == 0)) |
608 | mask |= (1 << i); | 608 | mask |= (1 << i); |
609 | 609 | ||
610 | printk(KERN_INFO "pd6729: ISA irqs = "); | 610 | printk(KERN_INFO "pd6729: ISA irqs = "); |
611 | for (i = 0; i < 16; i++) | 611 | for (i = 0; i < 16; i++) |
612 | if (mask & (1<<i)) | 612 | if (mask & (1<<i)) |
613 | printk("%s%d", ((mask & ((1<<i)-1)) ? "," : ""), i); | 613 | printk("%s%d", ((mask & ((1<<i)-1)) ? "," : ""), i); |
614 | 614 | ||
615 | if (mask == 0) | 615 | if (mask == 0) |
616 | printk("none!"); | 616 | printk("none!"); |
617 | else | 617 | else |
618 | printk(" polling status changes.\n"); | 618 | printk(" polling status changes.\n"); |
619 | 619 | ||
620 | return mask; | 620 | return mask; |
621 | } | 621 | } |
622 | 622 | ||
623 | static int pd6729_pci_probe(struct pci_dev *dev, | 623 | static int pd6729_pci_probe(struct pci_dev *dev, |
624 | const struct pci_device_id *id) | 624 | const struct pci_device_id *id) |
625 | { | 625 | { |
626 | int i, j, ret; | 626 | int i, j, ret; |
627 | u_int mask; | 627 | u_int mask; |
628 | char configbyte; | 628 | char configbyte; |
629 | struct pd6729_socket *socket; | 629 | struct pd6729_socket *socket; |
630 | 630 | ||
631 | socket = kzalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS, | 631 | socket = kzalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS, |
632 | GFP_KERNEL); | 632 | GFP_KERNEL); |
633 | if (!socket) { | 633 | if (!socket) { |
634 | dev_warn(&dev->dev, "failed to kzalloc socket.\n"); | 634 | dev_warn(&dev->dev, "failed to kzalloc socket.\n"); |
635 | return -ENOMEM; | 635 | return -ENOMEM; |
636 | } | 636 | } |
637 | 637 | ||
638 | ret = pci_enable_device(dev); | 638 | ret = pci_enable_device(dev); |
639 | if (ret) { | 639 | if (ret) { |
640 | dev_warn(&dev->dev, "failed to enable pci_device.\n"); | 640 | dev_warn(&dev->dev, "failed to enable pci_device.\n"); |
641 | goto err_out_free_mem; | 641 | goto err_out_free_mem; |
642 | } | 642 | } |
643 | 643 | ||
644 | if (!pci_resource_start(dev, 0)) { | 644 | if (!pci_resource_start(dev, 0)) { |
645 | dev_warn(&dev->dev, "refusing to load the driver as the " | 645 | dev_warn(&dev->dev, "refusing to load the driver as the " |
646 | "io_base is NULL.\n"); | 646 | "io_base is NULL.\n"); |
647 | ret = -ENOMEM; | 647 | ret = -ENOMEM; |
648 | goto err_out_disable; | 648 | goto err_out_disable; |
649 | } | 649 | } |
650 | 650 | ||
651 | dev_info(&dev->dev, "Cirrus PD6729 PCI to PCMCIA Bridge at 0x%llx " | 651 | dev_info(&dev->dev, "Cirrus PD6729 PCI to PCMCIA Bridge at 0x%llx " |
652 | "on irq %d\n", | 652 | "on irq %d\n", |
653 | (unsigned long long)pci_resource_start(dev, 0), dev->irq); | 653 | (unsigned long long)pci_resource_start(dev, 0), dev->irq); |
654 | /* | 654 | /* |
655 | * Since we have no memory BARs some firmware may not | 655 | * Since we have no memory BARs some firmware may not |
656 | * have had PCI_COMMAND_MEMORY enabled, yet the device needs it. | 656 | * have had PCI_COMMAND_MEMORY enabled, yet the device needs it. |
657 | */ | 657 | */ |
658 | pci_read_config_byte(dev, PCI_COMMAND, &configbyte); | 658 | pci_read_config_byte(dev, PCI_COMMAND, &configbyte); |
659 | if (!(configbyte & PCI_COMMAND_MEMORY)) { | 659 | if (!(configbyte & PCI_COMMAND_MEMORY)) { |
660 | dev_dbg(&dev->dev, "pd6729: Enabling PCI_COMMAND_MEMORY.\n"); | 660 | dev_dbg(&dev->dev, "pd6729: Enabling PCI_COMMAND_MEMORY.\n"); |
661 | configbyte |= PCI_COMMAND_MEMORY; | 661 | configbyte |= PCI_COMMAND_MEMORY; |
662 | pci_write_config_byte(dev, PCI_COMMAND, configbyte); | 662 | pci_write_config_byte(dev, PCI_COMMAND, configbyte); |
663 | } | 663 | } |
664 | 664 | ||
665 | ret = pci_request_regions(dev, "pd6729"); | 665 | ret = pci_request_regions(dev, "pd6729"); |
666 | if (ret) { | 666 | if (ret) { |
667 | dev_warn(&dev->dev, "pci request region failed.\n"); | 667 | dev_warn(&dev->dev, "pci request region failed.\n"); |
668 | goto err_out_disable; | 668 | goto err_out_disable; |
669 | } | 669 | } |
670 | 670 | ||
671 | if (dev->irq == NO_IRQ) | 671 | if (dev->irq == NO_IRQ) |
672 | irq_mode = 0; /* fall back to ISA interrupt mode */ | 672 | irq_mode = 0; /* fall back to ISA interrupt mode */ |
673 | 673 | ||
674 | mask = pd6729_isa_scan(); | 674 | mask = pd6729_isa_scan(); |
675 | if (irq_mode == 0 && mask == 0) { | 675 | if (irq_mode == 0 && mask == 0) { |
676 | dev_warn(&dev->dev, "no ISA interrupt is available.\n"); | 676 | dev_warn(&dev->dev, "no ISA interrupt is available.\n"); |
677 | ret = -ENODEV; | 677 | ret = -ENODEV; |
678 | goto err_out_free_res; | 678 | goto err_out_free_res; |
679 | } | 679 | } |
680 | 680 | ||
681 | for (i = 0; i < MAX_SOCKETS; i++) { | 681 | for (i = 0; i < MAX_SOCKETS; i++) { |
682 | socket[i].io_base = pci_resource_start(dev, 0); | 682 | socket[i].io_base = pci_resource_start(dev, 0); |
683 | socket[i].socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD; | 683 | socket[i].socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD; |
684 | socket[i].socket.map_size = 0x1000; | 684 | socket[i].socket.map_size = 0x1000; |
685 | socket[i].socket.irq_mask = mask; | 685 | socket[i].socket.irq_mask = mask; |
686 | socket[i].socket.pci_irq = dev->irq; | 686 | socket[i].socket.pci_irq = dev->irq; |
687 | socket[i].socket.cb_dev = dev; | 687 | socket[i].socket.cb_dev = dev; |
688 | socket[i].socket.owner = THIS_MODULE; | 688 | socket[i].socket.owner = THIS_MODULE; |
689 | 689 | ||
690 | socket[i].number = i; | 690 | socket[i].number = i; |
691 | 691 | ||
692 | socket[i].socket.ops = &pd6729_operations; | 692 | socket[i].socket.ops = &pd6729_operations; |
693 | socket[i].socket.resource_ops = &pccard_nonstatic_ops; | 693 | socket[i].socket.resource_ops = &pccard_nonstatic_ops; |
694 | socket[i].socket.dev.parent = &dev->dev; | 694 | socket[i].socket.dev.parent = &dev->dev; |
695 | socket[i].socket.driver_data = &socket[i]; | 695 | socket[i].socket.driver_data = &socket[i]; |
696 | } | 696 | } |
697 | 697 | ||
698 | pci_set_drvdata(dev, socket); | 698 | pci_set_drvdata(dev, socket); |
699 | if (irq_mode == 1) { | 699 | if (irq_mode == 1) { |
700 | /* Register the interrupt handler */ | 700 | /* Register the interrupt handler */ |
701 | ret = request_irq(dev->irq, pd6729_interrupt, IRQF_SHARED, | 701 | ret = request_irq(dev->irq, pd6729_interrupt, IRQF_SHARED, |
702 | "pd6729", socket); | 702 | "pd6729", socket); |
703 | if (ret) { | 703 | if (ret) { |
704 | dev_err(&dev->dev, "Failed to register irq %d\n", | 704 | dev_err(&dev->dev, "Failed to register irq %d\n", |
705 | dev->irq); | 705 | dev->irq); |
706 | goto err_out_free_res; | 706 | goto err_out_free_res; |
707 | } | 707 | } |
708 | } else { | 708 | } else { |
709 | /* poll Card status change */ | 709 | /* poll Card status change */ |
710 | init_timer(&socket->poll_timer); | 710 | init_timer(&socket->poll_timer); |
711 | socket->poll_timer.function = pd6729_interrupt_wrapper; | 711 | socket->poll_timer.function = pd6729_interrupt_wrapper; |
712 | socket->poll_timer.data = (unsigned long)socket; | 712 | socket->poll_timer.data = (unsigned long)socket; |
713 | socket->poll_timer.expires = jiffies + HZ; | 713 | socket->poll_timer.expires = jiffies + HZ; |
714 | add_timer(&socket->poll_timer); | 714 | add_timer(&socket->poll_timer); |
715 | } | 715 | } |
716 | 716 | ||
717 | for (i = 0; i < MAX_SOCKETS; i++) { | 717 | for (i = 0; i < MAX_SOCKETS; i++) { |
718 | ret = pcmcia_register_socket(&socket[i].socket); | 718 | ret = pcmcia_register_socket(&socket[i].socket); |
719 | if (ret) { | 719 | if (ret) { |
720 | dev_warn(&dev->dev, "pcmcia_register_socket failed.\n"); | 720 | dev_warn(&dev->dev, "pcmcia_register_socket failed.\n"); |
721 | for (j = 0; j < i ; j++) | 721 | for (j = 0; j < i ; j++) |
722 | pcmcia_unregister_socket(&socket[j].socket); | 722 | pcmcia_unregister_socket(&socket[j].socket); |
723 | goto err_out_free_res2; | 723 | goto err_out_free_res2; |
724 | } | 724 | } |
725 | } | 725 | } |
726 | 726 | ||
727 | return 0; | 727 | return 0; |
728 | 728 | ||
729 | err_out_free_res2: | 729 | err_out_free_res2: |
730 | if (irq_mode == 1) | 730 | if (irq_mode == 1) |
731 | free_irq(dev->irq, socket); | 731 | free_irq(dev->irq, socket); |
732 | else | 732 | else |
733 | del_timer_sync(&socket->poll_timer); | 733 | del_timer_sync(&socket->poll_timer); |
734 | err_out_free_res: | 734 | err_out_free_res: |
735 | pci_release_regions(dev); | 735 | pci_release_regions(dev); |
736 | err_out_disable: | 736 | err_out_disable: |
737 | pci_disable_device(dev); | 737 | pci_disable_device(dev); |
738 | 738 | ||
739 | err_out_free_mem: | 739 | err_out_free_mem: |
740 | kfree(socket); | 740 | kfree(socket); |
741 | return ret; | 741 | return ret; |
742 | } | 742 | } |
743 | 743 | ||
744 | static void pd6729_pci_remove(struct pci_dev *dev) | 744 | static void pd6729_pci_remove(struct pci_dev *dev) |
745 | { | 745 | { |
746 | int i; | 746 | int i; |
747 | struct pd6729_socket *socket = pci_get_drvdata(dev); | 747 | struct pd6729_socket *socket = pci_get_drvdata(dev); |
748 | 748 | ||
749 | for (i = 0; i < MAX_SOCKETS; i++) { | 749 | for (i = 0; i < MAX_SOCKETS; i++) { |
750 | /* Turn off all interrupt sources */ | 750 | /* Turn off all interrupt sources */ |
751 | indirect_write(&socket[i], I365_CSCINT, 0); | 751 | indirect_write(&socket[i], I365_CSCINT, 0); |
752 | indirect_write(&socket[i], I365_INTCTL, 0); | 752 | indirect_write(&socket[i], I365_INTCTL, 0); |
753 | 753 | ||
754 | pcmcia_unregister_socket(&socket[i].socket); | 754 | pcmcia_unregister_socket(&socket[i].socket); |
755 | } | 755 | } |
756 | 756 | ||
757 | if (irq_mode == 1) | 757 | if (irq_mode == 1) |
758 | free_irq(dev->irq, socket); | 758 | free_irq(dev->irq, socket); |
759 | else | 759 | else |
760 | del_timer_sync(&socket->poll_timer); | 760 | del_timer_sync(&socket->poll_timer); |
761 | pci_release_regions(dev); | 761 | pci_release_regions(dev); |
762 | pci_disable_device(dev); | 762 | pci_disable_device(dev); |
763 | 763 | ||
764 | kfree(socket); | 764 | kfree(socket); |
765 | } | 765 | } |
766 | 766 | ||
767 | static DEFINE_PCI_DEVICE_TABLE(pd6729_pci_ids) = { | 767 | static const struct pci_device_id pd6729_pci_ids[] = { |
768 | { PCI_DEVICE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6729) }, | 768 | { PCI_DEVICE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6729) }, |
769 | { } | 769 | { } |
770 | }; | 770 | }; |
771 | MODULE_DEVICE_TABLE(pci, pd6729_pci_ids); | 771 | MODULE_DEVICE_TABLE(pci, pd6729_pci_ids); |
772 | 772 | ||
773 | static struct pci_driver pd6729_pci_driver = { | 773 | static struct pci_driver pd6729_pci_driver = { |
774 | .name = "pd6729", | 774 | .name = "pd6729", |
775 | .id_table = pd6729_pci_ids, | 775 | .id_table = pd6729_pci_ids, |
776 | .probe = pd6729_pci_probe, | 776 | .probe = pd6729_pci_probe, |
777 | .remove = pd6729_pci_remove, | 777 | .remove = pd6729_pci_remove, |
778 | }; | 778 | }; |
779 | 779 | ||
780 | module_pci_driver(pd6729_pci_driver); | 780 | module_pci_driver(pd6729_pci_driver); |
781 | 781 |
drivers/pcmcia/vrc4173_cardu.c
1 | /* | 1 | /* |
2 | * FILE NAME | 2 | * FILE NAME |
3 | * drivers/pcmcia/vrc4173_cardu.c | 3 | * drivers/pcmcia/vrc4173_cardu.c |
4 | * | 4 | * |
5 | * BRIEF MODULE DESCRIPTION | 5 | * BRIEF MODULE DESCRIPTION |
6 | * NEC VRC4173 CARDU driver for Socket Services | 6 | * NEC VRC4173 CARDU driver for Socket Services |
7 | * (This device doesn't support CardBus. it is supporting only 16bit PC Card.) | 7 | * (This device doesn't support CardBus. it is supporting only 16bit PC Card.) |
8 | * | 8 | * |
9 | * Copyright 2002,2003 Yoichi Yuasa <yuasa@linux-mips.org> | 9 | * Copyright 2002,2003 Yoichi Yuasa <yuasa@linux-mips.org> |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify it | 11 | * This program is free software; you can redistribute it and/or modify it |
12 | * under the terms of the GNU General Public License as published by the | 12 | * under the terms of the GNU General Public License as published by the |
13 | * Free Software Foundation; either version 2 of the License, or (at your | 13 | * Free Software Foundation; either version 2 of the License, or (at your |
14 | * option) any later version. | 14 | * option) any later version. |
15 | * | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | 16 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |
24 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | 24 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
25 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * | 26 | * |
27 | * You should have received a copy of the GNU General Public License along | 27 | * You should have received a copy of the GNU General Public License along |
28 | * with this program; if not, write to the Free Software Foundation, Inc., | 28 | * with this program; if not, write to the Free Software Foundation, Inc., |
29 | * 675 Mass Ave, Cambridge, MA 02139, USA. | 29 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
30 | */ | 30 | */ |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/spinlock.h> | 34 | #include <linux/spinlock.h> |
35 | #include <linux/types.h> | 35 | #include <linux/types.h> |
36 | 36 | ||
37 | #include <asm/io.h> | 37 | #include <asm/io.h> |
38 | 38 | ||
39 | #include <pcmcia/ss.h> | 39 | #include <pcmcia/ss.h> |
40 | 40 | ||
41 | #include "vrc4173_cardu.h" | 41 | #include "vrc4173_cardu.h" |
42 | 42 | ||
43 | MODULE_DESCRIPTION("NEC VRC4173 CARDU driver for Socket Services"); | 43 | MODULE_DESCRIPTION("NEC VRC4173 CARDU driver for Socket Services"); |
44 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); | 44 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
45 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
46 | 46 | ||
47 | static int vrc4173_cardu_slots; | 47 | static int vrc4173_cardu_slots; |
48 | 48 | ||
49 | static vrc4173_socket_t cardu_sockets[CARDU_MAX_SOCKETS]; | 49 | static vrc4173_socket_t cardu_sockets[CARDU_MAX_SOCKETS]; |
50 | 50 | ||
51 | extern struct socket_info_t *pcmcia_register_socket (int slot, | 51 | extern struct socket_info_t *pcmcia_register_socket (int slot, |
52 | struct pccard_operations *vtable, | 52 | struct pccard_operations *vtable, |
53 | int use_bus_pm); | 53 | int use_bus_pm); |
54 | extern void pcmcia_unregister_socket(struct socket_info_t *s); | 54 | extern void pcmcia_unregister_socket(struct socket_info_t *s); |
55 | 55 | ||
56 | static inline uint8_t exca_readb(vrc4173_socket_t *socket, uint16_t offset) | 56 | static inline uint8_t exca_readb(vrc4173_socket_t *socket, uint16_t offset) |
57 | { | 57 | { |
58 | return readb(socket->base + EXCA_REGS_BASE + offset); | 58 | return readb(socket->base + EXCA_REGS_BASE + offset); |
59 | } | 59 | } |
60 | 60 | ||
61 | static inline uint16_t exca_readw(vrc4173_socket_t *socket, uint16_t offset) | 61 | static inline uint16_t exca_readw(vrc4173_socket_t *socket, uint16_t offset) |
62 | { | 62 | { |
63 | uint16_t val; | 63 | uint16_t val; |
64 | 64 | ||
65 | val = readb(socket->base + EXCA_REGS_BASE + offset); | 65 | val = readb(socket->base + EXCA_REGS_BASE + offset); |
66 | val |= (u16)readb(socket->base + EXCA_REGS_BASE + offset + 1) << 8; | 66 | val |= (u16)readb(socket->base + EXCA_REGS_BASE + offset + 1) << 8; |
67 | 67 | ||
68 | return val; | 68 | return val; |
69 | } | 69 | } |
70 | 70 | ||
71 | static inline void exca_writeb(vrc4173_socket_t *socket, uint16_t offset, uint8_t val) | 71 | static inline void exca_writeb(vrc4173_socket_t *socket, uint16_t offset, uint8_t val) |
72 | { | 72 | { |
73 | writeb(val, socket->base + EXCA_REGS_BASE + offset); | 73 | writeb(val, socket->base + EXCA_REGS_BASE + offset); |
74 | } | 74 | } |
75 | 75 | ||
76 | static inline void exca_writew(vrc4173_socket_t *socket, uint8_t offset, uint16_t val) | 76 | static inline void exca_writew(vrc4173_socket_t *socket, uint8_t offset, uint16_t val) |
77 | { | 77 | { |
78 | writeb((u8)val, socket->base + EXCA_REGS_BASE + offset); | 78 | writeb((u8)val, socket->base + EXCA_REGS_BASE + offset); |
79 | writeb((u8)(val >> 8), socket->base + EXCA_REGS_BASE + offset + 1); | 79 | writeb((u8)(val >> 8), socket->base + EXCA_REGS_BASE + offset + 1); |
80 | } | 80 | } |
81 | 81 | ||
82 | static inline uint32_t cardbus_socket_readl(vrc4173_socket_t *socket, u16 offset) | 82 | static inline uint32_t cardbus_socket_readl(vrc4173_socket_t *socket, u16 offset) |
83 | { | 83 | { |
84 | return readl(socket->base + CARDBUS_SOCKET_REGS_BASE + offset); | 84 | return readl(socket->base + CARDBUS_SOCKET_REGS_BASE + offset); |
85 | } | 85 | } |
86 | 86 | ||
87 | static inline void cardbus_socket_writel(vrc4173_socket_t *socket, u16 offset, uint32_t val) | 87 | static inline void cardbus_socket_writel(vrc4173_socket_t *socket, u16 offset, uint32_t val) |
88 | { | 88 | { |
89 | writel(val, socket->base + CARDBUS_SOCKET_REGS_BASE + offset); | 89 | writel(val, socket->base + CARDBUS_SOCKET_REGS_BASE + offset); |
90 | } | 90 | } |
91 | 91 | ||
92 | static void cardu_pciregs_init(struct pci_dev *dev) | 92 | static void cardu_pciregs_init(struct pci_dev *dev) |
93 | { | 93 | { |
94 | u32 syscnt; | 94 | u32 syscnt; |
95 | u16 brgcnt; | 95 | u16 brgcnt; |
96 | u8 devcnt; | 96 | u8 devcnt; |
97 | 97 | ||
98 | pci_write_config_dword(dev, 0x1c, 0x10000000); | 98 | pci_write_config_dword(dev, 0x1c, 0x10000000); |
99 | pci_write_config_dword(dev, 0x20, 0x17fff000); | 99 | pci_write_config_dword(dev, 0x20, 0x17fff000); |
100 | pci_write_config_dword(dev, 0x2c, 0); | 100 | pci_write_config_dword(dev, 0x2c, 0); |
101 | pci_write_config_dword(dev, 0x30, 0xfffc); | 101 | pci_write_config_dword(dev, 0x30, 0xfffc); |
102 | 102 | ||
103 | pci_read_config_word(dev, BRGCNT, &brgcnt); | 103 | pci_read_config_word(dev, BRGCNT, &brgcnt); |
104 | brgcnt &= ~IREQ_INT; | 104 | brgcnt &= ~IREQ_INT; |
105 | pci_write_config_word(dev, BRGCNT, brgcnt); | 105 | pci_write_config_word(dev, BRGCNT, brgcnt); |
106 | 106 | ||
107 | pci_read_config_dword(dev, SYSCNT, &syscnt); | 107 | pci_read_config_dword(dev, SYSCNT, &syscnt); |
108 | syscnt &= ~(BAD_VCC_REQ_DISB|PCPCI_EN|CH_ASSIGN_MASK|SUB_ID_WR_EN|PCI_CLK_RIN); | 108 | syscnt &= ~(BAD_VCC_REQ_DISB|PCPCI_EN|CH_ASSIGN_MASK|SUB_ID_WR_EN|PCI_CLK_RIN); |
109 | syscnt |= (CH_ASSIGN_NODMA|ASYN_INT_MODE); | 109 | syscnt |= (CH_ASSIGN_NODMA|ASYN_INT_MODE); |
110 | pci_write_config_dword(dev, SYSCNT, syscnt); | 110 | pci_write_config_dword(dev, SYSCNT, syscnt); |
111 | 111 | ||
112 | pci_read_config_byte(dev, DEVCNT, &devcnt); | 112 | pci_read_config_byte(dev, DEVCNT, &devcnt); |
113 | devcnt &= ~(ZOOM_VIDEO_EN|SR_PCI_INT_SEL_MASK|PCI_INT_MODE|IRQ_MODE); | 113 | devcnt &= ~(ZOOM_VIDEO_EN|SR_PCI_INT_SEL_MASK|PCI_INT_MODE|IRQ_MODE); |
114 | devcnt |= (SR_PCI_INT_SEL_NONE|IFG); | 114 | devcnt |= (SR_PCI_INT_SEL_NONE|IFG); |
115 | pci_write_config_byte(dev, DEVCNT, devcnt); | 115 | pci_write_config_byte(dev, DEVCNT, devcnt); |
116 | 116 | ||
117 | pci_write_config_byte(dev, CHIPCNT, S_PREF_DISB); | 117 | pci_write_config_byte(dev, CHIPCNT, S_PREF_DISB); |
118 | 118 | ||
119 | pci_write_config_byte(dev, SERRDIS, 0); | 119 | pci_write_config_byte(dev, SERRDIS, 0); |
120 | } | 120 | } |
121 | 121 | ||
122 | static int cardu_init(unsigned int slot) | 122 | static int cardu_init(unsigned int slot) |
123 | { | 123 | { |
124 | vrc4173_socket_t *socket = &cardu_sockets[slot]; | 124 | vrc4173_socket_t *socket = &cardu_sockets[slot]; |
125 | 125 | ||
126 | cardu_pciregs_init(socket->dev); | 126 | cardu_pciregs_init(socket->dev); |
127 | 127 | ||
128 | /* CARD_SC bits are cleared by reading CARD_SC. */ | 128 | /* CARD_SC bits are cleared by reading CARD_SC. */ |
129 | exca_writeb(socket, GLO_CNT, 0); | 129 | exca_writeb(socket, GLO_CNT, 0); |
130 | 130 | ||
131 | socket->cap.features |= SS_CAP_PCCARD | SS_CAP_PAGE_REGS; | 131 | socket->cap.features |= SS_CAP_PCCARD | SS_CAP_PAGE_REGS; |
132 | socket->cap.irq_mask = 0; | 132 | socket->cap.irq_mask = 0; |
133 | socket->cap.map_size = 0x1000; | 133 | socket->cap.map_size = 0x1000; |
134 | socket->cap.pci_irq = socket->dev->irq; | 134 | socket->cap.pci_irq = socket->dev->irq; |
135 | socket->events = 0; | 135 | socket->events = 0; |
136 | spin_lock_init(socket->event_lock); | 136 | spin_lock_init(socket->event_lock); |
137 | 137 | ||
138 | /* Enable PC Card status interrupts */ | 138 | /* Enable PC Card status interrupts */ |
139 | exca_writeb(socket, CARD_SCI, CARD_DT_EN|RDY_EN|BAT_WAR_EN|BAT_DEAD_EN); | 139 | exca_writeb(socket, CARD_SCI, CARD_DT_EN|RDY_EN|BAT_WAR_EN|BAT_DEAD_EN); |
140 | 140 | ||
141 | return 0; | 141 | return 0; |
142 | } | 142 | } |
143 | 143 | ||
144 | static int cardu_register_callback(unsigned int sock, | 144 | static int cardu_register_callback(unsigned int sock, |
145 | void (*handler)(void *, unsigned int), | 145 | void (*handler)(void *, unsigned int), |
146 | void * info) | 146 | void * info) |
147 | { | 147 | { |
148 | vrc4173_socket_t *socket = &cardu_sockets[sock]; | 148 | vrc4173_socket_t *socket = &cardu_sockets[sock]; |
149 | 149 | ||
150 | socket->handler = handler; | 150 | socket->handler = handler; |
151 | socket->info = info; | 151 | socket->info = info; |
152 | 152 | ||
153 | return 0; | 153 | return 0; |
154 | } | 154 | } |
155 | 155 | ||
156 | static int cardu_inquire_socket(unsigned int sock, socket_cap_t *cap) | 156 | static int cardu_inquire_socket(unsigned int sock, socket_cap_t *cap) |
157 | { | 157 | { |
158 | vrc4173_socket_t *socket = &cardu_sockets[sock]; | 158 | vrc4173_socket_t *socket = &cardu_sockets[sock]; |
159 | 159 | ||
160 | *cap = socket->cap; | 160 | *cap = socket->cap; |
161 | 161 | ||
162 | return 0; | 162 | return 0; |
163 | } | 163 | } |
164 | 164 | ||
165 | static int cardu_get_status(unsigned int sock, u_int *value) | 165 | static int cardu_get_status(unsigned int sock, u_int *value) |
166 | { | 166 | { |
167 | vrc4173_socket_t *socket = &cardu_sockets[sock]; | 167 | vrc4173_socket_t *socket = &cardu_sockets[sock]; |
168 | uint32_t state; | 168 | uint32_t state; |
169 | uint8_t status; | 169 | uint8_t status; |
170 | u_int val = 0; | 170 | u_int val = 0; |
171 | 171 | ||
172 | status = exca_readb(socket, IF_STATUS); | 172 | status = exca_readb(socket, IF_STATUS); |
173 | if (status & CARD_PWR) val |= SS_POWERON; | 173 | if (status & CARD_PWR) val |= SS_POWERON; |
174 | if (status & READY) val |= SS_READY; | 174 | if (status & READY) val |= SS_READY; |
175 | if (status & CARD_WP) val |= SS_WRPROT; | 175 | if (status & CARD_WP) val |= SS_WRPROT; |
176 | if ((status & (CARD_DETECT1|CARD_DETECT2)) == (CARD_DETECT1|CARD_DETECT2)) | 176 | if ((status & (CARD_DETECT1|CARD_DETECT2)) == (CARD_DETECT1|CARD_DETECT2)) |
177 | val |= SS_DETECT; | 177 | val |= SS_DETECT; |
178 | if (exca_readb(socket, INT_GEN_CNT) & CARD_TYPE_IO) { | 178 | if (exca_readb(socket, INT_GEN_CNT) & CARD_TYPE_IO) { |
179 | if (status & STSCHG) val |= SS_STSCHG; | 179 | if (status & STSCHG) val |= SS_STSCHG; |
180 | } else { | 180 | } else { |
181 | status &= BV_DETECT_MASK; | 181 | status &= BV_DETECT_MASK; |
182 | if (status != BV_DETECT_GOOD) { | 182 | if (status != BV_DETECT_GOOD) { |
183 | if (status == BV_DETECT_WARN) val |= SS_BATWARN; | 183 | if (status == BV_DETECT_WARN) val |= SS_BATWARN; |
184 | else val |= SS_BATDEAD; | 184 | else val |= SS_BATDEAD; |
185 | } | 185 | } |
186 | } | 186 | } |
187 | 187 | ||
188 | state = cardbus_socket_readl(socket, SKT_PRE_STATE); | 188 | state = cardbus_socket_readl(socket, SKT_PRE_STATE); |
189 | if (state & VOL_3V_CARD_DT) val |= SS_3VCARD; | 189 | if (state & VOL_3V_CARD_DT) val |= SS_3VCARD; |
190 | if (state & VOL_XV_CARD_DT) val |= SS_XVCARD; | 190 | if (state & VOL_XV_CARD_DT) val |= SS_XVCARD; |
191 | if (state & CB_CARD_DT) val |= SS_CARDBUS; | 191 | if (state & CB_CARD_DT) val |= SS_CARDBUS; |
192 | if (!(state & | 192 | if (!(state & |
193 | (VOL_YV_CARD_DT|VOL_XV_CARD_DT|VOL_3V_CARD_DT|VOL_5V_CARD_DT|CCD20|CCD10))) | 193 | (VOL_YV_CARD_DT|VOL_XV_CARD_DT|VOL_3V_CARD_DT|VOL_5V_CARD_DT|CCD20|CCD10))) |
194 | val |= SS_PENDING; | 194 | val |= SS_PENDING; |
195 | 195 | ||
196 | *value = val; | 196 | *value = val; |
197 | 197 | ||
198 | return 0; | 198 | return 0; |
199 | } | 199 | } |
200 | 200 | ||
201 | static inline uint8_t set_Vcc_value(u_char Vcc) | 201 | static inline uint8_t set_Vcc_value(u_char Vcc) |
202 | { | 202 | { |
203 | switch (Vcc) { | 203 | switch (Vcc) { |
204 | case 33: | 204 | case 33: |
205 | return VCC_3V; | 205 | return VCC_3V; |
206 | case 50: | 206 | case 50: |
207 | return VCC_5V; | 207 | return VCC_5V; |
208 | } | 208 | } |
209 | 209 | ||
210 | return VCC_0V; | 210 | return VCC_0V; |
211 | } | 211 | } |
212 | 212 | ||
213 | static inline uint8_t set_Vpp_value(u_char Vpp) | 213 | static inline uint8_t set_Vpp_value(u_char Vpp) |
214 | { | 214 | { |
215 | switch (Vpp) { | 215 | switch (Vpp) { |
216 | case 33: | 216 | case 33: |
217 | case 50: | 217 | case 50: |
218 | return VPP_VCC; | 218 | return VPP_VCC; |
219 | case 120: | 219 | case 120: |
220 | return VPP_12V; | 220 | return VPP_12V; |
221 | } | 221 | } |
222 | 222 | ||
223 | return VPP_0V; | 223 | return VPP_0V; |
224 | } | 224 | } |
225 | 225 | ||
226 | static int cardu_set_socket(unsigned int sock, socket_state_t *state) | 226 | static int cardu_set_socket(unsigned int sock, socket_state_t *state) |
227 | { | 227 | { |
228 | vrc4173_socket_t *socket = &cardu_sockets[sock]; | 228 | vrc4173_socket_t *socket = &cardu_sockets[sock]; |
229 | uint8_t val; | 229 | uint8_t val; |
230 | 230 | ||
231 | if (((state->Vpp == 33) || (state->Vpp == 50)) && (state->Vpp != state->Vcc)) | 231 | if (((state->Vpp == 33) || (state->Vpp == 50)) && (state->Vpp != state->Vcc)) |
232 | return -EINVAL; | 232 | return -EINVAL; |
233 | 233 | ||
234 | val = set_Vcc_value(state->Vcc); | 234 | val = set_Vcc_value(state->Vcc); |
235 | val |= set_Vpp_value(state->Vpp); | 235 | val |= set_Vpp_value(state->Vpp); |
236 | if (state->flags & SS_OUTPUT_ENA) val |= CARD_OUT_EN; | 236 | if (state->flags & SS_OUTPUT_ENA) val |= CARD_OUT_EN; |
237 | exca_writeb(socket, PWR_CNT, val); | 237 | exca_writeb(socket, PWR_CNT, val); |
238 | 238 | ||
239 | val = exca_readb(socket, INT_GEN_CNT) & CARD_REST0; | 239 | val = exca_readb(socket, INT_GEN_CNT) & CARD_REST0; |
240 | if (state->flags & SS_RESET) val &= ~CARD_REST0; | 240 | if (state->flags & SS_RESET) val &= ~CARD_REST0; |
241 | else val |= CARD_REST0; | 241 | else val |= CARD_REST0; |
242 | if (state->flags & SS_IOCARD) val |= CARD_TYPE_IO; | 242 | if (state->flags & SS_IOCARD) val |= CARD_TYPE_IO; |
243 | exca_writeb(socket, INT_GEN_CNT, val); | 243 | exca_writeb(socket, INT_GEN_CNT, val); |
244 | 244 | ||
245 | return 0; | 245 | return 0; |
246 | } | 246 | } |
247 | 247 | ||
248 | static int cardu_get_io_map(unsigned int sock, struct pccard_io_map *io) | 248 | static int cardu_get_io_map(unsigned int sock, struct pccard_io_map *io) |
249 | { | 249 | { |
250 | vrc4173_socket_t *socket = &cardu_sockets[sock]; | 250 | vrc4173_socket_t *socket = &cardu_sockets[sock]; |
251 | uint8_t ioctl, window; | 251 | uint8_t ioctl, window; |
252 | u_char map; | 252 | u_char map; |
253 | 253 | ||
254 | map = io->map; | 254 | map = io->map; |
255 | if (map > 1) | 255 | if (map > 1) |
256 | return -EINVAL; | 256 | return -EINVAL; |
257 | 257 | ||
258 | io->start = exca_readw(socket, IO_WIN_SA(map)); | 258 | io->start = exca_readw(socket, IO_WIN_SA(map)); |
259 | io->stop = exca_readw(socket, IO_WIN_EA(map)); | 259 | io->stop = exca_readw(socket, IO_WIN_EA(map)); |
260 | 260 | ||
261 | ioctl = exca_readb(socket, IO_WIN_CNT); | 261 | ioctl = exca_readb(socket, IO_WIN_CNT); |
262 | window = exca_readb(socket, ADR_WIN_EN); | 262 | window = exca_readb(socket, ADR_WIN_EN); |
263 | io->flags = (window & IO_WIN_EN(map)) ? MAP_ACTIVE : 0; | 263 | io->flags = (window & IO_WIN_EN(map)) ? MAP_ACTIVE : 0; |
264 | if (ioctl & IO_WIN_DATA_AUTOSZ(map)) | 264 | if (ioctl & IO_WIN_DATA_AUTOSZ(map)) |
265 | io->flags |= MAP_AUTOSZ; | 265 | io->flags |= MAP_AUTOSZ; |
266 | else if (ioctl & IO_WIN_DATA_16BIT(map)) | 266 | else if (ioctl & IO_WIN_DATA_16BIT(map)) |
267 | io->flags |= MAP_16BIT; | 267 | io->flags |= MAP_16BIT; |
268 | 268 | ||
269 | return 0; | 269 | return 0; |
270 | } | 270 | } |
271 | 271 | ||
272 | static int cardu_set_io_map(unsigned int sock, struct pccard_io_map *io) | 272 | static int cardu_set_io_map(unsigned int sock, struct pccard_io_map *io) |
273 | { | 273 | { |
274 | vrc4173_socket_t *socket = &cardu_sockets[sock]; | 274 | vrc4173_socket_t *socket = &cardu_sockets[sock]; |
275 | uint16_t ioctl; | 275 | uint16_t ioctl; |
276 | uint8_t window, enable; | 276 | uint8_t window, enable; |
277 | u_char map; | 277 | u_char map; |
278 | 278 | ||
279 | map = io->map; | 279 | map = io->map; |
280 | if (map > 1) | 280 | if (map > 1) |
281 | return -EINVAL; | 281 | return -EINVAL; |
282 | 282 | ||
283 | window = exca_readb(socket, ADR_WIN_EN); | 283 | window = exca_readb(socket, ADR_WIN_EN); |
284 | enable = IO_WIN_EN(map); | 284 | enable = IO_WIN_EN(map); |
285 | 285 | ||
286 | if (window & enable) { | 286 | if (window & enable) { |
287 | window &= ~enable; | 287 | window &= ~enable; |
288 | exca_writeb(socket, ADR_WIN_EN, window); | 288 | exca_writeb(socket, ADR_WIN_EN, window); |
289 | } | 289 | } |
290 | 290 | ||
291 | exca_writew(socket, IO_WIN_SA(map), io->start); | 291 | exca_writew(socket, IO_WIN_SA(map), io->start); |
292 | exca_writew(socket, IO_WIN_EA(map), io->stop); | 292 | exca_writew(socket, IO_WIN_EA(map), io->stop); |
293 | 293 | ||
294 | ioctl = exca_readb(socket, IO_WIN_CNT) & ~IO_WIN_CNT_MASK(map); | 294 | ioctl = exca_readb(socket, IO_WIN_CNT) & ~IO_WIN_CNT_MASK(map); |
295 | if (io->flags & MAP_AUTOSZ) ioctl |= IO_WIN_DATA_AUTOSZ(map); | 295 | if (io->flags & MAP_AUTOSZ) ioctl |= IO_WIN_DATA_AUTOSZ(map); |
296 | else if (io->flags & MAP_16BIT) ioctl |= IO_WIN_DATA_16BIT(map); | 296 | else if (io->flags & MAP_16BIT) ioctl |= IO_WIN_DATA_16BIT(map); |
297 | exca_writeb(socket, IO_WIN_CNT, ioctl); | 297 | exca_writeb(socket, IO_WIN_CNT, ioctl); |
298 | 298 | ||
299 | if (io->flags & MAP_ACTIVE) | 299 | if (io->flags & MAP_ACTIVE) |
300 | exca_writeb(socket, ADR_WIN_EN, window | enable); | 300 | exca_writeb(socket, ADR_WIN_EN, window | enable); |
301 | 301 | ||
302 | return 0; | 302 | return 0; |
303 | } | 303 | } |
304 | 304 | ||
305 | static int cardu_get_mem_map(unsigned int sock, struct pccard_mem_map *mem) | 305 | static int cardu_get_mem_map(unsigned int sock, struct pccard_mem_map *mem) |
306 | { | 306 | { |
307 | vrc4173_socket_t *socket = &cardu_sockets[sock]; | 307 | vrc4173_socket_t *socket = &cardu_sockets[sock]; |
308 | uint32_t start, stop, offset, page; | 308 | uint32_t start, stop, offset, page; |
309 | uint8_t window; | 309 | uint8_t window; |
310 | u_char map; | 310 | u_char map; |
311 | 311 | ||
312 | map = mem->map; | 312 | map = mem->map; |
313 | if (map > 4) | 313 | if (map > 4) |
314 | return -EINVAL; | 314 | return -EINVAL; |
315 | 315 | ||
316 | window = exca_readb(socket, ADR_WIN_EN); | 316 | window = exca_readb(socket, ADR_WIN_EN); |
317 | mem->flags = (window & MEM_WIN_EN(map)) ? MAP_ACTIVE : 0; | 317 | mem->flags = (window & MEM_WIN_EN(map)) ? MAP_ACTIVE : 0; |
318 | 318 | ||
319 | start = exca_readw(socket, MEM_WIN_SA(map)); | 319 | start = exca_readw(socket, MEM_WIN_SA(map)); |
320 | mem->flags |= (start & MEM_WIN_DSIZE) ? MAP_16BIT : 0; | 320 | mem->flags |= (start & MEM_WIN_DSIZE) ? MAP_16BIT : 0; |
321 | start = (start & 0x0fff) << 12; | 321 | start = (start & 0x0fff) << 12; |
322 | 322 | ||
323 | stop = exca_readw(socket, MEM_WIN_EA(map)); | 323 | stop = exca_readw(socket, MEM_WIN_EA(map)); |
324 | stop = ((stop & 0x0fff) << 12) + 0x0fff; | 324 | stop = ((stop & 0x0fff) << 12) + 0x0fff; |
325 | 325 | ||
326 | offset = exca_readw(socket, MEM_WIN_OA(map)); | 326 | offset = exca_readw(socket, MEM_WIN_OA(map)); |
327 | mem->flags |= (offset & MEM_WIN_WP) ? MAP_WRPROT : 0; | 327 | mem->flags |= (offset & MEM_WIN_WP) ? MAP_WRPROT : 0; |
328 | mem->flags |= (offset & MEM_WIN_REGSET) ? MAP_ATTRIB : 0; | 328 | mem->flags |= (offset & MEM_WIN_REGSET) ? MAP_ATTRIB : 0; |
329 | offset = ((offset & 0x3fff) << 12) + start; | 329 | offset = ((offset & 0x3fff) << 12) + start; |
330 | mem->card_start = offset & 0x03ffffff; | 330 | mem->card_start = offset & 0x03ffffff; |
331 | 331 | ||
332 | page = exca_readb(socket, MEM_WIN_SAU(map)) << 24; | 332 | page = exca_readb(socket, MEM_WIN_SAU(map)) << 24; |
333 | mem->sys_start = start + page; | 333 | mem->sys_start = start + page; |
334 | mem->sys_stop = start + page; | 334 | mem->sys_stop = start + page; |
335 | 335 | ||
336 | return 0; | 336 | return 0; |
337 | } | 337 | } |
338 | 338 | ||
339 | static int cardu_set_mem_map(unsigned int sock, struct pccard_mem_map *mem) | 339 | static int cardu_set_mem_map(unsigned int sock, struct pccard_mem_map *mem) |
340 | { | 340 | { |
341 | vrc4173_socket_t *socket = &cardu_sockets[sock]; | 341 | vrc4173_socket_t *socket = &cardu_sockets[sock]; |
342 | uint16_t value; | 342 | uint16_t value; |
343 | uint8_t window, enable; | 343 | uint8_t window, enable; |
344 | u_long sys_start, sys_stop, card_start; | 344 | u_long sys_start, sys_stop, card_start; |
345 | u_char map; | 345 | u_char map; |
346 | 346 | ||
347 | map = mem->map; | 347 | map = mem->map; |
348 | sys_start = mem->sys_start; | 348 | sys_start = mem->sys_start; |
349 | sys_stop = mem->sys_stop; | 349 | sys_stop = mem->sys_stop; |
350 | card_start = mem->card_start; | 350 | card_start = mem->card_start; |
351 | 351 | ||
352 | if (map > 4 || sys_start > sys_stop || ((sys_start ^ sys_stop) >> 24) || | 352 | if (map > 4 || sys_start > sys_stop || ((sys_start ^ sys_stop) >> 24) || |
353 | (card_start >> 26)) | 353 | (card_start >> 26)) |
354 | return -EINVAL; | 354 | return -EINVAL; |
355 | 355 | ||
356 | window = exca_readb(socket, ADR_WIN_EN); | 356 | window = exca_readb(socket, ADR_WIN_EN); |
357 | enable = MEM_WIN_EN(map); | 357 | enable = MEM_WIN_EN(map); |
358 | if (window & enable) { | 358 | if (window & enable) { |
359 | window &= ~enable; | 359 | window &= ~enable; |
360 | exca_writeb(socket, ADR_WIN_EN, window); | 360 | exca_writeb(socket, ADR_WIN_EN, window); |
361 | } | 361 | } |
362 | 362 | ||
363 | exca_writeb(socket, MEM_WIN_SAU(map), sys_start >> 24); | 363 | exca_writeb(socket, MEM_WIN_SAU(map), sys_start >> 24); |
364 | 364 | ||
365 | value = (sys_start >> 12) & 0x0fff; | 365 | value = (sys_start >> 12) & 0x0fff; |
366 | if (mem->flags & MAP_16BIT) value |= MEM_WIN_DSIZE; | 366 | if (mem->flags & MAP_16BIT) value |= MEM_WIN_DSIZE; |
367 | exca_writew(socket, MEM_WIN_SA(map), value); | 367 | exca_writew(socket, MEM_WIN_SA(map), value); |
368 | 368 | ||
369 | value = (sys_stop >> 12) & 0x0fff; | 369 | value = (sys_stop >> 12) & 0x0fff; |
370 | exca_writew(socket, MEM_WIN_EA(map), value); | 370 | exca_writew(socket, MEM_WIN_EA(map), value); |
371 | 371 | ||
372 | value = ((card_start - sys_start) >> 12) & 0x3fff; | 372 | value = ((card_start - sys_start) >> 12) & 0x3fff; |
373 | if (mem->flags & MAP_WRPROT) value |= MEM_WIN_WP; | 373 | if (mem->flags & MAP_WRPROT) value |= MEM_WIN_WP; |
374 | if (mem->flags & MAP_ATTRIB) value |= MEM_WIN_REGSET; | 374 | if (mem->flags & MAP_ATTRIB) value |= MEM_WIN_REGSET; |
375 | exca_writew(socket, MEM_WIN_OA(map), value); | 375 | exca_writew(socket, MEM_WIN_OA(map), value); |
376 | 376 | ||
377 | if (mem->flags & MAP_ACTIVE) | 377 | if (mem->flags & MAP_ACTIVE) |
378 | exca_writeb(socket, ADR_WIN_EN, window | enable); | 378 | exca_writeb(socket, ADR_WIN_EN, window | enable); |
379 | 379 | ||
380 | return 0; | 380 | return 0; |
381 | } | 381 | } |
382 | 382 | ||
383 | static void cardu_proc_setup(unsigned int sock, struct proc_dir_entry *base) | 383 | static void cardu_proc_setup(unsigned int sock, struct proc_dir_entry *base) |
384 | { | 384 | { |
385 | } | 385 | } |
386 | 386 | ||
387 | static struct pccard_operations cardu_operations = { | 387 | static struct pccard_operations cardu_operations = { |
388 | .init = cardu_init, | 388 | .init = cardu_init, |
389 | .register_callback = cardu_register_callback, | 389 | .register_callback = cardu_register_callback, |
390 | .inquire_socket = cardu_inquire_socket, | 390 | .inquire_socket = cardu_inquire_socket, |
391 | .get_status = cardu_get_status, | 391 | .get_status = cardu_get_status, |
392 | .set_socket = cardu_set_socket, | 392 | .set_socket = cardu_set_socket, |
393 | .get_io_map = cardu_get_io_map, | 393 | .get_io_map = cardu_get_io_map, |
394 | .set_io_map = cardu_set_io_map, | 394 | .set_io_map = cardu_set_io_map, |
395 | .get_mem_map = cardu_get_mem_map, | 395 | .get_mem_map = cardu_get_mem_map, |
396 | .set_mem_map = cardu_set_mem_map, | 396 | .set_mem_map = cardu_set_mem_map, |
397 | .proc_setup = cardu_proc_setup, | 397 | .proc_setup = cardu_proc_setup, |
398 | }; | 398 | }; |
399 | 399 | ||
400 | static void cardu_bh(void *data) | 400 | static void cardu_bh(void *data) |
401 | { | 401 | { |
402 | vrc4173_socket_t *socket = (vrc4173_socket_t *)data; | 402 | vrc4173_socket_t *socket = (vrc4173_socket_t *)data; |
403 | uint16_t events; | 403 | uint16_t events; |
404 | 404 | ||
405 | spin_lock_irq(&socket->event_lock); | 405 | spin_lock_irq(&socket->event_lock); |
406 | events = socket->events; | 406 | events = socket->events; |
407 | socket->events = 0; | 407 | socket->events = 0; |
408 | spin_unlock_irq(&socket->event_lock); | 408 | spin_unlock_irq(&socket->event_lock); |
409 | 409 | ||
410 | if (socket->handler) | 410 | if (socket->handler) |
411 | socket->handler(socket->info, events); | 411 | socket->handler(socket->info, events); |
412 | } | 412 | } |
413 | 413 | ||
414 | static uint16_t get_events(vrc4173_socket_t *socket) | 414 | static uint16_t get_events(vrc4173_socket_t *socket) |
415 | { | 415 | { |
416 | uint16_t events = 0; | 416 | uint16_t events = 0; |
417 | uint8_t csc, status; | 417 | uint8_t csc, status; |
418 | 418 | ||
419 | status = exca_readb(socket, IF_STATUS); | 419 | status = exca_readb(socket, IF_STATUS); |
420 | csc = exca_readb(socket, CARD_SC); | 420 | csc = exca_readb(socket, CARD_SC); |
421 | if ((csc & CARD_DT_CHG) && | 421 | if ((csc & CARD_DT_CHG) && |
422 | ((status & (CARD_DETECT1|CARD_DETECT2)) == (CARD_DETECT1|CARD_DETECT2))) | 422 | ((status & (CARD_DETECT1|CARD_DETECT2)) == (CARD_DETECT1|CARD_DETECT2))) |
423 | events |= SS_DETECT; | 423 | events |= SS_DETECT; |
424 | 424 | ||
425 | if ((csc & RDY_CHG) && (status & READY)) | 425 | if ((csc & RDY_CHG) && (status & READY)) |
426 | events |= SS_READY; | 426 | events |= SS_READY; |
427 | 427 | ||
428 | if (exca_readb(socket, INT_GEN_CNT) & CARD_TYPE_IO) { | 428 | if (exca_readb(socket, INT_GEN_CNT) & CARD_TYPE_IO) { |
429 | if ((csc & BAT_DEAD_ST_CHG) && (status & STSCHG)) | 429 | if ((csc & BAT_DEAD_ST_CHG) && (status & STSCHG)) |
430 | events |= SS_STSCHG; | 430 | events |= SS_STSCHG; |
431 | } else { | 431 | } else { |
432 | if (csc & (BAT_WAR_CHG|BAT_DEAD_ST_CHG)) { | 432 | if (csc & (BAT_WAR_CHG|BAT_DEAD_ST_CHG)) { |
433 | if ((status & BV_DETECT_MASK) != BV_DETECT_GOOD) { | 433 | if ((status & BV_DETECT_MASK) != BV_DETECT_GOOD) { |
434 | if (status == BV_DETECT_WARN) events |= SS_BATWARN; | 434 | if (status == BV_DETECT_WARN) events |= SS_BATWARN; |
435 | else events |= SS_BATDEAD; | 435 | else events |= SS_BATDEAD; |
436 | } | 436 | } |
437 | } | 437 | } |
438 | } | 438 | } |
439 | 439 | ||
440 | return events; | 440 | return events; |
441 | } | 441 | } |
442 | 442 | ||
443 | static void cardu_interrupt(int irq, void *dev_id) | 443 | static void cardu_interrupt(int irq, void *dev_id) |
444 | { | 444 | { |
445 | vrc4173_socket_t *socket = (vrc4173_socket_t *)dev_id; | 445 | vrc4173_socket_t *socket = (vrc4173_socket_t *)dev_id; |
446 | uint16_t events; | 446 | uint16_t events; |
447 | 447 | ||
448 | INIT_WORK(&socket->tq_work, cardu_bh, socket); | 448 | INIT_WORK(&socket->tq_work, cardu_bh, socket); |
449 | 449 | ||
450 | events = get_events(socket); | 450 | events = get_events(socket); |
451 | if (events) { | 451 | if (events) { |
452 | spin_lock(&socket->event_lock); | 452 | spin_lock(&socket->event_lock); |
453 | socket->events |= events; | 453 | socket->events |= events; |
454 | spin_unlock(&socket->event_lock); | 454 | spin_unlock(&socket->event_lock); |
455 | schedule_work(&socket->tq_work); | 455 | schedule_work(&socket->tq_work); |
456 | } | 456 | } |
457 | } | 457 | } |
458 | 458 | ||
459 | static int vrc4173_cardu_probe(struct pci_dev *dev, | 459 | static int vrc4173_cardu_probe(struct pci_dev *dev, |
460 | const struct pci_device_id *ent) | 460 | const struct pci_device_id *ent) |
461 | { | 461 | { |
462 | vrc4173_socket_t *socket; | 462 | vrc4173_socket_t *socket; |
463 | unsigned long start, len, flags; | 463 | unsigned long start, len, flags; |
464 | int slot, err, ret; | 464 | int slot, err, ret; |
465 | 465 | ||
466 | slot = vrc4173_cardu_slots++; | 466 | slot = vrc4173_cardu_slots++; |
467 | socket = &cardu_sockets[slot]; | 467 | socket = &cardu_sockets[slot]; |
468 | if (socket->noprobe != 0) | 468 | if (socket->noprobe != 0) |
469 | return -EBUSY; | 469 | return -EBUSY; |
470 | 470 | ||
471 | sprintf(socket->name, "NEC VRC4173 CARDU%1d", slot+1); | 471 | sprintf(socket->name, "NEC VRC4173 CARDU%1d", slot+1); |
472 | 472 | ||
473 | if ((err = pci_enable_device(dev)) < 0) | 473 | if ((err = pci_enable_device(dev)) < 0) |
474 | return err; | 474 | return err; |
475 | 475 | ||
476 | start = pci_resource_start(dev, 0); | 476 | start = pci_resource_start(dev, 0); |
477 | if (start == 0) { | 477 | if (start == 0) { |
478 | ret = -ENODEV; | 478 | ret = -ENODEV; |
479 | goto disable; | 479 | goto disable; |
480 | } | 480 | } |
481 | 481 | ||
482 | len = pci_resource_len(dev, 0); | 482 | len = pci_resource_len(dev, 0); |
483 | if (len == 0) { | 483 | if (len == 0) { |
484 | ret = -ENODEV; | 484 | ret = -ENODEV; |
485 | goto disable; | 485 | goto disable; |
486 | } | 486 | } |
487 | 487 | ||
488 | flags = pci_resource_flags(dev, 0); | 488 | flags = pci_resource_flags(dev, 0); |
489 | if ((flags & IORESOURCE_MEM) == 0) { | 489 | if ((flags & IORESOURCE_MEM) == 0) { |
490 | ret = -EBUSY; | 490 | ret = -EBUSY; |
491 | goto disable; | 491 | goto disable; |
492 | } | 492 | } |
493 | 493 | ||
494 | err = pci_request_regions(dev, socket->name); | 494 | err = pci_request_regions(dev, socket->name); |
495 | if (err < 0) { | 495 | if (err < 0) { |
496 | ret = err; | 496 | ret = err; |
497 | goto disable; | 497 | goto disable; |
498 | } | 498 | } |
499 | 499 | ||
500 | socket->base = ioremap(start, len); | 500 | socket->base = ioremap(start, len); |
501 | if (socket->base == NULL) { | 501 | if (socket->base == NULL) { |
502 | ret = -ENODEV; | 502 | ret = -ENODEV; |
503 | goto release; | 503 | goto release; |
504 | } | 504 | } |
505 | 505 | ||
506 | socket->dev = dev; | 506 | socket->dev = dev; |
507 | 507 | ||
508 | socket->pcmcia_socket = pcmcia_register_socket(slot, &cardu_operations, 1); | 508 | socket->pcmcia_socket = pcmcia_register_socket(slot, &cardu_operations, 1); |
509 | if (socket->pcmcia_socket == NULL) { | 509 | if (socket->pcmcia_socket == NULL) { |
510 | ret = -ENOMEM; | 510 | ret = -ENOMEM; |
511 | goto unmap; | 511 | goto unmap; |
512 | } | 512 | } |
513 | 513 | ||
514 | if (request_irq(dev->irq, cardu_interrupt, IRQF_SHARED, socket->name, socket) < 0) { | 514 | if (request_irq(dev->irq, cardu_interrupt, IRQF_SHARED, socket->name, socket) < 0) { |
515 | ret = -EBUSY; | 515 | ret = -EBUSY; |
516 | goto unregister; | 516 | goto unregister; |
517 | } | 517 | } |
518 | 518 | ||
519 | printk(KERN_INFO "%s at %#08lx, IRQ %d\n", socket->name, start, dev->irq); | 519 | printk(KERN_INFO "%s at %#08lx, IRQ %d\n", socket->name, start, dev->irq); |
520 | 520 | ||
521 | return 0; | 521 | return 0; |
522 | 522 | ||
523 | unregister: | 523 | unregister: |
524 | pcmcia_unregister_socket(socket->pcmcia_socket); | 524 | pcmcia_unregister_socket(socket->pcmcia_socket); |
525 | socket->pcmcia_socket = NULL; | 525 | socket->pcmcia_socket = NULL; |
526 | unmap: | 526 | unmap: |
527 | iounmap(socket->base); | 527 | iounmap(socket->base); |
528 | socket->base = NULL; | 528 | socket->base = NULL; |
529 | release: | 529 | release: |
530 | pci_release_regions(dev); | 530 | pci_release_regions(dev); |
531 | disable: | 531 | disable: |
532 | pci_disable_device(dev); | 532 | pci_disable_device(dev); |
533 | return ret; | 533 | return ret; |
534 | } | 534 | } |
535 | 535 | ||
536 | static int vrc4173_cardu_setup(char *options) | 536 | static int vrc4173_cardu_setup(char *options) |
537 | { | 537 | { |
538 | if (options == NULL || *options == '\0') | 538 | if (options == NULL || *options == '\0') |
539 | return 1; | 539 | return 1; |
540 | 540 | ||
541 | if (strncmp(options, "cardu1:", 7) == 0) { | 541 | if (strncmp(options, "cardu1:", 7) == 0) { |
542 | options += 7; | 542 | options += 7; |
543 | if (*options != '\0') { | 543 | if (*options != '\0') { |
544 | if (strncmp(options, "noprobe", 7) == 0) { | 544 | if (strncmp(options, "noprobe", 7) == 0) { |
545 | cardu_sockets[CARDU1].noprobe = 1; | 545 | cardu_sockets[CARDU1].noprobe = 1; |
546 | options += 7; | 546 | options += 7; |
547 | } | 547 | } |
548 | 548 | ||
549 | if (*options != ',') | 549 | if (*options != ',') |
550 | return 1; | 550 | return 1; |
551 | } else | 551 | } else |
552 | return 1; | 552 | return 1; |
553 | } | 553 | } |
554 | 554 | ||
555 | if (strncmp(options, "cardu2:", 7) == 0) { | 555 | if (strncmp(options, "cardu2:", 7) == 0) { |
556 | options += 7; | 556 | options += 7; |
557 | if ((*options != '\0') && (strncmp(options, "noprobe", 7) == 0)) | 557 | if ((*options != '\0') && (strncmp(options, "noprobe", 7) == 0)) |
558 | cardu_sockets[CARDU2].noprobe = 1; | 558 | cardu_sockets[CARDU2].noprobe = 1; |
559 | } | 559 | } |
560 | 560 | ||
561 | return 1; | 561 | return 1; |
562 | } | 562 | } |
563 | 563 | ||
564 | __setup("vrc4173_cardu=", vrc4173_cardu_setup); | 564 | __setup("vrc4173_cardu=", vrc4173_cardu_setup); |
565 | 565 | ||
566 | static DEFINE_PCI_DEVICE_TABLE(vrc4173_cardu_id_table) = { | 566 | static const struct pci_device_id vrc4173_cardu_id_table[] = { |
567 | { PCI_DEVICE(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NAPCCARD) }, | 567 | { PCI_DEVICE(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NAPCCARD) }, |
568 | {0, } | 568 | {0, } |
569 | }; | 569 | }; |
570 | 570 | ||
571 | static struct pci_driver vrc4173_cardu_driver = { | 571 | static struct pci_driver vrc4173_cardu_driver = { |
572 | .name = "NEC VRC4173 CARDU", | 572 | .name = "NEC VRC4173 CARDU", |
573 | .probe = vrc4173_cardu_probe, | 573 | .probe = vrc4173_cardu_probe, |
574 | .id_table = vrc4173_cardu_id_table, | 574 | .id_table = vrc4173_cardu_id_table, |
575 | }; | 575 | }; |
576 | 576 | ||
577 | static int vrc4173_cardu_init(void) | 577 | static int vrc4173_cardu_init(void) |
578 | { | 578 | { |
579 | vrc4173_cardu_slots = 0; | 579 | vrc4173_cardu_slots = 0; |
580 | 580 | ||
581 | return pci_register_driver(&vrc4173_cardu_driver); | 581 | return pci_register_driver(&vrc4173_cardu_driver); |
582 | } | 582 | } |
583 | 583 | ||
584 | static void vrc4173_cardu_exit(void) | 584 | static void vrc4173_cardu_exit(void) |
585 | { | 585 | { |
586 | pci_unregister_driver(&vrc4173_cardu_driver); | 586 | pci_unregister_driver(&vrc4173_cardu_driver); |
587 | } | 587 | } |
588 | 588 | ||
589 | module_init(vrc4173_cardu_init); | 589 | module_init(vrc4173_cardu_init); |
590 | module_exit(vrc4173_cardu_exit); | 590 | module_exit(vrc4173_cardu_exit); |
591 | MODULE_DEVICE_TABLE(pci, vrc4173_cardu_id_table); | 591 | MODULE_DEVICE_TABLE(pci, vrc4173_cardu_id_table); |
592 | 592 |
drivers/pcmcia/yenta_socket.c
1 | /* | 1 | /* |
2 | * Regular cardbus driver ("yenta_socket") | 2 | * Regular cardbus driver ("yenta_socket") |
3 | * | 3 | * |
4 | * (C) Copyright 1999, 2000 Linus Torvalds | 4 | * (C) Copyright 1999, 2000 Linus Torvalds |
5 | * | 5 | * |
6 | * Changelog: | 6 | * Changelog: |
7 | * Aug 2002: Manfred Spraul <manfred@colorfullife.com> | 7 | * Aug 2002: Manfred Spraul <manfred@colorfullife.com> |
8 | * Dynamically adjust the size of the bridge resource | 8 | * Dynamically adjust the size of the bridge resource |
9 | * | 9 | * |
10 | * May 2003: Dominik Brodowski <linux@brodo.de> | 10 | * May 2003: Dominik Brodowski <linux@brodo.de> |
11 | * Merge pci_socket.c and yenta.c into one file | 11 | * Merge pci_socket.c and yenta.c into one file |
12 | */ | 12 | */ |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
15 | #include <linux/workqueue.h> | 15 | #include <linux/workqueue.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | 21 | ||
22 | #include <pcmcia/ss.h> | 22 | #include <pcmcia/ss.h> |
23 | 23 | ||
24 | #include "yenta_socket.h" | 24 | #include "yenta_socket.h" |
25 | #include "i82365.h" | 25 | #include "i82365.h" |
26 | 26 | ||
27 | static bool disable_clkrun; | 27 | static bool disable_clkrun; |
28 | module_param(disable_clkrun, bool, 0444); | 28 | module_param(disable_clkrun, bool, 0444); |
29 | MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option"); | 29 | MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option"); |
30 | 30 | ||
31 | static bool isa_probe = 1; | 31 | static bool isa_probe = 1; |
32 | module_param(isa_probe, bool, 0444); | 32 | module_param(isa_probe, bool, 0444); |
33 | MODULE_PARM_DESC(isa_probe, "If set ISA interrupts are probed (default). Set to N to disable probing"); | 33 | MODULE_PARM_DESC(isa_probe, "If set ISA interrupts are probed (default). Set to N to disable probing"); |
34 | 34 | ||
35 | static bool pwr_irqs_off; | 35 | static bool pwr_irqs_off; |
36 | module_param(pwr_irqs_off, bool, 0644); | 36 | module_param(pwr_irqs_off, bool, 0644); |
37 | MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only when seeing IRQ storms!"); | 37 | MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only when seeing IRQ storms!"); |
38 | 38 | ||
39 | static char o2_speedup[] = "default"; | 39 | static char o2_speedup[] = "default"; |
40 | module_param_string(o2_speedup, o2_speedup, sizeof(o2_speedup), 0444); | 40 | module_param_string(o2_speedup, o2_speedup, sizeof(o2_speedup), 0444); |
41 | MODULE_PARM_DESC(o2_speedup, "Use prefetch/burst for O2-bridges: 'on', 'off' " | 41 | MODULE_PARM_DESC(o2_speedup, "Use prefetch/burst for O2-bridges: 'on', 'off' " |
42 | "or 'default' (uses recommended behaviour for the detected bridge)"); | 42 | "or 'default' (uses recommended behaviour for the detected bridge)"); |
43 | 43 | ||
44 | /* | 44 | /* |
45 | * Only probe "regular" interrupts, don't | 45 | * Only probe "regular" interrupts, don't |
46 | * touch dangerous spots like the mouse irq, | 46 | * touch dangerous spots like the mouse irq, |
47 | * because there are mice that apparently | 47 | * because there are mice that apparently |
48 | * get really confused if they get fondled | 48 | * get really confused if they get fondled |
49 | * too intimately. | 49 | * too intimately. |
50 | * | 50 | * |
51 | * Default to 11, 10, 9, 7, 6, 5, 4, 3. | 51 | * Default to 11, 10, 9, 7, 6, 5, 4, 3. |
52 | */ | 52 | */ |
53 | static u32 isa_interrupts = 0x0ef8; | 53 | static u32 isa_interrupts = 0x0ef8; |
54 | 54 | ||
55 | 55 | ||
56 | #define debug(x, s, args...) dev_dbg(&s->dev->dev, x, ##args) | 56 | #define debug(x, s, args...) dev_dbg(&s->dev->dev, x, ##args) |
57 | 57 | ||
58 | /* Don't ask.. */ | 58 | /* Don't ask.. */ |
59 | #define to_cycles(ns) ((ns)/120) | 59 | #define to_cycles(ns) ((ns)/120) |
60 | #define to_ns(cycles) ((cycles)*120) | 60 | #define to_ns(cycles) ((cycles)*120) |
61 | 61 | ||
62 | /* | 62 | /* |
63 | * yenta PCI irq probing. | 63 | * yenta PCI irq probing. |
64 | * currently only used in the TI/EnE initialization code | 64 | * currently only used in the TI/EnE initialization code |
65 | */ | 65 | */ |
66 | #ifdef CONFIG_YENTA_TI | 66 | #ifdef CONFIG_YENTA_TI |
67 | static int yenta_probe_cb_irq(struct yenta_socket *socket); | 67 | static int yenta_probe_cb_irq(struct yenta_socket *socket); |
68 | static unsigned int yenta_probe_irq(struct yenta_socket *socket, | 68 | static unsigned int yenta_probe_irq(struct yenta_socket *socket, |
69 | u32 isa_irq_mask); | 69 | u32 isa_irq_mask); |
70 | #endif | 70 | #endif |
71 | 71 | ||
72 | 72 | ||
73 | static unsigned int override_bios; | 73 | static unsigned int override_bios; |
74 | module_param(override_bios, uint, 0000); | 74 | module_param(override_bios, uint, 0000); |
75 | MODULE_PARM_DESC(override_bios, "yenta ignore bios resource allocation"); | 75 | MODULE_PARM_DESC(override_bios, "yenta ignore bios resource allocation"); |
76 | 76 | ||
77 | /* | 77 | /* |
78 | * Generate easy-to-use ways of reading a cardbus sockets | 78 | * Generate easy-to-use ways of reading a cardbus sockets |
79 | * regular memory space ("cb_xxx"), configuration space | 79 | * regular memory space ("cb_xxx"), configuration space |
80 | * ("config_xxx") and compatibility space ("exca_xxxx") | 80 | * ("config_xxx") and compatibility space ("exca_xxxx") |
81 | */ | 81 | */ |
82 | static inline u32 cb_readl(struct yenta_socket *socket, unsigned reg) | 82 | static inline u32 cb_readl(struct yenta_socket *socket, unsigned reg) |
83 | { | 83 | { |
84 | u32 val = readl(socket->base + reg); | 84 | u32 val = readl(socket->base + reg); |
85 | debug("%04x %08x\n", socket, reg, val); | 85 | debug("%04x %08x\n", socket, reg, val); |
86 | return val; | 86 | return val; |
87 | } | 87 | } |
88 | 88 | ||
89 | static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val) | 89 | static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val) |
90 | { | 90 | { |
91 | debug("%04x %08x\n", socket, reg, val); | 91 | debug("%04x %08x\n", socket, reg, val); |
92 | writel(val, socket->base + reg); | 92 | writel(val, socket->base + reg); |
93 | readl(socket->base + reg); /* avoid problems with PCI write posting */ | 93 | readl(socket->base + reg); /* avoid problems with PCI write posting */ |
94 | } | 94 | } |
95 | 95 | ||
96 | static inline u8 config_readb(struct yenta_socket *socket, unsigned offset) | 96 | static inline u8 config_readb(struct yenta_socket *socket, unsigned offset) |
97 | { | 97 | { |
98 | u8 val; | 98 | u8 val; |
99 | pci_read_config_byte(socket->dev, offset, &val); | 99 | pci_read_config_byte(socket->dev, offset, &val); |
100 | debug("%04x %02x\n", socket, offset, val); | 100 | debug("%04x %02x\n", socket, offset, val); |
101 | return val; | 101 | return val; |
102 | } | 102 | } |
103 | 103 | ||
104 | static inline u16 config_readw(struct yenta_socket *socket, unsigned offset) | 104 | static inline u16 config_readw(struct yenta_socket *socket, unsigned offset) |
105 | { | 105 | { |
106 | u16 val; | 106 | u16 val; |
107 | pci_read_config_word(socket->dev, offset, &val); | 107 | pci_read_config_word(socket->dev, offset, &val); |
108 | debug("%04x %04x\n", socket, offset, val); | 108 | debug("%04x %04x\n", socket, offset, val); |
109 | return val; | 109 | return val; |
110 | } | 110 | } |
111 | 111 | ||
112 | static inline u32 config_readl(struct yenta_socket *socket, unsigned offset) | 112 | static inline u32 config_readl(struct yenta_socket *socket, unsigned offset) |
113 | { | 113 | { |
114 | u32 val; | 114 | u32 val; |
115 | pci_read_config_dword(socket->dev, offset, &val); | 115 | pci_read_config_dword(socket->dev, offset, &val); |
116 | debug("%04x %08x\n", socket, offset, val); | 116 | debug("%04x %08x\n", socket, offset, val); |
117 | return val; | 117 | return val; |
118 | } | 118 | } |
119 | 119 | ||
120 | static inline void config_writeb(struct yenta_socket *socket, unsigned offset, u8 val) | 120 | static inline void config_writeb(struct yenta_socket *socket, unsigned offset, u8 val) |
121 | { | 121 | { |
122 | debug("%04x %02x\n", socket, offset, val); | 122 | debug("%04x %02x\n", socket, offset, val); |
123 | pci_write_config_byte(socket->dev, offset, val); | 123 | pci_write_config_byte(socket->dev, offset, val); |
124 | } | 124 | } |
125 | 125 | ||
126 | static inline void config_writew(struct yenta_socket *socket, unsigned offset, u16 val) | 126 | static inline void config_writew(struct yenta_socket *socket, unsigned offset, u16 val) |
127 | { | 127 | { |
128 | debug("%04x %04x\n", socket, offset, val); | 128 | debug("%04x %04x\n", socket, offset, val); |
129 | pci_write_config_word(socket->dev, offset, val); | 129 | pci_write_config_word(socket->dev, offset, val); |
130 | } | 130 | } |
131 | 131 | ||
132 | static inline void config_writel(struct yenta_socket *socket, unsigned offset, u32 val) | 132 | static inline void config_writel(struct yenta_socket *socket, unsigned offset, u32 val) |
133 | { | 133 | { |
134 | debug("%04x %08x\n", socket, offset, val); | 134 | debug("%04x %08x\n", socket, offset, val); |
135 | pci_write_config_dword(socket->dev, offset, val); | 135 | pci_write_config_dword(socket->dev, offset, val); |
136 | } | 136 | } |
137 | 137 | ||
138 | static inline u8 exca_readb(struct yenta_socket *socket, unsigned reg) | 138 | static inline u8 exca_readb(struct yenta_socket *socket, unsigned reg) |
139 | { | 139 | { |
140 | u8 val = readb(socket->base + 0x800 + reg); | 140 | u8 val = readb(socket->base + 0x800 + reg); |
141 | debug("%04x %02x\n", socket, reg, val); | 141 | debug("%04x %02x\n", socket, reg, val); |
142 | return val; | 142 | return val; |
143 | } | 143 | } |
144 | 144 | ||
145 | static inline u8 exca_readw(struct yenta_socket *socket, unsigned reg) | 145 | static inline u8 exca_readw(struct yenta_socket *socket, unsigned reg) |
146 | { | 146 | { |
147 | u16 val; | 147 | u16 val; |
148 | val = readb(socket->base + 0x800 + reg); | 148 | val = readb(socket->base + 0x800 + reg); |
149 | val |= readb(socket->base + 0x800 + reg + 1) << 8; | 149 | val |= readb(socket->base + 0x800 + reg + 1) << 8; |
150 | debug("%04x %04x\n", socket, reg, val); | 150 | debug("%04x %04x\n", socket, reg, val); |
151 | return val; | 151 | return val; |
152 | } | 152 | } |
153 | 153 | ||
154 | static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val) | 154 | static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val) |
155 | { | 155 | { |
156 | debug("%04x %02x\n", socket, reg, val); | 156 | debug("%04x %02x\n", socket, reg, val); |
157 | writeb(val, socket->base + 0x800 + reg); | 157 | writeb(val, socket->base + 0x800 + reg); |
158 | readb(socket->base + 0x800 + reg); /* PCI write posting... */ | 158 | readb(socket->base + 0x800 + reg); /* PCI write posting... */ |
159 | } | 159 | } |
160 | 160 | ||
161 | static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val) | 161 | static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val) |
162 | { | 162 | { |
163 | debug("%04x %04x\n", socket, reg, val); | 163 | debug("%04x %04x\n", socket, reg, val); |
164 | writeb(val, socket->base + 0x800 + reg); | 164 | writeb(val, socket->base + 0x800 + reg); |
165 | writeb(val >> 8, socket->base + 0x800 + reg + 1); | 165 | writeb(val >> 8, socket->base + 0x800 + reg + 1); |
166 | 166 | ||
167 | /* PCI write posting... */ | 167 | /* PCI write posting... */ |
168 | readb(socket->base + 0x800 + reg); | 168 | readb(socket->base + 0x800 + reg); |
169 | readb(socket->base + 0x800 + reg + 1); | 169 | readb(socket->base + 0x800 + reg + 1); |
170 | } | 170 | } |
171 | 171 | ||
172 | static ssize_t show_yenta_registers(struct device *yentadev, struct device_attribute *attr, char *buf) | 172 | static ssize_t show_yenta_registers(struct device *yentadev, struct device_attribute *attr, char *buf) |
173 | { | 173 | { |
174 | struct pci_dev *dev = to_pci_dev(yentadev); | 174 | struct pci_dev *dev = to_pci_dev(yentadev); |
175 | struct yenta_socket *socket = pci_get_drvdata(dev); | 175 | struct yenta_socket *socket = pci_get_drvdata(dev); |
176 | int offset = 0, i; | 176 | int offset = 0, i; |
177 | 177 | ||
178 | offset = snprintf(buf, PAGE_SIZE, "CB registers:"); | 178 | offset = snprintf(buf, PAGE_SIZE, "CB registers:"); |
179 | for (i = 0; i < 0x24; i += 4) { | 179 | for (i = 0; i < 0x24; i += 4) { |
180 | unsigned val; | 180 | unsigned val; |
181 | if (!(i & 15)) | 181 | if (!(i & 15)) |
182 | offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i); | 182 | offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i); |
183 | val = cb_readl(socket, i); | 183 | val = cb_readl(socket, i); |
184 | offset += snprintf(buf + offset, PAGE_SIZE - offset, " %08x", val); | 184 | offset += snprintf(buf + offset, PAGE_SIZE - offset, " %08x", val); |
185 | } | 185 | } |
186 | 186 | ||
187 | offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n\nExCA registers:"); | 187 | offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n\nExCA registers:"); |
188 | for (i = 0; i < 0x45; i++) { | 188 | for (i = 0; i < 0x45; i++) { |
189 | unsigned char val; | 189 | unsigned char val; |
190 | if (!(i & 7)) { | 190 | if (!(i & 7)) { |
191 | if (i & 8) { | 191 | if (i & 8) { |
192 | memcpy(buf + offset, " -", 2); | 192 | memcpy(buf + offset, " -", 2); |
193 | offset += 2; | 193 | offset += 2; |
194 | } else | 194 | } else |
195 | offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i); | 195 | offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i); |
196 | } | 196 | } |
197 | val = exca_readb(socket, i); | 197 | val = exca_readb(socket, i); |
198 | offset += snprintf(buf + offset, PAGE_SIZE - offset, " %02x", val); | 198 | offset += snprintf(buf + offset, PAGE_SIZE - offset, " %02x", val); |
199 | } | 199 | } |
200 | buf[offset++] = '\n'; | 200 | buf[offset++] = '\n'; |
201 | return offset; | 201 | return offset; |
202 | } | 202 | } |
203 | 203 | ||
204 | static DEVICE_ATTR(yenta_registers, S_IRUSR, show_yenta_registers, NULL); | 204 | static DEVICE_ATTR(yenta_registers, S_IRUSR, show_yenta_registers, NULL); |
205 | 205 | ||
206 | /* | 206 | /* |
207 | * Ugh, mixed-mode cardbus and 16-bit pccard state: things depend | 207 | * Ugh, mixed-mode cardbus and 16-bit pccard state: things depend |
208 | * on what kind of card is inserted.. | 208 | * on what kind of card is inserted.. |
209 | */ | 209 | */ |
210 | static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value) | 210 | static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value) |
211 | { | 211 | { |
212 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); | 212 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); |
213 | unsigned int val; | 213 | unsigned int val; |
214 | u32 state = cb_readl(socket, CB_SOCKET_STATE); | 214 | u32 state = cb_readl(socket, CB_SOCKET_STATE); |
215 | 215 | ||
216 | val = (state & CB_3VCARD) ? SS_3VCARD : 0; | 216 | val = (state & CB_3VCARD) ? SS_3VCARD : 0; |
217 | val |= (state & CB_XVCARD) ? SS_XVCARD : 0; | 217 | val |= (state & CB_XVCARD) ? SS_XVCARD : 0; |
218 | val |= (state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING; | 218 | val |= (state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING; |
219 | val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? SS_PENDING : 0; | 219 | val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? SS_PENDING : 0; |
220 | 220 | ||
221 | 221 | ||
222 | if (state & CB_CBCARD) { | 222 | if (state & CB_CBCARD) { |
223 | val |= SS_CARDBUS; | 223 | val |= SS_CARDBUS; |
224 | val |= (state & CB_CARDSTS) ? SS_STSCHG : 0; | 224 | val |= (state & CB_CARDSTS) ? SS_STSCHG : 0; |
225 | val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT; | 225 | val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT; |
226 | val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0; | 226 | val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0; |
227 | } else if (state & CB_16BITCARD) { | 227 | } else if (state & CB_16BITCARD) { |
228 | u8 status = exca_readb(socket, I365_STATUS); | 228 | u8 status = exca_readb(socket, I365_STATUS); |
229 | val |= ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0; | 229 | val |= ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0; |
230 | if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { | 230 | if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { |
231 | val |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG; | 231 | val |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG; |
232 | } else { | 232 | } else { |
233 | val |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD; | 233 | val |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD; |
234 | val |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN; | 234 | val |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN; |
235 | } | 235 | } |
236 | val |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0; | 236 | val |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0; |
237 | val |= (status & I365_CS_READY) ? SS_READY : 0; | 237 | val |= (status & I365_CS_READY) ? SS_READY : 0; |
238 | val |= (status & I365_CS_POWERON) ? SS_POWERON : 0; | 238 | val |= (status & I365_CS_POWERON) ? SS_POWERON : 0; |
239 | } | 239 | } |
240 | 240 | ||
241 | *value = val; | 241 | *value = val; |
242 | return 0; | 242 | return 0; |
243 | } | 243 | } |
244 | 244 | ||
245 | static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state) | 245 | static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state) |
246 | { | 246 | { |
247 | /* some birdges require to use the ExCA registers to power 16bit cards */ | 247 | /* some birdges require to use the ExCA registers to power 16bit cards */ |
248 | if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) && | 248 | if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) && |
249 | (socket->flags & YENTA_16BIT_POWER_EXCA)) { | 249 | (socket->flags & YENTA_16BIT_POWER_EXCA)) { |
250 | u8 reg, old; | 250 | u8 reg, old; |
251 | reg = old = exca_readb(socket, I365_POWER); | 251 | reg = old = exca_readb(socket, I365_POWER); |
252 | reg &= ~(I365_VCC_MASK | I365_VPP1_MASK | I365_VPP2_MASK); | 252 | reg &= ~(I365_VCC_MASK | I365_VPP1_MASK | I365_VPP2_MASK); |
253 | 253 | ||
254 | /* i82365SL-DF style */ | 254 | /* i82365SL-DF style */ |
255 | if (socket->flags & YENTA_16BIT_POWER_DF) { | 255 | if (socket->flags & YENTA_16BIT_POWER_DF) { |
256 | switch (state->Vcc) { | 256 | switch (state->Vcc) { |
257 | case 33: | 257 | case 33: |
258 | reg |= I365_VCC_3V; | 258 | reg |= I365_VCC_3V; |
259 | break; | 259 | break; |
260 | case 50: | 260 | case 50: |
261 | reg |= I365_VCC_5V; | 261 | reg |= I365_VCC_5V; |
262 | break; | 262 | break; |
263 | default: | 263 | default: |
264 | reg = 0; | 264 | reg = 0; |
265 | break; | 265 | break; |
266 | } | 266 | } |
267 | switch (state->Vpp) { | 267 | switch (state->Vpp) { |
268 | case 33: | 268 | case 33: |
269 | case 50: | 269 | case 50: |
270 | reg |= I365_VPP1_5V; | 270 | reg |= I365_VPP1_5V; |
271 | break; | 271 | break; |
272 | case 120: | 272 | case 120: |
273 | reg |= I365_VPP1_12V; | 273 | reg |= I365_VPP1_12V; |
274 | break; | 274 | break; |
275 | } | 275 | } |
276 | } else { | 276 | } else { |
277 | /* i82365SL-B style */ | 277 | /* i82365SL-B style */ |
278 | switch (state->Vcc) { | 278 | switch (state->Vcc) { |
279 | case 50: | 279 | case 50: |
280 | reg |= I365_VCC_5V; | 280 | reg |= I365_VCC_5V; |
281 | break; | 281 | break; |
282 | default: | 282 | default: |
283 | reg = 0; | 283 | reg = 0; |
284 | break; | 284 | break; |
285 | } | 285 | } |
286 | switch (state->Vpp) { | 286 | switch (state->Vpp) { |
287 | case 50: | 287 | case 50: |
288 | reg |= I365_VPP1_5V | I365_VPP2_5V; | 288 | reg |= I365_VPP1_5V | I365_VPP2_5V; |
289 | break; | 289 | break; |
290 | case 120: | 290 | case 120: |
291 | reg |= I365_VPP1_12V | I365_VPP2_12V; | 291 | reg |= I365_VPP1_12V | I365_VPP2_12V; |
292 | break; | 292 | break; |
293 | } | 293 | } |
294 | } | 294 | } |
295 | 295 | ||
296 | if (reg != old) | 296 | if (reg != old) |
297 | exca_writeb(socket, I365_POWER, reg); | 297 | exca_writeb(socket, I365_POWER, reg); |
298 | } else { | 298 | } else { |
299 | u32 reg = 0; /* CB_SC_STPCLK? */ | 299 | u32 reg = 0; /* CB_SC_STPCLK? */ |
300 | switch (state->Vcc) { | 300 | switch (state->Vcc) { |
301 | case 33: | 301 | case 33: |
302 | reg = CB_SC_VCC_3V; | 302 | reg = CB_SC_VCC_3V; |
303 | break; | 303 | break; |
304 | case 50: | 304 | case 50: |
305 | reg = CB_SC_VCC_5V; | 305 | reg = CB_SC_VCC_5V; |
306 | break; | 306 | break; |
307 | default: | 307 | default: |
308 | reg = 0; | 308 | reg = 0; |
309 | break; | 309 | break; |
310 | } | 310 | } |
311 | switch (state->Vpp) { | 311 | switch (state->Vpp) { |
312 | case 33: | 312 | case 33: |
313 | reg |= CB_SC_VPP_3V; | 313 | reg |= CB_SC_VPP_3V; |
314 | break; | 314 | break; |
315 | case 50: | 315 | case 50: |
316 | reg |= CB_SC_VPP_5V; | 316 | reg |= CB_SC_VPP_5V; |
317 | break; | 317 | break; |
318 | case 120: | 318 | case 120: |
319 | reg |= CB_SC_VPP_12V; | 319 | reg |= CB_SC_VPP_12V; |
320 | break; | 320 | break; |
321 | } | 321 | } |
322 | if (reg != cb_readl(socket, CB_SOCKET_CONTROL)) | 322 | if (reg != cb_readl(socket, CB_SOCKET_CONTROL)) |
323 | cb_writel(socket, CB_SOCKET_CONTROL, reg); | 323 | cb_writel(socket, CB_SOCKET_CONTROL, reg); |
324 | } | 324 | } |
325 | } | 325 | } |
326 | 326 | ||
327 | static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) | 327 | static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) |
328 | { | 328 | { |
329 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); | 329 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); |
330 | u16 bridge; | 330 | u16 bridge; |
331 | 331 | ||
332 | /* if powering down: do it immediately */ | 332 | /* if powering down: do it immediately */ |
333 | if (state->Vcc == 0) | 333 | if (state->Vcc == 0) |
334 | yenta_set_power(socket, state); | 334 | yenta_set_power(socket, state); |
335 | 335 | ||
336 | socket->io_irq = state->io_irq; | 336 | socket->io_irq = state->io_irq; |
337 | bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~(CB_BRIDGE_CRST | CB_BRIDGE_INTR); | 337 | bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~(CB_BRIDGE_CRST | CB_BRIDGE_INTR); |
338 | if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) { | 338 | if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) { |
339 | u8 intr; | 339 | u8 intr; |
340 | bridge |= (state->flags & SS_RESET) ? CB_BRIDGE_CRST : 0; | 340 | bridge |= (state->flags & SS_RESET) ? CB_BRIDGE_CRST : 0; |
341 | 341 | ||
342 | /* ISA interrupt control? */ | 342 | /* ISA interrupt control? */ |
343 | intr = exca_readb(socket, I365_INTCTL); | 343 | intr = exca_readb(socket, I365_INTCTL); |
344 | intr = (intr & ~0xf); | 344 | intr = (intr & ~0xf); |
345 | if (!socket->dev->irq) { | 345 | if (!socket->dev->irq) { |
346 | intr |= socket->cb_irq ? socket->cb_irq : state->io_irq; | 346 | intr |= socket->cb_irq ? socket->cb_irq : state->io_irq; |
347 | bridge |= CB_BRIDGE_INTR; | 347 | bridge |= CB_BRIDGE_INTR; |
348 | } | 348 | } |
349 | exca_writeb(socket, I365_INTCTL, intr); | 349 | exca_writeb(socket, I365_INTCTL, intr); |
350 | } else { | 350 | } else { |
351 | u8 reg; | 351 | u8 reg; |
352 | 352 | ||
353 | reg = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | I365_INTR_ENA); | 353 | reg = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | I365_INTR_ENA); |
354 | reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; | 354 | reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; |
355 | reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; | 355 | reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; |
356 | if (state->io_irq != socket->dev->irq) { | 356 | if (state->io_irq != socket->dev->irq) { |
357 | reg |= state->io_irq; | 357 | reg |= state->io_irq; |
358 | bridge |= CB_BRIDGE_INTR; | 358 | bridge |= CB_BRIDGE_INTR; |
359 | } | 359 | } |
360 | exca_writeb(socket, I365_INTCTL, reg); | 360 | exca_writeb(socket, I365_INTCTL, reg); |
361 | 361 | ||
362 | reg = exca_readb(socket, I365_POWER) & (I365_VCC_MASK|I365_VPP1_MASK); | 362 | reg = exca_readb(socket, I365_POWER) & (I365_VCC_MASK|I365_VPP1_MASK); |
363 | reg |= I365_PWR_NORESET; | 363 | reg |= I365_PWR_NORESET; |
364 | if (state->flags & SS_PWR_AUTO) | 364 | if (state->flags & SS_PWR_AUTO) |
365 | reg |= I365_PWR_AUTO; | 365 | reg |= I365_PWR_AUTO; |
366 | if (state->flags & SS_OUTPUT_ENA) | 366 | if (state->flags & SS_OUTPUT_ENA) |
367 | reg |= I365_PWR_OUT; | 367 | reg |= I365_PWR_OUT; |
368 | if (exca_readb(socket, I365_POWER) != reg) | 368 | if (exca_readb(socket, I365_POWER) != reg) |
369 | exca_writeb(socket, I365_POWER, reg); | 369 | exca_writeb(socket, I365_POWER, reg); |
370 | 370 | ||
371 | /* CSC interrupt: no ISA irq for CSC */ | 371 | /* CSC interrupt: no ISA irq for CSC */ |
372 | reg = exca_readb(socket, I365_CSCINT); | 372 | reg = exca_readb(socket, I365_CSCINT); |
373 | reg &= I365_CSC_IRQ_MASK; | 373 | reg &= I365_CSC_IRQ_MASK; |
374 | reg |= I365_CSC_DETECT; | 374 | reg |= I365_CSC_DETECT; |
375 | if (state->flags & SS_IOCARD) { | 375 | if (state->flags & SS_IOCARD) { |
376 | if (state->csc_mask & SS_STSCHG) | 376 | if (state->csc_mask & SS_STSCHG) |
377 | reg |= I365_CSC_STSCHG; | 377 | reg |= I365_CSC_STSCHG; |
378 | } else { | 378 | } else { |
379 | if (state->csc_mask & SS_BATDEAD) | 379 | if (state->csc_mask & SS_BATDEAD) |
380 | reg |= I365_CSC_BVD1; | 380 | reg |= I365_CSC_BVD1; |
381 | if (state->csc_mask & SS_BATWARN) | 381 | if (state->csc_mask & SS_BATWARN) |
382 | reg |= I365_CSC_BVD2; | 382 | reg |= I365_CSC_BVD2; |
383 | if (state->csc_mask & SS_READY) | 383 | if (state->csc_mask & SS_READY) |
384 | reg |= I365_CSC_READY; | 384 | reg |= I365_CSC_READY; |
385 | } | 385 | } |
386 | exca_writeb(socket, I365_CSCINT, reg); | 386 | exca_writeb(socket, I365_CSCINT, reg); |
387 | exca_readb(socket, I365_CSC); | 387 | exca_readb(socket, I365_CSC); |
388 | if (sock->zoom_video) | 388 | if (sock->zoom_video) |
389 | sock->zoom_video(sock, state->flags & SS_ZVCARD); | 389 | sock->zoom_video(sock, state->flags & SS_ZVCARD); |
390 | } | 390 | } |
391 | config_writew(socket, CB_BRIDGE_CONTROL, bridge); | 391 | config_writew(socket, CB_BRIDGE_CONTROL, bridge); |
392 | /* Socket event mask: get card insert/remove events.. */ | 392 | /* Socket event mask: get card insert/remove events.. */ |
393 | cb_writel(socket, CB_SOCKET_EVENT, -1); | 393 | cb_writel(socket, CB_SOCKET_EVENT, -1); |
394 | cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); | 394 | cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); |
395 | 395 | ||
396 | /* if powering up: do it as the last step when the socket is configured */ | 396 | /* if powering up: do it as the last step when the socket is configured */ |
397 | if (state->Vcc != 0) | 397 | if (state->Vcc != 0) |
398 | yenta_set_power(socket, state); | 398 | yenta_set_power(socket, state); |
399 | return 0; | 399 | return 0; |
400 | } | 400 | } |
401 | 401 | ||
402 | static int yenta_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) | 402 | static int yenta_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) |
403 | { | 403 | { |
404 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); | 404 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); |
405 | int map; | 405 | int map; |
406 | unsigned char ioctl, addr, enable; | 406 | unsigned char ioctl, addr, enable; |
407 | 407 | ||
408 | map = io->map; | 408 | map = io->map; |
409 | 409 | ||
410 | if (map > 1) | 410 | if (map > 1) |
411 | return -EINVAL; | 411 | return -EINVAL; |
412 | 412 | ||
413 | enable = I365_ENA_IO(map); | 413 | enable = I365_ENA_IO(map); |
414 | addr = exca_readb(socket, I365_ADDRWIN); | 414 | addr = exca_readb(socket, I365_ADDRWIN); |
415 | 415 | ||
416 | /* Disable the window before changing it.. */ | 416 | /* Disable the window before changing it.. */ |
417 | if (addr & enable) { | 417 | if (addr & enable) { |
418 | addr &= ~enable; | 418 | addr &= ~enable; |
419 | exca_writeb(socket, I365_ADDRWIN, addr); | 419 | exca_writeb(socket, I365_ADDRWIN, addr); |
420 | } | 420 | } |
421 | 421 | ||
422 | exca_writew(socket, I365_IO(map)+I365_W_START, io->start); | 422 | exca_writew(socket, I365_IO(map)+I365_W_START, io->start); |
423 | exca_writew(socket, I365_IO(map)+I365_W_STOP, io->stop); | 423 | exca_writew(socket, I365_IO(map)+I365_W_STOP, io->stop); |
424 | 424 | ||
425 | ioctl = exca_readb(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map); | 425 | ioctl = exca_readb(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map); |
426 | if (io->flags & MAP_0WS) | 426 | if (io->flags & MAP_0WS) |
427 | ioctl |= I365_IOCTL_0WS(map); | 427 | ioctl |= I365_IOCTL_0WS(map); |
428 | if (io->flags & MAP_16BIT) | 428 | if (io->flags & MAP_16BIT) |
429 | ioctl |= I365_IOCTL_16BIT(map); | 429 | ioctl |= I365_IOCTL_16BIT(map); |
430 | if (io->flags & MAP_AUTOSZ) | 430 | if (io->flags & MAP_AUTOSZ) |
431 | ioctl |= I365_IOCTL_IOCS16(map); | 431 | ioctl |= I365_IOCTL_IOCS16(map); |
432 | exca_writeb(socket, I365_IOCTL, ioctl); | 432 | exca_writeb(socket, I365_IOCTL, ioctl); |
433 | 433 | ||
434 | if (io->flags & MAP_ACTIVE) | 434 | if (io->flags & MAP_ACTIVE) |
435 | exca_writeb(socket, I365_ADDRWIN, addr | enable); | 435 | exca_writeb(socket, I365_ADDRWIN, addr | enable); |
436 | return 0; | 436 | return 0; |
437 | } | 437 | } |
438 | 438 | ||
439 | static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem) | 439 | static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem) |
440 | { | 440 | { |
441 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); | 441 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); |
442 | struct pci_bus_region region; | 442 | struct pci_bus_region region; |
443 | int map; | 443 | int map; |
444 | unsigned char addr, enable; | 444 | unsigned char addr, enable; |
445 | unsigned int start, stop, card_start; | 445 | unsigned int start, stop, card_start; |
446 | unsigned short word; | 446 | unsigned short word; |
447 | 447 | ||
448 | pcibios_resource_to_bus(socket->dev->bus, ®ion, mem->res); | 448 | pcibios_resource_to_bus(socket->dev->bus, ®ion, mem->res); |
449 | 449 | ||
450 | map = mem->map; | 450 | map = mem->map; |
451 | start = region.start; | 451 | start = region.start; |
452 | stop = region.end; | 452 | stop = region.end; |
453 | card_start = mem->card_start; | 453 | card_start = mem->card_start; |
454 | 454 | ||
455 | if (map > 4 || start > stop || ((start ^ stop) >> 24) || | 455 | if (map > 4 || start > stop || ((start ^ stop) >> 24) || |
456 | (card_start >> 26) || mem->speed > 1000) | 456 | (card_start >> 26) || mem->speed > 1000) |
457 | return -EINVAL; | 457 | return -EINVAL; |
458 | 458 | ||
459 | enable = I365_ENA_MEM(map); | 459 | enable = I365_ENA_MEM(map); |
460 | addr = exca_readb(socket, I365_ADDRWIN); | 460 | addr = exca_readb(socket, I365_ADDRWIN); |
461 | if (addr & enable) { | 461 | if (addr & enable) { |
462 | addr &= ~enable; | 462 | addr &= ~enable; |
463 | exca_writeb(socket, I365_ADDRWIN, addr); | 463 | exca_writeb(socket, I365_ADDRWIN, addr); |
464 | } | 464 | } |
465 | 465 | ||
466 | exca_writeb(socket, CB_MEM_PAGE(map), start >> 24); | 466 | exca_writeb(socket, CB_MEM_PAGE(map), start >> 24); |
467 | 467 | ||
468 | word = (start >> 12) & 0x0fff; | 468 | word = (start >> 12) & 0x0fff; |
469 | if (mem->flags & MAP_16BIT) | 469 | if (mem->flags & MAP_16BIT) |
470 | word |= I365_MEM_16BIT; | 470 | word |= I365_MEM_16BIT; |
471 | if (mem->flags & MAP_0WS) | 471 | if (mem->flags & MAP_0WS) |
472 | word |= I365_MEM_0WS; | 472 | word |= I365_MEM_0WS; |
473 | exca_writew(socket, I365_MEM(map) + I365_W_START, word); | 473 | exca_writew(socket, I365_MEM(map) + I365_W_START, word); |
474 | 474 | ||
475 | word = (stop >> 12) & 0x0fff; | 475 | word = (stop >> 12) & 0x0fff; |
476 | switch (to_cycles(mem->speed)) { | 476 | switch (to_cycles(mem->speed)) { |
477 | case 0: | 477 | case 0: |
478 | break; | 478 | break; |
479 | case 1: | 479 | case 1: |
480 | word |= I365_MEM_WS0; | 480 | word |= I365_MEM_WS0; |
481 | break; | 481 | break; |
482 | case 2: | 482 | case 2: |
483 | word |= I365_MEM_WS1; | 483 | word |= I365_MEM_WS1; |
484 | break; | 484 | break; |
485 | default: | 485 | default: |
486 | word |= I365_MEM_WS1 | I365_MEM_WS0; | 486 | word |= I365_MEM_WS1 | I365_MEM_WS0; |
487 | break; | 487 | break; |
488 | } | 488 | } |
489 | exca_writew(socket, I365_MEM(map) + I365_W_STOP, word); | 489 | exca_writew(socket, I365_MEM(map) + I365_W_STOP, word); |
490 | 490 | ||
491 | word = ((card_start - start) >> 12) & 0x3fff; | 491 | word = ((card_start - start) >> 12) & 0x3fff; |
492 | if (mem->flags & MAP_WRPROT) | 492 | if (mem->flags & MAP_WRPROT) |
493 | word |= I365_MEM_WRPROT; | 493 | word |= I365_MEM_WRPROT; |
494 | if (mem->flags & MAP_ATTRIB) | 494 | if (mem->flags & MAP_ATTRIB) |
495 | word |= I365_MEM_REG; | 495 | word |= I365_MEM_REG; |
496 | exca_writew(socket, I365_MEM(map) + I365_W_OFF, word); | 496 | exca_writew(socket, I365_MEM(map) + I365_W_OFF, word); |
497 | 497 | ||
498 | if (mem->flags & MAP_ACTIVE) | 498 | if (mem->flags & MAP_ACTIVE) |
499 | exca_writeb(socket, I365_ADDRWIN, addr | enable); | 499 | exca_writeb(socket, I365_ADDRWIN, addr | enable); |
500 | return 0; | 500 | return 0; |
501 | } | 501 | } |
502 | 502 | ||
503 | 503 | ||
504 | 504 | ||
505 | static irqreturn_t yenta_interrupt(int irq, void *dev_id) | 505 | static irqreturn_t yenta_interrupt(int irq, void *dev_id) |
506 | { | 506 | { |
507 | unsigned int events; | 507 | unsigned int events; |
508 | struct yenta_socket *socket = (struct yenta_socket *) dev_id; | 508 | struct yenta_socket *socket = (struct yenta_socket *) dev_id; |
509 | u8 csc; | 509 | u8 csc; |
510 | u32 cb_event; | 510 | u32 cb_event; |
511 | 511 | ||
512 | /* Clear interrupt status for the event */ | 512 | /* Clear interrupt status for the event */ |
513 | cb_event = cb_readl(socket, CB_SOCKET_EVENT); | 513 | cb_event = cb_readl(socket, CB_SOCKET_EVENT); |
514 | cb_writel(socket, CB_SOCKET_EVENT, cb_event); | 514 | cb_writel(socket, CB_SOCKET_EVENT, cb_event); |
515 | 515 | ||
516 | csc = exca_readb(socket, I365_CSC); | 516 | csc = exca_readb(socket, I365_CSC); |
517 | 517 | ||
518 | if (!(cb_event || csc)) | 518 | if (!(cb_event || csc)) |
519 | return IRQ_NONE; | 519 | return IRQ_NONE; |
520 | 520 | ||
521 | events = (cb_event & (CB_CD1EVENT | CB_CD2EVENT)) ? SS_DETECT : 0 ; | 521 | events = (cb_event & (CB_CD1EVENT | CB_CD2EVENT)) ? SS_DETECT : 0 ; |
522 | events |= (csc & I365_CSC_DETECT) ? SS_DETECT : 0; | 522 | events |= (csc & I365_CSC_DETECT) ? SS_DETECT : 0; |
523 | if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { | 523 | if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { |
524 | events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; | 524 | events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; |
525 | } else { | 525 | } else { |
526 | events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0; | 526 | events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0; |
527 | events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; | 527 | events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; |
528 | events |= (csc & I365_CSC_READY) ? SS_READY : 0; | 528 | events |= (csc & I365_CSC_READY) ? SS_READY : 0; |
529 | } | 529 | } |
530 | 530 | ||
531 | if (events) | 531 | if (events) |
532 | pcmcia_parse_events(&socket->socket, events); | 532 | pcmcia_parse_events(&socket->socket, events); |
533 | 533 | ||
534 | return IRQ_HANDLED; | 534 | return IRQ_HANDLED; |
535 | } | 535 | } |
536 | 536 | ||
537 | static void yenta_interrupt_wrapper(unsigned long data) | 537 | static void yenta_interrupt_wrapper(unsigned long data) |
538 | { | 538 | { |
539 | struct yenta_socket *socket = (struct yenta_socket *) data; | 539 | struct yenta_socket *socket = (struct yenta_socket *) data; |
540 | 540 | ||
541 | yenta_interrupt(0, (void *)socket); | 541 | yenta_interrupt(0, (void *)socket); |
542 | socket->poll_timer.expires = jiffies + HZ; | 542 | socket->poll_timer.expires = jiffies + HZ; |
543 | add_timer(&socket->poll_timer); | 543 | add_timer(&socket->poll_timer); |
544 | } | 544 | } |
545 | 545 | ||
546 | static void yenta_clear_maps(struct yenta_socket *socket) | 546 | static void yenta_clear_maps(struct yenta_socket *socket) |
547 | { | 547 | { |
548 | int i; | 548 | int i; |
549 | struct resource res = { .start = 0, .end = 0x0fff }; | 549 | struct resource res = { .start = 0, .end = 0x0fff }; |
550 | pccard_io_map io = { 0, 0, 0, 0, 1 }; | 550 | pccard_io_map io = { 0, 0, 0, 0, 1 }; |
551 | pccard_mem_map mem = { .res = &res, }; | 551 | pccard_mem_map mem = { .res = &res, }; |
552 | 552 | ||
553 | yenta_set_socket(&socket->socket, &dead_socket); | 553 | yenta_set_socket(&socket->socket, &dead_socket); |
554 | for (i = 0; i < 2; i++) { | 554 | for (i = 0; i < 2; i++) { |
555 | io.map = i; | 555 | io.map = i; |
556 | yenta_set_io_map(&socket->socket, &io); | 556 | yenta_set_io_map(&socket->socket, &io); |
557 | } | 557 | } |
558 | for (i = 0; i < 5; i++) { | 558 | for (i = 0; i < 5; i++) { |
559 | mem.map = i; | 559 | mem.map = i; |
560 | yenta_set_mem_map(&socket->socket, &mem); | 560 | yenta_set_mem_map(&socket->socket, &mem); |
561 | } | 561 | } |
562 | } | 562 | } |
563 | 563 | ||
564 | /* redoes voltage interrogation if required */ | 564 | /* redoes voltage interrogation if required */ |
565 | static void yenta_interrogate(struct yenta_socket *socket) | 565 | static void yenta_interrogate(struct yenta_socket *socket) |
566 | { | 566 | { |
567 | u32 state; | 567 | u32 state; |
568 | 568 | ||
569 | state = cb_readl(socket, CB_SOCKET_STATE); | 569 | state = cb_readl(socket, CB_SOCKET_STATE); |
570 | if (!(state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) || | 570 | if (!(state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) || |
571 | (state & (CB_CDETECT1 | CB_CDETECT2 | CB_NOTACARD | CB_BADVCCREQ)) || | 571 | (state & (CB_CDETECT1 | CB_CDETECT2 | CB_NOTACARD | CB_BADVCCREQ)) || |
572 | ((state & (CB_16BITCARD | CB_CBCARD)) == (CB_16BITCARD | CB_CBCARD))) | 572 | ((state & (CB_16BITCARD | CB_CBCARD)) == (CB_16BITCARD | CB_CBCARD))) |
573 | cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST); | 573 | cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST); |
574 | } | 574 | } |
575 | 575 | ||
576 | /* Called at resume and initialization events */ | 576 | /* Called at resume and initialization events */ |
577 | static int yenta_sock_init(struct pcmcia_socket *sock) | 577 | static int yenta_sock_init(struct pcmcia_socket *sock) |
578 | { | 578 | { |
579 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); | 579 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); |
580 | 580 | ||
581 | exca_writeb(socket, I365_GBLCTL, 0x00); | 581 | exca_writeb(socket, I365_GBLCTL, 0x00); |
582 | exca_writeb(socket, I365_GENCTL, 0x00); | 582 | exca_writeb(socket, I365_GENCTL, 0x00); |
583 | 583 | ||
584 | /* Redo card voltage interrogation */ | 584 | /* Redo card voltage interrogation */ |
585 | yenta_interrogate(socket); | 585 | yenta_interrogate(socket); |
586 | 586 | ||
587 | yenta_clear_maps(socket); | 587 | yenta_clear_maps(socket); |
588 | 588 | ||
589 | if (socket->type && socket->type->sock_init) | 589 | if (socket->type && socket->type->sock_init) |
590 | socket->type->sock_init(socket); | 590 | socket->type->sock_init(socket); |
591 | 591 | ||
592 | /* Re-enable CSC interrupts */ | 592 | /* Re-enable CSC interrupts */ |
593 | cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); | 593 | cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); |
594 | 594 | ||
595 | return 0; | 595 | return 0; |
596 | } | 596 | } |
597 | 597 | ||
598 | static int yenta_sock_suspend(struct pcmcia_socket *sock) | 598 | static int yenta_sock_suspend(struct pcmcia_socket *sock) |
599 | { | 599 | { |
600 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); | 600 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); |
601 | 601 | ||
602 | /* Disable CSC interrupts */ | 602 | /* Disable CSC interrupts */ |
603 | cb_writel(socket, CB_SOCKET_MASK, 0x0); | 603 | cb_writel(socket, CB_SOCKET_MASK, 0x0); |
604 | 604 | ||
605 | return 0; | 605 | return 0; |
606 | } | 606 | } |
607 | 607 | ||
608 | /* | 608 | /* |
609 | * Use an adaptive allocation for the memory resource, | 609 | * Use an adaptive allocation for the memory resource, |
610 | * sometimes the memory behind pci bridges is limited: | 610 | * sometimes the memory behind pci bridges is limited: |
611 | * 1/8 of the size of the io window of the parent. | 611 | * 1/8 of the size of the io window of the parent. |
612 | * max 4 MB, min 16 kB. We try very hard to not get below | 612 | * max 4 MB, min 16 kB. We try very hard to not get below |
613 | * the "ACC" values, though. | 613 | * the "ACC" values, though. |
614 | */ | 614 | */ |
615 | #define BRIDGE_MEM_MAX (4*1024*1024) | 615 | #define BRIDGE_MEM_MAX (4*1024*1024) |
616 | #define BRIDGE_MEM_ACC (128*1024) | 616 | #define BRIDGE_MEM_ACC (128*1024) |
617 | #define BRIDGE_MEM_MIN (16*1024) | 617 | #define BRIDGE_MEM_MIN (16*1024) |
618 | 618 | ||
619 | #define BRIDGE_IO_MAX 512 | 619 | #define BRIDGE_IO_MAX 512 |
620 | #define BRIDGE_IO_ACC 256 | 620 | #define BRIDGE_IO_ACC 256 |
621 | #define BRIDGE_IO_MIN 32 | 621 | #define BRIDGE_IO_MIN 32 |
622 | 622 | ||
623 | #ifndef PCIBIOS_MIN_CARDBUS_IO | 623 | #ifndef PCIBIOS_MIN_CARDBUS_IO |
624 | #define PCIBIOS_MIN_CARDBUS_IO PCIBIOS_MIN_IO | 624 | #define PCIBIOS_MIN_CARDBUS_IO PCIBIOS_MIN_IO |
625 | #endif | 625 | #endif |
626 | 626 | ||
627 | static int yenta_search_one_res(struct resource *root, struct resource *res, | 627 | static int yenta_search_one_res(struct resource *root, struct resource *res, |
628 | u32 min) | 628 | u32 min) |
629 | { | 629 | { |
630 | u32 align, size, start, end; | 630 | u32 align, size, start, end; |
631 | 631 | ||
632 | if (res->flags & IORESOURCE_IO) { | 632 | if (res->flags & IORESOURCE_IO) { |
633 | align = 1024; | 633 | align = 1024; |
634 | size = BRIDGE_IO_MAX; | 634 | size = BRIDGE_IO_MAX; |
635 | start = PCIBIOS_MIN_CARDBUS_IO; | 635 | start = PCIBIOS_MIN_CARDBUS_IO; |
636 | end = ~0U; | 636 | end = ~0U; |
637 | } else { | 637 | } else { |
638 | unsigned long avail = root->end - root->start; | 638 | unsigned long avail = root->end - root->start; |
639 | int i; | 639 | int i; |
640 | size = BRIDGE_MEM_MAX; | 640 | size = BRIDGE_MEM_MAX; |
641 | if (size > avail/8) { | 641 | if (size > avail/8) { |
642 | size = (avail+1)/8; | 642 | size = (avail+1)/8; |
643 | /* round size down to next power of 2 */ | 643 | /* round size down to next power of 2 */ |
644 | i = 0; | 644 | i = 0; |
645 | while ((size /= 2) != 0) | 645 | while ((size /= 2) != 0) |
646 | i++; | 646 | i++; |
647 | size = 1 << i; | 647 | size = 1 << i; |
648 | } | 648 | } |
649 | if (size < min) | 649 | if (size < min) |
650 | size = min; | 650 | size = min; |
651 | align = size; | 651 | align = size; |
652 | start = PCIBIOS_MIN_MEM; | 652 | start = PCIBIOS_MIN_MEM; |
653 | end = ~0U; | 653 | end = ~0U; |
654 | } | 654 | } |
655 | 655 | ||
656 | do { | 656 | do { |
657 | if (allocate_resource(root, res, size, start, end, align, | 657 | if (allocate_resource(root, res, size, start, end, align, |
658 | NULL, NULL) == 0) { | 658 | NULL, NULL) == 0) { |
659 | return 1; | 659 | return 1; |
660 | } | 660 | } |
661 | size = size/2; | 661 | size = size/2; |
662 | align = size; | 662 | align = size; |
663 | } while (size >= min); | 663 | } while (size >= min); |
664 | 664 | ||
665 | return 0; | 665 | return 0; |
666 | } | 666 | } |
667 | 667 | ||
668 | 668 | ||
669 | static int yenta_search_res(struct yenta_socket *socket, struct resource *res, | 669 | static int yenta_search_res(struct yenta_socket *socket, struct resource *res, |
670 | u32 min) | 670 | u32 min) |
671 | { | 671 | { |
672 | struct resource *root; | 672 | struct resource *root; |
673 | int i; | 673 | int i; |
674 | 674 | ||
675 | pci_bus_for_each_resource(socket->dev->bus, root, i) { | 675 | pci_bus_for_each_resource(socket->dev->bus, root, i) { |
676 | if (!root) | 676 | if (!root) |
677 | continue; | 677 | continue; |
678 | 678 | ||
679 | if ((res->flags ^ root->flags) & | 679 | if ((res->flags ^ root->flags) & |
680 | (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH)) | 680 | (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH)) |
681 | continue; /* Wrong type */ | 681 | continue; /* Wrong type */ |
682 | 682 | ||
683 | if (yenta_search_one_res(root, res, min)) | 683 | if (yenta_search_one_res(root, res, min)) |
684 | return 1; | 684 | return 1; |
685 | } | 685 | } |
686 | return 0; | 686 | return 0; |
687 | } | 687 | } |
688 | 688 | ||
689 | static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end) | 689 | static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end) |
690 | { | 690 | { |
691 | struct pci_dev *dev = socket->dev; | 691 | struct pci_dev *dev = socket->dev; |
692 | struct resource *res; | 692 | struct resource *res; |
693 | struct pci_bus_region region; | 693 | struct pci_bus_region region; |
694 | unsigned mask; | 694 | unsigned mask; |
695 | 695 | ||
696 | res = dev->resource + PCI_BRIDGE_RESOURCES + nr; | 696 | res = dev->resource + PCI_BRIDGE_RESOURCES + nr; |
697 | /* Already allocated? */ | 697 | /* Already allocated? */ |
698 | if (res->parent) | 698 | if (res->parent) |
699 | return 0; | 699 | return 0; |
700 | 700 | ||
701 | /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ | 701 | /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ |
702 | mask = ~0xfff; | 702 | mask = ~0xfff; |
703 | if (type & IORESOURCE_IO) | 703 | if (type & IORESOURCE_IO) |
704 | mask = ~3; | 704 | mask = ~3; |
705 | 705 | ||
706 | res->name = dev->subordinate->name; | 706 | res->name = dev->subordinate->name; |
707 | res->flags = type; | 707 | res->flags = type; |
708 | 708 | ||
709 | region.start = config_readl(socket, addr_start) & mask; | 709 | region.start = config_readl(socket, addr_start) & mask; |
710 | region.end = config_readl(socket, addr_end) | ~mask; | 710 | region.end = config_readl(socket, addr_end) | ~mask; |
711 | if (region.start && region.end > region.start && !override_bios) { | 711 | if (region.start && region.end > region.start && !override_bios) { |
712 | pcibios_bus_to_resource(dev->bus, res, ®ion); | 712 | pcibios_bus_to_resource(dev->bus, res, ®ion); |
713 | if (pci_claim_resource(dev, PCI_BRIDGE_RESOURCES + nr) == 0) | 713 | if (pci_claim_resource(dev, PCI_BRIDGE_RESOURCES + nr) == 0) |
714 | return 0; | 714 | return 0; |
715 | dev_printk(KERN_INFO, &dev->dev, | 715 | dev_printk(KERN_INFO, &dev->dev, |
716 | "Preassigned resource %d busy or not available, " | 716 | "Preassigned resource %d busy or not available, " |
717 | "reconfiguring...\n", | 717 | "reconfiguring...\n", |
718 | nr); | 718 | nr); |
719 | } | 719 | } |
720 | 720 | ||
721 | if (type & IORESOURCE_IO) { | 721 | if (type & IORESOURCE_IO) { |
722 | if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) || | 722 | if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) || |
723 | (yenta_search_res(socket, res, BRIDGE_IO_ACC)) || | 723 | (yenta_search_res(socket, res, BRIDGE_IO_ACC)) || |
724 | (yenta_search_res(socket, res, BRIDGE_IO_MIN))) | 724 | (yenta_search_res(socket, res, BRIDGE_IO_MIN))) |
725 | return 1; | 725 | return 1; |
726 | } else { | 726 | } else { |
727 | if (type & IORESOURCE_PREFETCH) { | 727 | if (type & IORESOURCE_PREFETCH) { |
728 | if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) || | 728 | if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) || |
729 | (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || | 729 | (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || |
730 | (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) | 730 | (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) |
731 | return 1; | 731 | return 1; |
732 | /* Approximating prefetchable by non-prefetchable */ | 732 | /* Approximating prefetchable by non-prefetchable */ |
733 | res->flags = IORESOURCE_MEM; | 733 | res->flags = IORESOURCE_MEM; |
734 | } | 734 | } |
735 | if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) || | 735 | if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) || |
736 | (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || | 736 | (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || |
737 | (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) | 737 | (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) |
738 | return 1; | 738 | return 1; |
739 | } | 739 | } |
740 | 740 | ||
741 | dev_printk(KERN_INFO, &dev->dev, | 741 | dev_printk(KERN_INFO, &dev->dev, |
742 | "no resource of type %x available, trying to continue...\n", | 742 | "no resource of type %x available, trying to continue...\n", |
743 | type); | 743 | type); |
744 | res->start = res->end = res->flags = 0; | 744 | res->start = res->end = res->flags = 0; |
745 | return 0; | 745 | return 0; |
746 | } | 746 | } |
747 | 747 | ||
748 | /* | 748 | /* |
749 | * Allocate the bridge mappings for the device.. | 749 | * Allocate the bridge mappings for the device.. |
750 | */ | 750 | */ |
751 | static void yenta_allocate_resources(struct yenta_socket *socket) | 751 | static void yenta_allocate_resources(struct yenta_socket *socket) |
752 | { | 752 | { |
753 | int program = 0; | 753 | int program = 0; |
754 | program += yenta_allocate_res(socket, 0, IORESOURCE_IO, | 754 | program += yenta_allocate_res(socket, 0, IORESOURCE_IO, |
755 | PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0); | 755 | PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0); |
756 | program += yenta_allocate_res(socket, 1, IORESOURCE_IO, | 756 | program += yenta_allocate_res(socket, 1, IORESOURCE_IO, |
757 | PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1); | 757 | PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1); |
758 | program += yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH, | 758 | program += yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH, |
759 | PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0); | 759 | PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0); |
760 | program += yenta_allocate_res(socket, 3, IORESOURCE_MEM, | 760 | program += yenta_allocate_res(socket, 3, IORESOURCE_MEM, |
761 | PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1); | 761 | PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1); |
762 | if (program) | 762 | if (program) |
763 | pci_setup_cardbus(socket->dev->subordinate); | 763 | pci_setup_cardbus(socket->dev->subordinate); |
764 | } | 764 | } |
765 | 765 | ||
766 | 766 | ||
767 | /* | 767 | /* |
768 | * Free the bridge mappings for the device.. | 768 | * Free the bridge mappings for the device.. |
769 | */ | 769 | */ |
770 | static void yenta_free_resources(struct yenta_socket *socket) | 770 | static void yenta_free_resources(struct yenta_socket *socket) |
771 | { | 771 | { |
772 | int i; | 772 | int i; |
773 | for (i = 0; i < 4; i++) { | 773 | for (i = 0; i < 4; i++) { |
774 | struct resource *res; | 774 | struct resource *res; |
775 | res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i; | 775 | res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i; |
776 | if (res->start != 0 && res->end != 0) | 776 | if (res->start != 0 && res->end != 0) |
777 | release_resource(res); | 777 | release_resource(res); |
778 | res->start = res->end = res->flags = 0; | 778 | res->start = res->end = res->flags = 0; |
779 | } | 779 | } |
780 | } | 780 | } |
781 | 781 | ||
782 | 782 | ||
783 | /* | 783 | /* |
784 | * Close it down - release our resources and go home.. | 784 | * Close it down - release our resources and go home.. |
785 | */ | 785 | */ |
786 | static void yenta_close(struct pci_dev *dev) | 786 | static void yenta_close(struct pci_dev *dev) |
787 | { | 787 | { |
788 | struct yenta_socket *sock = pci_get_drvdata(dev); | 788 | struct yenta_socket *sock = pci_get_drvdata(dev); |
789 | 789 | ||
790 | /* Remove the register attributes */ | 790 | /* Remove the register attributes */ |
791 | device_remove_file(&dev->dev, &dev_attr_yenta_registers); | 791 | device_remove_file(&dev->dev, &dev_attr_yenta_registers); |
792 | 792 | ||
793 | /* we don't want a dying socket registered */ | 793 | /* we don't want a dying socket registered */ |
794 | pcmcia_unregister_socket(&sock->socket); | 794 | pcmcia_unregister_socket(&sock->socket); |
795 | 795 | ||
796 | /* Disable all events so we don't die in an IRQ storm */ | 796 | /* Disable all events so we don't die in an IRQ storm */ |
797 | cb_writel(sock, CB_SOCKET_MASK, 0x0); | 797 | cb_writel(sock, CB_SOCKET_MASK, 0x0); |
798 | exca_writeb(sock, I365_CSCINT, 0); | 798 | exca_writeb(sock, I365_CSCINT, 0); |
799 | 799 | ||
800 | if (sock->cb_irq) | 800 | if (sock->cb_irq) |
801 | free_irq(sock->cb_irq, sock); | 801 | free_irq(sock->cb_irq, sock); |
802 | else | 802 | else |
803 | del_timer_sync(&sock->poll_timer); | 803 | del_timer_sync(&sock->poll_timer); |
804 | 804 | ||
805 | if (sock->base) | 805 | if (sock->base) |
806 | iounmap(sock->base); | 806 | iounmap(sock->base); |
807 | yenta_free_resources(sock); | 807 | yenta_free_resources(sock); |
808 | 808 | ||
809 | pci_release_regions(dev); | 809 | pci_release_regions(dev); |
810 | pci_disable_device(dev); | 810 | pci_disable_device(dev); |
811 | pci_set_drvdata(dev, NULL); | 811 | pci_set_drvdata(dev, NULL); |
812 | } | 812 | } |
813 | 813 | ||
814 | 814 | ||
815 | static struct pccard_operations yenta_socket_operations = { | 815 | static struct pccard_operations yenta_socket_operations = { |
816 | .init = yenta_sock_init, | 816 | .init = yenta_sock_init, |
817 | .suspend = yenta_sock_suspend, | 817 | .suspend = yenta_sock_suspend, |
818 | .get_status = yenta_get_status, | 818 | .get_status = yenta_get_status, |
819 | .set_socket = yenta_set_socket, | 819 | .set_socket = yenta_set_socket, |
820 | .set_io_map = yenta_set_io_map, | 820 | .set_io_map = yenta_set_io_map, |
821 | .set_mem_map = yenta_set_mem_map, | 821 | .set_mem_map = yenta_set_mem_map, |
822 | }; | 822 | }; |
823 | 823 | ||
824 | 824 | ||
825 | #ifdef CONFIG_YENTA_TI | 825 | #ifdef CONFIG_YENTA_TI |
826 | #include "ti113x.h" | 826 | #include "ti113x.h" |
827 | #endif | 827 | #endif |
828 | #ifdef CONFIG_YENTA_RICOH | 828 | #ifdef CONFIG_YENTA_RICOH |
829 | #include "ricoh.h" | 829 | #include "ricoh.h" |
830 | #endif | 830 | #endif |
831 | #ifdef CONFIG_YENTA_TOSHIBA | 831 | #ifdef CONFIG_YENTA_TOSHIBA |
832 | #include "topic.h" | 832 | #include "topic.h" |
833 | #endif | 833 | #endif |
834 | #ifdef CONFIG_YENTA_O2 | 834 | #ifdef CONFIG_YENTA_O2 |
835 | #include "o2micro.h" | 835 | #include "o2micro.h" |
836 | #endif | 836 | #endif |
837 | 837 | ||
838 | enum { | 838 | enum { |
839 | CARDBUS_TYPE_DEFAULT = -1, | 839 | CARDBUS_TYPE_DEFAULT = -1, |
840 | CARDBUS_TYPE_TI, | 840 | CARDBUS_TYPE_TI, |
841 | CARDBUS_TYPE_TI113X, | 841 | CARDBUS_TYPE_TI113X, |
842 | CARDBUS_TYPE_TI12XX, | 842 | CARDBUS_TYPE_TI12XX, |
843 | CARDBUS_TYPE_TI1250, | 843 | CARDBUS_TYPE_TI1250, |
844 | CARDBUS_TYPE_RICOH, | 844 | CARDBUS_TYPE_RICOH, |
845 | CARDBUS_TYPE_TOPIC95, | 845 | CARDBUS_TYPE_TOPIC95, |
846 | CARDBUS_TYPE_TOPIC97, | 846 | CARDBUS_TYPE_TOPIC97, |
847 | CARDBUS_TYPE_O2MICRO, | 847 | CARDBUS_TYPE_O2MICRO, |
848 | CARDBUS_TYPE_ENE, | 848 | CARDBUS_TYPE_ENE, |
849 | }; | 849 | }; |
850 | 850 | ||
851 | /* | 851 | /* |
852 | * Different cardbus controllers have slightly different | 852 | * Different cardbus controllers have slightly different |
853 | * initialization sequences etc details. List them here.. | 853 | * initialization sequences etc details. List them here.. |
854 | */ | 854 | */ |
855 | static struct cardbus_type cardbus_type[] = { | 855 | static struct cardbus_type cardbus_type[] = { |
856 | #ifdef CONFIG_YENTA_TI | 856 | #ifdef CONFIG_YENTA_TI |
857 | [CARDBUS_TYPE_TI] = { | 857 | [CARDBUS_TYPE_TI] = { |
858 | .override = ti_override, | 858 | .override = ti_override, |
859 | .save_state = ti_save_state, | 859 | .save_state = ti_save_state, |
860 | .restore_state = ti_restore_state, | 860 | .restore_state = ti_restore_state, |
861 | .sock_init = ti_init, | 861 | .sock_init = ti_init, |
862 | }, | 862 | }, |
863 | [CARDBUS_TYPE_TI113X] = { | 863 | [CARDBUS_TYPE_TI113X] = { |
864 | .override = ti113x_override, | 864 | .override = ti113x_override, |
865 | .save_state = ti_save_state, | 865 | .save_state = ti_save_state, |
866 | .restore_state = ti_restore_state, | 866 | .restore_state = ti_restore_state, |
867 | .sock_init = ti_init, | 867 | .sock_init = ti_init, |
868 | }, | 868 | }, |
869 | [CARDBUS_TYPE_TI12XX] = { | 869 | [CARDBUS_TYPE_TI12XX] = { |
870 | .override = ti12xx_override, | 870 | .override = ti12xx_override, |
871 | .save_state = ti_save_state, | 871 | .save_state = ti_save_state, |
872 | .restore_state = ti_restore_state, | 872 | .restore_state = ti_restore_state, |
873 | .sock_init = ti_init, | 873 | .sock_init = ti_init, |
874 | }, | 874 | }, |
875 | [CARDBUS_TYPE_TI1250] = { | 875 | [CARDBUS_TYPE_TI1250] = { |
876 | .override = ti1250_override, | 876 | .override = ti1250_override, |
877 | .save_state = ti_save_state, | 877 | .save_state = ti_save_state, |
878 | .restore_state = ti_restore_state, | 878 | .restore_state = ti_restore_state, |
879 | .sock_init = ti_init, | 879 | .sock_init = ti_init, |
880 | }, | 880 | }, |
881 | [CARDBUS_TYPE_ENE] = { | 881 | [CARDBUS_TYPE_ENE] = { |
882 | .override = ene_override, | 882 | .override = ene_override, |
883 | .save_state = ti_save_state, | 883 | .save_state = ti_save_state, |
884 | .restore_state = ti_restore_state, | 884 | .restore_state = ti_restore_state, |
885 | .sock_init = ti_init, | 885 | .sock_init = ti_init, |
886 | }, | 886 | }, |
887 | #endif | 887 | #endif |
888 | #ifdef CONFIG_YENTA_RICOH | 888 | #ifdef CONFIG_YENTA_RICOH |
889 | [CARDBUS_TYPE_RICOH] = { | 889 | [CARDBUS_TYPE_RICOH] = { |
890 | .override = ricoh_override, | 890 | .override = ricoh_override, |
891 | .save_state = ricoh_save_state, | 891 | .save_state = ricoh_save_state, |
892 | .restore_state = ricoh_restore_state, | 892 | .restore_state = ricoh_restore_state, |
893 | }, | 893 | }, |
894 | #endif | 894 | #endif |
895 | #ifdef CONFIG_YENTA_TOSHIBA | 895 | #ifdef CONFIG_YENTA_TOSHIBA |
896 | [CARDBUS_TYPE_TOPIC95] = { | 896 | [CARDBUS_TYPE_TOPIC95] = { |
897 | .override = topic95_override, | 897 | .override = topic95_override, |
898 | }, | 898 | }, |
899 | [CARDBUS_TYPE_TOPIC97] = { | 899 | [CARDBUS_TYPE_TOPIC97] = { |
900 | .override = topic97_override, | 900 | .override = topic97_override, |
901 | }, | 901 | }, |
902 | #endif | 902 | #endif |
903 | #ifdef CONFIG_YENTA_O2 | 903 | #ifdef CONFIG_YENTA_O2 |
904 | [CARDBUS_TYPE_O2MICRO] = { | 904 | [CARDBUS_TYPE_O2MICRO] = { |
905 | .override = o2micro_override, | 905 | .override = o2micro_override, |
906 | .restore_state = o2micro_restore_state, | 906 | .restore_state = o2micro_restore_state, |
907 | }, | 907 | }, |
908 | #endif | 908 | #endif |
909 | }; | 909 | }; |
910 | 910 | ||
911 | 911 | ||
912 | static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mask) | 912 | static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mask) |
913 | { | 913 | { |
914 | int i; | 914 | int i; |
915 | unsigned long val; | 915 | unsigned long val; |
916 | u32 mask; | 916 | u32 mask; |
917 | u8 reg; | 917 | u8 reg; |
918 | 918 | ||
919 | /* | 919 | /* |
920 | * Probe for usable interrupts using the force | 920 | * Probe for usable interrupts using the force |
921 | * register to generate bogus card status events. | 921 | * register to generate bogus card status events. |
922 | */ | 922 | */ |
923 | cb_writel(socket, CB_SOCKET_EVENT, -1); | 923 | cb_writel(socket, CB_SOCKET_EVENT, -1); |
924 | cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); | 924 | cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); |
925 | reg = exca_readb(socket, I365_CSCINT); | 925 | reg = exca_readb(socket, I365_CSCINT); |
926 | exca_writeb(socket, I365_CSCINT, 0); | 926 | exca_writeb(socket, I365_CSCINT, 0); |
927 | val = probe_irq_on() & isa_irq_mask; | 927 | val = probe_irq_on() & isa_irq_mask; |
928 | for (i = 1; i < 16; i++) { | 928 | for (i = 1; i < 16; i++) { |
929 | if (!((val >> i) & 1)) | 929 | if (!((val >> i) & 1)) |
930 | continue; | 930 | continue; |
931 | exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG | (i << 4)); | 931 | exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG | (i << 4)); |
932 | cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); | 932 | cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); |
933 | udelay(100); | 933 | udelay(100); |
934 | cb_writel(socket, CB_SOCKET_EVENT, -1); | 934 | cb_writel(socket, CB_SOCKET_EVENT, -1); |
935 | } | 935 | } |
936 | cb_writel(socket, CB_SOCKET_MASK, 0); | 936 | cb_writel(socket, CB_SOCKET_MASK, 0); |
937 | exca_writeb(socket, I365_CSCINT, reg); | 937 | exca_writeb(socket, I365_CSCINT, reg); |
938 | 938 | ||
939 | mask = probe_irq_mask(val) & 0xffff; | 939 | mask = probe_irq_mask(val) & 0xffff; |
940 | 940 | ||
941 | return mask; | 941 | return mask; |
942 | } | 942 | } |
943 | 943 | ||
944 | 944 | ||
945 | /* | 945 | /* |
946 | * yenta PCI irq probing. | 946 | * yenta PCI irq probing. |
947 | * currently only used in the TI/EnE initialization code | 947 | * currently only used in the TI/EnE initialization code |
948 | */ | 948 | */ |
949 | #ifdef CONFIG_YENTA_TI | 949 | #ifdef CONFIG_YENTA_TI |
950 | 950 | ||
951 | /* interrupt handler, only used during probing */ | 951 | /* interrupt handler, only used during probing */ |
952 | static irqreturn_t yenta_probe_handler(int irq, void *dev_id) | 952 | static irqreturn_t yenta_probe_handler(int irq, void *dev_id) |
953 | { | 953 | { |
954 | struct yenta_socket *socket = (struct yenta_socket *) dev_id; | 954 | struct yenta_socket *socket = (struct yenta_socket *) dev_id; |
955 | u8 csc; | 955 | u8 csc; |
956 | u32 cb_event; | 956 | u32 cb_event; |
957 | 957 | ||
958 | /* Clear interrupt status for the event */ | 958 | /* Clear interrupt status for the event */ |
959 | cb_event = cb_readl(socket, CB_SOCKET_EVENT); | 959 | cb_event = cb_readl(socket, CB_SOCKET_EVENT); |
960 | cb_writel(socket, CB_SOCKET_EVENT, -1); | 960 | cb_writel(socket, CB_SOCKET_EVENT, -1); |
961 | csc = exca_readb(socket, I365_CSC); | 961 | csc = exca_readb(socket, I365_CSC); |
962 | 962 | ||
963 | if (cb_event || csc) { | 963 | if (cb_event || csc) { |
964 | socket->probe_status = 1; | 964 | socket->probe_status = 1; |
965 | return IRQ_HANDLED; | 965 | return IRQ_HANDLED; |
966 | } | 966 | } |
967 | 967 | ||
968 | return IRQ_NONE; | 968 | return IRQ_NONE; |
969 | } | 969 | } |
970 | 970 | ||
971 | /* probes the PCI interrupt, use only on override functions */ | 971 | /* probes the PCI interrupt, use only on override functions */ |
972 | static int yenta_probe_cb_irq(struct yenta_socket *socket) | 972 | static int yenta_probe_cb_irq(struct yenta_socket *socket) |
973 | { | 973 | { |
974 | u8 reg = 0; | 974 | u8 reg = 0; |
975 | 975 | ||
976 | if (!socket->cb_irq) | 976 | if (!socket->cb_irq) |
977 | return -1; | 977 | return -1; |
978 | 978 | ||
979 | socket->probe_status = 0; | 979 | socket->probe_status = 0; |
980 | 980 | ||
981 | if (request_irq(socket->cb_irq, yenta_probe_handler, IRQF_SHARED, "yenta", socket)) { | 981 | if (request_irq(socket->cb_irq, yenta_probe_handler, IRQF_SHARED, "yenta", socket)) { |
982 | dev_printk(KERN_WARNING, &socket->dev->dev, | 982 | dev_printk(KERN_WARNING, &socket->dev->dev, |
983 | "request_irq() in yenta_probe_cb_irq() failed!\n"); | 983 | "request_irq() in yenta_probe_cb_irq() failed!\n"); |
984 | return -1; | 984 | return -1; |
985 | } | 985 | } |
986 | 986 | ||
987 | /* generate interrupt, wait */ | 987 | /* generate interrupt, wait */ |
988 | if (!socket->dev->irq) | 988 | if (!socket->dev->irq) |
989 | reg = exca_readb(socket, I365_CSCINT); | 989 | reg = exca_readb(socket, I365_CSCINT); |
990 | exca_writeb(socket, I365_CSCINT, reg | I365_CSC_STSCHG); | 990 | exca_writeb(socket, I365_CSCINT, reg | I365_CSC_STSCHG); |
991 | cb_writel(socket, CB_SOCKET_EVENT, -1); | 991 | cb_writel(socket, CB_SOCKET_EVENT, -1); |
992 | cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); | 992 | cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); |
993 | cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); | 993 | cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); |
994 | 994 | ||
995 | msleep(100); | 995 | msleep(100); |
996 | 996 | ||
997 | /* disable interrupts */ | 997 | /* disable interrupts */ |
998 | cb_writel(socket, CB_SOCKET_MASK, 0); | 998 | cb_writel(socket, CB_SOCKET_MASK, 0); |
999 | exca_writeb(socket, I365_CSCINT, reg); | 999 | exca_writeb(socket, I365_CSCINT, reg); |
1000 | cb_writel(socket, CB_SOCKET_EVENT, -1); | 1000 | cb_writel(socket, CB_SOCKET_EVENT, -1); |
1001 | exca_readb(socket, I365_CSC); | 1001 | exca_readb(socket, I365_CSC); |
1002 | 1002 | ||
1003 | free_irq(socket->cb_irq, socket); | 1003 | free_irq(socket->cb_irq, socket); |
1004 | 1004 | ||
1005 | return (int) socket->probe_status; | 1005 | return (int) socket->probe_status; |
1006 | } | 1006 | } |
1007 | 1007 | ||
1008 | #endif /* CONFIG_YENTA_TI */ | 1008 | #endif /* CONFIG_YENTA_TI */ |
1009 | 1009 | ||
1010 | 1010 | ||
1011 | /* | 1011 | /* |
1012 | * Set static data that doesn't need re-initializing.. | 1012 | * Set static data that doesn't need re-initializing.. |
1013 | */ | 1013 | */ |
1014 | static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_irq_mask) | 1014 | static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_irq_mask) |
1015 | { | 1015 | { |
1016 | socket->socket.pci_irq = socket->cb_irq; | 1016 | socket->socket.pci_irq = socket->cb_irq; |
1017 | if (isa_probe) | 1017 | if (isa_probe) |
1018 | socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask); | 1018 | socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask); |
1019 | else | 1019 | else |
1020 | socket->socket.irq_mask = 0; | 1020 | socket->socket.irq_mask = 0; |
1021 | 1021 | ||
1022 | dev_printk(KERN_INFO, &socket->dev->dev, | 1022 | dev_printk(KERN_INFO, &socket->dev->dev, |
1023 | "ISA IRQ mask 0x%04x, PCI irq %d\n", | 1023 | "ISA IRQ mask 0x%04x, PCI irq %d\n", |
1024 | socket->socket.irq_mask, socket->cb_irq); | 1024 | socket->socket.irq_mask, socket->cb_irq); |
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | /* | 1027 | /* |
1028 | * Initialize the standard cardbus registers | 1028 | * Initialize the standard cardbus registers |
1029 | */ | 1029 | */ |
1030 | static void yenta_config_init(struct yenta_socket *socket) | 1030 | static void yenta_config_init(struct yenta_socket *socket) |
1031 | { | 1031 | { |
1032 | u16 bridge; | 1032 | u16 bridge; |
1033 | struct pci_dev *dev = socket->dev; | 1033 | struct pci_dev *dev = socket->dev; |
1034 | struct pci_bus_region region; | 1034 | struct pci_bus_region region; |
1035 | 1035 | ||
1036 | pcibios_resource_to_bus(socket->dev->bus, ®ion, &dev->resource[0]); | 1036 | pcibios_resource_to_bus(socket->dev->bus, ®ion, &dev->resource[0]); |
1037 | 1037 | ||
1038 | config_writel(socket, CB_LEGACY_MODE_BASE, 0); | 1038 | config_writel(socket, CB_LEGACY_MODE_BASE, 0); |
1039 | config_writel(socket, PCI_BASE_ADDRESS_0, region.start); | 1039 | config_writel(socket, PCI_BASE_ADDRESS_0, region.start); |
1040 | config_writew(socket, PCI_COMMAND, | 1040 | config_writew(socket, PCI_COMMAND, |
1041 | PCI_COMMAND_IO | | 1041 | PCI_COMMAND_IO | |
1042 | PCI_COMMAND_MEMORY | | 1042 | PCI_COMMAND_MEMORY | |
1043 | PCI_COMMAND_MASTER | | 1043 | PCI_COMMAND_MASTER | |
1044 | PCI_COMMAND_WAIT); | 1044 | PCI_COMMAND_WAIT); |
1045 | 1045 | ||
1046 | /* MAGIC NUMBERS! Fixme */ | 1046 | /* MAGIC NUMBERS! Fixme */ |
1047 | config_writeb(socket, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4); | 1047 | config_writeb(socket, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4); |
1048 | config_writeb(socket, PCI_LATENCY_TIMER, 168); | 1048 | config_writeb(socket, PCI_LATENCY_TIMER, 168); |
1049 | config_writel(socket, PCI_PRIMARY_BUS, | 1049 | config_writel(socket, PCI_PRIMARY_BUS, |
1050 | (176 << 24) | /* sec. latency timer */ | 1050 | (176 << 24) | /* sec. latency timer */ |
1051 | ((unsigned int)dev->subordinate->busn_res.end << 16) | /* subordinate bus */ | 1051 | ((unsigned int)dev->subordinate->busn_res.end << 16) | /* subordinate bus */ |
1052 | ((unsigned int)dev->subordinate->busn_res.start << 8) | /* secondary bus */ | 1052 | ((unsigned int)dev->subordinate->busn_res.start << 8) | /* secondary bus */ |
1053 | dev->subordinate->primary); /* primary bus */ | 1053 | dev->subordinate->primary); /* primary bus */ |
1054 | 1054 | ||
1055 | /* | 1055 | /* |
1056 | * Set up the bridging state: | 1056 | * Set up the bridging state: |
1057 | * - enable write posting. | 1057 | * - enable write posting. |
1058 | * - memory window 0 prefetchable, window 1 non-prefetchable | 1058 | * - memory window 0 prefetchable, window 1 non-prefetchable |
1059 | * - PCI interrupts enabled if a PCI interrupt exists.. | 1059 | * - PCI interrupts enabled if a PCI interrupt exists.. |
1060 | */ | 1060 | */ |
1061 | bridge = config_readw(socket, CB_BRIDGE_CONTROL); | 1061 | bridge = config_readw(socket, CB_BRIDGE_CONTROL); |
1062 | bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN); | 1062 | bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN); |
1063 | bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN; | 1063 | bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN; |
1064 | config_writew(socket, CB_BRIDGE_CONTROL, bridge); | 1064 | config_writew(socket, CB_BRIDGE_CONTROL, bridge); |
1065 | } | 1065 | } |
1066 | 1066 | ||
1067 | /** | 1067 | /** |
1068 | * yenta_fixup_parent_bridge - Fix subordinate bus# of the parent bridge | 1068 | * yenta_fixup_parent_bridge - Fix subordinate bus# of the parent bridge |
1069 | * @cardbus_bridge: The PCI bus which the CardBus bridge bridges to | 1069 | * @cardbus_bridge: The PCI bus which the CardBus bridge bridges to |
1070 | * | 1070 | * |
1071 | * Checks if devices on the bus which the CardBus bridge bridges to would be | 1071 | * Checks if devices on the bus which the CardBus bridge bridges to would be |
1072 | * invisible during PCI scans because of a misconfigured subordinate number | 1072 | * invisible during PCI scans because of a misconfigured subordinate number |
1073 | * of the parent brige - some BIOSes seem to be too lazy to set it right. | 1073 | * of the parent brige - some BIOSes seem to be too lazy to set it right. |
1074 | * Does the fixup carefully by checking how far it can go without conflicts. | 1074 | * Does the fixup carefully by checking how far it can go without conflicts. |
1075 | * See http://bugzilla.kernel.org/show_bug.cgi?id=2944 for more information. | 1075 | * See http://bugzilla.kernel.org/show_bug.cgi?id=2944 for more information. |
1076 | */ | 1076 | */ |
1077 | static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge) | 1077 | static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge) |
1078 | { | 1078 | { |
1079 | struct pci_bus *sibling; | 1079 | struct pci_bus *sibling; |
1080 | unsigned char upper_limit; | 1080 | unsigned char upper_limit; |
1081 | /* | 1081 | /* |
1082 | * We only check and fix the parent bridge: All systems which need | 1082 | * We only check and fix the parent bridge: All systems which need |
1083 | * this fixup that have been reviewed are laptops and the only bridge | 1083 | * this fixup that have been reviewed are laptops and the only bridge |
1084 | * which needed fixing was the parent bridge of the CardBus bridge: | 1084 | * which needed fixing was the parent bridge of the CardBus bridge: |
1085 | */ | 1085 | */ |
1086 | struct pci_bus *bridge_to_fix = cardbus_bridge->parent; | 1086 | struct pci_bus *bridge_to_fix = cardbus_bridge->parent; |
1087 | 1087 | ||
1088 | /* Check bus numbers are already set up correctly: */ | 1088 | /* Check bus numbers are already set up correctly: */ |
1089 | if (bridge_to_fix->busn_res.end >= cardbus_bridge->busn_res.end) | 1089 | if (bridge_to_fix->busn_res.end >= cardbus_bridge->busn_res.end) |
1090 | return; /* The subordinate number is ok, nothing to do */ | 1090 | return; /* The subordinate number is ok, nothing to do */ |
1091 | 1091 | ||
1092 | if (!bridge_to_fix->parent) | 1092 | if (!bridge_to_fix->parent) |
1093 | return; /* Root bridges are ok */ | 1093 | return; /* Root bridges are ok */ |
1094 | 1094 | ||
1095 | /* stay within the limits of the bus range of the parent: */ | 1095 | /* stay within the limits of the bus range of the parent: */ |
1096 | upper_limit = bridge_to_fix->parent->busn_res.end; | 1096 | upper_limit = bridge_to_fix->parent->busn_res.end; |
1097 | 1097 | ||
1098 | /* check the bus ranges of all sibling bridges to prevent overlap */ | 1098 | /* check the bus ranges of all sibling bridges to prevent overlap */ |
1099 | list_for_each_entry(sibling, &bridge_to_fix->parent->children, | 1099 | list_for_each_entry(sibling, &bridge_to_fix->parent->children, |
1100 | node) { | 1100 | node) { |
1101 | /* | 1101 | /* |
1102 | * If the sibling has a higher secondary bus number | 1102 | * If the sibling has a higher secondary bus number |
1103 | * and it's secondary is equal or smaller than our | 1103 | * and it's secondary is equal or smaller than our |
1104 | * current upper limit, set the new upper limit to | 1104 | * current upper limit, set the new upper limit to |
1105 | * the bus number below the sibling's range: | 1105 | * the bus number below the sibling's range: |
1106 | */ | 1106 | */ |
1107 | if (sibling->busn_res.start > bridge_to_fix->busn_res.end | 1107 | if (sibling->busn_res.start > bridge_to_fix->busn_res.end |
1108 | && sibling->busn_res.start <= upper_limit) | 1108 | && sibling->busn_res.start <= upper_limit) |
1109 | upper_limit = sibling->busn_res.start - 1; | 1109 | upper_limit = sibling->busn_res.start - 1; |
1110 | } | 1110 | } |
1111 | 1111 | ||
1112 | /* Show that the wanted subordinate number is not possible: */ | 1112 | /* Show that the wanted subordinate number is not possible: */ |
1113 | if (cardbus_bridge->busn_res.end > upper_limit) | 1113 | if (cardbus_bridge->busn_res.end > upper_limit) |
1114 | dev_printk(KERN_WARNING, &cardbus_bridge->dev, | 1114 | dev_printk(KERN_WARNING, &cardbus_bridge->dev, |
1115 | "Upper limit for fixing this " | 1115 | "Upper limit for fixing this " |
1116 | "bridge's parent bridge: #%02x\n", upper_limit); | 1116 | "bridge's parent bridge: #%02x\n", upper_limit); |
1117 | 1117 | ||
1118 | /* If we have room to increase the bridge's subordinate number, */ | 1118 | /* If we have room to increase the bridge's subordinate number, */ |
1119 | if (bridge_to_fix->busn_res.end < upper_limit) { | 1119 | if (bridge_to_fix->busn_res.end < upper_limit) { |
1120 | 1120 | ||
1121 | /* use the highest number of the hidden bus, within limits */ | 1121 | /* use the highest number of the hidden bus, within limits */ |
1122 | unsigned char subordinate_to_assign = | 1122 | unsigned char subordinate_to_assign = |
1123 | min_t(int, cardbus_bridge->busn_res.end, upper_limit); | 1123 | min_t(int, cardbus_bridge->busn_res.end, upper_limit); |
1124 | 1124 | ||
1125 | dev_printk(KERN_INFO, &bridge_to_fix->dev, | 1125 | dev_printk(KERN_INFO, &bridge_to_fix->dev, |
1126 | "Raising subordinate bus# of parent " | 1126 | "Raising subordinate bus# of parent " |
1127 | "bus (#%02x) from #%02x to #%02x\n", | 1127 | "bus (#%02x) from #%02x to #%02x\n", |
1128 | bridge_to_fix->number, | 1128 | bridge_to_fix->number, |
1129 | (int)bridge_to_fix->busn_res.end, subordinate_to_assign); | 1129 | (int)bridge_to_fix->busn_res.end, subordinate_to_assign); |
1130 | 1130 | ||
1131 | /* Save the new subordinate in the bus struct of the bridge */ | 1131 | /* Save the new subordinate in the bus struct of the bridge */ |
1132 | bridge_to_fix->busn_res.end = subordinate_to_assign; | 1132 | bridge_to_fix->busn_res.end = subordinate_to_assign; |
1133 | 1133 | ||
1134 | /* and update the PCI config space with the new subordinate */ | 1134 | /* and update the PCI config space with the new subordinate */ |
1135 | pci_write_config_byte(bridge_to_fix->self, | 1135 | pci_write_config_byte(bridge_to_fix->self, |
1136 | PCI_SUBORDINATE_BUS, bridge_to_fix->busn_res.end); | 1136 | PCI_SUBORDINATE_BUS, bridge_to_fix->busn_res.end); |
1137 | } | 1137 | } |
1138 | } | 1138 | } |
1139 | 1139 | ||
1140 | /* | 1140 | /* |
1141 | * Initialize a cardbus controller. Make sure we have a usable | 1141 | * Initialize a cardbus controller. Make sure we have a usable |
1142 | * interrupt, and that we can map the cardbus area. Fill in the | 1142 | * interrupt, and that we can map the cardbus area. Fill in the |
1143 | * socket information structure.. | 1143 | * socket information structure.. |
1144 | */ | 1144 | */ |
1145 | static int yenta_probe(struct pci_dev *dev, const struct pci_device_id *id) | 1145 | static int yenta_probe(struct pci_dev *dev, const struct pci_device_id *id) |
1146 | { | 1146 | { |
1147 | struct yenta_socket *socket; | 1147 | struct yenta_socket *socket; |
1148 | int ret; | 1148 | int ret; |
1149 | 1149 | ||
1150 | /* | 1150 | /* |
1151 | * If we failed to assign proper bus numbers for this cardbus | 1151 | * If we failed to assign proper bus numbers for this cardbus |
1152 | * controller during PCI probe, its subordinate pci_bus is NULL. | 1152 | * controller during PCI probe, its subordinate pci_bus is NULL. |
1153 | * Bail out if so. | 1153 | * Bail out if so. |
1154 | */ | 1154 | */ |
1155 | if (!dev->subordinate) { | 1155 | if (!dev->subordinate) { |
1156 | dev_printk(KERN_ERR, &dev->dev, "no bus associated! " | 1156 | dev_printk(KERN_ERR, &dev->dev, "no bus associated! " |
1157 | "(try 'pci=assign-busses')\n"); | 1157 | "(try 'pci=assign-busses')\n"); |
1158 | return -ENODEV; | 1158 | return -ENODEV; |
1159 | } | 1159 | } |
1160 | 1160 | ||
1161 | socket = kzalloc(sizeof(struct yenta_socket), GFP_KERNEL); | 1161 | socket = kzalloc(sizeof(struct yenta_socket), GFP_KERNEL); |
1162 | if (!socket) | 1162 | if (!socket) |
1163 | return -ENOMEM; | 1163 | return -ENOMEM; |
1164 | 1164 | ||
1165 | /* prepare pcmcia_socket */ | 1165 | /* prepare pcmcia_socket */ |
1166 | socket->socket.ops = ¥ta_socket_operations; | 1166 | socket->socket.ops = ¥ta_socket_operations; |
1167 | socket->socket.resource_ops = &pccard_nonstatic_ops; | 1167 | socket->socket.resource_ops = &pccard_nonstatic_ops; |
1168 | socket->socket.dev.parent = &dev->dev; | 1168 | socket->socket.dev.parent = &dev->dev; |
1169 | socket->socket.driver_data = socket; | 1169 | socket->socket.driver_data = socket; |
1170 | socket->socket.owner = THIS_MODULE; | 1170 | socket->socket.owner = THIS_MODULE; |
1171 | socket->socket.features = SS_CAP_PAGE_REGS | SS_CAP_PCCARD; | 1171 | socket->socket.features = SS_CAP_PAGE_REGS | SS_CAP_PCCARD; |
1172 | socket->socket.map_size = 0x1000; | 1172 | socket->socket.map_size = 0x1000; |
1173 | socket->socket.cb_dev = dev; | 1173 | socket->socket.cb_dev = dev; |
1174 | 1174 | ||
1175 | /* prepare struct yenta_socket */ | 1175 | /* prepare struct yenta_socket */ |
1176 | socket->dev = dev; | 1176 | socket->dev = dev; |
1177 | pci_set_drvdata(dev, socket); | 1177 | pci_set_drvdata(dev, socket); |
1178 | 1178 | ||
1179 | /* | 1179 | /* |
1180 | * Do some basic sanity checking.. | 1180 | * Do some basic sanity checking.. |
1181 | */ | 1181 | */ |
1182 | if (pci_enable_device(dev)) { | 1182 | if (pci_enable_device(dev)) { |
1183 | ret = -EBUSY; | 1183 | ret = -EBUSY; |
1184 | goto free; | 1184 | goto free; |
1185 | } | 1185 | } |
1186 | 1186 | ||
1187 | ret = pci_request_regions(dev, "yenta_socket"); | 1187 | ret = pci_request_regions(dev, "yenta_socket"); |
1188 | if (ret) | 1188 | if (ret) |
1189 | goto disable; | 1189 | goto disable; |
1190 | 1190 | ||
1191 | if (!pci_resource_start(dev, 0)) { | 1191 | if (!pci_resource_start(dev, 0)) { |
1192 | dev_printk(KERN_ERR, &dev->dev, "No cardbus resource!\n"); | 1192 | dev_printk(KERN_ERR, &dev->dev, "No cardbus resource!\n"); |
1193 | ret = -ENODEV; | 1193 | ret = -ENODEV; |
1194 | goto release; | 1194 | goto release; |
1195 | } | 1195 | } |
1196 | 1196 | ||
1197 | /* | 1197 | /* |
1198 | * Ok, start setup.. Map the cardbus registers, | 1198 | * Ok, start setup.. Map the cardbus registers, |
1199 | * and request the IRQ. | 1199 | * and request the IRQ. |
1200 | */ | 1200 | */ |
1201 | socket->base = ioremap(pci_resource_start(dev, 0), 0x1000); | 1201 | socket->base = ioremap(pci_resource_start(dev, 0), 0x1000); |
1202 | if (!socket->base) { | 1202 | if (!socket->base) { |
1203 | ret = -ENOMEM; | 1203 | ret = -ENOMEM; |
1204 | goto release; | 1204 | goto release; |
1205 | } | 1205 | } |
1206 | 1206 | ||
1207 | /* | 1207 | /* |
1208 | * report the subsystem vendor and device for help debugging | 1208 | * report the subsystem vendor and device for help debugging |
1209 | * the irq stuff... | 1209 | * the irq stuff... |
1210 | */ | 1210 | */ |
1211 | dev_printk(KERN_INFO, &dev->dev, "CardBus bridge found [%04x:%04x]\n", | 1211 | dev_printk(KERN_INFO, &dev->dev, "CardBus bridge found [%04x:%04x]\n", |
1212 | dev->subsystem_vendor, dev->subsystem_device); | 1212 | dev->subsystem_vendor, dev->subsystem_device); |
1213 | 1213 | ||
1214 | yenta_config_init(socket); | 1214 | yenta_config_init(socket); |
1215 | 1215 | ||
1216 | /* Disable all events */ | 1216 | /* Disable all events */ |
1217 | cb_writel(socket, CB_SOCKET_MASK, 0x0); | 1217 | cb_writel(socket, CB_SOCKET_MASK, 0x0); |
1218 | 1218 | ||
1219 | /* Set up the bridge regions.. */ | 1219 | /* Set up the bridge regions.. */ |
1220 | yenta_allocate_resources(socket); | 1220 | yenta_allocate_resources(socket); |
1221 | 1221 | ||
1222 | socket->cb_irq = dev->irq; | 1222 | socket->cb_irq = dev->irq; |
1223 | 1223 | ||
1224 | /* Do we have special options for the device? */ | 1224 | /* Do we have special options for the device? */ |
1225 | if (id->driver_data != CARDBUS_TYPE_DEFAULT && | 1225 | if (id->driver_data != CARDBUS_TYPE_DEFAULT && |
1226 | id->driver_data < ARRAY_SIZE(cardbus_type)) { | 1226 | id->driver_data < ARRAY_SIZE(cardbus_type)) { |
1227 | socket->type = &cardbus_type[id->driver_data]; | 1227 | socket->type = &cardbus_type[id->driver_data]; |
1228 | 1228 | ||
1229 | ret = socket->type->override(socket); | 1229 | ret = socket->type->override(socket); |
1230 | if (ret < 0) | 1230 | if (ret < 0) |
1231 | goto unmap; | 1231 | goto unmap; |
1232 | } | 1232 | } |
1233 | 1233 | ||
1234 | /* We must finish initialization here */ | 1234 | /* We must finish initialization here */ |
1235 | 1235 | ||
1236 | if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, IRQF_SHARED, "yenta", socket)) { | 1236 | if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, IRQF_SHARED, "yenta", socket)) { |
1237 | /* No IRQ or request_irq failed. Poll */ | 1237 | /* No IRQ or request_irq failed. Poll */ |
1238 | socket->cb_irq = 0; /* But zero is a valid IRQ number. */ | 1238 | socket->cb_irq = 0; /* But zero is a valid IRQ number. */ |
1239 | init_timer(&socket->poll_timer); | 1239 | init_timer(&socket->poll_timer); |
1240 | socket->poll_timer.function = yenta_interrupt_wrapper; | 1240 | socket->poll_timer.function = yenta_interrupt_wrapper; |
1241 | socket->poll_timer.data = (unsigned long)socket; | 1241 | socket->poll_timer.data = (unsigned long)socket; |
1242 | socket->poll_timer.expires = jiffies + HZ; | 1242 | socket->poll_timer.expires = jiffies + HZ; |
1243 | add_timer(&socket->poll_timer); | 1243 | add_timer(&socket->poll_timer); |
1244 | dev_printk(KERN_INFO, &dev->dev, | 1244 | dev_printk(KERN_INFO, &dev->dev, |
1245 | "no PCI IRQ, CardBus support disabled for this " | 1245 | "no PCI IRQ, CardBus support disabled for this " |
1246 | "socket.\n"); | 1246 | "socket.\n"); |
1247 | dev_printk(KERN_INFO, &dev->dev, | 1247 | dev_printk(KERN_INFO, &dev->dev, |
1248 | "check your BIOS CardBus, BIOS IRQ or ACPI " | 1248 | "check your BIOS CardBus, BIOS IRQ or ACPI " |
1249 | "settings.\n"); | 1249 | "settings.\n"); |
1250 | } else { | 1250 | } else { |
1251 | socket->socket.features |= SS_CAP_CARDBUS; | 1251 | socket->socket.features |= SS_CAP_CARDBUS; |
1252 | } | 1252 | } |
1253 | 1253 | ||
1254 | /* Figure out what the dang thing can do for the PCMCIA layer... */ | 1254 | /* Figure out what the dang thing can do for the PCMCIA layer... */ |
1255 | yenta_interrogate(socket); | 1255 | yenta_interrogate(socket); |
1256 | yenta_get_socket_capabilities(socket, isa_interrupts); | 1256 | yenta_get_socket_capabilities(socket, isa_interrupts); |
1257 | dev_printk(KERN_INFO, &dev->dev, | 1257 | dev_printk(KERN_INFO, &dev->dev, |
1258 | "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); | 1258 | "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); |
1259 | 1259 | ||
1260 | yenta_fixup_parent_bridge(dev->subordinate); | 1260 | yenta_fixup_parent_bridge(dev->subordinate); |
1261 | 1261 | ||
1262 | /* Register it with the pcmcia layer.. */ | 1262 | /* Register it with the pcmcia layer.. */ |
1263 | ret = pcmcia_register_socket(&socket->socket); | 1263 | ret = pcmcia_register_socket(&socket->socket); |
1264 | if (ret == 0) { | 1264 | if (ret == 0) { |
1265 | /* Add the yenta register attributes */ | 1265 | /* Add the yenta register attributes */ |
1266 | ret = device_create_file(&dev->dev, &dev_attr_yenta_registers); | 1266 | ret = device_create_file(&dev->dev, &dev_attr_yenta_registers); |
1267 | if (ret == 0) | 1267 | if (ret == 0) |
1268 | goto out; | 1268 | goto out; |
1269 | 1269 | ||
1270 | /* error path... */ | 1270 | /* error path... */ |
1271 | pcmcia_unregister_socket(&socket->socket); | 1271 | pcmcia_unregister_socket(&socket->socket); |
1272 | } | 1272 | } |
1273 | 1273 | ||
1274 | unmap: | 1274 | unmap: |
1275 | iounmap(socket->base); | 1275 | iounmap(socket->base); |
1276 | release: | 1276 | release: |
1277 | pci_release_regions(dev); | 1277 | pci_release_regions(dev); |
1278 | disable: | 1278 | disable: |
1279 | pci_disable_device(dev); | 1279 | pci_disable_device(dev); |
1280 | free: | 1280 | free: |
1281 | kfree(socket); | 1281 | kfree(socket); |
1282 | out: | 1282 | out: |
1283 | return ret; | 1283 | return ret; |
1284 | } | 1284 | } |
1285 | 1285 | ||
1286 | #ifdef CONFIG_PM | 1286 | #ifdef CONFIG_PM |
1287 | static int yenta_dev_suspend_noirq(struct device *dev) | 1287 | static int yenta_dev_suspend_noirq(struct device *dev) |
1288 | { | 1288 | { |
1289 | struct pci_dev *pdev = to_pci_dev(dev); | 1289 | struct pci_dev *pdev = to_pci_dev(dev); |
1290 | struct yenta_socket *socket = pci_get_drvdata(pdev); | 1290 | struct yenta_socket *socket = pci_get_drvdata(pdev); |
1291 | 1291 | ||
1292 | if (!socket) | 1292 | if (!socket) |
1293 | return 0; | 1293 | return 0; |
1294 | 1294 | ||
1295 | if (socket->type && socket->type->save_state) | 1295 | if (socket->type && socket->type->save_state) |
1296 | socket->type->save_state(socket); | 1296 | socket->type->save_state(socket); |
1297 | 1297 | ||
1298 | pci_save_state(pdev); | 1298 | pci_save_state(pdev); |
1299 | pci_read_config_dword(pdev, 16*4, &socket->saved_state[0]); | 1299 | pci_read_config_dword(pdev, 16*4, &socket->saved_state[0]); |
1300 | pci_read_config_dword(pdev, 17*4, &socket->saved_state[1]); | 1300 | pci_read_config_dword(pdev, 17*4, &socket->saved_state[1]); |
1301 | pci_disable_device(pdev); | 1301 | pci_disable_device(pdev); |
1302 | 1302 | ||
1303 | return 0; | 1303 | return 0; |
1304 | } | 1304 | } |
1305 | 1305 | ||
1306 | static int yenta_dev_resume_noirq(struct device *dev) | 1306 | static int yenta_dev_resume_noirq(struct device *dev) |
1307 | { | 1307 | { |
1308 | struct pci_dev *pdev = to_pci_dev(dev); | 1308 | struct pci_dev *pdev = to_pci_dev(dev); |
1309 | struct yenta_socket *socket = pci_get_drvdata(pdev); | 1309 | struct yenta_socket *socket = pci_get_drvdata(pdev); |
1310 | int ret; | 1310 | int ret; |
1311 | 1311 | ||
1312 | if (!socket) | 1312 | if (!socket) |
1313 | return 0; | 1313 | return 0; |
1314 | 1314 | ||
1315 | pci_write_config_dword(pdev, 16*4, socket->saved_state[0]); | 1315 | pci_write_config_dword(pdev, 16*4, socket->saved_state[0]); |
1316 | pci_write_config_dword(pdev, 17*4, socket->saved_state[1]); | 1316 | pci_write_config_dword(pdev, 17*4, socket->saved_state[1]); |
1317 | 1317 | ||
1318 | ret = pci_enable_device(pdev); | 1318 | ret = pci_enable_device(pdev); |
1319 | if (ret) | 1319 | if (ret) |
1320 | return ret; | 1320 | return ret; |
1321 | 1321 | ||
1322 | pci_set_master(pdev); | 1322 | pci_set_master(pdev); |
1323 | 1323 | ||
1324 | if (socket->type && socket->type->restore_state) | 1324 | if (socket->type && socket->type->restore_state) |
1325 | socket->type->restore_state(socket); | 1325 | socket->type->restore_state(socket); |
1326 | 1326 | ||
1327 | return 0; | 1327 | return 0; |
1328 | } | 1328 | } |
1329 | 1329 | ||
1330 | static const struct dev_pm_ops yenta_pm_ops = { | 1330 | static const struct dev_pm_ops yenta_pm_ops = { |
1331 | .suspend_noirq = yenta_dev_suspend_noirq, | 1331 | .suspend_noirq = yenta_dev_suspend_noirq, |
1332 | .resume_noirq = yenta_dev_resume_noirq, | 1332 | .resume_noirq = yenta_dev_resume_noirq, |
1333 | .freeze_noirq = yenta_dev_suspend_noirq, | 1333 | .freeze_noirq = yenta_dev_suspend_noirq, |
1334 | .thaw_noirq = yenta_dev_resume_noirq, | 1334 | .thaw_noirq = yenta_dev_resume_noirq, |
1335 | .poweroff_noirq = yenta_dev_suspend_noirq, | 1335 | .poweroff_noirq = yenta_dev_suspend_noirq, |
1336 | .restore_noirq = yenta_dev_resume_noirq, | 1336 | .restore_noirq = yenta_dev_resume_noirq, |
1337 | }; | 1337 | }; |
1338 | 1338 | ||
1339 | #define YENTA_PM_OPS (¥ta_pm_ops) | 1339 | #define YENTA_PM_OPS (¥ta_pm_ops) |
1340 | #else | 1340 | #else |
1341 | #define YENTA_PM_OPS NULL | 1341 | #define YENTA_PM_OPS NULL |
1342 | #endif | 1342 | #endif |
1343 | 1343 | ||
1344 | #define CB_ID(vend, dev, type) \ | 1344 | #define CB_ID(vend, dev, type) \ |
1345 | { \ | 1345 | { \ |
1346 | .vendor = vend, \ | 1346 | .vendor = vend, \ |
1347 | .device = dev, \ | 1347 | .device = dev, \ |
1348 | .subvendor = PCI_ANY_ID, \ | 1348 | .subvendor = PCI_ANY_ID, \ |
1349 | .subdevice = PCI_ANY_ID, \ | 1349 | .subdevice = PCI_ANY_ID, \ |
1350 | .class = PCI_CLASS_BRIDGE_CARDBUS << 8, \ | 1350 | .class = PCI_CLASS_BRIDGE_CARDBUS << 8, \ |
1351 | .class_mask = ~0, \ | 1351 | .class_mask = ~0, \ |
1352 | .driver_data = CARDBUS_TYPE_##type, \ | 1352 | .driver_data = CARDBUS_TYPE_##type, \ |
1353 | } | 1353 | } |
1354 | 1354 | ||
1355 | static DEFINE_PCI_DEVICE_TABLE(yenta_table) = { | 1355 | static const struct pci_device_id yenta_table[] = { |
1356 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1031, TI), | 1356 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1031, TI), |
1357 | 1357 | ||
1358 | /* | 1358 | /* |
1359 | * TBD: Check if these TI variants can use more | 1359 | * TBD: Check if these TI variants can use more |
1360 | * advanced overrides instead. (I can't get the | 1360 | * advanced overrides instead. (I can't get the |
1361 | * data sheets for these devices. --rmk) | 1361 | * data sheets for these devices. --rmk) |
1362 | */ | 1362 | */ |
1363 | #ifdef CONFIG_YENTA_TI | 1363 | #ifdef CONFIG_YENTA_TI |
1364 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1210, TI), | 1364 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1210, TI), |
1365 | 1365 | ||
1366 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1130, TI113X), | 1366 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1130, TI113X), |
1367 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1131, TI113X), | 1367 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1131, TI113X), |
1368 | 1368 | ||
1369 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1211, TI12XX), | 1369 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1211, TI12XX), |
1370 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1220, TI12XX), | 1370 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1220, TI12XX), |
1371 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1221, TI12XX), | 1371 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1221, TI12XX), |
1372 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1225, TI12XX), | 1372 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1225, TI12XX), |
1373 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1251A, TI12XX), | 1373 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1251A, TI12XX), |
1374 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1251B, TI12XX), | 1374 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1251B, TI12XX), |
1375 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, TI12XX), | 1375 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, TI12XX), |
1376 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1450, TI12XX), | 1376 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1450, TI12XX), |
1377 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1451A, TI12XX), | 1377 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1451A, TI12XX), |
1378 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1510, TI12XX), | 1378 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1510, TI12XX), |
1379 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1520, TI12XX), | 1379 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1520, TI12XX), |
1380 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1620, TI12XX), | 1380 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1620, TI12XX), |
1381 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4410, TI12XX), | 1381 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4410, TI12XX), |
1382 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4450, TI12XX), | 1382 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4450, TI12XX), |
1383 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4451, TI12XX), | 1383 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4451, TI12XX), |
1384 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4510, TI12XX), | 1384 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4510, TI12XX), |
1385 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4520, TI12XX), | 1385 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4520, TI12XX), |
1386 | 1386 | ||
1387 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250), | 1387 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250), |
1388 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250), | 1388 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250), |
1389 | 1389 | ||
1390 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11, TI12XX), | 1390 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11, TI12XX), |
1391 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X515, TI12XX), | 1391 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X515, TI12XX), |
1392 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12, TI12XX), | 1392 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12, TI12XX), |
1393 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X420, TI12XX), | 1393 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X420, TI12XX), |
1394 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X620, TI12XX), | 1394 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X620, TI12XX), |
1395 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7410, TI12XX), | 1395 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7410, TI12XX), |
1396 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7510, TI12XX), | 1396 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7510, TI12XX), |
1397 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7610, TI12XX), | 1397 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7610, TI12XX), |
1398 | 1398 | ||
1399 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_710, ENE), | 1399 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_710, ENE), |
1400 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_712, ENE), | 1400 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_712, ENE), |
1401 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_720, ENE), | 1401 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_720, ENE), |
1402 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_722, ENE), | 1402 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_722, ENE), |
1403 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE), | 1403 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE), |
1404 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE), | 1404 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE), |
1405 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE), | 1405 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE), |
1406 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE), | 1406 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE), |
1407 | #endif /* CONFIG_YENTA_TI */ | 1407 | #endif /* CONFIG_YENTA_TI */ |
1408 | 1408 | ||
1409 | #ifdef CONFIG_YENTA_RICOH | 1409 | #ifdef CONFIG_YENTA_RICOH |
1410 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH), | 1410 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH), |
1411 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH), | 1411 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH), |
1412 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C475, RICOH), | 1412 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C475, RICOH), |
1413 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH), | 1413 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH), |
1414 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH), | 1414 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH), |
1415 | #endif | 1415 | #endif |
1416 | 1416 | ||
1417 | #ifdef CONFIG_YENTA_TOSHIBA | 1417 | #ifdef CONFIG_YENTA_TOSHIBA |
1418 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95, TOPIC95), | 1418 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95, TOPIC95), |
1419 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97), | 1419 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97), |
1420 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97), | 1420 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97), |
1421 | #endif | 1421 | #endif |
1422 | 1422 | ||
1423 | #ifdef CONFIG_YENTA_O2 | 1423 | #ifdef CONFIG_YENTA_O2 |
1424 | CB_ID(PCI_VENDOR_ID_O2, PCI_ANY_ID, O2MICRO), | 1424 | CB_ID(PCI_VENDOR_ID_O2, PCI_ANY_ID, O2MICRO), |
1425 | #endif | 1425 | #endif |
1426 | 1426 | ||
1427 | /* match any cardbus bridge */ | 1427 | /* match any cardbus bridge */ |
1428 | CB_ID(PCI_ANY_ID, PCI_ANY_ID, DEFAULT), | 1428 | CB_ID(PCI_ANY_ID, PCI_ANY_ID, DEFAULT), |
1429 | { /* all zeroes */ } | 1429 | { /* all zeroes */ } |
1430 | }; | 1430 | }; |
1431 | MODULE_DEVICE_TABLE(pci, yenta_table); | 1431 | MODULE_DEVICE_TABLE(pci, yenta_table); |
1432 | 1432 | ||
1433 | 1433 | ||
1434 | static struct pci_driver yenta_cardbus_driver = { | 1434 | static struct pci_driver yenta_cardbus_driver = { |
1435 | .name = "yenta_cardbus", | 1435 | .name = "yenta_cardbus", |
1436 | .id_table = yenta_table, | 1436 | .id_table = yenta_table, |
1437 | .probe = yenta_probe, | 1437 | .probe = yenta_probe, |
1438 | .remove = yenta_close, | 1438 | .remove = yenta_close, |
1439 | .driver.pm = YENTA_PM_OPS, | 1439 | .driver.pm = YENTA_PM_OPS, |
1440 | }; | 1440 | }; |
1441 | 1441 | ||
1442 | module_pci_driver(yenta_cardbus_driver); | 1442 | module_pci_driver(yenta_cardbus_driver); |
1443 | 1443 | ||
1444 | MODULE_LICENSE("GPL"); | 1444 | MODULE_LICENSE("GPL"); |
1445 | 1445 |