17418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle/* 27418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle * Copyright (C) 2012 Sven Schnelle <svens@stackframe.org> 37418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle * 47418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle * This program is free software; you can redistribute it and/or modify 57418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle * it under the terms of the GNU General Public License version 2 as 67418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle * published by the Free Software Foundation. 77418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle * 87418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle */ 97418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 107418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#include <linux/platform_device.h> 117418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#include <linux/module.h> 127418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#include <linux/init.h> 137418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#include <linux/rtc.h> 147418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#include <linux/types.h> 157418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#include <linux/bcd.h> 167418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#include <linux/rtc-ds2404.h> 177418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#include <linux/delay.h> 187418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#include <linux/gpio.h> 197418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#include <linux/slab.h> 207418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 217418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#include <linux/io.h> 227418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 237418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#define DS2404_STATUS_REG 0x200 247418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#define DS2404_CONTROL_REG 0x201 257418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#define DS2404_RTC_REG 0x202 267418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 277418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#define DS2404_WRITE_SCRATCHPAD_CMD 0x0f 287418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#define DS2404_READ_SCRATCHPAD_CMD 0xaa 297418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#define DS2404_COPY_SCRATCHPAD_CMD 0x55 307418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#define DS2404_READ_MEMORY_CMD 0xf0 317418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 327418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestruct ds2404; 337418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 347418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestruct ds2404_chip_ops { 357418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle int (*map_io)(struct ds2404 *chip, struct platform_device *pdev, 367418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle struct ds2404_platform_data *pdata); 377418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle void (*unmap_io)(struct ds2404 *chip); 387418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle}; 397418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 407418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#define DS2404_RST 0 417418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#define DS2404_CLK 1 427418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle#define DS2404_DQ 2 437418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 447418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestruct ds2404_gpio { 457418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle const char *name; 467418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle unsigned int gpio; 477418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle}; 487418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 497418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestruct ds2404 { 507418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle struct ds2404_gpio *gpio; 517418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle struct ds2404_chip_ops *ops; 527418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle struct rtc_device *rtc; 537418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle}; 547418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 557418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic struct ds2404_gpio ds2404_gpio[] = { 567418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle { "RTC RST", 0 }, 577418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle { "RTC CLK", 0 }, 587418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle { "RTC DQ", 0 }, 597418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle}; 607418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 617418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic int ds2404_gpio_map(struct ds2404 *chip, struct platform_device *pdev, 627418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle struct ds2404_platform_data *pdata) 637418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle{ 647418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle int i, err; 657418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 667418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_gpio[DS2404_RST].gpio = pdata->gpio_rst; 677418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_gpio[DS2404_CLK].gpio = pdata->gpio_clk; 687418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_gpio[DS2404_DQ].gpio = pdata->gpio_dq; 697418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 707418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle for (i = 0; i < ARRAY_SIZE(ds2404_gpio); i++) { 717418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle err = gpio_request(ds2404_gpio[i].gpio, ds2404_gpio[i].name); 727418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle if (err) { 730fae82378ad55a7dfd03f5f6fb092798d8019bc3Jingoo Han dev_err(&pdev->dev, "error mapping gpio %s: %d\n", 747418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_gpio[i].name, err); 757418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle goto err_request; 767418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle } 777418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle if (i != DS2404_DQ) 787418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle gpio_direction_output(ds2404_gpio[i].gpio, 1); 797418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle } 807418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 817418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle chip->gpio = ds2404_gpio; 827418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle return 0; 837418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 847418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelleerr_request: 857418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle while (--i >= 0) 867418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle gpio_free(ds2404_gpio[i].gpio); 877418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle return err; 887418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle} 897418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 907418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic void ds2404_gpio_unmap(struct ds2404 *chip) 917418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle{ 927418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle int i; 937418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 947418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle for (i = 0; i < ARRAY_SIZE(ds2404_gpio); i++) 957418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle gpio_free(ds2404_gpio[i].gpio); 967418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle} 977418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 987418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic struct ds2404_chip_ops ds2404_gpio_ops = { 997418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle .map_io = ds2404_gpio_map, 1007418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle .unmap_io = ds2404_gpio_unmap, 1017418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle}; 1027418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1037418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic void ds2404_reset(struct device *dev) 1047418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle{ 1057418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle gpio_set_value(ds2404_gpio[DS2404_RST].gpio, 0); 1067418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle udelay(1000); 1077418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle gpio_set_value(ds2404_gpio[DS2404_RST].gpio, 1); 1087418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 0); 1097418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle gpio_direction_output(ds2404_gpio[DS2404_DQ].gpio, 0); 1107418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle udelay(10); 1117418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle} 1127418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1137418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic void ds2404_write_byte(struct device *dev, u8 byte) 1147418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle{ 1157418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle int i; 1167418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1177418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle gpio_direction_output(ds2404_gpio[DS2404_DQ].gpio, 1); 1187418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle for (i = 0; i < 8; i++) { 1197418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle gpio_set_value(ds2404_gpio[DS2404_DQ].gpio, byte & (1 << i)); 1207418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle udelay(10); 1217418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 1); 1227418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle udelay(10); 1237418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 0); 1247418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle udelay(10); 1257418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle } 1267418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle} 1277418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1287418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic u8 ds2404_read_byte(struct device *dev) 1297418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle{ 1307418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle int i; 1317418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle u8 ret = 0; 1327418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1337418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle gpio_direction_input(ds2404_gpio[DS2404_DQ].gpio); 1347418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1357418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle for (i = 0; i < 8; i++) { 1367418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 0); 1377418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle udelay(10); 1387418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle if (gpio_get_value(ds2404_gpio[DS2404_DQ].gpio)) 1397418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ret |= 1 << i; 1407418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 1); 1417418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle udelay(10); 1427418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle } 1437418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle return ret; 1447418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle} 1457418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1467418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic void ds2404_read_memory(struct device *dev, u16 offset, 1477418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle int length, u8 *out) 1487418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle{ 1497418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_reset(dev); 1507418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_write_byte(dev, DS2404_READ_MEMORY_CMD); 1517418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_write_byte(dev, offset & 0xff); 1527418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_write_byte(dev, (offset >> 8) & 0xff); 1537418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle while (length--) 1547418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle *out++ = ds2404_read_byte(dev); 1557418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle} 1567418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1577418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic void ds2404_write_memory(struct device *dev, u16 offset, 1587418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle int length, u8 *out) 1597418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle{ 1607418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle int i; 1617418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle u8 ta01, ta02, es; 1627418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1637418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_reset(dev); 1647418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_write_byte(dev, DS2404_WRITE_SCRATCHPAD_CMD); 1657418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_write_byte(dev, offset & 0xff); 1667418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_write_byte(dev, (offset >> 8) & 0xff); 1677418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1687418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle for (i = 0; i < length; i++) 1697418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_write_byte(dev, out[i]); 1707418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1717418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_reset(dev); 1727418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_write_byte(dev, DS2404_READ_SCRATCHPAD_CMD); 1737418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1747418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ta01 = ds2404_read_byte(dev); 1757418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ta02 = ds2404_read_byte(dev); 1767418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle es = ds2404_read_byte(dev); 1777418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1787418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle for (i = 0; i < length; i++) { 1797418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle if (out[i] != ds2404_read_byte(dev)) { 1800fae82378ad55a7dfd03f5f6fb092798d8019bc3Jingoo Han dev_err(dev, "read invalid data\n"); 1817418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle return; 1827418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle } 1837418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle } 1847418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1857418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_reset(dev); 1867418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_write_byte(dev, DS2404_COPY_SCRATCHPAD_CMD); 1877418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_write_byte(dev, ta01); 1887418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_write_byte(dev, ta02); 1897418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_write_byte(dev, es); 1907418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1917418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle gpio_direction_input(ds2404_gpio[DS2404_DQ].gpio); 1927418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle while (gpio_get_value(ds2404_gpio[DS2404_DQ].gpio)) 1937418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ; 1947418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle} 1957418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 1967418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic void ds2404_enable_osc(struct device *dev) 1977418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle{ 1987418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle u8 in[1] = { 0x10 }; /* enable oscillator */ 1997418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_write_memory(dev, 0x201, 1, in); 2007418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle} 2017418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2027418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic int ds2404_read_time(struct device *dev, struct rtc_time *dt) 2037418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle{ 2047418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle unsigned long time = 0; 2057418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2067418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_read_memory(dev, 0x203, 4, (u8 *)&time); 2077418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle time = le32_to_cpu(time); 2087418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2097418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle rtc_time_to_tm(time, dt); 2107418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle return rtc_valid_tm(dt); 2117418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle} 2127418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2137418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic int ds2404_set_mmss(struct device *dev, unsigned long secs) 2147418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle{ 2157418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle u32 time = cpu_to_le32(secs); 2167418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_write_memory(dev, 0x203, 4, (u8 *)&time); 2177418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle return 0; 2187418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle} 2197418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2207418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic const struct rtc_class_ops ds2404_rtc_ops = { 2217418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle .read_time = ds2404_read_time, 2227418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle .set_mmss = ds2404_set_mmss, 2237418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle}; 2247418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2257418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic int rtc_probe(struct platform_device *pdev) 2267418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle{ 22777bf38223c0bf51bb303bc074881b403be3c09b4Jingoo Han struct ds2404_platform_data *pdata = dev_get_platdata(&pdev->dev); 2287418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle struct ds2404 *chip; 2297418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle int retval = -EBUSY; 2307418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2312a444cf77cb584485aea4f1ee5538a5dee705e99Jingoo Han chip = devm_kzalloc(&pdev->dev, sizeof(struct ds2404), GFP_KERNEL); 2327418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle if (!chip) 2337418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle return -ENOMEM; 2347418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2357418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle chip->ops = &ds2404_gpio_ops; 2367418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2377418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle retval = chip->ops->map_io(chip, pdev, pdata); 2387418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle if (retval) 2397418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle goto err_chip; 2407418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2417418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle dev_info(&pdev->dev, "using GPIOs RST:%d, CLK:%d, DQ:%d\n", 2427418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle chip->gpio[DS2404_RST].gpio, chip->gpio[DS2404_CLK].gpio, 2437418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle chip->gpio[DS2404_DQ].gpio); 2447418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2457418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle platform_set_drvdata(pdev, chip); 2467418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2472a444cf77cb584485aea4f1ee5538a5dee705e99Jingoo Han chip->rtc = devm_rtc_device_register(&pdev->dev, "ds2404", 2482a444cf77cb584485aea4f1ee5538a5dee705e99Jingoo Han &ds2404_rtc_ops, THIS_MODULE); 2497418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle if (IS_ERR(chip->rtc)) { 2507418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle retval = PTR_ERR(chip->rtc); 2517418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle goto err_io; 2527418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle } 2537418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2547418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle ds2404_enable_osc(&pdev->dev); 2557418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle return 0; 2567418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2577418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelleerr_io: 2587418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle chip->ops->unmap_io(chip); 2597418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelleerr_chip: 2607418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle return retval; 2617418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle} 2627418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2637418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic int rtc_remove(struct platform_device *dev) 2647418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle{ 2657418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle struct ds2404 *chip = platform_get_drvdata(dev); 2667418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2677418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle chip->ops->unmap_io(chip); 2687418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2697418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle return 0; 2707418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle} 2717418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2727418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnellestatic struct platform_driver rtc_device_driver = { 2737418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle .probe = rtc_probe, 2747418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle .remove = rtc_remove, 2757418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle .driver = { 2767418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle .name = "ds2404", 2777418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle .owner = THIS_MODULE, 2787418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle }, 2797418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle}; 28056ae1b8e420015f1428bf9443f1b3321ad789b02Srinivas Kandagatlamodule_platform_driver(rtc_device_driver); 2817418a1198991beb5bf6656b2ac0bcbde378c5539Sven Schnelle 2827418a1198991beb5bf6656b2ac0bcbde378c5539Sven SchnelleMODULE_DESCRIPTION("DS2404 RTC"); 2837418a1198991beb5bf6656b2ac0bcbde378c5539Sven SchnelleMODULE_AUTHOR("Sven Schnelle"); 2847418a1198991beb5bf6656b2ac0bcbde378c5539Sven SchnelleMODULE_LICENSE("GPL"); 2857418a1198991beb5bf6656b2ac0bcbde378c5539Sven SchnelleMODULE_ALIAS("platform:ds2404"); 286