Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Microchip MPFS RTC driver
0004  *
0005  * Copyright (c) 2021-2022 Microchip Corporation. All rights reserved.
0006  *
0007  * Author: Daire McNamara <daire.mcnamara@microchip.com>
0008  *         & Conor Dooley <conor.dooley@microchip.com>
0009  */
0010 #include "linux/bits.h"
0011 #include "linux/iopoll.h"
0012 #include <linux/clk.h>
0013 #include <linux/io.h>
0014 #include <linux/module.h>
0015 #include <linux/kernel.h>
0016 #include <linux/of.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/pm_wakeirq.h>
0019 #include <linux/slab.h>
0020 #include <linux/rtc.h>
0021 
0022 #define CONTROL_REG     0x00
0023 #define MODE_REG        0x04
0024 #define PRESCALER_REG       0x08
0025 #define ALARM_LOWER_REG     0x0c
0026 #define ALARM_UPPER_REG     0x10
0027 #define COMPARE_LOWER_REG   0x14
0028 #define COMPARE_UPPER_REG   0x18
0029 #define DATETIME_LOWER_REG  0x20
0030 #define DATETIME_UPPER_REG  0x24
0031 
0032 #define CONTROL_RUNNING_BIT BIT(0)
0033 #define CONTROL_START_BIT   BIT(0)
0034 #define CONTROL_STOP_BIT    BIT(1)
0035 #define CONTROL_ALARM_ON_BIT    BIT(2)
0036 #define CONTROL_ALARM_OFF_BIT   BIT(3)
0037 #define CONTROL_RESET_BIT   BIT(4)
0038 #define CONTROL_UPLOAD_BIT  BIT(5)
0039 #define CONTROL_DOWNLOAD_BIT    BIT(6)
0040 #define CONTROL_MATCH_BIT   BIT(7)
0041 #define CONTROL_WAKEUP_CLR_BIT  BIT(8)
0042 #define CONTROL_WAKEUP_SET_BIT  BIT(9)
0043 #define CONTROL_UPDATED_BIT BIT(10)
0044 
0045 #define MODE_CLOCK_CALENDAR BIT(0)
0046 #define MODE_WAKE_EN        BIT(1)
0047 #define MODE_WAKE_RESET     BIT(2)
0048 #define MODE_WAKE_CONTINUE  BIT(3)
0049 
0050 #define MAX_PRESCALER_COUNT GENMASK(25, 0)
0051 #define DATETIME_UPPER_MASK GENMASK(29, 0)
0052 #define ALARM_UPPER_MASK    GENMASK(10, 0)
0053 
0054 #define UPLOAD_TIMEOUT_US   50
0055 
0056 struct mpfs_rtc_dev {
0057     struct rtc_device *rtc;
0058     void __iomem *base;
0059 };
0060 
0061 static void mpfs_rtc_start(struct mpfs_rtc_dev *rtcdev)
0062 {
0063     u32 ctrl;
0064 
0065     ctrl = readl(rtcdev->base + CONTROL_REG);
0066     ctrl &= ~CONTROL_STOP_BIT;
0067     ctrl |= CONTROL_START_BIT;
0068     writel(ctrl, rtcdev->base + CONTROL_REG);
0069 }
0070 
0071 static void mpfs_rtc_clear_irq(struct mpfs_rtc_dev *rtcdev)
0072 {
0073     u32 val = readl(rtcdev->base + CONTROL_REG);
0074 
0075     val &= ~(CONTROL_ALARM_ON_BIT | CONTROL_STOP_BIT);
0076     val |= CONTROL_ALARM_OFF_BIT;
0077     writel(val, rtcdev->base + CONTROL_REG);
0078     /*
0079      * Ensure that the posted write to the CONTROL_REG register completed before
0080      * returning from this function. Not doing this may result in the interrupt
0081      * only being cleared some time after this function returns.
0082      */
0083     (void)readl(rtcdev->base + CONTROL_REG);
0084 }
0085 
0086 static int mpfs_rtc_readtime(struct device *dev, struct rtc_time *tm)
0087 {
0088     struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
0089     u64 time;
0090 
0091     time = readl(rtcdev->base + DATETIME_LOWER_REG);
0092     time |= ((u64)readl(rtcdev->base + DATETIME_UPPER_REG) & DATETIME_UPPER_MASK) << 32;
0093     rtc_time64_to_tm(time, tm);
0094 
0095     return 0;
0096 }
0097 
0098 static int mpfs_rtc_settime(struct device *dev, struct rtc_time *tm)
0099 {
0100     struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
0101     u32 ctrl, prog;
0102     u64 time;
0103     int ret;
0104 
0105     time = rtc_tm_to_time64(tm);
0106 
0107     writel((u32)time, rtcdev->base + DATETIME_LOWER_REG);
0108     writel((u32)(time >> 32) & DATETIME_UPPER_MASK, rtcdev->base + DATETIME_UPPER_REG);
0109 
0110     ctrl = readl(rtcdev->base + CONTROL_REG);
0111     ctrl &= ~CONTROL_STOP_BIT;
0112     ctrl |= CONTROL_UPLOAD_BIT;
0113     writel(ctrl, rtcdev->base + CONTROL_REG);
0114 
0115     ret = read_poll_timeout(readl, prog, prog & CONTROL_UPLOAD_BIT, 0, UPLOAD_TIMEOUT_US,
0116                 false, rtcdev->base + CONTROL_REG);
0117     if (ret) {
0118         dev_err(dev, "timed out uploading time to rtc");
0119         return ret;
0120     }
0121     mpfs_rtc_start(rtcdev);
0122 
0123     return 0;
0124 }
0125 
0126 static int mpfs_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
0127 {
0128     struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
0129     u32 mode = readl(rtcdev->base + MODE_REG);
0130     u64 time;
0131 
0132     alrm->enabled = mode & MODE_WAKE_EN;
0133 
0134     time = (u64)readl(rtcdev->base + ALARM_LOWER_REG) << 32;
0135     time |= (readl(rtcdev->base + ALARM_UPPER_REG) & ALARM_UPPER_MASK);
0136     rtc_time64_to_tm(time, &alrm->time);
0137 
0138     return 0;
0139 }
0140 
0141 static int mpfs_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
0142 {
0143     struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
0144     u32 mode, ctrl;
0145     u64 time;
0146 
0147     /* Disable the alarm before updating */
0148     ctrl = readl(rtcdev->base + CONTROL_REG);
0149     ctrl |= CONTROL_ALARM_OFF_BIT;
0150     writel(ctrl, rtcdev->base + CONTROL_REG);
0151 
0152     time = rtc_tm_to_time64(&alrm->time);
0153 
0154     writel((u32)time, rtcdev->base + ALARM_LOWER_REG);
0155     writel((u32)(time >> 32) & ALARM_UPPER_MASK, rtcdev->base + ALARM_UPPER_REG);
0156 
0157     /* Bypass compare register in alarm mode */
0158     writel(GENMASK(31, 0), rtcdev->base + COMPARE_LOWER_REG);
0159     writel(GENMASK(29, 0), rtcdev->base + COMPARE_UPPER_REG);
0160 
0161     /* Configure the RTC to enable the alarm. */
0162     ctrl = readl(rtcdev->base + CONTROL_REG);
0163     mode = readl(rtcdev->base + MODE_REG);
0164     if (alrm->enabled) {
0165         mode = MODE_WAKE_EN | MODE_WAKE_CONTINUE;
0166         /* Enable the alarm */
0167         ctrl &= ~CONTROL_ALARM_OFF_BIT;
0168         ctrl |= CONTROL_ALARM_ON_BIT;
0169     }
0170     ctrl &= ~CONTROL_STOP_BIT;
0171     ctrl |= CONTROL_START_BIT;
0172     writel(ctrl, rtcdev->base + CONTROL_REG);
0173     writel(mode, rtcdev->base + MODE_REG);
0174 
0175     return 0;
0176 }
0177 
0178 static int mpfs_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
0179 {
0180     struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
0181     u32 ctrl;
0182 
0183     ctrl = readl(rtcdev->base + CONTROL_REG);
0184     ctrl &= ~(CONTROL_ALARM_ON_BIT | CONTROL_ALARM_OFF_BIT | CONTROL_STOP_BIT);
0185 
0186     if (enabled)
0187         ctrl |= CONTROL_ALARM_ON_BIT;
0188     else
0189         ctrl |= CONTROL_ALARM_OFF_BIT;
0190 
0191     writel(ctrl, rtcdev->base + CONTROL_REG);
0192 
0193     return 0;
0194 }
0195 
0196 static inline struct clk *mpfs_rtc_init_clk(struct device *dev)
0197 {
0198     struct clk *clk;
0199     int ret;
0200 
0201     clk = devm_clk_get(dev, "rtc");
0202     if (IS_ERR(clk))
0203         return clk;
0204 
0205     ret = clk_prepare_enable(clk);
0206     if (ret)
0207         return ERR_PTR(ret);
0208 
0209     devm_add_action_or_reset(dev, (void (*) (void *))clk_disable_unprepare, clk);
0210     return clk;
0211 }
0212 
0213 static irqreturn_t mpfs_rtc_wakeup_irq_handler(int irq, void *dev)
0214 {
0215     struct mpfs_rtc_dev *rtcdev = dev;
0216 
0217     mpfs_rtc_clear_irq(rtcdev);
0218 
0219     rtc_update_irq(rtcdev->rtc, 1, RTC_IRQF | RTC_AF);
0220 
0221     return IRQ_HANDLED;
0222 }
0223 
0224 static const struct rtc_class_ops mpfs_rtc_ops = {
0225     .read_time      = mpfs_rtc_readtime,
0226     .set_time       = mpfs_rtc_settime,
0227     .read_alarm     = mpfs_rtc_readalarm,
0228     .set_alarm      = mpfs_rtc_setalarm,
0229     .alarm_irq_enable   = mpfs_rtc_alarm_irq_enable,
0230 };
0231 
0232 static int mpfs_rtc_probe(struct platform_device *pdev)
0233 {
0234     struct mpfs_rtc_dev *rtcdev;
0235     struct clk *clk;
0236     u32 prescaler;
0237     int wakeup_irq, ret;
0238 
0239     rtcdev = devm_kzalloc(&pdev->dev, sizeof(struct mpfs_rtc_dev), GFP_KERNEL);
0240     if (!rtcdev)
0241         return -ENOMEM;
0242 
0243     platform_set_drvdata(pdev, rtcdev);
0244 
0245     rtcdev->rtc = devm_rtc_allocate_device(&pdev->dev);
0246     if (IS_ERR(rtcdev->rtc))
0247         return PTR_ERR(rtcdev->rtc);
0248 
0249     rtcdev->rtc->ops = &mpfs_rtc_ops;
0250 
0251     /* range is capped by alarm max, lower reg is 31:0 & upper is 10:0 */
0252     rtcdev->rtc->range_max = GENMASK_ULL(42, 0);
0253 
0254     clk = mpfs_rtc_init_clk(&pdev->dev);
0255     if (IS_ERR(clk))
0256         return PTR_ERR(clk);
0257 
0258     rtcdev->base = devm_platform_ioremap_resource(pdev, 0);
0259     if (IS_ERR(rtcdev->base)) {
0260         dev_dbg(&pdev->dev, "invalid ioremap resources\n");
0261         return PTR_ERR(rtcdev->base);
0262     }
0263 
0264     wakeup_irq = platform_get_irq(pdev, 0);
0265     if (wakeup_irq <= 0) {
0266         dev_dbg(&pdev->dev, "could not get wakeup irq\n");
0267         return wakeup_irq;
0268     }
0269     ret = devm_request_irq(&pdev->dev, wakeup_irq, mpfs_rtc_wakeup_irq_handler, 0,
0270                    dev_name(&pdev->dev), rtcdev);
0271     if (ret) {
0272         dev_dbg(&pdev->dev, "could not request wakeup irq\n");
0273         return ret;
0274     }
0275 
0276     /* prescaler hardware adds 1 to reg value */
0277     prescaler = clk_get_rate(devm_clk_get(&pdev->dev, "rtcref")) - 1;
0278 
0279     if (prescaler > MAX_PRESCALER_COUNT) {
0280         dev_dbg(&pdev->dev, "invalid prescaler %d\n", prescaler);
0281         return -EINVAL;
0282     }
0283 
0284     writel(prescaler, rtcdev->base + PRESCALER_REG);
0285     dev_info(&pdev->dev, "prescaler set to: 0x%X \r\n", prescaler);
0286 
0287     device_init_wakeup(&pdev->dev, true);
0288     ret = dev_pm_set_wake_irq(&pdev->dev, wakeup_irq);
0289     if (ret)
0290         dev_err(&pdev->dev, "failed to enable irq wake\n");
0291 
0292     return devm_rtc_register_device(rtcdev->rtc);
0293 }
0294 
0295 static int mpfs_rtc_remove(struct platform_device *pdev)
0296 {
0297     dev_pm_clear_wake_irq(&pdev->dev);
0298 
0299     return 0;
0300 }
0301 
0302 static const struct of_device_id mpfs_rtc_of_match[] = {
0303     { .compatible = "microchip,mpfs-rtc" },
0304     { }
0305 };
0306 
0307 MODULE_DEVICE_TABLE(of, mpfs_rtc_of_match);
0308 
0309 static struct platform_driver mpfs_rtc_driver = {
0310     .probe = mpfs_rtc_probe,
0311     .remove = mpfs_rtc_remove,
0312     .driver = {
0313         .name = "mpfs_rtc",
0314         .of_match_table = mpfs_rtc_of_match,
0315     },
0316 };
0317 
0318 module_platform_driver(mpfs_rtc_driver);
0319 
0320 MODULE_DESCRIPTION("Real time clock for Microchip Polarfire SoC");
0321 MODULE_AUTHOR("Daire McNamara <daire.mcnamara@microchip.com>");
0322 MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");
0323 MODULE_LICENSE("GPL");