summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>2016-09-18 12:08:28 +0200
committerKlaus Goger <klaus.goger@theobroma-systems.com>2016-09-18 13:45:15 +0200
commit8996395939a1dc8d5870a185e13e4cd102d7108b (patch)
tree9ddc880e38f3b36ee9232f370de54e417655d1bd
parent22941e8c96c021ed911258cdde68e2f10ecb92c4 (diff)
dm: pmic: wrap RSB into dm driver
Implement driver to wrap RSB in a device-model I2C driver.
-rw-r--r--drivers/i2c/Makefile1
-rw-r--r--drivers/i2c/sunxi-rsb.c104
2 files changed, 105 insertions, 0 deletions
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index c75c5793ef..0b6d8beb6c 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -40,5 +40,6 @@ obj-$(CONFIG_SYS_I2C_TEGRA) += tegra_i2c.o
obj-$(CONFIG_SYS_I2C_UNIPHIER) += i2c-uniphier.o
obj-$(CONFIG_SYS_I2C_UNIPHIER_F) += i2c-uniphier-f.o
obj-$(CONFIG_SYS_I2C_ZYNQ) += zynq_i2c.o
+obj-$(CONFIG_MACH_SUN9I) += sunxi-rsb.o
obj-$(CONFIG_I2C_MUX) += muxes/
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,
+};