Lines Matching +full:loongson +full:- +full:2 +full:k

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Loongson RTC driver
5 * Maintained out-of-tree by Huacai Chen <[email protected]>.
7 * Binbin Zhou <zhoubinbin@loongson.cn>
20 #define TOY_WRITE0_REG 0x24 /* TOY low 32-bits value (write-only) */
21 #define TOY_WRITE1_REG 0x28 /* TOY high 32-bits value (write-only) */
22 #define TOY_READ0_REG 0x2c /* TOY low 32-bits value (read-only) */
23 #define TOY_READ1_REG 0x30 /* TOY high 32-bits value (read-only) */
26 #define TOY_MATCH2_REG 0x3c /* TOY timing interrupt 2 */
31 #define RTC_WRITE0_REG 0x64 /* RTC counters value (write-only) */
32 #define RTC_READ0_REG 0x68 /* RTC counters value (read-only) */
35 #define RTC_MATCH2_REG 0x74 /* RTC timing interrupt 2 */
45 /* bitmask of TOY_MATCH0/1/2_REG */
56 #define OSC_ENABLE BIT(8) /* 1: 32.768k crystal enable */
66 * According to the LS1C manual, RTC_CTRL and alarm-related registers are not defined.
116 rtc_update_irq(priv->rtcdev, 1, RTC_AF | RTC_IRQF); in loongson_rtc_isr()
122 regmap_write(priv->regmap, TOY_MATCH0_REG, 0); in loongson_rtc_isr()
132 spin_lock(&priv->lock); in loongson_rtc_handler()
134 writel(readl(priv->pm_base + PM1_EN_REG) & ~RTC_EN, in loongson_rtc_handler()
135 priv->pm_base + PM1_EN_REG); in loongson_rtc_handler()
138 writel(RTC_STS, priv->pm_base + PM1_STS_REG); in loongson_rtc_handler()
139 spin_unlock(&priv->lock); in loongson_rtc_handler()
148 if (priv->config->flags & LS1C_RTC_CTRL_WORKAROUND) in loongson_rtc_set_enabled()
152 return regmap_update_bits(priv->regmap, RTC_CTRL_REG, TOY_ENABLE_MASK, in loongson_rtc_set_enabled()
162 if (priv->config->flags & LS1C_RTC_CTRL_WORKAROUND) in loongson_rtc_get_enabled()
165 ret = regmap_read(priv->regmap, RTC_CTRL_REG, &ctrl_data); in loongson_rtc_get_enabled()
175 u32 rtc_data[2]; in loongson_rtc_read_time()
179 return -EINVAL; in loongson_rtc_read_time()
181 ret = regmap_bulk_read(priv->regmap, TOY_READ0_REG, rtc_data, in loongson_rtc_read_time()
186 tm->tm_sec = FIELD_GET(TOY_SEC, rtc_data[0]); in loongson_rtc_read_time()
187 tm->tm_min = FIELD_GET(TOY_MIN, rtc_data[0]); in loongson_rtc_read_time()
188 tm->tm_hour = FIELD_GET(TOY_HOUR, rtc_data[0]); in loongson_rtc_read_time()
189 tm->tm_mday = FIELD_GET(TOY_DAY, rtc_data[0]); in loongson_rtc_read_time()
190 tm->tm_mon = FIELD_GET(TOY_MON, rtc_data[0]) - 1; in loongson_rtc_read_time()
191 tm->tm_year = rtc_data[1]; in loongson_rtc_read_time()
194 priv->fix_year = tm->tm_year / 64 * 64; in loongson_rtc_read_time()
201 u32 rtc_data[2]; in loongson_rtc_set_time()
204 rtc_data[0] = FIELD_PREP(TOY_SEC, tm->tm_sec) in loongson_rtc_set_time()
205 | FIELD_PREP(TOY_MIN, tm->tm_min) in loongson_rtc_set_time()
206 | FIELD_PREP(TOY_HOUR, tm->tm_hour) in loongson_rtc_set_time()
207 | FIELD_PREP(TOY_DAY, tm->tm_mday) in loongson_rtc_set_time()
208 | FIELD_PREP(TOY_MON, tm->tm_mon + 1); in loongson_rtc_set_time()
209 rtc_data[1] = tm->tm_year; in loongson_rtc_set_time()
211 ret = regmap_bulk_write(priv->regmap, TOY_WRITE0_REG, rtc_data, in loongson_rtc_set_time()
225 ret = regmap_read(priv->regmap, TOY_MATCH0_REG, &alarm_data); in loongson_rtc_read_alarm()
229 alrm->time.tm_sec = FIELD_GET(TOY_MATCH_SEC, alarm_data); in loongson_rtc_read_alarm()
230 alrm->time.tm_min = FIELD_GET(TOY_MATCH_MIN, alarm_data); in loongson_rtc_read_alarm()
231 alrm->time.tm_hour = FIELD_GET(TOY_MATCH_HOUR, alarm_data); in loongson_rtc_read_alarm()
232 alrm->time.tm_mday = FIELD_GET(TOY_MATCH_DAY, alarm_data); in loongson_rtc_read_alarm()
233 alrm->time.tm_mon = FIELD_GET(TOY_MATCH_MON, alarm_data) - 1; in loongson_rtc_read_alarm()
245 alrm->time.tm_year = FIELD_GET(TOY_MATCH_YEAR, alarm_data) + priv->fix_year; in loongson_rtc_read_alarm()
247 alrm->enabled = !!(readl(priv->pm_base + PM1_EN_REG) & RTC_EN); in loongson_rtc_read_alarm()
256 spin_lock(&priv->lock); in loongson_rtc_alarm_irq_enable()
257 val = readl(priv->pm_base + PM1_EN_REG); in loongson_rtc_alarm_irq_enable()
260 priv->pm_base + PM1_EN_REG); in loongson_rtc_alarm_irq_enable()
261 spin_unlock(&priv->lock); in loongson_rtc_alarm_irq_enable()
272 alarm_data = FIELD_PREP(TOY_MATCH_SEC, alrm->time.tm_sec) in loongson_rtc_set_alarm()
273 | FIELD_PREP(TOY_MATCH_MIN, alrm->time.tm_min) in loongson_rtc_set_alarm()
274 | FIELD_PREP(TOY_MATCH_HOUR, alrm->time.tm_hour) in loongson_rtc_set_alarm()
275 | FIELD_PREP(TOY_MATCH_DAY, alrm->time.tm_mday) in loongson_rtc_set_alarm()
276 | FIELD_PREP(TOY_MATCH_MON, alrm->time.tm_mon + 1) in loongson_rtc_set_alarm()
277 | FIELD_PREP(TOY_MATCH_YEAR, alrm->time.tm_year - priv->fix_year); in loongson_rtc_set_alarm()
279 ret = regmap_write(priv->regmap, TOY_MATCH0_REG, alarm_data); in loongson_rtc_set_alarm()
283 return loongson_rtc_alarm_irq_enable(dev, alrm->enabled); in loongson_rtc_set_alarm()
299 struct device *dev = &pdev->dev; in loongson_rtc_probe()
303 return -ENOMEM; in loongson_rtc_probe()
310 priv->regmap = devm_regmap_init_mmio(dev, regs, in loongson_rtc_probe()
312 if (IS_ERR(priv->regmap)) in loongson_rtc_probe()
313 return dev_err_probe(dev, PTR_ERR(priv->regmap), in loongson_rtc_probe()
316 priv->config = device_get_match_data(dev); in loongson_rtc_probe()
317 spin_lock_init(&priv->lock); in loongson_rtc_probe()
320 priv->rtcdev = devm_rtc_allocate_device(dev); in loongson_rtc_probe()
321 if (IS_ERR(priv->rtcdev)) in loongson_rtc_probe()
322 return dev_err_probe(dev, PTR_ERR(priv->rtcdev), in loongson_rtc_probe()
329 0, "loongson-alarm", priv); in loongson_rtc_probe()
334 priv->pm_base = regs - priv->config->pm_offset; in loongson_rtc_probe()
341 /* Loongson-1C RTC does not support alarm */ in loongson_rtc_probe()
342 clear_bit(RTC_FEATURE_ALARM, priv->rtcdev->features); in loongson_rtc_probe()
345 /* Loongson RTC does not support UIE */ in loongson_rtc_probe()
346 clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, priv->rtcdev->features); in loongson_rtc_probe()
347 priv->rtcdev->ops = &loongson_rtc_ops; in loongson_rtc_probe()
348 priv->rtcdev->range_min = RTC_TIMESTAMP_BEGIN_2000; in loongson_rtc_probe()
349 priv->rtcdev->range_max = RTC_TIMESTAMP_END_2099; in loongson_rtc_probe()
351 return devm_rtc_register_device(priv->rtcdev); in loongson_rtc_probe()
356 struct device *dev = &pdev->dev; in loongson_rtc_remove()
359 if (!test_bit(RTC_FEATURE_ALARM, priv->rtcdev->features)) in loongson_rtc_remove()
371 { .compatible = "loongson,ls1b-rtc", .data = &ls1b_rtc_config },
372 { .compatible = "loongson,ls1c-rtc", .data = &ls1c_rtc_config },
373 { .compatible = "loongson,ls7a-rtc", .data = &generic_rtc_config },
374 { .compatible = "loongson,ls2k1000-rtc", .data = &ls2k1000_rtc_config },
389 .name = "loongson-rtc",
396 MODULE_DESCRIPTION("Loongson RTC driver");
397 MODULE_AUTHOR("Binbin Zhou <zhoubinbin@loongson.cn>");