]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
rtc: armada38x: Add support for Armada 7K/8K
authorGregory CLEMENT <gregory.clement@free-electrons.com>
Mon, 20 Feb 2017 17:38:49 +0000 (18:38 +0100)
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>
Tue, 21 Feb 2017 22:21:30 +0000 (23:21 +0100)
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>
Documentation/devicetree/bindings/rtc/armada-380-rtc.txt
drivers/rtc/rtc-armada38x.c

index 2eb9d4ee7dc07d579cb25ac0dd135662cd682fe6..c3c9a1226f9aa622702d590f593618506509b3b6 100644 (file)
@@ -1,9 +1,11 @@
-* Real Time Clock of the Armada 38x SoCs
+* Real Time Clock of the Armada 38x/7K/8K SoCs
 
-RTC controller for the Armada 38x SoCs
+RTC controller for the Armada 38x, 7K and 8K SoCs
 
 Required properties:
-- compatible : Should be "marvell,armada-380-rtc"
+- compatible : Should be one of the following:
+       "marvell,armada-380-rtc" for Armada 38x SoC
+       "marvell,armada-8k-rtc" for Aramda 7K/8K SoCs
 - reg: a list of base address and size pairs, one for each entry in
   reg-names
 - reg names: should contain:
index b2a8e2ed71cabbf6b440a5da28d793f4027e1e71..21f355c37eab53cd4de0668e7250d1d578344e71 100644 (file)
 #define RTC_STATUS_ALARM1          BIT(0)
 #define RTC_STATUS_ALARM2          BIT(1)
 #define RTC_IRQ1_CONF      0x4
+#define RTC_IRQ2_CONF      0x8
 #define RTC_IRQ_AL_EN              BIT(0)
 #define RTC_IRQ_FREQ_EN                    BIT(1)
 #define RTC_IRQ_FREQ_1HZ           BIT(2)
 
 #define RTC_TIME           0xC
 #define RTC_ALARM1         0x10
+#define RTC_ALARM2         0x14
+
+/* Armada38x SoC registers  */
 #define RTC_38X_BRIDGE_TIMING_CTL   0x0
 #define RTC_38X_PERIOD_OFFS            0
 #define RTC_38X_PERIOD_MASK            (0x3FF << RTC_38X_PERIOD_OFFS)
 #define RTC_38X_READ_DELAY_OFFS                26
 #define RTC_38X_READ_DELAY_MASK                (0x1F << RTC_38X_READ_DELAY_OFFS)
 
+/* Armada 7K/8K registers  */
+#define RTC_8K_BRIDGE_TIMING_CTL0    0x0
+#define RTC_8K_WRCLK_PERIOD_OFFS       0
+#define RTC_8K_WRCLK_PERIOD_MASK       (0xFFFF << RTC_8K_WRCLK_PERIOD_OFFS)
+#define RTC_8K_WRCLK_SETUP_OFFS                16
+#define RTC_8K_WRCLK_SETUP_MASK                (0xFFFF << RTC_8K_WRCLK_SETUP_OFFS)
+#define RTC_8K_BRIDGE_TIMING_CTL1   0x4
+#define RTC_8K_READ_DELAY_OFFS         0
+#define RTC_8K_READ_DELAY_MASK         (0xFFFF << RTC_8K_READ_DELAY_OFFS)
+
+#define RTC_8K_ISR                 0x10
+#define RTC_8K_IMR                 0x14
+#define RTC_8K_ALARM2                  BIT(0)
+
 #define SOC_RTC_INTERRUPT          0x8
 #define SOC_RTC_ALARM1                 BIT(0)
 #define SOC_RTC_ALARM2                 BIT(1)
@@ -60,6 +78,8 @@ struct armada38x_rtc {
 };
 
 #define ALARM1 0
+#define ALARM2 1
+
 #define ALARM_REG(base, alarm)  ((base) + (alarm) * sizeof(u32))
 
 struct armada38x_rtc_data {
@@ -102,6 +122,28 @@ static void rtc_update_38x_mbus_timing_params(struct armada38x_rtc *rtc)
        writel(reg, rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL);
 }
 
+static void rtc_update_8k_mbus_timing_params(struct armada38x_rtc *rtc)
+{
+       u32 reg;
+
+       reg = readl(rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL0);
+       reg &= ~RTC_8K_WRCLK_PERIOD_MASK;
+       reg |= 0x3FF << RTC_8K_WRCLK_PERIOD_OFFS;
+       reg &= ~RTC_8K_WRCLK_SETUP_MASK;
+       reg |= 0x29 << RTC_8K_WRCLK_SETUP_OFFS;
+       writel(reg, rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL0);
+
+       reg = readl(rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL1);
+       reg &= ~RTC_8K_READ_DELAY_MASK;
+       reg |= 0x3F << RTC_8K_READ_DELAY_OFFS;
+       writel(reg, rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL1);
+}
+
+static u32 read_rtc_register(struct armada38x_rtc *rtc, u8 rtc_reg)
+{
+       return readl(rtc->regs + rtc_reg);
+}
+
 static u32 read_rtc_register_38x_wa(struct armada38x_rtc *rtc, u8 rtc_reg)
 {
        int i, index_max = 0, max = 0;
@@ -157,6 +199,17 @@ static void armada38x_unmask_interrupt(struct armada38x_rtc *rtc)
 
        writel(val | SOC_RTC_ALARM1_MASK, rtc->regs_soc + SOC_RTC_INTERRUPT);
 }
+
+static void armada8k_clear_isr(struct armada38x_rtc *rtc)
+{
+       writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_ISR);
+}
+
+static void armada8k_unmask_interrupt(struct armada38x_rtc *rtc)
+{
+       writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_IMR);
+}
+
 static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
        struct armada38x_rtc *rtc = dev_get_drvdata(dev);
@@ -312,12 +365,24 @@ static const struct armada38x_rtc_data armada38x_data = {
        .alarm = ALARM1,
 };
 
+static const struct armada38x_rtc_data armada8k_data = {
+       .update_mbus_timing = rtc_update_8k_mbus_timing_params,
+       .read_rtc_reg = read_rtc_register,
+       .clear_isr = armada8k_clear_isr,
+       .unmask_interrupt = armada8k_unmask_interrupt,
+       .alarm = ALARM2,
+};
+
 #ifdef CONFIG_OF
 static const struct of_device_id armada38x_rtc_of_match_table[] = {
        {
                .compatible = "marvell,armada-380-rtc",
                .data = &armada38x_data,
        },
+       {
+               .compatible = "marvell,armada-8k-rtc",
+               .data = &armada8k_data,
+       },
        {}
 };
 MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table);