1 /* $OpenBSD: gdiumiic.c,v 1.6 2013/04/19 23:44:34 miod Exp $ */ 2 3 /* 4 * Copyright (c) 2010 Miodrag Vallat. 5 * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org> 6 * 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. 10 * 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. 18 */ 19 20 /* 21 * I2C bus bit-banging through GPIO pins. 22 * 23 * Derived from /sys/dev/gpio/gpioiic.c, with SDA and SCL pin order 24 * exchanged, and knowledge of bus contents added. 25 */ 26 27 #include <sys/param.h> 28 #include <sys/systm.h> 29 #include <sys/device.h> 30 #include <sys/gpio.h> 31 #include <sys/rwlock.h> 32 33 #include <machine/autoconf.h> 34 35 #include <dev/gpio/gpiovar.h> 36 37 #include <dev/i2c/i2cvar.h> 38 #include <dev/i2c/i2c_bitbang.h> 39 40 #define GPIOIIC_PIN_SDA 1 41 #define GPIOIIC_PIN_SCL 0 42 #define GPIOIIC_NPINS 2 43 44 #define GPIOIIC_SDA 0x02 45 #define GPIOIIC_SCL 0x01 46 47 struct gdiumiic_softc { 48 struct device sc_dev; 49 50 void * sc_gpio; 51 struct gpio_pinmap sc_map; 52 int __map[GPIOIIC_NPINS]; 53 54 struct i2c_controller sc_i2c_tag; 55 struct rwlock sc_i2c_lock; 56 57 int sc_sda; 58 int sc_scl; 59 }; 60 61 int gdiumiic_match(struct device *, void *, void *); 62 void gdiumiic_attach(struct device *, struct device *, void *); 63 int gdiumiic_detach(struct device *, int); 64 65 int gdiumiic_i2c_acquire_bus(void *, int); 66 void gdiumiic_i2c_release_bus(void *, int); 67 int gdiumiic_i2c_send_start(void *, int); 68 int gdiumiic_i2c_send_stop(void *, int); 69 int gdiumiic_i2c_initiate_xfer(void *, i2c_addr_t, int); 70 int gdiumiic_i2c_read_byte(void *, u_int8_t *, int); 71 int gdiumiic_i2c_write_byte(void *, u_int8_t, int); 72 73 void gdiumiic_bb_set_bits(void *, u_int32_t); 74 void gdiumiic_bb_set_dir(void *, u_int32_t); 75 u_int32_t gdiumiic_bb_read_bits(void *); 76 77 int gdiumiic_bustype(struct gpio_attach_args *); 78 void gdiumiic_sensors_scan(struct device *, 79 struct i2cbus_attach_args *, void *); 80 81 struct cfattach gdiumiic_ca = { 82 sizeof(struct gdiumiic_softc), 83 gdiumiic_match, 84 gdiumiic_attach, 85 gdiumiic_detach 86 }; 87 88 struct cfdriver gdiumiic_cd = { 89 NULL, "gdiumiic", DV_DULL 90 }; 91 92 static const struct i2c_bitbang_ops gdiumiic_bbops = { 93 gdiumiic_bb_set_bits, 94 gdiumiic_bb_set_dir, 95 gdiumiic_bb_read_bits, 96 { GPIOIIC_SDA, GPIOIIC_SCL, GPIOIIC_SDA, 0 } 97 }; 98 99 #define GDIUMIIC_BUSTYPE_SENSORS 0 100 #define GDIUMIIC_BUSTYPE_VIDCTRL 1 101 102 int 103 gdiumiic_bustype(struct gpio_attach_args *ga) 104 { 105 extern int gdium_revision; 106 107 /* 108 * Hardware pin connections depend upon the motherboard revision. 109 * XXX magic numbers (should match kernel configuration) 110 */ 111 switch (gdium_revision) { 112 case 0: 113 if (ga->ga_offset == 46 && ga->ga_mask == 0x03) 114 return GDIUMIIC_BUSTYPE_SENSORS; 115 break; 116 default: 117 if (ga->ga_offset == 6 && ga->ga_mask == 0x81) 118 return GDIUMIIC_BUSTYPE_SENSORS; 119 break; 120 } 121 122 if (ga->ga_offset == 41 && ga->ga_mask == 0x03) 123 return GDIUMIIC_BUSTYPE_VIDCTRL; 124 125 return -1; 126 127 } 128 129 int 130 gdiumiic_match(struct device *parent, void *match, void *aux) 131 { 132 struct cfdata *cf = match; 133 struct gpio_attach_args *ga = aux; 134 135 if (ga->ga_offset == -1 || gdiumiic_bustype(ga) < 0) 136 return 0; 137 138 return (sys_platform->system_type == LOONGSON_GDIUM && 139 strcmp(cf->cf_driver->cd_name, "gdiumiic") == 0); 140 } 141 142 void 143 gdiumiic_attach(struct device *parent, struct device *self, void *aux) 144 { 145 struct gdiumiic_softc *sc = (struct gdiumiic_softc *)self; 146 struct gpio_attach_args *ga = aux; 147 struct i2cbus_attach_args iba; 148 int caps; 149 150 /* Check that we have enough pins */ 151 if (gpio_npins(ga->ga_mask) != GPIOIIC_NPINS) { 152 printf(": invalid pin mask\n"); 153 return; 154 } 155 156 /* Map pins */ 157 sc->sc_gpio = ga->ga_gpio; 158 sc->sc_map.pm_map = sc->__map; 159 if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask, 160 &sc->sc_map)) { 161 printf(": can't map pins\n"); 162 return; 163 } 164 165 /* Configure SDA pin */ 166 caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA); 167 if (!(caps & GPIO_PIN_OUTPUT)) { 168 printf(": SDA pin is unable to drive output\n"); 169 goto fail; 170 } 171 if (!(caps & GPIO_PIN_INPUT)) { 172 printf(": SDA pin is unable to read input\n"); 173 goto fail; 174 } 175 printf(": SDA[%d]", sc->sc_map.pm_map[GPIOIIC_PIN_SDA]); 176 sc->sc_sda = GPIO_PIN_OUTPUT; 177 #if 0 178 if (caps & GPIO_PIN_OPENDRAIN) { 179 printf(" open-drain"); 180 sc->sc_sda |= GPIO_PIN_OPENDRAIN; 181 } else if ((caps & GPIO_PIN_PUSHPULL) && (caps & GPIO_PIN_TRISTATE)) { 182 printf(" push-pull tri-state"); 183 sc->sc_sda |= GPIO_PIN_PUSHPULL; 184 } 185 if (caps & GPIO_PIN_PULLUP) { 186 printf(" pull-up"); 187 sc->sc_sda |= GPIO_PIN_PULLUP; 188 } 189 #endif 190 gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA, sc->sc_sda); 191 192 /* Configure SCL pin */ 193 caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL); 194 if (!(caps & GPIO_PIN_OUTPUT)) { 195 printf(": SCL pin is unable to drive output\n"); 196 goto fail; 197 } 198 printf(", SCL[%d]", sc->sc_map.pm_map[GPIOIIC_PIN_SCL]); 199 sc->sc_scl = GPIO_PIN_OUTPUT; 200 #if 0 201 if (caps & GPIO_PIN_OPENDRAIN) { 202 printf(" open-drain"); 203 sc->sc_scl |= GPIO_PIN_OPENDRAIN; 204 if (caps & GPIO_PIN_PULLUP) { 205 printf(" pull-up"); 206 sc->sc_scl |= GPIO_PIN_PULLUP; 207 } 208 } else if (caps & GPIO_PIN_PUSHPULL) { 209 printf(" push-pull"); 210 sc->sc_scl |= GPIO_PIN_PUSHPULL; 211 } 212 #endif 213 gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL, sc->sc_scl); 214 215 printf("\n"); 216 217 /* Attach I2C bus */ 218 rw_init(&sc->sc_i2c_lock, "iiclk"); 219 sc->sc_i2c_tag.ic_cookie = sc; 220 sc->sc_i2c_tag.ic_acquire_bus = gdiumiic_i2c_acquire_bus; 221 sc->sc_i2c_tag.ic_release_bus = gdiumiic_i2c_release_bus; 222 sc->sc_i2c_tag.ic_send_start = gdiumiic_i2c_send_start; 223 sc->sc_i2c_tag.ic_send_stop = gdiumiic_i2c_send_stop; 224 sc->sc_i2c_tag.ic_initiate_xfer = gdiumiic_i2c_initiate_xfer; 225 sc->sc_i2c_tag.ic_read_byte = gdiumiic_i2c_read_byte; 226 sc->sc_i2c_tag.ic_write_byte = gdiumiic_i2c_write_byte; 227 228 bzero(&iba, sizeof(iba)); 229 iba.iba_name = "iic"; 230 iba.iba_tag = &sc->sc_i2c_tag; 231 if (gdiumiic_bustype(ga) == GDIUMIIC_BUSTYPE_SENSORS) 232 iba.iba_bus_scan = gdiumiic_sensors_scan; 233 config_found(self, &iba, iicbus_print); 234 235 return; 236 237 fail: 238 gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); 239 } 240 241 int 242 gdiumiic_detach(struct device *self, int flags) 243 { 244 return (0); 245 } 246 247 int 248 gdiumiic_i2c_acquire_bus(void *cookie, int flags) 249 { 250 struct gdiumiic_softc *sc = cookie; 251 252 if (cold || (flags & I2C_F_POLL)) 253 return (0); 254 255 return (rw_enter(&sc->sc_i2c_lock, RW_WRITE | RW_INTR)); 256 } 257 258 void 259 gdiumiic_i2c_release_bus(void *cookie, int flags) 260 { 261 struct gdiumiic_softc *sc = cookie; 262 263 if (cold || (flags & I2C_F_POLL)) 264 return; 265 266 rw_exit(&sc->sc_i2c_lock); 267 } 268 269 int 270 gdiumiic_i2c_send_start(void *cookie, int flags) 271 { 272 return (i2c_bitbang_send_start(cookie, flags, &gdiumiic_bbops)); 273 } 274 275 int 276 gdiumiic_i2c_send_stop(void *cookie, int flags) 277 { 278 return (i2c_bitbang_send_stop(cookie, flags, &gdiumiic_bbops)); 279 } 280 281 int 282 gdiumiic_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags) 283 { 284 return (i2c_bitbang_initiate_xfer(cookie, addr, flags, &gdiumiic_bbops)); 285 } 286 287 int 288 gdiumiic_i2c_read_byte(void *cookie, u_int8_t *bytep, int flags) 289 { 290 return (i2c_bitbang_read_byte(cookie, bytep, flags, &gdiumiic_bbops)); 291 } 292 293 int 294 gdiumiic_i2c_write_byte(void *cookie, u_int8_t byte, int flags) 295 { 296 return (i2c_bitbang_write_byte(cookie, byte, flags, &gdiumiic_bbops)); 297 } 298 299 void 300 gdiumiic_bb_set_bits(void *cookie, u_int32_t bits) 301 { 302 struct gdiumiic_softc *sc = cookie; 303 304 gpio_pin_write(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA, 305 bits & GPIOIIC_SDA ? GPIO_PIN_HIGH : GPIO_PIN_LOW); 306 gpio_pin_write(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL, 307 bits & GPIOIIC_SCL ? GPIO_PIN_HIGH : GPIO_PIN_LOW); 308 } 309 310 void 311 gdiumiic_bb_set_dir(void *cookie, u_int32_t bits) 312 { 313 struct gdiumiic_softc *sc = cookie; 314 int sda = sc->sc_sda; 315 316 sda &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE); 317 sda |= (bits & GPIOIIC_SDA ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT); 318 #if 0 319 if ((sda & GPIO_PIN_PUSHPULL) && !(bits & GPIOIIC_SDA)) 320 sda |= GPIO_PIN_TRISTATE; 321 #endif 322 if (sc->sc_sda != sda) { 323 sc->sc_sda = sda; 324 gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA, 325 sc->sc_sda); 326 } 327 } 328 329 u_int32_t 330 gdiumiic_bb_read_bits(void *cookie) 331 { 332 struct gdiumiic_softc *sc = cookie; 333 u_int32_t bits = 0; 334 335 if (gpio_pin_read(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA) == 336 GPIO_PIN_HIGH) 337 bits |= GPIOIIC_SDA; 338 if (gpio_pin_read(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL) == 339 GPIO_PIN_HIGH) 340 bits |= GPIOIIC_SCL; 341 342 return bits; 343 } 344 345 /* 346 * Attach devices to the first (sensors + RTC) i2c bus. 347 * 348 * Note that the i2c scan performed by the MI i2c code will fail to 349 * identify our lm75 chip correctly. 350 */ 351 void 352 gdiumiic_sensors_scan(struct device *iicdev, struct i2cbus_attach_args *iba, 353 void *arg) 354 { 355 struct i2c_attach_args ia; 356 /* not worth #define'ing _I2C_PRIVATE for */ 357 extern int iic_print(void *, const char *); 358 359 bzero(&ia, sizeof ia); 360 ia.ia_tag = iba->iba_tag; 361 ia.ia_addr = 0x40; 362 ia.ia_size = 1; 363 ia.ia_name = "stsec"; 364 config_found(iicdev, &ia, iic_print); 365 366 bzero(&ia, sizeof ia); 367 ia.ia_tag = iba->iba_tag; 368 ia.ia_addr = 0x48; 369 ia.ia_size = 1; 370 ia.ia_name = "lm75"; 371 config_found(iicdev, &ia, iic_print); 372 373 bzero(&ia, sizeof ia); 374 ia.ia_tag = iba->iba_tag; 375 ia.ia_addr = 0x68; 376 ia.ia_size = 1; 377 ia.ia_name = "mfokclock"; 378 config_found(iicdev, &ia, iic_print); 379 } 380