static void pcf8563_start(void *xdev) { device_t dev; uint8_t reg = PCF8563_R_SECOND, val; struct iic_msg msgs[] = { { 0, IIC_M_WR, sizeof(reg), ® }, { 0, IIC_M_RD, sizeof(val), &val } }; struct pcf8563_softc *sc; dev = (device_t)xdev; sc = device_get_softc(dev); config_intrhook_disestablish(&sc->enum_hook); /* * NB: PCF8563_R_SECOND_VL doesn't automatically clear when VDD * rises above Vlow again and needs to be cleared manually. * However, apparently this needs all of the time registers to be * set, i.e. pcf8563_settime(), and not just PCF8563_R_SECOND in * order for PCF8563_R_SECOND_VL to stick. Thus, we just issue a * warning here rather than failing with ENXIO in case it is set. * Note that pcf8563_settime() will also clear PCF8563_R_SECOND_VL * as a side-effect. */ msgs[0].slave = msgs[1].slave = sc->sc_addr; if (iicbus_transfer(dev, msgs, nitems(msgs)) != 0) { device_printf(dev, "%s: cannot read RTC\n", __func__); return; } if ((val & PCF8563_R_SECOND_VL) != 0) device_printf(dev, "%s: battery low\n", __func__); clock_register(dev, 1000000); /* 1 second resolution */ }
static int ds1307_write(device_t dev, uint16_t addr, uint8_t *data, size_t len) { struct iic_msg msg[1] = { { addr, IIC_M_WR, len, data }, }; return (iicbus_transfer(dev, msg, nitems(msg))); }
static int iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags) { struct iic_msg *buf, *m; void **usrbufs; device_t iicdev, parent; int error, i; iicdev = priv->sc->sc_dev; parent = device_get_parent(iicdev); error = 0; buf = malloc(sizeof(*d->msgs) * d->nmsgs, M_IIC, M_WAITOK); error = copyin(d->msgs, buf, sizeof(*d->msgs) * d->nmsgs); /* Alloc kernel buffers for userland data, copyin write data */ usrbufs = malloc(sizeof(void *) * d->nmsgs, M_IIC, M_WAITOK | M_ZERO); for (i = 0; i < d->nmsgs; i++) { m = &(buf[i]); usrbufs[i] = m->buf; /* * At least init the buffer to NULL so we can safely free() it later. * If the copyin() to buf failed, don't try to malloc bogus m->len. */ m->buf = NULL; if (error != 0) continue; m->buf = malloc(m->len, M_IIC, M_WAITOK); if (!(m->flags & IIC_M_RD)) error = copyin(usrbufs[i], m->buf, m->len); } if (error == 0) error = iicbus_request_bus(parent, iicdev, (flags & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR)); if (error == 0) { error = iicbus_transfer(iicdev, buf, d->nmsgs); iicbus_release_bus(parent, iicdev); } /* Copyout all read segments, free up kernel buffers */ for (i = 0; i < d->nmsgs; i++) { m = &(buf[i]); if ((error == 0) && (m->flags & IIC_M_RD)) error = copyout(m->buf, usrbufs[i], m->len); free(m->buf, M_IIC); } free(usrbufs, M_IIC); free(buf, M_IIC); return (error); }
static int ds1307_read(device_t dev, uint16_t addr, uint8_t reg, uint8_t *data, size_t len) { struct iic_msg msg[2] = { { addr, IIC_M_WR | IIC_M_NOSTOP, 1, ® }, { addr, IIC_M_RD, len, data }, }; return (iicbus_transfer(dev, msg, nitems(msg))); }
static int am335x_pmic_read(device_t dev, uint8_t addr, uint8_t *data, uint8_t size) { struct am335x_pmic_softc *sc = device_get_softc(dev); struct iic_msg msg[] = { { sc->sc_addr, IIC_M_WR, 1, &addr }, { sc->sc_addr, IIC_M_RD, size, data }, }; return (iicbus_transfer(dev, msg, 2)); }
static void at24co2n_read_mac(struct at24co2n_softc *sc) { uint8_t addr = AT24CO_EEPROM_ETH_MACADDR; struct iic_msg msgs[2] = { { sc->sc_addr, IIC_M_WR, 1, &addr }, { sc->sc_addr, IIC_M_RD, 6, sc->sc_mac_addr}, }; iicbus_transfer(sc->sc_dev, msgs, 2); }
static int max6657_read(device_t dev, uint32_t slave_addr, int reg) { uint8_t addr = reg; uint8_t data[1]; struct iic_msg msgs[2] = { { slave_addr, IIC_M_WR, 1, &addr }, { slave_addr, IIC_M_RD, 1, data }, }; return iicbus_transfer(dev, msgs, 2) != 0 ? -1 : data[0]; }
static void fled_cb(void *arg, int onoff) { uint8_t data[1]; struct iic_msg msgs[1] = { { LED_ADDR, IIC_M_WR, 1, data }, }; device_t dev = arg; data[0] = (onoff == 0); /* NB: low true */ (void) iicbus_transfer(dev, msgs, 1); }
/** * twl_test_present - checks if a device with given address is present * @sc: device soft context * @addr: the address of the device to scan for * * Sends just the address byte and checks for an ACK. If no ACK then device * is assumed to not be present. * * RETURNS: * EIO if device is not present, otherwise 0 is returned. */ static int twl_test_present(struct twl_softc *sc, uint8_t addr) { struct iic_msg msg; uint8_t tmp; /* Set the address to read from */ msg.slave = addr; msg.flags = IIC_M_RD; msg.len = 1; msg.buf = &tmp; if (iicbus_transfer(sc->sc_dev, &msg, 1) != 0) return (EIO); return (0); }
static int am335x_pmic_write(device_t dev, uint8_t address, uint8_t *data, uint8_t size) { uint8_t buffer[MAX_IIC_DATA_SIZE + 1]; struct am335x_pmic_softc *sc = device_get_softc(dev); struct iic_msg msg[] = { { sc->sc_addr, IIC_M_WR, size + 1, buffer }, }; if (size > MAX_IIC_DATA_SIZE) return (ENOMEM); buffer[0] = address; memcpy(buffer + 1, data, size); return (iicbus_transfer(dev, msg, 1)); }
/** * twl_write - writes one or more registers to the TWL device * @sc: device soft context * @nsub: the sub-module to read from * @reg: the register offset within the module to read * @buf: data to write * @cnt: the number of bytes to write * * Writes one or more registers. * * LOCKING: * Expects the TWL lock to be held. * * RETURNS: * Zero on success or a negative error code on failure. */ int twl_write(device_t dev, uint8_t nsub, uint8_t reg, uint8_t *buf, uint16_t cnt) { struct twl_softc *sc; struct iic_msg msg; uint8_t addr; uint8_t tmp_buf[TWL_MAX_IIC_DATA_SIZE + 1]; int rc; if (cnt > TWL_MAX_IIC_DATA_SIZE) return (ENOMEM); /* Set the register address as the first byte */ tmp_buf[0] = reg; memcpy(&tmp_buf[1], buf, cnt); sc = device_get_softc(dev); TWL_LOCK(sc); addr = sc->sc_subaddr_map[nsub]; if (addr == TWL_INVALID_CHIP_ID) { TWL_UNLOCK(sc); return (EIO); } /* Setup the transfer and execute it */ msg.slave = addr; msg.flags = IIC_M_WR; msg.len = cnt + 1; msg.buf = tmp_buf; TWL_UNLOCK(sc); rc = iicbus_transfer(dev, &msg, 1); if (rc != 0) { device_printf(sc->sc_dev, "iicbus write failed (adr:0x%02x, reg:0x%02x)\n", addr, reg); return (EIO); } return (0); }
static int onyx_write(struct onyx_softc *sc, uint8_t reg, const uint8_t value) { u_int size; uint8_t buf[16]; struct iic_msg msg[] = { { sc->sc_addr, IIC_M_WR, 0, buf } }; size = 1; msg[0].len = size + 1; buf[0] = reg; buf[1] = value; iicbus_transfer(sc->sc_dev, msg, 1); return (0); }
static int tumbler_write(struct tumbler_softc *sc, uint8_t reg, const void *data) { u_int size; uint8_t buf[16]; struct iic_msg msg[] = { { sc->sc_addr, IIC_M_WR, 0, buf } }; KASSERT(reg < sizeof(tumbler_regsize), ("bad reg")); size = tumbler_regsize[reg]; msg[0].len = size + 1; buf[0] = reg; memcpy(&buf[1], data, size); iicbus_transfer(sc->sc_dev, msg, 1); return (0); }
/** * twl_read - read one or more registers from the TWL device * @sc: device soft context * @nsub: the sub-module to read from * @reg: the register offset within the module to read * @buf: buffer to store the bytes in * @cnt: the number of bytes to read * * Reads one or registers and stores the result in the suppled buffer. * * LOCKING: * Expects the TWL lock to be held. * * RETURNS: * Zero on success or a negative error code on failure. */ int twl_read(device_t dev, uint8_t nsub, uint8_t reg, uint8_t *buf, uint16_t cnt) { struct twl_softc *sc; struct iic_msg msg[2]; uint8_t addr; int rc; sc = device_get_softc(dev); TWL_LOCK(sc); addr = sc->sc_subaddr_map[nsub]; if (addr == TWL_INVALID_CHIP_ID) { TWL_UNLOCK(sc); return (EIO); } /* Set the address to read from */ msg[0].slave = addr; msg[0].flags = IIC_M_WR | IIC_M_NOSTOP; msg[0].len = 1; msg[0].buf = ® /* Read the data back */ msg[1].slave = addr; msg[1].flags = IIC_M_RD; msg[1].len = cnt; msg[1].buf = buf; TWL_UNLOCK(sc); rc = iicbus_transfer(dev, msg, 2); if (rc != 0) { device_printf(dev, "iicbus read failed (adr:0x%02x, reg:0x%02x)\n", addr, reg); return (EIO); } return (0); }
static int pcf8563_gettime(device_t dev, struct timespec *ts) { struct clocktime ct; uint8_t reg = PCF8563_R_SECOND, val[PCF8563_NCLOCKREGS]; struct iic_msg msgs[] = { { 0, IIC_M_WR, sizeof(reg), ® }, { 0, IIC_M_RD, PCF8563_NCLOCKREGS, &val[PCF8563_R_SECOND] } }; struct pcf8563_softc *sc; int error; sc = device_get_softc(dev); msgs[0].slave = msgs[1].slave = sc->sc_addr; error = iicbus_transfer(dev, msgs, nitems(msgs)); if (error != 0) { device_printf(dev, "%s: cannot read RTC\n", __func__); return (error); } ct.nsec = 0; ct.sec = FROMBCD(val[PCF8563_R_SECOND] & PCF8563_M_SECOND); ct.min = FROMBCD(val[PCF8563_R_MINUTE] & PCF8563_M_MINUTE); ct.hour = FROMBCD(val[PCF8563_R_HOUR] & PCF8563_M_HOUR); ct.day = FROMBCD(val[PCF8563_R_DAY] & PCF8563_M_DAY); ct.dow = val[PCF8563_R_WEEKDAY] & PCF8563_M_WEEKDAY; ct.mon = FROMBCD(val[PCF8563_R_MONTH] & PCF8563_M_MONTH); ct.year = FROMBCD(val[PCF8563_R_YEAR] & PCF8563_M_YEAR); ct.year += sc->sc_year0; if (ct.year < POSIX_BASE_YEAR) ct.year += 100; /* assume [1970, 2069] */ if ((val[PCF8563_R_MONTH] & PCF8563_R_MONTH_C) != 0) { if (ct.year >= 100 + sc->sc_year0) sc->sc_flags |= PCF8563_CPOL; } else if (ct.year < 100 + sc->sc_year0) sc->sc_flags |= PCF8563_CPOL; return (clock_ct_to_ts(&ct, ts)); }
static int pcf8563_settime(device_t dev, struct timespec *ts) { struct clocktime ct; uint8_t val[PCF8563_NCLOCKREGS]; struct iic_msg msgs[] = { { 0, IIC_M_WR, PCF8563_NCLOCKREGS - 1, &val[PCF8563_R_CS2] } }; struct pcf8563_softc *sc; int error; sc = device_get_softc(dev); val[PCF8563_R_CS2] = PCF8563_R_SECOND; /* abuse */ /* Accuracy is only one second. */ if (ts->tv_nsec >= 500000000) ts->tv_sec++; ts->tv_nsec = 0; clock_ts_to_ct(ts, &ct); val[PCF8563_R_SECOND] = TOBCD(ct.sec); val[PCF8563_R_MINUTE] = TOBCD(ct.min); val[PCF8563_R_HOUR] = TOBCD(ct.hour); val[PCF8563_R_DAY] = TOBCD(ct.day); val[PCF8563_R_WEEKDAY] = ct.dow; val[PCF8563_R_MONTH] = TOBCD(ct.mon); val[PCF8563_R_YEAR] = TOBCD(ct.year % 100); if ((sc->sc_flags & PCF8563_CPOL) != 0) { if (ct.year >= 100 + sc->sc_year0) val[PCF8563_R_MONTH] |= PCF8563_R_MONTH_C; } else if (ct.year < 100 + sc->sc_year0) val[PCF8563_R_MONTH] |= PCF8563_R_MONTH_C; msgs[0].slave = sc->sc_addr; error = iicbus_transfer(dev, msgs, nitems(msgs)); if (error != 0) device_printf(dev, "%s: cannot write RTC\n", __func__); return (error); }
.flags = IIC_M_WR, .len = 1, .buf = &start, }, { .slave = DDC_ADDR << 1, .flags = IIC_M_RD, .len = len, .buf = buf, } }; /* * Avoid sending the segment addr to not upset non-compliant ddc * monitors. */ ret = iicbus_transfer(adapter, &msgs[3 - xfers], xfers); if (ret != 0) DRM_DEBUG_KMS("iicbus_transfer countdown %d error %d\n", retries, ret); } while (ret != 0 && --retries); return (ret == 0 ? 0 : -1); } static bool drm_edid_is_zero(u8 *in_edid, int length) { int i; u32 *raw_edid = (u32 *)in_edid; for (i = 0; i < length / 4; i++)