Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rtc: s3c: Handle clock enable failures

clk_enable() can fail so handle such case.

Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>

authored by

Krzysztof Kozlowski and committed by
Alexandre Belloni
498bcf31 9903f68a

+57 -15
+57 -15
drivers/rtc/rtc-s3c.c
··· 68 68 void (*disable) (struct s3c_rtc *info); 69 69 }; 70 70 71 - static void s3c_rtc_enable_clk(struct s3c_rtc *info) 71 + static int s3c_rtc_enable_clk(struct s3c_rtc *info) 72 72 { 73 73 unsigned long irq_flags; 74 + int ret = 0; 74 75 75 76 spin_lock_irqsave(&info->alarm_clk_lock, irq_flags); 77 + 76 78 if (info->clk_disabled) { 77 - clk_enable(info->rtc_clk); 78 - if (info->data->needs_src_clk) 79 - clk_enable(info->rtc_src_clk); 79 + ret = clk_enable(info->rtc_clk); 80 + if (ret) 81 + goto out; 82 + 83 + if (info->data->needs_src_clk) { 84 + ret = clk_enable(info->rtc_src_clk); 85 + if (ret) { 86 + clk_disable(info->rtc_clk); 87 + goto out; 88 + } 89 + } 80 90 info->clk_disabled = false; 81 91 } 92 + 93 + out: 82 94 spin_unlock_irqrestore(&info->alarm_clk_lock, irq_flags); 95 + 96 + return ret; 83 97 } 84 98 85 99 static void s3c_rtc_disable_clk(struct s3c_rtc *info) ··· 136 122 { 137 123 struct s3c_rtc *info = dev_get_drvdata(dev); 138 124 unsigned int tmp; 125 + int ret; 139 126 140 127 dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled); 141 128 142 - s3c_rtc_enable_clk(info); 129 + ret = s3c_rtc_enable_clk(info); 130 + if (ret) 131 + return ret; 143 132 144 133 tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; 145 134 ··· 153 136 154 137 s3c_rtc_disable_clk(info); 155 138 156 - if (enabled) 157 - s3c_rtc_enable_clk(info); 158 - else 139 + if (enabled) { 140 + ret = s3c_rtc_enable_clk(info); 141 + if (ret) 142 + return ret; 143 + } else { 159 144 s3c_rtc_disable_clk(info); 145 + } 160 146 161 147 return 0; 162 148 } ··· 167 147 /* Set RTC frequency */ 168 148 static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq) 169 149 { 150 + int ret; 151 + 170 152 if (!is_power_of_2(freq)) 171 153 return -EINVAL; 172 154 173 - s3c_rtc_enable_clk(info); 155 + ret = s3c_rtc_enable_clk(info); 156 + if (ret) 157 + return ret; 174 158 spin_lock_irq(&info->pie_lock); 175 159 176 160 if (info->data->set_freq) ··· 191 167 { 192 168 struct s3c_rtc *info = dev_get_drvdata(dev); 193 169 unsigned int have_retried = 0; 170 + int ret; 194 171 195 - s3c_rtc_enable_clk(info); 172 + ret = s3c_rtc_enable_clk(info); 173 + if (ret) 174 + return ret; 196 175 197 176 retry_get_time: 198 177 rtc_tm->tm_min = readb(info->base + S3C2410_RTCMIN); ··· 239 212 { 240 213 struct s3c_rtc *info = dev_get_drvdata(dev); 241 214 int year = tm->tm_year - 100; 215 + int ret; 242 216 243 217 dev_dbg(dev, "set time %04d.%02d.%02d %02d:%02d:%02d\n", 244 218 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, ··· 252 224 return -EINVAL; 253 225 } 254 226 255 - s3c_rtc_enable_clk(info); 227 + ret = s3c_rtc_enable_clk(info); 228 + if (ret) 229 + return ret; 256 230 257 231 writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_RTCSEC); 258 232 writeb(bin2bcd(tm->tm_min), info->base + S3C2410_RTCMIN); ··· 273 243 struct s3c_rtc *info = dev_get_drvdata(dev); 274 244 struct rtc_time *alm_tm = &alrm->time; 275 245 unsigned int alm_en; 246 + int ret; 276 247 277 - s3c_rtc_enable_clk(info); 248 + ret = s3c_rtc_enable_clk(info); 249 + if (ret) 250 + return ret; 278 251 279 252 alm_tm->tm_sec = readb(info->base + S3C2410_ALMSEC); 280 253 alm_tm->tm_min = readb(info->base + S3C2410_ALMMIN); ··· 326 293 struct s3c_rtc *info = dev_get_drvdata(dev); 327 294 struct rtc_time *tm = &alrm->time; 328 295 unsigned int alrm_en; 296 + int ret; 329 297 int year = tm->tm_year - 100; 330 298 331 299 dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", ··· 334 300 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, 335 301 tm->tm_hour, tm->tm_min, tm->tm_sec); 336 302 337 - s3c_rtc_enable_clk(info); 303 + ret = s3c_rtc_enable_clk(info); 304 + if (ret) 305 + return ret; 338 306 339 307 alrm_en = readb(info->base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; 340 308 writeb(0x00, info->base + S3C2410_RTCALM); ··· 385 349 static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) 386 350 { 387 351 struct s3c_rtc *info = dev_get_drvdata(dev); 352 + int ret; 388 353 389 - s3c_rtc_enable_clk(info); 354 + ret = s3c_rtc_enable_clk(info); 355 + if (ret) 356 + return ret; 390 357 391 358 if (info->data->enable_tick) 392 359 info->data->enable_tick(info, seq); ··· 628 589 static int s3c_rtc_suspend(struct device *dev) 629 590 { 630 591 struct s3c_rtc *info = dev_get_drvdata(dev); 592 + int ret; 631 593 632 - s3c_rtc_enable_clk(info); 594 + ret = s3c_rtc_enable_clk(info); 595 + if (ret) 596 + return ret; 633 597 634 598 /* save TICNT for anyone using periodic interrupts */ 635 599 if (info->data->save_tick_cnt)