diff options
Diffstat (limited to 'drivers/rtc/rtc-pl031.c')
-rw-r--r-- | drivers/rtc/rtc-pl031.c | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index e1687e19c59f..82eb7da2c478 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -308,10 +308,9 @@ static int pl031_remove(struct amba_device *adev) dev_pm_clear_wake_irq(&adev->dev); device_init_wakeup(&adev->dev, false); - free_irq(adev->irq[0], ldata); + if (adev->irq[0]) + free_irq(adev->irq[0], ldata); rtc_device_unregister(ldata->rtc); - iounmap(ldata->base); - kfree(ldata); amba_release_regions(adev); return 0; @@ -322,25 +321,28 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) int ret; struct pl031_local *ldata; struct pl031_vendor_data *vendor = id->data; - struct rtc_class_ops *ops = &vendor->ops; + struct rtc_class_ops *ops; unsigned long time, data; ret = amba_request_regions(adev, NULL); if (ret) goto err_req; - ldata = kzalloc(sizeof(struct pl031_local), GFP_KERNEL); - if (!ldata) { + ldata = devm_kzalloc(&adev->dev, sizeof(struct pl031_local), + GFP_KERNEL); + ops = devm_kmemdup(&adev->dev, &vendor->ops, sizeof(vendor->ops), + GFP_KERNEL); + if (!ldata || !ops) { ret = -ENOMEM; goto out; } - ldata->vendor = vendor; - - ldata->base = ioremap(adev->res.start, resource_size(&adev->res)); + ldata->vendor = vendor; + ldata->base = devm_ioremap(&adev->dev, adev->res.start, + resource_size(&adev->res)); if (!ldata->base) { ret = -ENOMEM; - goto out_no_remap; + goto out; } amba_set_drvdata(adev, ldata); @@ -373,28 +375,32 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) } } + if (!adev->irq[0]) { + /* When there's no interrupt, no point in exposing the alarm */ + ops->read_alarm = NULL; + ops->set_alarm = NULL; + ops->alarm_irq_enable = NULL; + } + device_init_wakeup(&adev->dev, true); ldata->rtc = rtc_device_register("pl031", &adev->dev, ops, THIS_MODULE); if (IS_ERR(ldata->rtc)) { ret = PTR_ERR(ldata->rtc); - goto out_no_rtc; + goto out; } - if (request_irq(adev->irq[0], pl031_interrupt, - vendor->irqflags, "rtc-pl031", ldata)) { - ret = -EIO; - goto out_no_irq; + if (adev->irq[0]) { + ret = request_irq(adev->irq[0], pl031_interrupt, + vendor->irqflags, "rtc-pl031", ldata); + if (ret) + goto out_no_irq; + dev_pm_set_wake_irq(&adev->dev, adev->irq[0]); } - dev_pm_set_wake_irq(&adev->dev, adev->irq[0]); return 0; out_no_irq: rtc_device_unregister(ldata->rtc); -out_no_rtc: - iounmap(ldata->base); -out_no_remap: - kfree(ldata); out: amba_release_regions(adev); err_req: @@ -446,7 +452,7 @@ static struct pl031_vendor_data stv2_pl031 = { .irqflags = IRQF_SHARED | IRQF_COND_SUSPEND, }; -static struct amba_id pl031_ids[] = { +static const struct amba_id pl031_ids[] = { { .id = 0x00041031, .mask = 0x000fffff, |