aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNadav Haklai <nadavh@marvell.com>2015-08-06 11:18:48 -0400
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2015-09-05 07:19:12 -0400
commit0c6e718389305cbc4cd9b8e3fd4b4173bd1127e6 (patch)
tree58da7761f2ef3da35d97f94245cee2963c6e0b3e
parentefbbb4fd6b6fe0d3d2cfb3c5bbcdf00f1995cb60 (diff)
rtc: armada38x: Align RTC set time procedure with the official errata
According to the Armada38x functional errata FE-3124064, writing to the RTC TIME register may fail. As a workaround, after writing to RTC TIME register, issue a dummy write of 0x0 twice to the RTC Status register. This is the updated implementation of the Errata that eliminates the need of the long 100ms delay during the RTC set time procedure. [gregory.clement@free-electrons.com]: removed the mutex and use the spinlock again Signed-off-by: Nadav Haklai <nadavh@marvell.com> Reviewed-by: Neta Zur Hershkovits <neta@marvell.com> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
-rw-r--r--drivers/rtc/rtc-armada38x.c32
1 files changed, 12 insertions, 20 deletions
diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c
index 2b08cac62f07..06c6bd5eab41 100644
--- a/drivers/rtc/rtc-armada38x.c
+++ b/drivers/rtc/rtc-armada38x.c
@@ -40,13 +40,6 @@ struct armada38x_rtc {
40 void __iomem *regs; 40 void __iomem *regs;
41 void __iomem *regs_soc; 41 void __iomem *regs_soc;
42 spinlock_t lock; 42 spinlock_t lock;
43 /*
44 * While setting the time, the RTC TIME register should not be
45 * accessed. Setting the RTC time involves sleeping during
46 * 100ms, so a mutex instead of a spinlock is used to protect
47 * it
48 */
49 struct mutex mutex_time;
50 int irq; 43 int irq;
51}; 44};
52 45
@@ -64,9 +57,9 @@ static void rtc_delayed_write(u32 val, struct armada38x_rtc *rtc, int offset)
64static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm) 57static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
65{ 58{
66 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 59 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
67 unsigned long time, time_check; 60 unsigned long time, time_check, flags;
68 61
69 mutex_lock(&rtc->mutex_time); 62 spin_lock_irqsave(&rtc->lock, flags);
70 time = readl(rtc->regs + RTC_TIME); 63 time = readl(rtc->regs + RTC_TIME);
71 /* 64 /*
72 * WA for failing time set attempts. As stated in HW ERRATA if 65 * WA for failing time set attempts. As stated in HW ERRATA if
@@ -77,7 +70,7 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
77 if ((time_check - time) > 1) 70 if ((time_check - time) > 1)
78 time_check = readl(rtc->regs + RTC_TIME); 71 time_check = readl(rtc->regs + RTC_TIME);
79 72
80 mutex_unlock(&rtc->mutex_time); 73 spin_unlock_irqrestore(&rtc->lock, flags);
81 74
82 rtc_time_to_tm(time_check, tm); 75 rtc_time_to_tm(time_check, tm);
83 76
@@ -88,23 +81,23 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
88{ 81{
89 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 82 struct armada38x_rtc *rtc = dev_get_drvdata(dev);
90 int ret = 0; 83 int ret = 0;
91 unsigned long time; 84 unsigned long time, flags;
92 85
93 ret = rtc_tm_to_time(tm, &time); 86 ret = rtc_tm_to_time(tm, &time);
94 87
95 if (ret) 88 if (ret)
96 goto out; 89 goto out;
97 /* 90 /*
98 * Setting the RTC time not always succeeds. According to the 91 * According to errata FE-3124064, Write to RTC TIME register
99 * errata we need to first write on the status register and 92 * may fail. As a workaround, after writing to RTC TIME
100 * then wait for 100ms before writing to the time register to be 93 * register, issue a dummy write of 0x0 twice to RTC Status
101 * sure that the data will be taken into account. 94 * register.
102 */ 95 */
103 mutex_lock(&rtc->mutex_time); 96 spin_lock_irqsave(&rtc->lock, flags);
104 rtc_delayed_write(0, rtc, RTC_STATUS);
105 msleep(100);
106 rtc_delayed_write(time, rtc, RTC_TIME); 97 rtc_delayed_write(time, rtc, RTC_TIME);
107 mutex_unlock(&rtc->mutex_time); 98 rtc_delayed_write(0, rtc, RTC_STATUS);
99 rtc_delayed_write(0, rtc, RTC_STATUS);
100 spin_unlock_irqrestore(&rtc->lock, flags);
108 101
109out: 102out:
110 return ret; 103 return ret;
@@ -229,7 +222,6 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev)
229 return -ENOMEM; 222 return -ENOMEM;
230 223
231 spin_lock_init(&rtc->lock); 224 spin_lock_init(&rtc->lock);
232 mutex_init(&rtc->mutex_time);
233 225
234 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc"); 226 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc");
235 rtc->regs = devm_ioremap_resource(&pdev->dev, res); 227 rtc->regs = devm_ioremap_resource(&pdev->dev, res);