4 * Copyright (c) 2008, Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD$");
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/device.h>
36 #include <sys/kernel.h>
38 #include <dev/gpio/gpiovar.h>
40 #include <dev/ppbus/ppbus_conf.h>
41 #include <dev/ppbus/ppbus_base.h>
42 #include <dev/ppbus/ppbus_io.h>
44 static int gpio_ppbus_open(void *, device_t
);
45 static void gpio_ppbus_close(void *, device_t
);
46 static int gpio_ppbus_pin_read(void *, int);
47 static void gpio_ppbus_pin_write(void *, int, int);
48 static void gpio_ppbus_pin_ctl(void *, int, int);
51 #define PORT(r, b, i) { PPBUS_R##r##TR, PPBUS_W##r##TR, b, i}
57 } ppbus_port
[PPBUS_NPINS
] = { /* parallel port wiring: */
58 PORT(C
, 0, 1), /* 1: /C0 Output */
59 PORT(D
, 0, 0), /* 2: D0 Output */
60 PORT(D
, 1, 0), /* 3: D1 Output */
61 PORT(D
, 2, 0), /* 4: D2 Output */
62 PORT(D
, 3, 0), /* 5: D3 Output */
63 PORT(D
, 4, 0), /* 6: D4 Output */
64 PORT(D
, 5, 0), /* 7: D5 Output */
65 PORT(D
, 6, 0), /* 8: D6 Output */
66 PORT(D
, 7, 0), /* 9: D7 Output */
67 PORT(S
, 6, 0), /* 10: S6 Input */
68 PORT(S
, 7, 1), /* 11: /S7 Input */
69 PORT(S
, 5, 0), /* 12: S5 Input */
70 PORT(S
, 4, 0), /* 13: S4 Input */
71 PORT(C
, 1, 1), /* 14: /C1 Output */
72 PORT(S
, 3, 0), /* 15: S3 Input */
73 PORT(C
, 2, 0), /* 16: C2 Output */
74 PORT(C
, 3, 1), /* 17: /C3 Output */
78 gpio_ppbus_attach(struct ppbus_softc
*sc
)
80 struct gpiobus_attach_args gba
;
84 for (pin
= &sc
->sc_gpio_pins
[0], i
= 0; i
< PPBUS_NPINS
; pin
++, i
++) {
87 if (((i
>= 9) && (i
<= 12)) || (i
== 14)) {
88 pin
->pin_caps
= GPIO_PIN_INPUT
;
89 pin
->pin_flags
= GPIO_PIN_INPUT
;
90 pin
->pin_state
= gpio_ppbus_pin_read(sc
, i
);
92 pin
->pin_caps
= GPIO_PIN_OUTPUT
;
93 pin
->pin_flags
= GPIO_PIN_OUTPUT
;
94 pin
->pin_state
= GPIO_PIN_LOW
;
95 gpio_ppbus_pin_write(sc
, i
, pin
->pin_state
);
98 gpio_ppbus_pin_ctl(sc
, i
, pin
->pin_flags
);
101 sc
->sc_gpio_gc
.gp_cookie
= sc
;
102 sc
->sc_gpio_gc
.gp_gc_open
= gpio_ppbus_open
;
103 sc
->sc_gpio_gc
.gp_gc_close
= gpio_ppbus_close
;
104 sc
->sc_gpio_gc
.gp_pin_read
= gpio_ppbus_pin_read
;
105 sc
->sc_gpio_gc
.gp_pin_write
= gpio_ppbus_pin_write
;
106 sc
->sc_gpio_gc
.gp_pin_ctl
= gpio_ppbus_pin_ctl
;
108 gba
.gba_gc
= &sc
->sc_gpio_gc
;
109 gba
.gba_pins
= sc
->sc_gpio_pins
;
110 gba
.gba_npins
= PPBUS_NPINS
;
112 config_found_ia(sc
->sc_dev
, "gpiobus", &gba
, gpiobus_print
);
116 gpio_ppbus_open(void *arg
, device_t dev
)
118 struct ppbus_softc
*sc
= arg
;
120 return ppbus_request_bus(sc
->sc_dev
, dev
, PPBUS_WAIT
|PPBUS_INTR
, (hz
));
124 gpio_ppbus_close(void *arg
, device_t dev
)
126 struct ppbus_softc
*sc
= arg
;
128 (void) ppbus_release_bus(sc
->sc_dev
, dev
, PPBUS_WAIT
|PPBUS_INTR
, (hz
));
132 gpio_ppbus_pin_read(void *arg
, int pin
)
134 struct ppbus_softc
*sc
= arg
;
135 u_char port
= ppbus_io(sc
->sc_dev
, ppbus_port
[pin
].rreg
, NULL
, 0, 0);
137 return ((port
>> ppbus_port
[pin
].bit
) & 1) ^ ppbus_port
[pin
].inv
;
141 gpio_ppbus_pin_write(void *arg
, int pin
, int value
)
143 struct ppbus_softc
*sc
= arg
;
144 u_char port
= ppbus_io(sc
->sc_dev
, ppbus_port
[pin
].rreg
, NULL
, 0, 0);
146 value
^= ppbus_port
[pin
].inv
;
147 value
<<= ppbus_port
[pin
].bit
;
148 port
&= ~(1 << ppbus_port
[pin
].bit
);
151 ppbus_io(sc
->sc_dev
, ppbus_port
[pin
].wreg
, NULL
, 0, port
);
155 gpio_ppbus_pin_ctl(void *arg
, int pin
, int flags
)
157 /* can't change parallel port pin configuration */