Lines Matching +full:sun6i +full:- +full:a31 +full:- +full:p2wi
2 * P2WI (Push-Pull Two Wire Interface) bus driver.
4 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
10 * The P2WI controller looks like an SMBus controller which only supports byte
13 * - it supports only one target device, and thus drop the address field
14 * - it adds a parity bit every 8bits of data
15 * - only one read access is required to read a byte (instead of a write
17 * - there's no Ack bit after each byte transfer
34 /* P2WI registers */
66 #define P2WI_DLEN_DATA_LENGTH(v) ((v - 1) & 0x7)
84 struct p2wi { struct
96 struct p2wi *p2wi = dev_id; in p2wi_interrupt() argument
99 status = readl(p2wi->regs + P2WI_INTS); in p2wi_interrupt()
100 p2wi->status = status; in p2wi_interrupt()
105 writel(status, p2wi->regs + P2WI_INTS); in p2wi_interrupt()
107 complete(&p2wi->complete); in p2wi_interrupt()
121 struct p2wi *p2wi = i2c_get_adapdata(adap); in p2wi_smbus_xfer() local
124 if (p2wi->target_addr >= 0 && addr != p2wi->target_addr) { in p2wi_smbus_xfer()
125 dev_err(&adap->dev, "invalid P2WI address\n"); in p2wi_smbus_xfer()
126 return -EINVAL; in p2wi_smbus_xfer()
130 return -EINVAL; in p2wi_smbus_xfer()
132 writel(command, p2wi->regs + P2WI_DADDR0); in p2wi_smbus_xfer()
137 writel(data->byte, p2wi->regs + P2WI_DATA0); in p2wi_smbus_xfer()
139 writel(dlen, p2wi->regs + P2WI_DLEN); in p2wi_smbus_xfer()
141 if (readl(p2wi->regs + P2WI_CTRL) & P2WI_CTRL_START_TRANS) { in p2wi_smbus_xfer()
142 dev_err(&adap->dev, "P2WI bus busy\n"); in p2wi_smbus_xfer()
143 return -EBUSY; in p2wi_smbus_xfer()
146 reinit_completion(&p2wi->complete); in p2wi_smbus_xfer()
149 p2wi->regs + P2WI_INTE); in p2wi_smbus_xfer()
152 p2wi->regs + P2WI_CTRL); in p2wi_smbus_xfer()
154 wait_for_completion(&p2wi->complete); in p2wi_smbus_xfer()
156 if (p2wi->status & P2WI_INTS_LOAD_BSY) { in p2wi_smbus_xfer()
157 dev_err(&adap->dev, "P2WI bus busy\n"); in p2wi_smbus_xfer()
158 return -EBUSY; in p2wi_smbus_xfer()
161 if (p2wi->status & P2WI_INTS_TRANS_ERR) { in p2wi_smbus_xfer()
162 dev_err(&adap->dev, "P2WI bus xfer error\n"); in p2wi_smbus_xfer()
163 return -ENXIO; in p2wi_smbus_xfer()
167 data->byte = readl(p2wi->regs + P2WI_DATA0); in p2wi_smbus_xfer()
178 { .compatible = "allwinner,sun6i-a31-p2wi" },
185 struct device *dev = &pdev->dev; in p2wi_probe()
186 struct device_node *np = dev->of_node; in p2wi_probe()
190 struct p2wi *p2wi; in p2wi_probe() local
196 of_property_read_u32(np, "clock-frequency", &clk_freq); in p2wi_probe()
199 "required clock-frequency (%u Hz) is too high (max = 6MHz)", in p2wi_probe()
201 return -EINVAL; in p2wi_probe()
205 dev_err(dev, "clock-frequency is set to 0 in DT\n"); in p2wi_probe()
206 return -EINVAL; in p2wi_probe()
210 dev_err(dev, "P2WI only supports one target device\n"); in p2wi_probe()
211 return -EINVAL; in p2wi_probe()
214 p2wi = devm_kzalloc(dev, sizeof(struct p2wi), GFP_KERNEL); in p2wi_probe()
215 if (!p2wi) in p2wi_probe()
216 return -ENOMEM; in p2wi_probe()
218 p2wi->target_addr = -1; in p2wi_probe()
221 * Authorize a p2wi node without any children to be able to use an in p2wi_probe()
222 * i2c-dev from userpace. in p2wi_probe()
223 * In this case the target_addr is set to -1 and won't be checked when in p2wi_probe()
224 * launching a P2WI transfer. in p2wi_probe()
232 return -EINVAL; in p2wi_probe()
235 p2wi->target_addr = target_addr; in p2wi_probe()
238 p2wi->regs = devm_platform_ioremap_resource(pdev, 0); in p2wi_probe()
239 if (IS_ERR(p2wi->regs)) in p2wi_probe()
240 return PTR_ERR(p2wi->regs); in p2wi_probe()
242 strscpy(p2wi->adapter.name, pdev->name, sizeof(p2wi->adapter.name)); in p2wi_probe()
247 p2wi->clk = devm_clk_get_enabled(dev, NULL); in p2wi_probe()
248 if (IS_ERR(p2wi->clk)) { in p2wi_probe()
249 ret = PTR_ERR(p2wi->clk); in p2wi_probe()
254 parent_clk_freq = clk_get_rate(p2wi->clk); in p2wi_probe()
256 p2wi->rstc = devm_reset_control_get_exclusive(dev, NULL); in p2wi_probe()
257 if (IS_ERR(p2wi->rstc)) { in p2wi_probe()
259 p2wi->rstc); in p2wi_probe()
260 return PTR_ERR(p2wi->rstc); in p2wi_probe()
263 ret = reset_control_deassert(p2wi->rstc); in p2wi_probe()
269 init_completion(&p2wi->complete); in p2wi_probe()
270 p2wi->adapter.dev.parent = dev; in p2wi_probe()
271 p2wi->adapter.algo = &p2wi_algo; in p2wi_probe()
272 p2wi->adapter.owner = THIS_MODULE; in p2wi_probe()
273 p2wi->adapter.dev.of_node = pdev->dev.of_node; in p2wi_probe()
274 platform_set_drvdata(pdev, p2wi); in p2wi_probe()
275 i2c_set_adapdata(&p2wi->adapter, p2wi); in p2wi_probe()
277 ret = devm_request_irq(dev, irq, p2wi_interrupt, 0, pdev->name, p2wi); in p2wi_probe()
284 writel(P2WI_CTRL_SOFT_RST, p2wi->regs + P2WI_CTRL); in p2wi_probe()
289 "clock-frequency is too high, setting it to %lu Hz\n", in p2wi_probe()
294 "clock-frequency is too low, setting it to %lu Hz\n", in p2wi_probe()
300 p2wi->regs + P2WI_CCR); in p2wi_probe()
302 ret = i2c_add_adapter(&p2wi->adapter); in p2wi_probe()
307 reset_control_assert(p2wi->rstc); in p2wi_probe()
314 struct p2wi *p2wi = platform_get_drvdata(dev); in p2wi_remove() local
316 reset_control_assert(p2wi->rstc); in p2wi_remove()
317 i2c_del_adapter(&p2wi->adapter); in p2wi_remove()
324 .name = "i2c-sunxi-p2wi",
330 MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
331 MODULE_DESCRIPTION("Allwinner P2WI driver");