xref: /linux/drivers/i2c/busses/i2c-sun6i-p2wi.c (revision c2cac347ef59e01c34cae69996fc6c47043f657f)
13e833490SBoris BREZILLON /*
23e833490SBoris BREZILLON  * P2WI (Push-Pull Two Wire Interface) bus driver.
33e833490SBoris BREZILLON  *
43e833490SBoris BREZILLON  * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
53e833490SBoris BREZILLON  *
63e833490SBoris BREZILLON  * This file is licensed under the terms of the GNU General Public License
73e833490SBoris BREZILLON  * version 2.  This program is licensed "as is" without any warranty of any
83e833490SBoris BREZILLON  * kind, whether express or implied.
93e833490SBoris BREZILLON  *
103e833490SBoris BREZILLON  * The P2WI controller looks like an SMBus controller which only supports byte
113e833490SBoris BREZILLON  * data transfers. But, it differs from standard SMBus protocol on several
123e833490SBoris BREZILLON  * aspects:
13*c2cac347SWolfram Sang  * - it supports only one target device, and thus drop the address field
143e833490SBoris BREZILLON  * - it adds a parity bit every 8bits of data
153e833490SBoris BREZILLON  * - only one read access is required to read a byte (instead of a write
163e833490SBoris BREZILLON  *   followed by a read access in standard SMBus protocol)
173e833490SBoris BREZILLON  * - there's no Ack bit after each byte transfer
183e833490SBoris BREZILLON  *
193e833490SBoris BREZILLON  * This means this bus cannot be used to interface with standard SMBus
203e833490SBoris BREZILLON  * devices (the only known device to support this interface is the AXP221
213e833490SBoris BREZILLON  * PMIC).
223e833490SBoris BREZILLON  *
233e833490SBoris BREZILLON  */
243e833490SBoris BREZILLON #include <linux/clk.h>
253e833490SBoris BREZILLON #include <linux/i2c.h>
263e833490SBoris BREZILLON #include <linux/io.h>
273e833490SBoris BREZILLON #include <linux/interrupt.h>
283e833490SBoris BREZILLON #include <linux/module.h>
293e833490SBoris BREZILLON #include <linux/of.h>
303e833490SBoris BREZILLON #include <linux/platform_device.h>
313e833490SBoris BREZILLON #include <linux/reset.h>
323e833490SBoris BREZILLON 
333e833490SBoris BREZILLON 
343e833490SBoris BREZILLON /* P2WI registers */
353e833490SBoris BREZILLON #define P2WI_CTRL		0x0
363e833490SBoris BREZILLON #define P2WI_CCR		0x4
373e833490SBoris BREZILLON #define P2WI_INTE		0x8
383e833490SBoris BREZILLON #define P2WI_INTS		0xc
393e833490SBoris BREZILLON #define P2WI_DADDR0		0x10
403e833490SBoris BREZILLON #define P2WI_DADDR1		0x14
413e833490SBoris BREZILLON #define P2WI_DLEN		0x18
423e833490SBoris BREZILLON #define P2WI_DATA0		0x1c
433e833490SBoris BREZILLON #define P2WI_DATA1		0x20
443e833490SBoris BREZILLON #define P2WI_LCR		0x24
453e833490SBoris BREZILLON #define P2WI_PMCR		0x28
463e833490SBoris BREZILLON 
473e833490SBoris BREZILLON /* CTRL fields */
483e833490SBoris BREZILLON #define P2WI_CTRL_START_TRANS		BIT(7)
493e833490SBoris BREZILLON #define P2WI_CTRL_ABORT_TRANS		BIT(6)
503e833490SBoris BREZILLON #define P2WI_CTRL_GLOBAL_INT_ENB	BIT(1)
513e833490SBoris BREZILLON #define P2WI_CTRL_SOFT_RST		BIT(0)
523e833490SBoris BREZILLON 
533e833490SBoris BREZILLON /* CLK CTRL fields */
543e833490SBoris BREZILLON #define P2WI_CCR_SDA_OUT_DELAY(v)	(((v) & 0x7) << 8)
553e833490SBoris BREZILLON #define P2WI_CCR_MAX_CLK_DIV		0xff
563e833490SBoris BREZILLON #define P2WI_CCR_CLK_DIV(v)		((v) & P2WI_CCR_MAX_CLK_DIV)
573e833490SBoris BREZILLON 
583e833490SBoris BREZILLON /* STATUS fields */
593e833490SBoris BREZILLON #define P2WI_INTS_TRANS_ERR_ID(v)	(((v) >> 8) & 0xff)
603e833490SBoris BREZILLON #define P2WI_INTS_LOAD_BSY		BIT(2)
613e833490SBoris BREZILLON #define P2WI_INTS_TRANS_ERR		BIT(1)
623e833490SBoris BREZILLON #define P2WI_INTS_TRANS_OVER		BIT(0)
633e833490SBoris BREZILLON 
643e833490SBoris BREZILLON /* DATA LENGTH fields*/
653e833490SBoris BREZILLON #define P2WI_DLEN_READ			BIT(4)
663e833490SBoris BREZILLON #define P2WI_DLEN_DATA_LENGTH(v)	((v - 1) & 0x7)
673e833490SBoris BREZILLON 
683e833490SBoris BREZILLON /* LINE CTRL fields*/
693e833490SBoris BREZILLON #define P2WI_LCR_SCL_STATE		BIT(5)
703e833490SBoris BREZILLON #define P2WI_LCR_SDA_STATE		BIT(4)
713e833490SBoris BREZILLON #define P2WI_LCR_SCL_CTL		BIT(3)
723e833490SBoris BREZILLON #define P2WI_LCR_SCL_CTL_EN		BIT(2)
733e833490SBoris BREZILLON #define P2WI_LCR_SDA_CTL		BIT(1)
743e833490SBoris BREZILLON #define P2WI_LCR_SDA_CTL_EN		BIT(0)
753e833490SBoris BREZILLON 
763e833490SBoris BREZILLON /* PMU MODE CTRL fields */
773e833490SBoris BREZILLON #define P2WI_PMCR_PMU_INIT_SEND		BIT(31)
783e833490SBoris BREZILLON #define P2WI_PMCR_PMU_INIT_DATA(v)	(((v) & 0xff) << 16)
793e833490SBoris BREZILLON #define P2WI_PMCR_PMU_MODE_REG(v)	(((v) & 0xff) << 8)
803e833490SBoris BREZILLON #define P2WI_PMCR_PMU_DEV_ADDR(v)	((v) & 0xff)
813e833490SBoris BREZILLON 
823e833490SBoris BREZILLON #define P2WI_MAX_FREQ			6000000
833e833490SBoris BREZILLON 
843e833490SBoris BREZILLON struct p2wi {
853e833490SBoris BREZILLON 	struct i2c_adapter adapter;
863e833490SBoris BREZILLON 	struct completion complete;
873e833490SBoris BREZILLON 	unsigned int status;
883e833490SBoris BREZILLON 	void __iomem *regs;
893e833490SBoris BREZILLON 	struct clk *clk;
903e833490SBoris BREZILLON 	struct reset_control *rstc;
91*c2cac347SWolfram Sang 	int target_addr;
923e833490SBoris BREZILLON };
933e833490SBoris BREZILLON 
943e833490SBoris BREZILLON static irqreturn_t p2wi_interrupt(int irq, void *dev_id)
953e833490SBoris BREZILLON {
963e833490SBoris BREZILLON 	struct p2wi *p2wi = dev_id;
973e833490SBoris BREZILLON 	unsigned long status;
983e833490SBoris BREZILLON 
993e833490SBoris BREZILLON 	status = readl(p2wi->regs + P2WI_INTS);
1003e833490SBoris BREZILLON 	p2wi->status = status;
1013e833490SBoris BREZILLON 
1023e833490SBoris BREZILLON 	/* Clear interrupts */
1033e833490SBoris BREZILLON 	status &= (P2WI_INTS_LOAD_BSY | P2WI_INTS_TRANS_ERR |
1043e833490SBoris BREZILLON 		   P2WI_INTS_TRANS_OVER);
1053e833490SBoris BREZILLON 	writel(status, p2wi->regs + P2WI_INTS);
1063e833490SBoris BREZILLON 
1073e833490SBoris BREZILLON 	complete(&p2wi->complete);
1083e833490SBoris BREZILLON 
1093e833490SBoris BREZILLON 	return IRQ_HANDLED;
1103e833490SBoris BREZILLON }
1113e833490SBoris BREZILLON 
1123e833490SBoris BREZILLON static u32 p2wi_functionality(struct i2c_adapter *adap)
1133e833490SBoris BREZILLON {
1143e833490SBoris BREZILLON 	return I2C_FUNC_SMBUS_BYTE_DATA;
1153e833490SBoris BREZILLON }
1163e833490SBoris BREZILLON 
1173e833490SBoris BREZILLON static int p2wi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
1183e833490SBoris BREZILLON 			   unsigned short flags, char read_write,
1193e833490SBoris BREZILLON 			   u8 command, int size, union i2c_smbus_data *data)
1203e833490SBoris BREZILLON {
1213e833490SBoris BREZILLON 	struct p2wi *p2wi = i2c_get_adapdata(adap);
1223e833490SBoris BREZILLON 	unsigned long dlen = P2WI_DLEN_DATA_LENGTH(1);
1233e833490SBoris BREZILLON 
124*c2cac347SWolfram Sang 	if (p2wi->target_addr >= 0 && addr != p2wi->target_addr) {
1253e833490SBoris BREZILLON 		dev_err(&adap->dev, "invalid P2WI address\n");
1263e833490SBoris BREZILLON 		return -EINVAL;
1273e833490SBoris BREZILLON 	}
1283e833490SBoris BREZILLON 
1293e833490SBoris BREZILLON 	if (!data)
1303e833490SBoris BREZILLON 		return -EINVAL;
1313e833490SBoris BREZILLON 
1323e833490SBoris BREZILLON 	writel(command, p2wi->regs + P2WI_DADDR0);
1333e833490SBoris BREZILLON 
1343e833490SBoris BREZILLON 	if (read_write == I2C_SMBUS_READ)
1353e833490SBoris BREZILLON 		dlen |= P2WI_DLEN_READ;
1363e833490SBoris BREZILLON 	else
1373e833490SBoris BREZILLON 		writel(data->byte, p2wi->regs + P2WI_DATA0);
1383e833490SBoris BREZILLON 
1393e833490SBoris BREZILLON 	writel(dlen, p2wi->regs + P2WI_DLEN);
1403e833490SBoris BREZILLON 
1413e833490SBoris BREZILLON 	if (readl(p2wi->regs + P2WI_CTRL) & P2WI_CTRL_START_TRANS) {
1423e833490SBoris BREZILLON 		dev_err(&adap->dev, "P2WI bus busy\n");
1433e833490SBoris BREZILLON 		return -EBUSY;
1443e833490SBoris BREZILLON 	}
1453e833490SBoris BREZILLON 
1463e833490SBoris BREZILLON 	reinit_completion(&p2wi->complete);
1473e833490SBoris BREZILLON 
1483e833490SBoris BREZILLON 	writel(P2WI_INTS_LOAD_BSY | P2WI_INTS_TRANS_ERR | P2WI_INTS_TRANS_OVER,
1493e833490SBoris BREZILLON 	       p2wi->regs + P2WI_INTE);
1503e833490SBoris BREZILLON 
1513e833490SBoris BREZILLON 	writel(P2WI_CTRL_START_TRANS | P2WI_CTRL_GLOBAL_INT_ENB,
1523e833490SBoris BREZILLON 	       p2wi->regs + P2WI_CTRL);
1533e833490SBoris BREZILLON 
1543e833490SBoris BREZILLON 	wait_for_completion(&p2wi->complete);
1553e833490SBoris BREZILLON 
1563e833490SBoris BREZILLON 	if (p2wi->status & P2WI_INTS_LOAD_BSY) {
1573e833490SBoris BREZILLON 		dev_err(&adap->dev, "P2WI bus busy\n");
1583e833490SBoris BREZILLON 		return -EBUSY;
1593e833490SBoris BREZILLON 	}
1603e833490SBoris BREZILLON 
1613e833490SBoris BREZILLON 	if (p2wi->status & P2WI_INTS_TRANS_ERR) {
1623e833490SBoris BREZILLON 		dev_err(&adap->dev, "P2WI bus xfer error\n");
1633e833490SBoris BREZILLON 		return -ENXIO;
1643e833490SBoris BREZILLON 	}
1653e833490SBoris BREZILLON 
1663e833490SBoris BREZILLON 	if (read_write == I2C_SMBUS_READ)
1673e833490SBoris BREZILLON 		data->byte = readl(p2wi->regs + P2WI_DATA0);
1683e833490SBoris BREZILLON 
1693e833490SBoris BREZILLON 	return 0;
1703e833490SBoris BREZILLON }
1713e833490SBoris BREZILLON 
1723e833490SBoris BREZILLON static const struct i2c_algorithm p2wi_algo = {
1733e833490SBoris BREZILLON 	.smbus_xfer = p2wi_smbus_xfer,
1743e833490SBoris BREZILLON 	.functionality = p2wi_functionality,
1753e833490SBoris BREZILLON };
1763e833490SBoris BREZILLON 
1773e833490SBoris BREZILLON static const struct of_device_id p2wi_of_match_table[] = {
1783e833490SBoris BREZILLON 	{ .compatible = "allwinner,sun6i-a31-p2wi" },
1793e833490SBoris BREZILLON 	{}
1803e833490SBoris BREZILLON };
1813e833490SBoris BREZILLON MODULE_DEVICE_TABLE(of, p2wi_of_match_table);
1823e833490SBoris BREZILLON 
1833e833490SBoris BREZILLON static int p2wi_probe(struct platform_device *pdev)
1843e833490SBoris BREZILLON {
1853e833490SBoris BREZILLON 	struct device *dev = &pdev->dev;
1863e833490SBoris BREZILLON 	struct device_node *np = dev->of_node;
1873e833490SBoris BREZILLON 	struct device_node *childnp;
1883e833490SBoris BREZILLON 	unsigned long parent_clk_freq;
18990224e64SAndy Shevchenko 	u32 clk_freq = I2C_MAX_STANDARD_MODE_FREQ;
1903e833490SBoris BREZILLON 	struct p2wi *p2wi;
191*c2cac347SWolfram Sang 	u32 target_addr;
1923e833490SBoris BREZILLON 	int clk_div;
1933e833490SBoris BREZILLON 	int irq;
1943e833490SBoris BREZILLON 	int ret;
1953e833490SBoris BREZILLON 
1963e833490SBoris BREZILLON 	of_property_read_u32(np, "clock-frequency", &clk_freq);
1973e833490SBoris BREZILLON 	if (clk_freq > P2WI_MAX_FREQ) {
1983e833490SBoris BREZILLON 		dev_err(dev,
1993e833490SBoris BREZILLON 			"required clock-frequency (%u Hz) is too high (max = 6MHz)",
2003e833490SBoris BREZILLON 			clk_freq);
2013e833490SBoris BREZILLON 		return -EINVAL;
2023e833490SBoris BREZILLON 	}
2033e833490SBoris BREZILLON 
2045ac61d26SAxel Lin 	if (clk_freq == 0) {
2055ac61d26SAxel Lin 		dev_err(dev, "clock-frequency is set to 0 in DT\n");
2065ac61d26SAxel Lin 		return -EINVAL;
2075ac61d26SAxel Lin 	}
2085ac61d26SAxel Lin 
2093e833490SBoris BREZILLON 	if (of_get_child_count(np) > 1) {
210*c2cac347SWolfram Sang 		dev_err(dev, "P2WI only supports one target device\n");
2113e833490SBoris BREZILLON 		return -EINVAL;
2123e833490SBoris BREZILLON 	}
2133e833490SBoris BREZILLON 
2143e833490SBoris BREZILLON 	p2wi = devm_kzalloc(dev, sizeof(struct p2wi), GFP_KERNEL);
2153e833490SBoris BREZILLON 	if (!p2wi)
2163e833490SBoris BREZILLON 		return -ENOMEM;
2173e833490SBoris BREZILLON 
218*c2cac347SWolfram Sang 	p2wi->target_addr = -1;
2193e833490SBoris BREZILLON 
2203e833490SBoris BREZILLON 	/*
2213e833490SBoris BREZILLON 	 * Authorize a p2wi node without any children to be able to use an
2223e833490SBoris BREZILLON 	 * i2c-dev from userpace.
223*c2cac347SWolfram Sang 	 * In this case the target_addr is set to -1 and won't be checked when
2243e833490SBoris BREZILLON 	 * launching a P2WI transfer.
2253e833490SBoris BREZILLON 	 */
2263e833490SBoris BREZILLON 	childnp = of_get_next_available_child(np, NULL);
2273e833490SBoris BREZILLON 	if (childnp) {
228*c2cac347SWolfram Sang 		ret = of_property_read_u32(childnp, "reg", &target_addr);
2293e833490SBoris BREZILLON 		if (ret) {
230*c2cac347SWolfram Sang 			dev_err(dev, "invalid target address on node %pOF\n",
231453a237cSRob Herring 				childnp);
2323e833490SBoris BREZILLON 			return -EINVAL;
2333e833490SBoris BREZILLON 		}
2343e833490SBoris BREZILLON 
235*c2cac347SWolfram Sang 		p2wi->target_addr = target_addr;
2363e833490SBoris BREZILLON 	}
2373e833490SBoris BREZILLON 
238e0442d76SDejin Zheng 	p2wi->regs = devm_platform_ioremap_resource(pdev, 0);
2393e833490SBoris BREZILLON 	if (IS_ERR(p2wi->regs))
2403e833490SBoris BREZILLON 		return PTR_ERR(p2wi->regs);
2413e833490SBoris BREZILLON 
242e47a0cedSLen Baker 	strscpy(p2wi->adapter.name, pdev->name, sizeof(p2wi->adapter.name));
2433e833490SBoris BREZILLON 	irq = platform_get_irq(pdev, 0);
244e42688edSDejin Zheng 	if (irq < 0)
2453e833490SBoris BREZILLON 		return irq;
2463e833490SBoris BREZILLON 
24775ff8a34SAndi Shyti 	p2wi->clk = devm_clk_get_enabled(dev, NULL);
2483e833490SBoris BREZILLON 	if (IS_ERR(p2wi->clk)) {
2493e833490SBoris BREZILLON 		ret = PTR_ERR(p2wi->clk);
2503e833490SBoris BREZILLON 		dev_err(dev, "failed to enable clk: %d\n", ret);
2513e833490SBoris BREZILLON 		return ret;
2523e833490SBoris BREZILLON 	}
2533e833490SBoris BREZILLON 
2543e833490SBoris BREZILLON 	parent_clk_freq = clk_get_rate(p2wi->clk);
2553e833490SBoris BREZILLON 
25696ae9eabSPhilipp Zabel 	p2wi->rstc = devm_reset_control_get_exclusive(dev, NULL);
2573e833490SBoris BREZILLON 	if (IS_ERR(p2wi->rstc)) {
2580abbf0acSDan Carpenter 		dev_err(dev, "failed to retrieve reset controller: %pe\n",
2590abbf0acSDan Carpenter 			p2wi->rstc);
26075ff8a34SAndi Shyti 		return PTR_ERR(p2wi->rstc);
2613e833490SBoris BREZILLON 	}
2623e833490SBoris BREZILLON 
2633e833490SBoris BREZILLON 	ret = reset_control_deassert(p2wi->rstc);
2643e833490SBoris BREZILLON 	if (ret) {
2653e833490SBoris BREZILLON 		dev_err(dev, "failed to deassert reset line: %d\n", ret);
26675ff8a34SAndi Shyti 		return ret;
2673e833490SBoris BREZILLON 	}
2683e833490SBoris BREZILLON 
2693e833490SBoris BREZILLON 	init_completion(&p2wi->complete);
2703e833490SBoris BREZILLON 	p2wi->adapter.dev.parent = dev;
2713e833490SBoris BREZILLON 	p2wi->adapter.algo = &p2wi_algo;
2723e833490SBoris BREZILLON 	p2wi->adapter.owner = THIS_MODULE;
2733e833490SBoris BREZILLON 	p2wi->adapter.dev.of_node = pdev->dev.of_node;
2743e833490SBoris BREZILLON 	platform_set_drvdata(pdev, p2wi);
2753e833490SBoris BREZILLON 	i2c_set_adapdata(&p2wi->adapter, p2wi);
2763e833490SBoris BREZILLON 
2773e833490SBoris BREZILLON 	ret = devm_request_irq(dev, irq, p2wi_interrupt, 0, pdev->name, p2wi);
2783e833490SBoris BREZILLON 	if (ret) {
2793e833490SBoris BREZILLON 		dev_err(dev, "can't register interrupt handler irq%d: %d\n",
2803e833490SBoris BREZILLON 			irq, ret);
2813e833490SBoris BREZILLON 		goto err_reset_assert;
2823e833490SBoris BREZILLON 	}
2833e833490SBoris BREZILLON 
2843e833490SBoris BREZILLON 	writel(P2WI_CTRL_SOFT_RST, p2wi->regs + P2WI_CTRL);
2853e833490SBoris BREZILLON 
2863e833490SBoris BREZILLON 	clk_div = parent_clk_freq / clk_freq;
2873e833490SBoris BREZILLON 	if (!clk_div) {
2883e833490SBoris BREZILLON 		dev_warn(dev,
2893e833490SBoris BREZILLON 			 "clock-frequency is too high, setting it to %lu Hz\n",
2903e833490SBoris BREZILLON 			 parent_clk_freq);
2913e833490SBoris BREZILLON 		clk_div = 1;
2923e833490SBoris BREZILLON 	} else if (clk_div > P2WI_CCR_MAX_CLK_DIV) {
2933e833490SBoris BREZILLON 		dev_warn(dev,
2943e833490SBoris BREZILLON 			 "clock-frequency is too low, setting it to %lu Hz\n",
2953e833490SBoris BREZILLON 			 parent_clk_freq / P2WI_CCR_MAX_CLK_DIV);
2963e833490SBoris BREZILLON 		clk_div = P2WI_CCR_MAX_CLK_DIV;
2973e833490SBoris BREZILLON 	}
2983e833490SBoris BREZILLON 
2993e833490SBoris BREZILLON 	writel(P2WI_CCR_SDA_OUT_DELAY(1) | P2WI_CCR_CLK_DIV(clk_div),
3003e833490SBoris BREZILLON 	       p2wi->regs + P2WI_CCR);
3013e833490SBoris BREZILLON 
3023e833490SBoris BREZILLON 	ret = i2c_add_adapter(&p2wi->adapter);
3033e833490SBoris BREZILLON 	if (!ret)
3043e833490SBoris BREZILLON 		return 0;
3053e833490SBoris BREZILLON 
3063e833490SBoris BREZILLON err_reset_assert:
3073e833490SBoris BREZILLON 	reset_control_assert(p2wi->rstc);
3083e833490SBoris BREZILLON 
3093e833490SBoris BREZILLON 	return ret;
3103e833490SBoris BREZILLON }
3113e833490SBoris BREZILLON 
312e190a0c3SUwe Kleine-König static void p2wi_remove(struct platform_device *dev)
3133e833490SBoris BREZILLON {
3143e833490SBoris BREZILLON 	struct p2wi *p2wi = platform_get_drvdata(dev);
3153e833490SBoris BREZILLON 
3163e833490SBoris BREZILLON 	reset_control_assert(p2wi->rstc);
3173e833490SBoris BREZILLON 	i2c_del_adapter(&p2wi->adapter);
3183e833490SBoris BREZILLON }
3193e833490SBoris BREZILLON 
3203e833490SBoris BREZILLON static struct platform_driver p2wi_driver = {
3213e833490SBoris BREZILLON 	.probe	= p2wi_probe,
322e190a0c3SUwe Kleine-König 	.remove_new = p2wi_remove,
3233e833490SBoris BREZILLON 	.driver	= {
3243e833490SBoris BREZILLON 		.name = "i2c-sunxi-p2wi",
3253e833490SBoris BREZILLON 		.of_match_table = p2wi_of_match_table,
3263e833490SBoris BREZILLON 	},
3273e833490SBoris BREZILLON };
3283e833490SBoris BREZILLON module_platform_driver(p2wi_driver);
3293e833490SBoris BREZILLON 
3303e833490SBoris BREZILLON MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
3313e833490SBoris BREZILLON MODULE_DESCRIPTION("Allwinner P2WI driver");
3323e833490SBoris BREZILLON MODULE_LICENSE("GPL v2");
333