Commit d73238d4 authored by Krzysztof Kozlowski's avatar Krzysztof Kozlowski Committed by Linus Torvalds
Browse files

rtc: s5m: limit endless loop waiting for register update



After setting alarm or time the driver is waiting for UDR register to be
cleared indicating that registers data have been transferred.

Limit the endless loop to only 5 retries.
Signed-off-by: default avatarKrzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: default avatarMark Brown <broonie@linaro.org>
Acked-by: default avatarSangbeom Kim <sbkim73@samsung.com>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Lee Jones <lee.jones@linaro.org>
Cc: Liam Girdwood <lgirdwood@gmail.com>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 7b003be8
...@@ -28,6 +28,16 @@ ...@@ -28,6 +28,16 @@
#include <linux/mfd/samsung/irq.h> #include <linux/mfd/samsung/irq.h>
#include <linux/mfd/samsung/rtc.h> #include <linux/mfd/samsung/rtc.h>
/*
* Maximum number of retries for checking changes in UDR field
* of SEC_RTC_UDR_CON register (to limit possible endless loop).
*
* After writing to RTC registers (setting time or alarm) read the UDR field
* in SEC_RTC_UDR_CON register. UDR is auto-cleared when data have
* been transferred.
*/
#define UDR_READ_RETRY_CNT 5
struct s5m_rtc_info { struct s5m_rtc_info {
struct device *dev; struct device *dev;
struct sec_pmic_dev *s5m87xx; struct sec_pmic_dev *s5m87xx;
...@@ -84,6 +94,25 @@ static int s5m8767_tm_to_data(struct rtc_time *tm, u8 *data) ...@@ -84,6 +94,25 @@ static int s5m8767_tm_to_data(struct rtc_time *tm, u8 *data)
} }
} }
/*
* Read RTC_UDR_CON register and wait till UDR field is cleared.
* This indicates that time/alarm update ended.
*/
static inline int s5m8767_wait_for_udr_update(struct s5m_rtc_info *info)
{
int ret, retry = UDR_READ_RETRY_CNT;
unsigned int data;
do {
ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data);
} while (--retry && (data & RTC_UDR_MASK) && !ret);
if (!retry)
dev_err(info->dev, "waiting for UDR update, reached max number of retries\n");
return ret;
}
static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info) static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
{ {
int ret; int ret;
...@@ -104,9 +133,7 @@ static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info) ...@@ -104,9 +133,7 @@ static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
return ret; return ret;
} }
do { ret = s5m8767_wait_for_udr_update(info);
ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data);
} while ((data & RTC_UDR_MASK) && !ret);
return ret; return ret;
} }
...@@ -133,9 +160,7 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info) ...@@ -133,9 +160,7 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
return ret; return ret;
} }
do { ret = s5m8767_wait_for_udr_update(info);
ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data);
} while ((data & RTC_UDR_MASK) && !ret);
return ret; return ret;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment