1 /*
2 * (C) Copyright 2019 Rockchip Electronics Co., Ltd
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <power/pmic.h>
10 #include <power/rk8xx_pmic.h>
11 #include <irq-generic.h>
12 #include <asm/arch/periph.h>
13 #include <dm/pinctrl.h>
14 #include <rtc.h>
15
16 #define RK817_INT_STS_REG0 0xf8
17 #define RK817_INT_MSK_REG0 0xf9
18
19 #define RK816_INT_STS_REG2 0x4c
20 #define RK816_INT_MSK_REG2 0x4d
21
22 #define RK808_INT_STS_REG1 0x4c
23 #define RK808_INT_MSK_REG1 0x4d
24
25 #define RK805_INT_STS_REG 0x4c
26 #define RK805_INT_MSK_REG 0x4d
27
28 #define RK808_RTC_CTRL_REG 0x10
29 #define RK808_RTC_STATUS_REG 0x11
30 #define RK808_RTC_INT_REG 0x12
31
32 #define RK817_RTC_CTRL_REG 0x0d
33 #define RK817_RTC_STATUS_REG 0x0e
34 #define RK817_RTC_INT_REG 0x0f
35
36 #define RTC_ALARM_EN 5
37 #define RTC_ALARM_STATUS BIT(6)
38
39 struct rk8xx_rtc_priv {
40 u8 rtc_int_sts_reg;
41 u8 rtc_int_msk_reg;
42 u8 int_sts_reg;
43 u8 int_msk_reg;
44 int rtc_alarm_trigger;
45 int irq_is_busy;
46 };
47
rtc_irq_handler(int irq,void * data)48 static void rtc_irq_handler(int irq, void *data)
49 {
50 struct udevice *dev = data;
51 struct rk8xx_rtc_priv *priv = dev_get_priv(dev);
52 int ret, val;
53
54 debug("%s: irq = %d\n", __func__, irq);
55
56 if (priv->rtc_int_sts_reg) {
57 val = pmic_reg_read(dev->parent, priv->rtc_int_sts_reg);
58 if (val < 0) {
59 printf("%s: i2c read reg 0x%x failed, ret=%d\n",
60 __func__, priv->rtc_int_sts_reg, val);
61 return;
62 }
63
64 if (val & RTC_ALARM_STATUS) {
65 priv->rtc_alarm_trigger = 1;
66 printf("RTC: alarm interrupt\n");
67 }
68
69 ret = pmic_reg_write(dev->parent,
70 priv->rtc_int_sts_reg, 0xfe);
71 if (ret < 0) {
72 printf("%s: i2c write reg 0x%x failed, ret=%d\n",
73 __func__, priv->rtc_int_sts_reg, ret);
74 return;
75 }
76 }
77
78 ret = pmic_reg_write(dev->parent,
79 priv->int_sts_reg, 0xff);
80 if (ret < 0) {
81 printf("%s: i2c write reg 0x%x failed, ret=%d\n",
82 __func__, priv->int_sts_reg, ret);
83 return;
84 }
85 debug("%s: reg[0x%x] = 0x%x\n", __func__, priv->int_sts_reg,
86 pmic_reg_read(dev->parent, priv->int_sts_reg));
87 }
88
rtc_interrupt_init(struct udevice * dev)89 static int rtc_interrupt_init(struct udevice *dev)
90 {
91 struct rk8xx_rtc_priv *priv = dev_get_priv(dev);
92 u32 interrupt[2], phandle;
93 int irq, ret;
94
95 phandle = dev_read_u32_default(dev->parent, "interrupt-parent", -1);
96 if (phandle < 0) {
97 printf("failed get 'interrupt-parent', ret=%d\n", phandle);
98 return phandle;
99 }
100
101 ret = dev_read_u32_array(dev->parent, "interrupts", interrupt, 2);
102 if (ret) {
103 printf("failed get 'interrupt', ret=%d\n", ret);
104 return ret;
105 }
106
107 irq = phandle_gpio_to_irq(phandle, interrupt[0]);
108 if (irq < 0) {
109 if (irq == -EBUSY) {
110 priv->irq_is_busy = 1;
111 return 0;
112 }
113 return irq;
114 }
115 irq_install_handler(irq, rtc_irq_handler, dev);
116 irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING);
117 irq_handler_enable(irq);
118
119 return 0;
120 }
121
rk8xx_rtc_alarm_trigger(struct udevice * dev)122 static int rk8xx_rtc_alarm_trigger(struct udevice *dev)
123 {
124 struct rk8xx_rtc_priv *priv = dev_get_priv(dev);
125 int val, ret, alarm_trigger = 0;
126
127 if (priv->irq_is_busy) {
128 val = pmic_reg_read(dev->parent, priv->rtc_int_sts_reg);
129 if (val < 0) {
130 printf("%s: i2c read reg 0x%x failed, ret=%d\n",
131 __func__, priv->rtc_int_sts_reg, val);
132 return val;
133 }
134 if (val & RTC_ALARM_STATUS) {
135 alarm_trigger = 1;
136 printf("rtc alarm interrupt\n");
137 }
138 ret = pmic_reg_write(dev->parent,
139 priv->rtc_int_sts_reg, 0xfe);
140 if (ret < 0) {
141 printf("%s: i2c write reg 0x%x failed, ret=%d\n",
142 __func__, priv->rtc_int_sts_reg, ret);
143 return ret;
144 }
145 return alarm_trigger;
146 } else {
147 return priv->rtc_alarm_trigger;
148 }
149 }
150
151 static struct rtc_ops rk8xx_rtc_ops = {
152 .alarm_trigger = rk8xx_rtc_alarm_trigger,
153 };
154
rk8xx_rtc_probe(struct udevice * dev)155 static int rk8xx_rtc_probe(struct udevice *dev)
156 {
157 struct rk8xx_priv *rk8xx = dev_get_priv(dev->parent);
158 struct rk8xx_rtc_priv *priv = dev_get_priv(dev);
159 int ret, val;
160
161 priv->rtc_int_sts_reg = RK808_RTC_STATUS_REG;
162 priv->rtc_int_msk_reg = RK808_RTC_INT_REG;
163 switch (rk8xx->variant) {
164 case RK808_ID:
165 case RK818_ID:
166 priv->int_msk_reg = RK808_INT_MSK_REG1;
167 priv->int_sts_reg = RK808_INT_STS_REG1;
168 break;
169 case RK805_ID:
170 priv->int_msk_reg = RK805_INT_MSK_REG;
171 priv->int_sts_reg = RK805_INT_STS_REG;
172 break;
173 case RK816_ID:
174 priv->int_msk_reg = RK816_INT_MSK_REG2;
175 priv->int_sts_reg = RK816_INT_STS_REG2;
176 break;
177 case RK809_ID:
178 case RK817_ID:
179 priv->rtc_int_sts_reg = RK817_RTC_STATUS_REG;
180 priv->rtc_int_msk_reg = RK817_RTC_INT_REG;
181 priv->int_msk_reg = RK817_INT_MSK_REG0;
182 priv->int_sts_reg = RK817_INT_STS_REG0;
183 break;
184 default:
185 return -EINVAL;
186 }
187
188 priv->rtc_alarm_trigger = 0;
189 priv->irq_is_busy = 0;
190 /* mask and clear interrupt */
191 val = pmic_reg_read(dev->parent, priv->int_msk_reg);
192 if (val < 0) {
193 printf("%s: i2c read reg 0x%x failed, ret=%d\n",
194 __func__, priv->int_msk_reg, val);
195 return val;
196 }
197 ret = pmic_reg_write(dev->parent,
198 priv->int_msk_reg, val | 0xc1);
199 if (ret < 0) {
200 printf("%s: i2c write reg 0x%x failed, ret=%d\n",
201 __func__, priv->int_msk_reg, ret);
202 return ret;
203 }
204 val = pmic_reg_read(dev->parent, priv->int_sts_reg);
205 if (val < 0) {
206 printf("%s: i2c read reg 0x%x failed, ret=%d\n",
207 __func__, priv->int_sts_reg, val);
208 return val;
209 }
210 ret = pmic_reg_write(dev->parent,
211 priv->int_sts_reg,
212 val | (1 << RTC_ALARM_EN));
213 if (ret < 0) {
214 printf("%s: i2c write reg 0x%x failed, ret=%d\n",
215 __func__, priv->int_sts_reg, ret);
216 return ret;
217 }
218 debug("%s: reg[0x%x] = 0x%x\n", __func__, priv->int_msk_reg,
219 pmic_reg_read(dev->parent, priv->int_msk_reg));
220 debug("%s: reg[0x%x] = 0x%x\n", __func__, priv->int_sts_reg,
221 pmic_reg_read(dev->parent, priv->int_sts_reg));
222
223 return rtc_interrupt_init(dev);
224 }
225
226 U_BOOT_DRIVER(rk8xx_rtc) = {
227 .name = "rk8xx_rtc",
228 .id = UCLASS_RTC,
229 .probe = rk8xx_rtc_probe,
230 .ops = &rk8xx_rtc_ops,
231 .priv_auto_alloc_size = sizeof(struct rk8xx_rtc_priv),
232 };
233