static int todds1307_write_rtc(struct rtc_t *rtc) { ds1307_state_t *statep = NULL; i2c_transfer_t *i2c_tp = NULL; int i2c_cmd_status = I2C_SUCCESS; if (!todds1307_attach_done) { return (todds1307_prom_setdate(rtc)); } statep = ddi_get_soft_state(ds1307_statep, instance); if (statep == NULL) { return (DDI_FAILURE); } if ((i2c_cmd_status = i2c_transfer_alloc(statep->ds1307_i2c_hdl, &i2c_tp, 8, 0, I2C_SLEEP)) != I2C_SUCCESS) { return (i2c_cmd_status); } i2c_tp->i2c_version = I2C_XFER_REV; i2c_tp->i2c_flags = I2C_WR; i2c_tp->i2c_wbuf[0] = (uchar_t)0x00; i2c_tp->i2c_wbuf[1] = rtc->rtc_sec; i2c_tp->i2c_wbuf[2] = rtc->rtc_min; i2c_tp->i2c_wbuf[3] = rtc->rtc_hrs; i2c_tp->i2c_wbuf[4] = rtc->rtc_dow; i2c_tp->i2c_wbuf[5] = rtc->rtc_dom; i2c_tp->i2c_wbuf[6] = rtc->rtc_mon; i2c_tp->i2c_wbuf[7] = rtc->rtc_year; i2c_tp->i2c_wlen = 8; if ((i2c_cmd_status = i2c_transfer(statep->ds1307_i2c_hdl, i2c_tp)) != I2C_SUCCESS) { (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); /* delay(drv_usectohz(I2C_DELAY)); */ drv_usecwait(I2C_DELAY); return (i2c_cmd_status); } tod_read[0] = -1; /* invalidate saved data from read routine */ (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); return (i2c_cmd_status); }
static void pca9556_detach(dev_info_t *dip) { pca9556_unit_t *pcap; int instance = ddi_get_instance(dip); pcap = ddi_get_soft_state(pca9556_soft_statep, instance); if ((pcap->pca9556_flags & PCA9556_REGFLAG) == PCA9556_REGFLAG) { i2c_client_unregister(pcap->pca9556_hdl); } if ((pcap->pca9556_flags & PCA9556_TBUFFLAG) == PCA9556_TBUFFLAG) { i2c_transfer_free(pcap->pca9556_hdl, pcap->pca9556_transfer); } if ((pcap->pca9556_flags & PCA9556_MINORFLAG) == PCA9556_MINORFLAG) { ddi_remove_minor_node(dip, NULL); } cv_destroy(&pcap->pca9556_cv); mutex_destroy(&pcap->pca9556_mutex); ddi_soft_state_free(pca9556_soft_statep, instance); }
static int todds1307_read_rtc(struct rtc_t *rtc) { static ds1307_state_t *statep = NULL; i2c_transfer_t *i2c_tp = NULL; int i2c_cmd_status = I2C_FAILURE; int counter = 4; if (!todds1307_attach_done) { return (todds1307_prom_getdate(rtc)); } statep = ddi_get_soft_state(ds1307_statep, instance); if (statep == NULL) { cmn_err(CE_WARN, "todds1307: ddi_get_soft_state failed"); return (DDI_FAILURE); } mutex_enter(&todds1307_rd_lock); /* * Allocate 1 byte for write buffer and 7 bytes for read buffer to * to accomodate sec, min, hrs, dayOfWeek, dayOfMonth, year */ if ((i2c_transfer_alloc(statep->ds1307_i2c_hdl, &i2c_tp, 1, 7, I2C_SLEEP)) != I2C_SUCCESS) { mutex_exit(&todds1307_rd_lock); return (DDI_FAILURE); } do { i2c_tp->i2c_version = I2C_XFER_REV; i2c_tp->i2c_flags = I2C_WR_RD; i2c_tp->i2c_wbuf[0] = (uchar_t)0x00; /* Start from reg 0x00 */ i2c_tp->i2c_wlen = 1; /* Write one byte address */ i2c_tp->i2c_rlen = 7; /* Read 7 regs */ if ((i2c_cmd_status = i2c_transfer(statep->ds1307_i2c_hdl, i2c_tp)) != I2C_SUCCESS) { drv_usecwait(I2C_DELAY); goto done; } /* for first read, need to get valid data */ while (tod_read[0] == -1 && counter > 0) { /* move data to static buffer */ bcopy(i2c_tp->i2c_rbuf, tod_read, 7); /* now read again */ /* Start reading reg from 0x00 */ i2c_tp->i2c_wbuf[0] = (uchar_t)0x00; i2c_tp->i2c_wlen = 1; /* Write one byte address */ i2c_tp->i2c_rlen = 7; /* Read 7 regs */ if ((i2c_cmd_status = i2c_transfer(statep->ds1307_i2c_hdl, i2c_tp)) != I2C_SUCCESS) { drv_usecwait(I2C_DELAY); goto done; } /* if they are not the same, then read again */ if (bcmp(tod_read, i2c_tp->i2c_rbuf, 7) != 0) { tod_read[0] = -1; counter--; } } } while (i2c_tp->i2c_rbuf[0] == 0x59 && /* if seconds register is 0x59 (BCD), add data should match */ bcmp(&tod_read[1], &i2c_tp->i2c_rbuf[1], 6) != 0 && counter-- > 0); if (counter < 0) cmn_err(CE_WARN, "i2ctod: TOD Chip failed ??"); /* move data to static buffer */ bcopy(i2c_tp->i2c_rbuf, tod_read, 7); rtc->rtc_year = bcd2int(i2c_tp->i2c_rbuf[6]); rtc->rtc_mon = bcd2int(i2c_tp->i2c_rbuf[5]); rtc->rtc_dom = bcd2int(i2c_tp->i2c_rbuf[4]); rtc->rtc_dow = bcd2int(i2c_tp->i2c_rbuf[3]); rtc->rtc_hrs = bcd2int(i2c_tp->i2c_rbuf[2]); rtc->rtc_min = bcd2int(i2c_tp->i2c_rbuf[1]); rtc->rtc_sec = bcd2int(i2c_tp->i2c_rbuf[0]); done: (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); mutex_exit(&todds1307_rd_lock); return (i2c_cmd_status); }
/* * register ds1307 client device with i2c services, and * allocate & initialize soft state structure. */ static int todds1307_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { static ds1307_state_t *statep = NULL; i2c_transfer_t *i2c_tp = NULL; uint8_t tempVal = (uint8_t)0; switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: return (DDI_SUCCESS); default: return (DDI_FAILURE); } if (instance != -1) { return (DDI_FAILURE); } instance = ddi_get_instance(dip); /* * Allocate soft state structure */ if (ddi_soft_state_zalloc(ds1307_statep, instance) != DDI_SUCCESS) { return (DDI_FAILURE); } statep = ddi_get_soft_state(ds1307_statep, instance); if (statep == NULL) { return (DDI_FAILURE); } statep->dip = dip; if (i2c_client_register(dip, &statep->ds1307_i2c_hdl) != I2C_SUCCESS) { ddi_soft_state_free(ds1307_statep, instance); delay(drv_usectohz(I2C_DELAY)); return (DDI_FAILURE); } /* check and initialize the oscillator */ (void) i2c_transfer_alloc(statep->ds1307_i2c_hdl, &i2c_tp, 1, 1, I2C_SLEEP); i2c_tp->i2c_version = I2C_XFER_REV; i2c_tp->i2c_flags = I2C_WR_RD; i2c_tp->i2c_wbuf[0] = (uchar_t)0x00; /* Read 00h */ i2c_tp->i2c_wlen = 1; i2c_tp->i2c_rlen = 1; if ((i2c_transfer(statep->ds1307_i2c_hdl, i2c_tp)) != I2C_SUCCESS) { (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); ddi_soft_state_free(ds1307_statep, instance); delay(drv_usectohz(I2C_DELAY)); return (DDI_FAILURE); } tempVal = i2c_tp->i2c_rbuf[0]; (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); if (tempVal & 0x80) { /* check Oscillator */ (void) i2c_transfer_alloc(statep->ds1307_i2c_hdl, &i2c_tp, 2, 1, I2C_SLEEP); i2c_tp->i2c_version = I2C_XFER_REV; i2c_tp->i2c_flags = I2C_WR; i2c_tp->i2c_wbuf[0] = 0x00; i2c_tp->i2c_wbuf[1] = (uchar_t)(i2c_tp->i2c_rbuf[0]& 0x7f); i2c_tp->i2c_wlen = 2; /* Enable oscillator */ if ((i2c_transfer(statep->ds1307_i2c_hdl, i2c_tp)) != I2C_SUCCESS) { (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); ddi_soft_state_free(ds1307_statep, instance); return (DDI_FAILURE); } (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); } /* * Create a periodical handler to read TOD. */ ASSERT(statep->cycid == NULL); statep->cycid = ddi_periodic_add(todds1307_cyclic, &soft_rtc, i2c_cyclic_timeout, DDI_IPL_1); statep->state = TOD_ATTACHED; todds1307_attach_done = 1; ddi_report_dev(dip); return (DDI_SUCCESS); }