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 <chenhuacai@kernel.org>.
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()
125 spin_lock(&priv->lock); in loongson_rtc_handler()
127 writel(readl(priv->pm_base + PM1_EN_REG) & ~RTC_EN, in loongson_rtc_handler()
128 priv->pm_base + PM1_EN_REG); in loongson_rtc_handler()
131 writel(RTC_STS, priv->pm_base + PM1_STS_REG); in loongson_rtc_handler()
132 spin_unlock(&priv->lock); in loongson_rtc_handler()
138 return regmap_write(priv->regmap, TOY_MATCH0_REG, 0); in loongson_rtc_handler()
145 if (priv->config->flags & LS1C_RTC_CTRL_WORKAROUND) in loongson_rtc_set_enabled()
149 return regmap_update_bits(priv->regmap, RTC_CTRL_REG, TOY_ENABLE_MASK, in loongson_rtc_set_enabled()
159 if (priv->config->flags & LS1C_RTC_CTRL_WORKAROUND) in loongson_rtc_get_enabled()
162 ret = regmap_read(priv->regmap, RTC_CTRL_REG, &ctrl_data); in loongson_rtc_get_enabled()
172 u32 rtc_data[2]; in loongson_rtc_read_time()
176 return -EINVAL; in loongson_rtc_read_time()
178 ret = regmap_bulk_read(priv->regmap, TOY_READ0_REG, rtc_data, in loongson_rtc_read_time()
183 tm->tm_sec = FIELD_GET(TOY_SEC, rtc_data[0]); in loongson_rtc_read_time()
184 tm->tm_min = FIELD_GET(TOY_MIN, rtc_data[0]); in loongson_rtc_read_time()
185 tm->tm_hour = FIELD_GET(TOY_HOUR, rtc_data[0]); in loongson_rtc_read_time()
186 tm->tm_mday = FIELD_GET(TOY_DAY, rtc_data[0]); in loongson_rtc_read_time()
187 tm->tm_mon = FIELD_GET(TOY_MON, rtc_data[0]) - 1; in loongson_rtc_read_time()
188 tm->tm_year = rtc_data[1]; in loongson_rtc_read_time()
191 priv->fix_year = tm->tm_year / 64 * 64; in loongson_rtc_read_time()
198 u32 rtc_data[2]; in loongson_rtc_set_time()
201 rtc_data[0] = FIELD_PREP(TOY_SEC, tm->tm_sec) in loongson_rtc_set_time()
202 | FIELD_PREP(TOY_MIN, tm->tm_min) in loongson_rtc_set_time()
203 | FIELD_PREP(TOY_HOUR, tm->tm_hour) in loongson_rtc_set_time()
204 | FIELD_PREP(TOY_DAY, tm->tm_mday) in loongson_rtc_set_time()
205 | FIELD_PREP(TOY_MON, tm->tm_mon + 1); in loongson_rtc_set_time()
206 rtc_data[1] = tm->tm_year; in loongson_rtc_set_time()
208 ret = regmap_bulk_write(priv->regmap, TOY_WRITE0_REG, rtc_data, in loongson_rtc_set_time()
222 ret = regmap_read(priv->regmap, TOY_MATCH0_REG, &alarm_data); in loongson_rtc_read_alarm()
226 alrm->time.tm_sec = FIELD_GET(TOY_MATCH_SEC, alarm_data); in loongson_rtc_read_alarm()
227 alrm->time.tm_min = FIELD_GET(TOY_MATCH_MIN, alarm_data); in loongson_rtc_read_alarm()
228 alrm->time.tm_hour = FIELD_GET(TOY_MATCH_HOUR, alarm_data); in loongson_rtc_read_alarm()
229 alrm->time.tm_mday = FIELD_GET(TOY_MATCH_DAY, alarm_data); in loongson_rtc_read_alarm()
230 alrm->time.tm_mon = FIELD_GET(TOY_MATCH_MON, alarm_data) - 1; in loongson_rtc_read_alarm()
242 alrm->time.tm_year = FIELD_GET(TOY_MATCH_YEAR, alarm_data) + priv->fix_year; in loongson_rtc_read_alarm()
244 alrm->enabled = !!(readl(priv->pm_base + PM1_EN_REG) & RTC_EN); in loongson_rtc_read_alarm()
253 spin_lock(&priv->lock); in loongson_rtc_alarm_irq_enable()
254 val = readl(priv->pm_base + PM1_EN_REG); in loongson_rtc_alarm_irq_enable()
257 priv->pm_base + PM1_EN_REG); in loongson_rtc_alarm_irq_enable()
258 spin_unlock(&priv->lock); in loongson_rtc_alarm_irq_enable()
269 alarm_data = FIELD_PREP(TOY_MATCH_SEC, alrm->time.tm_sec) in loongson_rtc_set_alarm()
270 | FIELD_PREP(TOY_MATCH_MIN, alrm->time.tm_min) in loongson_rtc_set_alarm()
271 | FIELD_PREP(TOY_MATCH_HOUR, alrm->time.tm_hour) in loongson_rtc_set_alarm()
272 | FIELD_PREP(TOY_MATCH_DAY, alrm->time.tm_mday) in loongson_rtc_set_alarm()
273 | FIELD_PREP(TOY_MATCH_MON, alrm->time.tm_mon + 1) in loongson_rtc_set_alarm()
274 | FIELD_PREP(TOY_MATCH_YEAR, alrm->time.tm_year - priv->fix_year); in loongson_rtc_set_alarm()
276 ret = regmap_write(priv->regmap, TOY_MATCH0_REG, alarm_data); in loongson_rtc_set_alarm()
280 return loongson_rtc_alarm_irq_enable(dev, alrm->enabled); in loongson_rtc_set_alarm()
296 struct device *dev = &pdev->dev; in loongson_rtc_probe()
300 return -ENOMEM; in loongson_rtc_probe()
307 priv->regmap = devm_regmap_init_mmio(dev, regs, in loongson_rtc_probe()
309 if (IS_ERR(priv->regmap)) in loongson_rtc_probe()
310 return dev_err_probe(dev, PTR_ERR(priv->regmap), in loongson_rtc_probe()
313 priv->config = device_get_match_data(dev); in loongson_rtc_probe()
314 spin_lock_init(&priv->lock); in loongson_rtc_probe()
317 priv->rtcdev = devm_rtc_allocate_device(dev); in loongson_rtc_probe()
318 if (IS_ERR(priv->rtcdev)) in loongson_rtc_probe()
319 return dev_err_probe(dev, PTR_ERR(priv->rtcdev), in loongson_rtc_probe()
326 0, "loongson-alarm", priv); in loongson_rtc_probe()
331 priv->pm_base = regs - priv->config->pm_offset; in loongson_rtc_probe()
338 /* Loongson-1C RTC does not support alarm */ in loongson_rtc_probe()
339 clear_bit(RTC_FEATURE_ALARM, priv->rtcdev->features); in loongson_rtc_probe()
342 /* Loongson RTC does not support UIE */ in loongson_rtc_probe()
343 clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, priv->rtcdev->features); in loongson_rtc_probe()
344 priv->rtcdev->ops = &loongson_rtc_ops; in loongson_rtc_probe()
345 priv->rtcdev->range_min = RTC_TIMESTAMP_BEGIN_2000; in loongson_rtc_probe()
346 priv->rtcdev->range_max = RTC_TIMESTAMP_END_2099; in loongson_rtc_probe()
348 return devm_rtc_register_device(priv->rtcdev); in loongson_rtc_probe()
353 struct device *dev = &pdev->dev; in loongson_rtc_remove()
356 if (!test_bit(RTC_FEATURE_ALARM, priv->rtcdev->features)) in loongson_rtc_remove()
368 { .compatible = "loongson,ls1b-rtc", .data = &ls1b_rtc_config },
369 { .compatible = "loongson,ls1c-rtc", .data = &ls1c_rtc_config },
370 { .compatible = "loongson,ls7a-rtc", .data = &generic_rtc_config },
371 { .compatible = "loongson,ls2k1000-rtc", .data = &ls2k1000_rtc_config },
386 .name = "loongson-rtc",
393 MODULE_DESCRIPTION("Loongson RTC driver");
394 MODULE_AUTHOR("Binbin Zhou <zhoubinbin@loongson.cn>");