History

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.

Krzysztof Kozlowski committed 12 years ago

Commit d73238d1 parent 7b003be1 file · +31 −6Browse files

Unified · Split

drivers/rtc/rtc-s5m.c+31−6
@@ -28,6 +28,16 @@ · 27 unmodified lines
28#include <linux/mfd/samsung/irq.h>28#include <linux/mfd/samsung/irq.h>
29#include <linux/mfd/samsung/rtc.h>29#include <linux/mfd/samsung/rtc.h>
30 30
31/*
32 * Maximum number of retries for checking changes in UDR field
33 * of SEC_RTC_UDR_CON register (to limit possible endless loop).
34 *
35 * After writing to RTC registers (setting time or alarm) read the UDR field
36 * in SEC_RTC_UDR_CON register. UDR is auto-cleared when data have
37 * been transferred.
38 */
39#define UDR_READ_RETRY_CNT 5
40
31struct s5m_rtc_info {41struct s5m_rtc_info {
32 struct device *dev;42 struct device *dev;
33 struct sec_pmic_dev *s5m87xx;43 struct sec_pmic_dev *s5m87xx;
@@ -84,6 +94,25 @@ static int s5m8767_tm_to_data(struct rtc_time *tm, u8 *data) · 50 unmodified lines
84 }94 }
85}95}
86 96
97/*
98 * Read RTC_UDR_CON register and wait till UDR field is cleared.
99 * This indicates that time/alarm update ended.
100 */
101static inline int s5m8767_wait_for_udr_update(struct s5m_rtc_info *info)
102{
103 int ret, retry = UDR_READ_RETRY_CNT;
104 unsigned int data;
105
106 do {
107 ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data);
108 } while (--retry && (data & RTC_UDR_MASK) && !ret);
109
110 if (!retry)
111 dev_err(info->dev, "waiting for UDR update, reached max number of retries\n");
112
113 return ret;
114}
115
87static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)116static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
88{117{
89 int ret;118 int ret;
@@ -104,9 +133,7 @@ static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info) · 14 unmodified lines
104 return ret;133 return ret;
105 }134 }
106 135
107 do {136 ret = s5m8767_wait_for_udr_update(info);
108 ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data);
109 } while ((data & RTC_UDR_MASK) && !ret);
110 137
111 return ret;138 return ret;
112}139}
@@ -133,9 +160,7 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info) · 20 unmodified lines
133 return ret;160 return ret;
134 }161 }
135 162
136 do {163 ret = s5m8767_wait_for_udr_update(info);
137 ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data);
138 } while ((data & RTC_UDR_MASK) && !ret);
139 164
140 return ret;165 return ret;
141}166}