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