1 /* $NetBSD: gpioow.c,v 1.11 2009/08/08 10:38:17 mbalmer Exp $ */
2 /* $OpenBSD: gpioow.c,v 1.1 2006/03/04 16:27:03 grange Exp $ */
5 * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <sys/cdefs.h>
21 __KERNEL_RCSID(0, "$NetBSD: gpioow.c,v 1.11 2009/08/08 10:38:17 mbalmer Exp $");
24 * 1-Wire bus bit-banging through GPIO pin.
27 #include <sys/param.h>
28 #include <sys/systm.h>
29 #include <sys/device.h>
32 #include <dev/gpio/gpiovar.h>
34 #include <dev/onewire/onewirevar.h>
36 #define GPIOOW_NPINS 1
37 #define GPIOOW_PIN_DATA 0
41 struct gpio_pinmap sc_map
;
42 int _map
[GPIOOW_NPINS
];
44 struct onewire_bus sc_ow_bus
;
51 int gpioow_match(device_t
, cfdata_t
, void *);
52 void gpioow_attach(device_t
, device_t
, void *);
53 int gpioow_detach(device_t
, int);
54 int gpioow_activate(device_t
, enum devact
);
56 int gpioow_ow_reset(void *);
57 int gpioow_ow_bit(void *, int);
59 void gpioow_bb_rx(void *);
60 void gpioow_bb_tx(void *);
61 int gpioow_bb_get(void *);
62 void gpioow_bb_set(void *, int);
64 CFATTACH_DECL_NEW(gpioow
, sizeof(struct gpioow_softc
),
65 gpioow_match
, gpioow_attach
, gpioow_detach
, gpioow_activate
);
67 extern struct cfdriver gpioow_cd
;
69 static const struct onewire_bbops gpioow_bbops
= {
77 gpioow_match(device_t parent
, cfdata_t cf
, void *aux
)
79 struct gpio_attach_args
*ga
= aux
;
81 if (strcmp(ga
->ga_dvname
, cf
->cf_name
))
84 if (ga
->ga_offset
== -1)
87 /* Check that we have enough pins */
88 if (gpio_npins(ga
->ga_mask
) != GPIOOW_NPINS
) {
89 aprint_debug("%s: invalid pin mask 0x%02x/n", cf
->cf_name
,
97 gpioow_attach(device_t parent
, device_t self
, void *aux
)
99 struct gpioow_softc
*sc
= device_private(self
);
100 struct gpio_attach_args
*ga
= aux
;
101 struct onewirebus_attach_args oba
;
105 sc
->sc_gpio
= ga
->ga_gpio
;
106 sc
->sc_map
.pm_map
= sc
->_map
;
107 if (gpio_pin_map(sc
->sc_gpio
, ga
->ga_offset
, ga
->ga_mask
,
109 aprint_error(": can't map pins\n");
113 /* Configure data pin */
114 caps
= gpio_pin_caps(sc
->sc_gpio
, &sc
->sc_map
, GPIOOW_PIN_DATA
);
115 if (!(caps
& GPIO_PIN_OUTPUT
)) {
116 aprint_error(": data pin is unable to drive output\n");
119 if (!(caps
& GPIO_PIN_INPUT
)) {
120 aprint_error(": data pin is unable to read input\n");
123 aprint_normal(": DATA[%d]", sc
->sc_map
.pm_map
[GPIOOW_PIN_DATA
]);
124 sc
->sc_data
= GPIO_PIN_OUTPUT
;
125 if (caps
& GPIO_PIN_OPENDRAIN
) {
126 aprint_normal(" open-drain");
127 sc
->sc_data
|= GPIO_PIN_OPENDRAIN
;
128 } else if ((caps
& GPIO_PIN_PUSHPULL
) && (caps
& GPIO_PIN_TRISTATE
)) {
129 aprint_normal(" push-pull tri-state");
130 sc
->sc_data
|= GPIO_PIN_PUSHPULL
;
132 if (caps
& GPIO_PIN_PULLUP
) {
133 aprint_normal(" pull-up");
134 sc
->sc_data
|= GPIO_PIN_PULLUP
;
136 gpio_pin_ctl(sc
->sc_gpio
, &sc
->sc_map
, GPIOOW_PIN_DATA
, sc
->sc_data
);
140 /* Attach 1-Wire bus */
141 sc
->sc_ow_bus
.bus_cookie
= sc
;
142 sc
->sc_ow_bus
.bus_reset
= gpioow_ow_reset
;
143 sc
->sc_ow_bus
.bus_bit
= gpioow_ow_bit
;
145 memset(&oba
, 0, sizeof(oba
));
146 oba
.oba_bus
= &sc
->sc_ow_bus
;
147 sc
->sc_ow_dev
= config_found(self
, &oba
, onewirebus_print
);
149 if (!pmf_device_register(self
, NULL
, NULL
))
150 aprint_error("%s: could not establish power handler\n",
155 gpio_pin_unmap(sc
->sc_gpio
, &sc
->sc_map
);
159 gpioow_detach(device_t self
, int flags
)
161 struct gpioow_softc
*sc
= device_private(self
);
164 if (sc
->sc_ow_dev
!= NULL
)
165 rv
= config_detach(sc
->sc_ow_dev
, flags
);
168 gpio_pin_unmap(sc
->sc_gpio
, &sc
->sc_map
);
169 pmf_device_deregister(self
);
175 gpioow_activate(device_t self
, enum devact act
)
177 struct gpioow_softc
*sc
= device_private(self
);
180 case DVACT_DEACTIVATE
:
189 gpioow_ow_reset(void *arg
)
191 return (onewire_bb_reset(&gpioow_bbops
, arg
));
195 gpioow_ow_bit(void *arg
, int value
)
197 return (onewire_bb_bit(&gpioow_bbops
, arg
, value
));
201 gpioow_bb_rx(void *arg
)
203 struct gpioow_softc
*sc
= arg
;
204 int data
= sc
->sc_data
;
206 data
&= ~(GPIO_PIN_INPUT
| GPIO_PIN_OUTPUT
| GPIO_PIN_TRISTATE
);
207 data
|= GPIO_PIN_INPUT
;
208 if (data
& GPIO_PIN_PUSHPULL
)
209 data
|= GPIO_PIN_TRISTATE
;
210 if (sc
->sc_data
!= data
) {
212 gpio_pin_ctl(sc
->sc_gpio
, &sc
->sc_map
, GPIOOW_PIN_DATA
,
218 gpioow_bb_tx(void *arg
)
220 struct gpioow_softc
*sc
= arg
;
221 int data
= sc
->sc_data
;
223 data
&= ~(GPIO_PIN_INPUT
| GPIO_PIN_OUTPUT
| GPIO_PIN_TRISTATE
);
224 data
|= GPIO_PIN_OUTPUT
;
225 if (sc
->sc_data
!= data
) {
227 gpio_pin_ctl(sc
->sc_gpio
, &sc
->sc_map
, GPIOOW_PIN_DATA
,
233 gpioow_bb_get(void *arg
)
235 struct gpioow_softc
*sc
= arg
;
237 return (gpio_pin_read(sc
->sc_gpio
, &sc
->sc_map
, GPIOOW_PIN_DATA
) ==
238 GPIO_PIN_HIGH
? 1 : 0);
242 gpioow_bb_set(void *arg
, int value
)
244 struct gpioow_softc
*sc
= arg
;
246 gpio_pin_write(sc
->sc_gpio
, &sc
->sc_map
, GPIOOW_PIN_DATA
,
247 value
? GPIO_PIN_HIGH
: GPIO_PIN_LOW
);