Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1/*
  2 *  drivers/pcmcia/m32r_pcc.c
  3 *
  4 *  Device driver for the PCMCIA functionality of M32R.
  5 *
  6 *  Copyright (c) 2001, 2002, 2003, 2004
  7 *    Hiroyuki Kondo, Naoto Sugai, Hayato Fujiwara
  8 */
  9
 10#include <linux/module.h>
 11#include <linux/moduleparam.h>
 12#include <linux/init.h>
 13#include <linux/types.h>
 14#include <linux/fcntl.h>
 15#include <linux/string.h>
 16#include <linux/kernel.h>
 17#include <linux/errno.h>
 18#include <linux/timer.h>
 19#include <linux/ioport.h>
 20#include <linux/delay.h>
 21#include <linux/workqueue.h>
 22#include <linux/interrupt.h>
 23#include <linux/platform_device.h>
 24#include <linux/bitops.h>
 25#include <asm/irq.h>
 26#include <asm/io.h>
 27#include <asm/addrspace.h>
 28
 29#include <pcmcia/ss.h>
 30
 31/* XXX: should be moved into asm/irq.h */
 32#define PCC0_IRQ 24
 33#define PCC1_IRQ 25
 34
 35#include "m32r_pcc.h"
 36
 37#define CHAOS_PCC_DEBUG
 38#ifdef CHAOS_PCC_DEBUG
 39	static volatile u_short dummy_readbuf;
 40#endif
 41
 42#define PCC_DEBUG_DBEX
 43
 44
 45/* Poll status interval -- 0 means default to interrupt */
 46static int poll_interval = 0;
 47
 48typedef enum pcc_space { as_none = 0, as_comm, as_attr, as_io } pcc_as_t;
 49
 50typedef struct pcc_socket {
 51	u_short			type, flags;
 52	struct pcmcia_socket	socket;
 53	unsigned int		number;
 54	unsigned int		ioaddr;
 55	u_long			mapaddr;
 56	u_long			base;	/* PCC register base */
 57	u_char			cs_irq, intr;
 58	pccard_io_map		io_map[MAX_IO_WIN];
 59	pccard_mem_map		mem_map[MAX_WIN];
 60	u_char			io_win;
 61	u_char			mem_win;
 62	pcc_as_t		current_space;
 63	u_char			last_iodbex;
 64#ifdef CHAOS_PCC_DEBUG
 65	u_char			last_iosize;
 66#endif
 67#ifdef CONFIG_PROC_FS
 68	struct proc_dir_entry *proc;
 69#endif
 70} pcc_socket_t;
 71
 72static int pcc_sockets = 0;
 73static pcc_socket_t socket[M32R_MAX_PCC] = {
 74	{ 0, }, /* ... */
 75};
 76
 77/*====================================================================*/
 78
 79static unsigned int pcc_get(u_short, unsigned int);
 80static void pcc_set(u_short, unsigned int , unsigned int );
 81
 82static DEFINE_SPINLOCK(pcc_lock);
 83
 84void pcc_iorw(int sock, unsigned long port, void *buf, size_t size, size_t nmemb, int wr, int flag)
 85{
 86	u_long addr;
 87	u_long flags;
 88	int need_ex;
 89#ifdef PCC_DEBUG_DBEX
 90	int _dbex;
 91#endif
 92	pcc_socket_t *t = &socket[sock];
 93#ifdef CHAOS_PCC_DEBUG
 94	int map_changed = 0;
 95#endif
 96
 97	/* Need lock ? */
 98	spin_lock_irqsave(&pcc_lock, flags);
 99
100	/*
101	 * Check if need dbex
102	 */
103	need_ex = (size > 1 && flag == 0) ? PCMOD_DBEX : 0;
104#ifdef PCC_DEBUG_DBEX
105	_dbex = need_ex;
106	need_ex = 0;
107#endif
108
109	/*
110	 * calculate access address
111	 */
112	addr = t->mapaddr + port - t->ioaddr + KSEG1; /* XXX */
113
114	/*
115	 * Check current mapping
116	 */
117	if (t->current_space != as_io || t->last_iodbex != need_ex) {
118
119		u_long cbsz;
120
121		/*
122		 * Disable first
123		 */
124		pcc_set(sock, PCCR, 0);
125
126		/*
127		 * Set mode and io address
128		 */
129		cbsz = (t->flags & MAP_16BIT) ? 0 : PCMOD_CBSZ;
130		pcc_set(sock, PCMOD, PCMOD_AS_IO | cbsz | need_ex);
131		pcc_set(sock, PCADR, addr & 0x1ff00000);
132
133		/*
134		 * Enable and read it
135		 */
136		pcc_set(sock, PCCR, 1);
137
138#ifdef CHAOS_PCC_DEBUG
139#if 0
140		map_changed = (t->current_space == as_attr && size == 2); /* XXX */
141#else
142		map_changed = 1;
143#endif
144#endif
145		t->current_space = as_io;
146	}
147
148	/*
149	 * access to IO space
150	 */
151	if (size == 1) {
152		/* Byte */
153		unsigned char *bp = (unsigned char *)buf;
154
155#ifdef CHAOS_DEBUG
156		if (map_changed) {
157			dummy_readbuf = readb(addr);
158		}
159#endif
160		if (wr) {
161			/* write Byte */
162			while (nmemb--) {
163				writeb(*bp++, addr);
164			}
165		} else {
166			/* read Byte */
167			while (nmemb--) {
168	    		*bp++ = readb(addr);
169			}
170		}
171	} else {
172		/* Word */
173		unsigned short *bp = (unsigned short *)buf;
174
175#ifdef CHAOS_PCC_DEBUG
176		if (map_changed) {
177			dummy_readbuf = readw(addr);
178		}
179#endif
180		if (wr) {
181			/* write Word */
182			while (nmemb--) {
183#ifdef PCC_DEBUG_DBEX
184				if (_dbex) {
185					unsigned char *cp = (unsigned char *)bp;
186					unsigned short tmp;
187					tmp = cp[1] << 8 | cp[0];
188					writew(tmp, addr);
189					bp++;
190				} else
191#endif
192				writew(*bp++, addr);
193	    	}
194	    } else {
195	    	/* read Word */
196	    	while (nmemb--) {
197#ifdef  PCC_DEBUG_DBEX
198				if (_dbex) {
199					unsigned char *cp = (unsigned char *)bp;
200					unsigned short tmp;
201					tmp = readw(addr);
202					cp[0] = tmp & 0xff;
203					cp[1] = (tmp >> 8) & 0xff;
204					bp++;
205				} else
206#endif
207				*bp++ = readw(addr);
208	    	}
209	    }
210	}
211
212#if 1
213	/* addr is no longer used */
214	if ((addr = pcc_get(sock, PCIRC)) & PCIRC_BWERR) {
215	  printk("m32r_pcc: BWERR detected : port 0x%04lx : iosize %dbit\n",
216			 port, size * 8);
217	  pcc_set(sock, PCIRC, addr);
218	}
219#endif
220	/*
221	 * save state
222	 */
223	t->last_iosize = size;
224	t->last_iodbex = need_ex;
225
226	/* Need lock ? */
227
228	spin_unlock_irqrestore(&pcc_lock,flags);
229
230	return;
231}
232
233void pcc_ioread(int sock, unsigned long port, void *buf, size_t size, size_t nmemb, int flag) {
234	pcc_iorw(sock, port, buf, size, nmemb, 0, flag);
235}
236
237void pcc_iowrite(int sock, unsigned long port, void *buf, size_t size, size_t nmemb, int flag) {
238    pcc_iorw(sock, port, buf, size, nmemb, 1, flag);
239}
240
241/*====================================================================*/
242
243#define IS_REGISTERED		0x2000
244#define IS_ALIVE		0x8000
245
246typedef struct pcc_t {
247	char			*name;
248	u_short			flags;
249} pcc_t;
250
251static pcc_t pcc[] = {
252	{ "xnux2", 0 }, { "xnux2", 0 },
253};
254
255static irqreturn_t pcc_interrupt(int, void *);
256
257/*====================================================================*/
258
259static struct timer_list poll_timer;
260
261static unsigned int pcc_get(u_short sock, unsigned int reg)
262{
263	return inl(socket[sock].base + reg);
264}
265
266
267static void pcc_set(u_short sock, unsigned int reg, unsigned int data)
268{
269  	outl(data, socket[sock].base + reg);
270}
271
272/*======================================================================
273
274	See if a card is present, powered up, in IO mode, and already
275	bound to a (non PC Card) Linux driver.  We leave these alone.
276
277	We make an exception for cards that seem to be serial devices.
278
279======================================================================*/
280
281static int __init is_alive(u_short sock)
282{
283	unsigned int stat;
284	unsigned int f;
285
286	stat = pcc_get(sock, PCIRC);
287	f = (stat & (PCIRC_CDIN1 | PCIRC_CDIN2)) >> 16;
288	if(!f){
289		printk("m32r_pcc: No Card is detected at socket %d : stat = 0x%08x\n",stat,sock);
290		return 0;
291	}
292	if(f!=3)
293		printk("m32r_pcc: Insertion fail (%.8x) at socket %d\n",stat,sock);
294	else
295		printk("m32r_pcc: Card is Inserted at socket %d(%.8x)\n",sock,stat);
296	return 0;
297}
298
299static void add_pcc_socket(ulong base, int irq, ulong mapaddr,
300			   unsigned int ioaddr)
301{
302  	pcc_socket_t *t = &socket[pcc_sockets];
303
304	/* add sockets */
305	t->ioaddr = ioaddr;
306	t->mapaddr = mapaddr;
307	t->base = base;
308#ifdef CHAOS_PCC_DEBUG
309	t->flags = MAP_16BIT;
310#else
311	t->flags = 0;
312#endif
313	if (is_alive(pcc_sockets))
314		t->flags |= IS_ALIVE;
315
316	/* add pcc */
317	if (t->base > 0) {
318		request_region(t->base, 0x20, "m32r-pcc");
319	}
320
321	printk(KERN_INFO "  %s ", pcc[pcc_sockets].name);
322	printk("pcc at 0x%08lx\n", t->base);
323
324	/* Update socket interrupt information, capabilities */
325	t->socket.features |= (SS_CAP_PCCARD | SS_CAP_STATIC_MAP);
326	t->socket.map_size = M32R_PCC_MAPSIZE;
327	t->socket.io_offset = ioaddr;	/* use for io access offset */
328	t->socket.irq_mask = 0;
329	t->socket.pci_irq = 2 + pcc_sockets; /* XXX */
330
331	request_irq(irq, pcc_interrupt, 0, "m32r-pcc", pcc_interrupt);
332
333	pcc_sockets++;
334
335	return;
336}
337
338
339/*====================================================================*/
340
341static irqreturn_t pcc_interrupt(int irq, void *dev)
342{
343	int i, j, irc;
344	u_int events, active;
345	int handled = 0;
346
347	pr_debug("m32r_pcc: pcc_interrupt(%d)\n", irq);
348
349	for (j = 0; j < 20; j++) {
350		active = 0;
351		for (i = 0; i < pcc_sockets; i++) {
352			if ((socket[i].cs_irq != irq) &&
353				(socket[i].socket.pci_irq != irq))
354				continue;
355			handled = 1;
356			irc = pcc_get(i, PCIRC);
357			irc >>=16;
358			pr_debug("m32r_pcc: interrupt: socket %d pcirc 0x%02x ",
359				i, irc);
360			if (!irc)
361				continue;
362
363			events = (irc) ? SS_DETECT : 0;
364			events |= (pcc_get(i,PCCR) & PCCR_PCEN) ? SS_READY : 0;
365			pr_debug("m32r_pcc: event 0x%02x\n", events);
366
367			if (events)
368				pcmcia_parse_events(&socket[i].socket, events);
369
370			active |= events;
371			active = 0;
372		}
373		if (!active) break;
374	}
375	if (j == 20)
376		printk(KERN_NOTICE "m32r-pcc: infinite loop in interrupt handler\n");
377
378	pr_debug("m32r_pcc: interrupt done\n");
379
380	return IRQ_RETVAL(handled);
381} /* pcc_interrupt */
382
383static void pcc_interrupt_wrapper(u_long data)
384{
385	pcc_interrupt(0, NULL);
386	init_timer(&poll_timer);
387	poll_timer.expires = jiffies + poll_interval;
388	add_timer(&poll_timer);
389}
390
391/*====================================================================*/
392
393static int _pcc_get_status(u_short sock, u_int *value)
394{
395	u_int status;
396
397	status = pcc_get(sock,PCIRC);
398	*value = ((status & PCIRC_CDIN1) && (status & PCIRC_CDIN2))
399		? SS_DETECT : 0;
400
401	status = pcc_get(sock,PCCR);
402
403#if 0
404	*value |= (status & PCCR_PCEN) ? SS_READY : 0;
405#else
406	*value |= SS_READY; /* XXX: always */
407#endif
408
409	status = pcc_get(sock,PCCSIGCR);
410	*value |= (status & PCCSIGCR_VEN) ? SS_POWERON : 0;
411
412	pr_debug("m32r_pcc: GetStatus(%d) = %#4.4x\n", sock, *value);
413	return 0;
414} /* _get_status */
415
416/*====================================================================*/
417
418static int _pcc_set_socket(u_short sock, socket_state_t *state)
419{
420	u_long reg = 0;
421
422	pr_debug("m32r_pcc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
423		  "io_irq %d, csc_mask %#2.2x)", sock, state->flags,
424		  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
425
426	if (state->Vcc) {
427		/*
428		 * 5V only
429		 */
430		if (state->Vcc == 50) {
431			reg |= PCCSIGCR_VEN;
432		} else {
433			return -EINVAL;
434		}
435	}
436
437	if (state->flags & SS_RESET) {
438		pr_debug("m32r_pcc: :RESET\n");
439		reg |= PCCSIGCR_CRST;
440	}
441	if (state->flags & SS_OUTPUT_ENA){
442		pr_debug("m32r_pcc: :OUTPUT_ENA\n");
443		/* bit clear */
444	} else {
445		reg |= PCCSIGCR_SEN;
446	}
447
448	pcc_set(sock,PCCSIGCR,reg);
449
450	if(state->flags & SS_IOCARD){
451		pr_debug("m32r_pcc: :IOCARD");
452	}
453	if (state->flags & SS_PWR_AUTO) {
454		pr_debug("m32r_pcc: :PWR_AUTO");
455	}
456	if (state->csc_mask & SS_DETECT)
457		pr_debug("m32r_pcc: :csc-SS_DETECT");
458	if (state->flags & SS_IOCARD) {
459		if (state->csc_mask & SS_STSCHG)
460			pr_debug("m32r_pcc: :STSCHG");
461	} else {
462		if (state->csc_mask & SS_BATDEAD)
463			pr_debug("m32r_pcc: :BATDEAD");
464		if (state->csc_mask & SS_BATWARN)
465			pr_debug("m32r_pcc: :BATWARN");
466		if (state->csc_mask & SS_READY)
467			pr_debug("m32r_pcc: :READY");
468	}
469	pr_debug("m32r_pcc: \n");
470	return 0;
471} /* _set_socket */
472
473/*====================================================================*/
474
475static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io)
476{
477	u_char map;
478
479	pr_debug("m32r_pcc: SetIOMap(%d, %d, %#2.2x, %d ns, "
480		  "%#llx-%#llx)\n", sock, io->map, io->flags,
481		  io->speed, (unsigned long long)io->start,
482		  (unsigned long long)io->stop);
483	map = io->map;
484
485	return 0;
486} /* _set_io_map */
487
488/*====================================================================*/
489
490static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem)
491{
492
493	u_char map = mem->map;
494	u_long mode;
495	u_long addr;
496	pcc_socket_t *t = &socket[sock];
497#ifdef CHAOS_PCC_DEBUG
498#if 0
499	pcc_as_t last = t->current_space;
500#endif
501#endif
502
503	pr_debug("m32r_pcc: SetMemMap(%d, %d, %#2.2x, %d ns, "
504		 "%#llx,  %#x)\n", sock, map, mem->flags,
505		 mem->speed, (unsigned long long)mem->static_start,
506		 mem->card_start);
507
508	/*
509	 * sanity check
510	 */
511	if ((map > MAX_WIN) || (mem->card_start > 0x3ffffff)){
512		return -EINVAL;
513	}
514
515	/*
516	 * de-activate
517	 */
518	if ((mem->flags & MAP_ACTIVE) == 0) {
519		t->current_space = as_none;
520		return 0;
521	}
522
523	/*
524	 * Disable first
525	 */
526	pcc_set(sock, PCCR, 0);
527
528	/*
529	 * Set mode
530	 */
531	if (mem->flags & MAP_ATTRIB) {
532		mode = PCMOD_AS_ATTRIB | PCMOD_CBSZ;
533		t->current_space = as_attr;
534	} else {
535		mode = 0; /* common memory */
536		t->current_space = as_comm;
537	}
538	pcc_set(sock, PCMOD, mode);
539
540	/*
541	 * Set address
542	 */
543	addr = t->mapaddr + (mem->card_start & M32R_PCC_MAPMASK);
544	pcc_set(sock, PCADR, addr);
545
546	mem->static_start = addr + mem->card_start;
547
548	/*
549	 * Enable again
550	 */
551	pcc_set(sock, PCCR, 1);
552
553#ifdef CHAOS_PCC_DEBUG
554#if 0
555	if (last != as_attr) {
556#else
557	if (1) {
558#endif
559		dummy_readbuf = *(u_char *)(addr + KSEG1);
560	}
561#endif
562
563	return 0;
564
565} /* _set_mem_map */
566
567#if 0 /* driver model ordering issue */
568/*======================================================================
569
570	Routines for accessing socket information and register dumps via
571	/proc/bus/pccard/...
572
573======================================================================*/
574
575static ssize_t show_info(struct class_device *class_dev, char *buf)
576{
577	pcc_socket_t *s = container_of(class_dev, struct pcc_socket,
578		socket.dev);
579
580	return sprintf(buf, "type:     %s\nbase addr:    0x%08lx\n",
581		pcc[s->type].name, s->base);
582}
583
584static ssize_t show_exca(struct class_device *class_dev, char *buf)
585{
586	/* FIXME */
587
588	return 0;
589}
590
591static CLASS_DEVICE_ATTR(info, S_IRUGO, show_info, NULL);
592static CLASS_DEVICE_ATTR(exca, S_IRUGO, show_exca, NULL);
593#endif
594
595/*====================================================================*/
596
597/* this is horribly ugly... proper locking needs to be done here at
598 * some time... */
599#define LOCKED(x) do {					\
600	int retval;					\
601	unsigned long flags;				\
602	spin_lock_irqsave(&pcc_lock, flags);		\
603	retval = x;					\
604	spin_unlock_irqrestore(&pcc_lock, flags);	\
605	return retval;					\
606} while (0)
607
608
609static int pcc_get_status(struct pcmcia_socket *s, u_int *value)
610{
611	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
612
613	if (socket[sock].flags & IS_ALIVE) {
614		*value = 0;
615		return -EINVAL;
616	}
617	LOCKED(_pcc_get_status(sock, value));
618}
619
620static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state)
621{
622	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
623
624	if (socket[sock].flags & IS_ALIVE)
625		return -EINVAL;
626
627	LOCKED(_pcc_set_socket(sock, state));
628}
629
630static int pcc_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
631{
632	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
633
634	if (socket[sock].flags & IS_ALIVE)
635		return -EINVAL;
636	LOCKED(_pcc_set_io_map(sock, io));
637}
638
639static int pcc_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
640{
641	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
642
643	if (socket[sock].flags & IS_ALIVE)
644		return -EINVAL;
645	LOCKED(_pcc_set_mem_map(sock, mem));
646}
647
648static int pcc_init(struct pcmcia_socket *s)
649{
650	pr_debug("m32r_pcc: init call\n");
651	return 0;
652}
653
654static struct pccard_operations pcc_operations = {
655	.init			= pcc_init,
656	.get_status		= pcc_get_status,
657	.set_socket		= pcc_set_socket,
658	.set_io_map		= pcc_set_io_map,
659	.set_mem_map		= pcc_set_mem_map,
660};
661
662/*====================================================================*/
663
664static struct platform_driver pcc_driver = {
665	.driver = {
666		.name		= "pcc",
667	},
668};
669
670static struct platform_device pcc_device = {
671	.name = "pcc",
672	.id = 0,
673};
674
675/*====================================================================*/
676
677static int __init init_m32r_pcc(void)
678{
679	int i, ret;
680
681	ret = platform_driver_register(&pcc_driver);
682	if (ret)
683		return ret;
684
685	ret = platform_device_register(&pcc_device);
686	if (ret){
687		platform_driver_unregister(&pcc_driver);
688		return ret;
689	}
690
691	printk(KERN_INFO "m32r PCC probe:\n");
692
693	pcc_sockets = 0;
694
695	add_pcc_socket(M32R_PCC0_BASE, PCC0_IRQ, M32R_PCC0_MAPBASE, 0x1000);
696
697#ifdef CONFIG_M32RPCC_SLOT2
698	add_pcc_socket(M32R_PCC1_BASE, PCC1_IRQ, M32R_PCC1_MAPBASE, 0x2000);
699#endif
700
701	if (pcc_sockets == 0) {
702		printk("socket is not found.\n");
703		platform_device_unregister(&pcc_device);
704		platform_driver_unregister(&pcc_driver);
705		return -ENODEV;
706	}
707
708	/* Set up interrupt handler(s) */
709
710	for (i = 0 ; i < pcc_sockets ; i++) {
711		socket[i].socket.dev.parent = &pcc_device.dev;
712		socket[i].socket.ops = &pcc_operations;
713		socket[i].socket.resource_ops = &pccard_static_ops;
714		socket[i].socket.owner = THIS_MODULE;
715		socket[i].number = i;
716		ret = pcmcia_register_socket(&socket[i].socket);
717		if (!ret)
718			socket[i].flags |= IS_REGISTERED;
719	}
720
721	/* Finally, schedule a polling interrupt */
722	if (poll_interval != 0) {
723		poll_timer.function = pcc_interrupt_wrapper;
724		poll_timer.data = 0;
725		init_timer(&poll_timer);
726		poll_timer.expires = jiffies + poll_interval;
727		add_timer(&poll_timer);
728	}
729
730	return 0;
731} /* init_m32r_pcc */
732
733static void __exit exit_m32r_pcc(void)
734{
735	int i;
736
737	for (i = 0; i < pcc_sockets; i++)
738		if (socket[i].flags & IS_REGISTERED)
739			pcmcia_unregister_socket(&socket[i].socket);
740
741	platform_device_unregister(&pcc_device);
742	if (poll_interval != 0)
743		del_timer_sync(&poll_timer);
744
745	platform_driver_unregister(&pcc_driver);
746} /* exit_m32r_pcc */
747
748module_init(init_m32r_pcc);
749module_exit(exit_m32r_pcc);
750MODULE_LICENSE("Dual MPL/GPL");
751/*====================================================================*/