1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2015 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
5 */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <log.h>
11 #include <rtc.h>
12
dm_rtc_get(struct udevice * dev,struct rtc_time * time)13 int dm_rtc_get(struct udevice *dev, struct rtc_time *time)
14 {
15 struct rtc_ops *ops = rtc_get_ops(dev);
16
17 assert(ops);
18 if (!ops->get)
19 return -ENOSYS;
20 return ops->get(dev, time);
21 }
22
dm_rtc_set(struct udevice * dev,struct rtc_time * time)23 int dm_rtc_set(struct udevice *dev, struct rtc_time *time)
24 {
25 struct rtc_ops *ops = rtc_get_ops(dev);
26
27 assert(ops);
28 if (!ops->set)
29 return -ENOSYS;
30 return ops->set(dev, time);
31 }
32
dm_rtc_reset(struct udevice * dev)33 int dm_rtc_reset(struct udevice *dev)
34 {
35 struct rtc_ops *ops = rtc_get_ops(dev);
36
37 assert(ops);
38 if (!ops->reset)
39 return -ENOSYS;
40 return ops->reset(dev);
41 }
42
dm_rtc_read(struct udevice * dev,unsigned int reg,u8 * buf,unsigned int len)43 int dm_rtc_read(struct udevice *dev, unsigned int reg, u8 *buf, unsigned int len)
44 {
45 struct rtc_ops *ops = rtc_get_ops(dev);
46
47 assert(ops);
48 if (ops->read)
49 return ops->read(dev, reg, buf, len);
50 if (!ops->read8)
51 return -ENOSYS;
52 while (len--) {
53 int ret = ops->read8(dev, reg++);
54
55 if (ret < 0)
56 return ret;
57 *buf++ = ret;
58 }
59 return 0;
60 }
61
dm_rtc_write(struct udevice * dev,unsigned int reg,const u8 * buf,unsigned int len)62 int dm_rtc_write(struct udevice *dev, unsigned int reg,
63 const u8 *buf, unsigned int len)
64 {
65 struct rtc_ops *ops = rtc_get_ops(dev);
66
67 assert(ops);
68 if (ops->write)
69 return ops->write(dev, reg, buf, len);
70 if (!ops->write8)
71 return -ENOSYS;
72 while (len--) {
73 int ret = ops->write8(dev, reg++, *buf++);
74
75 if (ret < 0)
76 return ret;
77 }
78 return 0;
79 }
80
rtc_read8(struct udevice * dev,unsigned int reg)81 int rtc_read8(struct udevice *dev, unsigned int reg)
82 {
83 struct rtc_ops *ops = rtc_get_ops(dev);
84
85 assert(ops);
86 if (ops->read8)
87 return ops->read8(dev, reg);
88 if (ops->read) {
89 u8 buf[1];
90 int ret = ops->read(dev, reg, buf, 1);
91
92 if (ret < 0)
93 return ret;
94 return buf[0];
95 }
96 return -ENOSYS;
97 }
98
rtc_write8(struct udevice * dev,unsigned int reg,int val)99 int rtc_write8(struct udevice *dev, unsigned int reg, int val)
100 {
101 struct rtc_ops *ops = rtc_get_ops(dev);
102
103 assert(ops);
104 if (ops->write8)
105 return ops->write8(dev, reg, val);
106 if (ops->write) {
107 u8 buf[1] = { val };
108
109 return ops->write(dev, reg, buf, 1);
110 }
111 return -ENOSYS;
112 }
113
rtc_read16(struct udevice * dev,unsigned int reg,u16 * valuep)114 int rtc_read16(struct udevice *dev, unsigned int reg, u16 *valuep)
115 {
116 u16 value = 0;
117 int ret;
118 int i;
119
120 for (i = 0; i < sizeof(value); i++) {
121 ret = rtc_read8(dev, reg + i);
122 if (ret < 0)
123 return ret;
124 value |= ret << (i << 3);
125 }
126
127 *valuep = value;
128 return 0;
129 }
130
rtc_write16(struct udevice * dev,unsigned int reg,u16 value)131 int rtc_write16(struct udevice *dev, unsigned int reg, u16 value)
132 {
133 int i, ret;
134
135 for (i = 0; i < sizeof(value); i++) {
136 ret = rtc_write8(dev, reg + i, (value >> (i << 3)) & 0xff);
137 if (ret)
138 return ret;
139 }
140
141 return 0;
142 }
143
rtc_read32(struct udevice * dev,unsigned int reg,u32 * valuep)144 int rtc_read32(struct udevice *dev, unsigned int reg, u32 *valuep)
145 {
146 u32 value = 0;
147 int ret;
148 int i;
149
150 for (i = 0; i < sizeof(value); i++) {
151 ret = rtc_read8(dev, reg + i);
152 if (ret < 0)
153 return ret;
154 value |= ret << (i << 3);
155 }
156
157 *valuep = value;
158 return 0;
159 }
160
rtc_write32(struct udevice * dev,unsigned int reg,u32 value)161 int rtc_write32(struct udevice *dev, unsigned int reg, u32 value)
162 {
163 int i, ret;
164
165 for (i = 0; i < sizeof(value); i++) {
166 ret = rtc_write8(dev, reg + i, (value >> (i << 3)) & 0xff);
167 if (ret)
168 return ret;
169 }
170
171 return 0;
172 }
173
174 UCLASS_DRIVER(rtc) = {
175 .name = "rtc",
176 .id = UCLASS_RTC,
177 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
178 .post_bind = dm_scan_fdt_dev,
179 #endif
180 };
181