18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * R-Car Generation 2 da9063(L)/da9210 regulator quirk
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Certain Gen2 development boards have an da9063 and one or more da9210
68c2ecf20Sopenharmony_ci * regulators. All of these regulators have their interrupt request lines
78c2ecf20Sopenharmony_ci * tied to the same interrupt pin (IRQ2) on the SoC.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * After cold boot or da9063-induced restart, both the da9063 and da9210 seem
108c2ecf20Sopenharmony_ci * to assert their interrupt request lines.  Hence as soon as one driver
118c2ecf20Sopenharmony_ci * requests this irq, it gets stuck in an interrupt storm, as it only manages
128c2ecf20Sopenharmony_ci * to deassert its own interrupt request line, and the other driver hasn't
138c2ecf20Sopenharmony_ci * installed an interrupt handler yet.
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * To handle this, install a quirk that masks the interrupts in both the
168c2ecf20Sopenharmony_ci * da9063 and da9210.  This quirk has to run after the i2c master driver has
178c2ecf20Sopenharmony_ci * been initialized, but before the i2c slave drivers are initialized.
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * Copyright (C) 2015 Glider bvba
208c2ecf20Sopenharmony_ci */
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include <linux/device.h>
238c2ecf20Sopenharmony_ci#include <linux/i2c.h>
248c2ecf20Sopenharmony_ci#include <linux/init.h>
258c2ecf20Sopenharmony_ci#include <linux/io.h>
268c2ecf20Sopenharmony_ci#include <linux/list.h>
278c2ecf20Sopenharmony_ci#include <linux/notifier.h>
288c2ecf20Sopenharmony_ci#include <linux/of.h>
298c2ecf20Sopenharmony_ci#include <linux/of_irq.h>
308c2ecf20Sopenharmony_ci#include <linux/mfd/da9063/registers.h>
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#define IRQC_BASE		0xe61c0000
338c2ecf20Sopenharmony_ci#define IRQC_MONITOR		0x104	/* IRQn Signal Level Monitor Register */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define REGULATOR_IRQ_MASK	BIT(2)	/* IRQ2, active low */
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci/* start of DA9210 System Control and Event Registers */
388c2ecf20Sopenharmony_ci#define DA9210_REG_MASK_A		0x54
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistruct regulator_quirk {
418c2ecf20Sopenharmony_ci	struct list_head		list;
428c2ecf20Sopenharmony_ci	const struct of_device_id	*id;
438c2ecf20Sopenharmony_ci	struct device_node		*np;
448c2ecf20Sopenharmony_ci	struct of_phandle_args		irq_args;
458c2ecf20Sopenharmony_ci	struct i2c_msg			i2c_msg;
468c2ecf20Sopenharmony_ci	bool				shared;	/* IRQ line is shared */
478c2ecf20Sopenharmony_ci};
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistatic LIST_HEAD(quirk_list);
508c2ecf20Sopenharmony_cistatic void __iomem *irqc;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/* first byte sets the memory pointer, following are consecutive reg values */
538c2ecf20Sopenharmony_cistatic u8 da9063_irq_clr[] = { DA9063_REG_IRQ_MASK_A, 0xff, 0xff, 0xff, 0xff };
548c2ecf20Sopenharmony_cistatic u8 da9210_irq_clr[] = { DA9210_REG_MASK_A, 0xff, 0xff };
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic struct i2c_msg da9063_msg = {
578c2ecf20Sopenharmony_ci	.len = ARRAY_SIZE(da9063_irq_clr),
588c2ecf20Sopenharmony_ci	.buf = da9063_irq_clr,
598c2ecf20Sopenharmony_ci};
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistatic struct i2c_msg da9210_msg = {
628c2ecf20Sopenharmony_ci	.len = ARRAY_SIZE(da9210_irq_clr),
638c2ecf20Sopenharmony_ci	.buf = da9210_irq_clr,
648c2ecf20Sopenharmony_ci};
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic const struct of_device_id rcar_gen2_quirk_match[] = {
678c2ecf20Sopenharmony_ci	{ .compatible = "dlg,da9063", .data = &da9063_msg },
688c2ecf20Sopenharmony_ci	{ .compatible = "dlg,da9063l", .data = &da9063_msg },
698c2ecf20Sopenharmony_ci	{ .compatible = "dlg,da9210", .data = &da9210_msg },
708c2ecf20Sopenharmony_ci	{},
718c2ecf20Sopenharmony_ci};
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_cistatic int regulator_quirk_notify(struct notifier_block *nb,
748c2ecf20Sopenharmony_ci				  unsigned long action, void *data)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	struct regulator_quirk *pos, *tmp;
778c2ecf20Sopenharmony_ci	struct device *dev = data;
788c2ecf20Sopenharmony_ci	struct i2c_client *client;
798c2ecf20Sopenharmony_ci	static bool done;
808c2ecf20Sopenharmony_ci	int ret;
818c2ecf20Sopenharmony_ci	u32 mon;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	if (done)
848c2ecf20Sopenharmony_ci		return 0;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	mon = ioread32(irqc + IRQC_MONITOR);
878c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s: %ld, IRQC_MONITOR = 0x%x\n", __func__, action, mon);
888c2ecf20Sopenharmony_ci	if (mon & REGULATOR_IRQ_MASK)
898c2ecf20Sopenharmony_ci		goto remove;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	if (action != BUS_NOTIFY_ADD_DEVICE || dev->type == &i2c_adapter_type)
928c2ecf20Sopenharmony_ci		return 0;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	client = to_i2c_client(dev);
958c2ecf20Sopenharmony_ci	dev_dbg(dev, "Detected %s\n", client->name);
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	/*
988c2ecf20Sopenharmony_ci	 * Send message to all PMICs that share an IRQ line to deassert it.
998c2ecf20Sopenharmony_ci	 *
1008c2ecf20Sopenharmony_ci	 * WARNING: This works only if all the PMICs are on the same I2C bus.
1018c2ecf20Sopenharmony_ci	 */
1028c2ecf20Sopenharmony_ci	list_for_each_entry(pos, &quirk_list, list) {
1038c2ecf20Sopenharmony_ci		if (!pos->shared)
1048c2ecf20Sopenharmony_ci			continue;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci		if (pos->np->parent != client->dev.parent->of_node)
1078c2ecf20Sopenharmony_ci			continue;
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci		dev_info(&client->dev, "clearing %s@0x%02x interrupts\n",
1108c2ecf20Sopenharmony_ci			 pos->id->compatible, pos->i2c_msg.addr);
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci		ret = i2c_transfer(client->adapter, &pos->i2c_msg, 1);
1138c2ecf20Sopenharmony_ci		if (ret != 1)
1148c2ecf20Sopenharmony_ci			dev_err(&client->dev, "i2c error %d\n", ret);
1158c2ecf20Sopenharmony_ci	}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	mon = ioread32(irqc + IRQC_MONITOR);
1188c2ecf20Sopenharmony_ci	if (mon & REGULATOR_IRQ_MASK)
1198c2ecf20Sopenharmony_ci		goto remove;
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	return 0;
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ciremove:
1248c2ecf20Sopenharmony_ci	dev_info(dev, "IRQ2 is not asserted, removing quirk\n");
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	list_for_each_entry_safe(pos, tmp, &quirk_list, list) {
1278c2ecf20Sopenharmony_ci		list_del(&pos->list);
1288c2ecf20Sopenharmony_ci		of_node_put(pos->np);
1298c2ecf20Sopenharmony_ci		kfree(pos);
1308c2ecf20Sopenharmony_ci	}
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	done = true;
1338c2ecf20Sopenharmony_ci	iounmap(irqc);
1348c2ecf20Sopenharmony_ci	return 0;
1358c2ecf20Sopenharmony_ci}
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_cistatic struct notifier_block regulator_quirk_nb = {
1388c2ecf20Sopenharmony_ci	.notifier_call = regulator_quirk_notify
1398c2ecf20Sopenharmony_ci};
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic int __init rcar_gen2_regulator_quirk(void)
1428c2ecf20Sopenharmony_ci{
1438c2ecf20Sopenharmony_ci	struct regulator_quirk *quirk, *pos, *tmp;
1448c2ecf20Sopenharmony_ci	struct of_phandle_args *argsa, *argsb;
1458c2ecf20Sopenharmony_ci	const struct of_device_id *id;
1468c2ecf20Sopenharmony_ci	struct device_node *np;
1478c2ecf20Sopenharmony_ci	u32 mon, addr;
1488c2ecf20Sopenharmony_ci	int ret;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	if (!of_machine_is_compatible("renesas,koelsch") &&
1518c2ecf20Sopenharmony_ci	    !of_machine_is_compatible("renesas,lager") &&
1528c2ecf20Sopenharmony_ci	    !of_machine_is_compatible("renesas,porter") &&
1538c2ecf20Sopenharmony_ci	    !of_machine_is_compatible("renesas,stout") &&
1548c2ecf20Sopenharmony_ci	    !of_machine_is_compatible("renesas,gose"))
1558c2ecf20Sopenharmony_ci		return -ENODEV;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	for_each_matching_node_and_match(np, rcar_gen2_quirk_match, &id) {
1588c2ecf20Sopenharmony_ci		if (!of_device_is_available(np)) {
1598c2ecf20Sopenharmony_ci			of_node_put(np);
1608c2ecf20Sopenharmony_ci			break;
1618c2ecf20Sopenharmony_ci		}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci		ret = of_property_read_u32(np, "reg", &addr);
1648c2ecf20Sopenharmony_ci		if (ret)	/* Skip invalid entry and continue */
1658c2ecf20Sopenharmony_ci			continue;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci		quirk = kzalloc(sizeof(*quirk), GFP_KERNEL);
1688c2ecf20Sopenharmony_ci		if (!quirk) {
1698c2ecf20Sopenharmony_ci			ret = -ENOMEM;
1708c2ecf20Sopenharmony_ci			of_node_put(np);
1718c2ecf20Sopenharmony_ci			goto err_mem;
1728c2ecf20Sopenharmony_ci		}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci		argsa = &quirk->irq_args;
1758c2ecf20Sopenharmony_ci		memcpy(&quirk->i2c_msg, id->data, sizeof(quirk->i2c_msg));
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci		quirk->id = id;
1788c2ecf20Sopenharmony_ci		quirk->np = of_node_get(np);
1798c2ecf20Sopenharmony_ci		quirk->i2c_msg.addr = addr;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci		ret = of_irq_parse_one(np, 0, argsa);
1828c2ecf20Sopenharmony_ci		if (ret) {	/* Skip invalid entry and continue */
1838c2ecf20Sopenharmony_ci			of_node_put(np);
1848c2ecf20Sopenharmony_ci			kfree(quirk);
1858c2ecf20Sopenharmony_ci			continue;
1868c2ecf20Sopenharmony_ci		}
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci		list_for_each_entry(pos, &quirk_list, list) {
1898c2ecf20Sopenharmony_ci			argsb = &pos->irq_args;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci			if (argsa->args_count != argsb->args_count)
1928c2ecf20Sopenharmony_ci				continue;
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci			ret = memcmp(argsa->args, argsb->args,
1958c2ecf20Sopenharmony_ci				     argsa->args_count *
1968c2ecf20Sopenharmony_ci				     sizeof(argsa->args[0]));
1978c2ecf20Sopenharmony_ci			if (!ret) {
1988c2ecf20Sopenharmony_ci				pos->shared = true;
1998c2ecf20Sopenharmony_ci				quirk->shared = true;
2008c2ecf20Sopenharmony_ci			}
2018c2ecf20Sopenharmony_ci		}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci		list_add_tail(&quirk->list, &quirk_list);
2048c2ecf20Sopenharmony_ci	}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	irqc = ioremap(IRQC_BASE, PAGE_SIZE);
2078c2ecf20Sopenharmony_ci	if (!irqc) {
2088c2ecf20Sopenharmony_ci		ret = -ENOMEM;
2098c2ecf20Sopenharmony_ci		goto err_mem;
2108c2ecf20Sopenharmony_ci	}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	mon = ioread32(irqc + IRQC_MONITOR);
2138c2ecf20Sopenharmony_ci	if (mon & REGULATOR_IRQ_MASK) {
2148c2ecf20Sopenharmony_ci		pr_debug("%s: IRQ2 is not asserted, not installing quirk\n",
2158c2ecf20Sopenharmony_ci			 __func__);
2168c2ecf20Sopenharmony_ci		ret = 0;
2178c2ecf20Sopenharmony_ci		goto err_free;
2188c2ecf20Sopenharmony_ci	}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	pr_info("IRQ2 is asserted, installing regulator quirk\n");
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	bus_register_notifier(&i2c_bus_type, &regulator_quirk_nb);
2238c2ecf20Sopenharmony_ci	return 0;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_cierr_free:
2268c2ecf20Sopenharmony_ci	iounmap(irqc);
2278c2ecf20Sopenharmony_cierr_mem:
2288c2ecf20Sopenharmony_ci	list_for_each_entry_safe(pos, tmp, &quirk_list, list) {
2298c2ecf20Sopenharmony_ci		list_del(&pos->list);
2308c2ecf20Sopenharmony_ci		of_node_put(pos->np);
2318c2ecf20Sopenharmony_ci		kfree(pos);
2328c2ecf20Sopenharmony_ci	}
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	return ret;
2358c2ecf20Sopenharmony_ci}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ciarch_initcall(rcar_gen2_regulator_quirk);
238