1 /*
2  * drivers/pcmcia/sa1100_shannon.c
3  *
4  * PCMCIA implementation routines for Shannon
5  *
6  */
7 #include <linux/kernel.h>
8 #include <linux/sched.h>
9 
10 #include <asm/hardware.h>
11 #include <asm/arch/shannon.h>
12 #include <asm/irq.h>
13 #include "sa1100_generic.h"
14 
shannon_pcmcia_init(struct pcmcia_init * init)15 static int shannon_pcmcia_init(struct pcmcia_init *init)
16 {
17 	int irq, res;
18 
19 	/* All those are inputs */
20 	GPDR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 |
21 		  SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1);
22 	GAFR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 |
23 		  SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1);
24 
25 	/* Set transition detect */
26 	set_GPIO_IRQ_edge(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1, GPIO_NO_EDGES);
27 	set_GPIO_IRQ_edge(SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1, GPIO_FALLING_EDGE);
28 
29 	/* Register interrupts */
30 	irq = SHANNON_IRQ_GPIO_EJECT_0;
31 	res = request_irq(irq, init->handler, SA_INTERRUPT, "PCMCIA_CD_0", NULL);
32 	if (res < 0) goto irq_err;
33 	irq = SHANNON_IRQ_GPIO_EJECT_1;
34 	res = request_irq(irq, init->handler, SA_INTERRUPT, "PCMCIA_CD_1", NULL);
35 	if (res < 0) goto irq_err;
36 
37 	return 2;
38 irq_err:
39 	printk(KERN_ERR "%s: Request for IRQ %d failed\n", __FUNCTION__, irq);
40 	return -1;
41 }
42 
shannon_pcmcia_shutdown(void)43 static int shannon_pcmcia_shutdown(void)
44 {
45 	/* disable IRQs */
46 	free_irq(SHANNON_IRQ_GPIO_EJECT_0, NULL);
47 	free_irq(SHANNON_IRQ_GPIO_EJECT_1, NULL);
48 
49 	return 0;
50 }
51 
shannon_pcmcia_socket_state(struct pcmcia_state_array * state_array)52 static int shannon_pcmcia_socket_state(struct pcmcia_state_array *state_array)
53 {
54 	unsigned long levels;
55 
56 	memset(state_array->state, 0,
57 	       state_array->size * sizeof(struct pcmcia_state));
58 
59 	levels = GPLR;
60 
61 	state_array->state[0].detect = (levels & SHANNON_GPIO_EJECT_0) ? 0 : 1;
62 	state_array->state[0].ready  = (levels & SHANNON_GPIO_RDY_0) ? 1 : 0;
63 	state_array->state[0].wrprot = 0; /* Not available on Shannon. */
64 	state_array->state[0].bvd1 = 1;
65 	state_array->state[0].bvd2 = 1;
66 	state_array->state[0].vs_3v  = 1; /* FIXME Can only apply 3.3V on Shannon. */
67 	state_array->state[0].vs_Xv  = 0;
68 
69 	state_array->state[1].detect = (levels & SHANNON_GPIO_EJECT_1) ? 0 : 1;
70 	state_array->state[1].ready  = (levels & SHANNON_GPIO_RDY_1) ? 1 : 0;
71 	state_array->state[1].wrprot = 0; /* Not available on Shannon. */
72 	state_array->state[1].bvd1 = 1;
73 	state_array->state[1].bvd2 = 1;
74 	state_array->state[1].vs_3v  = 1; /* FIXME Can only apply 3.3V on Shannon. */
75 	state_array->state[1].vs_Xv  = 0;
76 
77 	return 1;
78 }
79 
shannon_pcmcia_get_irq_info(struct pcmcia_irq_info * info)80 static int shannon_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
81 {
82 	if (info->sock == 0)
83 		info->irq = SHANNON_IRQ_GPIO_RDY_0;
84 	else if (info->sock == 1)
85 		info->irq = SHANNON_IRQ_GPIO_RDY_1;
86 	else return -1;
87 
88 	return 0;
89 }
90 
shannon_pcmcia_configure_socket(const struct pcmcia_configure * configure)91 static int shannon_pcmcia_configure_socket(const struct pcmcia_configure *configure)
92 {
93 
94 	switch (configure->vcc) {
95 	case 0:	/* power off */;
96 		printk(KERN_WARNING __FUNCTION__"(): CS asked for 0V, still applying 3.3V..\n");
97 		break;
98 	case 50:
99 		printk(KERN_WARNING __FUNCTION__"(): CS asked for 5V, applying 3.3V..\n");
100 	case 33:
101 		break;
102 	default:
103 		printk(KERN_ERR __FUNCTION__"(): unrecognized Vcc %u\n",
104 		       configure->vcc);
105 		return -1;
106 	}
107 
108 	printk(KERN_WARNING __FUNCTION__"(): Warning, Can't perform reset\n");
109 
110 	/* Silently ignore Vpp, output enable, speaker enable. */
111 
112 	return 0;
113 }
114 
shannon_pcmcia_socket_init(int sock)115 static int shannon_pcmcia_socket_init(int sock)
116 {
117 	if (sock == 0)
118 		set_GPIO_IRQ_edge(SHANNON_GPIO_EJECT_0, GPIO_BOTH_EDGES);
119 	else if (sock == 1)
120 		set_GPIO_IRQ_edge(SHANNON_GPIO_EJECT_1, GPIO_BOTH_EDGES);
121 
122 	return 0;
123 }
124 
shannon_pcmcia_socket_suspend(int sock)125 static int shannon_pcmcia_socket_suspend(int sock)
126 {
127 	if (sock == 0)
128 		set_GPIO_IRQ_edge(SHANNON_GPIO_EJECT_0, GPIO_NO_EDGES);
129 	else if (sock == 1)
130 		set_GPIO_IRQ_edge(SHANNON_GPIO_EJECT_1, GPIO_NO_EDGES);
131 
132 	return 0;
133 }
134 
135 struct pcmcia_low_level shannon_pcmcia_ops = {
136 	init:			shannon_pcmcia_init,
137 	shutdown:		shannon_pcmcia_shutdown,
138 	socket_state:		shannon_pcmcia_socket_state,
139 	get_irq_info:		shannon_pcmcia_get_irq_info,
140 	configure_socket:	shannon_pcmcia_configure_socket,
141 
142 	socket_init:		shannon_pcmcia_socket_init,
143 	socket_suspend:		shannon_pcmcia_socket_suspend,
144 };
145