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