1*2388feefSnonaka /* $NetBSD: ap_ms104_sh4.c,v 1.2 2012/01/21 19:44:29 nonaka Exp $ */
2238763f6Snonaka
3238763f6Snonaka /*-
4*2388feefSnonaka * Copyright (C) 2009 NONAKA Kimihiro <nonaka@netbsd.org>
5238763f6Snonaka * All rights reserved.
6238763f6Snonaka *
7238763f6Snonaka * Redistribution and use in source and binary forms, with or without
8238763f6Snonaka * modification, are permitted provided that the following conditions
9238763f6Snonaka * are met:
10238763f6Snonaka * 1. Redistributions of source code must retain the above copyright
11238763f6Snonaka * notice, this list of conditions and the following disclaimer.
12238763f6Snonaka * 2. Redistributions in binary form must reproduce the above copyright
13238763f6Snonaka * notice, this list of conditions and the following disclaimer in the
14238763f6Snonaka * documentation and/or other materials provided with the distribution.
15238763f6Snonaka *
16*2388feefSnonaka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*2388feefSnonaka * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*2388feefSnonaka * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*2388feefSnonaka * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*2388feefSnonaka * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*2388feefSnonaka * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*2388feefSnonaka * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*2388feefSnonaka * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*2388feefSnonaka * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*2388feefSnonaka * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26238763f6Snonaka */
27238763f6Snonaka
28238763f6Snonaka #include <sys/cdefs.h>
29*2388feefSnonaka __KERNEL_RCSID(0, "$NetBSD: ap_ms104_sh4.c,v 1.2 2012/01/21 19:44:29 nonaka Exp $");
30238763f6Snonaka
31238763f6Snonaka #include <sys/param.h>
32238763f6Snonaka #include <sys/systm.h>
33238763f6Snonaka #include <sys/intr.h>
34238763f6Snonaka
35238763f6Snonaka #include <sh3/devreg.h>
36238763f6Snonaka #include <sh3/pfcreg.h>
37238763f6Snonaka #include <sh3/exception.h>
38238763f6Snonaka
39238763f6Snonaka #include <evbsh3/ap_ms104_sh4/ap_ms104_sh4reg.h>
40238763f6Snonaka #include <evbsh3/ap_ms104_sh4/ap_ms104_sh4var.h>
41238763f6Snonaka
42238763f6Snonaka static int gpio_intr(void *arg);
43238763f6Snonaka
44238763f6Snonaka struct gpio_intrhand {
45238763f6Snonaka int ih_irq;
46238763f6Snonaka int (*ih_func)(void *);
47238763f6Snonaka void *ih_arg;
48238763f6Snonaka } gpio_intr_func_table[16];
49238763f6Snonaka
50238763f6Snonaka void
machine_init(void)51238763f6Snonaka machine_init(void)
52238763f6Snonaka {
53238763f6Snonaka
54238763f6Snonaka extintr_init();
55238763f6Snonaka gpio_intr_init();
56238763f6Snonaka }
57238763f6Snonaka
58238763f6Snonaka void
gpio_intr_init(void)59238763f6Snonaka gpio_intr_init(void)
60238763f6Snonaka {
61238763f6Snonaka uint32_t reg;
62238763f6Snonaka
63238763f6Snonaka _reg_write_2(SH4_GPIOIC, 0);
64238763f6Snonaka _reg_write_2(SH4_PDTRA, 0);
65238763f6Snonaka _reg_write_4(SH4_PCTRA, 0);
66238763f6Snonaka _reg_write_2(SH4_PDTRB, 0);
67238763f6Snonaka _reg_write_4(SH4_PCTRB, 0);
68238763f6Snonaka
69238763f6Snonaka (void) intc_intr_establish(SH4_INTEVT_GPIO, IST_LEVEL, IPL_TTY,
70238763f6Snonaka gpio_intr, NULL);
71238763f6Snonaka
72238763f6Snonaka /* setup for pc-card */
73238763f6Snonaka _reg_write_2(SH4_PDTRA, (1 << GPIO_PIN_CARD_PON)
74238763f6Snonaka | (1 << GPIO_PIN_CARD_RESET)
75238763f6Snonaka | (1 << GPIO_PIN_CARD_ENABLE)); /* disable */
76238763f6Snonaka reg = _reg_read_4(SH4_PCTRA);
77238763f6Snonaka reg &= ~(3 << (GPIO_PIN_CARD_CD * 2)); /* input */
78238763f6Snonaka reg &= ~(3 << (GPIO_PIN_CARD_PON * 2));
79238763f6Snonaka reg |= (1 << (GPIO_PIN_CARD_PON * 2)); /* output */
80238763f6Snonaka reg &= ~(3 << (GPIO_PIN_CARD_RESET * 2));
81238763f6Snonaka reg |= (1 << (GPIO_PIN_CARD_RESET * 2)); /* output */
82238763f6Snonaka reg &= ~(3 << (GPIO_PIN_CARD_ENABLE * 2));
83238763f6Snonaka reg |= (1 << (GPIO_PIN_CARD_ENABLE * 2)); /* output */
84238763f6Snonaka _reg_write_4(SH4_PCTRA, reg);
85238763f6Snonaka }
86238763f6Snonaka
87238763f6Snonaka void *
gpio_intr_establish(int pin,int (* ih_func)(void *),void * ih_arg)88238763f6Snonaka gpio_intr_establish(int pin, int (*ih_func)(void *), void *ih_arg)
89238763f6Snonaka {
90238763f6Snonaka uint32_t reg;
91238763f6Snonaka int s;
92238763f6Snonaka
93238763f6Snonaka KASSERT(pin >= 0 && pin <= 15);
94238763f6Snonaka KASSERT(gpio_intr_func_table[pin].ih_func == NULL);
95238763f6Snonaka KASSERT((_reg_read_4(SH4_PCTRA) & (1 << (pin * 2))) == 0); /*input*/
96238763f6Snonaka
97238763f6Snonaka s = splhigh();
98238763f6Snonaka
99238763f6Snonaka /* install interrupt handler */
100238763f6Snonaka gpio_intr_func_table[pin].ih_irq = pin;
101238763f6Snonaka gpio_intr_func_table[pin].ih_func = ih_func;
102238763f6Snonaka gpio_intr_func_table[pin].ih_arg = ih_arg;
103238763f6Snonaka
104238763f6Snonaka /* enable gpio interrupt */
105238763f6Snonaka reg = _reg_read_2(SH4_GPIOIC);
106238763f6Snonaka reg |= 1 << pin;
107238763f6Snonaka _reg_write_2(SH4_GPIOIC, reg);
108238763f6Snonaka
109238763f6Snonaka splx(s);
110238763f6Snonaka
111238763f6Snonaka return &gpio_intr_func_table[pin];
112238763f6Snonaka }
113238763f6Snonaka
114238763f6Snonaka void
gpior_intr_disestablish(void * cookie)115238763f6Snonaka gpior_intr_disestablish(void *cookie)
116238763f6Snonaka {
117238763f6Snonaka struct gpio_intrhand *ih = cookie;
118238763f6Snonaka int pin = ih->ih_irq;
119238763f6Snonaka uint16_t reg;
120238763f6Snonaka int s;
121238763f6Snonaka
122238763f6Snonaka KASSERT(pin >= 0 && pin <= 15);
123238763f6Snonaka
124238763f6Snonaka s = splhigh();
125238763f6Snonaka
126238763f6Snonaka /* disable gpio interrupt */
127238763f6Snonaka reg = _reg_read_2(SH4_GPIOIC);
128238763f6Snonaka reg &= ~(1 << pin);
129238763f6Snonaka _reg_write_2(SH4_GPIOIC, reg);
130238763f6Snonaka
131238763f6Snonaka /* deinstall interrupt handler */
132238763f6Snonaka gpio_intr_func_table[pin].ih_irq = 0;
133238763f6Snonaka gpio_intr_func_table[pin].ih_func = NULL;
134238763f6Snonaka gpio_intr_func_table[pin].ih_arg = NULL;
135238763f6Snonaka
136238763f6Snonaka splx(s);
137238763f6Snonaka }
138238763f6Snonaka
139238763f6Snonaka /*ARGSUSED*/
140238763f6Snonaka static int
gpio_intr(void * arg)141238763f6Snonaka gpio_intr(void *arg)
142238763f6Snonaka {
143238763f6Snonaka struct gpio_intrhand *ih;
144238763f6Snonaka uint32_t reg;
145238763f6Snonaka int retval = 0;
146238763f6Snonaka int pin;
147238763f6Snonaka
148238763f6Snonaka reg = _reg_read_4(SH4_PCTRA);
149238763f6Snonaka for (pin = 0; pin < 16; pin++) {
150238763f6Snonaka if (reg & (1 << pin)) {
151238763f6Snonaka ih = &gpio_intr_func_table[pin];
152238763f6Snonaka if (ih->ih_func != NULL) {
153238763f6Snonaka retval |= (*ih->ih_func)(ih->ih_arg);
154238763f6Snonaka } else {
155238763f6Snonaka uint16_t r;
156238763f6Snonaka r = _reg_read_2(SH4_GPIOIC);
157238763f6Snonaka r &= ~(1 << pin);
158238763f6Snonaka _reg_write_2(SH4_GPIOIC, r);
159238763f6Snonaka }
160238763f6Snonaka }
161238763f6Snonaka }
162238763f6Snonaka return retval;
163238763f6Snonaka }
164