42#include <sys/kernel.h>
43#include <sys/module.h>
46#include <sys/sysctl.h>
48#include <machine/bus.h>
50#include <dev/ofw/openfirm.h>
51#include <dev/ofw/ofw_bus.h>
52#include <dev/ofw/ofw_bus_subr.h>
57#include <dev/gpio/gpiobusvar.h>
62#define IN_PORT_REG 0x00
63#define OUT_PORT_REG 0x02
64#define POLARITY_INV_REG 0x04
70 (GPIO_PIN_OUTPUT | GPIO_PIN_INPUT \
71 | GPIO_PIN_PUSHPULL | GPIO_PIN_INVIN)
74#define dbg_dev_printf(dev, fmt, args...) \
75 device_printf(dev, fmt, ##args)
77#define dbg_dev_printf(dev, fmt, args...)
80#define TCA6416_BIT_FROM_PIN(pin) (pin % PINS_PER_REG)
81#define TCA6416_REG_ADDR(pin, baseaddr) (baseaddr | (pin / PINS_PER_REG))
105static void tca6416_regdump_setup(device_t
dev);
106static int tca6416_regdump_sysctl(SYSCTL_HANDLER_ARGS);
151 sc = device_get_softc(
dev);
175 uint8_t buffer[2] = {reg,
val};
177 sc = device_get_softc(
dev);
192 if (!ofw_bus_status_okay(
dev))
198 device_set_desc(
dev,
"TCA6416 I/O expander");
199 return (BUS_PROBE_DEFAULT);
207 sc = device_get_softc(
dev);
209 sc->
addr = iicbus_get_addr(
dev);
211 mtx_init(&sc->
mtx,
"tca6416 gpio",
"gpio", MTX_DEF);
215 device_printf(
dev,
"Could not create busdev child\n");
220 tca6416_regdump_setup(
dev);
231 sc = device_get_softc(
dev);
234 gpiobus_detach_bus(sc->
busdev);
236 mtx_destroy(&sc->
mtx);
246 sc = device_get_softc(
dev);
266 if (pin >=
NUM_PINS || caps == NULL)
278 uint8_t reg_addr, reg_bit,
val;
280 sc = device_get_softc(
dev);
282 if (pin >=
NUM_PINS || pflags == NULL)
292 *pflags = (
val & (1 << reg_bit))
293 ? GPIO_PIN_INPUT : GPIO_PIN_OUTPUT;
301 if (
val & (1 << reg_bit))
302 *pflags |= GPIO_PIN_INVIN;
310 uint8_t reg_addr, inv_reg_addr, reg_bit,
val, inv_val;
314 sc = device_get_softc(
dev);
332 if (flags & GPIO_PIN_INPUT)
333 val |= (1 << reg_bit);
334 else if (flags & GPIO_PIN_OUTPUT)
335 val &= ~(1 << reg_bit);
337 if (flags & GPIO_PIN_INVIN)
338 inv_val |= (1 << reg_bit);
340 inv_val &= ~(1 << reg_bit);
348 mtx_unlock(&sc->
mtx);
356 if (pin >=
NUM_PINS || name == NULL)
359 snprintf(name, GPIOMAXNAME,
"gpio_P%d%d", pin /
PINS_PER_REG,
369 uint8_t reg_bit, reg_addr, reg_pvalue;
372 sc = device_get_softc(
dev);
374 if (pin >=
NUM_PINS || pval == NULL)
386 *pval = reg_pvalue & (1 << reg_bit) ? 1 : 0;
395 uint8_t reg_addr, reg_bit, reg_value;
398 sc = device_get_softc(
dev);
413 mtx_unlock(&sc->
mtx);
418 reg_value |= (1 << reg_bit);
420 reg_value &= ~(1 << reg_bit);
426 mtx_unlock(&sc->
mtx);
430 mtx_unlock(&sc->
mtx);
440 uint8_t reg_addr, reg_bit, reg_value;
442 sc = device_get_softc(
dev);
456 mtx_unlock(&sc->
mtx);
461 reg_value ^= (1 << reg_bit);
467 mtx_unlock(&sc->
mtx);
474tca6416_regdump_setup(device_t
dev)
476 struct sysctl_ctx_list *ctx;
477 struct sysctl_oid *node;
479 ctx = device_get_sysctl_ctx(
dev);
480 node = device_get_sysctl_tree(
dev);
482 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
"in_reg_1",
484 tca6416_regdump_sysctl,
"A",
"Input port 1");
485 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
"in_reg_2",
486 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
dev,
487 IN_PORT_REG | 1, tca6416_regdump_sysctl,
"A",
"Input port 2");
488 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
"out_reg_1",
490 tca6416_regdump_sysctl,
"A",
"Output port 1");
491 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
"out_reg_2",
493 | 1, tca6416_regdump_sysctl,
"A",
"Output port 2");
494 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
"pol_inv_1",
495 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
dev,
497 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
"pol_inv_2",
498 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
dev,
501 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
"conf_reg_1",
502 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
dev,
503 CONF_REG, tca6416_regdump_sysctl,
"A",
"Configuration 1");
504 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
"conf_reg_2",
505 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
dev,
506 CONF_REG | 1, tca6416_regdump_sysctl,
"A",
"Configuration 2");
510tca6416_regdump_sysctl(SYSCTL_HANDLER_ARGS)
518 dev = (device_t)arg1;
520 sc = device_get_softc(
dev);
528 len = snprintf(
buf, 5,
"0x%02x", regval);
530 error = sysctl_handle_string(oidp,
buf,
len, req);
int iic2errno(int iic_status)
int iicbus_transfer_excl(device_t dev, struct iic_msg *msgs, uint32_t nmsgs, int how)
static int tca6416_pin_getname(device_t, uint32_t, char *)
#define dbg_dev_printf(dev, fmt, args...)
static int tca6416_attach(device_t)
DRIVER_MODULE(tca6416, iicbus, tca6416_driver, tca6416_devclass, 0, 0)
static int tca6416_pin_get(device_t, uint32_t, unsigned int *)
#define TCA6416_BIT_FROM_PIN(pin)
static int tca6416_pin_getcaps(device_t, uint32_t, uint32_t *)
static devclass_t tca6416_devclass
static int tca6416_pin_max(device_t, int *)
static int tca6416_pin_toggle(device_t, uint32_t)
static int tca6416_pin_set(device_t, uint32_t, unsigned int)
static device_method_t tca6416_methods[]
static int tca6416_pin_setflags(device_t, uint32_t, uint32_t)
static int tca6416_write(device_t, uint8_t, uint8_t)
static int tca6416_detach(device_t)
static int tca6416_read(device_t, uint8_t, uint8_t *)
#define TCA6416_REG_ADDR(pin, baseaddr)
static struct ofw_compat_data compat_data[]
static int tca6416_pin_getflags(device_t, uint32_t, uint32_t *)
static driver_t tca6416_driver
MODULE_VERSION(tca6416, 1)
static device_t tca6416_get_bus(device_t)
static int tca6416_probe(device_t)