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
2828 #include <linux/mfd/samsung/irq.h>
2929 #include <linux/mfd/samsung/rtc.h>
3030
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+
3141 struct s5m_rtc_info {
3242 struct device *dev;
3343 struct sec_pmic_dev *s5m87xx;
@@ -84,6 +94,25 @@ static int s5m8767_tm_to_data(struct rtc_time *tm, u8 *data) · 50 unmodified lines
8494 }
8595 }
8696
97+/*
98+ * Read RTC_UDR_CON register and wait till UDR field is cleared.
99+ * This indicates that time/alarm update ended.
100+ */
101+static 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+
87116 static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
88117 {
89118 int ret;
@@ -104,9 +133,7 @@ static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info) · 14 unmodified lines
104133 return ret;
105134 }
106135
107− do {
108− ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data);
109− } while ((data & RTC_UDR_MASK) && !ret);
136+ ret = s5m8767_wait_for_udr_update(info);
110137
111138 return ret;
112139 }
@@ -133,9 +160,7 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info) · 20 unmodified lines
133160 return ret;
134161 }
135162
136− do {
137− ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data);
138− } while ((data & RTC_UDR_MASK) && !ret);
163+ ret = s5m8767_wait_for_udr_update(info);
139164
140165 return ret;
141166 }