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