diff options
Diffstat (limited to 'drivers/i2c/sunxi-rsb.c')
-rw-r--r-- | drivers/i2c/sunxi-rsb.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/drivers/i2c/sunxi-rsb.c b/drivers/i2c/sunxi-rsb.c new file mode 100644 index 0000000000..2f332da44e --- /dev/null +++ b/drivers/i2c/sunxi-rsb.c @@ -0,0 +1,104 @@ +/* + * (C) Copyright 2016 Theobroma Systems Design und Consulting GmbH + * Written by Philipp Tomsich <philipp.tomsich@theobroma-systems.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <errno.h> +#include <i2c.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/rsb.h> +#include <asm/arch/pmic_bus.h> /* Should go away, once this driver is stand-alone */ +#include <dm/pinctrl.h> +#include <linux/sizes.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct sunxi_rsb { + void* regs; +}; + +/* This is just a simple wrapper around the native RSB driver, but should + in fact pull in the initialisation and hardware control in the future. */ + +static int sunxi_rsb_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs) +{ + int ret = 0; + int reg = -1; + + for (; nmsgs > 0; nmsgs--, msg++) { + debug("sunxi_rsb_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len); + if (msg->flags & I2C_M_RD) { + while ( (msg->len)-- && !ret ) { + debug("rsb_read(a: %d, r: %d, d: ...)\n", msg->addr, reg); + ret = rsb_read(msg->addr, reg++, (msg->buf)++); //, msg->len); + } + } else { + reg = *(msg->buf++); --(msg->len); + debug("sunxi_rsb_xfer: setting reg to %d\n", reg); + while ( (msg->len)-- && !ret ) { + debug("rsb_write(a: %d, r: %d, d: 0x%x)\n", msg->addr, reg, *(msg->buf)); + ret = rsb_write(msg->addr, reg++, *(msg->buf++)); + } + } + if (ret) { + debug("sunxi_rsb_xfer: error sending\n"); + return -EREMOTEIO; + } + } + + return ret; +} + +int sunxi_rsb_set_bus_speed(struct udevice *bus, unsigned int speed) +{ + debug("sunxi_rsb_set_bus_speed\n"); + return 0; +} + +static int sunxi_rsb_ofdata_to_platdata(struct udevice *bus) +{ + debug("sunxi_rsb_ofdata_to_platdata\n"); + return 0; +} + +static int sunxi_rsb_probe(struct udevice *bus) +{ + struct sunxi_rsb *priv = dev_get_priv(bus); + int ret; + debug("sunxi_rsb_probe\n"); + + /* make sure the RSB bus is initialised */ + ret = pmic_bus_init(); + debug("retval from pmic_bus_init(): %d\n", ret); + + priv->regs = (void *)dev_get_addr(bus); + + return 0; +} + +static const struct dm_i2c_ops sunxi_rsb_ops = { + .xfer = sunxi_rsb_xfer, + .set_bus_speed = sunxi_rsb_set_bus_speed, +}; + +static const struct udevice_id sunxi_rsb_ids[] = { + { .compatible = "allwinner,sun8i-a23-rsb" }, + { } +}; + +U_BOOT_DRIVER(i2c_rockchip) = { + .name = "sunxi_rsb", + .id = UCLASS_I2C, + .flags = DM_I2C_CHIP_RD_ADDRESS | DM_I2C_CHIP_WR_ADDRESS, + .of_match = sunxi_rsb_ids, + .ofdata_to_platdata = sunxi_rsb_ofdata_to_platdata, + .probe = sunxi_rsb_probe, + .priv_auto_alloc_size = sizeof(struct sunxi_rsb), + .ops = &sunxi_rsb_ops, +}; |