diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-02-04 08:03:40 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-02-04 08:03:40 +0100 |
commit | eadc4e40e68832fc61ae5e3ef2ef5cfcd9308b2c (patch) | |
tree | d6a3a2ec75d322fcbd1dc3cd2c828abab8213ca8 /drivers/rtc/rtc-at91rm9200.c | |
parent | Merge branch 'for-5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/denni... (diff) | |
parent | dt-bindings: rtc: at91rm9200: document clocks property (diff) | |
download | linux-eadc4e40e68832fc61ae5e3ef2ef5cfcd9308b2c.tar.xz linux-eadc4e40e68832fc61ae5e3ef2ef5cfcd9308b2c.zip |
Merge tag 'rtc-5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni:
"The VL_READ and VL_CLR ioctls have been reworked to be more useful.
This will not break userspace as there are very few users and they are
using the integer value as a boolean.
Apart from that, two drivers were reworked and a few fixes here and
there for a net reduction of number of lines.
Summary:
Subsystem:
- the VL_READ and VL_CLR ioctls are now documented and their behavior
is unified across all the drivers.
- RTC_I2C_AND_SPI Kconfig option rework to avoid selecting both
REGMAP_I2C and REGMAP_SPI unecessarily.
Drivers:
- at91rm9200: remove deprecated procfs, add sam9x60, sama5d4 and
sama5d2 compatibles.
- cmos: solve lost interrupts issue on MS Surface 3
- hym8563: return proper errno when time is invalid
- rv3029: many fixes, nvram support"
* tag 'rtc-5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (63 commits)
dt-bindings: rtc: at91rm9200: document clocks property
rtc: i2c/spi: Avoid inclusion of REGMAP support when not needed
rtc: Kconfig: select REGMAP_I2C when necessary
rtc: Kconfig: properly indent sd3078 entry
rtc: cmos: Refactor code by using the new dmi_get_bios_year() helper
rtc: cmos: Use predefined value for RTC IRQ on legacy x86
rtc: cmos: Stop using shared IRQ
rtc: tps6586x: Use IRQ_NOAUTOEN flag
rtc: at91rm9200: use FIELD_PREP/FIELD_GET
rtc: at91rm9200: avoid time readout in at91_rtc_setalarm
rtc: at91rm9200: move register definitions to C file
rtc: at91rm9200: add sama5d4 and sama5d2 compatibles
dt-bindings: rtc: at91rm9200: convert bindings to json-schema
rtc: at91rm9200: remove procfs information
dt-bindings: atmel, at91rm9200-rtc: add microchip, sam9x60-rtc
rtc: pcf8563: Use BIT
rtc: moxart: Convert to SPDX identifier
rtc: ds1343: Remove unused struct spi_device in struct ds1343_priv
rtc: rx8025: Remove struct i2c_client from struct rx8025_data
rtc: hym8563: Read the valid flag directly instead of caching it
...
Diffstat (limited to 'drivers/rtc/rtc-at91rm9200.c')
-rw-r--r-- | drivers/rtc/rtc-at91rm9200.c | 119 |
1 files changed, 74 insertions, 45 deletions
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index 3b833e02a657..5e811e04cb21 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -14,6 +14,7 @@ */ #include <linux/bcd.h> +#include <linux/bitfield.h> #include <linux/clk.h> #include <linux/completion.h> #include <linux/interrupt.h> @@ -30,7 +31,51 @@ #include <linux/time.h> #include <linux/uaccess.h> -#include "rtc-at91rm9200.h" +#define AT91_RTC_CR 0x00 /* Control Register */ +#define AT91_RTC_UPDTIM BIT(0) /* Update Request Time Register */ +#define AT91_RTC_UPDCAL BIT(1) /* Update Request Calendar Register */ + +#define AT91_RTC_MR 0x04 /* Mode Register */ + +#define AT91_RTC_TIMR 0x08 /* Time Register */ +#define AT91_RTC_SEC GENMASK(6, 0) /* Current Second */ +#define AT91_RTC_MIN GENMASK(14, 8) /* Current Minute */ +#define AT91_RTC_HOUR GENMASK(21, 16) /* Current Hour */ +#define AT91_RTC_AMPM BIT(22) /* Ante Meridiem Post Meridiem Indicator */ + +#define AT91_RTC_CALR 0x0c /* Calendar Register */ +#define AT91_RTC_CENT GENMASK(6, 0) /* Current Century */ +#define AT91_RTC_YEAR GENMASK(15, 8) /* Current Year */ +#define AT91_RTC_MONTH GENMASK(20, 16) /* Current Month */ +#define AT91_RTC_DAY GENMASK(23, 21) /* Current Day */ +#define AT91_RTC_DATE GENMASK(29, 24) /* Current Date */ + +#define AT91_RTC_TIMALR 0x10 /* Time Alarm Register */ +#define AT91_RTC_SECEN BIT(7) /* Second Alarm Enable */ +#define AT91_RTC_MINEN BIT(15) /* Minute Alarm Enable */ +#define AT91_RTC_HOUREN BIT(23) /* Hour Alarm Enable */ + +#define AT91_RTC_CALALR 0x14 /* Calendar Alarm Register */ +#define AT91_RTC_MTHEN BIT(23) /* Month Alarm Enable */ +#define AT91_RTC_DATEEN BIT(31) /* Date Alarm Enable */ + +#define AT91_RTC_SR 0x18 /* Status Register */ +#define AT91_RTC_ACKUPD BIT(0) /* Acknowledge for Update */ +#define AT91_RTC_ALARM BIT(1) /* Alarm Flag */ +#define AT91_RTC_SECEV BIT(2) /* Second Event */ +#define AT91_RTC_TIMEV BIT(3) /* Time Event */ +#define AT91_RTC_CALEV BIT(4) /* Calendar Event */ + +#define AT91_RTC_SCCR 0x1c /* Status Clear Command Register */ +#define AT91_RTC_IER 0x20 /* Interrupt Enable Register */ +#define AT91_RTC_IDR 0x24 /* Interrupt Disable Register */ +#define AT91_RTC_IMR 0x28 /* Interrupt Mask Register */ + +#define AT91_RTC_VER 0x2c /* Valid Entry Register */ +#define AT91_RTC_NVTIM BIT(0) /* Non valid Time */ +#define AT91_RTC_NVCAL BIT(1) /* Non valid Calendar */ +#define AT91_RTC_NVTIMALR BIT(2) /* Non valid Time Alarm */ +#define AT91_RTC_NVCALALR BIT(3) /* Non valid Calendar Alarm */ #define at91_rtc_read(field) \ readl_relaxed(at91_rtc_regs + field) @@ -117,20 +162,20 @@ static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg, } while ((time != at91_rtc_read(timereg)) || (date != at91_rtc_read(calreg))); - tm->tm_sec = bcd2bin((time & AT91_RTC_SEC) >> 0); - tm->tm_min = bcd2bin((time & AT91_RTC_MIN) >> 8); - tm->tm_hour = bcd2bin((time & AT91_RTC_HOUR) >> 16); + tm->tm_sec = bcd2bin(FIELD_GET(AT91_RTC_SEC, time)); + tm->tm_min = bcd2bin(FIELD_GET(AT91_RTC_MIN, time)); + tm->tm_hour = bcd2bin(FIELD_GET(AT91_RTC_HOUR, time)); /* * The Calendar Alarm register does not have a field for * the year - so these will return an invalid value. */ tm->tm_year = bcd2bin(date & AT91_RTC_CENT) * 100; /* century */ - tm->tm_year += bcd2bin((date & AT91_RTC_YEAR) >> 8); /* year */ + tm->tm_year += bcd2bin(FIELD_GET(AT91_RTC_YEAR, date)); /* year */ - tm->tm_wday = bcd2bin((date & AT91_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */ - tm->tm_mon = bcd2bin((date & AT91_RTC_MONTH) >> 16) - 1; - tm->tm_mday = bcd2bin((date & AT91_RTC_DATE) >> 24); + tm->tm_wday = bcd2bin(FIELD_GET(AT91_RTC_DAY, date)) - 1; /* day of the week [0-6], Sunday=0 */ + tm->tm_mon = bcd2bin(FIELD_GET(AT91_RTC_MONTH, date)) - 1; + tm->tm_mday = bcd2bin(FIELD_GET(AT91_RTC_DATE, date)); } /* @@ -167,16 +212,17 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) at91_rtc_write_idr(AT91_RTC_ACKUPD); at91_rtc_write(AT91_RTC_TIMR, - bin2bcd(tm->tm_sec) << 0 - | bin2bcd(tm->tm_min) << 8 - | bin2bcd(tm->tm_hour) << 16); + FIELD_PREP(AT91_RTC_SEC, bin2bcd(tm->tm_sec)) + | FIELD_PREP(AT91_RTC_MIN, bin2bcd(tm->tm_min)) + | FIELD_PREP(AT91_RTC_HOUR, bin2bcd(tm->tm_hour))); at91_rtc_write(AT91_RTC_CALR, - bin2bcd((tm->tm_year + 1900) / 100) /* century */ - | bin2bcd(tm->tm_year % 100) << 8 /* year */ - | bin2bcd(tm->tm_mon + 1) << 16 /* tm_mon starts at zero */ - | bin2bcd(tm->tm_wday + 1) << 21 /* day of the week [0-6], Sunday=0 */ - | bin2bcd(tm->tm_mday) << 24); + FIELD_PREP(AT91_RTC_CENT, + bin2bcd((tm->tm_year + 1900) / 100)) + | FIELD_PREP(AT91_RTC_YEAR, bin2bcd(tm->tm_year % 100)) + | FIELD_PREP(AT91_RTC_MONTH, bin2bcd(tm->tm_mon + 1)) + | FIELD_PREP(AT91_RTC_DAY, bin2bcd(tm->tm_wday + 1)) + | FIELD_PREP(AT91_RTC_DATE, bin2bcd(tm->tm_mday))); /* Restart Time/Calendar */ cr = at91_rtc_read(AT91_RTC_CR); @@ -211,25 +257,17 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) */ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct rtc_time tm; - - at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, &tm); - - tm.tm_mon = alrm->time.tm_mon; - tm.tm_mday = alrm->time.tm_mday; - tm.tm_hour = alrm->time.tm_hour; - tm.tm_min = alrm->time.tm_min; - tm.tm_sec = alrm->time.tm_sec; + struct rtc_time tm = alrm->time; at91_rtc_write_idr(AT91_RTC_ALARM); at91_rtc_write(AT91_RTC_TIMALR, - bin2bcd(tm.tm_sec) << 0 - | bin2bcd(tm.tm_min) << 8 - | bin2bcd(tm.tm_hour) << 16 + FIELD_PREP(AT91_RTC_SEC, bin2bcd(alrm->time.tm_sec)) + | FIELD_PREP(AT91_RTC_MIN, bin2bcd(alrm->time.tm_min)) + | FIELD_PREP(AT91_RTC_HOUR, bin2bcd(alrm->time.tm_hour)) | AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN); at91_rtc_write(AT91_RTC_CALALR, - bin2bcd(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */ - | bin2bcd(tm.tm_mday) << 24 + FIELD_PREP(AT91_RTC_MONTH, bin2bcd(alrm->time.tm_mon + 1)) + | FIELD_PREP(AT91_RTC_DATE, bin2bcd(alrm->time.tm_mday)) | AT91_RTC_DATEEN | AT91_RTC_MTHEN); if (alrm->enabled) { @@ -254,20 +292,6 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) return 0; } -/* - * Provide additional RTC information in /proc/driver/rtc - */ -static int at91_rtc_proc(struct device *dev, struct seq_file *seq) -{ - unsigned long imr = at91_rtc_read_imr(); - - seq_printf(seq, "update_IRQ\t: %s\n", - (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); - seq_printf(seq, "periodic_IRQ\t: %s\n", - (imr & AT91_RTC_SECEV) ? "yes" : "no"); - - return 0; -} /* * IRQ handler for the RTC @@ -327,6 +351,12 @@ static const struct of_device_id at91_rtc_dt_ids[] = { .compatible = "atmel,at91sam9x5-rtc", .data = &at91sam9x5_config, }, { + .compatible = "atmel,sama5d4-rtc", + .data = &at91rm9200_config, + }, { + .compatible = "atmel,sama5d2-rtc", + .data = &at91rm9200_config, + }, { /* sentinel */ } }; @@ -337,7 +367,6 @@ static const struct rtc_class_ops at91_rtc_ops = { .set_time = at91_rtc_settime, .read_alarm = at91_rtc_readalarm, .set_alarm = at91_rtc_setalarm, - .proc = at91_rtc_proc, .alarm_irq_enable = at91_rtc_alarm_irq_enable, }; |