1 |
1275 |
phoenix |
/*
|
2 |
|
|
* Regular lowlevel cardbus driver ("yenta")
|
3 |
|
|
*
|
4 |
|
|
* (C) Copyright 1999, 2000 Linus Torvalds
|
5 |
|
|
*
|
6 |
|
|
* Changelog:
|
7 |
|
|
* Aug 2002: Manfred Spraul <manfred@colorfullife.com>
|
8 |
|
|
* Dynamically adjust the size of the bridge resource
|
9 |
|
|
*
|
10 |
|
|
*/
|
11 |
|
|
#include <linux/init.h>
|
12 |
|
|
#include <linux/pci.h>
|
13 |
|
|
#include <linux/sched.h>
|
14 |
|
|
#include <linux/interrupt.h>
|
15 |
|
|
#include <linux/delay.h>
|
16 |
|
|
#include <linux/module.h>
|
17 |
|
|
|
18 |
|
|
#include <pcmcia/version.h>
|
19 |
|
|
#include <pcmcia/cs_types.h>
|
20 |
|
|
#include <pcmcia/ss.h>
|
21 |
|
|
#include <pcmcia/cs.h>
|
22 |
|
|
|
23 |
|
|
#include <asm/io.h>
|
24 |
|
|
|
25 |
|
|
#include "yenta.h"
|
26 |
|
|
#include "i82365.h"
|
27 |
|
|
|
28 |
|
|
#if 0
|
29 |
|
|
#define DEBUG(x,args...) printk(KERN_DEBUG __FUNCTION__ ": " x,##args)
|
30 |
|
|
#else
|
31 |
|
|
#define DEBUG(x,args...)
|
32 |
|
|
#endif
|
33 |
|
|
|
34 |
|
|
/* Don't ask.. */
|
35 |
|
|
#define to_cycles(ns) ((ns)/120)
|
36 |
|
|
#define to_ns(cycles) ((cycles)*120)
|
37 |
|
|
|
38 |
|
|
/*
|
39 |
|
|
* Generate easy-to-use ways of reading a cardbus sockets
|
40 |
|
|
* regular memory space ("cb_xxx"), configuration space
|
41 |
|
|
* ("config_xxx") and compatibility space ("exca_xxxx")
|
42 |
|
|
*/
|
43 |
|
|
static inline u32 cb_readl(pci_socket_t *socket, unsigned reg)
|
44 |
|
|
{
|
45 |
|
|
u32 val = readl(socket->base + reg);
|
46 |
|
|
DEBUG("%p %04x %08x\n", socket, reg, val);
|
47 |
|
|
return val;
|
48 |
|
|
}
|
49 |
|
|
|
50 |
|
|
static inline void cb_writel(pci_socket_t *socket, unsigned reg, u32 val)
|
51 |
|
|
{
|
52 |
|
|
DEBUG("%p %04x %08x\n", socket, reg, val);
|
53 |
|
|
writel(val, socket->base + reg);
|
54 |
|
|
}
|
55 |
|
|
|
56 |
|
|
static inline u8 config_readb(pci_socket_t *socket, unsigned offset)
|
57 |
|
|
{
|
58 |
|
|
u8 val;
|
59 |
|
|
pci_read_config_byte(socket->dev, offset, &val);
|
60 |
|
|
DEBUG("%p %04x %02x\n", socket, offset, val);
|
61 |
|
|
return val;
|
62 |
|
|
}
|
63 |
|
|
|
64 |
|
|
static inline u16 config_readw(pci_socket_t *socket, unsigned offset)
|
65 |
|
|
{
|
66 |
|
|
u16 val;
|
67 |
|
|
pci_read_config_word(socket->dev, offset, &val);
|
68 |
|
|
DEBUG("%p %04x %04x\n", socket, offset, val);
|
69 |
|
|
return val;
|
70 |
|
|
}
|
71 |
|
|
|
72 |
|
|
static inline u32 config_readl(pci_socket_t *socket, unsigned offset)
|
73 |
|
|
{
|
74 |
|
|
u32 val;
|
75 |
|
|
pci_read_config_dword(socket->dev, offset, &val);
|
76 |
|
|
DEBUG("%p %04x %08x\n", socket, offset, val);
|
77 |
|
|
return val;
|
78 |
|
|
}
|
79 |
|
|
|
80 |
|
|
static inline void config_writeb(pci_socket_t *socket, unsigned offset, u8 val)
|
81 |
|
|
{
|
82 |
|
|
DEBUG("%p %04x %02x\n", socket, offset, val);
|
83 |
|
|
pci_write_config_byte(socket->dev, offset, val);
|
84 |
|
|
}
|
85 |
|
|
|
86 |
|
|
static inline void config_writew(pci_socket_t *socket, unsigned offset, u16 val)
|
87 |
|
|
{
|
88 |
|
|
DEBUG("%p %04x %04x\n", socket, offset, val);
|
89 |
|
|
pci_write_config_word(socket->dev, offset, val);
|
90 |
|
|
}
|
91 |
|
|
|
92 |
|
|
static inline void config_writel(pci_socket_t *socket, unsigned offset, u32 val)
|
93 |
|
|
{
|
94 |
|
|
DEBUG("%p %04x %08x\n", socket, offset, val);
|
95 |
|
|
pci_write_config_dword(socket->dev, offset, val);
|
96 |
|
|
}
|
97 |
|
|
|
98 |
|
|
static inline u8 exca_readb(pci_socket_t *socket, unsigned reg)
|
99 |
|
|
{
|
100 |
|
|
u8 val = readb(socket->base + 0x800 + reg);
|
101 |
|
|
DEBUG("%p %04x %02x\n", socket, reg, val);
|
102 |
|
|
return val;
|
103 |
|
|
}
|
104 |
|
|
|
105 |
|
|
static inline u8 exca_readw(pci_socket_t *socket, unsigned reg)
|
106 |
|
|
{
|
107 |
|
|
u16 val;
|
108 |
|
|
val = readb(socket->base + 0x800 + reg);
|
109 |
|
|
val |= readb(socket->base + 0x800 + reg + 1) << 8;
|
110 |
|
|
DEBUG("%p %04x %04x\n", socket, reg, val);
|
111 |
|
|
return val;
|
112 |
|
|
}
|
113 |
|
|
|
114 |
|
|
static inline void exca_writeb(pci_socket_t *socket, unsigned reg, u8 val)
|
115 |
|
|
{
|
116 |
|
|
DEBUG("%p %04x %02x\n", socket, reg, val);
|
117 |
|
|
writeb(val, socket->base + 0x800 + reg);
|
118 |
|
|
}
|
119 |
|
|
|
120 |
|
|
static void exca_writew(pci_socket_t *socket, unsigned reg, u16 val)
|
121 |
|
|
{
|
122 |
|
|
DEBUG("%p %04x %04x\n", socket, reg, val);
|
123 |
|
|
writeb(val, socket->base + 0x800 + reg);
|
124 |
|
|
writeb(val >> 8, socket->base + 0x800 + reg + 1);
|
125 |
|
|
}
|
126 |
|
|
|
127 |
|
|
/*
|
128 |
|
|
* Ugh, mixed-mode cardbus and 16-bit pccard state: things depend
|
129 |
|
|
* on what kind of card is inserted..
|
130 |
|
|
*/
|
131 |
|
|
static int yenta_get_status(pci_socket_t *socket, unsigned int *value)
|
132 |
|
|
{
|
133 |
|
|
unsigned int val;
|
134 |
|
|
u32 state = cb_readl(socket, CB_SOCKET_STATE);
|
135 |
|
|
|
136 |
|
|
val = (state & CB_3VCARD) ? SS_3VCARD : 0;
|
137 |
|
|
val |= (state & CB_XVCARD) ? SS_XVCARD : 0;
|
138 |
|
|
val |= (state & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD | CB_3VCARD
|
139 |
|
|
| CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING;
|
140 |
|
|
|
141 |
|
|
if (state & CB_CBCARD) {
|
142 |
|
|
val |= SS_CARDBUS;
|
143 |
|
|
val |= (state & CB_CARDSTS) ? SS_STSCHG : 0;
|
144 |
|
|
val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT;
|
145 |
|
|
val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0;
|
146 |
|
|
} else {
|
147 |
|
|
u8 status = exca_readb(socket, I365_STATUS);
|
148 |
|
|
val |= ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0;
|
149 |
|
|
if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) {
|
150 |
|
|
val |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
|
151 |
|
|
} else {
|
152 |
|
|
val |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;
|
153 |
|
|
val |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;
|
154 |
|
|
}
|
155 |
|
|
val |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
|
156 |
|
|
val |= (status & I365_CS_READY) ? SS_READY : 0;
|
157 |
|
|
val |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
|
158 |
|
|
}
|
159 |
|
|
|
160 |
|
|
*value = val;
|
161 |
|
|
return 0;
|
162 |
|
|
}
|
163 |
|
|
|
164 |
|
|
static int yenta_Vcc_power(u32 control)
|
165 |
|
|
{
|
166 |
|
|
switch (control & CB_SC_VCC_MASK) {
|
167 |
|
|
case CB_SC_VCC_5V: return 50;
|
168 |
|
|
case CB_SC_VCC_3V: return 33;
|
169 |
|
|
default: return 0;
|
170 |
|
|
}
|
171 |
|
|
}
|
172 |
|
|
|
173 |
|
|
static int yenta_Vpp_power(u32 control)
|
174 |
|
|
{
|
175 |
|
|
switch (control & CB_SC_VPP_MASK) {
|
176 |
|
|
case CB_SC_VPP_12V: return 120;
|
177 |
|
|
case CB_SC_VPP_5V: return 50;
|
178 |
|
|
case CB_SC_VPP_3V: return 33;
|
179 |
|
|
default: return 0;
|
180 |
|
|
}
|
181 |
|
|
}
|
182 |
|
|
|
183 |
|
|
static int yenta_get_socket(pci_socket_t *socket, socket_state_t *state)
|
184 |
|
|
{
|
185 |
|
|
u8 reg;
|
186 |
|
|
u32 control;
|
187 |
|
|
|
188 |
|
|
control = cb_readl(socket, CB_SOCKET_CONTROL);
|
189 |
|
|
|
190 |
|
|
state->Vcc = yenta_Vcc_power(control);
|
191 |
|
|
state->Vpp = yenta_Vpp_power(control);
|
192 |
|
|
state->io_irq = socket->io_irq;
|
193 |
|
|
|
194 |
|
|
if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) {
|
195 |
|
|
u16 bridge = config_readw(socket, CB_BRIDGE_CONTROL);
|
196 |
|
|
if (bridge & CB_BRIDGE_CRST)
|
197 |
|
|
state->flags |= SS_RESET;
|
198 |
|
|
return 0;
|
199 |
|
|
}
|
200 |
|
|
|
201 |
|
|
/* 16-bit card state.. */
|
202 |
|
|
reg = exca_readb(socket, I365_POWER);
|
203 |
|
|
state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
|
204 |
|
|
state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
|
205 |
|
|
|
206 |
|
|
reg = exca_readb(socket, I365_INTCTL);
|
207 |
|
|
state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
|
208 |
|
|
state->flags |= (reg & I365_PC_IOCARD) ? SS_IOCARD : 0;
|
209 |
|
|
|
210 |
|
|
reg = exca_readb(socket, I365_CSCINT);
|
211 |
|
|
state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
|
212 |
|
|
if (state->flags & SS_IOCARD) {
|
213 |
|
|
state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0;
|
214 |
|
|
} else {
|
215 |
|
|
state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0;
|
216 |
|
|
state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
|
217 |
|
|
state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
|
218 |
|
|
}
|
219 |
|
|
|
220 |
|
|
return 0;
|
221 |
|
|
}
|
222 |
|
|
|
223 |
|
|
static void yenta_set_power(pci_socket_t *socket, socket_state_t *state)
|
224 |
|
|
{
|
225 |
|
|
u32 reg = 0; /* CB_SC_STPCLK? */
|
226 |
|
|
switch (state->Vcc) {
|
227 |
|
|
case 33: reg = CB_SC_VCC_3V; break;
|
228 |
|
|
case 50: reg = CB_SC_VCC_5V; break;
|
229 |
|
|
default: reg = 0; break;
|
230 |
|
|
}
|
231 |
|
|
switch (state->Vpp) {
|
232 |
|
|
case 33: reg |= CB_SC_VPP_3V; break;
|
233 |
|
|
case 50: reg |= CB_SC_VPP_5V; break;
|
234 |
|
|
case 120: reg |= CB_SC_VPP_12V; break;
|
235 |
|
|
}
|
236 |
|
|
if (reg != cb_readl(socket, CB_SOCKET_CONTROL))
|
237 |
|
|
cb_writel(socket, CB_SOCKET_CONTROL, reg);
|
238 |
|
|
}
|
239 |
|
|
|
240 |
|
|
static int yenta_set_socket(pci_socket_t *socket, socket_state_t *state)
|
241 |
|
|
{
|
242 |
|
|
u16 bridge;
|
243 |
|
|
|
244 |
|
|
if (state->flags & SS_DEBOUNCED) {
|
245 |
|
|
/* The insertion debounce period has ended. Clear any pending insertion events */
|
246 |
|
|
socket->events &= ~SS_DETECT;
|
247 |
|
|
state->flags &= ~SS_DEBOUNCED; /* SS_DEBOUNCED is oneshot */
|
248 |
|
|
}
|
249 |
|
|
yenta_set_power(socket, state);
|
250 |
|
|
socket->io_irq = state->io_irq;
|
251 |
|
|
bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~(CB_BRIDGE_CRST | CB_BRIDGE_INTR);
|
252 |
|
|
if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) {
|
253 |
|
|
u8 intr;
|
254 |
|
|
bridge |= (state->flags & SS_RESET) ? CB_BRIDGE_CRST : 0;
|
255 |
|
|
|
256 |
|
|
/* ISA interrupt control? */
|
257 |
|
|
intr = exca_readb(socket, I365_INTCTL);
|
258 |
|
|
intr = (intr & ~0xf);
|
259 |
|
|
if (!socket->cb_irq) {
|
260 |
|
|
intr |= state->io_irq;
|
261 |
|
|
bridge |= CB_BRIDGE_INTR;
|
262 |
|
|
}
|
263 |
|
|
exca_writeb(socket, I365_INTCTL, intr);
|
264 |
|
|
} else {
|
265 |
|
|
u8 reg;
|
266 |
|
|
|
267 |
|
|
reg = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | I365_INTR_ENA);
|
268 |
|
|
reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
|
269 |
|
|
reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
|
270 |
|
|
if (state->io_irq != socket->cb_irq) {
|
271 |
|
|
reg |= state->io_irq;
|
272 |
|
|
bridge |= CB_BRIDGE_INTR;
|
273 |
|
|
}
|
274 |
|
|
exca_writeb(socket, I365_INTCTL, reg);
|
275 |
|
|
|
276 |
|
|
reg = exca_readb(socket, I365_POWER) & (I365_VCC_MASK|I365_VPP1_MASK);
|
277 |
|
|
reg |= I365_PWR_NORESET;
|
278 |
|
|
if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
|
279 |
|
|
if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT;
|
280 |
|
|
if (exca_readb(socket, I365_POWER) != reg)
|
281 |
|
|
exca_writeb(socket, I365_POWER, reg);
|
282 |
|
|
|
283 |
|
|
/* CSC interrupt: no ISA irq for CSC */
|
284 |
|
|
reg = I365_CSC_DETECT;
|
285 |
|
|
if (state->flags & SS_IOCARD) {
|
286 |
|
|
if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
|
287 |
|
|
} else {
|
288 |
|
|
if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1;
|
289 |
|
|
if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2;
|
290 |
|
|
if (state->csc_mask & SS_READY) reg |= I365_CSC_READY;
|
291 |
|
|
}
|
292 |
|
|
exca_writeb(socket, I365_CSCINT, reg);
|
293 |
|
|
exca_readb(socket, I365_CSC);
|
294 |
|
|
|
295 |
|
|
if(socket->zoom_video)
|
296 |
|
|
socket->zoom_video(socket, state->flags & SS_ZVCARD);
|
297 |
|
|
}
|
298 |
|
|
config_writew(socket, CB_BRIDGE_CONTROL, bridge);
|
299 |
|
|
/* Socket event mask: get card insert/remove events.. */
|
300 |
|
|
cb_writel(socket, CB_SOCKET_EVENT, -1);
|
301 |
|
|
cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK);
|
302 |
|
|
return 0;
|
303 |
|
|
}
|
304 |
|
|
|
305 |
|
|
static int yenta_get_io_map(pci_socket_t *socket, struct pccard_io_map *io)
|
306 |
|
|
{
|
307 |
|
|
int map;
|
308 |
|
|
unsigned char ioctl, addr;
|
309 |
|
|
|
310 |
|
|
map = io->map;
|
311 |
|
|
if (map > 1)
|
312 |
|
|
return -EINVAL;
|
313 |
|
|
|
314 |
|
|
io->start = exca_readw(socket, I365_IO(map)+I365_W_START);
|
315 |
|
|
io->stop = exca_readw(socket, I365_IO(map)+I365_W_STOP);
|
316 |
|
|
|
317 |
|
|
ioctl = exca_readb(socket, I365_IOCTL);
|
318 |
|
|
addr = exca_readb(socket, I365_ADDRWIN);
|
319 |
|
|
io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0;
|
320 |
|
|
io->flags = (addr & I365_ENA_IO(map)) ? MAP_ACTIVE : 0;
|
321 |
|
|
io->flags |= (ioctl & I365_IOCTL_0WS(map)) ? MAP_0WS : 0;
|
322 |
|
|
io->flags |= (ioctl & I365_IOCTL_16BIT(map)) ? MAP_16BIT : 0;
|
323 |
|
|
io->flags |= (ioctl & I365_IOCTL_IOCS16(map)) ? MAP_AUTOSZ : 0;
|
324 |
|
|
|
325 |
|
|
return 0;
|
326 |
|
|
}
|
327 |
|
|
|
328 |
|
|
static int yenta_set_io_map(pci_socket_t *socket, struct pccard_io_map *io)
|
329 |
|
|
{
|
330 |
|
|
int map;
|
331 |
|
|
unsigned char ioctl, addr, enable;
|
332 |
|
|
|
333 |
|
|
map = io->map;
|
334 |
|
|
|
335 |
|
|
if (map > 1)
|
336 |
|
|
return -EINVAL;
|
337 |
|
|
|
338 |
|
|
enable = I365_ENA_IO(map);
|
339 |
|
|
addr = exca_readb(socket, I365_ADDRWIN);
|
340 |
|
|
|
341 |
|
|
/* Disable the window before changing it.. */
|
342 |
|
|
if (addr & enable) {
|
343 |
|
|
addr &= ~enable;
|
344 |
|
|
exca_writeb(socket, I365_ADDRWIN, addr);
|
345 |
|
|
}
|
346 |
|
|
|
347 |
|
|
exca_writew(socket, I365_IO(map)+I365_W_START, io->start);
|
348 |
|
|
exca_writew(socket, I365_IO(map)+I365_W_STOP, io->stop);
|
349 |
|
|
|
350 |
|
|
ioctl = exca_readb(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map);
|
351 |
|
|
if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map);
|
352 |
|
|
if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map);
|
353 |
|
|
if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map);
|
354 |
|
|
exca_writeb(socket, I365_IOCTL, ioctl);
|
355 |
|
|
|
356 |
|
|
if (io->flags & MAP_ACTIVE)
|
357 |
|
|
exca_writeb(socket, I365_ADDRWIN, addr | enable);
|
358 |
|
|
return 0;
|
359 |
|
|
}
|
360 |
|
|
|
361 |
|
|
static int yenta_get_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem)
|
362 |
|
|
{
|
363 |
|
|
int map;
|
364 |
|
|
unsigned char addr;
|
365 |
|
|
unsigned int start, stop, page, offset;
|
366 |
|
|
|
367 |
|
|
map = mem->map;
|
368 |
|
|
if (map > 4)
|
369 |
|
|
return -EINVAL;
|
370 |
|
|
|
371 |
|
|
addr = exca_readb(socket, I365_ADDRWIN);
|
372 |
|
|
mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0;
|
373 |
|
|
|
374 |
|
|
start = exca_readw(socket, I365_MEM(map) + I365_W_START);
|
375 |
|
|
mem->flags |= (start & I365_MEM_16BIT) ? MAP_16BIT : 0;
|
376 |
|
|
mem->flags |= (start & I365_MEM_0WS) ? MAP_0WS : 0;
|
377 |
|
|
start = (start & 0x0fff) << 12;
|
378 |
|
|
|
379 |
|
|
stop = exca_readw(socket, I365_MEM(map) + I365_W_STOP);
|
380 |
|
|
mem->speed = to_ns(stop >> 14);
|
381 |
|
|
stop = ((stop & 0x0fff) << 12) + 0x0fff;
|
382 |
|
|
|
383 |
|
|
offset = exca_readw(socket, I365_MEM(map) + I365_W_OFF);
|
384 |
|
|
mem->flags |= (offset & I365_MEM_WRPROT) ? MAP_WRPROT : 0;
|
385 |
|
|
mem->flags |= (offset & I365_MEM_REG) ? MAP_ATTRIB : 0;
|
386 |
|
|
offset = ((offset & 0x3fff) << 12) + start;
|
387 |
|
|
mem->card_start = offset & 0x3ffffff;
|
388 |
|
|
|
389 |
|
|
page = exca_readb(socket, CB_MEM_PAGE(map)) << 24;
|
390 |
|
|
mem->sys_start = start + page;
|
391 |
|
|
mem->sys_stop = start + page;
|
392 |
|
|
|
393 |
|
|
return 0;
|
394 |
|
|
}
|
395 |
|
|
|
396 |
|
|
static int yenta_set_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem)
|
397 |
|
|
{
|
398 |
|
|
int map;
|
399 |
|
|
unsigned char addr, enable;
|
400 |
|
|
unsigned int start, stop, card_start;
|
401 |
|
|
unsigned short word;
|
402 |
|
|
|
403 |
|
|
map = mem->map;
|
404 |
|
|
start = mem->sys_start;
|
405 |
|
|
stop = mem->sys_stop;
|
406 |
|
|
card_start = mem->card_start;
|
407 |
|
|
|
408 |
|
|
if (map > 4 || start > stop || ((start ^ stop) >> 24) ||
|
409 |
|
|
(card_start >> 26) || mem->speed > 1000)
|
410 |
|
|
return -EINVAL;
|
411 |
|
|
|
412 |
|
|
enable = I365_ENA_MEM(map);
|
413 |
|
|
addr = exca_readb(socket, I365_ADDRWIN);
|
414 |
|
|
if (addr & enable) {
|
415 |
|
|
addr &= ~enable;
|
416 |
|
|
exca_writeb(socket, I365_ADDRWIN, addr);
|
417 |
|
|
}
|
418 |
|
|
|
419 |
|
|
exca_writeb(socket, CB_MEM_PAGE(map), start >> 24);
|
420 |
|
|
|
421 |
|
|
word = (start >> 12) & 0x0fff;
|
422 |
|
|
if (mem->flags & MAP_16BIT)
|
423 |
|
|
word |= I365_MEM_16BIT;
|
424 |
|
|
if (mem->flags & MAP_0WS)
|
425 |
|
|
word |= I365_MEM_0WS;
|
426 |
|
|
exca_writew(socket, I365_MEM(map) + I365_W_START, word);
|
427 |
|
|
|
428 |
|
|
word = (stop >> 12) & 0x0fff;
|
429 |
|
|
switch (to_cycles(mem->speed)) {
|
430 |
|
|
case 0: break;
|
431 |
|
|
case 1: word |= I365_MEM_WS0; break;
|
432 |
|
|
case 2: word |= I365_MEM_WS1; break;
|
433 |
|
|
default: word |= I365_MEM_WS1 | I365_MEM_WS0; break;
|
434 |
|
|
}
|
435 |
|
|
exca_writew(socket, I365_MEM(map) + I365_W_STOP, word);
|
436 |
|
|
|
437 |
|
|
word = ((card_start - start) >> 12) & 0x3fff;
|
438 |
|
|
if (mem->flags & MAP_WRPROT)
|
439 |
|
|
word |= I365_MEM_WRPROT;
|
440 |
|
|
if (mem->flags & MAP_ATTRIB)
|
441 |
|
|
word |= I365_MEM_REG;
|
442 |
|
|
exca_writew(socket, I365_MEM(map) + I365_W_OFF, word);
|
443 |
|
|
|
444 |
|
|
if (mem->flags & MAP_ACTIVE)
|
445 |
|
|
exca_writeb(socket, I365_ADDRWIN, addr | enable);
|
446 |
|
|
return 0;
|
447 |
|
|
}
|
448 |
|
|
|
449 |
|
|
static void yenta_proc_setup(pci_socket_t *socket, struct proc_dir_entry *base)
|
450 |
|
|
{
|
451 |
|
|
/* Not done yet */
|
452 |
|
|
}
|
453 |
|
|
|
454 |
|
|
static unsigned int yenta_events(pci_socket_t *socket)
|
455 |
|
|
{
|
456 |
|
|
u8 csc;
|
457 |
|
|
u32 cb_event;
|
458 |
|
|
unsigned int events;
|
459 |
|
|
|
460 |
|
|
/* Clear interrupt status for the event */
|
461 |
|
|
cb_event = cb_readl(socket, CB_SOCKET_EVENT);
|
462 |
|
|
cb_writel(socket, CB_SOCKET_EVENT, cb_event);
|
463 |
|
|
|
464 |
|
|
csc = exca_readb(socket, I365_CSC);
|
465 |
|
|
|
466 |
|
|
events = (cb_event & (CB_CD1EVENT | CB_CD2EVENT)) ? SS_DETECT : 0 ;
|
467 |
|
|
events |= (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
|
468 |
|
|
if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) {
|
469 |
|
|
events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
|
470 |
|
|
} else {
|
471 |
|
|
events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;
|
472 |
|
|
events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
|
473 |
|
|
events |= (csc & I365_CSC_READY) ? SS_READY : 0;
|
474 |
|
|
}
|
475 |
|
|
return events;
|
476 |
|
|
}
|
477 |
|
|
|
478 |
|
|
|
479 |
|
|
static void yenta_bh(void *data)
|
480 |
|
|
{
|
481 |
|
|
pci_socket_t *socket = data;
|
482 |
|
|
unsigned int events;
|
483 |
|
|
|
484 |
|
|
spin_lock_irq(&socket->event_lock);
|
485 |
|
|
events = socket->events;
|
486 |
|
|
socket->events = 0;
|
487 |
|
|
spin_unlock_irq(&socket->event_lock);
|
488 |
|
|
if (socket->handler)
|
489 |
|
|
socket->handler(socket->info, events);
|
490 |
|
|
}
|
491 |
|
|
|
492 |
|
|
static void yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
493 |
|
|
{
|
494 |
|
|
unsigned int events;
|
495 |
|
|
pci_socket_t *socket = (pci_socket_t *) dev_id;
|
496 |
|
|
|
497 |
|
|
events = yenta_events(socket);
|
498 |
|
|
if (events) {
|
499 |
|
|
spin_lock(&socket->event_lock);
|
500 |
|
|
socket->events |= events;
|
501 |
|
|
spin_unlock(&socket->event_lock);
|
502 |
|
|
schedule_task(&socket->tq_task);
|
503 |
|
|
}
|
504 |
|
|
}
|
505 |
|
|
|
506 |
|
|
static void yenta_interrupt_wrapper(unsigned long data)
|
507 |
|
|
{
|
508 |
|
|
pci_socket_t *socket = (pci_socket_t *) data;
|
509 |
|
|
|
510 |
|
|
yenta_interrupt(0, (void *)socket, NULL);
|
511 |
|
|
socket->poll_timer.expires = jiffies + HZ;
|
512 |
|
|
add_timer(&socket->poll_timer);
|
513 |
|
|
}
|
514 |
|
|
|
515 |
|
|
/*
|
516 |
|
|
* Only probe "regular" interrupts, don't
|
517 |
|
|
* touch dangerous spots like the mouse irq,
|
518 |
|
|
* because there are mice that apparently
|
519 |
|
|
* get really confused if they get fondled
|
520 |
|
|
* too intimately.
|
521 |
|
|
*
|
522 |
|
|
* Default to 11, 10, 9, 7, 6, 5, 4, 3.
|
523 |
|
|
*/
|
524 |
|
|
static u32 isa_interrupts = 0x0ef8;
|
525 |
|
|
|
526 |
|
|
static unsigned int yenta_probe_irq(pci_socket_t *socket, u32 isa_irq_mask)
|
527 |
|
|
{
|
528 |
|
|
int i;
|
529 |
|
|
unsigned long val;
|
530 |
|
|
u16 bridge_ctrl;
|
531 |
|
|
u32 mask;
|
532 |
|
|
|
533 |
|
|
/* Set up ISA irq routing to probe the ISA irqs.. */
|
534 |
|
|
bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL);
|
535 |
|
|
if (!(bridge_ctrl & CB_BRIDGE_INTR)) {
|
536 |
|
|
bridge_ctrl |= CB_BRIDGE_INTR;
|
537 |
|
|
config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
|
538 |
|
|
}
|
539 |
|
|
|
540 |
|
|
/*
|
541 |
|
|
* Probe for usable interrupts using the force
|
542 |
|
|
* register to generate bogus card status events.
|
543 |
|
|
*/
|
544 |
|
|
cb_writel(socket, CB_SOCKET_EVENT, -1);
|
545 |
|
|
cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
|
546 |
|
|
exca_writeb(socket, I365_CSCINT, 0);
|
547 |
|
|
val = probe_irq_on() & isa_irq_mask;
|
548 |
|
|
for (i = 1; i < 16; i++) {
|
549 |
|
|
if (!((val >> i) & 1))
|
550 |
|
|
continue;
|
551 |
|
|
exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG | (i << 4));
|
552 |
|
|
cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS);
|
553 |
|
|
udelay(100);
|
554 |
|
|
cb_writel(socket, CB_SOCKET_EVENT, -1);
|
555 |
|
|
}
|
556 |
|
|
cb_writel(socket, CB_SOCKET_MASK, 0);
|
557 |
|
|
exca_writeb(socket, I365_CSCINT, 0);
|
558 |
|
|
|
559 |
|
|
mask = probe_irq_mask(val) & 0xffff;
|
560 |
|
|
|
561 |
|
|
bridge_ctrl &= ~CB_BRIDGE_INTR;
|
562 |
|
|
config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
|
563 |
|
|
|
564 |
|
|
return mask;
|
565 |
|
|
}
|
566 |
|
|
|
567 |
|
|
/*
|
568 |
|
|
* Set static data that doesn't need re-initializing..
|
569 |
|
|
*/
|
570 |
|
|
static void yenta_get_socket_capabilities(pci_socket_t *socket, u32 isa_irq_mask)
|
571 |
|
|
{
|
572 |
|
|
socket->cap.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS;
|
573 |
|
|
socket->cap.map_size = 0x1000;
|
574 |
|
|
socket->cap.pci_irq = socket->cb_irq;
|
575 |
|
|
socket->cap.irq_mask = yenta_probe_irq(socket, isa_irq_mask);
|
576 |
|
|
socket->cap.cb_dev = socket->dev;
|
577 |
|
|
socket->cap.bus = NULL;
|
578 |
|
|
|
579 |
|
|
printk(KERN_INFO "Yenta ISA IRQ mask 0x%04x, PCI irq %d\n",
|
580 |
|
|
socket->cap.irq_mask, socket->cb_irq);
|
581 |
|
|
}
|
582 |
|
|
|
583 |
|
|
extern void cardbus_register(pci_socket_t *socket);
|
584 |
|
|
|
585 |
|
|
/*
|
586 |
|
|
* 'Bottom half' for the yenta_open routine. Allocate the interrupt line
|
587 |
|
|
* and register the socket with the upper layers.
|
588 |
|
|
*/
|
589 |
|
|
static void yenta_open_bh(void * data)
|
590 |
|
|
{
|
591 |
|
|
pci_socket_t * socket = (pci_socket_t *) data;
|
592 |
|
|
|
593 |
|
|
/* It's OK to overwrite this now */
|
594 |
|
|
socket->tq_task.routine = yenta_bh;
|
595 |
|
|
|
596 |
|
|
if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->name, socket)) {
|
597 |
|
|
/* No IRQ or request_irq failed. Poll */
|
598 |
|
|
socket->cb_irq = 0; /* But zero is a valid IRQ number. */
|
599 |
|
|
socket->poll_timer.function = yenta_interrupt_wrapper;
|
600 |
|
|
socket->poll_timer.data = (unsigned long)socket;
|
601 |
|
|
socket->poll_timer.expires = jiffies + HZ;
|
602 |
|
|
add_timer(&socket->poll_timer);
|
603 |
|
|
}
|
604 |
|
|
|
605 |
|
|
/* Figure out what the dang thing can do for the PCMCIA layer... */
|
606 |
|
|
yenta_get_socket_capabilities(socket, isa_interrupts);
|
607 |
|
|
printk(KERN_INFO "Socket status: %08x\n",
|
608 |
|
|
cb_readl(socket, CB_SOCKET_STATE));
|
609 |
|
|
|
610 |
|
|
/* Register it with the pcmcia layer.. */
|
611 |
|
|
cardbus_register(socket);
|
612 |
|
|
|
613 |
|
|
MOD_DEC_USE_COUNT;
|
614 |
|
|
}
|
615 |
|
|
|
616 |
|
|
static void yenta_clear_maps(pci_socket_t *socket)
|
617 |
|
|
{
|
618 |
|
|
int i;
|
619 |
|
|
pccard_io_map io = { 0, 0, 0, 0, 1 };
|
620 |
|
|
pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
|
621 |
|
|
|
622 |
|
|
mem.sys_stop = 0x0fff;
|
623 |
|
|
yenta_set_socket(socket, &dead_socket);
|
624 |
|
|
for (i = 0; i < 2; i++) {
|
625 |
|
|
io.map = i;
|
626 |
|
|
yenta_set_io_map(socket, &io);
|
627 |
|
|
}
|
628 |
|
|
for (i = 0; i < 5; i++) {
|
629 |
|
|
mem.map = i;
|
630 |
|
|
yenta_set_mem_map(socket, &mem);
|
631 |
|
|
}
|
632 |
|
|
}
|
633 |
|
|
|
634 |
|
|
/*
|
635 |
|
|
* Initialize the standard cardbus registers
|
636 |
|
|
*/
|
637 |
|
|
static void yenta_config_init(pci_socket_t *socket)
|
638 |
|
|
{
|
639 |
|
|
u32 state;
|
640 |
|
|
u16 bridge;
|
641 |
|
|
struct pci_dev *dev = socket->dev;
|
642 |
|
|
|
643 |
|
|
pci_set_power_state(socket->dev, 0);
|
644 |
|
|
|
645 |
|
|
config_writel(socket, CB_LEGACY_MODE_BASE, 0);
|
646 |
|
|
config_writel(socket, PCI_BASE_ADDRESS_0, dev->resource[0].start);
|
647 |
|
|
config_writew(socket, PCI_COMMAND,
|
648 |
|
|
PCI_COMMAND_IO |
|
649 |
|
|
PCI_COMMAND_MEMORY |
|
650 |
|
|
PCI_COMMAND_MASTER |
|
651 |
|
|
PCI_COMMAND_WAIT);
|
652 |
|
|
|
653 |
|
|
/* MAGIC NUMBERS! Fixme */
|
654 |
|
|
config_writeb(socket, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4);
|
655 |
|
|
config_writeb(socket, PCI_LATENCY_TIMER, 168);
|
656 |
|
|
config_writel(socket, PCI_PRIMARY_BUS,
|
657 |
|
|
(176 << 24) | /* sec. latency timer */
|
658 |
|
|
(dev->subordinate->subordinate << 16) | /* subordinate bus */
|
659 |
|
|
(dev->subordinate->secondary << 8) | /* secondary bus */
|
660 |
|
|
dev->subordinate->primary); /* primary bus */
|
661 |
|
|
|
662 |
|
|
/*
|
663 |
|
|
* Set up the bridging state:
|
664 |
|
|
* - enable write posting.
|
665 |
|
|
* - memory window 0 prefetchable, window 1 non-prefetchable
|
666 |
|
|
* - PCI interrupts enabled if a PCI interrupt exists..
|
667 |
|
|
*/
|
668 |
|
|
bridge = config_readw(socket, CB_BRIDGE_CONTROL);
|
669 |
|
|
bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_INTR | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN);
|
670 |
|
|
bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN;
|
671 |
|
|
if (!socket->cb_irq)
|
672 |
|
|
bridge |= CB_BRIDGE_INTR;
|
673 |
|
|
config_writew(socket, CB_BRIDGE_CONTROL, bridge);
|
674 |
|
|
|
675 |
|
|
exca_writeb(socket, I365_GBLCTL, 0x00);
|
676 |
|
|
exca_writeb(socket, I365_GENCTL, 0x00);
|
677 |
|
|
|
678 |
|
|
/* Redo card voltage interrogation */
|
679 |
|
|
state = cb_readl(socket, CB_SOCKET_STATE);
|
680 |
|
|
if (!(state & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD |
|
681 |
|
|
CB_3VCARD | CB_XVCARD | CB_YVCARD)))
|
682 |
|
|
|
683 |
|
|
cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST);
|
684 |
|
|
}
|
685 |
|
|
|
686 |
|
|
/* Called at resume and initialization events */
|
687 |
|
|
static int yenta_init(pci_socket_t *socket)
|
688 |
|
|
{
|
689 |
|
|
yenta_config_init(socket);
|
690 |
|
|
yenta_clear_maps(socket);
|
691 |
|
|
|
692 |
|
|
/* Re-enable interrupts */
|
693 |
|
|
cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK);
|
694 |
|
|
return 0;
|
695 |
|
|
}
|
696 |
|
|
|
697 |
|
|
static int yenta_suspend(pci_socket_t *socket)
|
698 |
|
|
{
|
699 |
|
|
yenta_set_socket(socket, &dead_socket);
|
700 |
|
|
|
701 |
|
|
/* Disable interrupts */
|
702 |
|
|
cb_writel(socket, CB_SOCKET_MASK, 0x0);
|
703 |
|
|
|
704 |
|
|
/*
|
705 |
|
|
* This does not work currently. The controller
|
706 |
|
|
* loses too much information during D3 to come up
|
707 |
|
|
* cleanly. We should probably fix yenta_init()
|
708 |
|
|
* to update all the critical registers, notably
|
709 |
|
|
* the IO and MEM bridging region data.. That is
|
710 |
|
|
* something that pci_set_power_state() should
|
711 |
|
|
* probably know about bridges anyway.
|
712 |
|
|
*
|
713 |
|
|
pci_set_power_state(socket->dev, 3);
|
714 |
|
|
*/
|
715 |
|
|
|
716 |
|
|
return 0;
|
717 |
|
|
}
|
718 |
|
|
|
719 |
|
|
/*
|
720 |
|
|
* Use an adaptive allocation for the memory resource,
|
721 |
|
|
* sometimes the size behind pci bridges is limited:
|
722 |
|
|
* 1/8 of the size of the io window of the parent.
|
723 |
|
|
* max 4 MB, min 16 kB.
|
724 |
|
|
*/
|
725 |
|
|
#define BRIDGE_SIZE_MAX 4*1024*1024
|
726 |
|
|
#define BRIDGE_SIZE_MIN 16*1024
|
727 |
|
|
|
728 |
|
|
static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type)
|
729 |
|
|
{
|
730 |
|
|
struct pci_bus *bus;
|
731 |
|
|
struct resource *root, *res;
|
732 |
|
|
u32 start, end;
|
733 |
|
|
u32 align, size, min, max;
|
734 |
|
|
unsigned offset;
|
735 |
|
|
unsigned mask;
|
736 |
|
|
|
737 |
|
|
/* The granularity of the memory limit is 4kB, on IO it's 4 bytes */
|
738 |
|
|
mask = ~0xfff;
|
739 |
|
|
if (type & IORESOURCE_IO)
|
740 |
|
|
mask = ~3;
|
741 |
|
|
|
742 |
|
|
offset = 0x1c + 8*nr;
|
743 |
|
|
bus = socket->dev->subordinate;
|
744 |
|
|
res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;
|
745 |
|
|
res->name = bus->name;
|
746 |
|
|
res->flags = type;
|
747 |
|
|
res->start = 0;
|
748 |
|
|
res->end = 0;
|
749 |
|
|
root = pci_find_parent_resource(socket->dev, res);
|
750 |
|
|
|
751 |
|
|
if (!root)
|
752 |
|
|
return;
|
753 |
|
|
|
754 |
|
|
start = config_readl(socket, offset) & mask;
|
755 |
|
|
end = config_readl(socket, offset+4) | ~mask;
|
756 |
|
|
if (start && end > start) {
|
757 |
|
|
res->start = start;
|
758 |
|
|
res->end = end;
|
759 |
|
|
if (request_resource(root, res) == 0)
|
760 |
|
|
return;
|
761 |
|
|
printk(KERN_INFO "yenta %s: Preassigned resource %d busy, reconfiguring...\n",
|
762 |
|
|
socket->dev->slot_name, nr);
|
763 |
|
|
res->start = res->end = 0;
|
764 |
|
|
}
|
765 |
|
|
|
766 |
|
|
if (type & IORESOURCE_IO) {
|
767 |
|
|
align = 1024;
|
768 |
|
|
size = 256;
|
769 |
|
|
min = 0x4000;
|
770 |
|
|
max = 0xffff;
|
771 |
|
|
} else {
|
772 |
|
|
unsigned long avail = root->end - root->start;
|
773 |
|
|
int i;
|
774 |
|
|
align = size = BRIDGE_SIZE_MAX;
|
775 |
|
|
if (size > avail/8) {
|
776 |
|
|
size=(avail+1)/8;
|
777 |
|
|
/* round size down to next power of 2 */
|
778 |
|
|
i = 0;
|
779 |
|
|
while ((size /= 2) != 0)
|
780 |
|
|
i++;
|
781 |
|
|
size = 1 << i;
|
782 |
|
|
}
|
783 |
|
|
if (size < BRIDGE_SIZE_MIN)
|
784 |
|
|
size = BRIDGE_SIZE_MIN;
|
785 |
|
|
align = size;
|
786 |
|
|
min = PCIBIOS_MIN_MEM; max = ~0U;
|
787 |
|
|
}
|
788 |
|
|
|
789 |
|
|
if (allocate_resource(root, res, size, min, max, align, NULL, NULL) < 0) {
|
790 |
|
|
printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n",
|
791 |
|
|
socket->dev->slot_name, type);
|
792 |
|
|
res->start = res->end = 0;
|
793 |
|
|
return;
|
794 |
|
|
}
|
795 |
|
|
|
796 |
|
|
config_writel(socket, offset, res->start);
|
797 |
|
|
config_writel(socket, offset+4, res->end);
|
798 |
|
|
}
|
799 |
|
|
|
800 |
|
|
/*
|
801 |
|
|
* Allocate the bridge mappings for the device..
|
802 |
|
|
*/
|
803 |
|
|
static void yenta_allocate_resources(pci_socket_t *socket)
|
804 |
|
|
{
|
805 |
|
|
yenta_allocate_res(socket, 0, IORESOURCE_MEM|IORESOURCE_PREFETCH);
|
806 |
|
|
yenta_allocate_res(socket, 1, IORESOURCE_MEM);
|
807 |
|
|
yenta_allocate_res(socket, 2, IORESOURCE_IO);
|
808 |
|
|
yenta_allocate_res(socket, 3, IORESOURCE_IO); /* PCI isn't clever enough to use this one yet */
|
809 |
|
|
}
|
810 |
|
|
|
811 |
|
|
/*
|
812 |
|
|
* Free the bridge mappings for the device..
|
813 |
|
|
*/
|
814 |
|
|
static void yenta_free_resources(pci_socket_t *socket)
|
815 |
|
|
{
|
816 |
|
|
int i;
|
817 |
|
|
for (i=0;i<4;i++) {
|
818 |
|
|
struct resource *res;
|
819 |
|
|
res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i;
|
820 |
|
|
if (res->start != 0 && res->end != 0)
|
821 |
|
|
release_resource(res);
|
822 |
|
|
res->start = res->end = 0;
|
823 |
|
|
}
|
824 |
|
|
}
|
825 |
|
|
/*
|
826 |
|
|
* Close it down - release our resources and go home..
|
827 |
|
|
*/
|
828 |
|
|
static void yenta_close(pci_socket_t *sock)
|
829 |
|
|
{
|
830 |
|
|
/* Disable all events so we don't die in an IRQ storm */
|
831 |
|
|
cb_writel(sock, CB_SOCKET_MASK, 0x0);
|
832 |
|
|
exca_writeb(sock, I365_CSCINT, 0);
|
833 |
|
|
|
834 |
|
|
if (sock->cb_irq)
|
835 |
|
|
free_irq(sock->cb_irq, sock);
|
836 |
|
|
else
|
837 |
|
|
del_timer_sync(&sock->poll_timer);
|
838 |
|
|
|
839 |
|
|
if (sock->base)
|
840 |
|
|
iounmap(sock->base);
|
841 |
|
|
yenta_free_resources(sock);
|
842 |
|
|
}
|
843 |
|
|
|
844 |
|
|
#include "ti113x.h"
|
845 |
|
|
#include "ricoh.h"
|
846 |
|
|
|
847 |
|
|
/*
|
848 |
|
|
* Different cardbus controllers have slightly different
|
849 |
|
|
* initialization sequences etc details. List them here..
|
850 |
|
|
*/
|
851 |
|
|
#define PD(x,y) PCI_VENDOR_ID_##x, PCI_DEVICE_ID_##x##_##y
|
852 |
|
|
static struct cardbus_override_struct {
|
853 |
|
|
unsigned short vendor;
|
854 |
|
|
unsigned short device;
|
855 |
|
|
struct pci_socket_ops *op;
|
856 |
|
|
} cardbus_override[] = {
|
857 |
|
|
{ PD(TI,1130), &ti113x_ops },
|
858 |
|
|
{ PD(TI,1031), &ti_ops },
|
859 |
|
|
{ PD(TI,1131), &ti113x_ops },
|
860 |
|
|
{ PD(TI,1250), &ti1250_ops },
|
861 |
|
|
{ PD(TI,1220), &ti_ops },
|
862 |
|
|
{ PD(TI,1221), &ti_ops },
|
863 |
|
|
{ PD(TI,1210), &ti_ops },
|
864 |
|
|
{ PD(TI,1450), &ti_ops },
|
865 |
|
|
{ PD(TI,1225), &ti_ops },
|
866 |
|
|
{ PD(TI,1251A), &ti_ops },
|
867 |
|
|
{ PD(TI,1211), &ti_ops },
|
868 |
|
|
{ PD(TI,1251B), &ti_ops },
|
869 |
|
|
{ PD(TI,1410), &ti_ops },
|
870 |
|
|
{ PD(TI,1420), &ti_ops },
|
871 |
|
|
{ PD(TI,4410), &ti_ops },
|
872 |
|
|
{ PD(TI,4451), &ti_ops },
|
873 |
|
|
{ PD(TI,1510), &ti_ops },
|
874 |
|
|
{ PD(TI,1520), &ti_ops },
|
875 |
|
|
|
876 |
|
|
{ PD(ENE,1211), &ti_ops },
|
877 |
|
|
{ PD(ENE,1225), &ti_ops },
|
878 |
|
|
{ PD(ENE,1410), &ti_ops },
|
879 |
|
|
{ PD(ENE,1420), &ti_ops },
|
880 |
|
|
|
881 |
|
|
{ PD(RICOH,RL5C465), &ricoh_ops },
|
882 |
|
|
{ PD(RICOH,RL5C466), &ricoh_ops },
|
883 |
|
|
{ PD(RICOH,RL5C475), &ricoh_ops },
|
884 |
|
|
{ PD(RICOH,RL5C476), &ricoh_ops },
|
885 |
|
|
{ PD(RICOH,RL5C478), &ricoh_ops }
|
886 |
|
|
};
|
887 |
|
|
|
888 |
|
|
#define NR_OVERRIDES (sizeof(cardbus_override)/sizeof(struct cardbus_override_struct))
|
889 |
|
|
|
890 |
|
|
/*
|
891 |
|
|
* Initialize a cardbus controller. Make sure we have a usable
|
892 |
|
|
* interrupt, and that we can map the cardbus area. Fill in the
|
893 |
|
|
* socket information structure..
|
894 |
|
|
*/
|
895 |
|
|
static int yenta_open(pci_socket_t *socket)
|
896 |
|
|
{
|
897 |
|
|
int i;
|
898 |
|
|
struct pci_dev *dev = socket->dev;
|
899 |
|
|
|
900 |
|
|
/*
|
901 |
|
|
* Do some basic sanity checking..
|
902 |
|
|
*/
|
903 |
|
|
if (pci_enable_device(dev))
|
904 |
|
|
return -1;
|
905 |
|
|
if (!pci_resource_start(dev, 0)) {
|
906 |
|
|
printk(KERN_ERR "No cardbus resource!\n");
|
907 |
|
|
return -1;
|
908 |
|
|
}
|
909 |
|
|
|
910 |
|
|
/*
|
911 |
|
|
* Ok, start setup.. Map the cardbus registers,
|
912 |
|
|
* and request the IRQ.
|
913 |
|
|
*/
|
914 |
|
|
socket->base = ioremap(pci_resource_start(dev, 0), 0x1000);
|
915 |
|
|
if (!socket->base)
|
916 |
|
|
return -1;
|
917 |
|
|
|
918 |
|
|
yenta_config_init(socket);
|
919 |
|
|
|
920 |
|
|
/* Disable all events */
|
921 |
|
|
cb_writel(socket, CB_SOCKET_MASK, 0x0);
|
922 |
|
|
|
923 |
|
|
/* Set up the bridge regions.. */
|
924 |
|
|
yenta_allocate_resources(socket);
|
925 |
|
|
|
926 |
|
|
socket->cb_irq = dev->irq;
|
927 |
|
|
|
928 |
|
|
/* Do we have special options for the device? */
|
929 |
|
|
for (i = 0; i < NR_OVERRIDES; i++) {
|
930 |
|
|
struct cardbus_override_struct *d = cardbus_override+i;
|
931 |
|
|
if (dev->vendor == d->vendor && dev->device == d->device) {
|
932 |
|
|
socket->op = d->op;
|
933 |
|
|
if (d->op->open) {
|
934 |
|
|
int retval = d->op->open(socket);
|
935 |
|
|
if (retval < 0)
|
936 |
|
|
return retval;
|
937 |
|
|
}
|
938 |
|
|
}
|
939 |
|
|
}
|
940 |
|
|
|
941 |
|
|
/* Get the PCMCIA kernel thread to complete the
|
942 |
|
|
initialisation later. We can't do this here,
|
943 |
|
|
because, er, because Linus says so :)
|
944 |
|
|
*/
|
945 |
|
|
socket->tq_task.routine = yenta_open_bh;
|
946 |
|
|
socket->tq_task.data = socket;
|
947 |
|
|
|
948 |
|
|
MOD_INC_USE_COUNT;
|
949 |
|
|
schedule_task(&socket->tq_task);
|
950 |
|
|
|
951 |
|
|
return 0;
|
952 |
|
|
}
|
953 |
|
|
|
954 |
|
|
/*
|
955 |
|
|
* Standard plain cardbus - no frills, no extensions
|
956 |
|
|
*/
|
957 |
|
|
struct pci_socket_ops yenta_operations = {
|
958 |
|
|
yenta_open,
|
959 |
|
|
yenta_close,
|
960 |
|
|
yenta_init,
|
961 |
|
|
yenta_suspend,
|
962 |
|
|
yenta_get_status,
|
963 |
|
|
yenta_get_socket,
|
964 |
|
|
yenta_set_socket,
|
965 |
|
|
yenta_get_io_map,
|
966 |
|
|
yenta_set_io_map,
|
967 |
|
|
yenta_get_mem_map,
|
968 |
|
|
yenta_set_mem_map,
|
969 |
|
|
yenta_proc_setup
|
970 |
|
|
};
|
971 |
|
|
EXPORT_SYMBOL(yenta_operations);
|
972 |
|
|
MODULE_LICENSE("GPL");
|