Annotation of sys/dev/gpio/gpioiic.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: gpioiic.c,v 1.7 2007/06/05 08:37:20 jsg Exp $ */
2:
3: /*
4: * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: /*
20: * I2C bus bit-banging through GPIO pins.
21: */
22:
23: #include <sys/param.h>
24: #include <sys/systm.h>
25: #include <sys/device.h>
26: #include <sys/gpio.h>
27: #include <sys/rwlock.h>
28:
29: #include <dev/gpio/gpiovar.h>
30:
31: #include <dev/i2c/i2cvar.h>
32: #include <dev/i2c/i2c_bitbang.h>
33:
34: #define GPIOIIC_PIN_SDA 0
35: #define GPIOIIC_PIN_SCL 1
36: #define GPIOIIC_NPINS 2
37:
38: #define GPIOIIC_SDA 0x01
39: #define GPIOIIC_SCL 0x02
40:
41: struct gpioiic_softc {
42: struct device sc_dev;
43:
44: void * sc_gpio;
45: struct gpio_pinmap sc_map;
46: int __map[GPIOIIC_NPINS];
47:
48: struct i2c_controller sc_i2c_tag;
49: struct rwlock sc_i2c_lock;
50:
51: int sc_sda;
52: int sc_scl;
53: };
54:
55: int gpioiic_match(struct device *, void *, void *);
56: void gpioiic_attach(struct device *, struct device *, void *);
57: int gpioiic_detach(struct device *, int);
58:
59: int gpioiic_i2c_acquire_bus(void *, int);
60: void gpioiic_i2c_release_bus(void *, int);
61: int gpioiic_i2c_send_start(void *, int);
62: int gpioiic_i2c_send_stop(void *, int);
63: int gpioiic_i2c_initiate_xfer(void *, i2c_addr_t, int);
64: int gpioiic_i2c_read_byte(void *, u_int8_t *, int);
65: int gpioiic_i2c_write_byte(void *, u_int8_t, int);
66:
67: void gpioiic_bb_set_bits(void *, u_int32_t);
68: void gpioiic_bb_set_dir(void *, u_int32_t);
69: u_int32_t gpioiic_bb_read_bits(void *);
70:
71: struct cfattach gpioiic_ca = {
72: sizeof(struct gpioiic_softc),
73: gpioiic_match,
74: gpioiic_attach,
75: gpioiic_detach
76: };
77:
78: struct cfdriver gpioiic_cd = {
79: NULL, "gpioiic", DV_DULL
80: };
81:
82: static const struct i2c_bitbang_ops gpioiic_bbops = {
83: gpioiic_bb_set_bits,
84: gpioiic_bb_set_dir,
85: gpioiic_bb_read_bits,
86: { GPIOIIC_SDA, GPIOIIC_SCL, GPIOIIC_SDA, 0 }
87: };
88:
89: int
90: gpioiic_match(struct device *parent, void *match, void *aux)
91: {
92: struct cfdata *cf = match;
93:
94: return (strcmp(cf->cf_driver->cd_name, "gpioiic") == 0);
95: }
96:
97: void
98: gpioiic_attach(struct device *parent, struct device *self, void *aux)
99: {
100: struct gpioiic_softc *sc = (struct gpioiic_softc *)self;
101: struct gpio_attach_args *ga = aux;
102: struct i2cbus_attach_args iba;
103: int caps;
104:
105: /* Check that we have enough pins */
106: if (gpio_npins(ga->ga_mask) != GPIOIIC_NPINS) {
107: printf(": invalid pin mask\n");
108: return;
109: }
110:
111: /* Map pins */
112: sc->sc_gpio = ga->ga_gpio;
113: sc->sc_map.pm_map = sc->__map;
114: if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask,
115: &sc->sc_map)) {
116: printf(": can't map pins\n");
117: return;
118: }
119:
120: /* Configure SDA pin */
121: caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA);
122: if (!(caps & GPIO_PIN_OUTPUT)) {
123: printf(": SDA pin is unable to drive output\n");
124: goto fail;
125: }
126: if (!(caps & GPIO_PIN_INPUT)) {
127: printf(": SDA pin is unable to read input\n");
128: goto fail;
129: }
130: printf(": SDA[%d]", sc->sc_map.pm_map[GPIOIIC_PIN_SDA]);
131: sc->sc_sda = GPIO_PIN_OUTPUT;
132: if (caps & GPIO_PIN_OPENDRAIN) {
133: printf(" open-drain");
134: sc->sc_sda |= GPIO_PIN_OPENDRAIN;
135: } else if ((caps & GPIO_PIN_PUSHPULL) && (caps & GPIO_PIN_TRISTATE)) {
136: printf(" push-pull tri-state");
137: sc->sc_sda |= GPIO_PIN_PUSHPULL;
138: }
139: if (caps & GPIO_PIN_PULLUP) {
140: printf(" pull-up");
141: sc->sc_sda |= GPIO_PIN_PULLUP;
142: }
143: gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA, sc->sc_sda);
144:
145: /* Configure SCL pin */
146: caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL);
147: if (!(caps & GPIO_PIN_OUTPUT)) {
148: printf(": SCL pin is unable to drive output\n");
149: goto fail;
150: }
151: printf(", SCL[%d]", sc->sc_map.pm_map[GPIOIIC_PIN_SCL]);
152: sc->sc_scl = GPIO_PIN_OUTPUT;
153: if (caps & GPIO_PIN_OPENDRAIN) {
154: printf(" open-drain");
155: sc->sc_scl |= GPIO_PIN_OPENDRAIN;
156: if (caps & GPIO_PIN_PULLUP) {
157: printf(" pull-up");
158: sc->sc_scl |= GPIO_PIN_PULLUP;
159: }
160: } else if (caps & GPIO_PIN_PUSHPULL) {
161: printf(" push-pull");
162: sc->sc_scl |= GPIO_PIN_PUSHPULL;
163: }
164: gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL, sc->sc_scl);
165:
166: printf("\n");
167:
168: /* Attach I2C bus */
169: rw_init(&sc->sc_i2c_lock, "iiclk");
170: sc->sc_i2c_tag.ic_cookie = sc;
171: sc->sc_i2c_tag.ic_acquire_bus = gpioiic_i2c_acquire_bus;
172: sc->sc_i2c_tag.ic_release_bus = gpioiic_i2c_release_bus;
173: sc->sc_i2c_tag.ic_send_start = gpioiic_i2c_send_start;
174: sc->sc_i2c_tag.ic_send_stop = gpioiic_i2c_send_stop;
175: sc->sc_i2c_tag.ic_initiate_xfer = gpioiic_i2c_initiate_xfer;
176: sc->sc_i2c_tag.ic_read_byte = gpioiic_i2c_read_byte;
177: sc->sc_i2c_tag.ic_write_byte = gpioiic_i2c_write_byte;
178:
179: bzero(&iba, sizeof(iba));
180: iba.iba_name = "iic";
181: iba.iba_tag = &sc->sc_i2c_tag;
182: config_found(self, &iba, iicbus_print);
183:
184: return;
185:
186: fail:
187: gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
188: }
189:
190: int
191: gpioiic_detach(struct device *self, int flags)
192: {
193: return (0);
194: }
195:
196: int
197: gpioiic_i2c_acquire_bus(void *cookie, int flags)
198: {
199: struct gpioiic_softc *sc = cookie;
200:
201: if (cold || (flags & I2C_F_POLL))
202: return (0);
203:
204: return (rw_enter(&sc->sc_i2c_lock, RW_WRITE | RW_INTR));
205: }
206:
207: void
208: gpioiic_i2c_release_bus(void *cookie, int flags)
209: {
210: struct gpioiic_softc *sc = cookie;
211:
212: if (cold || (flags & I2C_F_POLL))
213: return;
214:
215: rw_exit(&sc->sc_i2c_lock);
216: }
217:
218: int
219: gpioiic_i2c_send_start(void *cookie, int flags)
220: {
221: return (i2c_bitbang_send_start(cookie, flags, &gpioiic_bbops));
222: }
223:
224: int
225: gpioiic_i2c_send_stop(void *cookie, int flags)
226: {
227: return (i2c_bitbang_send_stop(cookie, flags, &gpioiic_bbops));
228: }
229:
230: int
231: gpioiic_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags)
232: {
233: return (i2c_bitbang_initiate_xfer(cookie, addr, flags, &gpioiic_bbops));
234: }
235:
236: int
237: gpioiic_i2c_read_byte(void *cookie, u_int8_t *bytep, int flags)
238: {
239: return (i2c_bitbang_read_byte(cookie, bytep, flags, &gpioiic_bbops));
240: }
241:
242: int
243: gpioiic_i2c_write_byte(void *cookie, u_int8_t byte, int flags)
244: {
245: return (i2c_bitbang_write_byte(cookie, byte, flags, &gpioiic_bbops));
246: }
247:
248: void
249: gpioiic_bb_set_bits(void *cookie, u_int32_t bits)
250: {
251: struct gpioiic_softc *sc = cookie;
252:
253: gpio_pin_write(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA,
254: bits & GPIOIIC_SDA ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
255: gpio_pin_write(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL,
256: bits & GPIOIIC_SCL ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
257: }
258:
259: void
260: gpioiic_bb_set_dir(void *cookie, u_int32_t bits)
261: {
262: struct gpioiic_softc *sc = cookie;
263: int sda = sc->sc_sda;
264:
265: sda &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE);
266: sda |= (bits & GPIOIIC_SDA ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT);
267: if ((sda & GPIO_PIN_PUSHPULL) && !(bits & GPIOIIC_SDA))
268: sda |= GPIO_PIN_TRISTATE;
269: if (sc->sc_sda != sda) {
270: sc->sc_sda = sda;
271: gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA,
272: sc->sc_sda);
273: }
274: }
275:
276: u_int32_t
277: gpioiic_bb_read_bits(void *cookie)
278: {
279: struct gpioiic_softc *sc = cookie;
280:
281: return (gpio_pin_read(sc->sc_gpio, &sc->sc_map,
282: GPIOIIC_PIN_SDA) == GPIO_PIN_HIGH ? GPIOIIC_SDA : 0);
283: }
CVSweb