^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * RTC driver for the Armada 38x Marvell SoCs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2015 Marvell
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Gregory Clement <gregory.clement@free-electrons.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/rtc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define RTC_STATUS 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define RTC_STATUS_ALARM1 BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define RTC_STATUS_ALARM2 BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define RTC_IRQ1_CONF 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define RTC_IRQ2_CONF 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define RTC_IRQ_AL_EN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define RTC_IRQ_FREQ_EN BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define RTC_IRQ_FREQ_1HZ BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define RTC_CCR 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define RTC_CCR_MODE BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define RTC_CONF_TEST 0x1C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define RTC_NOMINAL_TIMING BIT(13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define RTC_TIME 0xC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define RTC_ALARM1 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define RTC_ALARM2 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* Armada38x SoC registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define RTC_38X_BRIDGE_TIMING_CTL 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define RTC_38X_PERIOD_OFFS 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define RTC_38X_PERIOD_MASK (0x3FF << RTC_38X_PERIOD_OFFS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define RTC_38X_READ_DELAY_OFFS 26
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define RTC_38X_READ_DELAY_MASK (0x1F << RTC_38X_READ_DELAY_OFFS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* Armada 7K/8K registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define RTC_8K_BRIDGE_TIMING_CTL0 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define RTC_8K_WRCLK_PERIOD_OFFS 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define RTC_8K_WRCLK_PERIOD_MASK (0xFFFF << RTC_8K_WRCLK_PERIOD_OFFS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define RTC_8K_WRCLK_SETUP_OFFS 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define RTC_8K_WRCLK_SETUP_MASK (0xFFFF << RTC_8K_WRCLK_SETUP_OFFS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define RTC_8K_BRIDGE_TIMING_CTL1 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define RTC_8K_READ_DELAY_OFFS 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define RTC_8K_READ_DELAY_MASK (0xFFFF << RTC_8K_READ_DELAY_OFFS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define RTC_8K_ISR 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define RTC_8K_IMR 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define RTC_8K_ALARM2 BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define SOC_RTC_INTERRUPT 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define SOC_RTC_ALARM1 BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define SOC_RTC_ALARM2 BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define SOC_RTC_ALARM1_MASK BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define SOC_RTC_ALARM2_MASK BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define SAMPLE_NR 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct value_to_freq {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) u8 freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct armada38x_rtc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct rtc_device *rtc_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) void __iomem *regs_soc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) bool initialized;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct value_to_freq *val_to_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) const struct armada38x_rtc_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define ALARM1 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define ALARM2 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define ALARM_REG(base, alarm) ((base) + (alarm) * sizeof(u32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct armada38x_rtc_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* Initialize the RTC-MBUS bridge timing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) void (*update_mbus_timing)(struct armada38x_rtc *rtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) u32 (*read_rtc_reg)(struct armada38x_rtc *rtc, u8 rtc_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) void (*clear_isr)(struct armada38x_rtc *rtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) void (*unmask_interrupt)(struct armada38x_rtc *rtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) u32 alarm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * According to the datasheet, the OS should wait 5us after every
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * register write to the RTC hard macro so that the required update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * can occur without holding off the system bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * According to errata RES-3124064, Write to any RTC register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * may fail. As a workaround, before writing to RTC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * register, issue a dummy write of 0x0 twice to RTC Status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static void rtc_delayed_write(u32 val, struct armada38x_rtc *rtc, int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) writel(0, rtc->regs + RTC_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) writel(0, rtc->regs + RTC_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) writel(val, rtc->regs + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) udelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* Update RTC-MBUS bridge timing parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static void rtc_update_38x_mbus_timing_params(struct armada38x_rtc *rtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) reg = readl(rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) reg &= ~RTC_38X_PERIOD_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) reg |= 0x3FF << RTC_38X_PERIOD_OFFS; /* Maximum value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) reg &= ~RTC_38X_READ_DELAY_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) reg |= 0x1F << RTC_38X_READ_DELAY_OFFS; /* Maximum value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) writel(reg, rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static void rtc_update_8k_mbus_timing_params(struct armada38x_rtc *rtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) reg = readl(rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) reg &= ~RTC_8K_WRCLK_PERIOD_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) reg |= 0x3FF << RTC_8K_WRCLK_PERIOD_OFFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) reg &= ~RTC_8K_WRCLK_SETUP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) reg |= 0x29 << RTC_8K_WRCLK_SETUP_OFFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) writel(reg, rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) reg = readl(rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) reg &= ~RTC_8K_READ_DELAY_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) reg |= 0x3F << RTC_8K_READ_DELAY_OFFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) writel(reg, rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static u32 read_rtc_register(struct armada38x_rtc *rtc, u8 rtc_reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return readl(rtc->regs + rtc_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static u32 read_rtc_register_38x_wa(struct armada38x_rtc *rtc, u8 rtc_reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) int i, index_max = 0, max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) for (i = 0; i < SAMPLE_NR; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) rtc->val_to_freq[i].value = readl(rtc->regs + rtc_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) rtc->val_to_freq[i].freq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) for (i = 0; i < SAMPLE_NR; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) int j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) u32 value = rtc->val_to_freq[i].value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) while (rtc->val_to_freq[j].freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (rtc->val_to_freq[j].value == value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) rtc->val_to_freq[j].freq++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) j++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (!rtc->val_to_freq[j].freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) rtc->val_to_freq[j].value = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) rtc->val_to_freq[j].freq = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (rtc->val_to_freq[j].freq > max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) index_max = j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) max = rtc->val_to_freq[j].freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * If a value already has half of the sample this is the most
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * frequent one and we can stop the research right now
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (max > SAMPLE_NR / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return rtc->val_to_freq[index_max].value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static void armada38x_clear_isr(struct armada38x_rtc *rtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) u32 val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) writel(val & ~SOC_RTC_ALARM1, rtc->regs_soc + SOC_RTC_INTERRUPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static void armada38x_unmask_interrupt(struct armada38x_rtc *rtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) u32 val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) writel(val | SOC_RTC_ALARM1_MASK, rtc->regs_soc + SOC_RTC_INTERRUPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static void armada8k_clear_isr(struct armada38x_rtc *rtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_ISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static void armada8k_unmask_interrupt(struct armada38x_rtc *rtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_IMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct armada38x_rtc *rtc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) unsigned long time, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) spin_lock_irqsave(&rtc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) time = rtc->data->read_rtc_reg(rtc, RTC_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) spin_unlock_irqrestore(&rtc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) rtc_time64_to_tm(time, tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static void armada38x_rtc_reset(struct armada38x_rtc *rtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) reg = rtc->data->read_rtc_reg(rtc, RTC_CONF_TEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /* If bits [7:0] are non-zero, assume RTC was uninitialized */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (reg & 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) rtc_delayed_write(0, rtc, RTC_CONF_TEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) msleep(500); /* Oscillator startup time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) rtc_delayed_write(0, rtc, RTC_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) rtc_delayed_write(SOC_RTC_ALARM1 | SOC_RTC_ALARM2, rtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) RTC_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) rtc_delayed_write(RTC_NOMINAL_TIMING, rtc, RTC_CCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) rtc->initialized = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct armada38x_rtc *rtc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) unsigned long time, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) time = rtc_tm_to_time64(tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (!rtc->initialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) armada38x_rtc_reset(rtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) spin_lock_irqsave(&rtc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) rtc_delayed_write(time, rtc, RTC_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) spin_unlock_irqrestore(&rtc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct armada38x_rtc *rtc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) unsigned long time, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) u32 reg = ALARM_REG(RTC_ALARM1, rtc->data->alarm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) spin_lock_irqsave(&rtc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) time = rtc->data->read_rtc_reg(rtc, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) val = rtc->data->read_rtc_reg(rtc, reg_irq) & RTC_IRQ_AL_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) spin_unlock_irqrestore(&rtc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) alrm->enabled = val ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) rtc_time64_to_tm(time, &alrm->time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct armada38x_rtc *rtc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) u32 reg = ALARM_REG(RTC_ALARM1, rtc->data->alarm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) unsigned long time, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) time = rtc_tm_to_time64(&alrm->time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) spin_lock_irqsave(&rtc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) rtc_delayed_write(time, rtc, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (alrm->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) rtc_delayed_write(RTC_IRQ_AL_EN, rtc, reg_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) rtc->data->unmask_interrupt(rtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) spin_unlock_irqrestore(&rtc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static int armada38x_rtc_alarm_irq_enable(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) unsigned int enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct armada38x_rtc *rtc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) spin_lock_irqsave(&rtc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) rtc_delayed_write(RTC_IRQ_AL_EN, rtc, reg_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) rtc_delayed_write(0, rtc, reg_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) spin_unlock_irqrestore(&rtc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static irqreturn_t armada38x_rtc_alarm_irq(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct armada38x_rtc *rtc = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) int event = RTC_IRQF | RTC_AF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) dev_dbg(&rtc->rtc_dev->dev, "%s:irq(%d)\n", __func__, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) spin_lock(&rtc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) rtc->data->clear_isr(rtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) val = rtc->data->read_rtc_reg(rtc, reg_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* disable all the interrupts for alarm*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) rtc_delayed_write(0, rtc, reg_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /* Ack the event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) rtc_delayed_write(1 << rtc->data->alarm, rtc, RTC_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) spin_unlock(&rtc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (val & RTC_IRQ_FREQ_EN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (val & RTC_IRQ_FREQ_1HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) event |= RTC_UF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) event |= RTC_PF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) rtc_update_irq(rtc->rtc_dev, 1, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * The information given in the Armada 388 functional spec is complex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * They give two different formulas for calculating the offset value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * but when considering "Offset" as an 8-bit signed integer, they both
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * reduce down to (we shall rename "Offset" as "val" here):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * val = (f_ideal / f_measured - 1) / resolution where f_ideal = 32768
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * Converting to time, f = 1/t:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * val = (t_measured / t_ideal - 1) / resolution where t_ideal = 1/32768
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * => t_measured / t_ideal = val * resolution + 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * "offset" in the RTC interface is defined as:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * t = t0 * (1 + offset * 1e-9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * where t is the desired period, t0 is the measured period with a zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * offset, which is t_measured above. With t0 = t_measured and t = t_ideal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * offset = (t_ideal / t_measured - 1) / 1e-9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * => t_ideal / t_measured = offset * 1e-9 + 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * so:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * offset * 1e-9 + 1 = 1 / (val * resolution + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * We want "resolution" to be an integer, so resolution = R * 1e-9, giving
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * offset = 1e18 / (val * R + 1e9) - 1e9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * val = (1e18 / (offset + 1e9) - 1e9) / R
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * with a common transformation:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) * f(x) = 1e18 / (x + 1e9) - 1e9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * offset = f(val * R)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * val = f(offset) / R
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * Armada 38x supports two modes, fine mode (954ppb) and coarse mode (3815ppb).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static long armada38x_ppb_convert(long ppb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) long div = ppb + 1000000000L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return div_s64(1000000000000000000LL + div / 2, div) - 1000000000L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static int armada38x_rtc_read_offset(struct device *dev, long *offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct armada38x_rtc *rtc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) unsigned long ccr, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) long ppb_cor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) spin_lock_irqsave(&rtc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) ccr = rtc->data->read_rtc_reg(rtc, RTC_CCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) spin_unlock_irqrestore(&rtc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) ppb_cor = (ccr & RTC_CCR_MODE ? 3815 : 954) * (s8)ccr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /* ppb_cor + 1000000000L can never be zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) *offset = armada38x_ppb_convert(ppb_cor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static int armada38x_rtc_set_offset(struct device *dev, long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct armada38x_rtc *rtc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) unsigned long ccr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) long ppb_cor, off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * The maximum ppb_cor is -128 * 3815 .. 127 * 3815, but we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * need to clamp the input. This equates to -484270 .. 488558.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * Not only is this to stop out of range "off" but also to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * avoid the division by zero in armada38x_ppb_convert().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) offset = clamp(offset, -484270L, 488558L);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) ppb_cor = armada38x_ppb_convert(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * Use low update mode where possible, which gives a better
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * resolution of correction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) off = DIV_ROUND_CLOSEST(ppb_cor, 954);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (off > 127 || off < -128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) ccr = RTC_CCR_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) off = DIV_ROUND_CLOSEST(ppb_cor, 3815);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * Armada 388 requires a bit pattern in bits 14..8 depending on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * the sign bit: { 0, ~S, S, S, S, S, S }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) ccr |= (off & 0x3fff) ^ 0x2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) rtc_delayed_write(ccr, rtc, RTC_CCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static const struct rtc_class_ops armada38x_rtc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) .read_time = armada38x_rtc_read_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) .set_time = armada38x_rtc_set_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) .read_alarm = armada38x_rtc_read_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) .set_alarm = armada38x_rtc_set_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) .alarm_irq_enable = armada38x_rtc_alarm_irq_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) .read_offset = armada38x_rtc_read_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) .set_offset = armada38x_rtc_set_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) static const struct rtc_class_ops armada38x_rtc_ops_noirq = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) .read_time = armada38x_rtc_read_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) .set_time = armada38x_rtc_set_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) .read_alarm = armada38x_rtc_read_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) .read_offset = armada38x_rtc_read_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) .set_offset = armada38x_rtc_set_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) static const struct armada38x_rtc_data armada38x_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) .update_mbus_timing = rtc_update_38x_mbus_timing_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) .read_rtc_reg = read_rtc_register_38x_wa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) .clear_isr = armada38x_clear_isr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) .unmask_interrupt = armada38x_unmask_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) .alarm = ALARM1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static const struct armada38x_rtc_data armada8k_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) .update_mbus_timing = rtc_update_8k_mbus_timing_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) .read_rtc_reg = read_rtc_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) .clear_isr = armada8k_clear_isr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) .unmask_interrupt = armada8k_unmask_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) .alarm = ALARM2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static const struct of_device_id armada38x_rtc_of_match_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) .compatible = "marvell,armada-380-rtc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) .data = &armada38x_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) .compatible = "marvell,armada-8k-rtc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) .data = &armada8k_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) static __init int armada38x_rtc_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) struct armada38x_rtc *rtc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) rtc = devm_kzalloc(&pdev->dev, sizeof(struct armada38x_rtc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (!rtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) rtc->data = of_device_get_match_data(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) rtc->val_to_freq = devm_kcalloc(&pdev->dev, SAMPLE_NR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) sizeof(struct value_to_freq), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (!rtc->val_to_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) spin_lock_init(&rtc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) rtc->regs = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (IS_ERR(rtc->regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return PTR_ERR(rtc->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc-soc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) rtc->regs_soc = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (IS_ERR(rtc->regs_soc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return PTR_ERR(rtc->regs_soc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) rtc->irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (rtc->irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return rtc->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (IS_ERR(rtc->rtc_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return PTR_ERR(rtc->rtc_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (devm_request_irq(&pdev->dev, rtc->irq, armada38x_rtc_alarm_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 0, pdev->name, rtc) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) dev_warn(&pdev->dev, "Interrupt not available.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) rtc->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) platform_set_drvdata(pdev, rtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (rtc->irq != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) device_init_wakeup(&pdev->dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) rtc->rtc_dev->ops = &armada38x_rtc_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * If there is no interrupt available then we can't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) * use the alarm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) rtc->rtc_dev->ops = &armada38x_rtc_ops_noirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /* Update RTC-MBUS bridge timing parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) rtc->data->update_mbus_timing(rtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) rtc->rtc_dev->range_max = U32_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return rtc_register_device(rtc->rtc_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) static int armada38x_rtc_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (device_may_wakeup(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) struct armada38x_rtc *rtc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return enable_irq_wake(rtc->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) static int armada38x_rtc_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (device_may_wakeup(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct armada38x_rtc *rtc = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) /* Update RTC-MBUS bridge timing parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) rtc->data->update_mbus_timing(rtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return disable_irq_wake(rtc->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) static SIMPLE_DEV_PM_OPS(armada38x_rtc_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) armada38x_rtc_suspend, armada38x_rtc_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static struct platform_driver armada38x_rtc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) .name = "armada38x-rtc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) .pm = &armada38x_rtc_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) .of_match_table = of_match_ptr(armada38x_rtc_of_match_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) module_platform_driver_probe(armada38x_rtc_driver, armada38x_rtc_probe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) MODULE_DESCRIPTION("Marvell Armada 38x RTC driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) MODULE_LICENSE("GPL");