^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) * drivers/rtc/rtc-pl031.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Real Time Clock interface for ARM AMBA PrimeCell 031 RTC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: Deepak Saxena <dsaxena@plexity.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright 2006 (c) MontaVista Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright 2010 (c) ST-Ericsson AB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/rtc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/amba/bus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/bcd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/pm_wakeirq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Register definitions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define RTC_DR 0x00 /* Data read register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define RTC_MR 0x04 /* Match register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define RTC_LR 0x08 /* Data load register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define RTC_CR 0x0c /* Control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define RTC_IMSC 0x10 /* Interrupt mask and set register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define RTC_RIS 0x14 /* Raw interrupt status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define RTC_MIS 0x18 /* Masked interrupt status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define RTC_ICR 0x1c /* Interrupt clear register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /* ST variants have additional timer functionality */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define RTC_TDR 0x20 /* Timer data read register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define RTC_TLR 0x24 /* Timer data load register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define RTC_TCR 0x28 /* Timer control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define RTC_YDR 0x30 /* Year data read register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define RTC_YMR 0x34 /* Year match register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define RTC_YLR 0x38 /* Year data load register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define RTC_CR_EN (1 << 0) /* counter enable bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define RTC_CR_CWEN (1 << 26) /* Clockwatch enable bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define RTC_TCR_EN (1 << 1) /* Periodic timer enable bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* Common bit definitions for Interrupt status and control registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define RTC_BIT_AI (1 << 0) /* Alarm interrupt bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define RTC_BIT_PI (1 << 1) /* Periodic interrupt bit. ST variants only. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* Common bit definations for ST v2 for reading/writing time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define RTC_SEC_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define RTC_SEC_MASK (0x3F << RTC_SEC_SHIFT) /* Second [0-59] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define RTC_MIN_SHIFT 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define RTC_MIN_MASK (0x3F << RTC_MIN_SHIFT) /* Minute [0-59] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define RTC_HOUR_SHIFT 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define RTC_HOUR_MASK (0x1F << RTC_HOUR_SHIFT) /* Hour [0-23] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define RTC_WDAY_SHIFT 17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define RTC_WDAY_MASK (0x7 << RTC_WDAY_SHIFT) /* Day of Week [1-7] 1=Sunday */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define RTC_MDAY_SHIFT 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define RTC_MDAY_MASK (0x1F << RTC_MDAY_SHIFT) /* Day of Month [1-31] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define RTC_MON_SHIFT 25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define RTC_MON_MASK (0xF << RTC_MON_SHIFT) /* Month [1-12] 1=January */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define RTC_TIMER_FREQ 32768
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * struct pl031_vendor_data - per-vendor variations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * @ops: the vendor-specific operations used on this silicon version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * @clockwatch: if this is an ST Microelectronics silicon version with a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * clockwatch function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * @st_weekday: if this is an ST Microelectronics silicon version that need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * the weekday fix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * @irqflags: special IRQ flags per variant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct pl031_vendor_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct rtc_class_ops ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) bool clockwatch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) bool st_weekday;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned long irqflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) time64_t range_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) timeu64_t range_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct pl031_local {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct pl031_vendor_data *vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct rtc_device *rtc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static int pl031_alarm_irq_enable(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) unsigned int enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct pl031_local *ldata = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) unsigned long imsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* Clear any pending alarm interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) writel(RTC_BIT_AI, ldata->base + RTC_ICR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) imsc = readl(ldata->base + RTC_IMSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (enabled == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) writel(imsc | RTC_BIT_AI, ldata->base + RTC_IMSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) writel(imsc & ~RTC_BIT_AI, ldata->base + RTC_IMSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return 0;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * Convert Gregorian date to ST v2 RTC format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int pl031_stv2_tm_to_time(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct rtc_time *tm, unsigned long *st_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) unsigned long *bcd_year)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int year = tm->tm_year + 1900;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int wday = tm->tm_wday;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* wday masking is not working in hardware so wday must be valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (wday < -1 || wday > 6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) dev_err(dev, "invalid wday value %d\n", tm->tm_wday);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) } else if (wday == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* wday is not provided, calculate it here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct rtc_time calc_tm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) rtc_time64_to_tm(rtc_tm_to_time64(tm), &calc_tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) wday = calc_tm.tm_wday;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) *bcd_year = (bin2bcd(year % 100) | bin2bcd(year / 100) << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) *st_time = ((tm->tm_mon + 1) << RTC_MON_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) | (tm->tm_mday << RTC_MDAY_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) | ((wday + 1) << RTC_WDAY_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) | (tm->tm_hour << RTC_HOUR_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) | (tm->tm_min << RTC_MIN_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) | (tm->tm_sec << RTC_SEC_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^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) * Convert ST v2 RTC format to Gregorian date.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static int pl031_stv2_time_to_tm(unsigned long st_time, unsigned long bcd_year,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct rtc_time *tm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) tm->tm_year = bcd2bin(bcd_year) + (bcd2bin(bcd_year >> 8) * 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) tm->tm_mon = ((st_time & RTC_MON_MASK) >> RTC_MON_SHIFT) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) tm->tm_mday = ((st_time & RTC_MDAY_MASK) >> RTC_MDAY_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) tm->tm_wday = ((st_time & RTC_WDAY_MASK) >> RTC_WDAY_SHIFT) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) tm->tm_hour = ((st_time & RTC_HOUR_MASK) >> RTC_HOUR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) tm->tm_min = ((st_time & RTC_MIN_MASK) >> RTC_MIN_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) tm->tm_sec = ((st_time & RTC_SEC_MASK) >> RTC_SEC_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) tm->tm_year -= 1900;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static int pl031_stv2_read_time(struct device *dev, struct rtc_time *tm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct pl031_local *ldata = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) pl031_stv2_time_to_tm(readl(ldata->base + RTC_DR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) readl(ldata->base + RTC_YDR), tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static int pl031_stv2_set_time(struct device *dev, struct rtc_time *tm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) unsigned long time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) unsigned long bcd_year;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct pl031_local *ldata = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) ret = pl031_stv2_tm_to_time(dev, tm, &time, &bcd_year);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) writel(bcd_year, ldata->base + RTC_YLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) writel(time, ldata->base + RTC_LR);
^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) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static int pl031_stv2_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct pl031_local *ldata = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) ret = pl031_stv2_time_to_tm(readl(ldata->base + RTC_MR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) readl(ldata->base + RTC_YMR), &alarm->time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static int pl031_stv2_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct pl031_local *ldata = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) unsigned long time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) unsigned long bcd_year;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) ret = pl031_stv2_tm_to_time(dev, &alarm->time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) &time, &bcd_year);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) writel(bcd_year, ldata->base + RTC_YMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) writel(time, ldata->base + RTC_MR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) pl031_alarm_irq_enable(dev, alarm->enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static irqreturn_t pl031_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct pl031_local *ldata = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) unsigned long rtcmis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) unsigned long events = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) rtcmis = readl(ldata->base + RTC_MIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (rtcmis & RTC_BIT_AI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) writel(RTC_BIT_AI, ldata->base + RTC_ICR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) events |= (RTC_AF | RTC_IRQF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) rtc_update_irq(ldata->rtc, 1, events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static int pl031_read_time(struct device *dev, struct rtc_time *tm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct pl031_local *ldata = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) rtc_time64_to_tm(readl(ldata->base + RTC_DR), tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static int pl031_set_time(struct device *dev, struct rtc_time *tm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) struct pl031_local *ldata = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) writel(rtc_tm_to_time64(tm), ldata->base + RTC_LR);
^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 pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct pl031_local *ldata = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) rtc_time64_to_tm(readl(ldata->base + RTC_MR), &alarm->time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct pl031_local *ldata = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) writel(rtc_tm_to_time64(&alarm->time), ldata->base + RTC_MR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) pl031_alarm_irq_enable(dev, alarm->enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return 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) static void pl031_remove(struct amba_device *adev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct pl031_local *ldata = dev_get_drvdata(&adev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) dev_pm_clear_wake_irq(&adev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) device_init_wakeup(&adev->dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (adev->irq[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) free_irq(adev->irq[0], ldata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) amba_release_regions(adev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) struct pl031_local *ldata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct pl031_vendor_data *vendor = id->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct rtc_class_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) unsigned long time, data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) ret = amba_request_regions(adev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) goto err_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ldata = devm_kzalloc(&adev->dev, sizeof(struct pl031_local),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) ops = devm_kmemdup(&adev->dev, &vendor->ops, sizeof(vendor->ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (!ldata || !ops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) ldata->vendor = vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ldata->base = devm_ioremap(&adev->dev, adev->res.start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) resource_size(&adev->res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (!ldata->base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) amba_set_drvdata(adev, ldata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) dev_dbg(&adev->dev, "designer ID = 0x%02x\n", amba_manf(adev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) dev_dbg(&adev->dev, "revision = 0x%01x\n", amba_rev(adev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) data = readl(ldata->base + RTC_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* Enable the clockwatch on ST Variants */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (vendor->clockwatch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) data |= RTC_CR_CWEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) data |= RTC_CR_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) writel(data, ldata->base + RTC_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * On ST PL031 variants, the RTC reset value does not provide correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * weekday for 2000-01-01. Correct the erroneous sunday to saturday.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (vendor->st_weekday) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (readl(ldata->base + RTC_YDR) == 0x2000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) time = readl(ldata->base + RTC_DR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if ((time &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) (RTC_MON_MASK | RTC_MDAY_MASK | RTC_WDAY_MASK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) == 0x02120000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) time = time | (0x7 << RTC_WDAY_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) writel(0x2000, ldata->base + RTC_YLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) writel(time, ldata->base + RTC_LR);
^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) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (!adev->irq[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /* When there's no interrupt, no point in exposing the alarm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) ops->read_alarm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) ops->set_alarm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) ops->alarm_irq_enable = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) device_init_wakeup(&adev->dev, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) ldata->rtc = devm_rtc_allocate_device(&adev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (IS_ERR(ldata->rtc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) ret = PTR_ERR(ldata->rtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ldata->rtc->ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ldata->rtc->range_min = vendor->range_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) ldata->rtc->range_max = vendor->range_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) ret = rtc_register_device(ldata->rtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (adev->irq[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) ret = request_irq(adev->irq[0], pl031_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) vendor->irqflags, "rtc-pl031", ldata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) dev_pm_set_wake_irq(&adev->dev, adev->irq[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) amba_release_regions(adev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) err_req:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /* Operations for the original ARM version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static struct pl031_vendor_data arm_pl031 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) .ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) .read_time = pl031_read_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) .set_time = pl031_set_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) .read_alarm = pl031_read_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) .set_alarm = pl031_set_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) .alarm_irq_enable = pl031_alarm_irq_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) .range_max = U32_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /* The First ST derivative */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static struct pl031_vendor_data stv1_pl031 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) .ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) .read_time = pl031_read_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) .set_time = pl031_set_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) .read_alarm = pl031_read_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) .set_alarm = pl031_set_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) .alarm_irq_enable = pl031_alarm_irq_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) .clockwatch = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) .st_weekday = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) .range_max = U32_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /* And the second ST derivative */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) static struct pl031_vendor_data stv2_pl031 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) .ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) .read_time = pl031_stv2_read_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) .set_time = pl031_stv2_set_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) .read_alarm = pl031_stv2_read_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) .set_alarm = pl031_stv2_set_alarm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) .alarm_irq_enable = pl031_alarm_irq_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) .clockwatch = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) .st_weekday = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * This variant shares the IRQ with another block and must not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * suspend that IRQ line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * TODO check if it shares with IRQF_NO_SUSPEND user, else we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * remove IRQF_COND_SUSPEND
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) .irqflags = IRQF_SHARED | IRQF_COND_SUSPEND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) .range_min = RTC_TIMESTAMP_BEGIN_0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) .range_max = RTC_TIMESTAMP_END_9999,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static const struct amba_id pl031_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) .id = 0x00041031,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) .mask = 0x000fffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) .data = &arm_pl031,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /* ST Micro variants */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) .id = 0x00180031,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) .mask = 0x00ffffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) .data = &stv1_pl031,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) .id = 0x00280031,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) .mask = 0x00ffffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) .data = &stv2_pl031,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) {0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) MODULE_DEVICE_TABLE(amba, pl031_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) static struct amba_driver pl031_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) .drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) .name = "rtc-pl031",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) .id_table = pl031_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) .probe = pl031_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) .remove = pl031_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) module_amba_driver(pl031_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) MODULE_DESCRIPTION("ARM AMBA PL031 RTC Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) MODULE_LICENSE("GPL");