static int strtc_clock_read(struct strtc_softc *sc, struct clock_ymdhms *dt) { u_int8_t bcd[M41ST84_REG_DATE_BYTES], cmdbuf[1]; int i; if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { printf("%s: strtc_clock_read: failed to acquire I2C bus\n", sc->sc_dev.dv_xname); return (0); } /* Read each RTC register in order. */ for (i = M41ST84_REG_CSEC; i < M41ST84_REG_DATE_BYTES; i++) { cmdbuf[0] = i; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &bcd[i], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); printf("%s: strtc_clock_read: failed to read rtc " "at 0x%x\n", sc->sc_dev.dv_xname, i); return (0); } } /* Done with I2C */ iic_release_bus(sc->sc_tag, I2C_F_POLL); /* * Convert the M41ST84's register values into something useable */ dt->dt_sec = FROMBCD(bcd[M41ST84_REG_SEC] & M41ST84_SEC_MASK); dt->dt_min = FROMBCD(bcd[M41ST84_REG_MIN] & M41ST84_MIN_MASK); dt->dt_hour = FROMBCD(bcd[M41ST84_REG_CENHR] & M41ST84_HOUR_MASK); dt->dt_day = FROMBCD(bcd[M41ST84_REG_DATE] & M41ST84_DATE_MASK); dt->dt_mon = FROMBCD(bcd[M41ST84_REG_MONTH] & M41ST84_MONTH_MASK); /* XXX: Should be an MD way to specify EPOCH used by BIOS/Firmware */ dt->dt_year = FROMBCD(bcd[M41ST84_REG_YEAR]) + POSIX_BASE_YEAR; return (1); }
int pcaled_gpio_pin_read(void *arg, int pin) { struct pcaled_softc *sc = arg; iic_acquire_bus(sc->sc_tag, I2C_F_POLL); uint8_t cmd, data; if (pin < 8) cmd = 0; else cmd = 1; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &cmd, 1, &data, 1, I2C_F_POLL)) goto fail; /* XXX */ fail: iic_release_bus(sc->sc_tag, I2C_F_POLL); return (data >> (pin & 3)) & 1; }
int lmtemp_temp_read(struct lmtemp_softc *sc, uint8_t which, int *valp) { u_int8_t cmd, buf[2]; int error; cmd = which; error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &cmd, 1, buf, 2, 0); if (error) return (error); /* Some chips return transient 0's.. we try next time */ if (buf[0] == 0x00 && buf[1] == 0x00) return (1); /* convert to half-degrees C */ *valp = ((buf[0] << 8) | buf[1]) / (1 << (16 - sc->sc_bits)); return (0); }
int max7301_match(struct device *parent, void *v, void *arg) { struct i2c_attach_args *ia = arg; int ok = 0; uint8_t cmd, data; if (ia->ia_addr != MAX7301_ADDR) return (0); /* attempt to read input register 0 */ iic_acquire_bus(ia->ia_tag, I2C_F_POLL); cmd = 0; if (iic_exec(ia->ia_tag, I2C_OP_READ_WITH_STOP, ia->ia_addr, &cmd, sizeof cmd, &data, sizeof data, I2C_F_POLL)) goto fail; ok = 1; fail: iic_release_bus(ia->ia_tag, I2C_F_POLL); return (ok); }
void maxds_refresh(void *arg) { struct maxds_softc *sc = arg; u_int8_t cmd; u_int16_t data; iic_acquire_bus(sc->sc_tag, 0); cmd = DS1631_TEMP; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) { sc->sc_sensor[MAXDS_TEMP].value = 273150000 + (int)(betoh16(data)) / 8 * 31250; sc->sc_sensor[MAXDS_TEMP].flags &= ~SENSOR_FINVALID; } else sc->sc_sensor[MAXDS_TEMP].flags |= SENSOR_FINVALID; iic_release_bus(sc->sc_tag, 0); }
int lmtemp_temp_read(struct lmtemp_softc *sc, uint8_t which, int *valp) { u_int8_t cmd; u_int16_t data = 0x0000; int error; cmd = which; error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0); if (error) return (error); /* Some chips return transient 0's.. we try next time */ if (data == 0x0000) return (1); /* convert to half-degrees C */ *valp = betoh16(data) / (1 << (16 - sc->sc_bits)); return (0); }
static int as3722_match(device_t parent, cfdata_t match, void *aux) { struct i2c_attach_args *ia = aux; uint8_t reg, id1; int error; if (ia->ia_name == NULL) { iic_acquire_bus(ia->ia_tag, I2C_F_POLL); reg = AS3722_ASIC_ID1_REG; error = iic_exec(ia->ia_tag, I2C_OP_READ_WITH_STOP, ia->ia_addr, ®, 1, &id1, 1, I2C_F_POLL); iic_release_bus(ia->ia_tag, I2C_F_POLL); if (error == 0 && id1 == 0x0c) return 1; return 0; } else { return iic_compat_match(ia, as3722_compats); } }
static int awin_hdmi_read_edid_block(struct awin_hdmi_softc *sc, uint8_t *data, uint8_t block) { i2c_tag_t tag = &sc->sc_ic; uint8_t wbuf[2]; int error; if ((error = iic_acquire_bus(tag, I2C_F_POLL)) != 0) return error; wbuf[0] = block; /* start address */ if ((error = iic_exec(tag, I2C_OP_READ_WITH_STOP, DDC_ADDR, wbuf, 1, data, 128, I2C_F_POLL)) != 0) { iic_release_bus(tag, I2C_F_POLL); return error; } iic_release_bus(tag, I2C_F_POLL); return 0; }
static uint8_t tps65217pmic_reg_read(struct tps65217pmic_softc *sc, uint8_t reg) { uint8_t wbuf[2]; uint8_t rv; if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL) != 0) { aprint_error_dev(sc->sc_dev, "cannot acquire bus for read\n"); return 0; } wbuf[0] = reg; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, wbuf, 1, &rv, 1, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, "cannot execute operation\n"); iic_release_bus(sc->sc_tag, I2C_F_POLL); return 0; } iic_release_bus(sc->sc_tag, I2C_F_POLL); return rv; }
static int rs5c372rtc_clock_write(struct rs5c372rtc_softc *sc, struct clock_ymdhms *dt) { uint8_t bcd[RS5C372_NRTC_REGS]; uint8_t cmdbuf[1]; /* * Convert our time representation into something the RS5C372 * can understand. */ bcd[RS5C372_SECONDS] = TOBCD(dt->dt_sec); bcd[RS5C372_MINUTES] = TOBCD(dt->dt_min); bcd[RS5C372_HOURS] = TOBCD(dt->dt_hour); bcd[RS5C372_DATE] = TOBCD(dt->dt_day); bcd[RS5C372_DAY] = TOBCD(dt->dt_wday); bcd[RS5C372_MONTH] = TOBCD(dt->dt_mon); bcd[RS5C372_YEAR] = TOBCD(dt->dt_year % 100); if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, "rs5c372rtc_clock_write: failed to " "acquire I2C bus\n"); return (0); } cmdbuf[0] = (RS5C372_SECONDS << 4); if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address, cmdbuf, 1, bcd, RS5C372_NRTC_REGS, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "rs5c372rtc_clock_write: failed to write rtc\n"); return (0); } iic_release_bus(sc->sc_tag, I2C_F_POLL); return (1); }
/*ARGSUSED*/ int pcfrtc_read(dev_t dev, struct uio *uio, int flags) { struct pcfrtc_softc *sc; u_int8_t ch, cmdbuf[1]; int a, error; if ((sc = device_lookup(&pcfrtc_cd, minor(dev))) == NULL) return (ENXIO); if (uio->uio_offset >= PCF8583_NVRAM_SIZE) return (EINVAL); if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) return (error); while (uio->uio_resid && uio->uio_offset < PCF8583_NVRAM_SIZE) { a = (int)uio->uio_offset; cmdbuf[0] = a + PCF8583_NVRAM_START; if ((error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &ch, 1, 0)) != 0) { iic_release_bus(sc->sc_tag, 0); printf("%s: pcfrtc_read: read failed at 0x%x\n", sc->sc_dev.dv_xname, a); return (error); } if ((error = uiomove(&ch, 1, uio)) != 0) { iic_release_bus(sc->sc_tag, 0); return (error); } } iic_release_bus(sc->sc_tag, 0); return (0); }
/*ARGSUSED*/ int m41t00_read(dev_t dev, struct uio *uio, int flags) { struct m41t00_softc *sc; u_int8_t ch, cmdbuf[1]; int a, error; if ((sc = device_lookup_private(&m41trtc_cd, minor(dev))) == NULL) return ENXIO; if (uio->uio_offset >= M41T00_NBYTES) return EINVAL; if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) return error; while (uio->uio_resid && uio->uio_offset < M41T00_NBYTES) { a = (int)uio->uio_offset; cmdbuf[0] = a; if ((error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &ch, 1, 0)) != 0) { iic_release_bus(sc->sc_tag, 0); aprint_error_dev(sc->sc_dev, "m41t00_read: read failed at 0x%x\n", a); return error; } if ((error = uiomove(&ch, 1, uio)) != 0) { iic_release_bus(sc->sc_tag, 0); return error; } } iic_release_bus(sc->sc_tag, 0); return 0; }
static int pcf8563rtc_clock_read(struct pcf8563rtc_softc *sc, struct clock_ymdhms *dt) { uint8_t bcd[PCF8563_NREGS]; uint8_t reg = PCF8563_R_SECOND; const int flags = cold ? I2C_F_POLL : 0; if (iic_acquire_bus(sc->sc_tag, flags)) { device_printf(sc->sc_dev, "acquire bus for read failed\n"); return 0; } if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, ®, 1, &bcd[reg], PCF8563_R_YEAR - reg + 1, flags)) { iic_release_bus(sc->sc_tag, flags); device_printf(sc->sc_dev, "read failed\n"); return 0; } iic_release_bus(sc->sc_tag, flags); if (bcd[PCF8563_R_SECOND] & PCF8563_M_VL) return 0; dt->dt_sec = bcdtobin(bcd[PCF8563_R_SECOND] & PCF8563_M_SECOND); dt->dt_min = bcdtobin(bcd[PCF8563_R_MINUTE] & PCF8563_M_MINUTE); dt->dt_hour = bcdtobin(bcd[PCF8563_R_HOUR] & PCF8563_M_HOUR); dt->dt_day = bcdtobin(bcd[PCF8563_R_DAY] & PCF8563_M_DAY); dt->dt_wday = bcdtobin(bcd[PCF8563_R_WEEKDAY] & PCF8563_M_WEEKDAY); dt->dt_mon = bcdtobin(bcd[PCF8563_R_MONTH] & PCF8563_M_MONTH); dt->dt_year = 1900 + (bcdtobin(bcd[PCF8563_R_YEAR] & PCF8563_M_YEAR) % 100); if ((bcd[PCF8563_R_MONTH] & PCF8563_M_CENTURY) == 0) dt->dt_year += 100; return 1; }
/*ARGSUSED*/ int strtc_read(dev_t dev, struct uio *uio, int flags) { struct strtc_softc *sc; u_int8_t ch, cmdbuf[1]; int a, error; if ((sc = device_lookup_private(&strtc_cd, minor(dev))) == NULL) return (ENXIO); if (uio->uio_offset >= M41ST84_USER_RAM_SIZE) return (EINVAL); if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) return (error); while (uio->uio_resid && uio->uio_offset < M41ST84_USER_RAM_SIZE) { a = (int)uio->uio_offset; cmdbuf[0] = a + M41ST84_USER_RAM; if ((error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &ch, 1, 0)) != 0) { iic_release_bus(sc->sc_tag, 0); aprint_error_dev(sc->sc_dev, "strtc_read: read failed at 0x%x\n", a); return (error); } if ((error = uiomove(&ch, 1, uio)) != 0) { iic_release_bus(sc->sc_tag, 0); return (error); } } iic_release_bus(sc->sc_tag, 0); return (0); }
static void rs5c372rtc_reg_write(struct rs5c372rtc_softc *sc, int reg, uint8_t val) { uint8_t cmdbuf[2]; if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, "rs5c372rtc_reg_write: failed to acquire I2C bus\n"); return; } reg &= 0xf; cmdbuf[0] = (reg << 4); cmdbuf[1] = val; if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "rs5c372rtc_reg_write: failed to write reg%d\n", reg); return; } iic_release_bus(sc->sc_tag, I2C_F_POLL); }
static int strtc_clock_write(struct strtc_softc *sc, struct clock_ymdhms *dt) { uint8_t bcd[M41ST84_REG_DATE_BYTES], cmdbuf[2]; int i; /* * Convert our time representation into something the M41ST84 * can understand. */ bcd[M41ST84_REG_CSEC] = TOBCD(0); /* must always write as 0 */ bcd[M41ST84_REG_SEC] = TOBCD(dt->dt_sec); bcd[M41ST84_REG_MIN] = TOBCD(dt->dt_min); bcd[M41ST84_REG_CENHR] = TOBCD(dt->dt_hour); bcd[M41ST84_REG_DATE] = TOBCD(dt->dt_day); bcd[M41ST84_REG_DAY] = TOBCD(dt->dt_wday); bcd[M41ST84_REG_MONTH] = TOBCD(dt->dt_mon); bcd[M41ST84_REG_YEAR] = TOBCD((dt->dt_year - POSIX_BASE_YEAR) % 100); if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, "strtc_clock_write: failed to acquire I2C bus\n"); return (0); } /* Stop the clock */ cmdbuf[0] = M41ST84_REG_SEC; cmdbuf[1] = M41ST84_SEC_ST; if (iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "strtc_clock_write: failed to Hold Clock\n"); return (0); } /* * Check for the HT bit -- if set, then clock lost power & stopped * If that happened, then clear the bit so that the clock will have * a chance to run again. */ cmdbuf[0] = M41ST84_REG_AL_HOUR; if (iic_exec(sc->sc_tag, I2C_OP_READ, sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "strtc_clock_write: failed to read HT\n"); return (0); } if (cmdbuf[1] & M41ST84_AL_HOUR_HT) { cmdbuf[1] &= ~M41ST84_AL_HOUR_HT; if (iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "strtc_clock_write: failed to reset HT\n"); return (0); } } /* * Write registers in reverse order. The last write (to the Seconds * register) will undo the Clock Hold, above. */ for (i = M41ST84_REG_DATE_BYTES - 1; i >= 0; i--) { cmdbuf[0] = i; if (iic_exec(sc->sc_tag, i ? I2C_OP_WRITE : I2C_OP_WRITE_WITH_STOP, sc->sc_address, cmdbuf, 1, &bcd[i], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "strtc_clock_write: failed to write rtc " " at 0x%x\n", i); /* XXX: Clock Hold is likely still asserted! */ return (0); } } iic_release_bus(sc->sc_tag, I2C_F_POLL); return (1); }
void maxds_attach(struct device *parent, struct device *self, void *aux) { struct maxds_softc *sc = (struct maxds_softc *)self; struct i2c_attach_args *ia = aux; u_int8_t cmd, data; int i; printf(": %s", ia->ia_name); sc->sc_tag = ia->ia_tag; sc->sc_addr = ia->ia_addr; iic_acquire_bus(sc->sc_tag, 0); cmd = DS1631_CONTROL; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) { if (data & DS1631_CONTROL_1SHOT) { /* * 1-Shot mode would require us to write every refresh * which is stupid. Put us into continuous mode. */ data &= ~DS1631_CONTROL_1SHOT; (void) iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0); //delay(10 * 1000); printf(", continuous"); goto dostart; } if (data & DS1631_CONTROL_DONE) { dostart: cmd = DS1631_START; if (strcmp(ia->ia_name, "ds1624") == 0) cmd = DS1624_START; (void) iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, NULL, 0, 0); printf(", starting"); } } iic_release_bus(sc->sc_tag, 0); /* Initialize sensor data. */ strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, sizeof(sc->sc_sensordev.xname)); sc->sc_sensor[MAXDS_TEMP].type = SENSOR_TEMP; strlcpy(sc->sc_sensor[MAXDS_TEMP].desc, "Internal", sizeof(sc->sc_sensor[MAXDS_TEMP].desc)); if (sensor_task_register(sc, maxds_refresh, 5) == NULL) { printf(", unable to register update task\n"); return; } for (i = 0; i < MAXDS_NUM_SENSORS; i++) sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]); sensordev_install(&sc->sc_sensordev); printf("\n"); }
static void pic16lc_read_1(struct pic16lc_softc *sc, uint8_t cmd, uint8_t *valp) { iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &cmd, 1, valp, 1, 0); }
static int strtc_clock_read(struct strtc_softc *sc, struct clock_ymdhms *dt) { u_int8_t bcd[M41ST84_REG_DATE_BYTES], cmdbuf[1]; int i; if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, "strtc_clock_read: failed to acquire I2C bus\n"); return (0); } /* * Check for the HT bit -- if set, then clock lost power & stopped * If that happened, then clear the bit so that the clock will have * a chance to run again. */ cmdbuf[0] = M41ST84_REG_AL_HOUR; if (iic_exec(sc->sc_tag, I2C_OP_READ, sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "strtc_clock_read: failed to read HT\n"); return (0); } if (cmdbuf[1] & M41ST84_AL_HOUR_HT) { cmdbuf[1] &= ~M41ST84_AL_HOUR_HT; if (iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "strtc_clock_read: failed to reset HT\n"); return (0); } } /* Read each RTC register in order. */ for (i = M41ST84_REG_CSEC; i < M41ST84_REG_DATE_BYTES; i++) { cmdbuf[0] = i; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &bcd[i], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "strtc_clock_read: failed to read rtc " "at 0x%x\n", i); return (0); } } /* Done with I2C */ iic_release_bus(sc->sc_tag, I2C_F_POLL); /* * Convert the M41ST84's register values into something useable */ dt->dt_sec = FROMBCD(bcd[M41ST84_REG_SEC] & M41ST84_SEC_MASK); dt->dt_min = FROMBCD(bcd[M41ST84_REG_MIN] & M41ST84_MIN_MASK); dt->dt_hour = FROMBCD(bcd[M41ST84_REG_CENHR] & M41ST84_HOUR_MASK); dt->dt_day = FROMBCD(bcd[M41ST84_REG_DATE] & M41ST84_DATE_MASK); dt->dt_mon = FROMBCD(bcd[M41ST84_REG_MONTH] & M41ST84_MONTH_MASK); /* XXX: Should be an MD way to specify EPOCH used by BIOS/Firmware */ dt->dt_year = FROMBCD(bcd[M41ST84_REG_YEAR]) + POSIX_BASE_YEAR; return (1); }
static void coram_attach(device_t parent, device_t self, void *aux) { struct coram_softc *sc = device_private(self); const struct pci_attach_args *pa = aux; pci_intr_handle_t ih; pcireg_t reg; const char *intrstr; struct coram_iic_softc *cic; uint32_t value; int i; #ifdef CORAM_ATTACH_I2C struct i2cbus_attach_args iba; #endif sc->sc_dev = self; pci_aprint_devinfo(pa, NULL); reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); sc->sc_board = coram_board_lookup(PCI_VENDOR(reg), PCI_PRODUCT(reg)); KASSERT(sc->sc_board != NULL); if (pci_mapreg_map(pa, CX23885_MMBASE, PCI_MAPREG_TYPE_MEM, 0, &sc->sc_memt, &sc->sc_memh, NULL, &sc->sc_mems)) { aprint_error_dev(self, "couldn't map memory space\n"); return; } sc->sc_dmat = pa->pa_dmat; sc->sc_pc = pa->pa_pc; if (pci_intr_map(pa, &ih)) { aprint_error_dev(self, "couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pa->pa_pc, ih); sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_VM, coram_intr, self); if (sc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); return; } aprint_normal_dev(self, "interrupting at %s\n", intrstr); /* set master */ reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); reg |= PCI_COMMAND_MASTER_ENABLE; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg); /* I2C */ for(i = 0; i < I2C_NUM; i++) { cic = &sc->sc_iic[i]; cic->cic_sc = sc; if (bus_space_subregion(sc->sc_memt, sc->sc_memh, I2C_BASE + (I2C_SIZE * i), I2C_SIZE, &cic->cic_regh)) panic("failed to subregion i2c"); mutex_init(&cic->cic_busmutex, MUTEX_DRIVER, IPL_NONE); cic->cic_i2c.ic_cookie = cic; cic->cic_i2c.ic_acquire_bus = coram_iic_acquire_bus; cic->cic_i2c.ic_release_bus = coram_iic_release_bus; cic->cic_i2c.ic_exec = coram_iic_exec; #ifdef CORAM_ATTACH_I2C /* attach iic(4) */ memset(&iba, 0, sizeof(iba)); iba.iba_tag = &cic->cic_i2c; iba.iba_type = I2C_TYPE_SMBUS; cic->cic_i2cdev = config_found_ia(self, "i2cbus", &iba, iicbus_print); #endif } /* HVR1250 GPIO */ value = bus_space_read_4(sc->sc_memt, sc->sc_memh, 0x110010); #if 1 value &= ~0x00010001; bus_space_write_4(sc->sc_memt, sc->sc_memh, 0x110010, value); delay(5000); #endif value |= 0x00010001; bus_space_write_4(sc->sc_memt, sc->sc_memh, 0x110010, value); #if 0 int i; uint8_t foo[256]; uint8_t bar; bar = 0; // seeprom_bootstrap_read(&sc->sc_i2c, 0x50, 0, 256, foo, 256); iic_acquire_bus(&sc->sc_i2c, I2C_F_POLL); iic_exec(&sc->sc_i2c, I2C_OP_READ_WITH_STOP, 0x50, &bar, 1, foo, 256, I2C_F_POLL); iic_release_bus(&sc->sc_i2c, I2C_F_POLL); printf("\n"); for ( i = 0; i < 256; i++) { if ( (i % 8) == 0 ) printf("%02x: ", i); printf("%02x", foo[i]); if ( (i % 8) == 7 ) printf("\n"); else printf(" "); } printf("\n"); #endif sc->sc_demod = cx24227_open(sc->sc_dev, &sc->sc_iic[0].cic_i2c, 0x19); if (sc->sc_demod == NULL) aprint_error_dev(self, "couldn't open cx24227\n"); sc->sc_tuner = mt2131_open(sc->sc_dev, &sc->sc_iic[0].cic_i2c, 0x61); if (sc->sc_tuner == NULL) aprint_error_dev(self, "couldn't open mt2131\n"); coram_mpeg_attach(sc); if (!pmf_device_register(self, NULL, coram_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); return; }
void tsl_attach(struct device *parent, struct device *self, void *aux) { struct tsl_softc *sc = (struct tsl_softc *)self; struct i2c_attach_args *ia = aux; u_int8_t cmd, data; sc->sc_tag = ia->ia_tag; sc->sc_addr = ia->ia_addr; iic_acquire_bus(sc->sc_tag, 0); cmd = TSL2560_REG_CONTROL; data = TSL2560_CONTROL_POWER; if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { iic_release_bus(sc->sc_tag, 0); printf(": power up failed\n"); return; } cmd = TSL2560_REG_TIMING; data = TSL2560_TIMING_GAIN | TSL2560_TIMING_INTEG2; if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { iic_release_bus(sc->sc_tag, 0); printf(": cannot write timing register\n"); return; } cmd = TSL2560_REG_ID; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { iic_release_bus(sc->sc_tag, 0); printf(": cannot read ID register\n"); return; } iic_release_bus(sc->sc_tag, 0); switch (data >> 4) { case 0: printf(": TSL2560 rev %x", data & 0x0f); break; case 1: printf(": TSL2561 rev %x", data & 0x0f); break; default: printf(": unknown part number %x", data >> 4); break; } /* Initialize sensor data. */ strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, sizeof(sc->sc_sensordev.xname)); sc->sc_sensor.type = SENSOR_LUX; if (sensor_task_register(sc, tsl_refresh, 5) == NULL) { printf(": unable to register update task\n"); return; } sensor_attach(&sc->sc_sensordev, &sc->sc_sensor); sensordev_install(&sc->sc_sensordev); printf("\n"); }
int cros_ec_i2c_command(struct cros_ec_softc *sc, uint8_t cmd, int cmd_version, const uint8_t *out, int out_len, uint8_t **in, int in_len) { int out_bytes, in_bytes, ret; uint8_t *ptr = sc->out; uint8_t *inptr = sc->in; inptr += sizeof(uint64_t); /* returned data should be 64-bit aligned */ if (!sc->cmd_version_is_supported) { /* old-style */ *ptr++ = cmd; out_bytes = out_len + 1; in_bytes = in_len + 2; inptr--; /* status byte */ } else { /* new-style */ *ptr++ = EC_CMD_VERSION0 + cmd_version; *ptr++ = cmd; *ptr++ = out_len; out_bytes = out_len + 4; in_bytes = in_len + 3; inptr -= 2; /* status byte, length */ } memcpy(ptr, out, out_len); ptr += out_len; if (sc->cmd_version_is_supported) *ptr++ = (uint8_t) cros_ec_calc_checksum(sc->out, out_len + 3); iic_acquire_bus(sc->sc_tag, 0); ret = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, NULL, 0, &sc->out, out_bytes, 0); if (ret) { DPRINTF(("%s: I2C write failed\n", __func__)); iic_release_bus(sc->sc_tag, 0); return -1; } ret = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, NULL, 0, inptr, in_bytes, 0); if (ret) { DPRINTF(("%s: I2C read failed\n", __func__)); iic_release_bus(sc->sc_tag, 0); return -1; } iic_release_bus(sc->sc_tag, 0); if (*inptr != EC_RES_SUCCESS) { DPRINTF(("%s: bad result\n", __func__)); return -(int)*inptr; } if (sc->cmd_version_is_supported) { int len, csum; len = inptr[1]; if (len > sizeof(sc->in)) { DPRINTF(("%s: Received length too large\n", __func__)); return -1; } csum = cros_ec_calc_checksum(inptr, 2 + len); if (csum != inptr[2 + len]) { DPRINTF(("%s: Invalid checksum\n", __func__)); return -1; } in_len = min(in_len, len); } *in = sc->in + sizeof(uint64_t); return in_len; }
static int m41t00_clock_write(struct m41t00_softc *sc, struct clock_ymdhms *dt) { uint8_t bcd[M41T00_DATE_BYTES], cmdbuf[2]; uint8_t init_seconds, final_seconds; int i; /* * Convert our time representation into something the MAX6900 * can understand. */ bcd[M41T00_SEC] = TOBCD(dt->dt_sec); bcd[M41T00_MIN] = TOBCD(dt->dt_min); bcd[M41T00_CENHR] = TOBCD(dt->dt_hour); bcd[M41T00_DATE] = TOBCD(dt->dt_day); bcd[M41T00_DAY] = TOBCD(dt->dt_wday); bcd[M41T00_MONTH] = TOBCD(dt->dt_mon); bcd[M41T00_YEAR] = TOBCD(dt->dt_year % 100); if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, "m41t00_clock_write: failed to acquire I2C bus\n"); return 0; } /* * The MAX6900 RTC manual recommends ensuring "atomicity" of * a non-burst write by: * * - writing SECONDS * - reading back SECONDS, remembering it as "initial seconds" * - write the remaing RTC registers * - read back SECONDS as "final seconds" * - if "initial seconds" == 59, ensure "final seconds" == 59 * - else, ensure "final seconds" is no more than one second * beyond "initial seconds". * * This sounds reasonable for the M41T00, too. */ again: cmdbuf[0] = M41T00_SEC; if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address, cmdbuf, 1, &bcd[M41T00_SEC], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "m41t00_clock_write: failed to write SECONDS\n"); return 0; } cmdbuf[0] = M41T00_SEC; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &init_seconds, 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "m41t00_clock_write: failed to read " "INITIAL SECONDS\n"); return 0; } init_seconds = FROMBCD(init_seconds & M41T00_SEC_MASK); for (i = 1; i < M41T00_DATE_BYTES; i++) { cmdbuf[0] = m41t00_rtc_offset[i]; if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address, cmdbuf, 1, &bcd[i], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "m41t00_clock_write: failed to write rtc " " at 0x%x\n", m41t00_rtc_offset[i]); return 0; } } cmdbuf[0] = M41T00_SEC; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &final_seconds, 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "m41t00_clock_write: failed to read " "FINAL SECONDS\n"); return 0; } final_seconds = FROMBCD(final_seconds & M41T00_SEC_MASK); if ((init_seconds != final_seconds) && (((init_seconds + 1) % 60) != final_seconds)) { #if 1 printf("%s: m41t00_clock_write: init %d, final %d, try again\n", device_xname(sc->sc_dev), init_seconds, final_seconds); #endif goto again; } iic_release_bus(sc->sc_tag, I2C_F_POLL); return 1; }
void adc_attach(struct device *parent, struct device *self, void *aux) { struct adc_softc *sc = (struct adc_softc *)self; struct i2c_attach_args *ia = aux; u_int8_t cmd, data; int nsens = 0, i; sc->sc_tag = ia->ia_tag; sc->sc_addr = ia->ia_addr; printf(": %s", ia->ia_name); sc->sc_chip = 0; if (strcmp(ia->ia_name, "ad7417") == 0) sc->sc_chip = 7417; if (strcmp(ia->ia_name, "ad7418") == 0) sc->sc_chip = 7418; if (sc->sc_chip != 0) { cmd = AD741X_CONFIG2; data = 0; if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { printf(", config2 reset failed\n"); return; } } cmd = AD741X_CONFIG; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { printf(", config reset failed\n"); return; } data &= 0xfe; if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { printf(", config reset failed\n"); return; } sc->sc_config = data; /* Initialize sensor data. */ strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, sizeof(sc->sc_sensordev.xname)); sc->sc_sensor[ADC_TEMP].type = SENSOR_TEMP; strlcpy(sc->sc_sensor[ADC_TEMP].desc, "Internal", sizeof(sc->sc_sensor[ADC_TEMP].desc)); nsens = 1; if (sc->sc_chip == 7417 || sc->sc_chip == 7418) { sc->sc_sensor[ADC_ADC0].type = SENSOR_INTEGER; nsens++; } if (sc->sc_chip == 7417 || sc->sc_chip == 7418) { sc->sc_sensor[ADC_ADC1].type = SENSOR_INTEGER; sc->sc_sensor[ADC_ADC2].type = SENSOR_INTEGER; sc->sc_sensor[ADC_ADC3].type = SENSOR_INTEGER; nsens += 3; } if (sensor_task_register(sc, adc_refresh, 5) == NULL) { printf(", unable to register update task\n"); return; } sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[0]); if (sc->sc_chip == 7417 || sc->sc_chip == 7418) sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[1]); if (sc->sc_chip == 7417) for (i = 2; i < nsens; i++) sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]); sensordev_install(&sc->sc_sensordev); printf("\n"); }
static int pcfrtc_clock_read(struct pcfrtc_softc *sc, struct clock_ymdhms *dt, uint8_t *centi) { u_int8_t bcd[10], cmdbuf[1]; int i, err; if ((err = iic_acquire_bus(sc->sc_tag, I2C_F_POLL))) { aprint_error_dev(sc->sc_dev, "pcfrtc_clock_read: failed to acquire I2C bus\n"); return err; } /* Read each timekeeping register in order. */ for (i = 0; i < 10; i++) { cmdbuf[0] = pcf8583_rtc_offset[i]; if ((err = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &bcd[i], 1, I2C_F_POLL))) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "pcfrtc_clock_read: failed to read rtc " "at 0x%x\n", pcf8583_rtc_offset[i]); return err; } } /* Done with I2C */ iic_release_bus(sc->sc_tag, I2C_F_POLL); /* * Convert the PCF8583's register values into something useable */ *centi = FROMBCD(bcd[PCF8583_REG_CENTI]); dt->dt_sec = FROMBCD(bcd[PCF8583_REG_SEC]); dt->dt_min = FROMBCD(bcd[PCF8583_REG_MIN]); dt->dt_hour = FROMBCD(bcd[PCF8583_REG_HOUR] & PCF8583_HOUR_MASK); if (bcd[PCF8583_REG_HOUR] & PCF8583_HOUR_12H) { dt->dt_hour %= 12; /* 12AM -> 0, 12PM -> 12 */ if (bcd[PCF8583_REG_HOUR] & PCF8583_HOUR_PM) dt->dt_hour += 12; } dt->dt_day = FROMBCD(bcd[PCF8583_REG_YEARDATE] & PCF8583_DATE_MASK); dt->dt_mon = FROMBCD(bcd[PCF8583_REG_WKDYMON] & PCF8583_MON_MASK); dt->dt_year = bcd[8] + (bcd[9] * 100); /* Try to notice if the year's rolled over. */ if (bcd[PCF8583_REG_CSR] & PCF8583_CSR_MASK) aprint_error_dev(sc->sc_dev, "cannot check year in mask mode\n"); else { while (dt->dt_year % 4 != (bcd[PCF8583_REG_YEARDATE] & PCF8583_YEAR_MASK) >> PCF8583_YEAR_SHIFT) dt->dt_year++; } return 0; }
void admtemp_attach(struct device *parent, struct device *self, void *aux) { struct admtemp_softc *sc = (struct admtemp_softc *)self; struct i2c_attach_args *ia = aux; u_int8_t cmd, data, stat; int xeon = 0, i; sc->sc_tag = ia->ia_tag; sc->sc_addr = ia->ia_addr; if (strcmp(ia->ia_name, "xeontemp") == 0) { printf(": Xeon"); xeon = 1; } else printf(": %s", ia->ia_name); iic_acquire_bus(sc->sc_tag, 0); cmd = ADM1021_CONFIG_READ; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { iic_release_bus(sc->sc_tag, 0); printf(", cannot get control register\n"); return; } if (data & ADM1021_CONFIG_RUN) { cmd = ADM1021_STATUS; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &stat, sizeof stat, 0)) { iic_release_bus(sc->sc_tag, 0); printf(", cannot read status register\n"); return; } if ((stat & ADM1021_STATUS_INVAL) == ADM1021_STATUS_INVAL) { if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &stat, sizeof stat, 0)) { iic_release_bus(sc->sc_tag, 0); printf(", cannot read status register\n"); return; } } /* means external is dead */ if ((stat & ADM1021_STATUS_INVAL) != ADM1021_STATUS_INVAL && (stat & ADM1021_STATUS_NOEXT)) sc->sc_noexternal = 1; data &= ~ADM1021_CONFIG_RUN; cmd = ADM1021_CONFIG_WRITE; if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { iic_release_bus(sc->sc_tag, 0); printf(", cannot set control register\n"); return; } } iic_release_bus(sc->sc_tag, 0); /* Initialize sensor data. */ strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, sizeof(sc->sc_sensordev.xname)); sc->sc_sensor[ADMTEMP_EXT].type = SENSOR_TEMP; strlcpy(sc->sc_sensor[ADMTEMP_EXT].desc, xeon ? "Xeon" : "External", sizeof(sc->sc_sensor[ADMTEMP_EXT].desc)); sc->sc_sensor[ADMTEMP_INT].type = SENSOR_TEMP; strlcpy(sc->sc_sensor[ADMTEMP_INT].desc, xeon ? "Xeon" : "Internal", sizeof(sc->sc_sensor[ADMTEMP_INT].desc)); if (sensor_task_register(sc, admtemp_refresh, 5) == NULL) { printf(", unable to register update task\n"); return; } for (i = 0; i < (sc->sc_noexternal ? 1 : ADMTEMP_NUM_SENSORS); i++) sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]); sensordev_install(&sc->sc_sensordev); printf("\n"); }
void pcfadc_attach(struct device *parent, struct device *self, void *aux) { struct pcfadc_softc *sc = (struct pcfadc_softc *)self; u_char chanuse[PCF8591_CHANNELS * 4], desc[PCF8591_CHANNELS * 32]; u_char *cp; u_int8_t junk[PCF8591_CHANNELS + 1]; u_int32_t transinfo[PCF8591_CHANNELS * 4]; struct i2c_attach_args *ia = aux; int dlen, clen, tlen, node = *(int *)ia->ia_cookie; u_int i; if ((dlen = OF_getprop(node, "channels-description", desc, sizeof(desc))) < 0) { printf(": couldn't find \"channels-description\" property\n"); return; } if (dlen > sizeof(desc) || desc[dlen - 1] != '\0') { printf(": bad \"channels-description\" property\n"); return; } if ((clen = OF_getprop(node, "channels-in-use", chanuse, sizeof(chanuse))) < 0) { printf(": couldn't find \"channels-in-use\" property\n"); return; } if ((clen % 4) != 0) { printf(": invalid \"channels-in-use\" length %d\n", clen); return; } sc->sc_nchan = clen / 4; if (sc->sc_nchan > PCF8591_CHANNELS) { printf(": invalid number of channels (%d)\n", sc->sc_nchan); return; } if ((tlen = OF_getprop(node, "tables", sc->sc_xlate, sizeof(sc->sc_xlate))) < 0) { printf(": couldn't find \"tables\" property\n"); return; } /* We only support complete, single width tables */ if (tlen != 256) { printf(": invalid \"tables\" length %d\n", tlen); return; } if ((tlen = OF_getprop(node, "translation", transinfo, sizeof(transinfo))) < 0) { printf(": couldn't find \"translation\" property\n"); return; } if (tlen != (sc->sc_nchan * 4 * 4)) { printf(": invalid \"translation\" length %d\n", tlen); return; } cp = desc; for (i = 0; i < sc->sc_nchan; i++) { struct pcfadc_channel *chp = &sc->sc_channels[i]; chp->chan_sensor.type = SENSOR_TEMP; if (cp >= desc + dlen) { printf(": invalid \"channels-description\"\n"); return; } strlcpy(chp->chan_sensor.desc, cp, sizeof(chp->chan_sensor.desc)); cp += strlen(cp) + 1; /* * We only support input temperature channels, with * valid channel numbers, and basic (unscaled) translation * * XXX TODO: support voltage (type 2) channels and type 4 * (scaled) translation tables */ if (chanuse[(i * 4)] > PCF8591_CHANNELS || /* channel # */ chanuse[(i * 4) + 1] != 0 || /* dir == input */ chanuse[(i * 4) + 2] != 1 || /* type == temp */ transinfo[(i * 4)] != 3 || /* xlate == table */ transinfo[(i * 4) + 2] != 0 || /* no xlate offset */ transinfo[(i * 4) + 3] != 0x100) { /* xlate tbl length */ printf(": unsupported sensor %d\n", i); return; } chp->chan_num = chanuse[(i * 4)]; } sc->sc_tag = ia->ia_tag; sc->sc_addr = ia->ia_addr; iic_acquire_bus(sc->sc_tag, 0); /* Try a read now, so we can fail if it doesn't work */ if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, NULL, 0, junk, sc->sc_nchan + 1, 0)) { printf(": read failed\n"); iic_release_bus(sc->sc_tag, 0); return; } iic_release_bus(sc->sc_tag, 0); /* Initialize sensor data. */ strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, sizeof(sc->sc_sensordev.xname)); for (i = 0; i < sc->sc_nchan; i++) if (!(sc->sc_channels[i].chan_sensor.flags & SENSOR_FINVALID)) sensor_attach(&sc->sc_sensordev, &sc->sc_channels[i].chan_sensor); if (sensor_task_register(sc, pcfadc_refresh, 5)) { printf(": unable to register update task\n"); return; } sensordev_install(&sc->sc_sensordev); printf("\n"); }
static int maxrtc_clock_write(struct maxrtc_softc *sc, struct clock_ymdhms *dt) { uint8_t bcd[MAX6900_BURST_LEN], cmdbuf[2]; uint8_t init_seconds, final_seconds; int i; /* * Convert our time representation into something the MAX6900 * can understand. */ bcd[MAX6900_BURST_SECOND] = TOBCD(dt->dt_sec); bcd[MAX6900_BURST_MINUTE] = TOBCD(dt->dt_min); bcd[MAX6900_BURST_HOUR] = TOBCD(dt->dt_hour) & MAX6900_HOUR_24MASK; bcd[MAX6900_BURST_DATE] = TOBCD(dt->dt_day); bcd[MAX6900_BURST_WDAY] = TOBCD(dt->dt_wday); bcd[MAX6900_BURST_MONTH] = TOBCD(dt->dt_mon); bcd[MAX6900_BURST_YEAR] = TOBCD(dt->dt_year % 100); /* century in control slot */ bcd[MAX6900_BURST_CONTROL] = TOBCD(dt->dt_year / 100); if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, "maxrtc_clock_write: failed to acquire I2C bus\n"); return (0); } /* Start by clearing the control register's write-protect bit. */ cmdbuf[0] = MAX6900_REG_CONTROL | MAX6900_CMD_WRITE; cmdbuf[1] = 0; if (iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "maxrtc_clock_write: failed to clear WP bit\n"); return (0); } /* * The MAX6900 RTC manual recommends ensuring "atomicity" of * a non-burst write by: * * - writing SECONDS * - reading back SECONDS, remembering it as "initial seconds" * - write the remaing RTC registers * - read back SECONDS as "final seconds" * - if "initial seconds" == 59, ensure "final seconds" == 59 * - else, ensure "final seconds" is no more than one second * beyond "initial seconds". */ again: cmdbuf[0] = MAX6900_REG_SECOND | MAX6900_CMD_WRITE; if (iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address, cmdbuf, 1, &bcd[MAX6900_BURST_SECOND], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "maxrtc_clock_write: failed to write SECONDS\n"); return (0); } cmdbuf[0] = MAX6900_REG_SECOND | MAX6900_CMD_READ; if (iic_exec(sc->sc_tag, I2C_OP_READ, sc->sc_address, cmdbuf, 1, &init_seconds, 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "maxrtc_clock_write: failed to read " "INITIAL SECONDS\n"); return (0); } for (i = 1; i < MAX6900_BURST_LEN; i++) { cmdbuf[0] = max6900_rtc_offset[i] | MAX6900_CMD_WRITE; if (iic_exec(sc->sc_tag, i != MAX6900_BURST_LEN - 1 ? I2C_OP_WRITE : I2C_OP_WRITE_WITH_STOP, sc->sc_address, cmdbuf, 1, &bcd[i], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "maxrtc_clock_write: failed to write rtc " " at 0x%x\n", max6900_rtc_offset[i]); return (0); } } cmdbuf[0] = MAX6900_REG_SECOND | MAX6900_CMD_READ; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &final_seconds, 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "maxrtc_clock_write: failed to read " "FINAL SECONDS\n"); return (0); } if ((init_seconds == 59 && final_seconds != 59) || (init_seconds != 59 && final_seconds != init_seconds + 1)) { #if 1 printf("%s: maxrtc_clock_write: init %d, final %d, try again\n", device_xname(sc->sc_dev), init_seconds, final_seconds); #endif goto again; } /* Finish by setting the control register's write-protect bit. */ cmdbuf[0] = MAX6900_REG_CONTROL | MAX6900_CMD_WRITE; cmdbuf[1] = MAX6900_CONTROL_WP; if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "maxrtc_clock_write: failed to set WP bit\n"); return (0); } iic_release_bus(sc->sc_tag, I2C_F_POLL); return (1); }
/*ARGSUSED*/ int maxrtc_write(dev_t dev, struct uio *uio, int flags) { struct maxrtc_softc *sc; u_int8_t cmdbuf[2]; int a, error, sverror; if ((sc = device_lookup_private(&maxrtc_cd, minor(dev))) == NULL) return (ENXIO); if (uio->uio_offset >= MAX6900_RAM_BYTES) return (EINVAL); if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) return (error); /* Start by clearing the control register's write-protect bit. */ cmdbuf[0] = MAX6900_REG_CONTROL | MAX6900_CMD_WRITE; cmdbuf[1] = 0; if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, 0)) != 0) { iic_release_bus(sc->sc_tag, 0); aprint_error_dev(sc->sc_dev, "maxrtc_write: failed to clear WP bit\n"); return (error); } while (uio->uio_resid && uio->uio_offset < MAX6900_RAM_BYTES) { a = (int)uio->uio_offset; cmdbuf[0] = MAX6900_REG_RAM(a) | MAX6900_CMD_WRITE; if ((error = uiomove(&cmdbuf[1], 1, uio)) != 0) break; if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, 0)) != 0) { aprint_error_dev(sc->sc_dev, "maxrtc_write: write failed at 0x%x\n", a); break; } } /* Set the write-protect bit again. */ cmdbuf[0] = MAX6900_REG_CONTROL | MAX6900_CMD_WRITE; cmdbuf[1] = MAX6900_CONTROL_WP; sverror = error; if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, 0)) != 0) { if (sverror != 0) error = sverror; aprint_error_dev(sc->sc_dev, "maxrtc_write: failed to set WP bit\n"); } iic_release_bus(sc->sc_tag, 0); return (error); }
void lmtemp_attach(struct device *parent, struct device *self, void *aux) { struct lmtemp_softc *sc = (struct lmtemp_softc *)self; struct i2c_attach_args *ia = aux; u_int8_t cmd, data; sc->sc_tag = ia->ia_tag; sc->sc_addr = ia->ia_addr; printf(": %s", ia->ia_name); /* If in SHUTDOWN mode, wake it up */ iic_acquire_bus(sc->sc_tag, 0); cmd = LM75_REG_CONFIG; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { iic_release_bus(sc->sc_tag, 0); printf(", fails to respond\n"); return; } if (data & LM75_CONFIG_SHUTDOWN) { data &= ~LM75_CONFIG_SHUTDOWN; if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { printf(", cannot wake up\n"); iic_release_bus(sc->sc_tag, 0); return; } printf(", woken up"); } iic_release_bus(sc->sc_tag, 0); sc->sc_model = LM_MODEL_LM75; sc->sc_bits = 9; sc->sc_ratio = 500000; /* 0.5 degC for LSB */ if (strcmp(ia->ia_name, "lm77") == 0) { sc->sc_model = LM_MODEL_LM77; sc->sc_bits = 13; } else if (strcmp(ia->ia_name, "lm76") == 0) { sc->sc_model = LM_MODEL_LM76; sc->sc_bits = 13; sc->sc_ratio = 62500; /* 0.0625 degC for LSB */ } else if (strcmp(ia->ia_name, "ds1775") == 0) { sc->sc_model = LM_MODEL_DS1775; //sc->sc_bits = DS1755_CONFIG_RESOLUTION(data); } else if (strcmp(ia->ia_name, "lm75a") == 0) { /* For simplicity's sake, treat the LM75A as an LM75 */ sc->sc_model = LM_MODEL_LM75A; } printf("\n"); /* Initialize sensor data */ strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, sizeof(sc->sc_sensordev.xname)); sc->sc_sensor.type = SENSOR_TEMP; /* Hook into the hw.sensors sysctl */ sensor_attach(&sc->sc_sensordev, &sc->sc_sensor); sensordev_install(&sc->sc_sensordev); sensor_task_register(sc, lmtemp_refresh_sensor_data, LM_POLLTIME); }