|  | // SPDX-License-Identifier: GPL-2.0 | 
|  | /* | 
|  | * Texas Instruments K3 RTC driver | 
|  | * | 
|  | * Copyright (C) 2021-2022 Texas Instruments Incorporated - https://www.ti.com/ | 
|  | */ | 
|  |  | 
|  | #include <linux/clk.h> | 
|  | #include <linux/delay.h> | 
|  | #include <linux/mod_devicetable.h> | 
|  | #include <linux/module.h> | 
|  | #include <linux/of.h> | 
|  | #include <linux/platform_device.h> | 
|  | #include <linux/sys_soc.h> | 
|  | #include <linux/property.h> | 
|  | #include <linux/regmap.h> | 
|  | #include <linux/rtc.h> | 
|  |  | 
|  | /* Registers */ | 
|  | #define REG_K3RTC_S_CNT_LSW		0x08 | 
|  | #define REG_K3RTC_S_CNT_MSW		0x0c | 
|  | #define REG_K3RTC_COMP			0x10 | 
|  | #define REG_K3RTC_ON_OFF_S_CNT_LSW	0x20 | 
|  | #define REG_K3RTC_ON_OFF_S_CNT_MSW	0x24 | 
|  | #define REG_K3RTC_SCRATCH0		0x30 | 
|  | #define REG_K3RTC_SCRATCH7		0x4c | 
|  | #define REG_K3RTC_GENERAL_CTL		0x50 | 
|  | #define REG_K3RTC_IRQSTATUS_RAW_SYS	0x54 | 
|  | #define REG_K3RTC_IRQSTATUS_SYS		0x58 | 
|  | #define REG_K3RTC_IRQENABLE_SET_SYS	0x5c | 
|  | #define REG_K3RTC_IRQENABLE_CLR_SYS	0x60 | 
|  | #define REG_K3RTC_SYNCPEND		0x68 | 
|  | #define REG_K3RTC_KICK0			0x70 | 
|  | #define REG_K3RTC_KICK1			0x74 | 
|  |  | 
|  | /* Freeze when lsw is read and unfreeze when msw is read */ | 
|  | #define K3RTC_CNT_FMODE_S_CNT_VALUE	(0x2 << 24) | 
|  |  | 
|  | /* Magic values for lock/unlock */ | 
|  | #define K3RTC_KICK0_UNLOCK_VALUE	0x83e70b13 | 
|  | #define K3RTC_KICK1_UNLOCK_VALUE	0x95a4f1e0 | 
|  |  | 
|  | /* Multiplier for ppb conversions */ | 
|  | #define K3RTC_PPB_MULT			(1000000000LL) | 
|  | /* Min and max values supported with 'offset' interface (swapped sign) */ | 
|  | #define K3RTC_MIN_OFFSET		(-277761) | 
|  | #define K3RTC_MAX_OFFSET		(277778) | 
|  |  | 
|  | static const struct regmap_config ti_k3_rtc_regmap_config = { | 
|  | .name = "peripheral-registers", | 
|  | .reg_bits = 32, | 
|  | .val_bits = 32, | 
|  | .reg_stride = 4, | 
|  | .max_register = REG_K3RTC_KICK1, | 
|  | }; | 
|  |  | 
|  | enum ti_k3_rtc_fields { | 
|  | K3RTC_KICK0, | 
|  | K3RTC_KICK1, | 
|  | K3RTC_S_CNT_LSW, | 
|  | K3RTC_S_CNT_MSW, | 
|  | K3RTC_O32K_OSC_DEP_EN, | 
|  | K3RTC_UNLOCK, | 
|  | K3RTC_CNT_FMODE, | 
|  | K3RTC_PEND, | 
|  | K3RTC_RELOAD_FROM_BBD, | 
|  | K3RTC_COMP, | 
|  |  | 
|  | K3RTC_ALM_S_CNT_LSW, | 
|  | K3RTC_ALM_S_CNT_MSW, | 
|  | K3RTC_IRQ_STATUS_RAW, | 
|  | K3RTC_IRQ_STATUS, | 
|  | K3RTC_IRQ_ENABLE_SET, | 
|  | K3RTC_IRQ_ENABLE_CLR, | 
|  |  | 
|  | K3RTC_IRQ_STATUS_ALT, | 
|  | K3RTC_IRQ_ENABLE_CLR_ALT, | 
|  |  | 
|  | K3_RTC_MAX_FIELDS | 
|  | }; | 
|  |  | 
|  | static const struct reg_field ti_rtc_reg_fields[] = { | 
|  | [K3RTC_KICK0] = REG_FIELD(REG_K3RTC_KICK0, 0, 31), | 
|  | [K3RTC_KICK1] = REG_FIELD(REG_K3RTC_KICK1, 0, 31), | 
|  | [K3RTC_S_CNT_LSW] = REG_FIELD(REG_K3RTC_S_CNT_LSW, 0, 31), | 
|  | [K3RTC_S_CNT_MSW] = REG_FIELD(REG_K3RTC_S_CNT_MSW, 0, 15), | 
|  | [K3RTC_O32K_OSC_DEP_EN] = REG_FIELD(REG_K3RTC_GENERAL_CTL, 21, 21), | 
|  | [K3RTC_UNLOCK] = REG_FIELD(REG_K3RTC_GENERAL_CTL, 23, 23), | 
|  | [K3RTC_CNT_FMODE] = REG_FIELD(REG_K3RTC_GENERAL_CTL, 24, 25), | 
|  | [K3RTC_PEND] = REG_FIELD(REG_K3RTC_SYNCPEND, 0, 1), | 
|  | [K3RTC_RELOAD_FROM_BBD] = REG_FIELD(REG_K3RTC_SYNCPEND, 31, 31), | 
|  | [K3RTC_COMP] = REG_FIELD(REG_K3RTC_COMP, 0, 31), | 
|  |  | 
|  | /* We use on to off as alarm trigger */ | 
|  | [K3RTC_ALM_S_CNT_LSW] = REG_FIELD(REG_K3RTC_ON_OFF_S_CNT_LSW, 0, 31), | 
|  | [K3RTC_ALM_S_CNT_MSW] = REG_FIELD(REG_K3RTC_ON_OFF_S_CNT_MSW, 0, 15), | 
|  | [K3RTC_IRQ_STATUS_RAW] = REG_FIELD(REG_K3RTC_IRQSTATUS_RAW_SYS, 0, 0), | 
|  | [K3RTC_IRQ_STATUS] = REG_FIELD(REG_K3RTC_IRQSTATUS_SYS, 0, 0), | 
|  | [K3RTC_IRQ_ENABLE_SET] = REG_FIELD(REG_K3RTC_IRQENABLE_SET_SYS, 0, 0), | 
|  | [K3RTC_IRQ_ENABLE_CLR] = REG_FIELD(REG_K3RTC_IRQENABLE_CLR_SYS, 0, 0), | 
|  | /* Off to on is alternate */ | 
|  | [K3RTC_IRQ_STATUS_ALT] = REG_FIELD(REG_K3RTC_IRQSTATUS_SYS, 1, 1), | 
|  | [K3RTC_IRQ_ENABLE_CLR_ALT] = REG_FIELD(REG_K3RTC_IRQENABLE_CLR_SYS, 1, 1), | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct ti_k3_rtc - Private data for ti-k3-rtc | 
|  | * @irq:		IRQ | 
|  | * @sync_timeout_us:	data sync timeout period in uSec | 
|  | * @rate_32k:		32k clock rate in Hz | 
|  | * @rtc_dev:		rtc device | 
|  | * @regmap:		rtc mmio regmap | 
|  | * @r_fields:		rtc register fields | 
|  | */ | 
|  | struct ti_k3_rtc { | 
|  | unsigned int irq; | 
|  | u32 sync_timeout_us; | 
|  | unsigned long rate_32k; | 
|  | struct rtc_device *rtc_dev; | 
|  | struct regmap *regmap; | 
|  | struct regmap_field *r_fields[K3_RTC_MAX_FIELDS]; | 
|  | }; | 
|  |  | 
|  | static int k3rtc_field_read(struct ti_k3_rtc *priv, enum ti_k3_rtc_fields f) | 
|  | { | 
|  | int ret; | 
|  | int val; | 
|  |  | 
|  | ret = regmap_field_read(priv->r_fields[f], &val); | 
|  | /* | 
|  | * We shouldn't be seeing regmap fail on us for mmio reads | 
|  | * This is possible if clock context fails, but that isn't the case for us | 
|  | */ | 
|  | if (WARN_ON_ONCE(ret)) | 
|  | return ret; | 
|  | return val; | 
|  | } | 
|  |  | 
|  | static void k3rtc_field_write(struct ti_k3_rtc *priv, enum ti_k3_rtc_fields f, u32 val) | 
|  | { | 
|  | regmap_field_write(priv->r_fields[f], val); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * k3rtc_fence  - Ensure a register sync took place between the two domains | 
|  | * @priv:      pointer to priv data | 
|  | * | 
|  | * Return: 0 if the sync took place, else returns -ETIMEDOUT | 
|  | */ | 
|  | static int k3rtc_fence(struct ti_k3_rtc *priv) | 
|  | { | 
|  | int ret; | 
|  |  | 
|  | ret = regmap_field_read_poll_timeout(priv->r_fields[K3RTC_PEND], ret, | 
|  | !ret, 2, priv->sync_timeout_us); | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | static inline int k3rtc_check_unlocked(struct ti_k3_rtc *priv) | 
|  | { | 
|  | int ret; | 
|  |  | 
|  | ret = k3rtc_field_read(priv, K3RTC_UNLOCK); | 
|  | if (ret < 0) | 
|  | return ret; | 
|  |  | 
|  | return (ret) ? 0 : 1; | 
|  | } | 
|  |  | 
|  | static int k3rtc_unlock_rtc(struct ti_k3_rtc *priv) | 
|  | { | 
|  | int ret; | 
|  |  | 
|  | ret = k3rtc_check_unlocked(priv); | 
|  | if (!ret) | 
|  | return ret; | 
|  |  | 
|  | k3rtc_field_write(priv, K3RTC_KICK0, K3RTC_KICK0_UNLOCK_VALUE); | 
|  | k3rtc_field_write(priv, K3RTC_KICK1, K3RTC_KICK1_UNLOCK_VALUE); | 
|  |  | 
|  | /* Skip fence since we are going to check the unlock bit as fence */ | 
|  | ret = regmap_field_read_poll_timeout(priv->r_fields[K3RTC_UNLOCK], ret, | 
|  | ret, 2, priv->sync_timeout_us); | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * This is the list of SoCs affected by TI's i2327 errata causing the RTC | 
|  | * state-machine to break if not unlocked fast enough during boot. These | 
|  | * SoCs must have the bootloader unlock this device very early in the | 
|  | * boot-flow before we (Linux) can use this device. | 
|  | */ | 
|  | static const struct soc_device_attribute has_erratum_i2327[] = { | 
|  | { .family = "AM62X", .revision = "SR1.0" }, | 
|  | { /* sentinel */ } | 
|  | }; | 
|  |  | 
|  | static int k3rtc_configure(struct device *dev) | 
|  | { | 
|  | int ret; | 
|  | struct ti_k3_rtc *priv = dev_get_drvdata(dev); | 
|  |  | 
|  | /* | 
|  | * HWBUG: The compare state machine is broken if the RTC module | 
|  | * is NOT unlocked in under one second of boot - which is pretty long | 
|  | * time from the perspective of Linux driver (module load, u-boot | 
|  | * shell all can take much longer than this. | 
|  | * | 
|  | * In such occurrence, it is assumed that the RTC module is unusable | 
|  | */ | 
|  | if (soc_device_match(has_erratum_i2327)) { | 
|  | ret = k3rtc_check_unlocked(priv); | 
|  | /* If there is an error OR if we are locked, return error */ | 
|  | if (ret) { | 
|  | dev_err(dev, | 
|  | HW_ERR "Erratum i2327 unlock QUIRK! Cannot operate!!\n"); | 
|  | return -EFAULT; | 
|  | } | 
|  | } else { | 
|  | /* May need to explicitly unlock first time */ | 
|  | ret = k3rtc_unlock_rtc(priv); | 
|  | if (ret) { | 
|  | dev_err(dev, "Failed to unlock(%d)!\n", ret); | 
|  | return ret; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Enable Shadow register sync on 32k clock boundary */ | 
|  | k3rtc_field_write(priv, K3RTC_O32K_OSC_DEP_EN, 0x1); | 
|  |  | 
|  | /* | 
|  | * Wait at least clock sync time before proceeding further programming. | 
|  | * This ensures that the 32k based sync is active. | 
|  | */ | 
|  | usleep_range(priv->sync_timeout_us, priv->sync_timeout_us + 5); | 
|  |  | 
|  | /* We need to ensure fence here to make sure sync here */ | 
|  | ret = k3rtc_fence(priv); | 
|  | if (ret) { | 
|  | dev_err(dev, | 
|  | "Failed fence osc_dep enable(%d) - is 32k clk working?!\n", ret); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * FMODE setting: Reading lower seconds will freeze value on higher | 
|  | * seconds. This also implies that we must *ALWAYS* read lower seconds | 
|  | * prior to reading higher seconds | 
|  | */ | 
|  | k3rtc_field_write(priv, K3RTC_CNT_FMODE, K3RTC_CNT_FMODE_S_CNT_VALUE); | 
|  |  | 
|  | /* Clear any spurious IRQ sources if any */ | 
|  | k3rtc_field_write(priv, K3RTC_IRQ_STATUS_ALT, 0x1); | 
|  | k3rtc_field_write(priv, K3RTC_IRQ_STATUS, 0x1); | 
|  | /* Disable all IRQs */ | 
|  | k3rtc_field_write(priv, K3RTC_IRQ_ENABLE_CLR_ALT, 0x1); | 
|  | k3rtc_field_write(priv, K3RTC_IRQ_ENABLE_CLR, 0x1); | 
|  |  | 
|  | /* And.. Let us Sync the writes in */ | 
|  | return k3rtc_fence(priv); | 
|  | } | 
|  |  | 
|  | static int ti_k3_rtc_read_time(struct device *dev, struct rtc_time *tm) | 
|  | { | 
|  | struct ti_k3_rtc *priv = dev_get_drvdata(dev); | 
|  | u32 seconds_lo, seconds_hi; | 
|  |  | 
|  | seconds_lo = k3rtc_field_read(priv, K3RTC_S_CNT_LSW); | 
|  | seconds_hi = k3rtc_field_read(priv, K3RTC_S_CNT_MSW); | 
|  |  | 
|  | rtc_time64_to_tm((((time64_t)seconds_hi) << 32) | (time64_t)seconds_lo, tm); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int ti_k3_rtc_set_time(struct device *dev, struct rtc_time *tm) | 
|  | { | 
|  | struct ti_k3_rtc *priv = dev_get_drvdata(dev); | 
|  | time64_t seconds; | 
|  |  | 
|  | seconds = rtc_tm_to_time64(tm); | 
|  |  | 
|  | /* | 
|  | * Read operation on LSW will freeze the RTC, so to update | 
|  | * the time, we cannot use field operations. Just write since the | 
|  | * reserved bits are ignored. | 
|  | */ | 
|  | regmap_write(priv->regmap, REG_K3RTC_S_CNT_LSW, seconds); | 
|  | regmap_write(priv->regmap, REG_K3RTC_S_CNT_MSW, seconds >> 32); | 
|  |  | 
|  | return k3rtc_fence(priv); | 
|  | } | 
|  |  | 
|  | static int ti_k3_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | 
|  | { | 
|  | struct ti_k3_rtc *priv = dev_get_drvdata(dev); | 
|  | u32 reg; | 
|  | u32 offset = enabled ? K3RTC_IRQ_ENABLE_SET : K3RTC_IRQ_ENABLE_CLR; | 
|  |  | 
|  | reg = k3rtc_field_read(priv, K3RTC_IRQ_ENABLE_SET); | 
|  | if ((enabled && reg) || (!enabled && !reg)) | 
|  | return 0; | 
|  |  | 
|  | k3rtc_field_write(priv, offset, 0x1); | 
|  |  | 
|  | /* | 
|  | * Ensure the write sync is through - NOTE: it should be OK to have | 
|  | * ISR to fire as we are checking sync (which should be done in a 32k | 
|  | * cycle or so). | 
|  | */ | 
|  | return k3rtc_fence(priv); | 
|  | } | 
|  |  | 
|  | static int ti_k3_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 
|  | { | 
|  | struct ti_k3_rtc *priv = dev_get_drvdata(dev); | 
|  | u32 seconds_lo, seconds_hi; | 
|  |  | 
|  | seconds_lo = k3rtc_field_read(priv, K3RTC_ALM_S_CNT_LSW); | 
|  | seconds_hi = k3rtc_field_read(priv, K3RTC_ALM_S_CNT_MSW); | 
|  |  | 
|  | rtc_time64_to_tm((((time64_t)seconds_hi) << 32) | (time64_t)seconds_lo, &alarm->time); | 
|  |  | 
|  | alarm->enabled = k3rtc_field_read(priv, K3RTC_IRQ_ENABLE_SET); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int ti_k3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 
|  | { | 
|  | struct ti_k3_rtc *priv = dev_get_drvdata(dev); | 
|  | time64_t seconds; | 
|  | int ret; | 
|  |  | 
|  | seconds = rtc_tm_to_time64(&alarm->time); | 
|  |  | 
|  | k3rtc_field_write(priv, K3RTC_ALM_S_CNT_LSW, seconds); | 
|  | k3rtc_field_write(priv, K3RTC_ALM_S_CNT_MSW, (seconds >> 32)); | 
|  |  | 
|  | /* Make sure the alarm time is synced in */ | 
|  | ret = k3rtc_fence(priv); | 
|  | if (ret) { | 
|  | dev_err(dev, "Failed to fence(%d)! Potential config issue?\n", ret); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /* Alarm IRQ enable will do a sync */ | 
|  | return ti_k3_rtc_alarm_irq_enable(dev, alarm->enabled); | 
|  | } | 
|  |  | 
|  | static int ti_k3_rtc_read_offset(struct device *dev, long *offset) | 
|  | { | 
|  | struct ti_k3_rtc *priv = dev_get_drvdata(dev); | 
|  | u32 ticks_per_hr = priv->rate_32k * 3600; | 
|  | int comp; | 
|  | s64 tmp; | 
|  |  | 
|  | comp = k3rtc_field_read(priv, K3RTC_COMP); | 
|  |  | 
|  | /* Convert from RTC calibration register format to ppb format */ | 
|  | tmp = comp * (s64)K3RTC_PPB_MULT; | 
|  | if (tmp < 0) | 
|  | tmp -= ticks_per_hr / 2LL; | 
|  | else | 
|  | tmp += ticks_per_hr / 2LL; | 
|  | tmp = div_s64(tmp, ticks_per_hr); | 
|  |  | 
|  | /* Offset value operates in negative way, so swap sign */ | 
|  | *offset = (long)-tmp; | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int ti_k3_rtc_set_offset(struct device *dev, long offset) | 
|  | { | 
|  | struct ti_k3_rtc *priv = dev_get_drvdata(dev); | 
|  | u32 ticks_per_hr = priv->rate_32k * 3600; | 
|  | int comp; | 
|  | s64 tmp; | 
|  |  | 
|  | /* Make sure offset value is within supported range */ | 
|  | if (offset < K3RTC_MIN_OFFSET || offset > K3RTC_MAX_OFFSET) | 
|  | return -ERANGE; | 
|  |  | 
|  | /* Convert from ppb format to RTC calibration register format */ | 
|  | tmp = offset * (s64)ticks_per_hr; | 
|  | if (tmp < 0) | 
|  | tmp -= K3RTC_PPB_MULT / 2LL; | 
|  | else | 
|  | tmp += K3RTC_PPB_MULT / 2LL; | 
|  | tmp = div_s64(tmp, K3RTC_PPB_MULT); | 
|  |  | 
|  | /* Offset value operates in negative way, so swap sign */ | 
|  | comp = (int)-tmp; | 
|  |  | 
|  | k3rtc_field_write(priv, K3RTC_COMP, comp); | 
|  |  | 
|  | return k3rtc_fence(priv); | 
|  | } | 
|  |  | 
|  | static irqreturn_t ti_k3_rtc_interrupt(s32 irq, void *dev_id) | 
|  | { | 
|  | struct device *dev = dev_id; | 
|  | struct ti_k3_rtc *priv = dev_get_drvdata(dev); | 
|  | u32 reg; | 
|  | int ret; | 
|  |  | 
|  | /* | 
|  | * IRQ assertion can be very fast, however, the IRQ Status clear | 
|  | * de-assert depends on 32k clock edge in the 32k domain | 
|  | * If we clear the status prior to the first 32k clock edge, | 
|  | * the status bit is cleared, but the IRQ stays re-asserted. | 
|  | * | 
|  | * To prevent this condition, we need to wait for clock sync time. | 
|  | * We can either do that by polling the 32k observability signal for | 
|  | * a toggle OR we could just sleep and let the processor do other | 
|  | * stuff. | 
|  | */ | 
|  | usleep_range(priv->sync_timeout_us, priv->sync_timeout_us + 2); | 
|  |  | 
|  | /* Lets make sure that this is a valid interrupt */ | 
|  | reg = k3rtc_field_read(priv, K3RTC_IRQ_STATUS); | 
|  |  | 
|  | if (!reg) { | 
|  | u32 raw = k3rtc_field_read(priv, K3RTC_IRQ_STATUS_RAW); | 
|  |  | 
|  | dev_err(dev, | 
|  | HW_ERR | 
|  | "Erratum i2327/IRQ trig: status: 0x%08x / 0x%08x\n", reg, raw); | 
|  | return IRQ_NONE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Write 1 to clear status reg | 
|  | * We cannot use a field operation here due to a potential race between | 
|  | * 32k domain and vbus domain. | 
|  | */ | 
|  | regmap_write(priv->regmap, REG_K3RTC_IRQSTATUS_SYS, 0x1); | 
|  |  | 
|  | /* Sync the write in */ | 
|  | ret = k3rtc_fence(priv); | 
|  | if (ret) { | 
|  | dev_err(dev, "Failed to fence irq status clr(%d)!\n", ret); | 
|  | return IRQ_NONE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Force the 32k status to be reloaded back in to ensure status is | 
|  | * reflected back correctly. | 
|  | */ | 
|  | k3rtc_field_write(priv, K3RTC_RELOAD_FROM_BBD, 0x1); | 
|  |  | 
|  | /* Ensure the write sync is through */ | 
|  | ret = k3rtc_fence(priv); | 
|  | if (ret) { | 
|  | dev_err(dev, "Failed to fence reload from bbd(%d)!\n", ret); | 
|  | return IRQ_NONE; | 
|  | } | 
|  |  | 
|  | /* Now we ensure that the status bit is cleared */ | 
|  | ret = regmap_field_read_poll_timeout(priv->r_fields[K3RTC_IRQ_STATUS], | 
|  | ret, !ret, 2, priv->sync_timeout_us); | 
|  | if (ret) { | 
|  | dev_err(dev, "Time out waiting for status clear\n"); | 
|  | return IRQ_NONE; | 
|  | } | 
|  |  | 
|  | /* Notify RTC core on event */ | 
|  | rtc_update_irq(priv->rtc_dev, 1, RTC_IRQF | RTC_AF); | 
|  |  | 
|  | return IRQ_HANDLED; | 
|  | } | 
|  |  | 
|  | static const struct rtc_class_ops ti_k3_rtc_ops = { | 
|  | .read_time = ti_k3_rtc_read_time, | 
|  | .set_time = ti_k3_rtc_set_time, | 
|  | .read_alarm = ti_k3_rtc_read_alarm, | 
|  | .set_alarm = ti_k3_rtc_set_alarm, | 
|  | .read_offset = ti_k3_rtc_read_offset, | 
|  | .set_offset = ti_k3_rtc_set_offset, | 
|  | .alarm_irq_enable = ti_k3_rtc_alarm_irq_enable, | 
|  | }; | 
|  |  | 
|  | static int ti_k3_rtc_scratch_read(void *priv_data, unsigned int offset, | 
|  | void *val, size_t bytes) | 
|  | { | 
|  | struct ti_k3_rtc *priv = (struct ti_k3_rtc *)priv_data; | 
|  |  | 
|  | return regmap_bulk_read(priv->regmap, REG_K3RTC_SCRATCH0 + offset, val, bytes / 4); | 
|  | } | 
|  |  | 
|  | static int ti_k3_rtc_scratch_write(void *priv_data, unsigned int offset, | 
|  | void *val, size_t bytes) | 
|  | { | 
|  | struct ti_k3_rtc *priv = (struct ti_k3_rtc *)priv_data; | 
|  | int ret; | 
|  |  | 
|  | ret = regmap_bulk_write(priv->regmap, REG_K3RTC_SCRATCH0 + offset, val, bytes / 4); | 
|  | if (ret) | 
|  | return ret; | 
|  |  | 
|  | return k3rtc_fence(priv); | 
|  | } | 
|  |  | 
|  | static struct nvmem_config ti_k3_rtc_nvmem_config = { | 
|  | .name = "ti_k3_rtc_scratch", | 
|  | .word_size = 4, | 
|  | .stride = 4, | 
|  | .size = REG_K3RTC_SCRATCH7 - REG_K3RTC_SCRATCH0 + 4, | 
|  | .reg_read = ti_k3_rtc_scratch_read, | 
|  | .reg_write = ti_k3_rtc_scratch_write, | 
|  | }; | 
|  |  | 
|  | static int k3rtc_get_32kclk(struct device *dev, struct ti_k3_rtc *priv) | 
|  | { | 
|  | struct clk *clk; | 
|  |  | 
|  | clk = devm_clk_get_enabled(dev, "osc32k"); | 
|  | if (IS_ERR(clk)) | 
|  | return PTR_ERR(clk); | 
|  |  | 
|  | priv->rate_32k = clk_get_rate(clk); | 
|  |  | 
|  | /* Make sure we are exact 32k clock. Else, try to compensate delay */ | 
|  | if (priv->rate_32k != 32768) | 
|  | dev_warn(dev, "Clock rate %ld is not 32768! Could misbehave!\n", | 
|  | priv->rate_32k); | 
|  |  | 
|  | /* | 
|  | * Sync timeout should be two 32k clk sync cycles = ~61uS. We double | 
|  | * it to comprehend intermediate bus segment and cpu frequency | 
|  | * deltas | 
|  | */ | 
|  | priv->sync_timeout_us = (u32)(DIV_ROUND_UP_ULL(1000000, priv->rate_32k) * 4); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int k3rtc_get_vbusclk(struct device *dev, struct ti_k3_rtc *priv) | 
|  | { | 
|  | struct clk *clk; | 
|  |  | 
|  | /* Note: VBUS isn't a context clock, it is needed for hardware operation */ | 
|  | clk = devm_clk_get_enabled(dev, "vbus"); | 
|  | if (IS_ERR(clk)) | 
|  | return PTR_ERR(clk); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int ti_k3_rtc_probe(struct platform_device *pdev) | 
|  | { | 
|  | struct device *dev = &pdev->dev; | 
|  | struct ti_k3_rtc *priv; | 
|  | void __iomem *rtc_base; | 
|  | int ret; | 
|  |  | 
|  | priv = devm_kzalloc(dev, sizeof(struct ti_k3_rtc), GFP_KERNEL); | 
|  | if (!priv) | 
|  | return -ENOMEM; | 
|  |  | 
|  | rtc_base = devm_platform_ioremap_resource(pdev, 0); | 
|  | if (IS_ERR(rtc_base)) | 
|  | return PTR_ERR(rtc_base); | 
|  |  | 
|  | priv->regmap = devm_regmap_init_mmio(dev, rtc_base, &ti_k3_rtc_regmap_config); | 
|  | if (IS_ERR(priv->regmap)) | 
|  | return PTR_ERR(priv->regmap); | 
|  |  | 
|  | ret = devm_regmap_field_bulk_alloc(dev, priv->regmap, priv->r_fields, | 
|  | ti_rtc_reg_fields, K3_RTC_MAX_FIELDS); | 
|  | if (ret) | 
|  | return ret; | 
|  |  | 
|  | ret = k3rtc_get_32kclk(dev, priv); | 
|  | if (ret) | 
|  | return ret; | 
|  | ret = k3rtc_get_vbusclk(dev, priv); | 
|  | if (ret) | 
|  | return ret; | 
|  |  | 
|  | ret = platform_get_irq(pdev, 0); | 
|  | if (ret < 0) | 
|  | return ret; | 
|  | priv->irq = (unsigned int)ret; | 
|  |  | 
|  | priv->rtc_dev = devm_rtc_allocate_device(dev); | 
|  | if (IS_ERR(priv->rtc_dev)) | 
|  | return PTR_ERR(priv->rtc_dev); | 
|  |  | 
|  | priv->rtc_dev->ops = &ti_k3_rtc_ops; | 
|  | priv->rtc_dev->range_max = (1ULL << 48) - 1;	/* 48Bit seconds */ | 
|  | ti_k3_rtc_nvmem_config.priv = priv; | 
|  |  | 
|  | ret = devm_request_threaded_irq(dev, priv->irq, NULL, | 
|  | ti_k3_rtc_interrupt, | 
|  | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, | 
|  | dev_name(dev), dev); | 
|  | if (ret) { | 
|  | dev_err(dev, "Could not request IRQ: %d\n", ret); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | platform_set_drvdata(pdev, priv); | 
|  |  | 
|  | ret = k3rtc_configure(dev); | 
|  | if (ret) | 
|  | return ret; | 
|  |  | 
|  | if (device_property_present(dev, "wakeup-source")) | 
|  | device_init_wakeup(dev, true); | 
|  | else | 
|  | device_set_wakeup_capable(dev, true); | 
|  |  | 
|  | ret = devm_rtc_register_device(priv->rtc_dev); | 
|  | if (ret) | 
|  | return ret; | 
|  |  | 
|  | return devm_rtc_nvmem_register(priv->rtc_dev, &ti_k3_rtc_nvmem_config); | 
|  | } | 
|  |  | 
|  | static const struct of_device_id ti_k3_rtc_of_match_table[] = { | 
|  | {.compatible = "ti,am62-rtc" }, | 
|  | {} | 
|  | }; | 
|  | MODULE_DEVICE_TABLE(of, ti_k3_rtc_of_match_table); | 
|  |  | 
|  | static int __maybe_unused ti_k3_rtc_suspend(struct device *dev) | 
|  | { | 
|  | struct ti_k3_rtc *priv = dev_get_drvdata(dev); | 
|  |  | 
|  | if (device_may_wakeup(dev)) | 
|  | return enable_irq_wake(priv->irq); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int __maybe_unused ti_k3_rtc_resume(struct device *dev) | 
|  | { | 
|  | struct ti_k3_rtc *priv = dev_get_drvdata(dev); | 
|  |  | 
|  | if (device_may_wakeup(dev)) | 
|  | disable_irq_wake(priv->irq); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static SIMPLE_DEV_PM_OPS(ti_k3_rtc_pm_ops, ti_k3_rtc_suspend, ti_k3_rtc_resume); | 
|  |  | 
|  | static struct platform_driver ti_k3_rtc_driver = { | 
|  | .probe = ti_k3_rtc_probe, | 
|  | .driver = { | 
|  | .name = "rtc-ti-k3", | 
|  | .of_match_table = ti_k3_rtc_of_match_table, | 
|  | .pm = &ti_k3_rtc_pm_ops, | 
|  | }, | 
|  | }; | 
|  | module_platform_driver(ti_k3_rtc_driver); | 
|  |  | 
|  | MODULE_LICENSE("GPL"); | 
|  | MODULE_DESCRIPTION("TI K3 RTC driver"); | 
|  | MODULE_AUTHOR("Nishanth Menon"); |