From a36159eec6ca17402b0e146b86efaf76568dc353 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 20 Sep 2024 01:41:23 +0000
Subject: [PATCH] 重命名 AX88772C_eeprom/asix.c 为 asix_mac.c
---
kernel/drivers/rtc/rtc-snvs.c | 167 +++++++++++++++++++++++++++++++++----------------------
1 files changed, 100 insertions(+), 67 deletions(-)
diff --git a/kernel/drivers/rtc/rtc-snvs.c b/kernel/drivers/rtc/rtc-snvs.c
index 3cf011e..cc7f6c4 100644
--- a/kernel/drivers/rtc/rtc-snvs.c
+++ b/kernel/drivers/rtc/rtc-snvs.c
@@ -7,8 +7,8 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/pm_wakeirq.h>
#include <linux/rtc.h>
#include <linux/clk.h>
#include <linux/mfd/syscon.h>
@@ -31,6 +31,14 @@
#define SNVS_LPPGDR_INIT 0x41736166
#define CNTR_TO_SECS_SH 15
+
+/* The maximum RTC clock cycles that are allowed to pass between two
+ * consecutive clock counter register reads. If the values are corrupted a
+ * bigger difference is expected. The RTC frequency is 32kHz. With 320 cycles
+ * we end at 10ms which should be enough for most cases. If it once takes
+ * longer than expected we do a retry.
+ */
+#define MAX_RTC_READ_DIFF_CYCLES 320
struct snvs_rtc_data {
struct rtc_device *rtc;
@@ -56,6 +64,7 @@
static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
{
u64 read1, read2;
+ s64 diff;
unsigned int timeout = 100;
/* As expected, the registers might update between the read of the LSB
@@ -66,7 +75,8 @@
do {
read2 = read1;
read1 = rtc_read_lpsrt(data);
- } while (read1 != read2 && --timeout);
+ diff = read1 - read2;
+ } while (((diff < 0) || (diff > MAX_RTC_READ_DIFF_CYCLES)) && --timeout);
if (!timeout)
dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
@@ -78,13 +88,15 @@
static int rtc_read_lp_counter_lsb(struct snvs_rtc_data *data, u32 *lsb)
{
u32 count1, count2;
+ s32 diff;
unsigned int timeout = 100;
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
do {
count2 = count1;
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
- } while (count1 != count2 && --timeout);
+ diff = count1 - count2;
+ } while (((diff < 0) || (diff > MAX_RTC_READ_DIFF_CYCLES)) && --timeout);
if (!timeout) {
dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
return -ETIMEDOUT;
@@ -148,9 +160,20 @@
static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct snvs_rtc_data *data = dev_get_drvdata(dev);
- unsigned long time = rtc_read_lp_counter(data);
+ unsigned long time;
+ int ret;
- rtc_time_to_tm(time, tm);
+ if (data->clk) {
+ ret = clk_enable(data->clk);
+ if (ret)
+ return ret;
+ }
+
+ time = rtc_read_lp_counter(data);
+ rtc_time64_to_tm(time, tm);
+
+ if (data->clk)
+ clk_disable(data->clk);
return 0;
}
@@ -158,10 +181,14 @@
static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct snvs_rtc_data *data = dev_get_drvdata(dev);
- unsigned long time;
+ unsigned long time = rtc_tm_to_time64(tm);
int ret;
- rtc_tm_to_time(tm, &time);
+ if (data->clk) {
+ ret = clk_enable(data->clk);
+ if (ret)
+ return ret;
+ }
/* Disable RTC first */
ret = snvs_rtc_enable(data, false);
@@ -175,6 +202,9 @@
/* Enable RTC again */
ret = snvs_rtc_enable(data, true);
+ if (data->clk)
+ clk_disable(data->clk);
+
return ret;
}
@@ -182,12 +212,22 @@
{
struct snvs_rtc_data *data = dev_get_drvdata(dev);
u32 lptar, lpsr;
+ int ret;
+
+ if (data->clk) {
+ ret = clk_enable(data->clk);
+ if (ret)
+ return ret;
+ }
regmap_read(data->regmap, data->offset + SNVS_LPTAR, &lptar);
- rtc_time_to_tm(lptar, &alrm->time);
+ rtc_time64_to_tm(lptar, &alrm->time);
regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0;
+
+ if (data->clk)
+ clk_disable(data->clk);
return 0;
}
@@ -195,22 +235,37 @@
static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
{
struct snvs_rtc_data *data = dev_get_drvdata(dev);
+ int ret;
+
+ if (data->clk) {
+ ret = clk_enable(data->clk);
+ if (ret)
+ return ret;
+ }
regmap_update_bits(data->regmap, data->offset + SNVS_LPCR,
(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN),
enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0);
- return rtc_write_sync_lp(data);
+ ret = rtc_write_sync_lp(data);
+
+ if (data->clk)
+ clk_disable(data->clk);
+
+ return ret;
}
static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct snvs_rtc_data *data = dev_get_drvdata(dev);
- struct rtc_time *alrm_tm = &alrm->time;
- unsigned long time;
+ unsigned long time = rtc_tm_to_time64(&alrm->time);
int ret;
- rtc_tm_to_time(alrm_tm, &time);
+ if (data->clk) {
+ ret = clk_enable(data->clk);
+ if (ret)
+ return ret;
+ }
regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);
ret = rtc_write_sync_lp(data);
@@ -220,6 +275,9 @@
/* Clear alarm interrupt status bit */
regmap_write(data->regmap, data->offset + SNVS_LPSR, SNVS_LPSR_LPTA);
+
+ if (data->clk)
+ clk_disable(data->clk);
return snvs_rtc_alarm_irq_enable(dev, alrm->enabled);
}
@@ -239,6 +297,9 @@
u32 lpsr;
u32 events = 0;
+ if (data->clk)
+ clk_enable(data->clk);
+
regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
if (lpsr & SNVS_LPSR_LPTA) {
@@ -253,6 +314,9 @@
/* clear interrupt status */
regmap_write(data->regmap, data->offset + SNVS_LPSR, lpsr);
+ if (data->clk)
+ clk_disable(data->clk);
+
return events ? IRQ_HANDLED : IRQ_NONE;
}
@@ -262,10 +326,15 @@
.reg_stride = 4,
};
+static void snvs_rtc_action(void *data)
+{
+ if (data)
+ clk_disable_unprepare(data);
+}
+
static int snvs_rtc_probe(struct platform_device *pdev)
{
struct snvs_rtc_data *data;
- struct resource *res;
int ret;
void __iomem *mmio;
@@ -281,9 +350,8 @@
if (IS_ERR(data->regmap)) {
dev_warn(&pdev->dev, "snvs rtc: you use old dts file, please update it\n");
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- mmio = devm_ioremap_resource(&pdev->dev, res);
+ mmio = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mmio))
return PTR_ERR(mmio);
@@ -314,6 +382,10 @@
}
}
+ ret = devm_add_action_or_reset(&pdev->dev, snvs_rtc_action, data->clk);
+ if (ret)
+ return ret;
+
platform_set_drvdata(pdev, data);
/* Initialize glitch detect */
@@ -326,90 +398,51 @@
ret = snvs_rtc_enable(data, true);
if (ret) {
dev_err(&pdev->dev, "failed to enable rtc %d\n", ret);
- goto error_rtc_device_register;
+ return ret;
}
device_init_wakeup(&pdev->dev, true);
+ ret = dev_pm_set_wake_irq(&pdev->dev, data->irq);
+ if (ret)
+ dev_err(&pdev->dev, "failed to enable irq wake\n");
ret = devm_request_irq(&pdev->dev, data->irq, snvs_rtc_irq_handler,
IRQF_SHARED, "rtc alarm", &pdev->dev);
if (ret) {
dev_err(&pdev->dev, "failed to request irq %d: %d\n",
data->irq, ret);
- goto error_rtc_device_register;
+ return ret;
}
data->rtc->ops = &snvs_rtc_ops;
- ret = rtc_register_device(data->rtc);
- if (ret) {
- dev_err(&pdev->dev, "failed to register rtc: %d\n", ret);
- goto error_rtc_device_register;
- }
+ data->rtc->range_max = U32_MAX;
- return 0;
-
-error_rtc_device_register:
- if (data->clk)
- clk_disable_unprepare(data->clk);
-
- return ret;
+ return rtc_register_device(data->rtc);
}
-#ifdef CONFIG_PM_SLEEP
-static int snvs_rtc_suspend(struct device *dev)
-{
- struct snvs_rtc_data *data = dev_get_drvdata(dev);
-
- if (device_may_wakeup(dev))
- return enable_irq_wake(data->irq);
-
- return 0;
-}
-
-static int snvs_rtc_suspend_noirq(struct device *dev)
+static int __maybe_unused snvs_rtc_suspend_noirq(struct device *dev)
{
struct snvs_rtc_data *data = dev_get_drvdata(dev);
if (data->clk)
- clk_disable_unprepare(data->clk);
+ clk_disable(data->clk);
return 0;
}
-static int snvs_rtc_resume(struct device *dev)
-{
- struct snvs_rtc_data *data = dev_get_drvdata(dev);
-
- if (device_may_wakeup(dev))
- return disable_irq_wake(data->irq);
-
- return 0;
-}
-
-static int snvs_rtc_resume_noirq(struct device *dev)
+static int __maybe_unused snvs_rtc_resume_noirq(struct device *dev)
{
struct snvs_rtc_data *data = dev_get_drvdata(dev);
if (data->clk)
- return clk_prepare_enable(data->clk);
+ return clk_enable(data->clk);
return 0;
}
static const struct dev_pm_ops snvs_rtc_pm_ops = {
- .suspend = snvs_rtc_suspend,
- .suspend_noirq = snvs_rtc_suspend_noirq,
- .resume = snvs_rtc_resume,
- .resume_noirq = snvs_rtc_resume_noirq,
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(snvs_rtc_suspend_noirq, snvs_rtc_resume_noirq)
};
-
-#define SNVS_RTC_PM_OPS (&snvs_rtc_pm_ops)
-
-#else
-
-#define SNVS_RTC_PM_OPS NULL
-
-#endif
static const struct of_device_id snvs_dt_ids[] = {
{ .compatible = "fsl,sec-v4.0-mon-rtc-lp", },
@@ -420,7 +453,7 @@
static struct platform_driver snvs_rtc_driver = {
.driver = {
.name = "snvs_rtc",
- .pm = SNVS_RTC_PM_OPS,
+ .pm = &snvs_rtc_pm_ops,
.of_match_table = snvs_dt_ids,
},
.probe = snvs_rtc_probe,
--
Gitblit v1.6.2