aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGregory CLEMENT <gregory.clement@free-electrons.com>2017-02-20 12:38:49 -0500
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2017-02-21 17:21:30 -0500
commit34f54f579a9988e96e85e22fc151c15955ae40f0 (patch)
treebc95b0472cebefc575f96ddd93a4a3b87d8cb3ee
parent75faea9179a775fbc3380e918ac90dc9991dc450 (diff)
rtc: armada38x: Add support for Armada 7K/8K
The Armada 7K/8K use the same RTC IP than the Armada 38x. However the SOC integration differs in 2 points: - MBUS bridge timing initialization - IRQ configuration at SoC level Moreover the Armada 7K/8K have an issue preventing to get the interrupt from alarm 1. This commit allows to use alarm 2 for these A7K/8K but to still use alarm 1 for the Armada 38x. Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
-rw-r--r--Documentation/devicetree/bindings/rtc/armada-380-rtc.txt8
-rw-r--r--drivers/rtc/rtc-armada38x.c65
2 files changed, 70 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/rtc/armada-380-rtc.txt b/Documentation/devicetree/bindings/rtc/armada-380-rtc.txt
index 2eb9d4ee7dc0..c3c9a1226f9a 100644
--- a/Documentation/devicetree/bindings/rtc/armada-380-rtc.txt
+++ b/Documentation/devicetree/bindings/rtc/armada-380-rtc.txt
@@ -1,9 +1,11 @@
1* Real Time Clock of the Armada 38x SoCs 1* Real Time Clock of the Armada 38x/7K/8K SoCs
2 2
3RTC controller for the Armada 38x SoCs 3RTC controller for the Armada 38x, 7K and 8K SoCs
4 4
5Required properties: 5Required properties:
6- compatible : Should be "marvell,armada-380-rtc" 6- compatible : Should be one of the following:
7 "marvell,armada-380-rtc" for Armada 38x SoC
8 "marvell,armada-8k-rtc" for Aramda 7K/8K SoCs
7- reg: a list of base address and size pairs, one for each entry in 9- reg: a list of base address and size pairs, one for each entry in
8 reg-names 10 reg-names
9- reg names: should contain: 11- reg names: should contain:
diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c
index b2a8e2ed71ca..21f355c37eab 100644
--- a/drivers/rtc/rtc-armada38x.c
+++ b/drivers/rtc/rtc-armada38x.c
@@ -24,18 +24,36 @@
24#define RTC_STATUS_ALARM1 BIT(0) 24#define RTC_STATUS_ALARM1 BIT(0)
25#define RTC_STATUS_ALARM2 BIT(1) 25#define RTC_STATUS_ALARM2 BIT(1)
26#define RTC_IRQ1_CONF 0x4 26#define RTC_IRQ1_CONF 0x4
27#define RTC_IRQ2_CONF 0x8
27#define RTC_IRQ_AL_EN BIT(0) 28#define RTC_IRQ_AL_EN BIT(0)
28#define RTC_IRQ_FREQ_EN BIT(1) 29#define RTC_IRQ_FREQ_EN BIT(1)
29#define RTC_IRQ_FREQ_1HZ BIT(2) 30#define RTC_IRQ_FREQ_1HZ BIT(2)
30 31
31#define RTC_TIME 0xC 32#define RTC_TIME 0xC
32#define RTC_ALARM1 0x10 33#define RTC_ALARM1 0x10
34#define RTC_ALARM2 0x14
35
36/* Armada38x SoC registers */
33#define RTC_38X_BRIDGE_TIMING_CTL 0x0 37#define RTC_38X_BRIDGE_TIMING_CTL 0x0
34#define RTC_38X_PERIOD_OFFS 0 38#define RTC_38X_PERIOD_OFFS 0
35#define RTC_38X_PERIOD_MASK (0x3FF << RTC_38X_PERIOD_OFFS) 39#define RTC_38X_PERIOD_MASK (0x3FF << RTC_38X_PERIOD_OFFS)
36#define RTC_38X_READ_DELAY_OFFS 26 40#define RTC_38X_READ_DELAY_OFFS 26
37#define RTC_38X_READ_DELAY_MASK (0x1F << RTC_38X_READ_DELAY_OFFS) 41#define RTC_38X_READ_DELAY_MASK (0x1F << RTC_38X_READ_DELAY_OFFS)
38 42
43/* Armada 7K/8K registers */
44#define RTC_8K_BRIDGE_TIMING_CTL0 0x0
45#define RTC_8K_WRCLK_PERIOD_OFFS 0
46#define RTC_8K_WRCLK_PERIOD_MASK (0xFFFF << RTC_8K_WRCLK_PERIOD_OFFS)
47#define RTC_8K_WRCLK_SETUP_OFFS 16
48#define RTC_8K_WRCLK_SETUP_MASK (0xFFFF << RTC_8K_WRCLK_SETUP_OFFS)
49#define RTC_8K_BRIDGE_TIMING_CTL1 0x4
50#define RTC_8K_READ_DELAY_OFFS 0
51#define RTC_8K_READ_DELAY_MASK (0xFFFF << RTC_8K_READ_DELAY_OFFS)
52
53#define RTC_8K_ISR 0x10
54#define RTC_8K_IMR 0x14
55#define RTC_8K_ALARM2 BIT(0)
56
39#define SOC_RTC_INTERRUPT 0x8 57#define SOC_RTC_INTERRUPT 0x8
40#define SOC_RTC_ALARM1 BIT(0) 58#define SOC_RTC_ALARM1 BIT(0)
41#define SOC_RTC_ALARM2 BIT(1) 59#define SOC_RTC_ALARM2 BIT(1)
@@ -60,6 +78,8 @@ struct armada38x_rtc {
60}; 78};
61 79
62#define ALARM1 0 80#define ALARM1 0
81#define ALARM2 1
82
63#define ALARM_REG(base, alarm) ((base) + (alarm) * sizeof(u32)) 83#define ALARM_REG(base, alarm) ((base) + (alarm) * sizeof(u32))
64 84
65struct armada38x_rtc_data { 85struct armada38x_rtc_data {
@@ -102,6 +122,28 @@ static void rtc_update_38x_mbus_timing_params(struct armada38x_rtc *rtc)
102 writel(reg, rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL); 122 writel(reg, rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL);
103} 123}
104 124
125static void rtc_update_8k_mbus_timing_params(struct armada38x_rtc *rtc)
126{
127 u32 reg;
128
129 reg = readl(rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL0);
130 reg &= ~RTC_8K_WRCLK_PERIOD_MASK;
131 reg |= 0x3FF << RTC_8K_WRCLK_PERIOD_OFFS;
132 reg &= ~RTC_8K_WRCLK_SETUP_MASK;
133 reg |= 0x29 << RTC_8K_WRCLK_SETUP_OFFS;
134 writel(reg, rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL0);
135
136 reg = readl(rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL1);
137 reg &= ~RTC_8K_READ_DELAY_MASK;
138 reg |= 0x3F << RTC_8K_READ_DELAY_OFFS;
139 writel(reg, rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL1);
140}
141
142static u32 read_rtc_register(struct armada38x_rtc *rtc, u8 rtc_reg)
143{
144 return readl(rtc->regs + rtc_reg);
145}
146
105static u32 read_rtc_register_38x_wa(struct armada38x_rtc *rtc, u8 rtc_reg) 147static u32 read_rtc_register_38x_wa(struct armada38x_rtc *rtc, u8 rtc_reg)
106{ 148{
107 int i, index_max = 0, max = 0; 149 int i, index_max = 0, max = 0;
@@ -157,6 +199,17 @@ static void armada38x_unmask_interrupt(struct armada38x_rtc *rtc)
157 199
158 writel(val | SOC_RTC_ALARM1_MASK, rtc->regs_soc + SOC_RTC_INTERRUPT); 200 writel(val | SOC_RTC_ALARM1_MASK, rtc->regs_soc + SOC_RTC_INTERRUPT);
159} 201}
202
203static void armada8k_clear_isr(struct armada38x_rtc *rtc)
204{
205 writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_ISR);
206}
207
208static void armada8k_unmask_interrupt(struct armada38x_rtc *rtc)
209{
210 writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_IMR);
211}
212
160static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm) 213static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
161{ 214{
162 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 215 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
@@ -312,12 +365,24 @@ static const struct armada38x_rtc_data armada38x_data = {
312 .alarm = ALARM1, 365 .alarm = ALARM1,
313}; 366};
314 367
368static const struct armada38x_rtc_data armada8k_data = {
369 .update_mbus_timing = rtc_update_8k_mbus_timing_params,
370 .read_rtc_reg = read_rtc_register,
371 .clear_isr = armada8k_clear_isr,
372 .unmask_interrupt = armada8k_unmask_interrupt,
373 .alarm = ALARM2,
374};
375
315#ifdef CONFIG_OF 376#ifdef CONFIG_OF
316static const struct of_device_id armada38x_rtc_of_match_table[] = { 377static const struct of_device_id armada38x_rtc_of_match_table[] = {
317 { 378 {
318 .compatible = "marvell,armada-380-rtc", 379 .compatible = "marvell,armada-380-rtc",
319 .data = &armada38x_data, 380 .data = &armada38x_data,
320 }, 381 },
382 {
383 .compatible = "marvell,armada-8k-rtc",
384 .data = &armada8k_data,
385 },
321 {} 386 {}
322}; 387};
323MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table); 388MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table);