示例#1
0
static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct spi_device *spi = to_spi_device(dev);
	u8 txbuf[1], rxbuf[7];
	int ret;

	txbuf[0] = PCF2123_READ | PCF2123_REG_SC;
	ret = spi_write_then_read(spi, txbuf, sizeof(txbuf),
			rxbuf, sizeof(rxbuf));
	if (ret < 0)
		return ret;
	pcf2123_delay_trec();

	tm->tm_sec = bcd2bin(rxbuf[0] & 0x7F);
	tm->tm_min = bcd2bin(rxbuf[1] & 0x7F);
	tm->tm_hour = bcd2bin(rxbuf[2] & 0x3F); 
	tm->tm_mday = bcd2bin(rxbuf[3] & 0x3F);
	tm->tm_wday = rxbuf[4] & 0x07;
	tm->tm_mon = bcd2bin(rxbuf[5] & 0x1F) - 1; 
	tm->tm_year = bcd2bin(rxbuf[6]);
	if (tm->tm_year < 70)
		tm->tm_year += 100;	

	dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
			"mday=%d, mon=%d, year=%d, wday=%d\n",
			__func__,
			tm->tm_sec, tm->tm_min, tm->tm_hour,
			tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);

	
	if (rtc_valid_tm(tm) < 0)
		dev_err(dev, "retrieved date/time is not valid.\n");

	return 0;
}
示例#2
0
static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct spi_device *spi = to_spi_device(dev);
	u8 txbuf[1], rxbuf[7];
	int ret;

	txbuf[0] = PCF2123_READ | PCF2123_REG_SC;
	ret = spi_write_then_read(spi, txbuf, sizeof(txbuf),
			rxbuf, sizeof(rxbuf));
	if (ret < 0)
		return ret;
	pcf2123_delay_trec();

	tm->tm_sec = bcd2bin(rxbuf[0] & 0x7F);
	tm->tm_min = bcd2bin(rxbuf[1] & 0x7F);
	tm->tm_hour = bcd2bin(rxbuf[2] & 0x3F); /* rtc hr 0-23 */
	tm->tm_mday = bcd2bin(rxbuf[3] & 0x3F);
	tm->tm_wday = rxbuf[4] & 0x07;
	tm->tm_mon = bcd2bin(rxbuf[5] & 0x1F) - 1; /* rtc mn 1-12 */
	tm->tm_year = bcd2bin(rxbuf[6]);
	if (tm->tm_year < 70)
		tm->tm_year += 100;	/* assume we are in 1970...2069 */

	dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
			"mday=%d, mon=%d, year=%d, wday=%d\n",
			__func__,
			tm->tm_sec, tm->tm_min, tm->tm_hour,
			tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);

	return rtc_valid_tm(tm);
}
示例#3
0
static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,
			     const char *buffer, size_t count) {
	struct spi_device *spi = to_spi_device(dev);
	struct pcf2123_sysfs_reg *r;
	u8 txbuf[2];
	unsigned long reg;
	unsigned long val;

	int ret;

	r = container_of(attr, struct pcf2123_sysfs_reg, attr);

	ret = kstrtoul(r->name, 16, &reg);
	if (ret)
		return ret;

	ret = kstrtoul(buffer, 10, &val);
	if (ret)
		return ret;

	txbuf[0] = PCF2123_WRITE | reg;
	txbuf[1] = val;
	ret = spi_write(spi, txbuf, sizeof(txbuf));
	if (ret < 0)
		return -EIO;
	pcf2123_delay_trec();
	return count;
}
static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	struct spi_device *spi = to_spi_device(dev);
	u8 txbuf[8];
	int ret;

	dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
			"mday=%d, mon=%d, year=%d, wday=%d\n",
			__func__,
			tm->tm_sec, tm->tm_min, tm->tm_hour,
			tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);

	/*                        */
	txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
	txbuf[1] = 0x20;
	ret = spi_write(spi, txbuf, 2);
	if (ret < 0)
		return ret;
	pcf2123_delay_trec();

	/*                  */
	txbuf[0] = PCF2123_WRITE | PCF2123_REG_SC;
	txbuf[1] = bin2bcd(tm->tm_sec & 0x7F);
	txbuf[2] = bin2bcd(tm->tm_min & 0x7F);
	txbuf[3] = bin2bcd(tm->tm_hour & 0x3F);
	txbuf[4] = bin2bcd(tm->tm_mday & 0x3F);
	txbuf[5] = tm->tm_wday & 0x07;
	txbuf[6] = bin2bcd((tm->tm_mon + 1) & 0x1F); /*             */
	txbuf[7] = bin2bcd(tm->tm_year < 100 ? tm->tm_year : tm->tm_year - 100);

	ret = spi_write(spi, txbuf, sizeof(txbuf));
	if (ret < 0)
		return ret;
	pcf2123_delay_trec();

	/*                   */
	txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
	txbuf[1] = 0x00;
	ret = spi_write(spi, txbuf, 2);
	if (ret < 0)
		return ret;
	pcf2123_delay_trec();

	return 0;
}
示例#5
0
static int pcf2123_write(struct device *dev, u8 *txbuf, size_t size)
{
	struct spi_device *spi = to_spi_device(dev);
	int ret;

	txbuf[0] |= PCF2123_WRITE;
	ret = spi_write(spi, txbuf, size);
	pcf2123_delay_trec();

	return ret;
}
示例#6
0
static int pcf2123_read(struct device *dev, u8 reg, u8 *rxbuf, size_t size)
{
	struct spi_device *spi = to_spi_device(dev);
	int ret;

	reg |= PCF2123_READ;
	ret = spi_write_then_read(spi, &reg, 1, rxbuf, size);
	pcf2123_delay_trec();

	return ret;
}
static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr,
			    char *buffer)
{
	struct spi_device *spi = to_spi_device(dev);
	struct pcf2123_sysfs_reg *r;
	u8 txbuf[1], rxbuf[1];
	unsigned long reg;
	int ret;

	r = container_of(attr, struct pcf2123_sysfs_reg, attr);

	if (strict_strtoul(r->name, 16, &reg))
		return -EINVAL;

	txbuf[0] = PCF2123_READ | reg;
	ret = spi_write_then_read(spi, txbuf, 1, rxbuf, 1);
	if (ret < 0)
		return -EIO;
	pcf2123_delay_trec();
	return sprintf(buffer, "0x%x\n", rxbuf[0]);
}
示例#8
0
static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct spi_device *spi = to_spi_device(dev);
	u8 txbuf[1], rxbuf[7];
	int ret;

	txbuf[0] = PCF2123_READ | PCF2123_REG_SC;
	ret = spi_write_then_read(spi, txbuf, sizeof(txbuf),
			rxbuf, sizeof(rxbuf));
	if (ret < 0)
		return ret;
	pcf2123_delay_trec();

	tm->tm_sec = bcd2bin(rxbuf[0] & 0x7F);
	tm->tm_min = bcd2bin(rxbuf[1] & 0x7F);
	tm->tm_hour = bcd2bin(rxbuf[2] & 0x3F); /* rtc hr 0-23 */
	tm->tm_mday = bcd2bin(rxbuf[3] & 0x3F);
	tm->tm_wday = rxbuf[4] & 0x07;
	tm->tm_mon = bcd2bin(rxbuf[5] & 0x1F) - 1; /* rtc mn 1-12 */
	tm->tm_year = bcd2bin(rxbuf[6]);
	if (tm->tm_year < 70)
		tm->tm_year += 100;	/* assume we are in 1970...2069 */

	dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
			"mday=%d, mon=%d, year=%d, wday=%d\n",
			__func__,
			tm->tm_sec, tm->tm_min, tm->tm_hour,
			tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);

	/* the clock can give out invalid datetime, but we cannot return
	 * -EINVAL otherwise hwclock will refuse to set the time on bootup.
	 */
	if (rtc_valid_tm(tm) < 0)
		dev_err(dev, "retrieved date/time is not valid.\n");

	return 0;
}
static int __devinit pcf2123_probe(struct spi_device *spi)
{
	struct rtc_device *rtc;
	struct pcf2123_plat_data *pdata;
	u8 txbuf[2], rxbuf[2];
	int ret, i;

	pdata = kzalloc(sizeof(struct pcf2123_plat_data), GFP_KERNEL);
	if (!pdata)
		return -ENOMEM;
	spi->dev.platform_data = pdata;

	/*                               */
	txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
	txbuf[1] = 0x58;
	dev_dbg(&spi->dev, "resetting RTC (0x%02X 0x%02X)\n",
			txbuf[0], txbuf[1]);
	ret = spi_write(spi, txbuf, 2 * sizeof(u8));
	if (ret < 0)
		goto kfree_exit;
	pcf2123_delay_trec();

	/*                  */
	txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
	txbuf[1] = 0x20;
	dev_dbg(&spi->dev, "stopping RTC (0x%02X 0x%02X)\n",
			txbuf[0], txbuf[1]);
	ret = spi_write(spi, txbuf, 2 * sizeof(u8));
	if (ret < 0)
		goto kfree_exit;
	pcf2123_delay_trec();

	/*                                         */
	txbuf[0] = PCF2123_READ | PCF2123_REG_CTRL1;
	dev_dbg(&spi->dev, "checking for presence of RTC (0x%02X)\n",
			txbuf[0]);
	ret = spi_write_then_read(spi, txbuf, 1 * sizeof(u8),
					rxbuf, 2 * sizeof(u8));
	dev_dbg(&spi->dev, "received data from RTC (0x%02X 0x%02X)\n",
			rxbuf[0], rxbuf[1]);
	if (ret < 0)
		goto kfree_exit;
	pcf2123_delay_trec();

	if (!(rxbuf[0] & 0x20)) {
		dev_err(&spi->dev, "chip not found\n");
		goto kfree_exit;
	}

	dev_info(&spi->dev, "chip found, driver version " DRV_VERSION "\n");
	dev_info(&spi->dev, "spiclk %u KHz.\n",
			(spi->max_speed_hz + 500) / 1000);

	/*                   */
	txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
	txbuf[1] = 0x00;
	ret = spi_write(spi, txbuf, sizeof(txbuf));
	if (ret < 0)
		goto kfree_exit;
	pcf2123_delay_trec();

	/*                             */
	rtc = rtc_device_register(pcf2123_driver.driver.name, &spi->dev,
			&pcf2123_rtc_ops, THIS_MODULE);

	if (IS_ERR(rtc)) {
		dev_err(&spi->dev, "failed to register.\n");
		ret = PTR_ERR(rtc);
		goto kfree_exit;
	}

	pdata->rtc = rtc;

	for (i = 0; i < 16; i++) {
		sprintf(pdata->regs[i].name, "%1x", i);
		pdata->regs[i].attr.attr.mode = S_IRUGO | S_IWUSR;
		pdata->regs[i].attr.attr.name = pdata->regs[i].name;
		pdata->regs[i].attr.show = pcf2123_show;
		pdata->regs[i].attr.store = pcf2123_store;
		ret = device_create_file(&spi->dev, &pdata->regs[i].attr);
		if (ret) {
			dev_err(&spi->dev, "Unable to create sysfs %s\n",
				pdata->regs[i].name);
			goto sysfs_exit;
		}
	}

	return 0;

sysfs_exit:
	for (i--; i >= 0; i--)
		device_remove_file(&spi->dev, &pdata->regs[i].attr);

kfree_exit:
	kfree(pdata);
	spi->dev.platform_data = NULL;
	return ret;
}