xref: /rk3399_rockchip-uboot/drivers/rtc/rk8xx_rtc.c (revision 0ed9e58e181bffa16069c98cd9bae417b042c835)
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 
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 
79 static int rtc_interrupt_init(struct udevice *dev)
80 {
81 	struct rk8xx_priv *rk8xx = dev_get_priv(dev->parent);
82 	struct rk8xx_rtc_priv *priv = dev_get_priv(dev);
83 	int irq;
84 
85 	if (!rk8xx->irq_chip) {
86 		printf("Failed to get parent irq chip\n");
87 		return -ENOENT;
88 	}
89 
90 	irq = virq_to_irq(rk8xx->irq_chip, RK8XX_IRQ_RTC_ALARM);
91 	if (irq < 0) {
92 		if (irq == -EBUSY) {
93 			priv->irq_is_busy = 1;
94 			return 0;
95 		}
96 		return irq;
97 	}
98 	irq_install_handler(irq, rtc_irq_handler, dev);
99 	irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING);
100 	irq_handler_enable(irq);
101 
102 	return 0;
103 }
104 
105 static int rk8xx_rtc_alarm_trigger(struct udevice *dev)
106 {
107 	struct rk8xx_rtc_priv *priv = dev_get_priv(dev);
108 	int val, ret, alarm_trigger = 0;
109 
110 	if (priv->irq_is_busy) {
111 		val = pmic_reg_read(dev->parent, priv->rtc_int_sts_reg);
112 		if (val < 0) {
113 			printf("%s: i2c read reg 0x%x failed, ret=%d\n",
114 			       __func__, priv->rtc_int_sts_reg, val);
115 			return val;
116 		}
117 		if (val & RTC_ALARM_STATUS) {
118 			alarm_trigger = 1;
119 			printf("rtc alarm interrupt\n");
120 		}
121 		ret = pmic_reg_write(dev->parent,
122 				     priv->rtc_int_sts_reg, 0xfe);
123 		if (ret < 0) {
124 			printf("%s: i2c write reg 0x%x failed, ret=%d\n",
125 			       __func__, priv->rtc_int_sts_reg, ret);
126 			return ret;
127 		}
128 		return alarm_trigger;
129 	} else {
130 		return priv->rtc_alarm_trigger;
131 	}
132 }
133 
134 static struct rtc_ops rk8xx_rtc_ops = {
135 	.alarm_trigger = rk8xx_rtc_alarm_trigger,
136 };
137 
138 static int rk8xx_rtc_probe(struct udevice *dev)
139 {
140 	struct rk8xx_priv *rk8xx = dev_get_priv(dev->parent);
141 	struct rk8xx_rtc_priv *priv = dev_get_priv(dev);
142 	int ret, val, mask_val;
143 
144 	priv->rtc_int_sts_reg = RK808_RTC_STATUS_REG;
145 	priv->rtc_int_msk_reg = RK808_RTC_INT_REG;
146 	switch (rk8xx->variant) {
147 	case RK808_ID:
148 	case RK818_ID:
149 		priv->int_msk_reg = RK808_INT_MSK_REG1;
150 		priv->int_sts_reg = RK808_INT_STS_REG1;
151 		mask_val = RK808_IRQ_RTC_PERIOD_MSK | RK808_IRQ_VOUT_LOW_MSK;
152 		break;
153 	case RK805_ID:
154 		priv->int_msk_reg = RK805_INT_MSK_REG;
155 		priv->int_sts_reg = RK805_INT_STS_REG;
156 		mask_val = RK805_IRQ_RTC_PERIOD_MSK;
157 		break;
158 	case RK816_ID:
159 		priv->int_msk_reg = RK816_INT_MSK_REG2;
160 		priv->int_sts_reg = RK816_INT_STS_REG2;
161 		mask_val = RK816_IRQ_RTC_PERIOD_MSK;
162 		break;
163 	case RK809_ID:
164 	case RK817_ID:
165 		priv->rtc_int_sts_reg = RK817_RTC_STATUS_REG;
166 		priv->rtc_int_msk_reg = RK817_RTC_INT_REG;
167 		priv->int_msk_reg = RK817_INT_MSK_REG0;
168 		priv->int_sts_reg = RK817_INT_STS_REG0;
169 		mask_val = RK817_IRQ_RTC_PERIOD_MSK;
170 		break;
171 	default:
172 		return -EINVAL;
173 	}
174 
175 	priv->rtc_alarm_trigger = 0;
176 	priv->irq_is_busy = 0;
177 	/* mask and clear interrupt */
178 	val = pmic_reg_read(dev->parent, priv->int_msk_reg);
179 	if (val < 0) {
180 		printf("%s: i2c read reg 0x%x failed, ret=%d\n",
181 		       __func__, priv->int_msk_reg, val);
182 		return val;
183 	}
184 	ret = pmic_reg_write(dev->parent,
185 			     priv->int_msk_reg, val | mask_val);
186 	if (ret < 0) {
187 		printf("%s: i2c write reg 0x%x failed, ret=%d\n",
188 		       __func__, priv->int_msk_reg, ret);
189 		return ret;
190 	}
191 	val = pmic_reg_read(dev->parent, priv->int_sts_reg);
192 	if (val < 0) {
193 		printf("%s: i2c read reg 0x%x failed, ret=%d\n",
194 		       __func__, priv->int_sts_reg, val);
195 		return val;
196 	}
197 	ret = pmic_reg_write(dev->parent,
198 			     priv->int_sts_reg,
199 			     val | (1 << RTC_ALARM_EN));
200 	if (ret < 0) {
201 		printf("%s: i2c write reg 0x%x failed, ret=%d\n",
202 		       __func__, priv->int_sts_reg, ret);
203 		return ret;
204 	}
205 	debug("%s: reg[0x%x] = 0x%x\n", __func__, priv->int_msk_reg,
206 	      pmic_reg_read(dev->parent, priv->int_msk_reg));
207 	debug("%s: reg[0x%x] = 0x%x\n", __func__, priv->int_sts_reg,
208 	      pmic_reg_read(dev->parent, priv->int_sts_reg));
209 
210 	return rtc_interrupt_init(dev);
211 }
212 
213 U_BOOT_DRIVER(rk8xx_rtc) = {
214 	.name   = "rk8xx_rtc",
215 	.id     = UCLASS_RTC,
216 	.probe  = rk8xx_rtc_probe,
217 	.ops	= &rk8xx_rtc_ops,
218 	.priv_auto_alloc_size = sizeof(struct rk8xx_rtc_priv),
219 };
220