blob: 18c0d8d1ddf779dbba8f09d7b898b7b687bd0a74 [file] [log] [blame]
Marcelo Tosattide957c82005-10-28 17:46:13 -07001/*
2 * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series.
3 *
Magnus Dammcbba0de22006-12-13 15:40:18 +09004 * (C) 1999-2000 Magnus Damm <damm@opensource.se>
Marcelo Tosattide957c82005-10-28 17:46:13 -07005 * (C) 2001-2002 Montavista Software, Inc.
6 * <mlocke@mvista.com>
7 *
8 * Support for two slots by Cyclades Corporation
9 * <oliver.kurth@cyclades.de>
10 * Further fixes, v2.6 kernel port
11 * <marcelo.tosatti@cyclades.com>
Vitaly Bordug1371d3b2005-12-08 13:56:12 -020012 *
Vitaly Bordug80128ff2007-07-09 11:37:35 -070013 * Some fixes, additions (C) 2005-2007 Montavista Software, Inc.
Vitaly Bordug1371d3b2005-12-08 13:56:12 -020014 * <vbordug@ru.mvista.com>
Marcelo Tosattide957c82005-10-28 17:46:13 -070015 *
16 * "The ExCA standard specifies that socket controllers should provide
17 * two IO and five memory windows per socket, which can be independently
18 * configured and positioned in the host address space and mapped to
19 * arbitrary segments of card address space. " - David A Hinds. 1999
20 *
21 * This controller does _not_ meet the ExCA standard.
22 *
23 * m8xx pcmcia controller brief info:
24 * + 8 windows (attrib, mem, i/o)
25 * + up to two slots (SLOT_A and SLOT_B)
26 * + inputpins, outputpins, event and mask registers.
27 * - no offset register. sigh.
28 *
29 * Because of the lacking offset register we must map the whole card.
30 * We assign each memory window PCMCIA_MEM_WIN_SIZE address space.
31 * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO
32 * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE.
33 * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE.
34 * They are maximum 64KByte each...
35 */
36
37#include <linux/module.h>
38#include <linux/init.h>
39#include <linux/types.h>
40#include <linux/fcntl.h>
41#include <linux/string.h>
42
Marcelo Tosattide957c82005-10-28 17:46:13 -070043#include <linux/kernel.h>
44#include <linux/errno.h>
Marcelo Tosattide957c82005-10-28 17:46:13 -070045#include <linux/timer.h>
46#include <linux/ioport.h>
47#include <linux/delay.h>
48#include <linux/interrupt.h>
Vitaly Bordug80128ff2007-07-09 11:37:35 -070049#include <linux/fsl_devices.h>
Jiri Slaby1977f032007-10-18 23:40:25 -070050#include <linux/bitops.h>
Stephen Rothwellad19dbd2008-05-23 16:31:08 +100051#include <linux/of_device.h>
52#include <linux/of_platform.h>
Marcelo Tosattide957c82005-10-28 17:46:13 -070053
Vitaly Bordug80128ff2007-07-09 11:37:35 -070054#include <asm/io.h>
Vitaly Bordug80128ff2007-07-09 11:37:35 -070055#include <asm/time.h>
Marcelo Tosattide957c82005-10-28 17:46:13 -070056#include <asm/mpc8xx.h>
57#include <asm/8xx_immap.h>
58#include <asm/irq.h>
Vitaly Bordug80128ff2007-07-09 11:37:35 -070059#include <asm/fs_pd.h>
Marcelo Tosattide957c82005-10-28 17:46:13 -070060
Marcelo Tosattide957c82005-10-28 17:46:13 -070061#include <pcmcia/ss.h>
62
Marcelo Tosattide957c82005-10-28 17:46:13 -070063#define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args)
64#define pcmcia_error(args...) printk(KERN_ERR "m8xx_pcmcia: "args)
65
66static const char *version = "Version 0.06, Aug 2005";
67MODULE_LICENSE("Dual MPL/GPL");
68
69#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B)
70
Marcelo Tosattide957c82005-10-28 17:46:13 -070071/* The ADS board use SLOT_A */
72#ifdef CONFIG_ADS
73#define CONFIG_PCMCIA_SLOT_A
74#define CONFIG_BD_IS_MHZ
75#endif
76
77/* The FADS series are a mess */
78#ifdef CONFIG_FADS
79#if defined(CONFIG_MPC860T) || defined(CONFIG_MPC860) || defined(CONFIG_MPC821)
80#define CONFIG_PCMCIA_SLOT_A
81#else
82#define CONFIG_PCMCIA_SLOT_B
83#endif
84#endif
85
Vitaly Bordug1371d3b2005-12-08 13:56:12 -020086#if defined(CONFIG_MPC885ADS)
87#define CONFIG_PCMCIA_SLOT_A
88#define PCMCIA_GLITCHY_CD
89#endif
90
Marcelo Tosattide957c82005-10-28 17:46:13 -070091/* Cyclades ACS uses both slots */
92#ifdef CONFIG_PRxK
93#define CONFIG_PCMCIA_SLOT_A
94#define CONFIG_PCMCIA_SLOT_B
95#endif
96
Vitaly Bordug99121c02007-07-17 04:03:37 -070097#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */
Marcelo Tosattide957c82005-10-28 17:46:13 -070098
99#if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B)
100
101#define PCMCIA_SOCKETS_NO 2
102/* We have only 8 windows, dualsocket support will be limited. */
103#define PCMCIA_MEM_WIN_NO 2
104#define PCMCIA_IO_WIN_NO 2
105#define PCMCIA_SLOT_MSG "SLOT_A and SLOT_B"
106
107#elif defined(CONFIG_PCMCIA_SLOT_A) || defined(CONFIG_PCMCIA_SLOT_B)
108
109#define PCMCIA_SOCKETS_NO 1
110/* full support for one slot */
111#define PCMCIA_MEM_WIN_NO 5
112#define PCMCIA_IO_WIN_NO 2
113
114/* define _slot_ to be able to optimize macros */
115
116#ifdef CONFIG_PCMCIA_SLOT_A
117#define _slot_ 0
118#define PCMCIA_SLOT_MSG "SLOT_A"
119#else
120#define _slot_ 1
121#define PCMCIA_SLOT_MSG "SLOT_B"
122#endif
123
124#else
125#error m8xx_pcmcia: Bad configuration!
126#endif
127
128/* ------------------------------------------------------------------------- */
129
Vitaly Bordug99121c02007-07-17 04:03:37 -0700130#define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0 */
131#define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte */
132#define PCMCIA_IO_WIN_BASE _IO_BASE /* base address for io window 0 */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700133/* ------------------------------------------------------------------------- */
134
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700135static int pcmcia_schlvl;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700136
Ingo Molnar34af9462006-06-27 02:53:55 -0700137static DEFINE_SPINLOCK(events_lock);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700138
Marcelo Tosattide957c82005-10-28 17:46:13 -0700139#define PCMCIA_SOCKET_KEY_5V 1
140#define PCMCIA_SOCKET_KEY_LV 2
141
142/* look up table for pgcrx registers */
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700143static u32 *m8xx_pgcrx[2];
Marcelo Tosattide957c82005-10-28 17:46:13 -0700144
145/*
146 * This structure is used to address each window in the PCMCIA controller.
147 *
148 * Keep in mind that we assume that pcmcia_win[n+1] is mapped directly
149 * after pcmcia_win[n]...
150 */
151
152struct pcmcia_win {
Vitaly Bordug99121c02007-07-17 04:03:37 -0700153 u32 br;
154 u32 or;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700155};
156
157/*
158 * For some reason the hardware guys decided to make both slots share
159 * some registers.
160 *
161 * Could someone invent object oriented hardware ?
162 *
163 * The macros are used to get the right bit from the registers.
164 * SLOT_A : slot = 0
165 * SLOT_B : slot = 1
166 */
167
168#define M8XX_PCMCIA_VS1(slot) (0x80000000 >> (slot << 4))
169#define M8XX_PCMCIA_VS2(slot) (0x40000000 >> (slot << 4))
170#define M8XX_PCMCIA_VS_MASK(slot) (0xc0000000 >> (slot << 4))
171#define M8XX_PCMCIA_VS_SHIFT(slot) (30 - (slot << 4))
172
173#define M8XX_PCMCIA_WP(slot) (0x20000000 >> (slot << 4))
174#define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4))
175#define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4))
176#define M8XX_PCMCIA_BVD2(slot) (0x04000000 >> (slot << 4))
177#define M8XX_PCMCIA_BVD1(slot) (0x02000000 >> (slot << 4))
178#define M8XX_PCMCIA_RDY(slot) (0x01000000 >> (slot << 4))
179#define M8XX_PCMCIA_RDY_L(slot) (0x00800000 >> (slot << 4))
180#define M8XX_PCMCIA_RDY_H(slot) (0x00400000 >> (slot << 4))
181#define M8XX_PCMCIA_RDY_R(slot) (0x00200000 >> (slot << 4))
182#define M8XX_PCMCIA_RDY_F(slot) (0x00100000 >> (slot << 4))
183#define M8XX_PCMCIA_MASK(slot) (0xFFFF0000 >> (slot << 4))
184
185#define M8XX_PCMCIA_POR_VALID 0x00000001
186#define M8XX_PCMCIA_POR_WRPROT 0x00000002
187#define M8XX_PCMCIA_POR_ATTRMEM 0x00000010
188#define M8XX_PCMCIA_POR_IO 0x00000018
189#define M8XX_PCMCIA_POR_16BIT 0x00000040
190
191#define M8XX_PGCRX(slot) m8xx_pgcrx[slot]
192
193#define M8XX_PGCRX_CXOE 0x00000080
194#define M8XX_PGCRX_CXRESET 0x00000040
195
196/* we keep one lookup table per socket to check flags */
197
Vitaly Bordug99121c02007-07-17 04:03:37 -0700198#define PCMCIA_EVENTS_MAX 5 /* 4 max at a time + termination */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700199
200struct event_table {
201 u32 regbit;
202 u32 eventbit;
203};
204
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700205static const char driver_name[] = "m8xx-pcmcia";
206
Marcelo Tosattide957c82005-10-28 17:46:13 -0700207struct socket_info {
Vitaly Bordug99121c02007-07-17 04:03:37 -0700208 void (*handler) (void *info, u32 events);
209 void *info;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700210
211 u32 slot;
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700212 pcmconf8xx_t *pcmcia;
213 u32 bus_freq;
214 int hwirq;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700215
216 socket_state_t state;
217 struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO];
Vitaly Bordug99121c02007-07-17 04:03:37 -0700218 struct pccard_io_map io_win[PCMCIA_IO_WIN_NO];
Marcelo Tosattide957c82005-10-28 17:46:13 -0700219 struct event_table events[PCMCIA_EVENTS_MAX];
220 struct pcmcia_socket socket;
221};
222
223static struct socket_info socket[PCMCIA_SOCKETS_NO];
224
225/*
226 * Search this table to see if the windowsize is
227 * supported...
228 */
229
230#define M8XX_SIZES_NO 32
231
Vitaly Bordug99121c02007-07-17 04:03:37 -0700232static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] = {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700233 0x00000001, 0x00000002, 0x00000008, 0x00000004,
234 0x00000080, 0x00000040, 0x00000010, 0x00000020,
235 0x00008000, 0x00004000, 0x00001000, 0x00002000,
236 0x00000100, 0x00000200, 0x00000800, 0x00000400,
237
238 0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff,
239 0x01000000, 0x02000000, 0xffffffff, 0x04000000,
240 0x00010000, 0x00020000, 0x00080000, 0x00040000,
241 0x00800000, 0x00400000, 0x00100000, 0x00200000
242};
243
244/* ------------------------------------------------------------------------- */
245
David Howells7d12e782006-10-05 14:55:46 +0100246static irqreturn_t m8xx_interrupt(int irq, void *dev);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700247
Vitaly Bordug99121c02007-07-17 04:03:37 -0700248#define PCMCIA_BMT_LIMIT (15*4) /* Bus Monitor Timeout value */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700249
Marcelo Tosattide957c82005-10-28 17:46:13 -0700250/* FADS Boards from Motorola */
251
252#if defined(CONFIG_FADS)
253
254#define PCMCIA_BOARD_MSG "FADS"
255
256static int voltage_set(int slot, int vcc, int vpp)
257{
258 u32 reg = 0;
259
Vitaly Bordug99121c02007-07-17 04:03:37 -0700260 switch (vcc) {
261 case 0:
262 break;
263 case 33:
264 reg |= BCSR1_PCCVCC0;
265 break;
266 case 50:
267 reg |= BCSR1_PCCVCC1;
268 break;
269 default:
270 return 1;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700271 }
272
Vitaly Bordug99121c02007-07-17 04:03:37 -0700273 switch (vpp) {
274 case 0:
275 break;
276 case 33:
277 case 50:
278 if (vcc == vpp)
279 reg |= BCSR1_PCCVPP1;
280 else
Marcelo Tosattide957c82005-10-28 17:46:13 -0700281 return 1;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700282 break;
283 case 120:
284 if ((vcc == 33) || (vcc == 50))
285 reg |= BCSR1_PCCVPP0;
286 else
287 return 1;
288 default:
289 return 1;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700290 }
291
292 /* first, turn off all power */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700293 out_be32((u32 *) BCSR1,
294 in_be32((u32 *) BCSR1) & ~(BCSR1_PCCVCC_MASK |
295 BCSR1_PCCVPP_MASK));
Marcelo Tosattide957c82005-10-28 17:46:13 -0700296
297 /* enable new powersettings */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700298 out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | reg);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700299
300 return 0;
301}
302
303#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
304
305static void hardware_enable(int slot)
306{
Vitaly Bordug99121c02007-07-17 04:03:37 -0700307 out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) & ~BCSR1_PCCEN);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700308}
309
310static void hardware_disable(int slot)
311{
Vitaly Bordug99121c02007-07-17 04:03:37 -0700312 out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | BCSR1_PCCEN);
Vitaly Bordug1371d3b2005-12-08 13:56:12 -0200313}
314
315#endif
316
317/* MPC885ADS Boards */
318
319#if defined(CONFIG_MPC885ADS)
320
321#define PCMCIA_BOARD_MSG "MPC885ADS"
Vitaly Bordug1371d3b2005-12-08 13:56:12 -0200322#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
323
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700324static inline void hardware_enable(int slot)
Vitaly Bordug1371d3b2005-12-08 13:56:12 -0200325{
Vitaly Bordug99121c02007-07-17 04:03:37 -0700326 m8xx_pcmcia_ops.hw_ctrl(slot, 1);
Vitaly Bordug1371d3b2005-12-08 13:56:12 -0200327}
328
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700329static inline void hardware_disable(int slot)
Vitaly Bordug1371d3b2005-12-08 13:56:12 -0200330{
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700331 m8xx_pcmcia_ops.hw_ctrl(slot, 0);
332}
Vitaly Bordug1371d3b2005-12-08 13:56:12 -0200333
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700334static inline int voltage_set(int slot, int vcc, int vpp)
335{
336 return m8xx_pcmcia_ops.voltage_set(slot, vcc, vpp);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700337}
338
339#endif
340
Marcelo Tosattide957c82005-10-28 17:46:13 -0700341#if defined(CONFIG_PRxK)
342#include <asm/cpld.h>
343extern volatile fpga_pc_regs *fpga_pc;
344
345#define PCMCIA_BOARD_MSG "MPC855T"
346
347static int voltage_set(int slot, int vcc, int vpp)
348{
349 u8 reg = 0;
350 u8 regread;
351 cpld_regs *ccpld = get_cpld();
352
Vitaly Bordug99121c02007-07-17 04:03:37 -0700353 switch (vcc) {
354 case 0:
355 break;
356 case 33:
357 reg |= PCMCIA_VCC_33;
358 break;
359 case 50:
360 reg |= PCMCIA_VCC_50;
361 break;
362 default:
363 return 1;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700364 }
365
Vitaly Bordug99121c02007-07-17 04:03:37 -0700366 switch (vpp) {
367 case 0:
368 break;
369 case 33:
370 case 50:
371 if (vcc == vpp)
372 reg |= PCMCIA_VPP_VCC;
373 else
Marcelo Tosattide957c82005-10-28 17:46:13 -0700374 return 1;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700375 break;
376 case 120:
377 if ((vcc == 33) || (vcc == 50))
378 reg |= PCMCIA_VPP_12;
379 else
380 return 1;
381 default:
382 return 1;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700383 }
384
385 reg = reg >> (slot << 2);
386 regread = in_8(&ccpld->fpga_pc_ctl);
Vitaly Bordug99121c02007-07-17 04:03:37 -0700387 if (reg !=
388 (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700389 /* enable new powersettings */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700390 regread =
391 regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >>
392 (slot << 2));
Marcelo Tosattide957c82005-10-28 17:46:13 -0700393 out_8(&ccpld->fpga_pc_ctl, reg | regread);
394 msleep(100);
395 }
396
397 return 0;
398}
399
400#define socket_get(_slot_) PCMCIA_SOCKET_KEY_LV
Vitaly Bordug99121c02007-07-17 04:03:37 -0700401#define hardware_enable(_slot_) /* No hardware to enable */
402#define hardware_disable(_slot_) /* No hardware to disable */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700403
Vitaly Bordug99121c02007-07-17 04:03:37 -0700404#endif /* CONFIG_PRxK */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700405
Marcelo Tosattide957c82005-10-28 17:46:13 -0700406static u32 pending_events[PCMCIA_SOCKETS_NO];
Ingo Molnar34af9462006-06-27 02:53:55 -0700407static DEFINE_SPINLOCK(pending_event_lock);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700408
David Howells7d12e782006-10-05 14:55:46 +0100409static irqreturn_t m8xx_interrupt(int irq, void *dev)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700410{
411 struct socket_info *s;
412 struct event_table *e;
413 unsigned int i, events, pscr, pipr, per;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700414 pcmconf8xx_t *pcmcia = socket[0].pcmcia;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700415
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200416 pr_debug("m8xx_pcmcia: Interrupt!\n");
Marcelo Tosattide957c82005-10-28 17:46:13 -0700417 /* get interrupt sources */
418
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700419 pscr = in_be32(&pcmcia->pcmc_pscr);
420 pipr = in_be32(&pcmcia->pcmc_pipr);
421 per = in_be32(&pcmcia->pcmc_per);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700422
Vitaly Bordug99121c02007-07-17 04:03:37 -0700423 for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700424 s = &socket[i];
425 e = &s->events[0];
426 events = 0;
427
Vitaly Bordug99121c02007-07-17 04:03:37 -0700428 while (e->regbit) {
429 if (pscr & e->regbit)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700430 events |= e->eventbit;
431
Vitaly Bordug99121c02007-07-17 04:03:37 -0700432 e++;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700433 }
434
435 /*
436 * report only if both card detect signals are the same
437 * not too nice done,
438 * we depend on that CD2 is the bit to the left of CD1...
439 */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700440 if (events & SS_DETECT)
441 if (((pipr & M8XX_PCMCIA_CD2(i)) >> 1) ^
442 (pipr & M8XX_PCMCIA_CD1(i))) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700443 events &= ~SS_DETECT;
444 }
Marcelo Tosattide957c82005-10-28 17:46:13 -0700445#ifdef PCMCIA_GLITCHY_CD
446 /*
447 * I've experienced CD problems with my ADS board.
448 * We make an extra check to see if there was a
449 * real change of Card detection.
450 */
451
Vitaly Bordug99121c02007-07-17 04:03:37 -0700452 if ((events & SS_DETECT) &&
453 ((pipr &
454 (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i))) == 0) &&
455 (s->state.Vcc | s->state.Vpp)) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700456 events &= ~SS_DETECT;
457 /*printk( "CD glitch workaround - CD = 0x%08x!\n",
Vitaly Bordug99121c02007-07-17 04:03:37 -0700458 (pipr & (M8XX_PCMCIA_CD2(i)
459 | M8XX_PCMCIA_CD1(i)))); */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700460 }
461#endif
462
463 /* call the handler */
464
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200465 pr_debug("m8xx_pcmcia: slot %u: events = 0x%02x, pscr = 0x%08x, "
Vitaly Bordug99121c02007-07-17 04:03:37 -0700466 "pipr = 0x%08x\n", i, events, pscr, pipr);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700467
Vitaly Bordug99121c02007-07-17 04:03:37 -0700468 if (events) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700469 spin_lock(&pending_event_lock);
470 pending_events[i] |= events;
471 spin_unlock(&pending_event_lock);
472 /*
473 * Turn off RDY_L bits in the PER mask on
474 * CD interrupt receival.
475 *
476 * They can generate bad interrupts on the
477 * ACS4,8,16,32. - marcelo
478 */
479 per &= ~M8XX_PCMCIA_RDY_L(0);
480 per &= ~M8XX_PCMCIA_RDY_L(1);
481
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700482 out_be32(&pcmcia->pcmc_per, per);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700483
484 if (events)
485 pcmcia_parse_events(&socket[i].socket, events);
486 }
487 }
488
489 /* clear the interrupt sources */
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700490 out_be32(&pcmcia->pcmc_pscr, pscr);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700491
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200492 pr_debug("m8xx_pcmcia: Interrupt done.\n");
Marcelo Tosattide957c82005-10-28 17:46:13 -0700493
494 return IRQ_HANDLED;
495}
496
497static u32 m8xx_get_graycode(u32 size)
498{
499 u32 k;
500
Vitaly Bordug99121c02007-07-17 04:03:37 -0700501 for (k = 0; k < M8XX_SIZES_NO; k++)
502 if (m8xx_size_to_gray[k] == size)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700503 break;
504
Vitaly Bordug99121c02007-07-17 04:03:37 -0700505 if ((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
Marcelo Tosattide957c82005-10-28 17:46:13 -0700506 k = -1;
507
508 return k;
509}
510
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700511static u32 m8xx_get_speed(u32 ns, u32 is_io, u32 bus_freq)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700512{
513 u32 reg, clocks, psst, psl, psht;
514
Vitaly Bordug99121c02007-07-17 04:03:37 -0700515 if (!ns) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700516
517 /*
518 * We get called with IO maps setup to 0ns
519 * if not specified by the user.
520 * They should be 255ns.
521 */
522
Vitaly Bordug99121c02007-07-17 04:03:37 -0700523 if (is_io)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700524 ns = 255;
525 else
Vitaly Bordug99121c02007-07-17 04:03:37 -0700526 ns = 100; /* fast memory if 0 */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700527 }
528
529 /*
530 * In PSST, PSL, PSHT fields we tell the controller
531 * timing parameters in CLKOUT clock cycles.
532 * CLKOUT is the same as GCLK2_50.
533 */
534
535/* how we want to adjust the timing - in percent */
536
Vitaly Bordug99121c02007-07-17 04:03:37 -0700537#define ADJ 180 /* 80 % longer accesstime - to be sure */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700538
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700539 clocks = ((bus_freq / 1000) * ns) / 1000;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700540 clocks = (clocks * ADJ) / (100 * 1000);
541 if (clocks >= PCMCIA_BMT_LIMIT) {
542 printk("Max access time limit reached\n");
543 clocks = PCMCIA_BMT_LIMIT - 1;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700544 }
545
Vitaly Bordug99121c02007-07-17 04:03:37 -0700546 psst = clocks / 7; /* setup time */
547 psht = clocks / 7; /* hold time */
548 psl = (clocks * 5) / 7; /* strobe length */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700549
550 psst += clocks - (psst + psht + psl);
551
Vitaly Bordug99121c02007-07-17 04:03:37 -0700552 reg = psst << 12;
553 reg |= psl << 7;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700554 reg |= psht << 16;
555
556 return reg;
557}
558
559static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value)
560{
561 int lsock = container_of(sock, struct socket_info, socket)->slot;
562 struct socket_info *s = &socket[lsock];
563 unsigned int pipr, reg;
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700564 pcmconf8xx_t *pcmcia = s->pcmcia;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700565
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700566 pipr = in_be32(&pcmcia->pcmc_pipr);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700567
Vitaly Bordug99121c02007-07-17 04:03:37 -0700568 *value = ((pipr & (M8XX_PCMCIA_CD1(lsock)
569 | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700570 *value |= (pipr & M8XX_PCMCIA_WP(lsock)) ? SS_WRPROT : 0;
571
572 if (s->state.flags & SS_IOCARD)
573 *value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_STSCHG : 0;
574 else {
575 *value |= (pipr & M8XX_PCMCIA_RDY(lsock)) ? SS_READY : 0;
576 *value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_BATDEAD : 0;
577 *value |= (pipr & M8XX_PCMCIA_BVD2(lsock)) ? SS_BATWARN : 0;
578 }
579
580 if (s->state.Vcc | s->state.Vpp)
581 *value |= SS_POWERON;
582
583 /*
584 * Voltage detection:
585 * This driver only supports 16-Bit pc-cards.
586 * Cardbus is not handled here.
587 *
588 * To determine what voltage to use we must read the VS1 and VS2 pin.
589 * Depending on what socket type is present,
590 * different combinations mean different things.
591 *
592 * Card Key Socket Key VS1 VS2 Card Vcc for CIS parse
593 *
594 * 5V 5V, LV* NC NC 5V only 5V (if available)
595 *
596 * 5V 5V, LV* GND NC 5 or 3.3V as low as possible
597 *
598 * 5V 5V, LV* GND GND 5, 3.3, x.xV as low as possible
599 *
600 * LV* 5V - - shall not fit into socket
601 *
602 * LV* LV* GND NC 3.3V only 3.3V
603 *
604 * LV* LV* NC GND x.xV x.xV (if avail.)
605 *
606 * LV* LV* GND GND 3.3 or x.xV as low as possible
607 *
608 * *LV means Low Voltage
609 *
610 *
611 * That gives us the following table:
612 *
613 * Socket VS1 VS2 Voltage
614 *
615 * 5V NC NC 5V
616 * 5V NC GND none (should not be possible)
617 * 5V GND NC >= 3.3V
618 * 5V GND GND >= x.xV
619 *
620 * LV NC NC 5V (if available)
621 * LV NC GND x.xV (if available)
622 * LV GND NC 3.3V
623 * LV GND GND >= x.xV
624 *
625 * So, how do I determine if I have a 5V or a LV
626 * socket on my board? Look at the socket!
627 *
628 *
629 * Socket with 5V key:
630 * ++--------------------------------------------+
631 * || |
632 * || ||
633 * || ||
634 * | |
635 * +---------------------------------------------+
636 *
637 * Socket with LV key:
638 * ++--------------------------------------------+
639 * || |
640 * | ||
641 * | ||
642 * | |
643 * +---------------------------------------------+
644 *
645 *
646 * With other words - LV only cards does not fit
647 * into the 5V socket!
648 */
649
650 /* read out VS1 and VS2 */
651
652 reg = (pipr & M8XX_PCMCIA_VS_MASK(lsock))
Vitaly Bordug99121c02007-07-17 04:03:37 -0700653 >> M8XX_PCMCIA_VS_SHIFT(lsock);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700654
Vitaly Bordug99121c02007-07-17 04:03:37 -0700655 if (socket_get(lsock) == PCMCIA_SOCKET_KEY_LV) {
656 switch (reg) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700657 case 1:
658 *value |= SS_3VCARD;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700659 break; /* GND, NC - 3.3V only */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700660 case 2:
661 *value |= SS_XVCARD;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700662 break; /* NC. GND - x.xV only */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700663 };
664 }
665
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200666 pr_debug("m8xx_pcmcia: GetStatus(%d) = %#2.2x\n", lsock, *value);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700667 return 0;
668}
669
Vitaly Bordug99121c02007-07-17 04:03:37 -0700670static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t * state)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700671{
672 int lsock = container_of(sock, struct socket_info, socket)->slot;
673 struct socket_info *s = &socket[lsock];
674 struct event_table *e;
675 unsigned int reg;
676 unsigned long flags;
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700677 pcmconf8xx_t *pcmcia = socket[0].pcmcia;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700678
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200679 pr_debug("m8xx_pcmcia: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
Vitaly Bordug99121c02007-07-17 04:03:37 -0700680 "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,
681 state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700682
683 /* First, set voltage - bail out if invalid */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700684 if (voltage_set(lsock, state->Vcc, state->Vpp))
Marcelo Tosattide957c82005-10-28 17:46:13 -0700685 return -EINVAL;
686
687 /* Take care of reset... */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700688 if (state->flags & SS_RESET)
689 out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET); /* active high */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700690 else
Vitaly Bordug99121c02007-07-17 04:03:37 -0700691 out_be32(M8XX_PGCRX(lsock),
692 in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXRESET);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700693
694 /* ... and output enable. */
695
696 /* The CxOE signal is connected to a 74541 on the ADS.
697 I guess most other boards used the ADS as a reference.
698 I tried to control the CxOE signal with SS_OUTPUT_ENA,
699 but the reset signal seems connected via the 541.
700 If the CxOE is left high are some signals tristated and
Joe Perchesf26fc4e2008-02-03 17:26:02 +0200701 no pullups are present -> the cards act weird.
Marcelo Tosattide957c82005-10-28 17:46:13 -0700702 So right now the buffers are enabled if the power is on. */
703
Vitaly Bordug99121c02007-07-17 04:03:37 -0700704 if (state->Vcc || state->Vpp)
705 out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXOE); /* active low */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700706 else
Vitaly Bordug99121c02007-07-17 04:03:37 -0700707 out_be32(M8XX_PGCRX(lsock),
708 in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXOE);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700709
710 /*
711 * We'd better turn off interrupts before
712 * we mess with the events-table..
713 */
714
715 spin_lock_irqsave(&events_lock, flags);
716
717 /*
718 * Play around with the interrupt mask to be able to
719 * give the events the generic pcmcia driver wants us to.
720 */
721
722 e = &s->events[0];
723 reg = 0;
724
Vitaly Bordug99121c02007-07-17 04:03:37 -0700725 if (state->csc_mask & SS_DETECT) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700726 e->eventbit = SS_DETECT;
727 reg |= e->regbit = (M8XX_PCMCIA_CD2(lsock)
728 | M8XX_PCMCIA_CD1(lsock));
729 e++;
730 }
Vitaly Bordug99121c02007-07-17 04:03:37 -0700731 if (state->flags & SS_IOCARD) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700732 /*
733 * I/O card
734 */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700735 if (state->csc_mask & SS_STSCHG) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700736 e->eventbit = SS_STSCHG;
737 reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
738 e++;
739 }
740 /*
741 * If io_irq is non-zero we should enable irq.
742 */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700743 if (state->io_irq) {
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700744 out_be32(M8XX_PGCRX(lsock),
Vitaly Bordug99121c02007-07-17 04:03:37 -0700745 in_be32(M8XX_PGCRX(lsock)) |
746 mk_int_int_mask(s->hwirq) << 24);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700747 /*
748 * Strange thing here:
749 * The manual does not tell us which interrupt
750 * the sources generate.
751 * Anyhow, I found out that RDY_L generates IREQLVL.
752 *
753 * We use level triggerd interrupts, and they don't
754 * have to be cleared in PSCR in the interrupt handler.
755 */
756 reg |= M8XX_PCMCIA_RDY_L(lsock);
Vitaly Bordug99121c02007-07-17 04:03:37 -0700757 } else
758 out_be32(M8XX_PGCRX(lsock),
759 in_be32(M8XX_PGCRX(lsock)) & 0x00ffffff);
760 } else {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700761 /*
762 * Memory card
763 */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700764 if (state->csc_mask & SS_BATDEAD) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700765 e->eventbit = SS_BATDEAD;
766 reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
767 e++;
768 }
Vitaly Bordug99121c02007-07-17 04:03:37 -0700769 if (state->csc_mask & SS_BATWARN) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700770 e->eventbit = SS_BATWARN;
771 reg |= e->regbit = M8XX_PCMCIA_BVD2(lsock);
772 e++;
773 }
774 /* What should I trigger on - low/high,raise,fall? */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700775 if (state->csc_mask & SS_READY) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700776 e->eventbit = SS_READY;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700777 reg |= e->regbit = 0; //??
Marcelo Tosattide957c82005-10-28 17:46:13 -0700778 e++;
779 }
780 }
781
Vitaly Bordug99121c02007-07-17 04:03:37 -0700782 e->regbit = 0; /* terminate list */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700783
784 /*
785 * Clear the status changed .
786 * Port A and Port B share the same port.
787 * Writing ones will clear the bits.
788 */
789
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700790 out_be32(&pcmcia->pcmc_pscr, reg);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700791
792 /*
793 * Write the mask.
794 * Port A and Port B share the same port.
795 * Need for read-modify-write.
796 * Ones will enable the interrupt.
797 */
798
Vitaly Bordug99121c02007-07-17 04:03:37 -0700799 reg |=
800 in_be32(&pcmcia->
801 pcmc_per) & (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700802 out_be32(&pcmcia->pcmc_per, reg);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700803
804 spin_unlock_irqrestore(&events_lock, flags);
805
806 /* copy the struct and modify the copy */
807
808 s->state = *state;
809
810 return 0;
811}
812
813static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
814{
815 int lsock = container_of(sock, struct socket_info, socket)->slot;
816
817 struct socket_info *s = &socket[lsock];
818 struct pcmcia_win *w;
819 unsigned int reg, winnr;
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700820 pcmconf8xx_t *pcmcia = s->pcmcia;
821
Marcelo Tosattide957c82005-10-28 17:46:13 -0700822#define M8XX_SIZE (io->stop - io->start + 1)
823#define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start)
824
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200825 pr_debug("m8xx_pcmcia: SetIOMap(%d, %d, %#2.2x, %d ns, "
Wolfram Sang5f784332009-10-19 11:42:13 +0200826 "%#4.4llx-%#4.4llx)\n", lsock, io->map, io->flags,
827 io->speed, (unsigned long long)io->start,
828 (unsigned long long)io->stop);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700829
830 if ((io->map >= PCMCIA_IO_WIN_NO) || (io->start > 0xffff)
831 || (io->stop > 0xffff) || (io->stop < io->start))
832 return -EINVAL;
833
Vitaly Bordug99121c02007-07-17 04:03:37 -0700834 if ((reg = m8xx_get_graycode(M8XX_SIZE)) == -1)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700835 return -EINVAL;
836
Vitaly Bordug99121c02007-07-17 04:03:37 -0700837 if (io->flags & MAP_ACTIVE) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700838
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200839 pr_debug("m8xx_pcmcia: io->flags & MAP_ACTIVE\n");
Marcelo Tosattide957c82005-10-28 17:46:13 -0700840
841 winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
Vitaly Bordug99121c02007-07-17 04:03:37 -0700842 + (lsock * PCMCIA_IO_WIN_NO) + io->map;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700843
844 /* setup registers */
845
Vitaly Bordug99121c02007-07-17 04:03:37 -0700846 w = (void *)&pcmcia->pcmc_pbr0;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700847 w += winnr;
848
Vitaly Bordug99121c02007-07-17 04:03:37 -0700849 out_be32(&w->or, 0); /* turn off window first */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700850 out_be32(&w->br, M8XX_BASE);
851
852 reg <<= 27;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700853 reg |= M8XX_PCMCIA_POR_IO | (lsock << 2);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700854
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700855 reg |= m8xx_get_speed(io->speed, 1, s->bus_freq);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700856
Vitaly Bordug99121c02007-07-17 04:03:37 -0700857 if (io->flags & MAP_WRPROT)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700858 reg |= M8XX_PCMCIA_POR_WRPROT;
859
Vitaly Bordug99121c02007-07-17 04:03:37 -0700860 /*if(io->flags & (MAP_16BIT | MAP_AUTOSZ)) */
861 if (io->flags & MAP_16BIT)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700862 reg |= M8XX_PCMCIA_POR_16BIT;
863
Vitaly Bordug99121c02007-07-17 04:03:37 -0700864 if (io->flags & MAP_ACTIVE)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700865 reg |= M8XX_PCMCIA_POR_VALID;
866
867 out_be32(&w->or, reg);
868
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200869 pr_debug("m8xx_pcmcia: Socket %u: Mapped io window %u at "
870 "%#8.8x, OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700871 } else {
872 /* shutdown IO window */
873 winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
Vitaly Bordug99121c02007-07-17 04:03:37 -0700874 + (lsock * PCMCIA_IO_WIN_NO) + io->map;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700875
876 /* setup registers */
877
Vitaly Bordug99121c02007-07-17 04:03:37 -0700878 w = (void *)&pcmcia->pcmc_pbr0;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700879 w += winnr;
880
Vitaly Bordug99121c02007-07-17 04:03:37 -0700881 out_be32(&w->or, 0); /* turn off window */
882 out_be32(&w->br, 0); /* turn off base address */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700883
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200884 pr_debug("m8xx_pcmcia: Socket %u: Unmapped io window %u at "
885 "%#8.8x, OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700886 }
887
888 /* copy the struct and modify the copy */
889 s->io_win[io->map] = *io;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700890 s->io_win[io->map].flags &= (MAP_WRPROT | MAP_16BIT | MAP_ACTIVE);
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200891 pr_debug("m8xx_pcmcia: SetIOMap exit\n");
Marcelo Tosattide957c82005-10-28 17:46:13 -0700892
893 return 0;
894}
895
Vitaly Bordug99121c02007-07-17 04:03:37 -0700896static int m8xx_set_mem_map(struct pcmcia_socket *sock,
897 struct pccard_mem_map *mem)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700898{
899 int lsock = container_of(sock, struct socket_info, socket)->slot;
900 struct socket_info *s = &socket[lsock];
901 struct pcmcia_win *w;
902 struct pccard_mem_map *old;
903 unsigned int reg, winnr;
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700904 pcmconf8xx_t *pcmcia = s->pcmcia;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700905
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200906 pr_debug("m8xx_pcmcia: SetMemMap(%d, %d, %#2.2x, %d ns, "
Wolfram Sang5f784332009-10-19 11:42:13 +0200907 "%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags,
908 mem->speed, (unsigned long long)mem->static_start,
909 mem->card_start);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700910
911 if ((mem->map >= PCMCIA_MEM_WIN_NO)
Vitaly Bordug99121c02007-07-17 04:03:37 -0700912// || ((mem->s) >= PCMCIA_MEM_WIN_SIZE)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700913 || (mem->card_start >= 0x04000000)
Vitaly Bordug99121c02007-07-17 04:03:37 -0700914 || (mem->static_start & 0xfff) /* 4KByte resolution */
915 ||(mem->card_start & 0xfff))
Marcelo Tosattide957c82005-10-28 17:46:13 -0700916 return -EINVAL;
917
Vitaly Bordug99121c02007-07-17 04:03:37 -0700918 if ((reg = m8xx_get_graycode(PCMCIA_MEM_WIN_SIZE)) == -1) {
919 printk("Cannot set size to 0x%08x.\n", PCMCIA_MEM_WIN_SIZE);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700920 return -EINVAL;
921 }
922 reg <<= 27;
923
924 winnr = (lsock * PCMCIA_MEM_WIN_NO) + mem->map;
925
926 /* Setup the window in the pcmcia controller */
927
Vitaly Bordug99121c02007-07-17 04:03:37 -0700928 w = (void *)&pcmcia->pcmc_pbr0;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700929 w += winnr;
930
931 reg |= lsock << 2;
932
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700933 reg |= m8xx_get_speed(mem->speed, 0, s->bus_freq);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700934
Vitaly Bordug99121c02007-07-17 04:03:37 -0700935 if (mem->flags & MAP_ATTRIB)
936 reg |= M8XX_PCMCIA_POR_ATTRMEM;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700937
Vitaly Bordug99121c02007-07-17 04:03:37 -0700938 if (mem->flags & MAP_WRPROT)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700939 reg |= M8XX_PCMCIA_POR_WRPROT;
940
Vitaly Bordug99121c02007-07-17 04:03:37 -0700941 if (mem->flags & MAP_16BIT)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700942 reg |= M8XX_PCMCIA_POR_16BIT;
943
Vitaly Bordug99121c02007-07-17 04:03:37 -0700944 if (mem->flags & MAP_ACTIVE)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700945 reg |= M8XX_PCMCIA_POR_VALID;
946
947 out_be32(&w->or, reg);
948
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200949 pr_debug("m8xx_pcmcia: Socket %u: Mapped memory window %u at %#8.8x, "
Vitaly Bordug99121c02007-07-17 04:03:37 -0700950 "OR = %#8.8x.\n", lsock, mem->map, w->br, w->or);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700951
Vitaly Bordug99121c02007-07-17 04:03:37 -0700952 if (mem->flags & MAP_ACTIVE) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700953 /* get the new base address */
954 mem->static_start = PCMCIA_MEM_WIN_BASE +
Vitaly Bordug99121c02007-07-17 04:03:37 -0700955 (PCMCIA_MEM_WIN_SIZE * winnr)
956 + mem->card_start;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700957 }
958
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200959 pr_debug("m8xx_pcmcia: SetMemMap(%d, %d, %#2.2x, %d ns, "
Wolfram Sang5f784332009-10-19 11:42:13 +0200960 "%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags,
961 mem->speed, (unsigned long long)mem->static_start,
962 mem->card_start);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700963
964 /* copy the struct and modify the copy */
965
966 old = &s->mem_win[mem->map];
967
968 *old = *mem;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700969 old->flags &= (MAP_ATTRIB | MAP_WRPROT | MAP_16BIT | MAP_ACTIVE);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700970
971 return 0;
972}
973
974static int m8xx_sock_init(struct pcmcia_socket *sock)
975{
976 int i;
977 pccard_io_map io = { 0, 0, 0, 0, 1 };
978 pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
979
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200980 pr_debug("m8xx_pcmcia: sock_init(%d)\n", s);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700981
982 m8xx_set_socket(sock, &dead_socket);
983 for (i = 0; i < PCMCIA_IO_WIN_NO; i++) {
984 io.map = i;
985 m8xx_set_io_map(sock, &io);
986 }
987 for (i = 0; i < PCMCIA_MEM_WIN_NO; i++) {
988 mem.map = i;
989 m8xx_set_mem_map(sock, &mem);
990 }
991
992 return 0;
993
994}
995
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700996static int m8xx_sock_suspend(struct pcmcia_socket *sock)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700997{
998 return m8xx_set_socket(sock, &dead_socket);
999}
1000
1001static struct pccard_operations m8xx_services = {
Vitaly Bordug99121c02007-07-17 04:03:37 -07001002 .init = m8xx_sock_init,
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001003 .suspend = m8xx_sock_suspend,
Marcelo Tosattide957c82005-10-28 17:46:13 -07001004 .get_status = m8xx_get_status,
Marcelo Tosattide957c82005-10-28 17:46:13 -07001005 .set_socket = m8xx_set_socket,
1006 .set_io_map = m8xx_set_io_map,
1007 .set_mem_map = m8xx_set_mem_map,
1008};
1009
Grant Likely1c48a5c2011-02-17 02:43:24 -07001010static int __init m8xx_probe(struct platform_device *ofdev)
Marcelo Tosattide957c82005-10-28 17:46:13 -07001011{
1012 struct pcmcia_win *w;
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001013 unsigned int i, m, hwirq;
1014 pcmconf8xx_t *pcmcia;
1015 int status;
Anatolij Gustschin2005ce32010-06-03 01:38:57 +02001016 struct device_node *np = ofdev->dev.of_node;
Marcelo Tosattide957c82005-10-28 17:46:13 -07001017
1018 pcmcia_info("%s\n", version);
1019
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001020 pcmcia = of_iomap(np, 0);
Vitaly Bordug99121c02007-07-17 04:03:37 -07001021 if (pcmcia == NULL)
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001022 return -EINVAL;
1023
1024 pcmcia_schlvl = irq_of_parse_and_map(np, 0);
Vitaly Bordug99121c02007-07-17 04:03:37 -07001025 hwirq = irq_map[pcmcia_schlvl].hwirq;
Julia Lawall5a1c3e12008-02-04 22:27:44 -08001026 if (pcmcia_schlvl < 0) {
1027 iounmap(pcmcia);
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001028 return -EINVAL;
Julia Lawall5a1c3e12008-02-04 22:27:44 -08001029 }
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001030
1031 m8xx_pgcrx[0] = &pcmcia->pcmc_pgcra;
1032 m8xx_pgcrx[1] = &pcmcia->pcmc_pgcrb;
1033
Marcelo Tosattide957c82005-10-28 17:46:13 -07001034 pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001035 " with IRQ %u (%d). \n", pcmcia_schlvl, hwirq);
Marcelo Tosattide957c82005-10-28 17:46:13 -07001036
1037 /* Configure Status change interrupt */
1038
Vitaly Bordug99121c02007-07-17 04:03:37 -07001039 if (request_irq(pcmcia_schlvl, m8xx_interrupt, IRQF_SHARED,
1040 driver_name, socket)) {
Marcelo Tosattide957c82005-10-28 17:46:13 -07001041 pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n",
1042 pcmcia_schlvl);
Julia Lawall5a1c3e12008-02-04 22:27:44 -08001043 iounmap(pcmcia);
Marcelo Tosattide957c82005-10-28 17:46:13 -07001044 return -1;
1045 }
1046
Vitaly Bordug99121c02007-07-17 04:03:37 -07001047 w = (void *)&pcmcia->pcmc_pbr0;
Marcelo Tosattide957c82005-10-28 17:46:13 -07001048
Vitaly Bordug99121c02007-07-17 04:03:37 -07001049 out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001050 clrbits32(&pcmcia->pcmc_per, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
Marcelo Tosattide957c82005-10-28 17:46:13 -07001051
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001052 /* connect interrupt and disable CxOE */
Marcelo Tosattide957c82005-10-28 17:46:13 -07001053
Vitaly Bordug99121c02007-07-17 04:03:37 -07001054 out_be32(M8XX_PGCRX(0),
1055 M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
1056 out_be32(M8XX_PGCRX(1),
1057 M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
Marcelo Tosattide957c82005-10-28 17:46:13 -07001058
Uwe Kleine-Königb5950762010-11-01 15:38:34 -04001059 /* initialize the fixed memory windows */
Marcelo Tosattide957c82005-10-28 17:46:13 -07001060
Vitaly Bordug99121c02007-07-17 04:03:37 -07001061 for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001062 for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
Marcelo Tosattide957c82005-10-28 17:46:13 -07001063 out_be32(&w->br, PCMCIA_MEM_WIN_BASE +
Vitaly Bordug99121c02007-07-17 04:03:37 -07001064 (PCMCIA_MEM_WIN_SIZE
1065 * (m + i * PCMCIA_MEM_WIN_NO)));
Marcelo Tosattide957c82005-10-28 17:46:13 -07001066
Vitaly Bordug99121c02007-07-17 04:03:37 -07001067 out_be32(&w->or, 0); /* set to not valid */
Marcelo Tosattide957c82005-10-28 17:46:13 -07001068
1069 w++;
1070 }
1071 }
1072
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001073 /* turn off voltage */
Marcelo Tosattide957c82005-10-28 17:46:13 -07001074 voltage_set(0, 0, 0);
1075 voltage_set(1, 0, 0);
1076
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001077 /* Enable external hardware */
Marcelo Tosattide957c82005-10-28 17:46:13 -07001078 hardware_enable(0);
1079 hardware_enable(1);
1080
Vitaly Bordug99121c02007-07-17 04:03:37 -07001081 for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
Marcelo Tosattide957c82005-10-28 17:46:13 -07001082 socket[i].slot = i;
1083 socket[i].socket.owner = THIS_MODULE;
Vitaly Bordug99121c02007-07-17 04:03:37 -07001084 socket[i].socket.features =
1085 SS_CAP_PCCARD | SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP;
Marcelo Tosattide957c82005-10-28 17:46:13 -07001086 socket[i].socket.irq_mask = 0x000;
1087 socket[i].socket.map_size = 0x1000;
1088 socket[i].socket.io_offset = 0;
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001089 socket[i].socket.pci_irq = pcmcia_schlvl;
Marcelo Tosattide957c82005-10-28 17:46:13 -07001090 socket[i].socket.ops = &m8xx_services;
Dominik Brodowski4e8804f2010-01-06 11:19:25 +01001091 socket[i].socket.resource_ops = &pccard_iodyn_ops;
Marcelo Tosattide957c82005-10-28 17:46:13 -07001092 socket[i].socket.cb_dev = NULL;
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001093 socket[i].socket.dev.parent = &ofdev->dev;
1094 socket[i].pcmcia = pcmcia;
1095 socket[i].bus_freq = ppc_proc_freq;
1096 socket[i].hwirq = hwirq;
1097
Marcelo Tosattide957c82005-10-28 17:46:13 -07001098 }
1099
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001100 for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
1101 status = pcmcia_register_socket(&socket[i].socket);
1102 if (status < 0)
1103 pcmcia_error("Socket register failed\n");
1104 }
Marcelo Tosattide957c82005-10-28 17:46:13 -07001105
1106 return 0;
1107}
1108
Grant Likely2dc11582010-08-06 09:25:50 -06001109static int m8xx_remove(struct platform_device *ofdev)
Marcelo Tosattide957c82005-10-28 17:46:13 -07001110{
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001111 u32 m, i;
1112 struct pcmcia_win *w;
1113 pcmconf8xx_t *pcmcia = socket[0].pcmcia;
Marcelo Tosattide957c82005-10-28 17:46:13 -07001114
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001115 for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
Vitaly Bordug99121c02007-07-17 04:03:37 -07001116 w = (void *)&pcmcia->pcmc_pbr0;
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001117
1118 out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(i));
1119 out_be32(&pcmcia->pcmc_per,
Vitaly Bordug99121c02007-07-17 04:03:37 -07001120 in_be32(&pcmcia->pcmc_per) & ~M8XX_PCMCIA_MASK(i));
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001121
1122 /* turn off interrupt and disable CxOE */
1123 out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE);
1124
1125 /* turn off memory windows */
1126 for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
Vitaly Bordug99121c02007-07-17 04:03:37 -07001127 out_be32(&w->or, 0); /* set to not valid */
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001128 w++;
1129 }
1130
1131 /* turn off voltage */
1132 voltage_set(i, 0, 0);
1133
1134 /* disable external hardware */
1135 hardware_disable(i);
1136 }
Marcelo Tosattide957c82005-10-28 17:46:13 -07001137 for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
1138 pcmcia_unregister_socket(&socket[i].socket);
Julia Lawall5a1c3e12008-02-04 22:27:44 -08001139 iounmap(pcmcia);
Marcelo Tosattide957c82005-10-28 17:46:13 -07001140
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001141 free_irq(pcmcia_schlvl, NULL);
Marcelo Tosattide957c82005-10-28 17:46:13 -07001142
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001143 return 0;
1144}
1145
Márton Németh63c9a8b2010-01-12 08:56:13 +01001146static const struct of_device_id m8xx_pcmcia_match[] = {
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001147 {
Vitaly Bordug99121c02007-07-17 04:03:37 -07001148 .type = "pcmcia",
1149 .compatible = "fsl,pq-pcmcia",
1150 },
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001151 {},
1152};
1153
1154MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match);
1155
Grant Likely1c48a5c2011-02-17 02:43:24 -07001156static struct platform_driver m8xx_pcmcia_driver = {
Grant Likely40182942010-04-13 16:13:02 -07001157 .driver = {
1158 .name = driver_name,
1159 .owner = THIS_MODULE,
Anatolij Gustschin2005ce32010-06-03 01:38:57 +02001160 .of_match_table = m8xx_pcmcia_match,
Grant Likely40182942010-04-13 16:13:02 -07001161 },
Vitaly Bordug99121c02007-07-17 04:03:37 -07001162 .probe = m8xx_probe,
1163 .remove = m8xx_remove,
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001164};
1165
Axel Lin5d95f8e22011-11-27 12:53:06 +08001166module_platform_driver(m8xx_pcmcia_driver);