1 /* $NetBSD: augpio.c,v 1.4 2006/03/24 02:58:36 gdamore Exp $ */
4 * Copyright (c) 2006 Itronix Inc.
7 * Written by Garrett D'Amore for Itronix Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of Itronix Inc. may not be used to endorse
18 * or promote products derived from this software without specific
19 * prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: augpio.c,v 1.4 2006/03/24 02:58:36 gdamore Exp $");
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/errno.h>
41 #include <sys/device.h>
43 #include <sys/kernel.h>
45 #include <dev/gpio/gpiovar.h>
47 #include <machine/bus.h>
48 #include <machine/cpu.h>
50 #include <mips/alchemy/include/aubusvar.h>
51 #include <mips/alchemy/include/aureg.h>
52 #include <mips/alchemy/dev/augpioreg.h>
53 #include <mips/alchemy/dev/augpiovar.h>
57 struct gpio_chipset_tag sc_gc
;
58 gpio_pin_t sc_pins
[AUGPIO_NPINS
];
60 bus_space_tag_t sc_bst
;
63 int (*sc_getctl
)(void *, int);
66 static int augpio_match(struct device
*, struct cfdata
*, void *);
67 static void augpio_attach(struct device
*, struct device
*, void *);
69 CFATTACH_DECL(augpio
, sizeof(struct augpio_softc
),
70 augpio_match
, augpio_attach
, NULL
, NULL
);
73 (*(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(x))
74 #define PUTREG(x, v) \
75 ((*(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(x)) = (v))
77 #define GETGPIO(x) GETREG(GPIO_BASE + (x))
78 #define PUTGPIO(x,v) PUTREG(GPIO_BASE + (x), (v))
79 #define GETGPIO2(x) GETREG(GPIO2_BASE + (x))
80 #define PUTGPIO2(x,v) PUTREG(GPIO2_BASE + (x), (v))
83 augpio_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
85 struct aubus_attach_args
*aa
= (struct aubus_attach_args
*)aux
;
87 if (strcmp(aa
->aa_name
, "augpio") != 0)
94 augpio_attach(struct device
*parent
, struct device
*self
, void *aux
)
98 struct augpio_softc
*sc
= (struct augpio_softc
*)self
;
99 struct aubus_attach_args
*aa
= aux
;
100 struct gpiobus_attach_args gba
;
102 sc
->sc_bst
= aa
->aa_st
;
103 sc
->sc_npins
= aa
->aa_addrs
[1];
104 sc
->sc_gc
.gp_cookie
= sc
;
106 if (aa
->aa_addrs
[0] == GPIO_BASE
) {
108 sc
->sc_caps
= GPIO_PIN_INPUT
| GPIO_PIN_OUTPUT
|
110 sc
->sc_gc
.gp_pin_read
= augpio_read
;
111 sc
->sc_gc
.gp_pin_write
= augpio_write
;
112 sc
->sc_gc
.gp_pin_ctl
= augpio_ctl
;
113 sc
->sc_getctl
= augpio_getctl
;
114 sc
->sc_name
= "primary block";
116 } else if (aa
->aa_addrs
[0] == GPIO2_BASE
) {
118 * We rely on firmware (or platform init code) to initialize
119 * the GPIO2 block. We can't do it ourselves, because
120 * resetting the GPIO2 block can have nasty effects (e.g.
123 sc
->sc_caps
= GPIO_PIN_INPUT
| GPIO_PIN_OUTPUT
;
124 sc
->sc_gc
.gp_pin_read
= augpio2_read
;
125 sc
->sc_gc
.gp_pin_write
= augpio2_write
;
126 sc
->sc_gc
.gp_pin_ctl
= augpio2_ctl
;
127 sc
->sc_getctl
= augpio2_getctl
;
128 sc
->sc_name
= "secondary block";
131 printf(": unidentified block\n");
135 for (pin
= 0; pin
< sc
->sc_npins
; pin
++) {
136 gpio_pin_t
*pp
= &sc
->sc_pins
[pin
];
139 pp
->pin_caps
= sc
->sc_caps
;
140 pp
->pin_flags
= sc
->sc_getctl(sc
, pin
);
141 pp
->pin_state
= sc
->sc_gc
.gp_pin_read(sc
, pin
);
144 gba
.gba_gc
= &sc
->sc_gc
;
145 gba
.gba_pins
= sc
->sc_pins
;
146 gba
.gba_npins
= sc
->sc_npins
;
148 printf(": Alchemy GPIO, %s\n", sc
->sc_name
);
149 config_found_ia(&sc
->sc_dev
, "gpiobus", &gba
, gpiobus_print
);
153 augpio_read(void *arg
, int pin
)
158 if (GETGPIO(AUGPIO_PINSTATERD
) & pin
)
159 return GPIO_PIN_HIGH
;
165 augpio_write(void *arg
, int pin
, int value
)
169 PUTGPIO(value
? AUGPIO_OUTPUTSET
: AUGPIO_OUTPUTCLR
, pin
);
173 augpio_ctl(void *arg
, int pin
, int flags
)
179 if (flags
& (GPIO_PIN_TRISTATE
|GPIO_PIN_INPUT
)) {
180 reg
= AUGPIO_TRIOUTCLR
;
181 } else if (flags
& GPIO_PIN_OUTPUT
) {
183 out
= GETGPIO(AUGPIO_OUTPUTRD
);
184 reg
= pin
& out
? AUGPIO_OUTPUTSET
: AUGPIO_OUTPUTCLR
;
193 augpio_getctl(void *arg
, int pin
)
196 if (GETGPIO(AUGPIO_TRIOUTRD
) & pin
)
197 return GPIO_PIN_OUTPUT
;
199 return GPIO_PIN_INPUT
;
203 augpio2_read(void *arg
, int pin
)
208 if (GETGPIO2(AUGPIO2_PINSTATE
) & pin
)
209 return GPIO_PIN_HIGH
;
215 augpio2_write(void *arg
, int pin
, int value
)
221 pin
= pin
| (pin
<< 16);
226 PUTGPIO2(AUGPIO2_OUTPUT
, pin
);
230 augpio2_ctl(void *arg
, int pin
, int flags
)
236 dir
= GETGPIO2(AUGPIO2_DIR
);
238 if (flags
& GPIO_PIN_INPUT
) {
240 } else if (flags
& GPIO_PIN_OUTPUT
) {
243 PUTGPIO2(AUGPIO2_DIR
, dir
);
247 augpio2_getctl(void *arg
, int pin
)
253 dir
= GETGPIO2(AUGPIO2_DIR
);
254 if (dir
& (uint32_t)pin
) {
255 return GPIO_PIN_OUTPUT
;
257 return GPIO_PIN_INPUT
;