diff options
author | Gregory CLEMENT <gregory.clement@free-electrons.com> | 2017-02-20 12:38:49 -0500 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2017-02-21 17:21:30 -0500 |
commit | 34f54f579a9988e96e85e22fc151c15955ae40f0 (patch) | |
tree | bc95b0472cebefc575f96ddd93a4a3b87d8cb3ee | |
parent | 75faea9179a775fbc3380e918ac90dc9991dc450 (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.txt | 8 | ||||
-rw-r--r-- | drivers/rtc/rtc-armada38x.c | 65 |
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 | ||
3 | RTC controller for the Armada 38x SoCs | 3 | RTC controller for the Armada 38x, 7K and 8K SoCs |
4 | 4 | ||
5 | Required properties: | 5 | Required 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 | ||
65 | struct armada38x_rtc_data { | 85 | struct 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 | ||
125 | static 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 | |||
142 | static u32 read_rtc_register(struct armada38x_rtc *rtc, u8 rtc_reg) | ||
143 | { | ||
144 | return readl(rtc->regs + rtc_reg); | ||
145 | } | ||
146 | |||
105 | static u32 read_rtc_register_38x_wa(struct armada38x_rtc *rtc, u8 rtc_reg) | 147 | static 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 | |||
203 | static void armada8k_clear_isr(struct armada38x_rtc *rtc) | ||
204 | { | ||
205 | writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_ISR); | ||
206 | } | ||
207 | |||
208 | static void armada8k_unmask_interrupt(struct armada38x_rtc *rtc) | ||
209 | { | ||
210 | writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_IMR); | ||
211 | } | ||
212 | |||
160 | static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm) | 213 | static 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 | ||
368 | static 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 |
316 | static const struct of_device_id armada38x_rtc_of_match_table[] = { | 377 | static 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 | }; |
323 | MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table); | 388 | MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table); |