Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
/*
 * 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);
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
static int
pca9556_attach(dev_info_t *dip)
{
	pca9556_unit_t 		*pcap;
	int 			instance = ddi_get_instance(dip);
	char			name[MAXNAMELEN];
	char *device_name;
	minor_t 		minor;
	int			i, num_ports;

	if (ddi_soft_state_zalloc(pca9556_soft_statep, instance) != 0) {
		cmn_err(CE_WARN, "%s%d failed to zalloc softstate",
		    ddi_get_name(dip), instance);
		return (DDI_FAILURE);
	}

	pcap = ddi_get_soft_state(pca9556_soft_statep, instance);

	if (pcap == NULL)
		return (DDI_FAILURE);

	mutex_init(&pcap->pca9556_mutex, NULL, MUTEX_DRIVER, NULL);
	cv_init(&pcap->pca9556_cv, NULL, CV_DRIVER, NULL);

	(void) snprintf(pcap->pca9556_name, sizeof (pcap->pca9556_name),
	    "%s_%d", ddi_driver_name(dip), instance);

	device_name = ddi_get_name(dip);

	if (strcmp(device_name, "i2c-pca9555") == 0) {
		num_ports = PCA9555_NUM_PORTS;
		pcap->pca9555_device = B_TRUE;
	} else {
		num_ports = PCA9556_NUM_PORTS;
		pcap->pca9555_device = B_FALSE;
		minor = INST_TO_MINOR(instance);
	}

	for (i = 0; i < num_ports; i++) {
		if (!(pcap->pca9555_device)) {
			(void) snprintf(pcap->pca9556_name,
			    sizeof (pcap->pca9556_name), "%s_%d",
			    ddi_driver_name(dip), instance);
			(void) snprintf(name, sizeof (name), "%s",
			    pcap->pca9556_name);
		} else {
			(void) sprintf(name, "port_%d", i);
			minor = INST_TO_MINOR(instance) |
			    PORT_TO_MINOR(I2C_PORT(i));
		}

		if (ddi_create_minor_node(dip, name, S_IFCHR, minor,
		    PCA9556_NODE_TYPE, NULL) == DDI_FAILURE) {
			cmn_err(CE_WARN, "%s: failed to create node for %s",
			    pcap->pca9556_name, name);
			pca9556_detach(dip);
			return (DDI_FAILURE);
		}
	}
	pcap->pca9556_flags |= PCA9556_MINORFLAG;

	/*
	 * Add a zero-length attribute to tell the world we support
	 * kernel ioctls (for layered drivers)
	 */
	(void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
	    DDI_KERNEL_IOCTL, NULL, 0);


	/*
	 * preallocate a single buffer for all reads and writes
	 */
	if (i2c_transfer_alloc(pcap->pca9556_hdl, &pcap->pca9556_transfer,
	    2, 2, I2C_SLEEP) != I2C_SUCCESS) {
		cmn_err(CE_WARN, "%s i2c_transfer_alloc failed",
		    pcap->pca9556_name);
		pca9556_detach(dip);
		return (DDI_FAILURE);
	}
	pcap->pca9556_flags |= PCA9556_TBUFFLAG;
	pcap->pca9556_transfer->i2c_version = I2C_XFER_REV;

	if (i2c_client_register(dip, &pcap->pca9556_hdl) != I2C_SUCCESS) {
		ddi_remove_minor_node(dip, NULL);
		cmn_err(CE_WARN, "%s i2c_client_register failed",
		    pcap->pca9556_name);
		pca9556_detach(dip);
		return (DDI_FAILURE);
	}
	pcap->pca9556_flags |= PCA9556_REGFLAG;

	/*
	 * Store the dip for future dip.
	 */
	pcap->pca9556_dip = dip;
	return (DDI_SUCCESS);
}