blob: 182034d2ef58aff5dae29734bdaf530b3f4ee761 [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 Dammcbba0de2006-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>
Rob Herringc11eede2013-11-10 23:19:08 -060051#include <linux/of_address.h>
Stephen Rothwellad19dbd2008-05-23 16:31:08 +100052#include <linux/of_device.h>
Rob Herringc11eede2013-11-10 23:19:08 -060053#include <linux/of_irq.h>
Stephen Rothwellad19dbd2008-05-23 16:31:08 +100054#include <linux/of_platform.h>
Marcelo Tosattide957c82005-10-28 17:46:13 -070055
Vitaly Bordug80128ff2007-07-09 11:37:35 -070056#include <asm/io.h>
Vitaly Bordug80128ff2007-07-09 11:37:35 -070057#include <asm/time.h>
Marcelo Tosattide957c82005-10-28 17:46:13 -070058#include <asm/mpc8xx.h>
59#include <asm/8xx_immap.h>
60#include <asm/irq.h>
Vitaly Bordug80128ff2007-07-09 11:37:35 -070061#include <asm/fs_pd.h>
Marcelo Tosattide957c82005-10-28 17:46:13 -070062
Marcelo Tosattide957c82005-10-28 17:46:13 -070063#include <pcmcia/ss.h>
64
Marcelo Tosattide957c82005-10-28 17:46:13 -070065#define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args)
66#define pcmcia_error(args...) printk(KERN_ERR "m8xx_pcmcia: "args)
67
68static const char *version = "Version 0.06, Aug 2005";
69MODULE_LICENSE("Dual MPL/GPL");
70
71#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B)
72
Marcelo Tosattide957c82005-10-28 17:46:13 -070073/* The ADS board use SLOT_A */
74#ifdef CONFIG_ADS
75#define CONFIG_PCMCIA_SLOT_A
76#define CONFIG_BD_IS_MHZ
77#endif
78
79/* The FADS series are a mess */
80#ifdef CONFIG_FADS
81#if defined(CONFIG_MPC860T) || defined(CONFIG_MPC860) || defined(CONFIG_MPC821)
82#define CONFIG_PCMCIA_SLOT_A
83#else
84#define CONFIG_PCMCIA_SLOT_B
85#endif
86#endif
87
Vitaly Bordug1371d3b2005-12-08 13:56:12 -020088#if defined(CONFIG_MPC885ADS)
89#define CONFIG_PCMCIA_SLOT_A
90#define PCMCIA_GLITCHY_CD
91#endif
92
Marcelo Tosattide957c82005-10-28 17:46:13 -070093/* Cyclades ACS uses both slots */
94#ifdef CONFIG_PRxK
95#define CONFIG_PCMCIA_SLOT_A
96#define CONFIG_PCMCIA_SLOT_B
97#endif
98
Vitaly Bordug99121c02007-07-17 04:03:37 -070099#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700100
101#if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B)
102
103#define PCMCIA_SOCKETS_NO 2
104/* We have only 8 windows, dualsocket support will be limited. */
105#define PCMCIA_MEM_WIN_NO 2
106#define PCMCIA_IO_WIN_NO 2
107#define PCMCIA_SLOT_MSG "SLOT_A and SLOT_B"
108
109#elif defined(CONFIG_PCMCIA_SLOT_A) || defined(CONFIG_PCMCIA_SLOT_B)
110
111#define PCMCIA_SOCKETS_NO 1
112/* full support for one slot */
113#define PCMCIA_MEM_WIN_NO 5
114#define PCMCIA_IO_WIN_NO 2
115
116/* define _slot_ to be able to optimize macros */
117
118#ifdef CONFIG_PCMCIA_SLOT_A
119#define _slot_ 0
120#define PCMCIA_SLOT_MSG "SLOT_A"
121#else
122#define _slot_ 1
123#define PCMCIA_SLOT_MSG "SLOT_B"
124#endif
125
126#else
127#error m8xx_pcmcia: Bad configuration!
128#endif
129
130/* ------------------------------------------------------------------------- */
131
Vitaly Bordug99121c02007-07-17 04:03:37 -0700132#define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0 */
133#define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte */
134#define PCMCIA_IO_WIN_BASE _IO_BASE /* base address for io window 0 */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700135/* ------------------------------------------------------------------------- */
136
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700137static int pcmcia_schlvl;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700138
Ingo Molnar34af9462006-06-27 02:53:55 -0700139static DEFINE_SPINLOCK(events_lock);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700140
Marcelo Tosattide957c82005-10-28 17:46:13 -0700141#define PCMCIA_SOCKET_KEY_5V 1
142#define PCMCIA_SOCKET_KEY_LV 2
143
144/* look up table for pgcrx registers */
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700145static u32 *m8xx_pgcrx[2];
Marcelo Tosattide957c82005-10-28 17:46:13 -0700146
147/*
148 * This structure is used to address each window in the PCMCIA controller.
149 *
150 * Keep in mind that we assume that pcmcia_win[n+1] is mapped directly
151 * after pcmcia_win[n]...
152 */
153
154struct pcmcia_win {
Vitaly Bordug99121c02007-07-17 04:03:37 -0700155 u32 br;
156 u32 or;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700157};
158
159/*
160 * For some reason the hardware guys decided to make both slots share
161 * some registers.
162 *
163 * Could someone invent object oriented hardware ?
164 *
165 * The macros are used to get the right bit from the registers.
166 * SLOT_A : slot = 0
167 * SLOT_B : slot = 1
168 */
169
170#define M8XX_PCMCIA_VS1(slot) (0x80000000 >> (slot << 4))
171#define M8XX_PCMCIA_VS2(slot) (0x40000000 >> (slot << 4))
172#define M8XX_PCMCIA_VS_MASK(slot) (0xc0000000 >> (slot << 4))
173#define M8XX_PCMCIA_VS_SHIFT(slot) (30 - (slot << 4))
174
175#define M8XX_PCMCIA_WP(slot) (0x20000000 >> (slot << 4))
176#define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4))
177#define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4))
178#define M8XX_PCMCIA_BVD2(slot) (0x04000000 >> (slot << 4))
179#define M8XX_PCMCIA_BVD1(slot) (0x02000000 >> (slot << 4))
180#define M8XX_PCMCIA_RDY(slot) (0x01000000 >> (slot << 4))
181#define M8XX_PCMCIA_RDY_L(slot) (0x00800000 >> (slot << 4))
182#define M8XX_PCMCIA_RDY_H(slot) (0x00400000 >> (slot << 4))
183#define M8XX_PCMCIA_RDY_R(slot) (0x00200000 >> (slot << 4))
184#define M8XX_PCMCIA_RDY_F(slot) (0x00100000 >> (slot << 4))
185#define M8XX_PCMCIA_MASK(slot) (0xFFFF0000 >> (slot << 4))
186
187#define M8XX_PCMCIA_POR_VALID 0x00000001
188#define M8XX_PCMCIA_POR_WRPROT 0x00000002
189#define M8XX_PCMCIA_POR_ATTRMEM 0x00000010
190#define M8XX_PCMCIA_POR_IO 0x00000018
191#define M8XX_PCMCIA_POR_16BIT 0x00000040
192
193#define M8XX_PGCRX(slot) m8xx_pgcrx[slot]
194
195#define M8XX_PGCRX_CXOE 0x00000080
196#define M8XX_PGCRX_CXRESET 0x00000040
197
198/* we keep one lookup table per socket to check flags */
199
Vitaly Bordug99121c02007-07-17 04:03:37 -0700200#define PCMCIA_EVENTS_MAX 5 /* 4 max at a time + termination */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700201
202struct event_table {
203 u32 regbit;
204 u32 eventbit;
205};
206
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700207static const char driver_name[] = "m8xx-pcmcia";
208
Marcelo Tosattide957c82005-10-28 17:46:13 -0700209struct socket_info {
Vitaly Bordug99121c02007-07-17 04:03:37 -0700210 void (*handler) (void *info, u32 events);
211 void *info;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700212
213 u32 slot;
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700214 pcmconf8xx_t *pcmcia;
215 u32 bus_freq;
216 int hwirq;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700217
218 socket_state_t state;
219 struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO];
Vitaly Bordug99121c02007-07-17 04:03:37 -0700220 struct pccard_io_map io_win[PCMCIA_IO_WIN_NO];
Marcelo Tosattide957c82005-10-28 17:46:13 -0700221 struct event_table events[PCMCIA_EVENTS_MAX];
222 struct pcmcia_socket socket;
223};
224
225static struct socket_info socket[PCMCIA_SOCKETS_NO];
226
227/*
228 * Search this table to see if the windowsize is
229 * supported...
230 */
231
232#define M8XX_SIZES_NO 32
233
Vitaly Bordug99121c02007-07-17 04:03:37 -0700234static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] = {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700235 0x00000001, 0x00000002, 0x00000008, 0x00000004,
236 0x00000080, 0x00000040, 0x00000010, 0x00000020,
237 0x00008000, 0x00004000, 0x00001000, 0x00002000,
238 0x00000100, 0x00000200, 0x00000800, 0x00000400,
239
240 0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff,
241 0x01000000, 0x02000000, 0xffffffff, 0x04000000,
242 0x00010000, 0x00020000, 0x00080000, 0x00040000,
243 0x00800000, 0x00400000, 0x00100000, 0x00200000
244};
245
246/* ------------------------------------------------------------------------- */
247
David Howells7d12e782006-10-05 14:55:46 +0100248static irqreturn_t m8xx_interrupt(int irq, void *dev);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700249
Vitaly Bordug99121c02007-07-17 04:03:37 -0700250#define PCMCIA_BMT_LIMIT (15*4) /* Bus Monitor Timeout value */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700251
Marcelo Tosattide957c82005-10-28 17:46:13 -0700252/* FADS Boards from Motorola */
253
254#if defined(CONFIG_FADS)
255
256#define PCMCIA_BOARD_MSG "FADS"
257
258static int voltage_set(int slot, int vcc, int vpp)
259{
260 u32 reg = 0;
261
Vitaly Bordug99121c02007-07-17 04:03:37 -0700262 switch (vcc) {
263 case 0:
264 break;
265 case 33:
266 reg |= BCSR1_PCCVCC0;
267 break;
268 case 50:
269 reg |= BCSR1_PCCVCC1;
270 break;
271 default:
272 return 1;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700273 }
274
Vitaly Bordug99121c02007-07-17 04:03:37 -0700275 switch (vpp) {
276 case 0:
277 break;
278 case 33:
279 case 50:
280 if (vcc == vpp)
281 reg |= BCSR1_PCCVPP1;
282 else
Marcelo Tosattide957c82005-10-28 17:46:13 -0700283 return 1;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700284 break;
285 case 120:
286 if ((vcc == 33) || (vcc == 50))
287 reg |= BCSR1_PCCVPP0;
288 else
289 return 1;
290 default:
291 return 1;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700292 }
293
294 /* first, turn off all power */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700295 out_be32((u32 *) BCSR1,
296 in_be32((u32 *) BCSR1) & ~(BCSR1_PCCVCC_MASK |
297 BCSR1_PCCVPP_MASK));
Marcelo Tosattide957c82005-10-28 17:46:13 -0700298
299 /* enable new powersettings */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700300 out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | reg);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700301
302 return 0;
303}
304
305#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
306
307static void hardware_enable(int slot)
308{
Vitaly Bordug99121c02007-07-17 04:03:37 -0700309 out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) & ~BCSR1_PCCEN);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700310}
311
312static void hardware_disable(int slot)
313{
Vitaly Bordug99121c02007-07-17 04:03:37 -0700314 out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | BCSR1_PCCEN);
Vitaly Bordug1371d3b2005-12-08 13:56:12 -0200315}
316
317#endif
318
319/* MPC885ADS Boards */
320
321#if defined(CONFIG_MPC885ADS)
322
323#define PCMCIA_BOARD_MSG "MPC885ADS"
Vitaly Bordug1371d3b2005-12-08 13:56:12 -0200324#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
325
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700326static inline void hardware_enable(int slot)
Vitaly Bordug1371d3b2005-12-08 13:56:12 -0200327{
Vitaly Bordug99121c02007-07-17 04:03:37 -0700328 m8xx_pcmcia_ops.hw_ctrl(slot, 1);
Vitaly Bordug1371d3b2005-12-08 13:56:12 -0200329}
330
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700331static inline void hardware_disable(int slot)
Vitaly Bordug1371d3b2005-12-08 13:56:12 -0200332{
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700333 m8xx_pcmcia_ops.hw_ctrl(slot, 0);
334}
Vitaly Bordug1371d3b2005-12-08 13:56:12 -0200335
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700336static inline int voltage_set(int slot, int vcc, int vpp)
337{
338 return m8xx_pcmcia_ops.voltage_set(slot, vcc, vpp);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700339}
340
341#endif
342
Marcelo Tosattide957c82005-10-28 17:46:13 -0700343#if defined(CONFIG_PRxK)
344#include <asm/cpld.h>
345extern volatile fpga_pc_regs *fpga_pc;
346
347#define PCMCIA_BOARD_MSG "MPC855T"
348
349static int voltage_set(int slot, int vcc, int vpp)
350{
351 u8 reg = 0;
352 u8 regread;
353 cpld_regs *ccpld = get_cpld();
354
Vitaly Bordug99121c02007-07-17 04:03:37 -0700355 switch (vcc) {
356 case 0:
357 break;
358 case 33:
359 reg |= PCMCIA_VCC_33;
360 break;
361 case 50:
362 reg |= PCMCIA_VCC_50;
363 break;
364 default:
365 return 1;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700366 }
367
Vitaly Bordug99121c02007-07-17 04:03:37 -0700368 switch (vpp) {
369 case 0:
370 break;
371 case 33:
372 case 50:
373 if (vcc == vpp)
374 reg |= PCMCIA_VPP_VCC;
375 else
Marcelo Tosattide957c82005-10-28 17:46:13 -0700376 return 1;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700377 break;
378 case 120:
379 if ((vcc == 33) || (vcc == 50))
380 reg |= PCMCIA_VPP_12;
381 else
382 return 1;
383 default:
384 return 1;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700385 }
386
387 reg = reg >> (slot << 2);
388 regread = in_8(&ccpld->fpga_pc_ctl);
Vitaly Bordug99121c02007-07-17 04:03:37 -0700389 if (reg !=
390 (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700391 /* enable new powersettings */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700392 regread =
393 regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >>
394 (slot << 2));
Marcelo Tosattide957c82005-10-28 17:46:13 -0700395 out_8(&ccpld->fpga_pc_ctl, reg | regread);
396 msleep(100);
397 }
398
399 return 0;
400}
401
402#define socket_get(_slot_) PCMCIA_SOCKET_KEY_LV
Vitaly Bordug99121c02007-07-17 04:03:37 -0700403#define hardware_enable(_slot_) /* No hardware to enable */
404#define hardware_disable(_slot_) /* No hardware to disable */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700405
Vitaly Bordug99121c02007-07-17 04:03:37 -0700406#endif /* CONFIG_PRxK */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700407
Marcelo Tosattide957c82005-10-28 17:46:13 -0700408static u32 pending_events[PCMCIA_SOCKETS_NO];
Ingo Molnar34af9462006-06-27 02:53:55 -0700409static DEFINE_SPINLOCK(pending_event_lock);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700410
David Howells7d12e782006-10-05 14:55:46 +0100411static irqreturn_t m8xx_interrupt(int irq, void *dev)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700412{
413 struct socket_info *s;
414 struct event_table *e;
415 unsigned int i, events, pscr, pipr, per;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700416 pcmconf8xx_t *pcmcia = socket[0].pcmcia;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700417
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200418 pr_debug("m8xx_pcmcia: Interrupt!\n");
Marcelo Tosattide957c82005-10-28 17:46:13 -0700419 /* get interrupt sources */
420
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700421 pscr = in_be32(&pcmcia->pcmc_pscr);
422 pipr = in_be32(&pcmcia->pcmc_pipr);
423 per = in_be32(&pcmcia->pcmc_per);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700424
Vitaly Bordug99121c02007-07-17 04:03:37 -0700425 for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700426 s = &socket[i];
427 e = &s->events[0];
428 events = 0;
429
Vitaly Bordug99121c02007-07-17 04:03:37 -0700430 while (e->regbit) {
431 if (pscr & e->regbit)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700432 events |= e->eventbit;
433
Vitaly Bordug99121c02007-07-17 04:03:37 -0700434 e++;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700435 }
436
437 /*
438 * report only if both card detect signals are the same
439 * not too nice done,
440 * we depend on that CD2 is the bit to the left of CD1...
441 */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700442 if (events & SS_DETECT)
443 if (((pipr & M8XX_PCMCIA_CD2(i)) >> 1) ^
444 (pipr & M8XX_PCMCIA_CD1(i))) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700445 events &= ~SS_DETECT;
446 }
Marcelo Tosattide957c82005-10-28 17:46:13 -0700447#ifdef PCMCIA_GLITCHY_CD
448 /*
449 * I've experienced CD problems with my ADS board.
450 * We make an extra check to see if there was a
451 * real change of Card detection.
452 */
453
Vitaly Bordug99121c02007-07-17 04:03:37 -0700454 if ((events & SS_DETECT) &&
455 ((pipr &
456 (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i))) == 0) &&
457 (s->state.Vcc | s->state.Vpp)) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700458 events &= ~SS_DETECT;
459 /*printk( "CD glitch workaround - CD = 0x%08x!\n",
Vitaly Bordug99121c02007-07-17 04:03:37 -0700460 (pipr & (M8XX_PCMCIA_CD2(i)
461 | M8XX_PCMCIA_CD1(i)))); */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700462 }
463#endif
464
465 /* call the handler */
466
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200467 pr_debug("m8xx_pcmcia: slot %u: events = 0x%02x, pscr = 0x%08x, "
Vitaly Bordug99121c02007-07-17 04:03:37 -0700468 "pipr = 0x%08x\n", i, events, pscr, pipr);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700469
Vitaly Bordug99121c02007-07-17 04:03:37 -0700470 if (events) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700471 spin_lock(&pending_event_lock);
472 pending_events[i] |= events;
473 spin_unlock(&pending_event_lock);
474 /*
475 * Turn off RDY_L bits in the PER mask on
476 * CD interrupt receival.
477 *
478 * They can generate bad interrupts on the
479 * ACS4,8,16,32. - marcelo
480 */
481 per &= ~M8XX_PCMCIA_RDY_L(0);
482 per &= ~M8XX_PCMCIA_RDY_L(1);
483
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700484 out_be32(&pcmcia->pcmc_per, per);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700485
486 if (events)
487 pcmcia_parse_events(&socket[i].socket, events);
488 }
489 }
490
491 /* clear the interrupt sources */
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700492 out_be32(&pcmcia->pcmc_pscr, pscr);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700493
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200494 pr_debug("m8xx_pcmcia: Interrupt done.\n");
Marcelo Tosattide957c82005-10-28 17:46:13 -0700495
496 return IRQ_HANDLED;
497}
498
499static u32 m8xx_get_graycode(u32 size)
500{
501 u32 k;
502
Vitaly Bordug99121c02007-07-17 04:03:37 -0700503 for (k = 0; k < M8XX_SIZES_NO; k++)
504 if (m8xx_size_to_gray[k] == size)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700505 break;
506
Vitaly Bordug99121c02007-07-17 04:03:37 -0700507 if ((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
Marcelo Tosattide957c82005-10-28 17:46:13 -0700508 k = -1;
509
510 return k;
511}
512
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700513static u32 m8xx_get_speed(u32 ns, u32 is_io, u32 bus_freq)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700514{
515 u32 reg, clocks, psst, psl, psht;
516
Vitaly Bordug99121c02007-07-17 04:03:37 -0700517 if (!ns) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700518
519 /*
520 * We get called with IO maps setup to 0ns
521 * if not specified by the user.
522 * They should be 255ns.
523 */
524
Vitaly Bordug99121c02007-07-17 04:03:37 -0700525 if (is_io)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700526 ns = 255;
527 else
Vitaly Bordug99121c02007-07-17 04:03:37 -0700528 ns = 100; /* fast memory if 0 */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700529 }
530
531 /*
532 * In PSST, PSL, PSHT fields we tell the controller
533 * timing parameters in CLKOUT clock cycles.
534 * CLKOUT is the same as GCLK2_50.
535 */
536
537/* how we want to adjust the timing - in percent */
538
Vitaly Bordug99121c02007-07-17 04:03:37 -0700539#define ADJ 180 /* 80 % longer accesstime - to be sure */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700540
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700541 clocks = ((bus_freq / 1000) * ns) / 1000;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700542 clocks = (clocks * ADJ) / (100 * 1000);
543 if (clocks >= PCMCIA_BMT_LIMIT) {
544 printk("Max access time limit reached\n");
545 clocks = PCMCIA_BMT_LIMIT - 1;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700546 }
547
Vitaly Bordug99121c02007-07-17 04:03:37 -0700548 psst = clocks / 7; /* setup time */
549 psht = clocks / 7; /* hold time */
550 psl = (clocks * 5) / 7; /* strobe length */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700551
552 psst += clocks - (psst + psht + psl);
553
Vitaly Bordug99121c02007-07-17 04:03:37 -0700554 reg = psst << 12;
555 reg |= psl << 7;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700556 reg |= psht << 16;
557
558 return reg;
559}
560
561static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value)
562{
563 int lsock = container_of(sock, struct socket_info, socket)->slot;
564 struct socket_info *s = &socket[lsock];
565 unsigned int pipr, reg;
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700566 pcmconf8xx_t *pcmcia = s->pcmcia;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700567
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700568 pipr = in_be32(&pcmcia->pcmc_pipr);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700569
Vitaly Bordug99121c02007-07-17 04:03:37 -0700570 *value = ((pipr & (M8XX_PCMCIA_CD1(lsock)
571 | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700572 *value |= (pipr & M8XX_PCMCIA_WP(lsock)) ? SS_WRPROT : 0;
573
574 if (s->state.flags & SS_IOCARD)
575 *value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_STSCHG : 0;
576 else {
577 *value |= (pipr & M8XX_PCMCIA_RDY(lsock)) ? SS_READY : 0;
578 *value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_BATDEAD : 0;
579 *value |= (pipr & M8XX_PCMCIA_BVD2(lsock)) ? SS_BATWARN : 0;
580 }
581
582 if (s->state.Vcc | s->state.Vpp)
583 *value |= SS_POWERON;
584
585 /*
586 * Voltage detection:
587 * This driver only supports 16-Bit pc-cards.
588 * Cardbus is not handled here.
589 *
590 * To determine what voltage to use we must read the VS1 and VS2 pin.
591 * Depending on what socket type is present,
592 * different combinations mean different things.
593 *
594 * Card Key Socket Key VS1 VS2 Card Vcc for CIS parse
595 *
596 * 5V 5V, LV* NC NC 5V only 5V (if available)
597 *
598 * 5V 5V, LV* GND NC 5 or 3.3V as low as possible
599 *
600 * 5V 5V, LV* GND GND 5, 3.3, x.xV as low as possible
601 *
602 * LV* 5V - - shall not fit into socket
603 *
604 * LV* LV* GND NC 3.3V only 3.3V
605 *
606 * LV* LV* NC GND x.xV x.xV (if avail.)
607 *
608 * LV* LV* GND GND 3.3 or x.xV as low as possible
609 *
610 * *LV means Low Voltage
611 *
612 *
613 * That gives us the following table:
614 *
615 * Socket VS1 VS2 Voltage
616 *
617 * 5V NC NC 5V
618 * 5V NC GND none (should not be possible)
619 * 5V GND NC >= 3.3V
620 * 5V GND GND >= x.xV
621 *
622 * LV NC NC 5V (if available)
623 * LV NC GND x.xV (if available)
624 * LV GND NC 3.3V
625 * LV GND GND >= x.xV
626 *
627 * So, how do I determine if I have a 5V or a LV
628 * socket on my board? Look at the socket!
629 *
630 *
631 * Socket with 5V key:
632 * ++--------------------------------------------+
633 * || |
634 * || ||
635 * || ||
636 * | |
637 * +---------------------------------------------+
638 *
639 * Socket with LV key:
640 * ++--------------------------------------------+
641 * || |
642 * | ||
643 * | ||
644 * | |
645 * +---------------------------------------------+
646 *
647 *
648 * With other words - LV only cards does not fit
649 * into the 5V socket!
650 */
651
652 /* read out VS1 and VS2 */
653
654 reg = (pipr & M8XX_PCMCIA_VS_MASK(lsock))
Vitaly Bordug99121c02007-07-17 04:03:37 -0700655 >> M8XX_PCMCIA_VS_SHIFT(lsock);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700656
Vitaly Bordug99121c02007-07-17 04:03:37 -0700657 if (socket_get(lsock) == PCMCIA_SOCKET_KEY_LV) {
658 switch (reg) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700659 case 1:
660 *value |= SS_3VCARD;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700661 break; /* GND, NC - 3.3V only */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700662 case 2:
663 *value |= SS_XVCARD;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700664 break; /* NC. GND - x.xV only */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700665 };
666 }
667
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200668 pr_debug("m8xx_pcmcia: GetStatus(%d) = %#2.2x\n", lsock, *value);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700669 return 0;
670}
671
Vitaly Bordug99121c02007-07-17 04:03:37 -0700672static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t * state)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700673{
674 int lsock = container_of(sock, struct socket_info, socket)->slot;
675 struct socket_info *s = &socket[lsock];
676 struct event_table *e;
677 unsigned int reg;
678 unsigned long flags;
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700679 pcmconf8xx_t *pcmcia = socket[0].pcmcia;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700680
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200681 pr_debug("m8xx_pcmcia: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
Vitaly Bordug99121c02007-07-17 04:03:37 -0700682 "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,
683 state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700684
685 /* First, set voltage - bail out if invalid */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700686 if (voltage_set(lsock, state->Vcc, state->Vpp))
Marcelo Tosattide957c82005-10-28 17:46:13 -0700687 return -EINVAL;
688
689 /* Take care of reset... */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700690 if (state->flags & SS_RESET)
691 out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET); /* active high */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700692 else
Vitaly Bordug99121c02007-07-17 04:03:37 -0700693 out_be32(M8XX_PGCRX(lsock),
694 in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXRESET);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700695
696 /* ... and output enable. */
697
698 /* The CxOE signal is connected to a 74541 on the ADS.
699 I guess most other boards used the ADS as a reference.
700 I tried to control the CxOE signal with SS_OUTPUT_ENA,
701 but the reset signal seems connected via the 541.
702 If the CxOE is left high are some signals tristated and
Joe Perchesf26fc4e2008-02-03 17:26:02 +0200703 no pullups are present -> the cards act weird.
Marcelo Tosattide957c82005-10-28 17:46:13 -0700704 So right now the buffers are enabled if the power is on. */
705
Vitaly Bordug99121c02007-07-17 04:03:37 -0700706 if (state->Vcc || state->Vpp)
707 out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXOE); /* active low */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700708 else
Vitaly Bordug99121c02007-07-17 04:03:37 -0700709 out_be32(M8XX_PGCRX(lsock),
710 in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXOE);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700711
712 /*
713 * We'd better turn off interrupts before
714 * we mess with the events-table..
715 */
716
717 spin_lock_irqsave(&events_lock, flags);
718
719 /*
720 * Play around with the interrupt mask to be able to
721 * give the events the generic pcmcia driver wants us to.
722 */
723
724 e = &s->events[0];
725 reg = 0;
726
Vitaly Bordug99121c02007-07-17 04:03:37 -0700727 if (state->csc_mask & SS_DETECT) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700728 e->eventbit = SS_DETECT;
729 reg |= e->regbit = (M8XX_PCMCIA_CD2(lsock)
730 | M8XX_PCMCIA_CD1(lsock));
731 e++;
732 }
Vitaly Bordug99121c02007-07-17 04:03:37 -0700733 if (state->flags & SS_IOCARD) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700734 /*
735 * I/O card
736 */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700737 if (state->csc_mask & SS_STSCHG) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700738 e->eventbit = SS_STSCHG;
739 reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
740 e++;
741 }
742 /*
743 * If io_irq is non-zero we should enable irq.
744 */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700745 if (state->io_irq) {
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700746 out_be32(M8XX_PGCRX(lsock),
Vitaly Bordug99121c02007-07-17 04:03:37 -0700747 in_be32(M8XX_PGCRX(lsock)) |
748 mk_int_int_mask(s->hwirq) << 24);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700749 /*
750 * Strange thing here:
751 * The manual does not tell us which interrupt
752 * the sources generate.
753 * Anyhow, I found out that RDY_L generates IREQLVL.
754 *
755 * We use level triggerd interrupts, and they don't
756 * have to be cleared in PSCR in the interrupt handler.
757 */
758 reg |= M8XX_PCMCIA_RDY_L(lsock);
Vitaly Bordug99121c02007-07-17 04:03:37 -0700759 } else
760 out_be32(M8XX_PGCRX(lsock),
761 in_be32(M8XX_PGCRX(lsock)) & 0x00ffffff);
762 } else {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700763 /*
764 * Memory card
765 */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700766 if (state->csc_mask & SS_BATDEAD) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700767 e->eventbit = SS_BATDEAD;
768 reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
769 e++;
770 }
Vitaly Bordug99121c02007-07-17 04:03:37 -0700771 if (state->csc_mask & SS_BATWARN) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700772 e->eventbit = SS_BATWARN;
773 reg |= e->regbit = M8XX_PCMCIA_BVD2(lsock);
774 e++;
775 }
776 /* What should I trigger on - low/high,raise,fall? */
Vitaly Bordug99121c02007-07-17 04:03:37 -0700777 if (state->csc_mask & SS_READY) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700778 e->eventbit = SS_READY;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700779 reg |= e->regbit = 0; //??
Marcelo Tosattide957c82005-10-28 17:46:13 -0700780 e++;
781 }
782 }
783
Vitaly Bordug99121c02007-07-17 04:03:37 -0700784 e->regbit = 0; /* terminate list */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700785
786 /*
787 * Clear the status changed .
788 * Port A and Port B share the same port.
789 * Writing ones will clear the bits.
790 */
791
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700792 out_be32(&pcmcia->pcmc_pscr, reg);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700793
794 /*
795 * Write the mask.
796 * Port A and Port B share the same port.
797 * Need for read-modify-write.
798 * Ones will enable the interrupt.
799 */
800
Vitaly Bordug99121c02007-07-17 04:03:37 -0700801 reg |=
802 in_be32(&pcmcia->
803 pcmc_per) & (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700804 out_be32(&pcmcia->pcmc_per, reg);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700805
806 spin_unlock_irqrestore(&events_lock, flags);
807
808 /* copy the struct and modify the copy */
809
810 s->state = *state;
811
812 return 0;
813}
814
815static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
816{
817 int lsock = container_of(sock, struct socket_info, socket)->slot;
818
819 struct socket_info *s = &socket[lsock];
820 struct pcmcia_win *w;
821 unsigned int reg, winnr;
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700822 pcmconf8xx_t *pcmcia = s->pcmcia;
823
Marcelo Tosattide957c82005-10-28 17:46:13 -0700824#define M8XX_SIZE (io->stop - io->start + 1)
825#define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start)
826
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200827 pr_debug("m8xx_pcmcia: SetIOMap(%d, %d, %#2.2x, %d ns, "
Wolfram Sang5f784332009-10-19 11:42:13 +0200828 "%#4.4llx-%#4.4llx)\n", lsock, io->map, io->flags,
829 io->speed, (unsigned long long)io->start,
830 (unsigned long long)io->stop);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700831
832 if ((io->map >= PCMCIA_IO_WIN_NO) || (io->start > 0xffff)
833 || (io->stop > 0xffff) || (io->stop < io->start))
834 return -EINVAL;
835
Vitaly Bordug99121c02007-07-17 04:03:37 -0700836 if ((reg = m8xx_get_graycode(M8XX_SIZE)) == -1)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700837 return -EINVAL;
838
Vitaly Bordug99121c02007-07-17 04:03:37 -0700839 if (io->flags & MAP_ACTIVE) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700840
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200841 pr_debug("m8xx_pcmcia: io->flags & MAP_ACTIVE\n");
Marcelo Tosattide957c82005-10-28 17:46:13 -0700842
843 winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
Vitaly Bordug99121c02007-07-17 04:03:37 -0700844 + (lsock * PCMCIA_IO_WIN_NO) + io->map;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700845
846 /* setup registers */
847
Vitaly Bordug99121c02007-07-17 04:03:37 -0700848 w = (void *)&pcmcia->pcmc_pbr0;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700849 w += winnr;
850
Vitaly Bordug99121c02007-07-17 04:03:37 -0700851 out_be32(&w->or, 0); /* turn off window first */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700852 out_be32(&w->br, M8XX_BASE);
853
854 reg <<= 27;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700855 reg |= M8XX_PCMCIA_POR_IO | (lsock << 2);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700856
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700857 reg |= m8xx_get_speed(io->speed, 1, s->bus_freq);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700858
Vitaly Bordug99121c02007-07-17 04:03:37 -0700859 if (io->flags & MAP_WRPROT)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700860 reg |= M8XX_PCMCIA_POR_WRPROT;
861
Vitaly Bordug99121c02007-07-17 04:03:37 -0700862 /*if(io->flags & (MAP_16BIT | MAP_AUTOSZ)) */
863 if (io->flags & MAP_16BIT)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700864 reg |= M8XX_PCMCIA_POR_16BIT;
865
Vitaly Bordug99121c02007-07-17 04:03:37 -0700866 if (io->flags & MAP_ACTIVE)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700867 reg |= M8XX_PCMCIA_POR_VALID;
868
869 out_be32(&w->or, reg);
870
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200871 pr_debug("m8xx_pcmcia: Socket %u: Mapped io window %u at "
872 "%#8.8x, OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700873 } else {
874 /* shutdown IO window */
875 winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
Vitaly Bordug99121c02007-07-17 04:03:37 -0700876 + (lsock * PCMCIA_IO_WIN_NO) + io->map;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700877
878 /* setup registers */
879
Vitaly Bordug99121c02007-07-17 04:03:37 -0700880 w = (void *)&pcmcia->pcmc_pbr0;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700881 w += winnr;
882
Vitaly Bordug99121c02007-07-17 04:03:37 -0700883 out_be32(&w->or, 0); /* turn off window */
884 out_be32(&w->br, 0); /* turn off base address */
Marcelo Tosattide957c82005-10-28 17:46:13 -0700885
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200886 pr_debug("m8xx_pcmcia: Socket %u: Unmapped io window %u at "
887 "%#8.8x, OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700888 }
889
890 /* copy the struct and modify the copy */
891 s->io_win[io->map] = *io;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700892 s->io_win[io->map].flags &= (MAP_WRPROT | MAP_16BIT | MAP_ACTIVE);
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200893 pr_debug("m8xx_pcmcia: SetIOMap exit\n");
Marcelo Tosattide957c82005-10-28 17:46:13 -0700894
895 return 0;
896}
897
Vitaly Bordug99121c02007-07-17 04:03:37 -0700898static int m8xx_set_mem_map(struct pcmcia_socket *sock,
899 struct pccard_mem_map *mem)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700900{
901 int lsock = container_of(sock, struct socket_info, socket)->slot;
902 struct socket_info *s = &socket[lsock];
903 struct pcmcia_win *w;
904 struct pccard_mem_map *old;
905 unsigned int reg, winnr;
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700906 pcmconf8xx_t *pcmcia = s->pcmcia;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700907
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200908 pr_debug("m8xx_pcmcia: SetMemMap(%d, %d, %#2.2x, %d ns, "
Wolfram Sang5f784332009-10-19 11:42:13 +0200909 "%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags,
910 mem->speed, (unsigned long long)mem->static_start,
911 mem->card_start);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700912
913 if ((mem->map >= PCMCIA_MEM_WIN_NO)
Vitaly Bordug99121c02007-07-17 04:03:37 -0700914// || ((mem->s) >= PCMCIA_MEM_WIN_SIZE)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700915 || (mem->card_start >= 0x04000000)
Vitaly Bordug99121c02007-07-17 04:03:37 -0700916 || (mem->static_start & 0xfff) /* 4KByte resolution */
917 ||(mem->card_start & 0xfff))
Marcelo Tosattide957c82005-10-28 17:46:13 -0700918 return -EINVAL;
919
Vitaly Bordug99121c02007-07-17 04:03:37 -0700920 if ((reg = m8xx_get_graycode(PCMCIA_MEM_WIN_SIZE)) == -1) {
921 printk("Cannot set size to 0x%08x.\n", PCMCIA_MEM_WIN_SIZE);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700922 return -EINVAL;
923 }
924 reg <<= 27;
925
926 winnr = (lsock * PCMCIA_MEM_WIN_NO) + mem->map;
927
928 /* Setup the window in the pcmcia controller */
929
Vitaly Bordug99121c02007-07-17 04:03:37 -0700930 w = (void *)&pcmcia->pcmc_pbr0;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700931 w += winnr;
932
933 reg |= lsock << 2;
934
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700935 reg |= m8xx_get_speed(mem->speed, 0, s->bus_freq);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700936
Vitaly Bordug99121c02007-07-17 04:03:37 -0700937 if (mem->flags & MAP_ATTRIB)
938 reg |= M8XX_PCMCIA_POR_ATTRMEM;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700939
Vitaly Bordug99121c02007-07-17 04:03:37 -0700940 if (mem->flags & MAP_WRPROT)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700941 reg |= M8XX_PCMCIA_POR_WRPROT;
942
Vitaly Bordug99121c02007-07-17 04:03:37 -0700943 if (mem->flags & MAP_16BIT)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700944 reg |= M8XX_PCMCIA_POR_16BIT;
945
Vitaly Bordug99121c02007-07-17 04:03:37 -0700946 if (mem->flags & MAP_ACTIVE)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700947 reg |= M8XX_PCMCIA_POR_VALID;
948
949 out_be32(&w->or, reg);
950
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200951 pr_debug("m8xx_pcmcia: Socket %u: Mapped memory window %u at %#8.8x, "
Vitaly Bordug99121c02007-07-17 04:03:37 -0700952 "OR = %#8.8x.\n", lsock, mem->map, w->br, w->or);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700953
Vitaly Bordug99121c02007-07-17 04:03:37 -0700954 if (mem->flags & MAP_ACTIVE) {
Marcelo Tosattide957c82005-10-28 17:46:13 -0700955 /* get the new base address */
956 mem->static_start = PCMCIA_MEM_WIN_BASE +
Vitaly Bordug99121c02007-07-17 04:03:37 -0700957 (PCMCIA_MEM_WIN_SIZE * winnr)
958 + mem->card_start;
Marcelo Tosattide957c82005-10-28 17:46:13 -0700959 }
960
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200961 pr_debug("m8xx_pcmcia: SetMemMap(%d, %d, %#2.2x, %d ns, "
Wolfram Sang5f784332009-10-19 11:42:13 +0200962 "%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags,
963 mem->speed, (unsigned long long)mem->static_start,
964 mem->card_start);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700965
966 /* copy the struct and modify the copy */
967
968 old = &s->mem_win[mem->map];
969
970 *old = *mem;
Vitaly Bordug99121c02007-07-17 04:03:37 -0700971 old->flags &= (MAP_ATTRIB | MAP_WRPROT | MAP_16BIT | MAP_ACTIVE);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700972
973 return 0;
974}
975
976static int m8xx_sock_init(struct pcmcia_socket *sock)
977{
978 int i;
979 pccard_io_map io = { 0, 0, 0, 0, 1 };
980 pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
981
Dominik Brodowskic9f50dd2009-10-23 12:56:46 +0200982 pr_debug("m8xx_pcmcia: sock_init(%d)\n", s);
Marcelo Tosattide957c82005-10-28 17:46:13 -0700983
984 m8xx_set_socket(sock, &dead_socket);
985 for (i = 0; i < PCMCIA_IO_WIN_NO; i++) {
986 io.map = i;
987 m8xx_set_io_map(sock, &io);
988 }
989 for (i = 0; i < PCMCIA_MEM_WIN_NO; i++) {
990 mem.map = i;
991 m8xx_set_mem_map(sock, &mem);
992 }
993
994 return 0;
995
996}
997
Vitaly Bordug80128ff2007-07-09 11:37:35 -0700998static int m8xx_sock_suspend(struct pcmcia_socket *sock)
Marcelo Tosattide957c82005-10-28 17:46:13 -0700999{
1000 return m8xx_set_socket(sock, &dead_socket);
1001}
1002
1003static struct pccard_operations m8xx_services = {
Vitaly Bordug99121c02007-07-17 04:03:37 -07001004 .init = m8xx_sock_init,
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001005 .suspend = m8xx_sock_suspend,
Marcelo Tosattide957c82005-10-28 17:46:13 -07001006 .get_status = m8xx_get_status,
Marcelo Tosattide957c82005-10-28 17:46:13 -07001007 .set_socket = m8xx_set_socket,
1008 .set_io_map = m8xx_set_io_map,
1009 .set_mem_map = m8xx_set_mem_map,
1010};
1011
Grant Likely1c48a5c2011-02-17 02:43:24 -07001012static int __init m8xx_probe(struct platform_device *ofdev)
Marcelo Tosattide957c82005-10-28 17:46:13 -07001013{
1014 struct pcmcia_win *w;
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001015 unsigned int i, m, hwirq;
1016 pcmconf8xx_t *pcmcia;
1017 int status;
Anatolij Gustschin2005ce32010-06-03 01:38:57 +02001018 struct device_node *np = ofdev->dev.of_node;
Marcelo Tosattide957c82005-10-28 17:46:13 -07001019
1020 pcmcia_info("%s\n", version);
1021
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001022 pcmcia = of_iomap(np, 0);
Vitaly Bordug99121c02007-07-17 04:03:37 -07001023 if (pcmcia == NULL)
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001024 return -EINVAL;
1025
1026 pcmcia_schlvl = irq_of_parse_and_map(np, 0);
Vitaly Bordug99121c02007-07-17 04:03:37 -07001027 hwirq = irq_map[pcmcia_schlvl].hwirq;
Julia Lawall5a1c3e1a2008-02-04 22:27:44 -08001028 if (pcmcia_schlvl < 0) {
1029 iounmap(pcmcia);
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001030 return -EINVAL;
Julia Lawall5a1c3e1a2008-02-04 22:27:44 -08001031 }
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001032
1033 m8xx_pgcrx[0] = &pcmcia->pcmc_pgcra;
1034 m8xx_pgcrx[1] = &pcmcia->pcmc_pgcrb;
1035
Marcelo Tosattide957c82005-10-28 17:46:13 -07001036 pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001037 " with IRQ %u (%d). \n", pcmcia_schlvl, hwirq);
Marcelo Tosattide957c82005-10-28 17:46:13 -07001038
1039 /* Configure Status change interrupt */
1040
Vitaly Bordug99121c02007-07-17 04:03:37 -07001041 if (request_irq(pcmcia_schlvl, m8xx_interrupt, IRQF_SHARED,
1042 driver_name, socket)) {
Marcelo Tosattide957c82005-10-28 17:46:13 -07001043 pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n",
1044 pcmcia_schlvl);
Julia Lawall5a1c3e1a2008-02-04 22:27:44 -08001045 iounmap(pcmcia);
Marcelo Tosattide957c82005-10-28 17:46:13 -07001046 return -1;
1047 }
1048
Vitaly Bordug99121c02007-07-17 04:03:37 -07001049 w = (void *)&pcmcia->pcmc_pbr0;
Marcelo Tosattide957c82005-10-28 17:46:13 -07001050
Vitaly Bordug99121c02007-07-17 04:03:37 -07001051 out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001052 clrbits32(&pcmcia->pcmc_per, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
Marcelo Tosattide957c82005-10-28 17:46:13 -07001053
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001054 /* connect interrupt and disable CxOE */
Marcelo Tosattide957c82005-10-28 17:46:13 -07001055
Vitaly Bordug99121c02007-07-17 04:03:37 -07001056 out_be32(M8XX_PGCRX(0),
1057 M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
1058 out_be32(M8XX_PGCRX(1),
1059 M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
Marcelo Tosattide957c82005-10-28 17:46:13 -07001060
Uwe Kleine-Königb5950762010-11-01 15:38:34 -04001061 /* initialize the fixed memory windows */
Marcelo Tosattide957c82005-10-28 17:46:13 -07001062
Vitaly Bordug99121c02007-07-17 04:03:37 -07001063 for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001064 for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
Marcelo Tosattide957c82005-10-28 17:46:13 -07001065 out_be32(&w->br, PCMCIA_MEM_WIN_BASE +
Vitaly Bordug99121c02007-07-17 04:03:37 -07001066 (PCMCIA_MEM_WIN_SIZE
1067 * (m + i * PCMCIA_MEM_WIN_NO)));
Marcelo Tosattide957c82005-10-28 17:46:13 -07001068
Vitaly Bordug99121c02007-07-17 04:03:37 -07001069 out_be32(&w->or, 0); /* set to not valid */
Marcelo Tosattide957c82005-10-28 17:46:13 -07001070
1071 w++;
1072 }
1073 }
1074
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001075 /* turn off voltage */
Marcelo Tosattide957c82005-10-28 17:46:13 -07001076 voltage_set(0, 0, 0);
1077 voltage_set(1, 0, 0);
1078
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001079 /* Enable external hardware */
Marcelo Tosattide957c82005-10-28 17:46:13 -07001080 hardware_enable(0);
1081 hardware_enable(1);
1082
Vitaly Bordug99121c02007-07-17 04:03:37 -07001083 for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
Marcelo Tosattide957c82005-10-28 17:46:13 -07001084 socket[i].slot = i;
1085 socket[i].socket.owner = THIS_MODULE;
Vitaly Bordug99121c02007-07-17 04:03:37 -07001086 socket[i].socket.features =
1087 SS_CAP_PCCARD | SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP;
Marcelo Tosattide957c82005-10-28 17:46:13 -07001088 socket[i].socket.irq_mask = 0x000;
1089 socket[i].socket.map_size = 0x1000;
1090 socket[i].socket.io_offset = 0;
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001091 socket[i].socket.pci_irq = pcmcia_schlvl;
Marcelo Tosattide957c82005-10-28 17:46:13 -07001092 socket[i].socket.ops = &m8xx_services;
Dominik Brodowski4e8804f2010-01-06 11:19:25 +01001093 socket[i].socket.resource_ops = &pccard_iodyn_ops;
Marcelo Tosattide957c82005-10-28 17:46:13 -07001094 socket[i].socket.cb_dev = NULL;
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001095 socket[i].socket.dev.parent = &ofdev->dev;
1096 socket[i].pcmcia = pcmcia;
1097 socket[i].bus_freq = ppc_proc_freq;
1098 socket[i].hwirq = hwirq;
1099
Marcelo Tosattide957c82005-10-28 17:46:13 -07001100 }
1101
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001102 for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
1103 status = pcmcia_register_socket(&socket[i].socket);
1104 if (status < 0)
1105 pcmcia_error("Socket register failed\n");
1106 }
Marcelo Tosattide957c82005-10-28 17:46:13 -07001107
1108 return 0;
1109}
1110
Grant Likely2dc11582010-08-06 09:25:50 -06001111static int m8xx_remove(struct platform_device *ofdev)
Marcelo Tosattide957c82005-10-28 17:46:13 -07001112{
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001113 u32 m, i;
1114 struct pcmcia_win *w;
1115 pcmconf8xx_t *pcmcia = socket[0].pcmcia;
Marcelo Tosattide957c82005-10-28 17:46:13 -07001116
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001117 for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
Vitaly Bordug99121c02007-07-17 04:03:37 -07001118 w = (void *)&pcmcia->pcmc_pbr0;
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001119
1120 out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(i));
1121 out_be32(&pcmcia->pcmc_per,
Vitaly Bordug99121c02007-07-17 04:03:37 -07001122 in_be32(&pcmcia->pcmc_per) & ~M8XX_PCMCIA_MASK(i));
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001123
1124 /* turn off interrupt and disable CxOE */
1125 out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE);
1126
1127 /* turn off memory windows */
1128 for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
Vitaly Bordug99121c02007-07-17 04:03:37 -07001129 out_be32(&w->or, 0); /* set to not valid */
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001130 w++;
1131 }
1132
1133 /* turn off voltage */
1134 voltage_set(i, 0, 0);
1135
1136 /* disable external hardware */
1137 hardware_disable(i);
1138 }
Marcelo Tosattide957c82005-10-28 17:46:13 -07001139 for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
1140 pcmcia_unregister_socket(&socket[i].socket);
Julia Lawall5a1c3e1a2008-02-04 22:27:44 -08001141 iounmap(pcmcia);
Marcelo Tosattide957c82005-10-28 17:46:13 -07001142
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001143 free_irq(pcmcia_schlvl, NULL);
Marcelo Tosattide957c82005-10-28 17:46:13 -07001144
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001145 return 0;
1146}
1147
Márton Németh63c9a8b2010-01-12 08:56:13 +01001148static const struct of_device_id m8xx_pcmcia_match[] = {
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001149 {
Vitaly Bordug99121c02007-07-17 04:03:37 -07001150 .type = "pcmcia",
1151 .compatible = "fsl,pq-pcmcia",
1152 },
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001153 {},
1154};
1155
1156MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match);
1157
Grant Likely1c48a5c2011-02-17 02:43:24 -07001158static struct platform_driver m8xx_pcmcia_driver = {
Grant Likely40182942010-04-13 16:13:02 -07001159 .driver = {
1160 .name = driver_name,
1161 .owner = THIS_MODULE,
Anatolij Gustschin2005ce32010-06-03 01:38:57 +02001162 .of_match_table = m8xx_pcmcia_match,
Grant Likely40182942010-04-13 16:13:02 -07001163 },
Vitaly Bordug99121c02007-07-17 04:03:37 -07001164 .probe = m8xx_probe,
1165 .remove = m8xx_remove,
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001166};
1167
Axel Lin5d95f8e22011-11-27 12:53:06 +08001168module_platform_driver(m8xx_pcmcia_driver);