xref: /linux/drivers/i2c/busses/i2c-sun6i-p2wi.c (revision 4632a93f015caf6d7db4352f37aab74a39e60d7a)
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:
133e833490SBoris BREZILLON  * - it supports only one slave 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/module.h>
263e833490SBoris BREZILLON #include <linux/i2c.h>
273e833490SBoris BREZILLON #include <linux/io.h>
283e833490SBoris BREZILLON #include <linux/interrupt.h>
293e833490SBoris BREZILLON #include <linux/module.h>
303e833490SBoris BREZILLON #include <linux/of.h>
313e833490SBoris BREZILLON #include <linux/platform_device.h>
323e833490SBoris BREZILLON #include <linux/reset.h>
333e833490SBoris BREZILLON 
343e833490SBoris BREZILLON 
353e833490SBoris BREZILLON /* P2WI registers */
363e833490SBoris BREZILLON #define P2WI_CTRL		0x0
373e833490SBoris BREZILLON #define P2WI_CCR		0x4
383e833490SBoris BREZILLON #define P2WI_INTE		0x8
393e833490SBoris BREZILLON #define P2WI_INTS		0xc
403e833490SBoris BREZILLON #define P2WI_DADDR0		0x10
413e833490SBoris BREZILLON #define P2WI_DADDR1		0x14
423e833490SBoris BREZILLON #define P2WI_DLEN		0x18
433e833490SBoris BREZILLON #define P2WI_DATA0		0x1c
443e833490SBoris BREZILLON #define P2WI_DATA1		0x20
453e833490SBoris BREZILLON #define P2WI_LCR		0x24
463e833490SBoris BREZILLON #define P2WI_PMCR		0x28
473e833490SBoris BREZILLON 
483e833490SBoris BREZILLON /* CTRL fields */
493e833490SBoris BREZILLON #define P2WI_CTRL_START_TRANS		BIT(7)
503e833490SBoris BREZILLON #define P2WI_CTRL_ABORT_TRANS		BIT(6)
513e833490SBoris BREZILLON #define P2WI_CTRL_GLOBAL_INT_ENB	BIT(1)
523e833490SBoris BREZILLON #define P2WI_CTRL_SOFT_RST		BIT(0)
533e833490SBoris BREZILLON 
543e833490SBoris BREZILLON /* CLK CTRL fields */
553e833490SBoris BREZILLON #define P2WI_CCR_SDA_OUT_DELAY(v)	(((v) & 0x7) << 8)
563e833490SBoris BREZILLON #define P2WI_CCR_MAX_CLK_DIV		0xff
573e833490SBoris BREZILLON #define P2WI_CCR_CLK_DIV(v)		((v) & P2WI_CCR_MAX_CLK_DIV)
583e833490SBoris BREZILLON 
593e833490SBoris BREZILLON /* STATUS fields */
603e833490SBoris BREZILLON #define P2WI_INTS_TRANS_ERR_ID(v)	(((v) >> 8) & 0xff)
613e833490SBoris BREZILLON #define P2WI_INTS_LOAD_BSY		BIT(2)
623e833490SBoris BREZILLON #define P2WI_INTS_TRANS_ERR		BIT(1)
633e833490SBoris BREZILLON #define P2WI_INTS_TRANS_OVER		BIT(0)
643e833490SBoris BREZILLON 
653e833490SBoris BREZILLON /* DATA LENGTH fields*/
663e833490SBoris BREZILLON #define P2WI_DLEN_READ			BIT(4)
673e833490SBoris BREZILLON #define P2WI_DLEN_DATA_LENGTH(v)	((v - 1) & 0x7)
683e833490SBoris BREZILLON 
693e833490SBoris BREZILLON /* LINE CTRL fields*/
703e833490SBoris BREZILLON #define P2WI_LCR_SCL_STATE		BIT(5)
713e833490SBoris BREZILLON #define P2WI_LCR_SDA_STATE		BIT(4)
723e833490SBoris BREZILLON #define P2WI_LCR_SCL_CTL		BIT(3)
733e833490SBoris BREZILLON #define P2WI_LCR_SCL_CTL_EN		BIT(2)
743e833490SBoris BREZILLON #define P2WI_LCR_SDA_CTL		BIT(1)
753e833490SBoris BREZILLON #define P2WI_LCR_SDA_CTL_EN		BIT(0)
763e833490SBoris BREZILLON 
773e833490SBoris BREZILLON /* PMU MODE CTRL fields */
783e833490SBoris BREZILLON #define P2WI_PMCR_PMU_INIT_SEND		BIT(31)
793e833490SBoris BREZILLON #define P2WI_PMCR_PMU_INIT_DATA(v)	(((v) & 0xff) << 16)
803e833490SBoris BREZILLON #define P2WI_PMCR_PMU_MODE_REG(v)	(((v) & 0xff) << 8)
813e833490SBoris BREZILLON #define P2WI_PMCR_PMU_DEV_ADDR(v)	((v) & 0xff)
823e833490SBoris BREZILLON 
833e833490SBoris BREZILLON #define P2WI_MAX_FREQ			6000000
843e833490SBoris BREZILLON 
853e833490SBoris BREZILLON struct p2wi {
863e833490SBoris BREZILLON 	struct i2c_adapter adapter;
873e833490SBoris BREZILLON 	struct completion complete;
883e833490SBoris BREZILLON 	unsigned int status;
893e833490SBoris BREZILLON 	void __iomem *regs;
903e833490SBoris BREZILLON 	struct clk *clk;
913e833490SBoris BREZILLON 	struct reset_control *rstc;
923e833490SBoris BREZILLON 	int slave_addr;
933e833490SBoris BREZILLON };
943e833490SBoris BREZILLON 
953e833490SBoris BREZILLON static irqreturn_t p2wi_interrupt(int irq, void *dev_id)
963e833490SBoris BREZILLON {
973e833490SBoris BREZILLON 	struct p2wi *p2wi = dev_id;
983e833490SBoris BREZILLON 	unsigned long status;
993e833490SBoris BREZILLON 
1003e833490SBoris BREZILLON 	status = readl(p2wi->regs + P2WI_INTS);
1013e833490SBoris BREZILLON 	p2wi->status = status;
1023e833490SBoris BREZILLON 
1033e833490SBoris BREZILLON 	/* Clear interrupts */
1043e833490SBoris BREZILLON 	status &= (P2WI_INTS_LOAD_BSY | P2WI_INTS_TRANS_ERR |
1053e833490SBoris BREZILLON 		   P2WI_INTS_TRANS_OVER);
1063e833490SBoris BREZILLON 	writel(status, p2wi->regs + P2WI_INTS);
1073e833490SBoris BREZILLON 
1083e833490SBoris BREZILLON 	complete(&p2wi->complete);
1093e833490SBoris BREZILLON 
1103e833490SBoris BREZILLON 	return IRQ_HANDLED;
1113e833490SBoris BREZILLON }
1123e833490SBoris BREZILLON 
1133e833490SBoris BREZILLON static u32 p2wi_functionality(struct i2c_adapter *adap)
1143e833490SBoris BREZILLON {
1153e833490SBoris BREZILLON 	return I2C_FUNC_SMBUS_BYTE_DATA;
1163e833490SBoris BREZILLON }
1173e833490SBoris BREZILLON 
1183e833490SBoris BREZILLON static int p2wi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
1193e833490SBoris BREZILLON 			   unsigned short flags, char read_write,
1203e833490SBoris BREZILLON 			   u8 command, int size, union i2c_smbus_data *data)
1213e833490SBoris BREZILLON {
1223e833490SBoris BREZILLON 	struct p2wi *p2wi = i2c_get_adapdata(adap);
1233e833490SBoris BREZILLON 	unsigned long dlen = P2WI_DLEN_DATA_LENGTH(1);
1243e833490SBoris BREZILLON 
1253e833490SBoris BREZILLON 	if (p2wi->slave_addr >= 0 && addr != p2wi->slave_addr) {
1263e833490SBoris BREZILLON 		dev_err(&adap->dev, "invalid P2WI address\n");
1273e833490SBoris BREZILLON 		return -EINVAL;
1283e833490SBoris BREZILLON 	}
1293e833490SBoris BREZILLON 
1303e833490SBoris BREZILLON 	if (!data)
1313e833490SBoris BREZILLON 		return -EINVAL;
1323e833490SBoris BREZILLON 
1333e833490SBoris BREZILLON 	writel(command, p2wi->regs + P2WI_DADDR0);
1343e833490SBoris BREZILLON 
1353e833490SBoris BREZILLON 	if (read_write == I2C_SMBUS_READ)
1363e833490SBoris BREZILLON 		dlen |= P2WI_DLEN_READ;
1373e833490SBoris BREZILLON 	else
1383e833490SBoris BREZILLON 		writel(data->byte, p2wi->regs + P2WI_DATA0);
1393e833490SBoris BREZILLON 
1403e833490SBoris BREZILLON 	writel(dlen, p2wi->regs + P2WI_DLEN);
1413e833490SBoris BREZILLON 
1423e833490SBoris BREZILLON 	if (readl(p2wi->regs + P2WI_CTRL) & P2WI_CTRL_START_TRANS) {
1433e833490SBoris BREZILLON 		dev_err(&adap->dev, "P2WI bus busy\n");
1443e833490SBoris BREZILLON 		return -EBUSY;
1453e833490SBoris BREZILLON 	}
1463e833490SBoris BREZILLON 
1473e833490SBoris BREZILLON 	reinit_completion(&p2wi->complete);
1483e833490SBoris BREZILLON 
1493e833490SBoris BREZILLON 	writel(P2WI_INTS_LOAD_BSY | P2WI_INTS_TRANS_ERR | P2WI_INTS_TRANS_OVER,
1503e833490SBoris BREZILLON 	       p2wi->regs + P2WI_INTE);
1513e833490SBoris BREZILLON 
1523e833490SBoris BREZILLON 	writel(P2WI_CTRL_START_TRANS | P2WI_CTRL_GLOBAL_INT_ENB,
1533e833490SBoris BREZILLON 	       p2wi->regs + P2WI_CTRL);
1543e833490SBoris BREZILLON 
1553e833490SBoris BREZILLON 	wait_for_completion(&p2wi->complete);
1563e833490SBoris BREZILLON 
1573e833490SBoris BREZILLON 	if (p2wi->status & P2WI_INTS_LOAD_BSY) {
1583e833490SBoris BREZILLON 		dev_err(&adap->dev, "P2WI bus busy\n");
1593e833490SBoris BREZILLON 		return -EBUSY;
1603e833490SBoris BREZILLON 	}
1613e833490SBoris BREZILLON 
1623e833490SBoris BREZILLON 	if (p2wi->status & P2WI_INTS_TRANS_ERR) {
1633e833490SBoris BREZILLON 		dev_err(&adap->dev, "P2WI bus xfer error\n");
1643e833490SBoris BREZILLON 		return -ENXIO;
1653e833490SBoris BREZILLON 	}
1663e833490SBoris BREZILLON 
1673e833490SBoris BREZILLON 	if (read_write == I2C_SMBUS_READ)
1683e833490SBoris BREZILLON 		data->byte = readl(p2wi->regs + P2WI_DATA0);
1693e833490SBoris BREZILLON 
1703e833490SBoris BREZILLON 	return 0;
1713e833490SBoris BREZILLON }
1723e833490SBoris BREZILLON 
1733e833490SBoris BREZILLON static const struct i2c_algorithm p2wi_algo = {
1743e833490SBoris BREZILLON 	.smbus_xfer = p2wi_smbus_xfer,
1753e833490SBoris BREZILLON 	.functionality = p2wi_functionality,
1763e833490SBoris BREZILLON };
1773e833490SBoris BREZILLON 
1783e833490SBoris BREZILLON static const struct of_device_id p2wi_of_match_table[] = {
1793e833490SBoris BREZILLON 	{ .compatible = "allwinner,sun6i-a31-p2wi" },
1803e833490SBoris BREZILLON 	{}
1813e833490SBoris BREZILLON };
1823e833490SBoris BREZILLON MODULE_DEVICE_TABLE(of, p2wi_of_match_table);
1833e833490SBoris BREZILLON 
1843e833490SBoris BREZILLON static int p2wi_probe(struct platform_device *pdev)
1853e833490SBoris BREZILLON {
1863e833490SBoris BREZILLON 	struct device *dev = &pdev->dev;
1873e833490SBoris BREZILLON 	struct device_node *np = dev->of_node;
1883e833490SBoris BREZILLON 	struct device_node *childnp;
1893e833490SBoris BREZILLON 	unsigned long parent_clk_freq;
1903e833490SBoris BREZILLON 	u32 clk_freq = 100000;
1913e833490SBoris BREZILLON 	struct resource *r;
1923e833490SBoris BREZILLON 	struct p2wi *p2wi;
1933e833490SBoris BREZILLON 	u32 slave_addr;
1943e833490SBoris BREZILLON 	int clk_div;
1953e833490SBoris BREZILLON 	int irq;
1963e833490SBoris BREZILLON 	int ret;
1973e833490SBoris BREZILLON 
1983e833490SBoris BREZILLON 	of_property_read_u32(np, "clock-frequency", &clk_freq);
1993e833490SBoris BREZILLON 	if (clk_freq > P2WI_MAX_FREQ) {
2003e833490SBoris BREZILLON 		dev_err(dev,
2013e833490SBoris BREZILLON 			"required clock-frequency (%u Hz) is too high (max = 6MHz)",
2023e833490SBoris BREZILLON 			clk_freq);
2033e833490SBoris BREZILLON 		return -EINVAL;
2043e833490SBoris BREZILLON 	}
2053e833490SBoris BREZILLON 
2063e833490SBoris BREZILLON 	if (of_get_child_count(np) > 1) {
2073e833490SBoris BREZILLON 		dev_err(dev, "P2WI only supports one slave device\n");
2083e833490SBoris BREZILLON 		return -EINVAL;
2093e833490SBoris BREZILLON 	}
2103e833490SBoris BREZILLON 
2113e833490SBoris BREZILLON 	p2wi = devm_kzalloc(dev, sizeof(struct p2wi), GFP_KERNEL);
2123e833490SBoris BREZILLON 	if (!p2wi)
2133e833490SBoris BREZILLON 		return -ENOMEM;
2143e833490SBoris BREZILLON 
2153e833490SBoris BREZILLON 	p2wi->slave_addr = -1;
2163e833490SBoris BREZILLON 
2173e833490SBoris BREZILLON 	/*
2183e833490SBoris BREZILLON 	 * Authorize a p2wi node without any children to be able to use an
2193e833490SBoris BREZILLON 	 * i2c-dev from userpace.
2203e833490SBoris BREZILLON 	 * In this case the slave_addr is set to -1 and won't be checked when
2213e833490SBoris BREZILLON 	 * launching a P2WI transfer.
2223e833490SBoris BREZILLON 	 */
2233e833490SBoris BREZILLON 	childnp = of_get_next_available_child(np, NULL);
2243e833490SBoris BREZILLON 	if (childnp) {
2253e833490SBoris BREZILLON 		ret = of_property_read_u32(childnp, "reg", &slave_addr);
2263e833490SBoris BREZILLON 		if (ret) {
2273e833490SBoris BREZILLON 			dev_err(dev, "invalid slave address on node %s\n",
2283e833490SBoris BREZILLON 				childnp->full_name);
2293e833490SBoris BREZILLON 			return -EINVAL;
2303e833490SBoris BREZILLON 		}
2313e833490SBoris BREZILLON 
2323e833490SBoris BREZILLON 		p2wi->slave_addr = slave_addr;
2333e833490SBoris BREZILLON 	}
2343e833490SBoris BREZILLON 
2353e833490SBoris BREZILLON 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2363e833490SBoris BREZILLON 	p2wi->regs = devm_ioremap_resource(dev, r);
2373e833490SBoris BREZILLON 	if (IS_ERR(p2wi->regs))
2383e833490SBoris BREZILLON 		return PTR_ERR(p2wi->regs);
2393e833490SBoris BREZILLON 
240*4632a93fSBoris BREZILLON 	strlcpy(p2wi->adapter.name, pdev->name, sizeof(p2wi->adapter.name));
2413e833490SBoris BREZILLON 	irq = platform_get_irq(pdev, 0);
2423e833490SBoris BREZILLON 	if (irq < 0) {
243c155ba88SWolfram Sang 		dev_err(dev, "failed to retrieve irq: %d\n", irq);
2443e833490SBoris BREZILLON 		return irq;
2453e833490SBoris BREZILLON 	}
2463e833490SBoris BREZILLON 
2473e833490SBoris BREZILLON 	p2wi->clk = devm_clk_get(dev, NULL);
2483e833490SBoris BREZILLON 	if (IS_ERR(p2wi->clk)) {
2493e833490SBoris BREZILLON 		ret = PTR_ERR(p2wi->clk);
2503e833490SBoris BREZILLON 		dev_err(dev, "failed to retrieve clk: %d\n", ret);
2513e833490SBoris BREZILLON 		return ret;
2523e833490SBoris BREZILLON 	}
2533e833490SBoris BREZILLON 
2543e833490SBoris BREZILLON 	ret = clk_prepare_enable(p2wi->clk);
2553e833490SBoris BREZILLON 	if (ret) {
2563e833490SBoris BREZILLON 		dev_err(dev, "failed to enable clk: %d\n", ret);
2573e833490SBoris BREZILLON 		return ret;
2583e833490SBoris BREZILLON 	}
2593e833490SBoris BREZILLON 
2603e833490SBoris BREZILLON 	parent_clk_freq = clk_get_rate(p2wi->clk);
2613e833490SBoris BREZILLON 
2623e833490SBoris BREZILLON 	p2wi->rstc = devm_reset_control_get(dev, NULL);
2633e833490SBoris BREZILLON 	if (IS_ERR(p2wi->rstc)) {
2643e833490SBoris BREZILLON 		ret = PTR_ERR(p2wi->rstc);
2653e833490SBoris BREZILLON 		dev_err(dev, "failed to retrieve reset controller: %d\n", ret);
2663e833490SBoris BREZILLON 		goto err_clk_disable;
2673e833490SBoris BREZILLON 	}
2683e833490SBoris BREZILLON 
2693e833490SBoris BREZILLON 	ret = reset_control_deassert(p2wi->rstc);
2703e833490SBoris BREZILLON 	if (ret) {
2713e833490SBoris BREZILLON 		dev_err(dev, "failed to deassert reset line: %d\n", ret);
2723e833490SBoris BREZILLON 		goto err_clk_disable;
2733e833490SBoris BREZILLON 	}
2743e833490SBoris BREZILLON 
2753e833490SBoris BREZILLON 	init_completion(&p2wi->complete);
2763e833490SBoris BREZILLON 	p2wi->adapter.dev.parent = dev;
2773e833490SBoris BREZILLON 	p2wi->adapter.algo = &p2wi_algo;
2783e833490SBoris BREZILLON 	p2wi->adapter.owner = THIS_MODULE;
2793e833490SBoris BREZILLON 	p2wi->adapter.dev.of_node = pdev->dev.of_node;
2803e833490SBoris BREZILLON 	platform_set_drvdata(pdev, p2wi);
2813e833490SBoris BREZILLON 	i2c_set_adapdata(&p2wi->adapter, p2wi);
2823e833490SBoris BREZILLON 
2833e833490SBoris BREZILLON 	ret = devm_request_irq(dev, irq, p2wi_interrupt, 0, pdev->name, p2wi);
2843e833490SBoris BREZILLON 	if (ret) {
2853e833490SBoris BREZILLON 		dev_err(dev, "can't register interrupt handler irq%d: %d\n",
2863e833490SBoris BREZILLON 			irq, ret);
2873e833490SBoris BREZILLON 		goto err_reset_assert;
2883e833490SBoris BREZILLON 	}
2893e833490SBoris BREZILLON 
2903e833490SBoris BREZILLON 	writel(P2WI_CTRL_SOFT_RST, p2wi->regs + P2WI_CTRL);
2913e833490SBoris BREZILLON 
2923e833490SBoris BREZILLON 	clk_div = parent_clk_freq / clk_freq;
2933e833490SBoris BREZILLON 	if (!clk_div) {
2943e833490SBoris BREZILLON 		dev_warn(dev,
2953e833490SBoris BREZILLON 			 "clock-frequency is too high, setting it to %lu Hz\n",
2963e833490SBoris BREZILLON 			 parent_clk_freq);
2973e833490SBoris BREZILLON 		clk_div = 1;
2983e833490SBoris BREZILLON 	} else if (clk_div > P2WI_CCR_MAX_CLK_DIV) {
2993e833490SBoris BREZILLON 		dev_warn(dev,
3003e833490SBoris BREZILLON 			 "clock-frequency is too low, setting it to %lu Hz\n",
3013e833490SBoris BREZILLON 			 parent_clk_freq / P2WI_CCR_MAX_CLK_DIV);
3023e833490SBoris BREZILLON 		clk_div = P2WI_CCR_MAX_CLK_DIV;
3033e833490SBoris BREZILLON 	}
3043e833490SBoris BREZILLON 
3053e833490SBoris BREZILLON 	writel(P2WI_CCR_SDA_OUT_DELAY(1) | P2WI_CCR_CLK_DIV(clk_div),
3063e833490SBoris BREZILLON 	       p2wi->regs + P2WI_CCR);
3073e833490SBoris BREZILLON 
3083e833490SBoris BREZILLON 	ret = i2c_add_adapter(&p2wi->adapter);
3093e833490SBoris BREZILLON 	if (!ret)
3103e833490SBoris BREZILLON 		return 0;
3113e833490SBoris BREZILLON 
3123e833490SBoris BREZILLON err_reset_assert:
3133e833490SBoris BREZILLON 	reset_control_assert(p2wi->rstc);
3143e833490SBoris BREZILLON 
3153e833490SBoris BREZILLON err_clk_disable:
3163e833490SBoris BREZILLON 	clk_disable_unprepare(p2wi->clk);
3173e833490SBoris BREZILLON 
3183e833490SBoris BREZILLON 	return ret;
3193e833490SBoris BREZILLON }
3203e833490SBoris BREZILLON 
3213e833490SBoris BREZILLON static int p2wi_remove(struct platform_device *dev)
3223e833490SBoris BREZILLON {
3233e833490SBoris BREZILLON 	struct p2wi *p2wi = platform_get_drvdata(dev);
3243e833490SBoris BREZILLON 
3253e833490SBoris BREZILLON 	reset_control_assert(p2wi->rstc);
3263e833490SBoris BREZILLON 	clk_disable_unprepare(p2wi->clk);
3273e833490SBoris BREZILLON 	i2c_del_adapter(&p2wi->adapter);
3283e833490SBoris BREZILLON 
3293e833490SBoris BREZILLON 	return 0;
3303e833490SBoris BREZILLON }
3313e833490SBoris BREZILLON 
3323e833490SBoris BREZILLON static struct platform_driver p2wi_driver = {
3333e833490SBoris BREZILLON 	.probe	= p2wi_probe,
3343e833490SBoris BREZILLON 	.remove	= p2wi_remove,
3353e833490SBoris BREZILLON 	.driver	= {
3363e833490SBoris BREZILLON 		.owner = THIS_MODULE,
3373e833490SBoris BREZILLON 		.name = "i2c-sunxi-p2wi",
3383e833490SBoris BREZILLON 		.of_match_table = p2wi_of_match_table,
3393e833490SBoris BREZILLON 	},
3403e833490SBoris BREZILLON };
3413e833490SBoris BREZILLON module_platform_driver(p2wi_driver);
3423e833490SBoris BREZILLON 
3433e833490SBoris BREZILLON MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
3443e833490SBoris BREZILLON MODULE_DESCRIPTION("Allwinner P2WI driver");
3453e833490SBoris BREZILLON MODULE_LICENSE("GPL v2");
346