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
p2wi_interrupt(int irq,void * dev_id)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
p2wi_functionality(struct i2c_adapter * adap)1123e833490SBoris BREZILLON static u32 p2wi_functionality(struct i2c_adapter *adap)
1133e833490SBoris BREZILLON {
1143e833490SBoris BREZILLON return I2C_FUNC_SMBUS_BYTE_DATA;
1153e833490SBoris BREZILLON }
1163e833490SBoris BREZILLON
p2wi_smbus_xfer(struct i2c_adapter * adap,u16 addr,unsigned short flags,char read_write,u8 command,int size,union i2c_smbus_data * data)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
p2wi_probe(struct platform_device * pdev)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
p2wi_remove(struct platform_device * dev)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