1 /* $NetBSD: ap_ms104_sh4.c,v 1.2 2012/01/21 19:44:29 nonaka Exp $ */
2
3 /*-
4 * Copyright (C) 2009 NONAKA Kimihiro <nonaka@netbsd.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: ap_ms104_sh4.c,v 1.2 2012/01/21 19:44:29 nonaka Exp $");
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/intr.h>
34
35 #include <sh3/devreg.h>
36 #include <sh3/pfcreg.h>
37 #include <sh3/exception.h>
38
39 #include <evbsh3/ap_ms104_sh4/ap_ms104_sh4reg.h>
40 #include <evbsh3/ap_ms104_sh4/ap_ms104_sh4var.h>
41
42 static int gpio_intr(void *arg);
43
44 struct gpio_intrhand {
45 int ih_irq;
46 int (*ih_func)(void *);
47 void *ih_arg;
48 } gpio_intr_func_table[16];
49
50 void
machine_init(void)51 machine_init(void)
52 {
53
54 extintr_init();
55 gpio_intr_init();
56 }
57
58 void
gpio_intr_init(void)59 gpio_intr_init(void)
60 {
61 uint32_t reg;
62
63 _reg_write_2(SH4_GPIOIC, 0);
64 _reg_write_2(SH4_PDTRA, 0);
65 _reg_write_4(SH4_PCTRA, 0);
66 _reg_write_2(SH4_PDTRB, 0);
67 _reg_write_4(SH4_PCTRB, 0);
68
69 (void) intc_intr_establish(SH4_INTEVT_GPIO, IST_LEVEL, IPL_TTY,
70 gpio_intr, NULL);
71
72 /* setup for pc-card */
73 _reg_write_2(SH4_PDTRA, (1 << GPIO_PIN_CARD_PON)
74 | (1 << GPIO_PIN_CARD_RESET)
75 | (1 << GPIO_PIN_CARD_ENABLE)); /* disable */
76 reg = _reg_read_4(SH4_PCTRA);
77 reg &= ~(3 << (GPIO_PIN_CARD_CD * 2)); /* input */
78 reg &= ~(3 << (GPIO_PIN_CARD_PON * 2));
79 reg |= (1 << (GPIO_PIN_CARD_PON * 2)); /* output */
80 reg &= ~(3 << (GPIO_PIN_CARD_RESET * 2));
81 reg |= (1 << (GPIO_PIN_CARD_RESET * 2)); /* output */
82 reg &= ~(3 << (GPIO_PIN_CARD_ENABLE * 2));
83 reg |= (1 << (GPIO_PIN_CARD_ENABLE * 2)); /* output */
84 _reg_write_4(SH4_PCTRA, reg);
85 }
86
87 void *
gpio_intr_establish(int pin,int (* ih_func)(void *),void * ih_arg)88 gpio_intr_establish(int pin, int (*ih_func)(void *), void *ih_arg)
89 {
90 uint32_t reg;
91 int s;
92
93 KASSERT(pin >= 0 && pin <= 15);
94 KASSERT(gpio_intr_func_table[pin].ih_func == NULL);
95 KASSERT((_reg_read_4(SH4_PCTRA) & (1 << (pin * 2))) == 0); /*input*/
96
97 s = splhigh();
98
99 /* install interrupt handler */
100 gpio_intr_func_table[pin].ih_irq = pin;
101 gpio_intr_func_table[pin].ih_func = ih_func;
102 gpio_intr_func_table[pin].ih_arg = ih_arg;
103
104 /* enable gpio interrupt */
105 reg = _reg_read_2(SH4_GPIOIC);
106 reg |= 1 << pin;
107 _reg_write_2(SH4_GPIOIC, reg);
108
109 splx(s);
110
111 return &gpio_intr_func_table[pin];
112 }
113
114 void
gpior_intr_disestablish(void * cookie)115 gpior_intr_disestablish(void *cookie)
116 {
117 struct gpio_intrhand *ih = cookie;
118 int pin = ih->ih_irq;
119 uint16_t reg;
120 int s;
121
122 KASSERT(pin >= 0 && pin <= 15);
123
124 s = splhigh();
125
126 /* disable gpio interrupt */
127 reg = _reg_read_2(SH4_GPIOIC);
128 reg &= ~(1 << pin);
129 _reg_write_2(SH4_GPIOIC, reg);
130
131 /* deinstall interrupt handler */
132 gpio_intr_func_table[pin].ih_irq = 0;
133 gpio_intr_func_table[pin].ih_func = NULL;
134 gpio_intr_func_table[pin].ih_arg = NULL;
135
136 splx(s);
137 }
138
139 /*ARGSUSED*/
140 static int
gpio_intr(void * arg)141 gpio_intr(void *arg)
142 {
143 struct gpio_intrhand *ih;
144 uint32_t reg;
145 int retval = 0;
146 int pin;
147
148 reg = _reg_read_4(SH4_PCTRA);
149 for (pin = 0; pin < 16; pin++) {
150 if (reg & (1 << pin)) {
151 ih = &gpio_intr_func_table[pin];
152 if (ih->ih_func != NULL) {
153 retval |= (*ih->ih_func)(ih->ih_arg);
154 } else {
155 uint16_t r;
156 r = _reg_read_2(SH4_GPIOIC);
157 r &= ~(1 << pin);
158 _reg_write_2(SH4_GPIOIC, r);
159 }
160 }
161 }
162 return retval;
163 }
164