1*433d6423SLionel Sambuc /* kernel headers */
2*433d6423SLionel Sambuc #include <minix/syslib.h>
3*433d6423SLionel Sambuc #include <minix/drvlib.h>
4*433d6423SLionel Sambuc #include <minix/log.h>
5*433d6423SLionel Sambuc #include <minix/mmio.h>
6*433d6423SLionel Sambuc #include <minix/gpio.h>
7*433d6423SLionel Sambuc #include <minix/clkconf.h>
8*433d6423SLionel Sambuc #include <minix/type.h>
9*433d6423SLionel Sambuc #include <minix/board.h>
10*433d6423SLionel Sambuc
11*433d6423SLionel Sambuc /* system headers */
12*433d6423SLionel Sambuc #include <sys/mman.h>
13*433d6423SLionel Sambuc #include <sys/types.h>
14*433d6423SLionel Sambuc
15*433d6423SLionel Sambuc /* usr headers */
16*433d6423SLionel Sambuc #include <stdio.h>
17*433d6423SLionel Sambuc #include <stdlib.h>
18*433d6423SLionel Sambuc #include <stdarg.h>
19*433d6423SLionel Sambuc #include <string.h>
20*433d6423SLionel Sambuc #include <errno.h>
21*433d6423SLionel Sambuc #include <assert.h>
22*433d6423SLionel Sambuc
23*433d6423SLionel Sambuc /* local headers */
24*433d6423SLionel Sambuc #include "gpio_omap.h"
25*433d6423SLionel Sambuc
26*433d6423SLionel Sambuc /* used for logging */
27*433d6423SLionel Sambuc static struct log log = {
28*433d6423SLionel Sambuc .name = "gpio_omap",
29*433d6423SLionel Sambuc .log_level = LEVEL_INFO,
30*433d6423SLionel Sambuc .log_func = default_log
31*433d6423SLionel Sambuc };
32*433d6423SLionel Sambuc
33*433d6423SLionel Sambuc struct gpio_driver
34*433d6423SLionel Sambuc {
35*433d6423SLionel Sambuc /* request access to a gpio */
36*433d6423SLionel Sambuc int (*claim) (char *owner, int nr, struct gpio ** gpio);
37*433d6423SLionel Sambuc
38*433d6423SLionel Sambuc /* Configure the GPIO for a certain purpose */
39*433d6423SLionel Sambuc int (*pin_mode) (struct gpio * gpio, int mode);
40*433d6423SLionel Sambuc
41*433d6423SLionel Sambuc /* Set the value for a GPIO */
42*433d6423SLionel Sambuc int (*set) (struct gpio * gpio, int value);
43*433d6423SLionel Sambuc
44*433d6423SLionel Sambuc /* Read the current value of the GPIO */
45*433d6423SLionel Sambuc int (*read) (struct gpio * gpio, int *value);
46*433d6423SLionel Sambuc
47*433d6423SLionel Sambuc /* Read and clear the value interrupt value of the GPIO */
48*433d6423SLionel Sambuc int (*intr_read) (struct gpio * gpio, int *value);
49*433d6423SLionel Sambuc
50*433d6423SLionel Sambuc /* Interrupt hook */
51*433d6423SLionel Sambuc int (*message_hook) (message * m);
52*433d6423SLionel Sambuc };
53*433d6423SLionel Sambuc
54*433d6423SLionel Sambuc static struct gpio_driver drv;
55*433d6423SLionel Sambuc
56*433d6423SLionel Sambuc struct omap_gpio_bank
57*433d6423SLionel Sambuc {
58*433d6423SLionel Sambuc const char *name;
59*433d6423SLionel Sambuc uint32_t register_address;
60*433d6423SLionel Sambuc uint32_t irq_nr; /* irq number */
61*433d6423SLionel Sambuc uint32_t base_address;
62*433d6423SLionel Sambuc int32_t disabled;
63*433d6423SLionel Sambuc int irq_id; /* original hook id??? */
64*433d6423SLionel Sambuc int irq_hook_id; /* hook id */
65*433d6423SLionel Sambuc uint32_t inter_values; /* values when the interrupt was called */
66*433d6423SLionel Sambuc };
67*433d6423SLionel Sambuc
68*433d6423SLionel Sambuc static struct omap_gpio_bank *omap_gpio_banks;
69*433d6423SLionel Sambuc
70*433d6423SLionel Sambuc static struct omap_gpio_bank am335x_gpio_banks[] = {
71*433d6423SLionel Sambuc {
72*433d6423SLionel Sambuc .name = "GPIO0",
73*433d6423SLionel Sambuc .register_address = AM335X_GPIO0_BASE,
74*433d6423SLionel Sambuc .irq_nr = AM335X_GPIO0A_IRQ,
75*433d6423SLionel Sambuc .base_address = 0,
76*433d6423SLionel Sambuc .disabled = 0,
77*433d6423SLionel Sambuc .irq_id = AM335X_GPIO0A_IRQ_HOOK_ID,
78*433d6423SLionel Sambuc .irq_hook_id = AM335X_GPIO0A_IRQ_HOOK_ID,
79*433d6423SLionel Sambuc
80*433d6423SLionel Sambuc },
81*433d6423SLionel Sambuc {
82*433d6423SLionel Sambuc .name = "GPIO1",
83*433d6423SLionel Sambuc .register_address = AM335X_GPIO1_BASE,
84*433d6423SLionel Sambuc .irq_nr = AM335X_GPIO1A_IRQ,
85*433d6423SLionel Sambuc .base_address = 0,
86*433d6423SLionel Sambuc .disabled = 0,
87*433d6423SLionel Sambuc .irq_id = AM335X_GPIO1A_IRQ_HOOK_ID,
88*433d6423SLionel Sambuc .irq_hook_id = AM335X_GPIO1A_IRQ_HOOK_ID,
89*433d6423SLionel Sambuc
90*433d6423SLionel Sambuc },
91*433d6423SLionel Sambuc {
92*433d6423SLionel Sambuc .name = "GPIO2",
93*433d6423SLionel Sambuc .register_address = AM335X_GPIO2_BASE,
94*433d6423SLionel Sambuc .irq_nr = AM335X_GPIO2A_IRQ,
95*433d6423SLionel Sambuc .base_address = 0,
96*433d6423SLionel Sambuc .disabled = 0,
97*433d6423SLionel Sambuc .irq_id = AM335X_GPIO2A_IRQ_HOOK_ID,
98*433d6423SLionel Sambuc .irq_hook_id = AM335X_GPIO2A_IRQ_HOOK_ID,
99*433d6423SLionel Sambuc
100*433d6423SLionel Sambuc },
101*433d6423SLionel Sambuc {
102*433d6423SLionel Sambuc .name = "GPIO3",
103*433d6423SLionel Sambuc .register_address = AM335X_GPIO3_BASE,
104*433d6423SLionel Sambuc .irq_nr = AM335X_GPIO3A_IRQ,
105*433d6423SLionel Sambuc .base_address = 0,
106*433d6423SLionel Sambuc .disabled = 0,
107*433d6423SLionel Sambuc .irq_id = AM335X_GPIO3A_IRQ_HOOK_ID,
108*433d6423SLionel Sambuc .irq_hook_id = AM335X_GPIO3A_IRQ_HOOK_ID,
109*433d6423SLionel Sambuc
110*433d6423SLionel Sambuc },
111*433d6423SLionel Sambuc {NULL, 0, 0, 0, 0, 0, 0, 0 }
112*433d6423SLionel Sambuc };
113*433d6423SLionel Sambuc
114*433d6423SLionel Sambuc static struct omap_gpio_bank dm37xx_gpio_banks[] = {
115*433d6423SLionel Sambuc {
116*433d6423SLionel Sambuc .name = "GPIO1",
117*433d6423SLionel Sambuc .register_address = DM37XX_GPIO1_BASE,
118*433d6423SLionel Sambuc .irq_nr = DM37XX_GPIO1_IRQ,
119*433d6423SLionel Sambuc .base_address = 0,
120*433d6423SLionel Sambuc .disabled = 0,
121*433d6423SLionel Sambuc .irq_id = DM37XX_GPIO1_IRQ_HOOK_ID,
122*433d6423SLionel Sambuc .irq_hook_id = DM37XX_GPIO1_IRQ_HOOK_ID,
123*433d6423SLionel Sambuc },
124*433d6423SLionel Sambuc {
125*433d6423SLionel Sambuc .name = "GPIO2",
126*433d6423SLionel Sambuc .register_address = DM37XX_GPIO2_BASE,
127*433d6423SLionel Sambuc .irq_nr = DM37XX_GPIO2_IRQ,
128*433d6423SLionel Sambuc .base_address = 0,
129*433d6423SLionel Sambuc .disabled = 0,
130*433d6423SLionel Sambuc .irq_id = DM37XX_GPIO2_IRQ_HOOK_ID,
131*433d6423SLionel Sambuc .irq_hook_id = DM37XX_GPIO2_IRQ_HOOK_ID,
132*433d6423SLionel Sambuc },
133*433d6423SLionel Sambuc {
134*433d6423SLionel Sambuc .name = "GPIO3",
135*433d6423SLionel Sambuc .register_address = DM37XX_GPIO3_BASE,
136*433d6423SLionel Sambuc .irq_nr = DM37XX_GPIO3_IRQ,
137*433d6423SLionel Sambuc .base_address = 0,
138*433d6423SLionel Sambuc .disabled = 0,
139*433d6423SLionel Sambuc .irq_id = DM37XX_GPIO3_IRQ_HOOK_ID,
140*433d6423SLionel Sambuc .irq_hook_id = DM37XX_GPIO3_IRQ_HOOK_ID,
141*433d6423SLionel Sambuc },
142*433d6423SLionel Sambuc {
143*433d6423SLionel Sambuc .name = "GPIO4",
144*433d6423SLionel Sambuc .register_address = DM37XX_GPIO4_BASE,
145*433d6423SLionel Sambuc .irq_nr = DM37XX_GPIO4_IRQ,
146*433d6423SLionel Sambuc .base_address = 0,
147*433d6423SLionel Sambuc .disabled = 0,
148*433d6423SLionel Sambuc .irq_id = DM37XX_GPIO4_IRQ_HOOK_ID,
149*433d6423SLionel Sambuc .irq_hook_id = DM37XX_GPIO4_IRQ_HOOK_ID,
150*433d6423SLionel Sambuc },
151*433d6423SLionel Sambuc {
152*433d6423SLionel Sambuc .name = "GPIO5",
153*433d6423SLionel Sambuc .register_address = DM37XX_GPIO5_BASE,
154*433d6423SLionel Sambuc .irq_nr = DM37XX_GPIO5_IRQ,
155*433d6423SLionel Sambuc .base_address = 0,
156*433d6423SLionel Sambuc .disabled = 0,
157*433d6423SLionel Sambuc .irq_id = DM37XX_GPIO5_IRQ_HOOK_ID,
158*433d6423SLionel Sambuc .irq_hook_id = DM37XX_GPIO5_IRQ_HOOK_ID,
159*433d6423SLionel Sambuc },
160*433d6423SLionel Sambuc {
161*433d6423SLionel Sambuc .name = "GPIO6",
162*433d6423SLionel Sambuc .register_address = DM37XX_GPIO6_BASE,
163*433d6423SLionel Sambuc .irq_nr = DM37XX_GPIO6_IRQ,
164*433d6423SLionel Sambuc .base_address = 0,
165*433d6423SLionel Sambuc .disabled = 0,
166*433d6423SLionel Sambuc .irq_id = DM37XX_GPIO6_IRQ_HOOK_ID,
167*433d6423SLionel Sambuc .irq_hook_id = DM37XX_GPIO6_IRQ_HOOK_ID,
168*433d6423SLionel Sambuc },
169*433d6423SLionel Sambuc {NULL, 0, 0, 0, 0, 0, 0, 0 }
170*433d6423SLionel Sambuc };
171*433d6423SLionel Sambuc
172*433d6423SLionel Sambuc static int nbanks; /* number of banks */
173*433d6423SLionel Sambuc
174*433d6423SLionel Sambuc /*
175*433d6423SLionel Sambuc * Defines the set of registers. There is a lot of commonality between the
176*433d6423SLionel Sambuc * AM335X and DM37XX gpio registers. To avoid ifdefs everywhere, we define
177*433d6423SLionel Sambuc * a central register set and only use ifdefs where they differ.
178*433d6423SLionel Sambuc */
179*433d6423SLionel Sambuc typedef struct gpio_omap_registers {
180*433d6423SLionel Sambuc vir_bytes REVISION;
181*433d6423SLionel Sambuc vir_bytes IRQENABLE;
182*433d6423SLionel Sambuc vir_bytes IRQSTATUS;
183*433d6423SLionel Sambuc vir_bytes DATAOUT;
184*433d6423SLionel Sambuc vir_bytes DATAIN;
185*433d6423SLionel Sambuc vir_bytes OE;
186*433d6423SLionel Sambuc vir_bytes RISINGDETECT;
187*433d6423SLionel Sambuc vir_bytes FALLINGDETECT;
188*433d6423SLionel Sambuc vir_bytes CLEARDATAOUT;
189*433d6423SLionel Sambuc vir_bytes SETDATAOUT;
190*433d6423SLionel Sambuc } gpio_omap_regs_t;
191*433d6423SLionel Sambuc
192*433d6423SLionel Sambuc /* Define the registers for each chip */
193*433d6423SLionel Sambuc
194*433d6423SLionel Sambuc gpio_omap_regs_t gpio_omap_dm37xx = {
195*433d6423SLionel Sambuc .REVISION = DM37XX_GPIO_REVISION,
196*433d6423SLionel Sambuc .IRQENABLE = DM37XX_GPIO_IRQENABLE1,
197*433d6423SLionel Sambuc .IRQSTATUS = DM37XX_GPIO_IRQSTATUS1,
198*433d6423SLionel Sambuc .DATAOUT = DM37XX_GPIO_DATAOUT,
199*433d6423SLionel Sambuc .DATAIN = DM37XX_GPIO_DATAIN,
200*433d6423SLionel Sambuc .OE = DM37XX_GPIO_OE,
201*433d6423SLionel Sambuc .RISINGDETECT = DM37XX_GPIO_RISINGDETECT1,
202*433d6423SLionel Sambuc .FALLINGDETECT = DM37XX_GPIO_FALLINGDETECT1,
203*433d6423SLionel Sambuc .CLEARDATAOUT = DM37XX_GPIO_CLEARDATAOUT,
204*433d6423SLionel Sambuc .SETDATAOUT = DM37XX_GPIO_SETDATAOUT
205*433d6423SLionel Sambuc };
206*433d6423SLionel Sambuc
207*433d6423SLionel Sambuc gpio_omap_regs_t gpio_omap_am335x = {
208*433d6423SLionel Sambuc .REVISION = AM335X_GPIO_REVISION,
209*433d6423SLionel Sambuc .IRQENABLE = AM335X_GPIO_IRQSTATUS_SET_0,
210*433d6423SLionel Sambuc .IRQSTATUS = AM335X_GPIO_IRQSTATUS_0,
211*433d6423SLionel Sambuc .DATAOUT = AM335X_GPIO_DATAOUT,
212*433d6423SLionel Sambuc .DATAIN = AM335X_GPIO_DATAIN,
213*433d6423SLionel Sambuc .OE = AM335X_GPIO_OE,
214*433d6423SLionel Sambuc .RISINGDETECT = AM335X_GPIO_RISINGDETECT,
215*433d6423SLionel Sambuc .FALLINGDETECT = AM335X_GPIO_FALLINGDETECT,
216*433d6423SLionel Sambuc .CLEARDATAOUT = AM335X_GPIO_CLEARDATAOUT,
217*433d6423SLionel Sambuc .SETDATAOUT = AM335X_GPIO_SETDATAOUT
218*433d6423SLionel Sambuc };
219*433d6423SLionel Sambuc
220*433d6423SLionel Sambuc static gpio_omap_regs_t *regs;
221*433d6423SLionel Sambuc
222*433d6423SLionel Sambuc
223*433d6423SLionel Sambuc static struct omap_gpio_bank *
omap_gpio_bank_get(int gpio_nr)224*433d6423SLionel Sambuc omap_gpio_bank_get(int gpio_nr)
225*433d6423SLionel Sambuc {
226*433d6423SLionel Sambuc struct omap_gpio_bank *bank;
227*433d6423SLionel Sambuc assert(gpio_nr >= 0 && gpio_nr <= 32 * nbanks);
228*433d6423SLionel Sambuc bank = &omap_gpio_banks[gpio_nr / 32];
229*433d6423SLionel Sambuc return bank;
230*433d6423SLionel Sambuc }
231*433d6423SLionel Sambuc
232*433d6423SLionel Sambuc static int
omap_gpio_claim(char * owner,int nr,struct gpio ** gpio)233*433d6423SLionel Sambuc omap_gpio_claim(char *owner, int nr, struct gpio **gpio)
234*433d6423SLionel Sambuc {
235*433d6423SLionel Sambuc log_trace(&log, "%s s claiming %d\n", owner, nr);
236*433d6423SLionel Sambuc
237*433d6423SLionel Sambuc if (nr < 0 && nr >= 32 * nbanks) {
238*433d6423SLionel Sambuc log_warn(&log, "%s is claiming unknown GPIO number %d\n",
239*433d6423SLionel Sambuc owner, nr);
240*433d6423SLionel Sambuc return EINVAL;
241*433d6423SLionel Sambuc }
242*433d6423SLionel Sambuc
243*433d6423SLionel Sambuc if (omap_gpio_bank_get(nr)->disabled == 1) {
244*433d6423SLionel Sambuc log_warn(&log, "%s is claiming GPIO %d from disabled bank\n",
245*433d6423SLionel Sambuc owner, nr);
246*433d6423SLionel Sambuc return EINVAL;
247*433d6423SLionel Sambuc }
248*433d6423SLionel Sambuc
249*433d6423SLionel Sambuc struct gpio *tmp = malloc(sizeof(struct gpio));
250*433d6423SLionel Sambuc memset(tmp, 0, sizeof(*tmp));
251*433d6423SLionel Sambuc
252*433d6423SLionel Sambuc tmp->nr = nr;
253*433d6423SLionel Sambuc *gpio = tmp;
254*433d6423SLionel Sambuc return OK;
255*433d6423SLionel Sambuc }
256*433d6423SLionel Sambuc
257*433d6423SLionel Sambuc static int
omap_gpio_pin_mode(struct gpio * gpio,int mode)258*433d6423SLionel Sambuc omap_gpio_pin_mode(struct gpio *gpio, int mode)
259*433d6423SLionel Sambuc {
260*433d6423SLionel Sambuc struct omap_gpio_bank *bank;
261*433d6423SLionel Sambuc assert(gpio != NULL);
262*433d6423SLionel Sambuc gpio->mode = mode;
263*433d6423SLionel Sambuc
264*433d6423SLionel Sambuc bank = omap_gpio_bank_get(gpio->nr);
265*433d6423SLionel Sambuc log_debug(&log,
266*433d6423SLionel Sambuc "pin mode bank %s, base address 0x%x -> register address (0x%x,0x%x,0x%x)\n",
267*433d6423SLionel Sambuc bank->name, bank->base_address, bank->register_address, regs->OE,
268*433d6423SLionel Sambuc bank->register_address + regs->OE);
269*433d6423SLionel Sambuc
270*433d6423SLionel Sambuc if (mode == GPIO_MODE_OUTPUT) {
271*433d6423SLionel Sambuc set32(bank->base_address + regs->OE, BIT(gpio->nr % 32), 0);
272*433d6423SLionel Sambuc } else {
273*433d6423SLionel Sambuc set32(bank->base_address + regs->FALLINGDETECT,
274*433d6423SLionel Sambuc BIT(gpio->nr % 32), 0xffffffff);
275*433d6423SLionel Sambuc set32(bank->base_address + regs->IRQENABLE, BIT(gpio->nr % 32),
276*433d6423SLionel Sambuc 0xffffffff);
277*433d6423SLionel Sambuc set32(bank->base_address + regs->OE, BIT(gpio->nr % 32),
278*433d6423SLionel Sambuc 0xffffffff);
279*433d6423SLionel Sambuc }
280*433d6423SLionel Sambuc return 0;
281*433d6423SLionel Sambuc }
282*433d6423SLionel Sambuc
283*433d6423SLionel Sambuc static int
omap_gpio_set(struct gpio * gpio,int value)284*433d6423SLionel Sambuc omap_gpio_set(struct gpio *gpio, int value)
285*433d6423SLionel Sambuc {
286*433d6423SLionel Sambuc struct omap_gpio_bank *bank;
287*433d6423SLionel Sambuc assert(gpio != NULL);
288*433d6423SLionel Sambuc assert(gpio->nr >= 0 && gpio->nr <= 32 * nbanks);
289*433d6423SLionel Sambuc
290*433d6423SLionel Sambuc bank = omap_gpio_bank_get(gpio->nr);
291*433d6423SLionel Sambuc if (value == 1) {
292*433d6423SLionel Sambuc write32(bank->base_address + regs->SETDATAOUT,
293*433d6423SLionel Sambuc BIT(gpio->nr % 32));
294*433d6423SLionel Sambuc } else {
295*433d6423SLionel Sambuc write32(bank->base_address + regs->CLEARDATAOUT,
296*433d6423SLionel Sambuc BIT(gpio->nr % 32));
297*433d6423SLionel Sambuc }
298*433d6423SLionel Sambuc return OK;
299*433d6423SLionel Sambuc }
300*433d6423SLionel Sambuc
301*433d6423SLionel Sambuc static int
omap_gpio_read(struct gpio * gpio,int * value)302*433d6423SLionel Sambuc omap_gpio_read(struct gpio *gpio, int *value)
303*433d6423SLionel Sambuc {
304*433d6423SLionel Sambuc struct omap_gpio_bank *bank;
305*433d6423SLionel Sambuc assert(gpio != NULL);
306*433d6423SLionel Sambuc assert(gpio->nr >= 0 && gpio->nr <= 32 * nbanks);
307*433d6423SLionel Sambuc
308*433d6423SLionel Sambuc bank = omap_gpio_bank_get(gpio->nr);
309*433d6423SLionel Sambuc log_trace(&log, "mode=%d OU/IN 0x%08x 0x%08x\n", gpio->mode,
310*433d6423SLionel Sambuc read32(bank->base_address + regs->DATAIN),
311*433d6423SLionel Sambuc read32(bank->base_address + regs->DATAOUT));
312*433d6423SLionel Sambuc
313*433d6423SLionel Sambuc if (gpio->mode == GPIO_MODE_INPUT) {
314*433d6423SLionel Sambuc *value =
315*433d6423SLionel Sambuc (read32(bank->base_address +
316*433d6423SLionel Sambuc regs->DATAIN) >> (gpio->nr % 32)) & 0x1;
317*433d6423SLionel Sambuc } else {
318*433d6423SLionel Sambuc *value =
319*433d6423SLionel Sambuc (read32(bank->base_address +
320*433d6423SLionel Sambuc regs->DATAOUT) >> (gpio->nr % 32)) & 0x1;
321*433d6423SLionel Sambuc }
322*433d6423SLionel Sambuc
323*433d6423SLionel Sambuc return OK;
324*433d6423SLionel Sambuc }
325*433d6423SLionel Sambuc
326*433d6423SLionel Sambuc static int
omap_gpio_intr_read(struct gpio * gpio,int * value)327*433d6423SLionel Sambuc omap_gpio_intr_read(struct gpio *gpio, int *value)
328*433d6423SLionel Sambuc {
329*433d6423SLionel Sambuc struct omap_gpio_bank *bank;
330*433d6423SLionel Sambuc assert(gpio != NULL);
331*433d6423SLionel Sambuc assert(gpio->nr >= 0 && gpio->nr <= 32 * nbanks);
332*433d6423SLionel Sambuc
333*433d6423SLionel Sambuc bank = omap_gpio_bank_get(gpio->nr);
334*433d6423SLionel Sambuc /* TODO: check if interrupt where enabled?? */
335*433d6423SLionel Sambuc
336*433d6423SLionel Sambuc *value = (bank->inter_values >> (gpio->nr % 32)) & 0x1;
337*433d6423SLionel Sambuc /* clear the data */
338*433d6423SLionel Sambuc bank->inter_values &= ~(1 << (gpio->nr % 32));
339*433d6423SLionel Sambuc
340*433d6423SLionel Sambuc return OK;
341*433d6423SLionel Sambuc }
342*433d6423SLionel Sambuc
343*433d6423SLionel Sambuc static int
omap_message_hook(message * m)344*433d6423SLionel Sambuc omap_message_hook(message * m)
345*433d6423SLionel Sambuc {
346*433d6423SLionel Sambuc unsigned long irq_set, i;
347*433d6423SLionel Sambuc struct omap_gpio_bank *bank;
348*433d6423SLionel Sambuc
349*433d6423SLionel Sambuc switch (_ENDPOINT_P(m->m_source)) {
350*433d6423SLionel Sambuc case HARDWARE:
351*433d6423SLionel Sambuc /* Hardware interrupt return a "set" if pending interrupts */
352*433d6423SLionel Sambuc irq_set = m->m_notify.interrupts;
353*433d6423SLionel Sambuc log_debug(&log, "HW message 0X%08llx\n", m->m_notify.interrupts);
354*433d6423SLionel Sambuc bank = &omap_gpio_banks[0];
355*433d6423SLionel Sambuc for (i = 0; omap_gpio_banks[i].name != NULL; i++) {
356*433d6423SLionel Sambuc bank = &omap_gpio_banks[i];
357*433d6423SLionel Sambuc
358*433d6423SLionel Sambuc if (irq_set & (1 << (bank->irq_id))) {
359*433d6423SLionel Sambuc log_trace(&log, "Interrupt for bank %s\n",
360*433d6423SLionel Sambuc bank->name);
361*433d6423SLionel Sambuc bank->inter_values |=
362*433d6423SLionel Sambuc read32(bank->base_address +
363*433d6423SLionel Sambuc regs->IRQSTATUS);
364*433d6423SLionel Sambuc /* clear the interrupts */
365*433d6423SLionel Sambuc write32(bank->base_address + regs->IRQSTATUS,
366*433d6423SLionel Sambuc 0xffffffff);
367*433d6423SLionel Sambuc if (sys_irqenable(&bank->irq_hook_id) != OK) {
368*433d6423SLionel Sambuc log_warn(&log,
369*433d6423SLionel Sambuc "Failed to enable irq for bank %s\n",
370*433d6423SLionel Sambuc bank->name);
371*433d6423SLionel Sambuc }
372*433d6423SLionel Sambuc }
373*433d6423SLionel Sambuc }
374*433d6423SLionel Sambuc return OK;
375*433d6423SLionel Sambuc default:
376*433d6423SLionel Sambuc log_debug(&log, "Unknown message\n");
377*433d6423SLionel Sambuc break;
378*433d6423SLionel Sambuc }
379*433d6423SLionel Sambuc return OK;
380*433d6423SLionel Sambuc }
381*433d6423SLionel Sambuc
revision_matches(u32_t board_id,u32_t rev)382*433d6423SLionel Sambuc static int revision_matches(u32_t board_id,u32_t rev) {
383*433d6423SLionel Sambuc /* figures out if the collected resition matches the one expected
384*433d6423SLionel Sambuc * from the board */
385*433d6423SLionel Sambuc if (BOARD_IS_BBXM(board_id)){
386*433d6423SLionel Sambuc if(
387*433d6423SLionel Sambuc DM37XX_GPIO_REVISION_MAJOR(rev) != 2
388*433d6423SLionel Sambuc || DM37XX_GPIO_REVISION_MINOR(rev) != 5
389*433d6423SLionel Sambuc ) {
390*433d6423SLionel Sambuc return 0;
391*433d6423SLionel Sambuc }
392*433d6423SLionel Sambuc } else if (BOARD_IS_BB(board_id)){
393*433d6423SLionel Sambuc if (
394*433d6423SLionel Sambuc AM335X_GPIO_REVISION_MAJOR(rev) != 0
395*433d6423SLionel Sambuc || AM335X_GPIO_REVISION_MINOR(rev) != 1
396*433d6423SLionel Sambuc ) {
397*433d6423SLionel Sambuc return 0;
398*433d6423SLionel Sambuc }
399*433d6423SLionel Sambuc }
400*433d6423SLionel Sambuc return 1;
401*433d6423SLionel Sambuc }
402*433d6423SLionel Sambuc
403*433d6423SLionel Sambuc static int
omap_gpio_init(struct gpio_driver * gpdrv)404*433d6423SLionel Sambuc omap_gpio_init(struct gpio_driver *gpdrv)
405*433d6423SLionel Sambuc {
406*433d6423SLionel Sambuc u32_t revision;
407*433d6423SLionel Sambuc int i;
408*433d6423SLionel Sambuc struct minix_mem_range mr;
409*433d6423SLionel Sambuc struct omap_gpio_bank *bank;
410*433d6423SLionel Sambuc struct machine machine;
411*433d6423SLionel Sambuc sys_getmachine(&machine);
412*433d6423SLionel Sambuc
413*433d6423SLionel Sambuc nbanks =0;
414*433d6423SLionel Sambuc omap_gpio_banks = NULL;
415*433d6423SLionel Sambuc if (BOARD_IS_BBXM(machine.board_id)){
416*433d6423SLionel Sambuc omap_gpio_banks = dm37xx_gpio_banks;
417*433d6423SLionel Sambuc regs = &gpio_omap_dm37xx;
418*433d6423SLionel Sambuc } else if (BOARD_IS_BB(machine.board_id)){
419*433d6423SLionel Sambuc omap_gpio_banks = am335x_gpio_banks;
420*433d6423SLionel Sambuc regs = &gpio_omap_am335x;
421*433d6423SLionel Sambuc }
422*433d6423SLionel Sambuc
423*433d6423SLionel Sambuc bank = &omap_gpio_banks[0];
424*433d6423SLionel Sambuc for (i = 0; omap_gpio_banks[i].name != NULL; i++) {
425*433d6423SLionel Sambuc nbanks++;
426*433d6423SLionel Sambuc bank = &omap_gpio_banks[i];
427*433d6423SLionel Sambuc mr.mr_base = bank->register_address;
428*433d6423SLionel Sambuc mr.mr_limit = bank->register_address + 0x400;
429*433d6423SLionel Sambuc
430*433d6423SLionel Sambuc if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
431*433d6423SLionel Sambuc log_warn(&log,
432*433d6423SLionel Sambuc "Unable to request permission to map memory\n");
433*433d6423SLionel Sambuc return EPERM; /* fixme */
434*433d6423SLionel Sambuc }
435*433d6423SLionel Sambuc
436*433d6423SLionel Sambuc /* Set the base address to use */
437*433d6423SLionel Sambuc bank->base_address =
438*433d6423SLionel Sambuc (uint32_t) vm_map_phys(SELF,
439*433d6423SLionel Sambuc (void *) bank->register_address, 0x400);
440*433d6423SLionel Sambuc
441*433d6423SLionel Sambuc if (bank->base_address == (uint32_t) MAP_FAILED) {
442*433d6423SLionel Sambuc log_warn(&log, "Unable to map GPIO memory\n");
443*433d6423SLionel Sambuc return EPERM; /* fixme */
444*433d6423SLionel Sambuc }
445*433d6423SLionel Sambuc
446*433d6423SLionel Sambuc revision = read32(bank->base_address + regs->REVISION);
447*433d6423SLionel Sambuc /* test if we can access it */
448*433d6423SLionel Sambuc if (! revision_matches(machine.board_id,revision)) {
449*433d6423SLionel Sambuc log_warn(&log,
450*433d6423SLionel Sambuc "Failed to read the revision of GPIO bank %s.. disabling\n",
451*433d6423SLionel Sambuc bank->name);
452*433d6423SLionel Sambuc log_warn(&log, "Got 0x%x\n", revision);
453*433d6423SLionel Sambuc bank->disabled = 1;
454*433d6423SLionel Sambuc } else {
455*433d6423SLionel Sambuc bank->disabled = 0;
456*433d6423SLionel Sambuc }
457*433d6423SLionel Sambuc
458*433d6423SLionel Sambuc if (sys_irqsetpolicy(bank->irq_nr, 0,
459*433d6423SLionel Sambuc &bank->irq_hook_id) != OK) {
460*433d6423SLionel Sambuc log_warn(&log,
461*433d6423SLionel Sambuc "GPIO: couldn't set IRQ policy for bank %s\n",
462*433d6423SLionel Sambuc bank->name);
463*433d6423SLionel Sambuc continue;
464*433d6423SLionel Sambuc };
465*433d6423SLionel Sambuc if (bank->irq_id != bank->irq_hook_id) {
466*433d6423SLionel Sambuc log_debug(&log, "requested id %d but got id %d\n",
467*433d6423SLionel Sambuc bank->irq_id, bank->irq_hook_id);
468*433d6423SLionel Sambuc }
469*433d6423SLionel Sambuc if (sys_irqenable(&bank->irq_hook_id) != OK) {
470*433d6423SLionel Sambuc log_warn(&log,
471*433d6423SLionel Sambuc "GPIO: couldn't enable interrupt for %s\n",
472*433d6423SLionel Sambuc bank->name);
473*433d6423SLionel Sambuc };
474*433d6423SLionel Sambuc log_trace(&log, "bank %s mapped on 0x%x with irq hook id %d\n",
475*433d6423SLionel Sambuc bank->name, bank->base_address, bank->irq_hook_id);
476*433d6423SLionel Sambuc
477*433d6423SLionel Sambuc };
478*433d6423SLionel Sambuc
479*433d6423SLionel Sambuc clkconf_init();
480*433d6423SLionel Sambuc
481*433d6423SLionel Sambuc if (BOARD_IS_BBXM(machine.board_id)){
482*433d6423SLionel Sambuc /* enable the interface and functional clock on GPIO bank 1 , this only
483*433d6423SLionel Sambuc applies to the Beagelboard XM */
484*433d6423SLionel Sambuc clkconf_set(CM_FCLKEN_WKUP, BIT(3), 0xffffffff);
485*433d6423SLionel Sambuc clkconf_set(CM_ICLKEN_WKUP, BIT(3), 0xffffffff);
486*433d6423SLionel Sambuc }
487*433d6423SLionel Sambuc clkconf_release();
488*433d6423SLionel Sambuc
489*433d6423SLionel Sambuc
490*433d6423SLionel Sambuc gpdrv->claim = omap_gpio_claim;
491*433d6423SLionel Sambuc gpdrv->pin_mode = omap_gpio_pin_mode;
492*433d6423SLionel Sambuc gpdrv->set = omap_gpio_set;
493*433d6423SLionel Sambuc gpdrv->read = omap_gpio_read;
494*433d6423SLionel Sambuc gpdrv->intr_read = omap_gpio_intr_read;
495*433d6423SLionel Sambuc gpdrv->message_hook = omap_message_hook;
496*433d6423SLionel Sambuc return 0;
497*433d6423SLionel Sambuc }
498*433d6423SLionel Sambuc
499*433d6423SLionel Sambuc int
gpio_init()500*433d6423SLionel Sambuc gpio_init()
501*433d6423SLionel Sambuc {
502*433d6423SLionel Sambuc return omap_gpio_init(&drv);
503*433d6423SLionel Sambuc }
504*433d6423SLionel Sambuc
505*433d6423SLionel Sambuc /* request access to a gpio */
506*433d6423SLionel Sambuc int
gpio_claim(char * owner,int nr,struct gpio ** gpio)507*433d6423SLionel Sambuc gpio_claim(char *owner, int nr, struct gpio **gpio)
508*433d6423SLionel Sambuc {
509*433d6423SLionel Sambuc return drv.claim(owner, nr, gpio);
510*433d6423SLionel Sambuc }
511*433d6423SLionel Sambuc
512*433d6423SLionel Sambuc /* Configure the GPIO for a certain purpose */
513*433d6423SLionel Sambuc int
gpio_pin_mode(struct gpio * gpio,int mode)514*433d6423SLionel Sambuc gpio_pin_mode(struct gpio *gpio, int mode)
515*433d6423SLionel Sambuc {
516*433d6423SLionel Sambuc return drv.pin_mode(gpio, mode);
517*433d6423SLionel Sambuc }
518*433d6423SLionel Sambuc
519*433d6423SLionel Sambuc /* Set the value for a GPIO */
520*433d6423SLionel Sambuc int
gpio_set(struct gpio * gpio,int value)521*433d6423SLionel Sambuc gpio_set(struct gpio *gpio, int value)
522*433d6423SLionel Sambuc {
523*433d6423SLionel Sambuc return drv.set(gpio, value);
524*433d6423SLionel Sambuc }
525*433d6423SLionel Sambuc
526*433d6423SLionel Sambuc /* Read the current value of the GPIO */
527*433d6423SLionel Sambuc int
gpio_read(struct gpio * gpio,int * value)528*433d6423SLionel Sambuc gpio_read(struct gpio *gpio, int *value)
529*433d6423SLionel Sambuc {
530*433d6423SLionel Sambuc return drv.read(gpio, value);
531*433d6423SLionel Sambuc }
532*433d6423SLionel Sambuc
533*433d6423SLionel Sambuc /* Read and clear the value interrupt value of the GPIO */
534*433d6423SLionel Sambuc int
gpio_intr_read(struct gpio * gpio,int * value)535*433d6423SLionel Sambuc gpio_intr_read(struct gpio *gpio, int *value)
536*433d6423SLionel Sambuc {
537*433d6423SLionel Sambuc return drv.intr_read(gpio, value);
538*433d6423SLionel Sambuc }
539*433d6423SLionel Sambuc
540*433d6423SLionel Sambuc /* Interrupt hook */
541*433d6423SLionel Sambuc int
gpio_intr_message(message * m)542*433d6423SLionel Sambuc gpio_intr_message(message * m)
543*433d6423SLionel Sambuc {
544*433d6423SLionel Sambuc return drv.message_hook(m);
545*433d6423SLionel Sambuc }
546*433d6423SLionel Sambuc
547*433d6423SLionel Sambuc int
gpio_release(void)548*433d6423SLionel Sambuc gpio_release(void)
549*433d6423SLionel Sambuc {
550*433d6423SLionel Sambuc return OK;
551*433d6423SLionel Sambuc }
552