^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) * Copyright (C) 2016 Oleksij Rempel <linux@rempel-privat.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/rtc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /* Miscellaneous registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /* Interrupt Location Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define HW_ILR 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define BM_RTCALF BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define BM_RTCCIF BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* Clock Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define HW_CCR 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* Calibration counter disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define BM_CCALOFF BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* Reset internal oscillator divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define BM_CTCRST BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* Clock Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define BM_CLKEN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* Counter Increment Interrupt Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define HW_CIIR 0x0C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define BM_CIIR_IMYEAR BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define BM_CIIR_IMMON BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define BM_CIIR_IMDOY BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define BM_CIIR_IMDOW BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define BM_CIIR_IMDOM BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define BM_CIIR_IMHOUR BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define BM_CIIR_IMMIN BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define BM_CIIR_IMSEC BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* Alarm Mask Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define HW_AMR 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define BM_AMR_IMYEAR BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define BM_AMR_IMMON BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define BM_AMR_IMDOY BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define BM_AMR_IMDOW BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define BM_AMR_IMDOM BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define BM_AMR_IMHOUR BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define BM_AMR_IMMIN BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define BM_AMR_IMSEC BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define BM_AMR_OFF 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /* Consolidated time registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define HW_CTIME0 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define BM_CTIME0_DOW_S 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define BM_CTIME0_DOW_M 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define BM_CTIME0_HOUR_S 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define BM_CTIME0_HOUR_M 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define BM_CTIME0_MIN_S 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define BM_CTIME0_MIN_M 0x3f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define BM_CTIME0_SEC_S 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define BM_CTIME0_SEC_M 0x3f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define HW_CTIME1 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define BM_CTIME1_YEAR_S 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define BM_CTIME1_YEAR_M 0xfff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define BM_CTIME1_MON_S 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define BM_CTIME1_MON_M 0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define BM_CTIME1_DOM_S 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define BM_CTIME1_DOM_M 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define HW_CTIME2 0x1C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define BM_CTIME2_DOY_S 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define BM_CTIME2_DOY_M 0xfff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* Time counter registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define HW_SEC 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define HW_MIN 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define HW_HOUR 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define HW_DOM 0x2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define HW_DOW 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define HW_DOY 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define HW_MONTH 0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define HW_YEAR 0x3C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define HW_CALIBRATION 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define BM_CALDIR_BACK BIT(17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define BM_CALVAL_M 0x1ffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* General purpose registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define HW_GPREG0 0x44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define HW_GPREG1 0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define HW_GPREG2 0x4C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define HW_GPREG3 0x50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define HW_GPREG4 0x54
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* Alarm register group */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define HW_ALSEC 0x60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define HW_ALMIN 0x64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define HW_ALHOUR 0x68
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define HW_ALDOM 0x6C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define HW_ALDOW 0x70
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define HW_ALDOY 0x74
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define HW_ALMON 0x78
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define HW_ALYEAR 0x7C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct asm9260_rtc_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) void __iomem *iobase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct rtc_device *rtc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static irqreturn_t asm9260_rtc_irq(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct asm9260_rtc_priv *priv = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) u32 isr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) unsigned long events = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) mutex_lock(&priv->rtc->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) isr = ioread32(priv->iobase + HW_CIIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (!isr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) mutex_unlock(&priv->rtc->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) iowrite32(0, priv->iobase + HW_CIIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) mutex_unlock(&priv->rtc->ops_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) events |= RTC_AF | RTC_IRQF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) rtc_update_irq(priv->rtc, 1, events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static int asm9260_rtc_read_time(struct device *dev, struct rtc_time *tm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) u32 ctime0, ctime1, ctime2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ctime0 = ioread32(priv->iobase + HW_CTIME0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ctime1 = ioread32(priv->iobase + HW_CTIME1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) ctime2 = ioread32(priv->iobase + HW_CTIME2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (ctime1 != ioread32(priv->iobase + HW_CTIME1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * woops, counter flipped right now. Now we are safe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * to reread.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ctime0 = ioread32(priv->iobase + HW_CTIME0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) ctime1 = ioread32(priv->iobase + HW_CTIME1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ctime2 = ioread32(priv->iobase + HW_CTIME2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) tm->tm_sec = (ctime0 >> BM_CTIME0_SEC_S) & BM_CTIME0_SEC_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) tm->tm_min = (ctime0 >> BM_CTIME0_MIN_S) & BM_CTIME0_MIN_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) tm->tm_hour = (ctime0 >> BM_CTIME0_HOUR_S) & BM_CTIME0_HOUR_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) tm->tm_wday = (ctime0 >> BM_CTIME0_DOW_S) & BM_CTIME0_DOW_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) tm->tm_mday = (ctime1 >> BM_CTIME1_DOM_S) & BM_CTIME1_DOM_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) tm->tm_mon = (ctime1 >> BM_CTIME1_MON_S) & BM_CTIME1_MON_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) tm->tm_year = (ctime1 >> BM_CTIME1_YEAR_S) & BM_CTIME1_YEAR_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) tm->tm_yday = (ctime2 >> BM_CTIME2_DOY_S) & BM_CTIME2_DOY_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static int asm9260_rtc_set_time(struct device *dev, struct rtc_time *tm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * make sure SEC counter will not flip other counter on write time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * real value will be written at the enf of sequence.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) iowrite32(0, priv->iobase + HW_SEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) iowrite32(tm->tm_year, priv->iobase + HW_YEAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) iowrite32(tm->tm_mon, priv->iobase + HW_MONTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) iowrite32(tm->tm_mday, priv->iobase + HW_DOM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) iowrite32(tm->tm_wday, priv->iobase + HW_DOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) iowrite32(tm->tm_yday, priv->iobase + HW_DOY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) iowrite32(tm->tm_hour, priv->iobase + HW_HOUR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) iowrite32(tm->tm_min, priv->iobase + HW_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) iowrite32(tm->tm_sec, priv->iobase + HW_SEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static int asm9260_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) alrm->time.tm_year = ioread32(priv->iobase + HW_ALYEAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) alrm->time.tm_mon = ioread32(priv->iobase + HW_ALMON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) alrm->time.tm_mday = ioread32(priv->iobase + HW_ALDOM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) alrm->time.tm_wday = ioread32(priv->iobase + HW_ALDOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) alrm->time.tm_yday = ioread32(priv->iobase + HW_ALDOY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) alrm->time.tm_hour = ioread32(priv->iobase + HW_ALHOUR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) alrm->time.tm_min = ioread32(priv->iobase + HW_ALMIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) alrm->time.tm_sec = ioread32(priv->iobase + HW_ALSEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) alrm->enabled = ioread32(priv->iobase + HW_AMR) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) alrm->pending = ioread32(priv->iobase + HW_CIIR) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return rtc_valid_tm(&alrm->time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static int asm9260_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) iowrite32(alrm->time.tm_year, priv->iobase + HW_ALYEAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) iowrite32(alrm->time.tm_mon, priv->iobase + HW_ALMON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) iowrite32(alrm->time.tm_mday, priv->iobase + HW_ALDOM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) iowrite32(alrm->time.tm_wday, priv->iobase + HW_ALDOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) iowrite32(alrm->time.tm_yday, priv->iobase + HW_ALDOY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) iowrite32(alrm->time.tm_hour, priv->iobase + HW_ALHOUR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) iowrite32(alrm->time.tm_min, priv->iobase + HW_ALMIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) iowrite32(alrm->time.tm_sec, priv->iobase + HW_ALSEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) iowrite32(alrm->enabled ? 0 : BM_AMR_OFF, priv->iobase + HW_AMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static int asm9260_alarm_irq_enable(struct device *dev, unsigned int enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) iowrite32(enabled ? 0 : BM_AMR_OFF, priv->iobase + HW_AMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static const struct rtc_class_ops asm9260_rtc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .read_time = asm9260_rtc_read_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) .set_time = asm9260_rtc_set_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) .read_alarm = asm9260_rtc_read_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .set_alarm = asm9260_rtc_set_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .alarm_irq_enable = asm9260_alarm_irq_enable,
^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 asm9260_rtc_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct asm9260_rtc_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) int irq_alarm, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) u32 ccr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) priv = devm_kzalloc(dev, sizeof(struct asm9260_rtc_priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) priv->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) platform_set_drvdata(pdev, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) irq_alarm = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (irq_alarm < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return irq_alarm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) priv->iobase = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (IS_ERR(priv->iobase))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return PTR_ERR(priv->iobase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) priv->clk = devm_clk_get(dev, "ahb");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (IS_ERR(priv->clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return PTR_ERR(priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ret = clk_prepare_enable(priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) dev_err(dev, "Failed to enable clk!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) ccr = ioread32(priv->iobase + HW_CCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /* if dev is not enabled, reset it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if ((ccr & (BM_CLKEN | BM_CTCRST)) != BM_CLKEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) iowrite32(BM_CTCRST, priv->iobase + HW_CCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) ccr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) iowrite32(BM_CLKEN | ccr, priv->iobase + HW_CCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) iowrite32(0, priv->iobase + HW_CIIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) iowrite32(BM_AMR_OFF, priv->iobase + HW_AMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) priv->rtc = devm_rtc_device_register(dev, dev_name(dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) &asm9260_rtc_ops, THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (IS_ERR(priv->rtc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ret = PTR_ERR(priv->rtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) dev_err(dev, "Failed to register RTC device: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) goto err_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) ret = devm_request_threaded_irq(dev, irq_alarm, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) asm9260_rtc_irq, IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) dev_name(dev), priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) dev_err(dev, "can't get irq %i, err %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) irq_alarm, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) goto err_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) err_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) clk_disable_unprepare(priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static int asm9260_rtc_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct asm9260_rtc_priv *priv = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /* Disable alarm matching */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) iowrite32(BM_AMR_OFF, priv->iobase + HW_AMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) clk_disable_unprepare(priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static const struct of_device_id asm9260_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) { .compatible = "alphascale,asm9260-rtc", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) MODULE_DEVICE_TABLE(of, asm9260_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static struct platform_driver asm9260_rtc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .probe = asm9260_rtc_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .remove = asm9260_rtc_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) .name = "asm9260-rtc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) .of_match_table = asm9260_dt_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) module_platform_driver(asm9260_rtc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) MODULE_AUTHOR("Oleksij Rempel <linux@rempel-privat.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) MODULE_DESCRIPTION("Alphascale asm9260 SoC Realtime Clock Driver (RTC)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) MODULE_LICENSE("GPL");