1 // SPDX-License-Identifier: GPL-2.0+ 2 // 3 // Copyright 2022 NXP. 4 5 #include <linux/init.h> 6 #include <linux/io.h> 7 #include <linux/kernel.h> 8 #include <linux/mfd/syscon.h> 9 #include <linux/module.h> 10 #include <linux/of.h> 11 #include <linux/platform_device.h> 12 #include <linux/pm_wakeirq.h> 13 #include <linux/regmap.h> 14 #include <linux/rtc.h> 15 16 #define BBNSM_CTRL 0x8 17 #define BBNSM_INT_EN 0x10 18 #define BBNSM_EVENTS 0x14 19 #define BBNSM_RTC_LS 0x40 20 #define BBNSM_RTC_MS 0x44 21 #define BBNSM_TA 0x50 22 23 #define RTC_EN 0x2 24 #define RTC_EN_MSK 0x3 25 #define TA_EN (0x2 << 2) 26 #define TA_DIS (0x1 << 2) 27 #define TA_EN_MSK (0x3 << 2) 28 #define RTC_INT_EN 0x2 29 #define TA_INT_EN (0x2 << 2) 30 31 #define BBNSM_EVENT_TA (0x2 << 2) 32 33 #define CNTR_TO_SECS_SH 15 34 35 struct bbnsm_rtc { 36 struct rtc_device *rtc; 37 struct regmap *regmap; 38 int irq; 39 struct clk *clk; 40 }; 41 42 static u32 bbnsm_read_counter(struct bbnsm_rtc *bbnsm) 43 { 44 u32 rtc_msb, rtc_lsb; 45 unsigned int timeout = 100; 46 u32 time; 47 u32 tmp = 0; 48 49 do { 50 time = tmp; 51 /* read the msb */ 52 regmap_read(bbnsm->regmap, BBNSM_RTC_MS, &rtc_msb); 53 /* read the lsb */ 54 regmap_read(bbnsm->regmap, BBNSM_RTC_LS, &rtc_lsb); 55 /* convert to seconds */ 56 tmp = (rtc_msb << 17) | (rtc_lsb >> 15); 57 } while (tmp != time && --timeout); 58 59 return time; 60 } 61 62 static int bbnsm_rtc_read_time(struct device *dev, struct rtc_time *tm) 63 { 64 struct bbnsm_rtc *bbnsm = dev_get_drvdata(dev); 65 unsigned long time; 66 u32 val; 67 68 regmap_read(bbnsm->regmap, BBNSM_CTRL, &val); 69 if ((val & RTC_EN_MSK) != RTC_EN) 70 return -EINVAL; 71 72 time = bbnsm_read_counter(bbnsm); 73 rtc_time64_to_tm(time, tm); 74 75 return 0; 76 } 77 78 static int bbnsm_rtc_set_time(struct device *dev, struct rtc_time *tm) 79 { 80 struct bbnsm_rtc *bbnsm = dev_get_drvdata(dev); 81 unsigned long time = rtc_tm_to_time64(tm); 82 83 /* disable the RTC first */ 84 regmap_update_bits(bbnsm->regmap, BBNSM_CTRL, RTC_EN_MSK, 0); 85 86 /* write the 32bit sec time to 47 bit timer counter, leaving 15 LSBs blank */ 87 regmap_write(bbnsm->regmap, BBNSM_RTC_LS, time << CNTR_TO_SECS_SH); 88 regmap_write(bbnsm->regmap, BBNSM_RTC_MS, time >> (32 - CNTR_TO_SECS_SH)); 89 90 /* Enable the RTC again */ 91 regmap_update_bits(bbnsm->regmap, BBNSM_CTRL, RTC_EN_MSK, RTC_EN); 92 93 return 0; 94 } 95 96 static int bbnsm_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 97 { 98 struct bbnsm_rtc *bbnsm = dev_get_drvdata(dev); 99 u32 bbnsm_events, bbnsm_ta; 100 101 regmap_read(bbnsm->regmap, BBNSM_TA, &bbnsm_ta); 102 rtc_time64_to_tm(bbnsm_ta, &alrm->time); 103 104 regmap_read(bbnsm->regmap, BBNSM_EVENTS, &bbnsm_events); 105 alrm->pending = (bbnsm_events & BBNSM_EVENT_TA) ? 1 : 0; 106 107 return 0; 108 } 109 110 static int bbnsm_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) 111 { 112 struct bbnsm_rtc *bbnsm = dev_get_drvdata(dev); 113 114 /* enable the alarm event */ 115 regmap_update_bits(bbnsm->regmap, BBNSM_CTRL, TA_EN_MSK, enable ? TA_EN : TA_DIS); 116 /* enable the alarm interrupt */ 117 regmap_update_bits(bbnsm->regmap, BBNSM_INT_EN, TA_EN_MSK, enable ? TA_EN : TA_DIS); 118 119 return 0; 120 } 121 122 static int bbnsm_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 123 { 124 struct bbnsm_rtc *bbnsm = dev_get_drvdata(dev); 125 unsigned long time = rtc_tm_to_time64(&alrm->time); 126 127 /* disable the alarm */ 128 regmap_update_bits(bbnsm->regmap, BBNSM_CTRL, TA_EN, TA_EN); 129 130 /* write the seconds to TA */ 131 regmap_write(bbnsm->regmap, BBNSM_TA, time); 132 133 return bbnsm_rtc_alarm_irq_enable(dev, alrm->enabled); 134 } 135 136 static const struct rtc_class_ops bbnsm_rtc_ops = { 137 .read_time = bbnsm_rtc_read_time, 138 .set_time = bbnsm_rtc_set_time, 139 .read_alarm = bbnsm_rtc_read_alarm, 140 .set_alarm = bbnsm_rtc_set_alarm, 141 .alarm_irq_enable = bbnsm_rtc_alarm_irq_enable, 142 }; 143 144 static irqreturn_t bbnsm_rtc_irq_handler(int irq, void *dev_id) 145 { 146 struct device *dev = dev_id; 147 struct bbnsm_rtc *bbnsm = dev_get_drvdata(dev); 148 u32 val; 149 150 regmap_read(bbnsm->regmap, BBNSM_EVENTS, &val); 151 if (val & BBNSM_EVENT_TA) { 152 bbnsm_rtc_alarm_irq_enable(dev, false); 153 /* clear the alarm event */ 154 regmap_write_bits(bbnsm->regmap, BBNSM_EVENTS, TA_EN_MSK, BBNSM_EVENT_TA); 155 rtc_update_irq(bbnsm->rtc, 1, RTC_AF | RTC_IRQF); 156 157 return IRQ_HANDLED; 158 } 159 160 return IRQ_NONE; 161 } 162 163 static int bbnsm_rtc_probe(struct platform_device *pdev) 164 { 165 struct device_node *np = pdev->dev.of_node; 166 struct bbnsm_rtc *bbnsm; 167 int ret; 168 169 bbnsm = devm_kzalloc(&pdev->dev, sizeof(*bbnsm), GFP_KERNEL); 170 if (!bbnsm) 171 return -ENOMEM; 172 173 bbnsm->rtc = devm_rtc_allocate_device(&pdev->dev); 174 if (IS_ERR(bbnsm->rtc)) 175 return PTR_ERR(bbnsm->rtc); 176 177 bbnsm->regmap = syscon_node_to_regmap(np->parent); 178 if (IS_ERR(bbnsm->regmap)) { 179 dev_dbg(&pdev->dev, "bbnsm get regmap failed\n"); 180 return PTR_ERR(bbnsm->regmap); 181 } 182 183 bbnsm->irq = platform_get_irq(pdev, 0); 184 if (bbnsm->irq < 0) 185 return bbnsm->irq; 186 187 platform_set_drvdata(pdev, bbnsm); 188 189 /* clear all the pending events */ 190 regmap_write(bbnsm->regmap, BBNSM_EVENTS, 0x7A); 191 192 device_init_wakeup(&pdev->dev, true); 193 dev_pm_set_wake_irq(&pdev->dev, bbnsm->irq); 194 195 ret = devm_request_irq(&pdev->dev, bbnsm->irq, bbnsm_rtc_irq_handler, 196 IRQF_SHARED, "rtc alarm", &pdev->dev); 197 if (ret) { 198 dev_err(&pdev->dev, "failed to request irq %d: %d\n", 199 bbnsm->irq, ret); 200 return ret; 201 } 202 203 bbnsm->rtc->ops = &bbnsm_rtc_ops; 204 bbnsm->rtc->range_max = U32_MAX; 205 206 return devm_rtc_register_device(bbnsm->rtc); 207 } 208 209 static const struct of_device_id bbnsm_dt_ids[] = { 210 { .compatible = "nxp,imx93-bbnsm-rtc" }, 211 { /* sentinel */ }, 212 }; 213 MODULE_DEVICE_TABLE(of, bbnsm_dt_ids); 214 215 static struct platform_driver bbnsm_rtc_driver = { 216 .driver = { 217 .name = "bbnsm_rtc", 218 .of_match_table = bbnsm_dt_ids, 219 }, 220 .probe = bbnsm_rtc_probe, 221 }; 222 module_platform_driver(bbnsm_rtc_driver); 223 224 MODULE_AUTHOR("Jacky Bai <ping.bai@nxp.com>"); 225 MODULE_DESCRIPTION("NXP BBNSM RTC Driver"); 226 MODULE_LICENSE("GPL"); 227