Commit 34f54f57 authored by Gregory CLEMENT's avatar Gregory CLEMENT Committed by Alexandre Belloni

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: default avatarGregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: default avatarAlexandre Belloni <alexandre.belloni@free-electrons.com>
parent 75faea91
* 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: 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: a list of base address and size pairs, one for each entry in
reg-names reg-names
- reg names: should contain: - reg names: should contain:
......
...@@ -24,18 +24,36 @@ ...@@ -24,18 +24,36 @@
#define RTC_STATUS_ALARM1 BIT(0) #define RTC_STATUS_ALARM1 BIT(0)
#define RTC_STATUS_ALARM2 BIT(1) #define RTC_STATUS_ALARM2 BIT(1)
#define RTC_IRQ1_CONF 0x4 #define RTC_IRQ1_CONF 0x4
#define RTC_IRQ2_CONF 0x8
#define RTC_IRQ_AL_EN BIT(0) #define RTC_IRQ_AL_EN BIT(0)
#define RTC_IRQ_FREQ_EN BIT(1) #define RTC_IRQ_FREQ_EN BIT(1)
#define RTC_IRQ_FREQ_1HZ BIT(2) #define RTC_IRQ_FREQ_1HZ BIT(2)
#define RTC_TIME 0xC #define RTC_TIME 0xC
#define RTC_ALARM1 0x10 #define RTC_ALARM1 0x10
#define RTC_ALARM2 0x14
/* Armada38x SoC registers */
#define RTC_38X_BRIDGE_TIMING_CTL 0x0 #define RTC_38X_BRIDGE_TIMING_CTL 0x0
#define RTC_38X_PERIOD_OFFS 0 #define RTC_38X_PERIOD_OFFS 0
#define RTC_38X_PERIOD_MASK (0x3FF << RTC_38X_PERIOD_OFFS) #define RTC_38X_PERIOD_MASK (0x3FF << RTC_38X_PERIOD_OFFS)
#define RTC_38X_READ_DELAY_OFFS 26 #define RTC_38X_READ_DELAY_OFFS 26
#define RTC_38X_READ_DELAY_MASK (0x1F << RTC_38X_READ_DELAY_OFFS) #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_INTERRUPT 0x8
#define SOC_RTC_ALARM1 BIT(0) #define SOC_RTC_ALARM1 BIT(0)
#define SOC_RTC_ALARM2 BIT(1) #define SOC_RTC_ALARM2 BIT(1)
...@@ -60,6 +78,8 @@ struct armada38x_rtc { ...@@ -60,6 +78,8 @@ struct armada38x_rtc {
}; };
#define ALARM1 0 #define ALARM1 0
#define ALARM2 1
#define ALARM_REG(base, alarm) ((base) + (alarm) * sizeof(u32)) #define ALARM_REG(base, alarm) ((base) + (alarm) * sizeof(u32))
struct armada38x_rtc_data { struct armada38x_rtc_data {
...@@ -102,6 +122,28 @@ static void rtc_update_38x_mbus_timing_params(struct armada38x_rtc *rtc) ...@@ -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); 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) static u32 read_rtc_register_38x_wa(struct armada38x_rtc *rtc, u8 rtc_reg)
{ {
int i, index_max = 0, max = 0; int i, index_max = 0, max = 0;
...@@ -157,6 +199,17 @@ static void armada38x_unmask_interrupt(struct armada38x_rtc *rtc) ...@@ -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); 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) static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
struct armada38x_rtc *rtc = dev_get_drvdata(dev); struct armada38x_rtc *rtc = dev_get_drvdata(dev);
...@@ -312,12 +365,24 @@ static const struct armada38x_rtc_data armada38x_data = { ...@@ -312,12 +365,24 @@ static const struct armada38x_rtc_data armada38x_data = {
.alarm = ALARM1, .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 #ifdef CONFIG_OF
static const struct of_device_id armada38x_rtc_of_match_table[] = { static const struct of_device_id armada38x_rtc_of_match_table[] = {
{ {
.compatible = "marvell,armada-380-rtc", .compatible = "marvell,armada-380-rtc",
.data = &armada38x_data, .data = &armada38x_data,
}, },
{
.compatible = "marvell,armada-8k-rtc",
.data = &armada8k_data,
},
{} {}
}; };
MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table); MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment