Lines Matching full:rsb
2 * RSB (Reduced Serial Bus) driver.
10 * The RSB controller looks like an SMBus controller which only supports
27 * RSB section of Allwinner's A80 user manual, which can be found at
51 #include <linux/sunxi-rsb.h>
54 /* RSB registers */
63 #define RSB_CMD 0x2c /* RSB Command */
114 #define RSB_CTRL_NAME "sunxi-rsb"
192 * sunxi_rsb_device_create() - allocate and add an RSB device
193 * @rsb: RSB controller
194 * @node: RSB slave device node
195 * @hwaddr: RSB slave hardware address
196 * @rtaddr: RSB slave runtime address
198 static struct sunxi_rsb_device *sunxi_rsb_device_create(struct sunxi_rsb *rsb, in sunxi_rsb_device_create() argument
208 rdev->rsb = rsb; in sunxi_rsb_device_create()
212 rdev->dev.parent = rsb->dev; in sunxi_rsb_device_create()
236 * sunxi_rsb_device_unregister(): unregister an RSB device
255 * sunxi_rsb_driver_register() - Register device driver with RSB core
258 * This API will register the client driver with the RSB framework.
269 static int _sunxi_rsb_run_xfer(struct sunxi_rsb *rsb) in _sunxi_rsb_run_xfer() argument
274 if (readl(rsb->regs + RSB_CTRL) & RSB_CTRL_START_TRANS) { in _sunxi_rsb_run_xfer()
275 dev_dbg(rsb->dev, "RSB transfer still in progress\n"); in _sunxi_rsb_run_xfer()
279 reinit_completion(&rsb->complete); in _sunxi_rsb_run_xfer()
282 writel(int_mask, rsb->regs + RSB_INTE); in _sunxi_rsb_run_xfer()
284 rsb->regs + RSB_CTRL); in _sunxi_rsb_run_xfer()
287 timeout = readl_poll_timeout_atomic(rsb->regs + RSB_INTS, in _sunxi_rsb_run_xfer()
290 writel(status, rsb->regs + RSB_INTS); in _sunxi_rsb_run_xfer()
292 timeout = !wait_for_completion_io_timeout(&rsb->complete, in _sunxi_rsb_run_xfer()
294 status = rsb->status; in _sunxi_rsb_run_xfer()
298 dev_dbg(rsb->dev, "RSB timeout\n"); in _sunxi_rsb_run_xfer()
301 writel(RSB_CTRL_ABORT_TRANS, rsb->regs + RSB_CTRL); in _sunxi_rsb_run_xfer()
304 writel(readl(rsb->regs + RSB_INTS), rsb->regs + RSB_INTS); in _sunxi_rsb_run_xfer()
310 dev_dbg(rsb->dev, "RSB busy\n"); in _sunxi_rsb_run_xfer()
316 dev_dbg(rsb->dev, "RSB slave nack\n"); in _sunxi_rsb_run_xfer()
321 dev_dbg(rsb->dev, "RSB transfer data error\n"); in _sunxi_rsb_run_xfer()
329 static int sunxi_rsb_read(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr, in sunxi_rsb_read() argument
349 dev_err(rsb->dev, "Invalid access width: %zd\n", len); in sunxi_rsb_read()
353 mutex_lock(&rsb->lock); in sunxi_rsb_read()
355 writel(addr, rsb->regs + RSB_ADDR); in sunxi_rsb_read()
356 writel(RSB_DAR_RTA(rtaddr), rsb->regs + RSB_DAR); in sunxi_rsb_read()
357 writel(cmd, rsb->regs + RSB_CMD); in sunxi_rsb_read()
359 ret = _sunxi_rsb_run_xfer(rsb); in sunxi_rsb_read()
363 *buf = readl(rsb->regs + RSB_DATA) & GENMASK(len * 8 - 1, 0); in sunxi_rsb_read()
366 mutex_unlock(&rsb->lock); in sunxi_rsb_read()
371 static int sunxi_rsb_write(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr, in sunxi_rsb_write() argument
391 dev_err(rsb->dev, "Invalid access width: %zd\n", len); in sunxi_rsb_write()
395 mutex_lock(&rsb->lock); in sunxi_rsb_write()
397 writel(addr, rsb->regs + RSB_ADDR); in sunxi_rsb_write()
398 writel(RSB_DAR_RTA(rtaddr), rsb->regs + RSB_DAR); in sunxi_rsb_write()
399 writel(*buf, rsb->regs + RSB_DATA); in sunxi_rsb_write()
400 writel(cmd, rsb->regs + RSB_CMD); in sunxi_rsb_write()
401 ret = _sunxi_rsb_run_xfer(rsb); in sunxi_rsb_write()
403 mutex_unlock(&rsb->lock); in sunxi_rsb_write()
408 /* RSB regmap functions */
423 return sunxi_rsb_read(rdev->rsb, rdev->rtaddr, reg, val, ctx->size); in regmap_sunxi_rsb_reg_read()
432 return sunxi_rsb_write(rdev->rsb, rdev->rtaddr, reg, &val, ctx->size); in regmap_sunxi_rsb_reg_write()
489 /* RSB controller driver functions */
492 struct sunxi_rsb *rsb = dev_id; in sunxi_rsb_irq() local
495 status = readl(rsb->regs + RSB_INTS); in sunxi_rsb_irq()
496 rsb->status = status; in sunxi_rsb_irq()
501 writel(status, rsb->regs + RSB_INTS); in sunxi_rsb_irq()
503 complete(&rsb->complete); in sunxi_rsb_irq()
508 static int sunxi_rsb_init_device_mode(struct sunxi_rsb *rsb) in sunxi_rsb_init_device_mode() argument
515 RSB_DMCR_MODE_REG | RSB_DMCR_DEV_ADDR, rsb->regs + RSB_DMCR); in sunxi_rsb_init_device_mode()
517 readl_poll_timeout(rsb->regs + RSB_DMCR, reg, in sunxi_rsb_init_device_mode()
523 writel(readl(rsb->regs + RSB_INTS), rsb->regs + RSB_INTS); in sunxi_rsb_init_device_mode()
535 * No designs with 2 RSB slave devices sharing identical hardware
562 static int of_rsb_register_devices(struct sunxi_rsb *rsb) in of_rsb_register_devices() argument
564 struct device *dev = rsb->dev; in of_rsb_register_devices()
598 writel(RSB_CMD_STRA, rsb->regs + RSB_CMD); in of_rsb_register_devices()
600 rsb->regs + RSB_DAR); in of_rsb_register_devices()
603 ret = _sunxi_rsb_run_xfer(rsb); in of_rsb_register_devices()
623 rdev = sunxi_rsb_device_create(rsb, child, hwaddr, rtaddr); in of_rsb_register_devices()
633 { .compatible = "allwinner,sun8i-a23-rsb" },
643 struct sunxi_rsb *rsb; in sunxi_rsb_probe() local
657 rsb = devm_kzalloc(dev, sizeof(*rsb), GFP_KERNEL); in sunxi_rsb_probe()
658 if (!rsb) in sunxi_rsb_probe()
661 rsb->dev = dev; in sunxi_rsb_probe()
662 platform_set_drvdata(pdev, rsb); in sunxi_rsb_probe()
664 rsb->regs = devm_ioremap_resource(dev, r); in sunxi_rsb_probe()
665 if (IS_ERR(rsb->regs)) in sunxi_rsb_probe()
666 return PTR_ERR(rsb->regs); in sunxi_rsb_probe()
672 rsb->clk = devm_clk_get(dev, NULL); in sunxi_rsb_probe()
673 if (IS_ERR(rsb->clk)) { in sunxi_rsb_probe()
674 ret = PTR_ERR(rsb->clk); in sunxi_rsb_probe()
679 ret = clk_prepare_enable(rsb->clk); in sunxi_rsb_probe()
685 p_clk_freq = clk_get_rate(rsb->clk); in sunxi_rsb_probe()
687 rsb->rstc = devm_reset_control_get(dev, NULL); in sunxi_rsb_probe()
688 if (IS_ERR(rsb->rstc)) { in sunxi_rsb_probe()
689 ret = PTR_ERR(rsb->rstc); in sunxi_rsb_probe()
694 ret = reset_control_deassert(rsb->rstc); in sunxi_rsb_probe()
700 init_completion(&rsb->complete); in sunxi_rsb_probe()
701 mutex_init(&rsb->lock); in sunxi_rsb_probe()
704 writel(RSB_CTRL_SOFT_RST, rsb->regs + RSB_CTRL); in sunxi_rsb_probe()
705 readl_poll_timeout(rsb->regs + RSB_CTRL, reg, in sunxi_rsb_probe()
725 dev_info(dev, "RSB running at %lu Hz\n", p_clk_freq / clk_div / 2); in sunxi_rsb_probe()
727 rsb->regs + RSB_CCR); in sunxi_rsb_probe()
729 ret = devm_request_irq(dev, irq, sunxi_rsb_irq, 0, RSB_CTRL_NAME, rsb); in sunxi_rsb_probe()
736 /* initialize all devices on the bus into RSB mode */ in sunxi_rsb_probe()
737 ret = sunxi_rsb_init_device_mode(rsb); in sunxi_rsb_probe()
741 of_rsb_register_devices(rsb); in sunxi_rsb_probe()
746 reset_control_assert(rsb->rstc); in sunxi_rsb_probe()
749 clk_disable_unprepare(rsb->clk); in sunxi_rsb_probe()
756 struct sunxi_rsb *rsb = platform_get_drvdata(pdev); in sunxi_rsb_remove() local
758 device_for_each_child(rsb->dev, NULL, sunxi_rsb_remove_devices); in sunxi_rsb_remove()
759 reset_control_assert(rsb->rstc); in sunxi_rsb_remove()
760 clk_disable_unprepare(rsb->clk); in sunxi_rsb_remove()