1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2012 Sven Schnelle <svens@stackframe.org>
4 #include <linux/platform_device.h>
5 #include <linux/module.h>
6 #include <linux/init.h>
8 #include <linux/types.h>
10 #include <linux/delay.h>
11 #include <linux/gpio/consumer.h>
12 #include <linux/slab.h>
16 #define DS2404_STATUS_REG 0x200
17 #define DS2404_CONTROL_REG 0x201
18 #define DS2404_RTC_REG 0x202
20 #define DS2404_WRITE_SCRATCHPAD_CMD 0x0f
21 #define DS2404_READ_SCRATCHPAD_CMD 0xaa
22 #define DS2404_COPY_SCRATCHPAD_CMD 0x55
23 #define DS2404_READ_MEMORY_CMD 0xf0
31 struct gpio_desc
*rst_gpiod
;
32 struct gpio_desc
*clk_gpiod
;
33 struct gpio_desc
*dq_gpiod
;
34 struct rtc_device
*rtc
;
37 static int ds2404_gpio_map(struct ds2404
*chip
, struct platform_device
*pdev
)
39 struct device
*dev
= &pdev
->dev
;
41 /* This will de-assert RESET, declare this GPIO as GPIOD_ACTIVE_LOW */
42 chip
->rst_gpiod
= devm_gpiod_get(dev
, "rst", GPIOD_OUT_LOW
);
43 if (IS_ERR(chip
->rst_gpiod
))
44 return PTR_ERR(chip
->rst_gpiod
);
46 chip
->clk_gpiod
= devm_gpiod_get(dev
, "clk", GPIOD_OUT_HIGH
);
47 if (IS_ERR(chip
->clk_gpiod
))
48 return PTR_ERR(chip
->clk_gpiod
);
50 chip
->dq_gpiod
= devm_gpiod_get(dev
, "dq", GPIOD_ASIS
);
51 if (IS_ERR(chip
->dq_gpiod
))
52 return PTR_ERR(chip
->dq_gpiod
);
57 static void ds2404_reset(struct ds2404
*chip
)
59 gpiod_set_value(chip
->rst_gpiod
, 1);
61 gpiod_set_value(chip
->rst_gpiod
, 0);
62 gpiod_set_value(chip
->clk_gpiod
, 0);
63 gpiod_direction_output(chip
->dq_gpiod
, 0);
67 static void ds2404_write_byte(struct ds2404
*chip
, u8 byte
)
71 gpiod_direction_output(chip
->dq_gpiod
, 1);
72 for (i
= 0; i
< 8; i
++) {
73 gpiod_set_value(chip
->dq_gpiod
, byte
& (1 << i
));
75 gpiod_set_value(chip
->clk_gpiod
, 1);
77 gpiod_set_value(chip
->clk_gpiod
, 0);
82 static u8
ds2404_read_byte(struct ds2404
*chip
)
87 gpiod_direction_input(chip
->dq_gpiod
);
89 for (i
= 0; i
< 8; i
++) {
90 gpiod_set_value(chip
->clk_gpiod
, 0);
92 if (gpiod_get_value(chip
->dq_gpiod
))
94 gpiod_set_value(chip
->clk_gpiod
, 1);
100 static void ds2404_read_memory(struct ds2404
*chip
, u16 offset
,
104 ds2404_write_byte(chip
, DS2404_READ_MEMORY_CMD
);
105 ds2404_write_byte(chip
, offset
& 0xff);
106 ds2404_write_byte(chip
, (offset
>> 8) & 0xff);
108 *out
++ = ds2404_read_byte(chip
);
111 static void ds2404_write_memory(struct ds2404
*chip
, u16 offset
,
118 ds2404_write_byte(chip
, DS2404_WRITE_SCRATCHPAD_CMD
);
119 ds2404_write_byte(chip
, offset
& 0xff);
120 ds2404_write_byte(chip
, (offset
>> 8) & 0xff);
122 for (i
= 0; i
< length
; i
++)
123 ds2404_write_byte(chip
, out
[i
]);
126 ds2404_write_byte(chip
, DS2404_READ_SCRATCHPAD_CMD
);
128 ta01
= ds2404_read_byte(chip
);
129 ta02
= ds2404_read_byte(chip
);
130 es
= ds2404_read_byte(chip
);
132 for (i
= 0; i
< length
; i
++) {
133 if (out
[i
] != ds2404_read_byte(chip
)) {
134 dev_err(chip
->dev
, "read invalid data\n");
140 ds2404_write_byte(chip
, DS2404_COPY_SCRATCHPAD_CMD
);
141 ds2404_write_byte(chip
, ta01
);
142 ds2404_write_byte(chip
, ta02
);
143 ds2404_write_byte(chip
, es
);
145 while (gpiod_get_value(chip
->dq_gpiod
))
149 static void ds2404_enable_osc(struct ds2404
*chip
)
151 u8 in
[1] = { 0x10 }; /* enable oscillator */
153 ds2404_write_memory(chip
, 0x201, 1, in
);
156 static int ds2404_read_time(struct device
*dev
, struct rtc_time
*dt
)
158 struct ds2404
*chip
= dev_get_drvdata(dev
);
159 unsigned long time
= 0;
162 ds2404_read_memory(chip
, 0x203, 4, (u8
*)&hw_time
);
163 time
= le32_to_cpu(hw_time
);
165 rtc_time64_to_tm(time
, dt
);
169 static int ds2404_set_time(struct device
*dev
, struct rtc_time
*dt
)
171 struct ds2404
*chip
= dev_get_drvdata(dev
);
172 u32 time
= cpu_to_le32(rtc_tm_to_time64(dt
));
173 ds2404_write_memory(chip
, 0x203, 4, (u8
*)&time
);
177 static const struct rtc_class_ops ds2404_rtc_ops
= {
178 .read_time
= ds2404_read_time
,
179 .set_time
= ds2404_set_time
,
182 static int rtc_probe(struct platform_device
*pdev
)
187 chip
= devm_kzalloc(&pdev
->dev
, sizeof(struct ds2404
), GFP_KERNEL
);
191 chip
->dev
= &pdev
->dev
;
193 chip
->rtc
= devm_rtc_allocate_device(&pdev
->dev
);
194 if (IS_ERR(chip
->rtc
))
195 return PTR_ERR(chip
->rtc
);
197 retval
= ds2404_gpio_map(chip
, pdev
);
201 platform_set_drvdata(pdev
, chip
);
203 chip
->rtc
->ops
= &ds2404_rtc_ops
;
204 chip
->rtc
->range_max
= U32_MAX
;
206 retval
= devm_rtc_register_device(chip
->rtc
);
210 ds2404_enable_osc(chip
);
214 static struct platform_driver rtc_device_driver
= {
220 module_platform_driver(rtc_device_driver
);
222 MODULE_DESCRIPTION("DS2404 RTC");
223 MODULE_AUTHOR("Sven Schnelle");
224 MODULE_LICENSE("GPL");
225 MODULE_ALIAS("platform:ds2404");