Blame view
drivers/pcmcia/m8xx_pcmcia.c
31.8 KB
de957c89b [PATCH] MPC8xx PC... |
1 2 3 |
/* * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series. * |
cbba0de2f pcmcia: Update em... |
4 |
* (C) 1999-2000 Magnus Damm <damm@opensource.se> |
de957c89b [PATCH] MPC8xx PC... |
5 6 7 8 9 10 11 |
* (C) 2001-2002 Montavista Software, Inc. * <mlocke@mvista.com> * * Support for two slots by Cyclades Corporation * <oliver.kurth@cyclades.de> * Further fixes, v2.6 kernel port * <marcelo.tosatti@cyclades.com> |
1371d3be0 [PATCH] 8xx PCMCI... |
12 |
* |
80128ff79 [POWERPC] 8xx: mp... |
13 |
* Some fixes, additions (C) 2005-2007 Montavista Software, Inc. |
1371d3be0 [PATCH] 8xx PCMCI... |
14 |
* <vbordug@ru.mvista.com> |
de957c89b [PATCH] MPC8xx PC... |
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
* * "The ExCA standard specifies that socket controllers should provide * two IO and five memory windows per socket, which can be independently * configured and positioned in the host address space and mapped to * arbitrary segments of card address space. " - David A Hinds. 1999 * * This controller does _not_ meet the ExCA standard. * * m8xx pcmcia controller brief info: * + 8 windows (attrib, mem, i/o) * + up to two slots (SLOT_A and SLOT_B) * + inputpins, outputpins, event and mask registers. * - no offset register. sigh. * * Because of the lacking offset register we must map the whole card. * We assign each memory window PCMCIA_MEM_WIN_SIZE address space. * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE. * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE. * They are maximum 64KByte each... */ #include <linux/module.h> #include <linux/init.h> #include <linux/types.h> #include <linux/fcntl.h> #include <linux/string.h> |
de957c89b [PATCH] MPC8xx PC... |
42 43 |
#include <linux/kernel.h> #include <linux/errno.h> |
de957c89b [PATCH] MPC8xx PC... |
44 45 46 47 |
#include <linux/timer.h> #include <linux/ioport.h> #include <linux/delay.h> #include <linux/interrupt.h> |
80128ff79 [POWERPC] 8xx: mp... |
48 |
#include <linux/fsl_devices.h> |
1977f0327 remove asm/bitops... |
49 |
#include <linux/bitops.h> |
ad19dbdb4 pcmcia: Use linux... |
50 51 |
#include <linux/of_device.h> #include <linux/of_platform.h> |
de957c89b [PATCH] MPC8xx PC... |
52 |
|
80128ff79 [POWERPC] 8xx: mp... |
53 |
#include <asm/io.h> |
80128ff79 [POWERPC] 8xx: mp... |
54 55 |
#include <asm/system.h> #include <asm/time.h> |
de957c89b [PATCH] MPC8xx PC... |
56 57 58 |
#include <asm/mpc8xx.h> #include <asm/8xx_immap.h> #include <asm/irq.h> |
80128ff79 [POWERPC] 8xx: mp... |
59 |
#include <asm/fs_pd.h> |
de957c89b [PATCH] MPC8xx PC... |
60 |
|
de957c89b [PATCH] MPC8xx PC... |
61 |
#include <pcmcia/ss.h> |
de957c89b [PATCH] MPC8xx PC... |
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
#define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args) #define pcmcia_error(args...) printk(KERN_ERR "m8xx_pcmcia: "args) static const char *version = "Version 0.06, Aug 2005"; MODULE_LICENSE("Dual MPL/GPL"); #if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) /* The RPX series use SLOT_B */ #if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE) #define CONFIG_PCMCIA_SLOT_B #define CONFIG_BD_IS_MHZ #endif /* The ADS board use SLOT_A */ #ifdef CONFIG_ADS #define CONFIG_PCMCIA_SLOT_A #define CONFIG_BD_IS_MHZ #endif /* The FADS series are a mess */ #ifdef CONFIG_FADS #if defined(CONFIG_MPC860T) || defined(CONFIG_MPC860) || defined(CONFIG_MPC821) #define CONFIG_PCMCIA_SLOT_A #else #define CONFIG_PCMCIA_SLOT_B #endif #endif |
1371d3be0 [PATCH] 8xx PCMCI... |
90 91 92 93 |
#if defined(CONFIG_MPC885ADS) #define CONFIG_PCMCIA_SLOT_A #define PCMCIA_GLITCHY_CD #endif |
de957c89b [PATCH] MPC8xx PC... |
94 95 96 97 98 |
/* Cyclades ACS uses both slots */ #ifdef CONFIG_PRxK #define CONFIG_PCMCIA_SLOT_A #define CONFIG_PCMCIA_SLOT_B #endif |
99121c0da powerpc: 8xx: fix... |
99 |
#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */ |
de957c89b [PATCH] MPC8xx PC... |
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
#if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B) #define PCMCIA_SOCKETS_NO 2 /* We have only 8 windows, dualsocket support will be limited. */ #define PCMCIA_MEM_WIN_NO 2 #define PCMCIA_IO_WIN_NO 2 #define PCMCIA_SLOT_MSG "SLOT_A and SLOT_B" #elif defined(CONFIG_PCMCIA_SLOT_A) || defined(CONFIG_PCMCIA_SLOT_B) #define PCMCIA_SOCKETS_NO 1 /* full support for one slot */ #define PCMCIA_MEM_WIN_NO 5 #define PCMCIA_IO_WIN_NO 2 /* define _slot_ to be able to optimize macros */ #ifdef CONFIG_PCMCIA_SLOT_A #define _slot_ 0 #define PCMCIA_SLOT_MSG "SLOT_A" #else #define _slot_ 1 #define PCMCIA_SLOT_MSG "SLOT_B" #endif #else #error m8xx_pcmcia: Bad configuration! #endif /* ------------------------------------------------------------------------- */ |
99121c0da powerpc: 8xx: fix... |
131 132 133 |
#define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0 */ #define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte */ #define PCMCIA_IO_WIN_BASE _IO_BASE /* base address for io window 0 */ |
de957c89b [PATCH] MPC8xx PC... |
134 |
/* ------------------------------------------------------------------------- */ |
80128ff79 [POWERPC] 8xx: mp... |
135 |
static int pcmcia_schlvl; |
de957c89b [PATCH] MPC8xx PC... |
136 |
|
34af946a2 [PATCH] spin/rwlo... |
137 |
static DEFINE_SPINLOCK(events_lock); |
de957c89b [PATCH] MPC8xx PC... |
138 |
|
de957c89b [PATCH] MPC8xx PC... |
139 140 141 142 |
#define PCMCIA_SOCKET_KEY_5V 1 #define PCMCIA_SOCKET_KEY_LV 2 /* look up table for pgcrx registers */ |
80128ff79 [POWERPC] 8xx: mp... |
143 |
static u32 *m8xx_pgcrx[2]; |
de957c89b [PATCH] MPC8xx PC... |
144 145 146 147 148 149 150 151 152 |
/* * This structure is used to address each window in the PCMCIA controller. * * Keep in mind that we assume that pcmcia_win[n+1] is mapped directly * after pcmcia_win[n]... */ struct pcmcia_win { |
99121c0da powerpc: 8xx: fix... |
153 154 |
u32 br; u32 or; |
de957c89b [PATCH] MPC8xx PC... |
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
}; /* * For some reason the hardware guys decided to make both slots share * some registers. * * Could someone invent object oriented hardware ? * * The macros are used to get the right bit from the registers. * SLOT_A : slot = 0 * SLOT_B : slot = 1 */ #define M8XX_PCMCIA_VS1(slot) (0x80000000 >> (slot << 4)) #define M8XX_PCMCIA_VS2(slot) (0x40000000 >> (slot << 4)) #define M8XX_PCMCIA_VS_MASK(slot) (0xc0000000 >> (slot << 4)) #define M8XX_PCMCIA_VS_SHIFT(slot) (30 - (slot << 4)) #define M8XX_PCMCIA_WP(slot) (0x20000000 >> (slot << 4)) #define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4)) #define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4)) #define M8XX_PCMCIA_BVD2(slot) (0x04000000 >> (slot << 4)) #define M8XX_PCMCIA_BVD1(slot) (0x02000000 >> (slot << 4)) #define M8XX_PCMCIA_RDY(slot) (0x01000000 >> (slot << 4)) #define M8XX_PCMCIA_RDY_L(slot) (0x00800000 >> (slot << 4)) #define M8XX_PCMCIA_RDY_H(slot) (0x00400000 >> (slot << 4)) #define M8XX_PCMCIA_RDY_R(slot) (0x00200000 >> (slot << 4)) #define M8XX_PCMCIA_RDY_F(slot) (0x00100000 >> (slot << 4)) #define M8XX_PCMCIA_MASK(slot) (0xFFFF0000 >> (slot << 4)) #define M8XX_PCMCIA_POR_VALID 0x00000001 #define M8XX_PCMCIA_POR_WRPROT 0x00000002 #define M8XX_PCMCIA_POR_ATTRMEM 0x00000010 #define M8XX_PCMCIA_POR_IO 0x00000018 #define M8XX_PCMCIA_POR_16BIT 0x00000040 #define M8XX_PGCRX(slot) m8xx_pgcrx[slot] #define M8XX_PGCRX_CXOE 0x00000080 #define M8XX_PGCRX_CXRESET 0x00000040 /* we keep one lookup table per socket to check flags */ |
99121c0da powerpc: 8xx: fix... |
197 |
#define PCMCIA_EVENTS_MAX 5 /* 4 max at a time + termination */ |
de957c89b [PATCH] MPC8xx PC... |
198 199 200 201 202 |
struct event_table { u32 regbit; u32 eventbit; }; |
80128ff79 [POWERPC] 8xx: mp... |
203 |
static const char driver_name[] = "m8xx-pcmcia"; |
de957c89b [PATCH] MPC8xx PC... |
204 |
struct socket_info { |
99121c0da powerpc: 8xx: fix... |
205 206 |
void (*handler) (void *info, u32 events); void *info; |
de957c89b [PATCH] MPC8xx PC... |
207 208 |
u32 slot; |
80128ff79 [POWERPC] 8xx: mp... |
209 210 211 |
pcmconf8xx_t *pcmcia; u32 bus_freq; int hwirq; |
de957c89b [PATCH] MPC8xx PC... |
212 213 214 |
socket_state_t state; struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO]; |
99121c0da powerpc: 8xx: fix... |
215 |
struct pccard_io_map io_win[PCMCIA_IO_WIN_NO]; |
de957c89b [PATCH] MPC8xx PC... |
216 217 218 219 220 221 222 223 224 225 226 227 |
struct event_table events[PCMCIA_EVENTS_MAX]; struct pcmcia_socket socket; }; static struct socket_info socket[PCMCIA_SOCKETS_NO]; /* * Search this table to see if the windowsize is * supported... */ #define M8XX_SIZES_NO 32 |
99121c0da powerpc: 8xx: fix... |
228 |
static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] = { |
de957c89b [PATCH] MPC8xx PC... |
229 230 231 232 233 234 235 236 237 238 239 240 |
0x00000001, 0x00000002, 0x00000008, 0x00000004, 0x00000080, 0x00000040, 0x00000010, 0x00000020, 0x00008000, 0x00004000, 0x00001000, 0x00002000, 0x00000100, 0x00000200, 0x00000800, 0x00000400, 0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01000000, 0x02000000, 0xffffffff, 0x04000000, 0x00010000, 0x00020000, 0x00080000, 0x00040000, 0x00800000, 0x00400000, 0x00100000, 0x00200000 }; /* ------------------------------------------------------------------------- */ |
7d12e780e IRQ: Maintain reg... |
241 |
static irqreturn_t m8xx_interrupt(int irq, void *dev); |
de957c89b [PATCH] MPC8xx PC... |
242 |
|
99121c0da powerpc: 8xx: fix... |
243 |
#define PCMCIA_BMT_LIMIT (15*4) /* Bus Monitor Timeout value */ |
de957c89b [PATCH] MPC8xx PC... |
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
/* ------------------------------------------------------------------------- */ /* board specific stuff: */ /* voltage_set(), hardware_enable() and hardware_disable() */ /* ------------------------------------------------------------------------- */ /* RPX Boards from Embedded Planet */ #if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE) /* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks. * SYPCR is write once only, therefore must the slowest memory be faster * than the bus monitor or we will get a machine check due to the bus timeout. */ #define PCMCIA_BOARD_MSG "RPX CLASSIC or RPX LITE" #undef PCMCIA_BMT_LIMIT #define PCMCIA_BMT_LIMIT (6*8) static int voltage_set(int slot, int vcc, int vpp) { u32 reg = 0; |
99121c0da powerpc: 8xx: fix... |
266 267 268 |
switch (vcc) { case 0: break; |
de957c89b [PATCH] MPC8xx PC... |
269 270 271 272 273 274 275 276 277 |
case 33: reg |= BCSR1_PCVCTL4; break; case 50: reg |= BCSR1_PCVCTL5; break; default: return 1; } |
99121c0da powerpc: 8xx: fix... |
278 279 280 |
switch (vpp) { case 0: break; |
de957c89b [PATCH] MPC8xx PC... |
281 282 |
case 33: case 50: |
99121c0da powerpc: 8xx: fix... |
283 |
if (vcc == vpp) |
de957c89b [PATCH] MPC8xx PC... |
284 285 286 287 288 289 290 291 292 |
reg |= BCSR1_PCVCTL6; else return 1; break; case 120: reg |= BCSR1_PCVCTL7; default: return 1; } |
99121c0da powerpc: 8xx: fix... |
293 |
if (!((vcc == 50) || (vcc == 0))) |
de957c89b [PATCH] MPC8xx PC... |
294 295 296 |
return 1; /* first, turn off all power */ |
99121c0da powerpc: 8xx: fix... |
297 298 299 300 301 |
out_be32(((u32 *) RPX_CSR_ADDR), in_be32(((u32 *) RPX_CSR_ADDR)) & ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5 | BCSR1_PCVCTL6 | BCSR1_PCVCTL7)); |
de957c89b [PATCH] MPC8xx PC... |
302 303 |
/* enable new powersettings */ |
99121c0da powerpc: 8xx: fix... |
304 |
out_be32(((u32 *) RPX_CSR_ADDR), in_be32(((u32 *) RPX_CSR_ADDR)) | reg); |
de957c89b [PATCH] MPC8xx PC... |
305 306 307 308 309 |
return 0; } #define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V |
99121c0da powerpc: 8xx: fix... |
310 311 |
#define hardware_enable(_slot_) /* No hardware to enable */ #define hardware_disable(_slot_) /* No hardware to disable */ |
de957c89b [PATCH] MPC8xx PC... |
312 |
|
99121c0da powerpc: 8xx: fix... |
313 |
#endif /* CONFIG_RPXCLASSIC */ |
de957c89b [PATCH] MPC8xx PC... |
314 315 316 317 318 319 320 321 322 323 |
/* FADS Boards from Motorola */ #if defined(CONFIG_FADS) #define PCMCIA_BOARD_MSG "FADS" static int voltage_set(int slot, int vcc, int vpp) { u32 reg = 0; |
99121c0da powerpc: 8xx: fix... |
324 325 326 327 328 329 330 331 332 333 334 |
switch (vcc) { case 0: break; case 33: reg |= BCSR1_PCCVCC0; break; case 50: reg |= BCSR1_PCCVCC1; break; default: return 1; |
de957c89b [PATCH] MPC8xx PC... |
335 |
} |
99121c0da powerpc: 8xx: fix... |
336 337 338 339 340 341 342 343 |
switch (vpp) { case 0: break; case 33: case 50: if (vcc == vpp) reg |= BCSR1_PCCVPP1; else |
de957c89b [PATCH] MPC8xx PC... |
344 |
return 1; |
99121c0da powerpc: 8xx: fix... |
345 346 347 348 349 350 351 352 |
break; case 120: if ((vcc == 33) || (vcc == 50)) reg |= BCSR1_PCCVPP0; else return 1; default: return 1; |
de957c89b [PATCH] MPC8xx PC... |
353 354 355 |
} /* first, turn off all power */ |
99121c0da powerpc: 8xx: fix... |
356 357 358 |
out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK)); |
1371d3be0 [PATCH] 8xx PCMCI... |
359 360 |
/* enable new powersettings */ |
99121c0da powerpc: 8xx: fix... |
361 |
out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | reg); |
1371d3be0 [PATCH] 8xx PCMCI... |
362 363 364 365 366 367 368 369 |
return 0; } #define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V static void hardware_enable(int slot) { |
99121c0da powerpc: 8xx: fix... |
370 |
out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) & ~BCSR1_PCCEN); |
1371d3be0 [PATCH] 8xx PCMCI... |
371 372 373 374 |
} static void hardware_disable(int slot) { |
99121c0da powerpc: 8xx: fix... |
375 |
out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | BCSR1_PCCEN); |
1371d3be0 [PATCH] 8xx PCMCI... |
376 377 378 379 380 381 382 383 384 |
} #endif /* MPC885ADS Boards */ #if defined(CONFIG_MPC885ADS) #define PCMCIA_BOARD_MSG "MPC885ADS" |
80128ff79 [POWERPC] 8xx: mp... |
385 |
#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V |
1371d3be0 [PATCH] 8xx PCMCI... |
386 |
|
80128ff79 [POWERPC] 8xx: mp... |
387 |
static inline void hardware_enable(int slot) |
1371d3be0 [PATCH] 8xx PCMCI... |
388 |
{ |
99121c0da powerpc: 8xx: fix... |
389 |
m8xx_pcmcia_ops.hw_ctrl(slot, 1); |
de957c89b [PATCH] MPC8xx PC... |
390 |
} |
80128ff79 [POWERPC] 8xx: mp... |
391 |
static inline void hardware_disable(int slot) |
de957c89b [PATCH] MPC8xx PC... |
392 |
{ |
80128ff79 [POWERPC] 8xx: mp... |
393 |
m8xx_pcmcia_ops.hw_ctrl(slot, 0); |
de957c89b [PATCH] MPC8xx PC... |
394 |
} |
80128ff79 [POWERPC] 8xx: mp... |
395 |
static inline int voltage_set(int slot, int vcc, int vpp) |
de957c89b [PATCH] MPC8xx PC... |
396 |
{ |
80128ff79 [POWERPC] 8xx: mp... |
397 |
return m8xx_pcmcia_ops.voltage_set(slot, vcc, vpp); |
de957c89b [PATCH] MPC8xx PC... |
398 399 400 401 402 403 404 405 406 407 408 409 410 411 |
} #endif /* ------------------------------------------------------------------------- */ /* Motorola MBX860 */ #if defined(CONFIG_MBX) #define PCMCIA_BOARD_MSG "MBX" static int voltage_set(int slot, int vcc, int vpp) { u8 reg = 0; |
99121c0da powerpc: 8xx: fix... |
412 413 414 415 416 417 418 419 420 421 422 |
switch (vcc) { case 0: break; case 33: reg |= CSR2_VCC_33; break; case 50: reg |= CSR2_VCC_50; break; default: return 1; |
de957c89b [PATCH] MPC8xx PC... |
423 |
} |
99121c0da powerpc: 8xx: fix... |
424 425 426 427 428 429 430 431 432 433 434 435 436 437 |
switch (vpp) { case 0: break; case 33: case 50: if (vcc == vpp) reg |= CSR2_VPP_VCC; else return 1; break; case 120: if ((vcc == 33) || (vcc == 50)) reg |= CSR2_VPP_12; else |
de957c89b [PATCH] MPC8xx PC... |
438 |
return 1; |
99121c0da powerpc: 8xx: fix... |
439 440 |
default: return 1; |
de957c89b [PATCH] MPC8xx PC... |
441 442 443 |
} /* first, turn off all power */ |
99121c0da powerpc: 8xx: fix... |
444 445 |
out_8((u8 *) MBX_CSR2_ADDR, in_8((u8 *) MBX_CSR2_ADDR) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK)); |
de957c89b [PATCH] MPC8xx PC... |
446 447 |
/* enable new powersettings */ |
99121c0da powerpc: 8xx: fix... |
448 |
out_8((u8 *) MBX_CSR2_ADDR, in_8((u8 *) MBX_CSR2_ADDR) | reg); |
de957c89b [PATCH] MPC8xx PC... |
449 450 451 452 453 |
return 0; } #define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V |
99121c0da powerpc: 8xx: fix... |
454 455 |
#define hardware_enable(_slot_) /* No hardware to enable */ #define hardware_disable(_slot_) /* No hardware to disable */ |
de957c89b [PATCH] MPC8xx PC... |
456 |
|
99121c0da powerpc: 8xx: fix... |
457 |
#endif /* CONFIG_MBX */ |
de957c89b [PATCH] MPC8xx PC... |
458 459 460 461 462 463 464 465 466 467 468 469 |
#if defined(CONFIG_PRxK) #include <asm/cpld.h> extern volatile fpga_pc_regs *fpga_pc; #define PCMCIA_BOARD_MSG "MPC855T" static int voltage_set(int slot, int vcc, int vpp) { u8 reg = 0; u8 regread; cpld_regs *ccpld = get_cpld(); |
99121c0da powerpc: 8xx: fix... |
470 471 472 473 474 475 476 477 478 479 480 |
switch (vcc) { case 0: break; case 33: reg |= PCMCIA_VCC_33; break; case 50: reg |= PCMCIA_VCC_50; break; default: return 1; |
de957c89b [PATCH] MPC8xx PC... |
481 |
} |
99121c0da powerpc: 8xx: fix... |
482 483 484 485 486 487 488 489 |
switch (vpp) { case 0: break; case 33: case 50: if (vcc == vpp) reg |= PCMCIA_VPP_VCC; else |
de957c89b [PATCH] MPC8xx PC... |
490 |
return 1; |
99121c0da powerpc: 8xx: fix... |
491 492 493 494 495 496 497 498 |
break; case 120: if ((vcc == 33) || (vcc == 50)) reg |= PCMCIA_VPP_12; else return 1; default: return 1; |
de957c89b [PATCH] MPC8xx PC... |
499 500 501 502 |
} reg = reg >> (slot << 2); regread = in_8(&ccpld->fpga_pc_ctl); |
99121c0da powerpc: 8xx: fix... |
503 504 |
if (reg != (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) { |
de957c89b [PATCH] MPC8xx PC... |
505 |
/* enable new powersettings */ |
99121c0da powerpc: 8xx: fix... |
506 507 508 |
regread = regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)); |
de957c89b [PATCH] MPC8xx PC... |
509 510 511 512 513 514 515 516 |
out_8(&ccpld->fpga_pc_ctl, reg | regread); msleep(100); } return 0; } #define socket_get(_slot_) PCMCIA_SOCKET_KEY_LV |
99121c0da powerpc: 8xx: fix... |
517 518 |
#define hardware_enable(_slot_) /* No hardware to enable */ #define hardware_disable(_slot_) /* No hardware to disable */ |
de957c89b [PATCH] MPC8xx PC... |
519 |
|
99121c0da powerpc: 8xx: fix... |
520 |
#endif /* CONFIG_PRxK */ |
de957c89b [PATCH] MPC8xx PC... |
521 |
|
de957c89b [PATCH] MPC8xx PC... |
522 |
static u32 pending_events[PCMCIA_SOCKETS_NO]; |
34af946a2 [PATCH] spin/rwlo... |
523 |
static DEFINE_SPINLOCK(pending_event_lock); |
de957c89b [PATCH] MPC8xx PC... |
524 |
|
7d12e780e IRQ: Maintain reg... |
525 |
static irqreturn_t m8xx_interrupt(int irq, void *dev) |
de957c89b [PATCH] MPC8xx PC... |
526 527 528 529 |
{ struct socket_info *s; struct event_table *e; unsigned int i, events, pscr, pipr, per; |
99121c0da powerpc: 8xx: fix... |
530 |
pcmconf8xx_t *pcmcia = socket[0].pcmcia; |
de957c89b [PATCH] MPC8xx PC... |
531 |
|
c9f50dddd pcmcia: use dynam... |
532 533 |
pr_debug("m8xx_pcmcia: Interrupt! "); |
de957c89b [PATCH] MPC8xx PC... |
534 |
/* get interrupt sources */ |
80128ff79 [POWERPC] 8xx: mp... |
535 536 537 |
pscr = in_be32(&pcmcia->pcmc_pscr); pipr = in_be32(&pcmcia->pcmc_pipr); per = in_be32(&pcmcia->pcmc_per); |
de957c89b [PATCH] MPC8xx PC... |
538 |
|
99121c0da powerpc: 8xx: fix... |
539 |
for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { |
de957c89b [PATCH] MPC8xx PC... |
540 541 542 |
s = &socket[i]; e = &s->events[0]; events = 0; |
99121c0da powerpc: 8xx: fix... |
543 544 |
while (e->regbit) { if (pscr & e->regbit) |
de957c89b [PATCH] MPC8xx PC... |
545 |
events |= e->eventbit; |
99121c0da powerpc: 8xx: fix... |
546 |
e++; |
de957c89b [PATCH] MPC8xx PC... |
547 548 549 550 551 552 553 |
} /* * report only if both card detect signals are the same * not too nice done, * we depend on that CD2 is the bit to the left of CD1... */ |
99121c0da powerpc: 8xx: fix... |
554 555 556 |
if (events & SS_DETECT) if (((pipr & M8XX_PCMCIA_CD2(i)) >> 1) ^ (pipr & M8XX_PCMCIA_CD1(i))) { |
de957c89b [PATCH] MPC8xx PC... |
557 558 |
events &= ~SS_DETECT; } |
de957c89b [PATCH] MPC8xx PC... |
559 560 561 562 563 564 |
#ifdef PCMCIA_GLITCHY_CD /* * I've experienced CD problems with my ADS board. * We make an extra check to see if there was a * real change of Card detection. */ |
99121c0da powerpc: 8xx: fix... |
565 566 567 568 |
if ((events & SS_DETECT) && ((pipr & (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i))) == 0) && (s->state.Vcc | s->state.Vpp)) { |
de957c89b [PATCH] MPC8xx PC... |
569 570 571 |
events &= ~SS_DETECT; /*printk( "CD glitch workaround - CD = 0x%08x! ", |
99121c0da powerpc: 8xx: fix... |
572 573 |
(pipr & (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i)))); */ |
de957c89b [PATCH] MPC8xx PC... |
574 575 576 577 |
} #endif /* call the handler */ |
c9f50dddd pcmcia: use dynam... |
578 |
pr_debug("m8xx_pcmcia: slot %u: events = 0x%02x, pscr = 0x%08x, " |
99121c0da powerpc: 8xx: fix... |
579 580 |
"pipr = 0x%08x ", i, events, pscr, pipr); |
de957c89b [PATCH] MPC8xx PC... |
581 |
|
99121c0da powerpc: 8xx: fix... |
582 |
if (events) { |
de957c89b [PATCH] MPC8xx PC... |
583 584 585 586 587 588 589 590 591 592 593 594 |
spin_lock(&pending_event_lock); pending_events[i] |= events; spin_unlock(&pending_event_lock); /* * Turn off RDY_L bits in the PER mask on * CD interrupt receival. * * They can generate bad interrupts on the * ACS4,8,16,32. - marcelo */ per &= ~M8XX_PCMCIA_RDY_L(0); per &= ~M8XX_PCMCIA_RDY_L(1); |
80128ff79 [POWERPC] 8xx: mp... |
595 |
out_be32(&pcmcia->pcmc_per, per); |
de957c89b [PATCH] MPC8xx PC... |
596 597 598 599 600 601 602 |
if (events) pcmcia_parse_events(&socket[i].socket, events); } } /* clear the interrupt sources */ |
80128ff79 [POWERPC] 8xx: mp... |
603 |
out_be32(&pcmcia->pcmc_pscr, pscr); |
de957c89b [PATCH] MPC8xx PC... |
604 |
|
c9f50dddd pcmcia: use dynam... |
605 606 |
pr_debug("m8xx_pcmcia: Interrupt done. "); |
de957c89b [PATCH] MPC8xx PC... |
607 608 609 610 611 612 613 |
return IRQ_HANDLED; } static u32 m8xx_get_graycode(u32 size) { u32 k; |
99121c0da powerpc: 8xx: fix... |
614 615 |
for (k = 0; k < M8XX_SIZES_NO; k++) if (m8xx_size_to_gray[k] == size) |
de957c89b [PATCH] MPC8xx PC... |
616 |
break; |
99121c0da powerpc: 8xx: fix... |
617 |
if ((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1)) |
de957c89b [PATCH] MPC8xx PC... |
618 619 620 621 |
k = -1; return k; } |
80128ff79 [POWERPC] 8xx: mp... |
622 |
static u32 m8xx_get_speed(u32 ns, u32 is_io, u32 bus_freq) |
de957c89b [PATCH] MPC8xx PC... |
623 624 |
{ u32 reg, clocks, psst, psl, psht; |
99121c0da powerpc: 8xx: fix... |
625 |
if (!ns) { |
de957c89b [PATCH] MPC8xx PC... |
626 627 628 629 630 631 |
/* * We get called with IO maps setup to 0ns * if not specified by the user. * They should be 255ns. */ |
99121c0da powerpc: 8xx: fix... |
632 |
if (is_io) |
de957c89b [PATCH] MPC8xx PC... |
633 634 |
ns = 255; else |
99121c0da powerpc: 8xx: fix... |
635 |
ns = 100; /* fast memory if 0 */ |
de957c89b [PATCH] MPC8xx PC... |
636 637 638 639 640 641 642 643 644 |
} /* * In PSST, PSL, PSHT fields we tell the controller * timing parameters in CLKOUT clock cycles. * CLKOUT is the same as GCLK2_50. */ /* how we want to adjust the timing - in percent */ |
99121c0da powerpc: 8xx: fix... |
645 |
#define ADJ 180 /* 80 % longer accesstime - to be sure */ |
de957c89b [PATCH] MPC8xx PC... |
646 |
|
80128ff79 [POWERPC] 8xx: mp... |
647 |
clocks = ((bus_freq / 1000) * ns) / 1000; |
99121c0da powerpc: 8xx: fix... |
648 649 650 651 652 |
clocks = (clocks * ADJ) / (100 * 1000); if (clocks >= PCMCIA_BMT_LIMIT) { printk("Max access time limit reached "); clocks = PCMCIA_BMT_LIMIT - 1; |
de957c89b [PATCH] MPC8xx PC... |
653 |
} |
99121c0da powerpc: 8xx: fix... |
654 655 656 |
psst = clocks / 7; /* setup time */ psht = clocks / 7; /* hold time */ psl = (clocks * 5) / 7; /* strobe length */ |
de957c89b [PATCH] MPC8xx PC... |
657 658 |
psst += clocks - (psst + psht + psl); |
99121c0da powerpc: 8xx: fix... |
659 660 |
reg = psst << 12; reg |= psl << 7; |
de957c89b [PATCH] MPC8xx PC... |
661 662 663 664 665 666 667 668 669 670 |
reg |= psht << 16; return reg; } static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value) { int lsock = container_of(sock, struct socket_info, socket)->slot; struct socket_info *s = &socket[lsock]; unsigned int pipr, reg; |
80128ff79 [POWERPC] 8xx: mp... |
671 |
pcmconf8xx_t *pcmcia = s->pcmcia; |
de957c89b [PATCH] MPC8xx PC... |
672 |
|
80128ff79 [POWERPC] 8xx: mp... |
673 |
pipr = in_be32(&pcmcia->pcmc_pipr); |
de957c89b [PATCH] MPC8xx PC... |
674 |
|
99121c0da powerpc: 8xx: fix... |
675 676 |
*value = ((pipr & (M8XX_PCMCIA_CD1(lsock) | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0; |
de957c89b [PATCH] MPC8xx PC... |
677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 |
*value |= (pipr & M8XX_PCMCIA_WP(lsock)) ? SS_WRPROT : 0; if (s->state.flags & SS_IOCARD) *value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_STSCHG : 0; else { *value |= (pipr & M8XX_PCMCIA_RDY(lsock)) ? SS_READY : 0; *value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_BATDEAD : 0; *value |= (pipr & M8XX_PCMCIA_BVD2(lsock)) ? SS_BATWARN : 0; } if (s->state.Vcc | s->state.Vpp) *value |= SS_POWERON; /* * Voltage detection: * This driver only supports 16-Bit pc-cards. * Cardbus is not handled here. * * To determine what voltage to use we must read the VS1 and VS2 pin. * Depending on what socket type is present, * different combinations mean different things. * * Card Key Socket Key VS1 VS2 Card Vcc for CIS parse * * 5V 5V, LV* NC NC 5V only 5V (if available) * * 5V 5V, LV* GND NC 5 or 3.3V as low as possible * * 5V 5V, LV* GND GND 5, 3.3, x.xV as low as possible * * LV* 5V - - shall not fit into socket * * LV* LV* GND NC 3.3V only 3.3V * * LV* LV* NC GND x.xV x.xV (if avail.) * * LV* LV* GND GND 3.3 or x.xV as low as possible * * *LV means Low Voltage * * * That gives us the following table: * * Socket VS1 VS2 Voltage * * 5V NC NC 5V * 5V NC GND none (should not be possible) * 5V GND NC >= 3.3V * 5V GND GND >= x.xV * * LV NC NC 5V (if available) * LV NC GND x.xV (if available) * LV GND NC 3.3V * LV GND GND >= x.xV * * So, how do I determine if I have a 5V or a LV * socket on my board? Look at the socket! * * * Socket with 5V key: * ++--------------------------------------------+ * || | * || || * || || * | | * +---------------------------------------------+ * * Socket with LV key: * ++--------------------------------------------+ * || | * | || * | || * | | * +---------------------------------------------+ * * * With other words - LV only cards does not fit * into the 5V socket! */ /* read out VS1 and VS2 */ reg = (pipr & M8XX_PCMCIA_VS_MASK(lsock)) |
99121c0da powerpc: 8xx: fix... |
760 |
>> M8XX_PCMCIA_VS_SHIFT(lsock); |
de957c89b [PATCH] MPC8xx PC... |
761 |
|
99121c0da powerpc: 8xx: fix... |
762 763 |
if (socket_get(lsock) == PCMCIA_SOCKET_KEY_LV) { switch (reg) { |
de957c89b [PATCH] MPC8xx PC... |
764 765 |
case 1: *value |= SS_3VCARD; |
99121c0da powerpc: 8xx: fix... |
766 |
break; /* GND, NC - 3.3V only */ |
de957c89b [PATCH] MPC8xx PC... |
767 768 |
case 2: *value |= SS_XVCARD; |
99121c0da powerpc: 8xx: fix... |
769 |
break; /* NC. GND - x.xV only */ |
de957c89b [PATCH] MPC8xx PC... |
770 771 |
}; } |
c9f50dddd pcmcia: use dynam... |
772 773 |
pr_debug("m8xx_pcmcia: GetStatus(%d) = %#2.2x ", lsock, *value); |
de957c89b [PATCH] MPC8xx PC... |
774 775 |
return 0; } |
99121c0da powerpc: 8xx: fix... |
776 |
static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t * state) |
de957c89b [PATCH] MPC8xx PC... |
777 778 779 780 781 782 |
{ int lsock = container_of(sock, struct socket_info, socket)->slot; struct socket_info *s = &socket[lsock]; struct event_table *e; unsigned int reg; unsigned long flags; |
80128ff79 [POWERPC] 8xx: mp... |
783 |
pcmconf8xx_t *pcmcia = socket[0].pcmcia; |
de957c89b [PATCH] MPC8xx PC... |
784 |
|
c9f50dddd pcmcia: use dynam... |
785 |
pr_debug("m8xx_pcmcia: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " |
99121c0da powerpc: 8xx: fix... |
786 787 788 |
"io_irq %d, csc_mask %#2.2x) ", lsock, state->flags, state->Vcc, state->Vpp, state->io_irq, state->csc_mask); |
de957c89b [PATCH] MPC8xx PC... |
789 790 |
/* First, set voltage - bail out if invalid */ |
99121c0da powerpc: 8xx: fix... |
791 |
if (voltage_set(lsock, state->Vcc, state->Vpp)) |
de957c89b [PATCH] MPC8xx PC... |
792 793 794 |
return -EINVAL; /* Take care of reset... */ |
99121c0da powerpc: 8xx: fix... |
795 796 |
if (state->flags & SS_RESET) out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET); /* active high */ |
de957c89b [PATCH] MPC8xx PC... |
797 |
else |
99121c0da powerpc: 8xx: fix... |
798 799 |
out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXRESET); |
de957c89b [PATCH] MPC8xx PC... |
800 801 802 803 804 805 806 807 |
/* ... and output enable. */ /* The CxOE signal is connected to a 74541 on the ADS. I guess most other boards used the ADS as a reference. I tried to control the CxOE signal with SS_OUTPUT_ENA, but the reset signal seems connected via the 541. If the CxOE is left high are some signals tristated and |
f26fc4e08 drivers/pcmcia/: ... |
808 |
no pullups are present -> the cards act weird. |
de957c89b [PATCH] MPC8xx PC... |
809 |
So right now the buffers are enabled if the power is on. */ |
99121c0da powerpc: 8xx: fix... |
810 811 |
if (state->Vcc || state->Vpp) out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXOE); /* active low */ |
de957c89b [PATCH] MPC8xx PC... |
812 |
else |
99121c0da powerpc: 8xx: fix... |
813 814 |
out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXOE); |
de957c89b [PATCH] MPC8xx PC... |
815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 |
/* * We'd better turn off interrupts before * we mess with the events-table.. */ spin_lock_irqsave(&events_lock, flags); /* * Play around with the interrupt mask to be able to * give the events the generic pcmcia driver wants us to. */ e = &s->events[0]; reg = 0; |
99121c0da powerpc: 8xx: fix... |
830 |
if (state->csc_mask & SS_DETECT) { |
de957c89b [PATCH] MPC8xx PC... |
831 832 833 834 835 |
e->eventbit = SS_DETECT; reg |= e->regbit = (M8XX_PCMCIA_CD2(lsock) | M8XX_PCMCIA_CD1(lsock)); e++; } |
99121c0da powerpc: 8xx: fix... |
836 |
if (state->flags & SS_IOCARD) { |
de957c89b [PATCH] MPC8xx PC... |
837 838 839 |
/* * I/O card */ |
99121c0da powerpc: 8xx: fix... |
840 |
if (state->csc_mask & SS_STSCHG) { |
de957c89b [PATCH] MPC8xx PC... |
841 842 843 844 845 846 847 |
e->eventbit = SS_STSCHG; reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock); e++; } /* * If io_irq is non-zero we should enable irq. */ |
99121c0da powerpc: 8xx: fix... |
848 |
if (state->io_irq) { |
80128ff79 [POWERPC] 8xx: mp... |
849 |
out_be32(M8XX_PGCRX(lsock), |
99121c0da powerpc: 8xx: fix... |
850 851 |
in_be32(M8XX_PGCRX(lsock)) | mk_int_int_mask(s->hwirq) << 24); |
de957c89b [PATCH] MPC8xx PC... |
852 853 854 855 856 857 858 859 860 861 |
/* * Strange thing here: * The manual does not tell us which interrupt * the sources generate. * Anyhow, I found out that RDY_L generates IREQLVL. * * We use level triggerd interrupts, and they don't * have to be cleared in PSCR in the interrupt handler. */ reg |= M8XX_PCMCIA_RDY_L(lsock); |
99121c0da powerpc: 8xx: fix... |
862 863 864 865 |
} else out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & 0x00ffffff); } else { |
de957c89b [PATCH] MPC8xx PC... |
866 867 868 |
/* * Memory card */ |
99121c0da powerpc: 8xx: fix... |
869 |
if (state->csc_mask & SS_BATDEAD) { |
de957c89b [PATCH] MPC8xx PC... |
870 871 872 873 |
e->eventbit = SS_BATDEAD; reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock); e++; } |
99121c0da powerpc: 8xx: fix... |
874 |
if (state->csc_mask & SS_BATWARN) { |
de957c89b [PATCH] MPC8xx PC... |
875 876 877 878 879 |
e->eventbit = SS_BATWARN; reg |= e->regbit = M8XX_PCMCIA_BVD2(lsock); e++; } /* What should I trigger on - low/high,raise,fall? */ |
99121c0da powerpc: 8xx: fix... |
880 |
if (state->csc_mask & SS_READY) { |
de957c89b [PATCH] MPC8xx PC... |
881 |
e->eventbit = SS_READY; |
99121c0da powerpc: 8xx: fix... |
882 |
reg |= e->regbit = 0; //?? |
de957c89b [PATCH] MPC8xx PC... |
883 884 885 |
e++; } } |
99121c0da powerpc: 8xx: fix... |
886 |
e->regbit = 0; /* terminate list */ |
de957c89b [PATCH] MPC8xx PC... |
887 888 889 890 891 892 |
/* * Clear the status changed . * Port A and Port B share the same port. * Writing ones will clear the bits. */ |
80128ff79 [POWERPC] 8xx: mp... |
893 |
out_be32(&pcmcia->pcmc_pscr, reg); |
de957c89b [PATCH] MPC8xx PC... |
894 895 896 897 898 899 900 |
/* * Write the mask. * Port A and Port B share the same port. * Need for read-modify-write. * Ones will enable the interrupt. */ |
99121c0da powerpc: 8xx: fix... |
901 902 903 |
reg |= in_be32(&pcmcia-> pcmc_per) & (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); |
80128ff79 [POWERPC] 8xx: mp... |
904 |
out_be32(&pcmcia->pcmc_per, reg); |
de957c89b [PATCH] MPC8xx PC... |
905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 |
spin_unlock_irqrestore(&events_lock, flags); /* copy the struct and modify the copy */ s->state = *state; return 0; } static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) { int lsock = container_of(sock, struct socket_info, socket)->slot; struct socket_info *s = &socket[lsock]; struct pcmcia_win *w; unsigned int reg, winnr; |
80128ff79 [POWERPC] 8xx: mp... |
922 |
pcmconf8xx_t *pcmcia = s->pcmcia; |
de957c89b [PATCH] MPC8xx PC... |
923 924 |
#define M8XX_SIZE (io->stop - io->start + 1) #define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start) |
c9f50dddd pcmcia: use dynam... |
925 |
pr_debug("m8xx_pcmcia: SetIOMap(%d, %d, %#2.2x, %d ns, " |
5f784336d pcmcia: Fix possi... |
926 927 928 929 |
"%#4.4llx-%#4.4llx) ", lsock, io->map, io->flags, io->speed, (unsigned long long)io->start, (unsigned long long)io->stop); |
de957c89b [PATCH] MPC8xx PC... |
930 931 932 933 |
if ((io->map >= PCMCIA_IO_WIN_NO) || (io->start > 0xffff) || (io->stop > 0xffff) || (io->stop < io->start)) return -EINVAL; |
99121c0da powerpc: 8xx: fix... |
934 |
if ((reg = m8xx_get_graycode(M8XX_SIZE)) == -1) |
de957c89b [PATCH] MPC8xx PC... |
935 |
return -EINVAL; |
99121c0da powerpc: 8xx: fix... |
936 |
if (io->flags & MAP_ACTIVE) { |
de957c89b [PATCH] MPC8xx PC... |
937 |
|
c9f50dddd pcmcia: use dynam... |
938 939 |
pr_debug("m8xx_pcmcia: io->flags & MAP_ACTIVE "); |
de957c89b [PATCH] MPC8xx PC... |
940 941 |
winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO) |
99121c0da powerpc: 8xx: fix... |
942 |
+ (lsock * PCMCIA_IO_WIN_NO) + io->map; |
de957c89b [PATCH] MPC8xx PC... |
943 944 |
/* setup registers */ |
99121c0da powerpc: 8xx: fix... |
945 |
w = (void *)&pcmcia->pcmc_pbr0; |
de957c89b [PATCH] MPC8xx PC... |
946 |
w += winnr; |
99121c0da powerpc: 8xx: fix... |
947 |
out_be32(&w->or, 0); /* turn off window first */ |
de957c89b [PATCH] MPC8xx PC... |
948 949 950 |
out_be32(&w->br, M8XX_BASE); reg <<= 27; |
99121c0da powerpc: 8xx: fix... |
951 |
reg |= M8XX_PCMCIA_POR_IO | (lsock << 2); |
de957c89b [PATCH] MPC8xx PC... |
952 |
|
80128ff79 [POWERPC] 8xx: mp... |
953 |
reg |= m8xx_get_speed(io->speed, 1, s->bus_freq); |
de957c89b [PATCH] MPC8xx PC... |
954 |
|
99121c0da powerpc: 8xx: fix... |
955 |
if (io->flags & MAP_WRPROT) |
de957c89b [PATCH] MPC8xx PC... |
956 |
reg |= M8XX_PCMCIA_POR_WRPROT; |
99121c0da powerpc: 8xx: fix... |
957 958 |
/*if(io->flags & (MAP_16BIT | MAP_AUTOSZ)) */ if (io->flags & MAP_16BIT) |
de957c89b [PATCH] MPC8xx PC... |
959 |
reg |= M8XX_PCMCIA_POR_16BIT; |
99121c0da powerpc: 8xx: fix... |
960 |
if (io->flags & MAP_ACTIVE) |
de957c89b [PATCH] MPC8xx PC... |
961 962 963 |
reg |= M8XX_PCMCIA_POR_VALID; out_be32(&w->or, reg); |
c9f50dddd pcmcia: use dynam... |
964 965 966 |
pr_debug("m8xx_pcmcia: Socket %u: Mapped io window %u at " "%#8.8x, OR = %#8.8x. ", lsock, io->map, w->br, w->or); |
de957c89b [PATCH] MPC8xx PC... |
967 968 969 |
} else { /* shutdown IO window */ winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO) |
99121c0da powerpc: 8xx: fix... |
970 |
+ (lsock * PCMCIA_IO_WIN_NO) + io->map; |
de957c89b [PATCH] MPC8xx PC... |
971 972 |
/* setup registers */ |
99121c0da powerpc: 8xx: fix... |
973 |
w = (void *)&pcmcia->pcmc_pbr0; |
de957c89b [PATCH] MPC8xx PC... |
974 |
w += winnr; |
99121c0da powerpc: 8xx: fix... |
975 976 |
out_be32(&w->or, 0); /* turn off window */ out_be32(&w->br, 0); /* turn off base address */ |
de957c89b [PATCH] MPC8xx PC... |
977 |
|
c9f50dddd pcmcia: use dynam... |
978 979 980 |
pr_debug("m8xx_pcmcia: Socket %u: Unmapped io window %u at " "%#8.8x, OR = %#8.8x. ", lsock, io->map, w->br, w->or); |
de957c89b [PATCH] MPC8xx PC... |
981 982 983 984 |
} /* copy the struct and modify the copy */ s->io_win[io->map] = *io; |
99121c0da powerpc: 8xx: fix... |
985 |
s->io_win[io->map].flags &= (MAP_WRPROT | MAP_16BIT | MAP_ACTIVE); |
c9f50dddd pcmcia: use dynam... |
986 987 |
pr_debug("m8xx_pcmcia: SetIOMap exit "); |
de957c89b [PATCH] MPC8xx PC... |
988 989 990 |
return 0; } |
99121c0da powerpc: 8xx: fix... |
991 992 |
static int m8xx_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem) |
de957c89b [PATCH] MPC8xx PC... |
993 994 995 996 997 998 |
{ int lsock = container_of(sock, struct socket_info, socket)->slot; struct socket_info *s = &socket[lsock]; struct pcmcia_win *w; struct pccard_mem_map *old; unsigned int reg, winnr; |
80128ff79 [POWERPC] 8xx: mp... |
999 |
pcmconf8xx_t *pcmcia = s->pcmcia; |
de957c89b [PATCH] MPC8xx PC... |
1000 |
|
c9f50dddd pcmcia: use dynam... |
1001 |
pr_debug("m8xx_pcmcia: SetMemMap(%d, %d, %#2.2x, %d ns, " |
5f784336d pcmcia: Fix possi... |
1002 1003 1004 1005 |
"%#5.5llx, %#5.5x) ", lsock, mem->map, mem->flags, mem->speed, (unsigned long long)mem->static_start, mem->card_start); |
de957c89b [PATCH] MPC8xx PC... |
1006 1007 |
if ((mem->map >= PCMCIA_MEM_WIN_NO) |
99121c0da powerpc: 8xx: fix... |
1008 |
// || ((mem->s) >= PCMCIA_MEM_WIN_SIZE) |
de957c89b [PATCH] MPC8xx PC... |
1009 |
|| (mem->card_start >= 0x04000000) |
99121c0da powerpc: 8xx: fix... |
1010 1011 |
|| (mem->static_start & 0xfff) /* 4KByte resolution */ ||(mem->card_start & 0xfff)) |
de957c89b [PATCH] MPC8xx PC... |
1012 |
return -EINVAL; |
99121c0da powerpc: 8xx: fix... |
1013 1014 1015 |
if ((reg = m8xx_get_graycode(PCMCIA_MEM_WIN_SIZE)) == -1) { printk("Cannot set size to 0x%08x. ", PCMCIA_MEM_WIN_SIZE); |
de957c89b [PATCH] MPC8xx PC... |
1016 1017 1018 1019 1020 1021 1022 |
return -EINVAL; } reg <<= 27; winnr = (lsock * PCMCIA_MEM_WIN_NO) + mem->map; /* Setup the window in the pcmcia controller */ |
99121c0da powerpc: 8xx: fix... |
1023 |
w = (void *)&pcmcia->pcmc_pbr0; |
de957c89b [PATCH] MPC8xx PC... |
1024 1025 1026 |
w += winnr; reg |= lsock << 2; |
80128ff79 [POWERPC] 8xx: mp... |
1027 |
reg |= m8xx_get_speed(mem->speed, 0, s->bus_freq); |
de957c89b [PATCH] MPC8xx PC... |
1028 |
|
99121c0da powerpc: 8xx: fix... |
1029 1030 |
if (mem->flags & MAP_ATTRIB) reg |= M8XX_PCMCIA_POR_ATTRMEM; |
de957c89b [PATCH] MPC8xx PC... |
1031 |
|
99121c0da powerpc: 8xx: fix... |
1032 |
if (mem->flags & MAP_WRPROT) |
de957c89b [PATCH] MPC8xx PC... |
1033 |
reg |= M8XX_PCMCIA_POR_WRPROT; |
99121c0da powerpc: 8xx: fix... |
1034 |
if (mem->flags & MAP_16BIT) |
de957c89b [PATCH] MPC8xx PC... |
1035 |
reg |= M8XX_PCMCIA_POR_16BIT; |
99121c0da powerpc: 8xx: fix... |
1036 |
if (mem->flags & MAP_ACTIVE) |
de957c89b [PATCH] MPC8xx PC... |
1037 1038 1039 |
reg |= M8XX_PCMCIA_POR_VALID; out_be32(&w->or, reg); |
c9f50dddd pcmcia: use dynam... |
1040 |
pr_debug("m8xx_pcmcia: Socket %u: Mapped memory window %u at %#8.8x, " |
99121c0da powerpc: 8xx: fix... |
1041 1042 |
"OR = %#8.8x. ", lsock, mem->map, w->br, w->or); |
de957c89b [PATCH] MPC8xx PC... |
1043 |
|
99121c0da powerpc: 8xx: fix... |
1044 |
if (mem->flags & MAP_ACTIVE) { |
de957c89b [PATCH] MPC8xx PC... |
1045 1046 |
/* get the new base address */ mem->static_start = PCMCIA_MEM_WIN_BASE + |
99121c0da powerpc: 8xx: fix... |
1047 1048 |
(PCMCIA_MEM_WIN_SIZE * winnr) + mem->card_start; |
de957c89b [PATCH] MPC8xx PC... |
1049 |
} |
c9f50dddd pcmcia: use dynam... |
1050 |
pr_debug("m8xx_pcmcia: SetMemMap(%d, %d, %#2.2x, %d ns, " |
5f784336d pcmcia: Fix possi... |
1051 1052 1053 1054 |
"%#5.5llx, %#5.5x) ", lsock, mem->map, mem->flags, mem->speed, (unsigned long long)mem->static_start, mem->card_start); |
de957c89b [PATCH] MPC8xx PC... |
1055 1056 1057 1058 1059 1060 |
/* copy the struct and modify the copy */ old = &s->mem_win[mem->map]; *old = *mem; |
99121c0da powerpc: 8xx: fix... |
1061 |
old->flags &= (MAP_ATTRIB | MAP_WRPROT | MAP_16BIT | MAP_ACTIVE); |
de957c89b [PATCH] MPC8xx PC... |
1062 1063 1064 1065 1066 1067 1068 1069 1070 |
return 0; } static int m8xx_sock_init(struct pcmcia_socket *sock) { int i; pccard_io_map io = { 0, 0, 0, 0, 1 }; pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 }; |
c9f50dddd pcmcia: use dynam... |
1071 1072 |
pr_debug("m8xx_pcmcia: sock_init(%d) ", s); |
de957c89b [PATCH] MPC8xx PC... |
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 |
m8xx_set_socket(sock, &dead_socket); for (i = 0; i < PCMCIA_IO_WIN_NO; i++) { io.map = i; m8xx_set_io_map(sock, &io); } for (i = 0; i < PCMCIA_MEM_WIN_NO; i++) { mem.map = i; m8xx_set_mem_map(sock, &mem); } return 0; } |
80128ff79 [POWERPC] 8xx: mp... |
1087 |
static int m8xx_sock_suspend(struct pcmcia_socket *sock) |
de957c89b [PATCH] MPC8xx PC... |
1088 1089 1090 1091 1092 |
{ return m8xx_set_socket(sock, &dead_socket); } static struct pccard_operations m8xx_services = { |
99121c0da powerpc: 8xx: fix... |
1093 |
.init = m8xx_sock_init, |
80128ff79 [POWERPC] 8xx: mp... |
1094 |
.suspend = m8xx_sock_suspend, |
de957c89b [PATCH] MPC8xx PC... |
1095 |
.get_status = m8xx_get_status, |
de957c89b [PATCH] MPC8xx PC... |
1096 1097 1098 1099 |
.set_socket = m8xx_set_socket, .set_io_map = m8xx_set_io_map, .set_mem_map = m8xx_set_mem_map, }; |
1c48a5c93 dt: Eliminate of_... |
1100 |
static int __init m8xx_probe(struct platform_device *ofdev) |
de957c89b [PATCH] MPC8xx PC... |
1101 1102 |
{ struct pcmcia_win *w; |
80128ff79 [POWERPC] 8xx: mp... |
1103 1104 1105 |
unsigned int i, m, hwirq; pcmconf8xx_t *pcmcia; int status; |
2005ce352 of/pcmcia: m8xx_p... |
1106 |
struct device_node *np = ofdev->dev.of_node; |
de957c89b [PATCH] MPC8xx PC... |
1107 1108 1109 |
pcmcia_info("%s ", version); |
80128ff79 [POWERPC] 8xx: mp... |
1110 |
pcmcia = of_iomap(np, 0); |
99121c0da powerpc: 8xx: fix... |
1111 |
if (pcmcia == NULL) |
80128ff79 [POWERPC] 8xx: mp... |
1112 1113 1114 |
return -EINVAL; pcmcia_schlvl = irq_of_parse_and_map(np, 0); |
99121c0da powerpc: 8xx: fix... |
1115 |
hwirq = irq_map[pcmcia_schlvl].hwirq; |
5a1c3e1aa drivers/pcmcia: A... |
1116 1117 |
if (pcmcia_schlvl < 0) { iounmap(pcmcia); |
80128ff79 [POWERPC] 8xx: mp... |
1118 |
return -EINVAL; |
5a1c3e1aa drivers/pcmcia: A... |
1119 |
} |
80128ff79 [POWERPC] 8xx: mp... |
1120 1121 1122 |
m8xx_pgcrx[0] = &pcmcia->pcmc_pgcra; m8xx_pgcrx[1] = &pcmcia->pcmc_pgcrb; |
de957c89b [PATCH] MPC8xx PC... |
1123 |
pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG |
80128ff79 [POWERPC] 8xx: mp... |
1124 1125 |
" with IRQ %u (%d). ", pcmcia_schlvl, hwirq); |
de957c89b [PATCH] MPC8xx PC... |
1126 1127 |
/* Configure Status change interrupt */ |
99121c0da powerpc: 8xx: fix... |
1128 1129 |
if (request_irq(pcmcia_schlvl, m8xx_interrupt, IRQF_SHARED, driver_name, socket)) { |
de957c89b [PATCH] MPC8xx PC... |
1130 1131 1132 |
pcmcia_error("Cannot allocate IRQ %u for SCHLVL! ", pcmcia_schlvl); |
5a1c3e1aa drivers/pcmcia: A... |
1133 |
iounmap(pcmcia); |
de957c89b [PATCH] MPC8xx PC... |
1134 1135 |
return -1; } |
99121c0da powerpc: 8xx: fix... |
1136 |
w = (void *)&pcmcia->pcmc_pbr0; |
de957c89b [PATCH] MPC8xx PC... |
1137 |
|
99121c0da powerpc: 8xx: fix... |
1138 |
out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); |
80128ff79 [POWERPC] 8xx: mp... |
1139 |
clrbits32(&pcmcia->pcmc_per, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); |
de957c89b [PATCH] MPC8xx PC... |
1140 |
|
80128ff79 [POWERPC] 8xx: mp... |
1141 |
/* connect interrupt and disable CxOE */ |
de957c89b [PATCH] MPC8xx PC... |
1142 |
|
99121c0da powerpc: 8xx: fix... |
1143 1144 1145 1146 |
out_be32(M8XX_PGCRX(0), M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16)); out_be32(M8XX_PGCRX(1), M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16)); |
de957c89b [PATCH] MPC8xx PC... |
1147 |
|
b595076a1 tree-wide: fix co... |
1148 |
/* initialize the fixed memory windows */ |
de957c89b [PATCH] MPC8xx PC... |
1149 |
|
99121c0da powerpc: 8xx: fix... |
1150 |
for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { |
80128ff79 [POWERPC] 8xx: mp... |
1151 |
for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) { |
de957c89b [PATCH] MPC8xx PC... |
1152 |
out_be32(&w->br, PCMCIA_MEM_WIN_BASE + |
99121c0da powerpc: 8xx: fix... |
1153 1154 |
(PCMCIA_MEM_WIN_SIZE * (m + i * PCMCIA_MEM_WIN_NO))); |
de957c89b [PATCH] MPC8xx PC... |
1155 |
|
99121c0da powerpc: 8xx: fix... |
1156 |
out_be32(&w->or, 0); /* set to not valid */ |
de957c89b [PATCH] MPC8xx PC... |
1157 1158 1159 1160 |
w++; } } |
80128ff79 [POWERPC] 8xx: mp... |
1161 |
/* turn off voltage */ |
de957c89b [PATCH] MPC8xx PC... |
1162 1163 |
voltage_set(0, 0, 0); voltage_set(1, 0, 0); |
80128ff79 [POWERPC] 8xx: mp... |
1164 |
/* Enable external hardware */ |
de957c89b [PATCH] MPC8xx PC... |
1165 1166 |
hardware_enable(0); hardware_enable(1); |
99121c0da powerpc: 8xx: fix... |
1167 |
for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { |
de957c89b [PATCH] MPC8xx PC... |
1168 1169 |
socket[i].slot = i; socket[i].socket.owner = THIS_MODULE; |
99121c0da powerpc: 8xx: fix... |
1170 1171 |
socket[i].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP; |
de957c89b [PATCH] MPC8xx PC... |
1172 1173 1174 |
socket[i].socket.irq_mask = 0x000; socket[i].socket.map_size = 0x1000; socket[i].socket.io_offset = 0; |
80128ff79 [POWERPC] 8xx: mp... |
1175 |
socket[i].socket.pci_irq = pcmcia_schlvl; |
de957c89b [PATCH] MPC8xx PC... |
1176 |
socket[i].socket.ops = &m8xx_services; |
4e8804ff6 pcmcia: m8xx_pcmc... |
1177 |
socket[i].socket.resource_ops = &pccard_iodyn_ops; |
de957c89b [PATCH] MPC8xx PC... |
1178 |
socket[i].socket.cb_dev = NULL; |
80128ff79 [POWERPC] 8xx: mp... |
1179 1180 1181 1182 |
socket[i].socket.dev.parent = &ofdev->dev; socket[i].pcmcia = pcmcia; socket[i].bus_freq = ppc_proc_freq; socket[i].hwirq = hwirq; |
de957c89b [PATCH] MPC8xx PC... |
1183 |
} |
80128ff79 [POWERPC] 8xx: mp... |
1184 1185 1186 1187 1188 1189 |
for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { status = pcmcia_register_socket(&socket[i].socket); if (status < 0) pcmcia_error("Socket register failed "); } |
de957c89b [PATCH] MPC8xx PC... |
1190 1191 1192 |
return 0; } |
2dc115813 of/device: Replac... |
1193 |
static int m8xx_remove(struct platform_device *ofdev) |
de957c89b [PATCH] MPC8xx PC... |
1194 |
{ |
80128ff79 [POWERPC] 8xx: mp... |
1195 1196 1197 1198 1199 |
u32 m, i; struct pcmcia_win *w; pcmconf8xx_t *pcmcia = socket[0].pcmcia; for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { |
99121c0da powerpc: 8xx: fix... |
1200 |
w = (void *)&pcmcia->pcmc_pbr0; |
80128ff79 [POWERPC] 8xx: mp... |
1201 1202 1203 |
out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(i)); out_be32(&pcmcia->pcmc_per, |
99121c0da powerpc: 8xx: fix... |
1204 |
in_be32(&pcmcia->pcmc_per) & ~M8XX_PCMCIA_MASK(i)); |
de957c89b [PATCH] MPC8xx PC... |
1205 |
|
80128ff79 [POWERPC] 8xx: mp... |
1206 1207 1208 1209 1210 |
/* turn off interrupt and disable CxOE */ out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE); /* turn off memory windows */ for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) { |
99121c0da powerpc: 8xx: fix... |
1211 |
out_be32(&w->or, 0); /* set to not valid */ |
80128ff79 [POWERPC] 8xx: mp... |
1212 1213 1214 1215 1216 1217 1218 1219 1220 |
w++; } /* turn off voltage */ voltage_set(i, 0, 0); /* disable external hardware */ hardware_disable(i); } |
de957c89b [PATCH] MPC8xx PC... |
1221 1222 |
for (i = 0; i < PCMCIA_SOCKETS_NO; i++) pcmcia_unregister_socket(&socket[i].socket); |
5a1c3e1aa drivers/pcmcia: A... |
1223 |
iounmap(pcmcia); |
de957c89b [PATCH] MPC8xx PC... |
1224 |
|
80128ff79 [POWERPC] 8xx: mp... |
1225 |
free_irq(pcmcia_schlvl, NULL); |
de957c89b [PATCH] MPC8xx PC... |
1226 |
|
80128ff79 [POWERPC] 8xx: mp... |
1227 1228 |
return 0; } |
63c9a8b30 pcmcia: make Open... |
1229 |
static const struct of_device_id m8xx_pcmcia_match[] = { |
80128ff79 [POWERPC] 8xx: mp... |
1230 |
{ |
99121c0da powerpc: 8xx: fix... |
1231 1232 1233 |
.type = "pcmcia", .compatible = "fsl,pq-pcmcia", }, |
80128ff79 [POWERPC] 8xx: mp... |
1234 1235 1236 1237 |
{}, }; MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match); |
1c48a5c93 dt: Eliminate of_... |
1238 |
static struct platform_driver m8xx_pcmcia_driver = { |
4018294b5 of: Remove duplic... |
1239 1240 1241 |
.driver = { .name = driver_name, .owner = THIS_MODULE, |
2005ce352 of/pcmcia: m8xx_p... |
1242 |
.of_match_table = m8xx_pcmcia_match, |
4018294b5 of: Remove duplic... |
1243 |
}, |
99121c0da powerpc: 8xx: fix... |
1244 1245 |
.probe = m8xx_probe, .remove = m8xx_remove, |
80128ff79 [POWERPC] 8xx: mp... |
1246 1247 1248 1249 |
}; static int __init m8xx_init(void) { |
1c48a5c93 dt: Eliminate of_... |
1250 |
return platform_driver_register(&m8xx_pcmcia_driver); |
80128ff79 [POWERPC] 8xx: mp... |
1251 1252 1253 1254 |
} static void __exit m8xx_exit(void) { |
1c48a5c93 dt: Eliminate of_... |
1255 |
platform_driver_unregister(&m8xx_pcmcia_driver); |
de957c89b [PATCH] MPC8xx PC... |
1256 1257 1258 1259 |
} module_init(m8xx_init); module_exit(m8xx_exit); |