blob: e5ae6ea4d5f3cf4aa55ed5c771c64f91e0f7db9e [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glassdbeda5b2015-04-20 12:37:23 -06002/*
3 * (C) Copyright 2015 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
Simon Glassdbeda5b2015-04-20 12:37:23 -06005 */
6
Patrick Delaunayb953ec22021-04-27 11:02:19 +02007#define LOG_CATEGORY UCLASS_RTC
8
Simon Glassdbeda5b2015-04-20 12:37:23 -06009#include <common.h>
10#include <dm.h>
11#include <errno.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060012#include <log.h>
Simon Glassdbeda5b2015-04-20 12:37:23 -060013#include <rtc.h>
14
15int 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
25int 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
35int 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
Rasmus Villemoesd8be0882020-07-06 22:01:10 +020045int 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
Rasmus Villemoes09381822020-07-06 22:01:11 +020064int 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
Simon Glassdbeda5b2015-04-20 12:37:23 -060083int rtc_read8(struct udevice *dev, unsigned int reg)
84{
85 struct rtc_ops *ops = rtc_get_ops(dev);
86
87 assert(ops);
Rasmus Villemoes5113f0b2020-07-06 22:01:12 +020088 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;
Simon Glassdbeda5b2015-04-20 12:37:23 -060099}
100
101int rtc_write8(struct udevice *dev, unsigned int reg, int val)
102{
103 struct rtc_ops *ops = rtc_get_ops(dev);
104
105 assert(ops);
Rasmus Villemoes5113f0b2020-07-06 22:01:12 +0200106 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;
Simon Glassdbeda5b2015-04-20 12:37:23 -0600114}
115
Bin Mengd24c7fb2017-03-16 07:26:27 -0700116int 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
133int 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
Simon Glassdbeda5b2015-04-20 12:37:23 -0600146int 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);
Simon Glass9a4eb592015-10-18 15:55:31 -0600154 if (ret < 0)
Simon Glassdbeda5b2015-04-20 12:37:23 -0600155 return ret;
156 value |= ret << (i << 3);
157 }
158
159 *valuep = value;
160 return 0;
161}
162
163int 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
176UCLASS_DRIVER(rtc) = {
177 .name = "rtc",
178 .id = UCLASS_RTC,
Michal Simek23a32872021-07-29 12:57:12 +0200179 .flags = DM_UC_FLAG_SEQ_ALIAS,
Simon Glass95397382021-08-07 07:24:04 -0600180#if CONFIG_IS_ENABLED(OF_REAL)
Simon Glass68c81fb2018-11-18 08:14:35 -0700181 .post_bind = dm_scan_fdt_dev,
Simon Glass67507e42020-10-03 11:31:34 -0600182#endif
Simon Glassdbeda5b2015-04-20 12:37:23 -0600183};