1 /* $OpenBSD: pca9554.c,v 1.17 2008/09/10 16:13:43 reyk Exp $ */ 2 3 /* 4 * Copyright (c) 2005 Theo de Raadt 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 #include <sys/param.h> 20 #include <sys/systm.h> 21 #include <sys/device.h> 22 #include <sys/gpio.h> 23 #include <sys/sensors.h> 24 25 #include <dev/i2c/i2cvar.h> 26 27 #include <dev/gpio/gpiovar.h> 28 29 /* Philips 9554/6/7 registers */ 30 #define PCA9554_IN 0x00 31 #define PCA9554_OUT 0x01 32 #define PCA9554_POLARITY 0x02 33 #define PCA9554_CONFIG 0x03 34 35 /* Philips 9555 registers */ 36 #define PCA9555_IN0 0x00 37 #define PCA9555_IN1 0x01 38 #define PCA9555_OUT0 0x02 39 #define PCA9555_OUT1 0x03 40 #define PCA9555_POLARITY0 0x04 41 #define PCA9555_POLARITY1 0x05 42 #define PCA9555_CONFIG0 0x06 43 #define PCA9555_CONFIG1 0x07 44 45 /* Sensors */ 46 #define PCAGPIO_NPINS 16 47 48 #define PCAGPIO_NPORTS 2 49 #define PCAGPIO_PORT(_pin) ((_pin) > 7 ? 1 : 0) 50 #define PCAGPIO_BIT(_pin) (1 << ((_pin) % 8)) 51 52 /* Register mapping index */ 53 enum pcigpio_cmd { 54 PCAGPIO_IN = 0, 55 PCAGPIO_OUT, 56 PCAGPIO_POLARITY, 57 PCAGPIO_CONFIG, 58 PCAGPIO_MAX 59 }; 60 61 struct pcagpio_softc { 62 struct device sc_dev; 63 i2c_tag_t sc_tag; 64 i2c_addr_t sc_addr; 65 66 u_int8_t sc_npins; 67 u_int8_t sc_control[PCAGPIO_NPORTS]; 68 u_int8_t sc_polarity[PCAGPIO_NPORTS]; 69 u_int8_t sc_regs[PCAGPIO_NPORTS][PCAGPIO_MAX]; 70 71 struct gpio_chipset_tag sc_gpio_gc; 72 gpio_pin_t sc_gpio_pins[PCAGPIO_NPINS]; 73 74 struct ksensor sc_sensor[PCAGPIO_NPINS]; 75 struct ksensordev sc_sensordev; 76 }; 77 78 int pcagpio_match(struct device *, void *, void *); 79 void pcagpio_attach(struct device *, struct device *, void *); 80 int pcagpio_init(struct pcagpio_softc *, int, u_int8_t *); 81 void pcagpio_refresh(void *); 82 83 int pcagpio_gpio_pin_read(void *, int); 84 void pcagpio_gpio_pin_write(void *, int, int); 85 void pcagpio_gpio_pin_ctl(void *, int, int); 86 87 struct cfattach pcagpio_ca = { 88 sizeof(struct pcagpio_softc), pcagpio_match, pcagpio_attach 89 }; 90 91 struct cfdriver pcagpio_cd = { 92 NULL, "pcagpio", DV_DULL 93 }; 94 95 int 96 pcagpio_match(struct device *parent, void *match, void *aux) 97 { 98 struct i2c_attach_args *ia = aux; 99 100 if (strcmp(ia->ia_name, "PCA9554") == 0 || 101 strcmp(ia->ia_name, "PCA9554M") == 0 || 102 strcmp(ia->ia_name, "pca9555") == 0 || 103 strcmp(ia->ia_name, "pca9556") == 0 || 104 strcmp(ia->ia_name, "pca9557") == 0) 105 return (1); 106 return (0); 107 } 108 109 void 110 pcagpio_attach(struct device *parent, struct device *self, void *aux) 111 { 112 struct pcagpio_softc *sc = (struct pcagpio_softc *)self; 113 struct i2c_attach_args *ia = aux; 114 struct gpiobus_attach_args gba; 115 int outputs = 0, i, port, bit; 116 u_int8_t data[PCAGPIO_NPORTS]; 117 118 sc->sc_tag = ia->ia_tag; 119 sc->sc_addr = ia->ia_addr; 120 121 if (strcmp(ia->ia_name, "pca9555") == 0) { 122 /* The pca9555 has two 8 bit ports */ 123 sc->sc_regs[0][PCAGPIO_IN] = PCA9555_IN0; 124 sc->sc_regs[0][PCAGPIO_OUT] = PCA9555_OUT0; 125 sc->sc_regs[0][PCAGPIO_POLARITY] = PCA9555_POLARITY0; 126 sc->sc_regs[0][PCAGPIO_CONFIG] = PCA9555_CONFIG0; 127 sc->sc_regs[1][PCAGPIO_IN] = PCA9555_IN1; 128 sc->sc_regs[1][PCAGPIO_OUT] = PCA9555_OUT1; 129 sc->sc_regs[1][PCAGPIO_POLARITY] = PCA9555_POLARITY1; 130 sc->sc_regs[1][PCAGPIO_CONFIG] = PCA9555_CONFIG1; 131 sc->sc_npins = 16; 132 } else { 133 /* All other supported devices have one 8 bit port */ 134 sc->sc_regs[0][PCAGPIO_IN] = PCA9554_IN; 135 sc->sc_regs[0][PCAGPIO_OUT] = PCA9554_OUT; 136 sc->sc_regs[0][PCAGPIO_POLARITY] = PCA9554_POLARITY; 137 sc->sc_regs[0][PCAGPIO_CONFIG] = PCA9554_CONFIG; 138 sc->sc_npins = 8; 139 } 140 if (pcagpio_init(sc, 0, &data[0]) != 0) 141 return; 142 if (sc->sc_npins > 8 && pcagpio_init(sc, 1, &data[1]) != 0) 143 return; 144 145 /* Initialize sensor data. */ 146 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 147 sizeof(sc->sc_sensordev.xname)); 148 149 for (i = 0; i < sc->sc_npins; i++) { 150 port = PCAGPIO_PORT(i); 151 bit = PCAGPIO_BIT(i); 152 sc->sc_sensor[i].type = SENSOR_INDICATOR; 153 if ((sc->sc_control[port] & bit) == 0) { 154 strlcpy(sc->sc_sensor[i].desc, "out", 155 sizeof(sc->sc_sensor[i].desc)); 156 outputs++; 157 } else 158 strlcpy(sc->sc_sensor[i].desc, "in", 159 sizeof(sc->sc_sensor[i].desc)); 160 } 161 162 if (sensor_task_register(sc, pcagpio_refresh, 5) == NULL) { 163 printf(", unable to register update task\n"); 164 return; 165 } 166 167 #if 0 168 for (i = 0; i < sc->sc_npins; i++) 169 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]); 170 sensordev_install(&sc->sc_sensordev); 171 #endif 172 173 printf(":"); 174 if (sc->sc_npins - outputs) 175 printf(" %d inputs", sc->sc_npins - outputs); 176 if (outputs) 177 printf(" %d outputs", outputs); 178 printf("\n"); 179 180 for (i = 0; i < sc->sc_npins; i++) { 181 port = PCAGPIO_PORT(i); 182 bit = PCAGPIO_BIT(i); 183 184 sc->sc_gpio_pins[i].pin_num = i; 185 sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; 186 187 if ((sc->sc_control[port] & bit) == 0) { 188 sc->sc_gpio_pins[i].pin_flags = GPIO_PIN_OUTPUT; 189 sc->sc_gpio_pins[i].pin_state = data[port] & 190 bit ? GPIO_PIN_HIGH : GPIO_PIN_LOW; 191 } 192 } 193 194 /* Create controller tag */ 195 sc->sc_gpio_gc.gp_cookie = sc; 196 sc->sc_gpio_gc.gp_pin_read = pcagpio_gpio_pin_read; 197 sc->sc_gpio_gc.gp_pin_write = pcagpio_gpio_pin_write; 198 sc->sc_gpio_gc.gp_pin_ctl = pcagpio_gpio_pin_ctl; 199 200 gba.gba_name = "gpio"; 201 gba.gba_gc = &sc->sc_gpio_gc; 202 gba.gba_pins = sc->sc_gpio_pins; 203 gba.gba_npins = sc->sc_npins; 204 205 config_found(&sc->sc_dev, &gba, gpiobus_print); 206 207 } 208 209 int 210 pcagpio_init(struct pcagpio_softc *sc, int port, u_int8_t *datap) 211 { 212 u_int8_t cmd, data; 213 214 cmd = sc->sc_regs[port][PCAGPIO_CONFIG]; 215 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 216 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 217 printf(": failed to initialize\n"); 218 return (-1); 219 } 220 sc->sc_control[port] = data; 221 cmd = sc->sc_regs[port][PCAGPIO_POLARITY]; 222 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 223 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 224 printf(": failed to initialize\n"); 225 return (-1); 226 } 227 sc->sc_polarity[port] = data; 228 cmd = sc->sc_regs[port][PCAGPIO_OUT]; 229 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 230 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 231 printf(": failed to initialize\n"); 232 return (-1); 233 } 234 235 *datap = data; 236 return (0); 237 } 238 239 void 240 pcagpio_refresh(void *arg) 241 { 242 struct pcagpio_softc *sc = arg; 243 u_int8_t cmd, bit, in[PCAGPIO_NPORTS], out[PCAGPIO_NPORTS]; 244 int i, port; 245 246 iic_acquire_bus(sc->sc_tag, 0); 247 248 for (i = 0; i < PCAGPIO_NPORTS; i++) { 249 cmd = sc->sc_regs[i][PCAGPIO_IN]; 250 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 251 sc->sc_addr, &cmd, sizeof cmd, &in[i], sizeof in[i], 0)) 252 goto invalid; 253 254 cmd = sc->sc_regs[i][PCAGPIO_OUT]; 255 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 256 sc->sc_addr, &cmd, sizeof cmd, &out[i], sizeof out[i], 0)) 257 goto invalid; 258 } 259 260 for (i = 0; i < sc->sc_npins; i++) { 261 port = PCAGPIO_PORT(i); 262 bit = PCAGPIO_BIT(i); 263 if ((sc->sc_control[port] & bit)) 264 sc->sc_sensor[i].value = (in[port] & bit) ? 1 : 0; 265 else 266 sc->sc_sensor[i].value = (out[port] & bit) ? 1 : 0; 267 } 268 269 invalid: 270 iic_release_bus(sc->sc_tag, 0); 271 } 272 273 274 int 275 pcagpio_gpio_pin_read(void *arg, int pin) 276 { 277 struct pcagpio_softc *sc = arg; 278 u_int8_t cmd, in; 279 int port, bit; 280 281 port = PCAGPIO_PORT(pin); 282 bit = PCAGPIO_BIT(pin); 283 284 cmd = sc->sc_regs[port][PCAGPIO_IN]; 285 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 286 sc->sc_addr, &cmd, sizeof cmd, &in, sizeof in, 0)) 287 return 0; 288 return ((in ^ sc->sc_polarity[port]) & bit) ? 1 : 0; 289 } 290 291 void 292 pcagpio_gpio_pin_write(void *arg, int pin, int value) 293 { 294 struct pcagpio_softc *sc = arg; 295 u_int8_t cmd, out, mask; 296 int port, bit; 297 298 port = PCAGPIO_PORT(pin); 299 bit = PCAGPIO_BIT(pin); 300 301 mask = 0xff ^ bit; 302 cmd = sc->sc_regs[port][PCAGPIO_OUT]; 303 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 304 sc->sc_addr, &cmd, sizeof cmd, &out, sizeof out, 0)) 305 return; 306 out = (out & mask) | (value ? bit : 0); 307 308 cmd = sc->sc_regs[port][PCAGPIO_OUT]; 309 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 310 sc->sc_addr, &cmd, sizeof cmd, &out, sizeof out, 0)) 311 return; 312 } 313 314 void 315 pcagpio_gpio_pin_ctl(void *arg, int pin, int flags) 316 { 317 #if 0 318 struct pcagpio_softc *sc = arg; 319 u_int32_t conf; 320 321 pcagpio_gpio_pin_select(sc, pin); 322 conf = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, 323 GSCGPIO_CONF); 324 325 conf &= ~(GSCGPIO_CONF_OUTPUTEN | GSCGPIO_CONF_PUSHPULL | 326 GSCGPIO_CONF_PULLUP); 327 if ((flags & GPIO_PIN_TRISTATE) == 0) 328 conf |= GSCGPIO_CONF_OUTPUTEN; 329 if (flags & GPIO_PIN_PUSHPULL) 330 conf |= GSCGPIO_CONF_PUSHPULL; 331 if (flags & GPIO_PIN_PULLUP) 332 conf |= GSCGPIO_CONF_PULLUP; 333 bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, 334 GSCGPIO_CONF, conf); 335 #endif 336 } 337