brintos

brintos / linux-shallow public Read only

0
0
Text · 12.2 KiB · c32fba5 Raw
554 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * pm8xxx RTC driver4 *5 * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.6 * Copyright (c) 2023, Linaro Limited7 */8#include <linux/of.h>9#include <linux/module.h>10#include <linux/nvmem-consumer.h>11#include <linux/init.h>12#include <linux/rtc.h>13#include <linux/platform_device.h>14#include <linux/pm.h>15#include <linux/pm_wakeirq.h>16#include <linux/regmap.h>17#include <linux/slab.h>18#include <linux/spinlock.h>19 20#include <linux/unaligned.h>21 22/* RTC_CTRL register bit fields */23#define PM8xxx_RTC_ENABLE		BIT(7)24#define PM8xxx_RTC_ALARM_CLEAR		BIT(0)25#define PM8xxx_RTC_ALARM_ENABLE		BIT(7)26 27#define NUM_8_BIT_RTC_REGS		0x428 29/**30 * struct pm8xxx_rtc_regs - describe RTC registers per PMIC versions31 * @ctrl:		address of control register32 * @write:		base address of write registers33 * @read:		base address of read registers34 * @alarm_ctrl:		address of alarm control register35 * @alarm_ctrl2:	address of alarm control2 register36 * @alarm_rw:		base address of alarm read-write registers37 * @alarm_en:		alarm enable mask38 */39struct pm8xxx_rtc_regs {40	unsigned int ctrl;41	unsigned int write;42	unsigned int read;43	unsigned int alarm_ctrl;44	unsigned int alarm_ctrl2;45	unsigned int alarm_rw;46	unsigned int alarm_en;47};48 49/**50 * struct pm8xxx_rtc -  RTC driver internal structure51 * @rtc:		RTC device52 * @regmap:		regmap used to access registers53 * @allow_set_time:	whether the time can be set54 * @alarm_irq:		alarm irq number55 * @regs:		register description56 * @dev:		device structure57 * @nvmem_cell:		nvmem cell for offset58 * @offset:		offset from epoch in seconds59 */60struct pm8xxx_rtc {61	struct rtc_device *rtc;62	struct regmap *regmap;63	bool allow_set_time;64	int alarm_irq;65	const struct pm8xxx_rtc_regs *regs;66	struct device *dev;67	struct nvmem_cell *nvmem_cell;68	u32 offset;69};70 71static int pm8xxx_rtc_read_nvmem_offset(struct pm8xxx_rtc *rtc_dd)72{73	size_t len;74	void *buf;75	int rc;76 77	buf = nvmem_cell_read(rtc_dd->nvmem_cell, &len);78	if (IS_ERR(buf)) {79		rc = PTR_ERR(buf);80		dev_dbg(rtc_dd->dev, "failed to read nvmem offset: %d\n", rc);81		return rc;82	}83 84	if (len != sizeof(u32)) {85		dev_dbg(rtc_dd->dev, "unexpected nvmem cell size %zu\n", len);86		kfree(buf);87		return -EINVAL;88	}89 90	rtc_dd->offset = get_unaligned_le32(buf);91 92	kfree(buf);93 94	return 0;95}96 97static int pm8xxx_rtc_write_nvmem_offset(struct pm8xxx_rtc *rtc_dd, u32 offset)98{99	u8 buf[sizeof(u32)];100	int rc;101 102	put_unaligned_le32(offset, buf);103 104	rc = nvmem_cell_write(rtc_dd->nvmem_cell, buf, sizeof(buf));105	if (rc < 0) {106		dev_dbg(rtc_dd->dev, "failed to write nvmem offset: %d\n", rc);107		return rc;108	}109 110	return 0;111}112 113static int pm8xxx_rtc_read_offset(struct pm8xxx_rtc *rtc_dd)114{115	if (!rtc_dd->nvmem_cell)116		return 0;117 118	return pm8xxx_rtc_read_nvmem_offset(rtc_dd);119}120 121static int pm8xxx_rtc_read_raw(struct pm8xxx_rtc *rtc_dd, u32 *secs)122{123	const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;124	u8 value[NUM_8_BIT_RTC_REGS];125	unsigned int reg;126	int rc;127 128	rc = regmap_bulk_read(rtc_dd->regmap, regs->read, value, sizeof(value));129	if (rc)130		return rc;131 132	/*133	 * Read the LSB again and check if there has been a carry over.134	 * If there has, redo the read operation.135	 */136	rc = regmap_read(rtc_dd->regmap, regs->read, &reg);137	if (rc < 0)138		return rc;139 140	if (reg < value[0]) {141		rc = regmap_bulk_read(rtc_dd->regmap, regs->read, value,142				      sizeof(value));143		if (rc)144			return rc;145	}146 147	*secs = get_unaligned_le32(value);148 149	return 0;150}151 152static int pm8xxx_rtc_update_offset(struct pm8xxx_rtc *rtc_dd, u32 secs)153{154	u32 raw_secs;155	u32 offset;156	int rc;157 158	if (!rtc_dd->nvmem_cell)159		return -ENODEV;160 161	rc = pm8xxx_rtc_read_raw(rtc_dd, &raw_secs);162	if (rc)163		return rc;164 165	offset = secs - raw_secs;166 167	if (offset == rtc_dd->offset)168		return 0;169 170	rc = pm8xxx_rtc_write_nvmem_offset(rtc_dd, offset);171	if (rc)172		return rc;173 174	rtc_dd->offset = offset;175 176	return 0;177}178 179/*180 * Steps to write the RTC registers.181 * 1. Disable alarm if enabled.182 * 2. Disable rtc if enabled.183 * 3. Write 0x00 to LSB.184 * 4. Write Byte[1], Byte[2], Byte[3] then Byte[0].185 * 5. Enable rtc if disabled in step 2.186 * 6. Enable alarm if disabled in step 1.187 */188static int __pm8xxx_rtc_set_time(struct pm8xxx_rtc *rtc_dd, u32 secs)189{190	const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;191	u8 value[NUM_8_BIT_RTC_REGS];192	bool alarm_enabled;193	int rc;194 195	put_unaligned_le32(secs, value);196 197	rc = regmap_update_bits_check(rtc_dd->regmap, regs->alarm_ctrl,198				      regs->alarm_en, 0, &alarm_enabled);199	if (rc)200		return rc;201 202	/* Disable RTC */203	rc = regmap_update_bits(rtc_dd->regmap, regs->ctrl, PM8xxx_RTC_ENABLE, 0);204	if (rc)205		return rc;206 207	/* Write 0 to Byte[0] */208	rc = regmap_write(rtc_dd->regmap, regs->write, 0);209	if (rc)210		return rc;211 212	/* Write Byte[1], Byte[2], Byte[3] */213	rc = regmap_bulk_write(rtc_dd->regmap, regs->write + 1,214			       &value[1], sizeof(value) - 1);215	if (rc)216		return rc;217 218	/* Write Byte[0] */219	rc = regmap_write(rtc_dd->regmap, regs->write, value[0]);220	if (rc)221		return rc;222 223	/* Enable RTC */224	rc = regmap_update_bits(rtc_dd->regmap, regs->ctrl, PM8xxx_RTC_ENABLE,225				PM8xxx_RTC_ENABLE);226	if (rc)227		return rc;228 229	if (alarm_enabled) {230		rc = regmap_update_bits(rtc_dd->regmap, regs->alarm_ctrl,231					regs->alarm_en, regs->alarm_en);232		if (rc)233			return rc;234	}235 236	return 0;237}238 239static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)240{241	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);242	u32 secs;243	int rc;244 245	secs = rtc_tm_to_time64(tm);246 247	if (rtc_dd->allow_set_time)248		rc = __pm8xxx_rtc_set_time(rtc_dd, secs);249	else250		rc = pm8xxx_rtc_update_offset(rtc_dd, secs);251 252	if (rc)253		return rc;254 255	dev_dbg(dev, "set time: %ptRd %ptRt (%u + %u)\n", tm, tm,256			secs - rtc_dd->offset, rtc_dd->offset);257	return 0;258}259 260static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)261{262	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);263	u32 secs;264	int rc;265 266	rc = pm8xxx_rtc_read_raw(rtc_dd, &secs);267	if (rc)268		return rc;269 270	secs += rtc_dd->offset;271	rtc_time64_to_tm(secs, tm);272 273	dev_dbg(dev, "read time: %ptRd %ptRt (%u + %u)\n", tm, tm,274			secs - rtc_dd->offset, rtc_dd->offset);275	return 0;276}277 278static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)279{280	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);281	const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;282	u8 value[NUM_8_BIT_RTC_REGS];283	u32 secs;284	int rc;285 286	secs = rtc_tm_to_time64(&alarm->time);287	secs -= rtc_dd->offset;288	put_unaligned_le32(secs, value);289 290	rc = regmap_update_bits(rtc_dd->regmap, regs->alarm_ctrl,291				regs->alarm_en, 0);292	if (rc)293		return rc;294 295	rc = regmap_bulk_write(rtc_dd->regmap, regs->alarm_rw, value,296			       sizeof(value));297	if (rc)298		return rc;299 300	if (alarm->enabled) {301		rc = regmap_update_bits(rtc_dd->regmap, regs->alarm_ctrl,302					regs->alarm_en, regs->alarm_en);303		if (rc)304			return rc;305	}306 307	dev_dbg(dev, "set alarm: %ptRd %ptRt\n", &alarm->time, &alarm->time);308 309	return 0;310}311 312static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)313{314	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);315	const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;316	u8 value[NUM_8_BIT_RTC_REGS];317	unsigned int ctrl_reg;318	u32 secs;319	int rc;320 321	rc = regmap_bulk_read(rtc_dd->regmap, regs->alarm_rw, value,322			      sizeof(value));323	if (rc)324		return rc;325 326	secs = get_unaligned_le32(value);327	secs += rtc_dd->offset;328	rtc_time64_to_tm(secs, &alarm->time);329 330	rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg);331	if (rc)332		return rc;333 334	alarm->enabled = !!(ctrl_reg & PM8xxx_RTC_ALARM_ENABLE);335 336	dev_dbg(dev, "read alarm: %ptRd %ptRt\n", &alarm->time, &alarm->time);337 338	return 0;339}340 341static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)342{343	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);344	const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;345	u8 value[NUM_8_BIT_RTC_REGS] = {0};346	unsigned int val;347	int rc;348 349	if (enable)350		val = regs->alarm_en;351	else352		val = 0;353 354	rc = regmap_update_bits(rtc_dd->regmap, regs->alarm_ctrl,355				regs->alarm_en, val);356	if (rc)357		return rc;358 359	/* Clear alarm register */360	if (!enable) {361		rc = regmap_bulk_write(rtc_dd->regmap, regs->alarm_rw, value,362				       sizeof(value));363		if (rc)364			return rc;365	}366 367	return 0;368}369 370static const struct rtc_class_ops pm8xxx_rtc_ops = {371	.read_time	= pm8xxx_rtc_read_time,372	.set_time	= pm8xxx_rtc_set_time,373	.set_alarm	= pm8xxx_rtc_set_alarm,374	.read_alarm	= pm8xxx_rtc_read_alarm,375	.alarm_irq_enable = pm8xxx_rtc_alarm_irq_enable,376};377 378static irqreturn_t pm8xxx_alarm_trigger(int irq, void *dev_id)379{380	struct pm8xxx_rtc *rtc_dd = dev_id;381	const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;382	int rc;383 384	rtc_update_irq(rtc_dd->rtc, 1, RTC_IRQF | RTC_AF);385 386	/* Disable alarm */387	rc = regmap_update_bits(rtc_dd->regmap, regs->alarm_ctrl,388				regs->alarm_en, 0);389	if (rc)390		return IRQ_NONE;391 392	/* Clear alarm status */393	rc = regmap_update_bits(rtc_dd->regmap, regs->alarm_ctrl2,394				PM8xxx_RTC_ALARM_CLEAR, 0);395	if (rc)396		return IRQ_NONE;397 398	return IRQ_HANDLED;399}400 401static int pm8xxx_rtc_enable(struct pm8xxx_rtc *rtc_dd)402{403	const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;404 405	return regmap_update_bits(rtc_dd->regmap, regs->ctrl, PM8xxx_RTC_ENABLE,406				  PM8xxx_RTC_ENABLE);407}408 409static const struct pm8xxx_rtc_regs pm8921_regs = {410	.ctrl		= 0x11d,411	.write		= 0x11f,412	.read		= 0x123,413	.alarm_rw	= 0x127,414	.alarm_ctrl	= 0x11d,415	.alarm_ctrl2	= 0x11e,416	.alarm_en	= BIT(1),417};418 419static const struct pm8xxx_rtc_regs pm8058_regs = {420	.ctrl		= 0x1e8,421	.write		= 0x1ea,422	.read		= 0x1ee,423	.alarm_rw	= 0x1f2,424	.alarm_ctrl	= 0x1e8,425	.alarm_ctrl2	= 0x1e9,426	.alarm_en	= BIT(1),427};428 429static const struct pm8xxx_rtc_regs pm8941_regs = {430	.ctrl		= 0x6046,431	.write		= 0x6040,432	.read		= 0x6048,433	.alarm_rw	= 0x6140,434	.alarm_ctrl	= 0x6146,435	.alarm_ctrl2	= 0x6148,436	.alarm_en	= BIT(7),437};438 439static const struct pm8xxx_rtc_regs pmk8350_regs = {440	.ctrl		= 0x6146,441	.write		= 0x6140,442	.read		= 0x6148,443	.alarm_rw	= 0x6240,444	.alarm_ctrl	= 0x6246,445	.alarm_ctrl2	= 0x6248,446	.alarm_en	= BIT(7),447};448 449static const struct of_device_id pm8xxx_id_table[] = {450	{ .compatible = "qcom,pm8921-rtc", .data = &pm8921_regs },451	{ .compatible = "qcom,pm8058-rtc", .data = &pm8058_regs },452	{ .compatible = "qcom,pm8941-rtc", .data = &pm8941_regs },453	{ .compatible = "qcom,pmk8350-rtc", .data = &pmk8350_regs },454	{ },455};456MODULE_DEVICE_TABLE(of, pm8xxx_id_table);457 458static int pm8xxx_rtc_probe(struct platform_device *pdev)459{460	const struct of_device_id *match;461	struct pm8xxx_rtc *rtc_dd;462	int rc;463 464	match = of_match_node(pm8xxx_id_table, pdev->dev.of_node);465	if (!match)466		return -ENXIO;467 468	rtc_dd = devm_kzalloc(&pdev->dev, sizeof(*rtc_dd), GFP_KERNEL);469	if (rtc_dd == NULL)470		return -ENOMEM;471 472	rtc_dd->regmap = dev_get_regmap(pdev->dev.parent, NULL);473	if (!rtc_dd->regmap)474		return -ENXIO;475 476	rtc_dd->alarm_irq = platform_get_irq(pdev, 0);477	if (rtc_dd->alarm_irq < 0)478		return -ENXIO;479 480	rtc_dd->allow_set_time = of_property_read_bool(pdev->dev.of_node,481						      "allow-set-time");482 483	rtc_dd->nvmem_cell = devm_nvmem_cell_get(&pdev->dev, "offset");484	if (IS_ERR(rtc_dd->nvmem_cell)) {485		rc = PTR_ERR(rtc_dd->nvmem_cell);486		if (rc != -ENOENT)487			return rc;488		rtc_dd->nvmem_cell = NULL;489	}490 491	rtc_dd->regs = match->data;492	rtc_dd->dev = &pdev->dev;493 494	if (!rtc_dd->allow_set_time) {495		rc = pm8xxx_rtc_read_offset(rtc_dd);496		if (rc)497			return rc;498	}499 500	rc = pm8xxx_rtc_enable(rtc_dd);501	if (rc)502		return rc;503 504	platform_set_drvdata(pdev, rtc_dd);505 506	device_init_wakeup(&pdev->dev, 1);507 508	rtc_dd->rtc = devm_rtc_allocate_device(&pdev->dev);509	if (IS_ERR(rtc_dd->rtc))510		return PTR_ERR(rtc_dd->rtc);511 512	rtc_dd->rtc->ops = &pm8xxx_rtc_ops;513	rtc_dd->rtc->range_max = U32_MAX;514 515	rc = devm_request_any_context_irq(&pdev->dev, rtc_dd->alarm_irq,516					  pm8xxx_alarm_trigger,517					  IRQF_TRIGGER_RISING,518					  "pm8xxx_rtc_alarm", rtc_dd);519	if (rc < 0)520		return rc;521 522	rc = devm_rtc_register_device(rtc_dd->rtc);523	if (rc)524		return rc;525 526	rc = dev_pm_set_wake_irq(&pdev->dev, rtc_dd->alarm_irq);527	if (rc)528		return rc;529 530	return 0;531}532 533static void pm8xxx_remove(struct platform_device *pdev)534{535	dev_pm_clear_wake_irq(&pdev->dev);536}537 538static struct platform_driver pm8xxx_rtc_driver = {539	.probe		= pm8xxx_rtc_probe,540	.remove_new	= pm8xxx_remove,541	.driver	= {542		.name		= "rtc-pm8xxx",543		.of_match_table	= pm8xxx_id_table,544	},545};546 547module_platform_driver(pm8xxx_rtc_driver);548 549MODULE_ALIAS("platform:rtc-pm8xxx");550MODULE_DESCRIPTION("PMIC8xxx RTC driver");551MODULE_LICENSE("GPL v2");552MODULE_AUTHOR("Anirudh Ghayal <aghayal@codeaurora.org>");553MODULE_AUTHOR("Johan Hovold <johan@kernel.org>");554