[U-Boot] [PATCH v2 06/12] dm: pmic: add max77686 pmic driver

Przemyslaw Marczak
2015-03-03T16:24:37Z

This is the implementation of driver model uclass pmic driver.
The max77686 pmic driver implements read/write operations and driver
bind method - to bind other pmic uclass devices as a parent pmic device.
This driver provides pmic_platdata for also for child regulator.

This driver will try to bind the regulator device with regulator driver.
This should succeed if regulator driver is compiled.

If no regulator driver found, then the pmic can still provide read/write
operations, and can be used with pmic framework function calls.

Signed-off-by: Przemyslaw Marczak <p.marczak@samsung.com>
---
Changes V2:
- add implementation of pmic read/write
- max77686: add new operations
- max77686: header: change PMIC_NUM_OF_REGS to MAX77686_NUM_OF_REGS
---
drivers/power/pmic/Makefile | 1 +
drivers/power/pmic/max77686.c | 102 +++++++++++++++++++++++++++++++++++++
drivers/power/pmic/pmic_max77686.c | 2 +-
include/power/max77686_pmic.h | 2 +-
4 files changed, 105 insertions(+), 2 deletions(-)
create mode 100644 drivers/power/pmic/max77686.c

diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index 985cfdb..242c767 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_POWER_MAX8998) += pmic_max8998.o
obj-$(CONFIG_POWER_MAX8997) += pmic_max8997.o
obj-$(CONFIG_POWER_MUIC_MAX8997) += muic_max8997.o
obj-$(CONFIG_POWER_MAX77686) += pmic_max77686.o
+obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
obj-$(CONFIG_POWER_PFUZE100) += pmic_pfuze100.o
obj-$(CONFIG_POWER_TPS65090_I2C) += pmic_tps65090.o
obj-$(CONFIG_POWER_TPS65090_EC) += pmic_tps65090_ec.o
diff --git a/drivers/power/pmic/max77686.c b/drivers/power/pmic/max77686.c
new file mode 100644
index 0000000..01867ac
--- /dev/null
+++ b/drivers/power/pmic/max77686.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2014-2015 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <dm.h>
+#include <power/pmic.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+#include <dm/root.h>
+#include <dm/lists.h>
+#include <power/max77686_pmic.h>
+#include <errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int max77686_write(struct udevice *pmic, unsigned reg, unsigned char val)
+{
+ unsigned char buf[4] = { 0 };
+
+ buf[0] = cpu_to_le32(val) & 0xff;
+
+ if (dm_i2c_write(pmic, reg, buf, 1)) {
+ error("write error to device: %p register: %#x!", pmic, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int max77686_read(struct udevice *pmic, unsigned reg, unsigned char *val)
+{
+ unsigned char buf[4] = { 0 };
+
+ if (dm_i2c_read(pmic, reg, buf, 1)) {
+ error("read error from device: %p register: %#x!", pmic, reg);
+ return -EIO;
+ }
+
+ *val = le32_to_cpu(buf[0]);
+
+ return 0;
+}
+
+static int max77686_bind(struct udevice *pmic)
+{
+ struct dm_i2c_chip *i2c_chip = dev_get_parent_platdata(pmic);
+ struct pmic_platdata *pl = pmic->platdata;
+ struct udevice *reg_dev;
+ struct driver *reg_drv;
+ int ret;
+
+ /* The same platdata is used for the regulator driver */
+ pl->if_type = PMIC_I2C;
+ pl->if_bus_num = pmic->parent->req_seq;
+ pl->if_addr_cs = i2c_chip->chip_addr;
+ pl->if_max_offset = MAX77686_NUM_OF_REGS;
+
+ reg_drv = lists_driver_lookup_name("max77686 regulator");
+ if (!reg_drv) {
+ error("PMIC: %s regulator driver not found!\n", pmic->name);
+ return 0;
+ }
+
+ /**
+ * Try bind the child regulator driver
+ * |-- I2C bus
+ * '---max77686 pmic I/O driver
+ * '--max77686 regulator driver
+ */
+ ret = device_bind(pmic, reg_drv, pmic->name, pmic->platdata,
+ pmic->of_offset, &reg_dev);
+ if (ret)
+ error("%s regulator bind failed", pmic->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static struct dm_pmic_ops max77686_ops = {
+ .read = max77686_read,
+ .write = max77686_write,
+};
+
+static const struct udevice_id max77686_ids[] = {
+ { .compatible = "maxim,max77686_pmic"},
+ { }
+};
+
+U_BOOT_DRIVER(pmic_max77686) = {
+ .name = "max77686 pmic",
+ .id = UCLASS_PMIC,
+ .of_match = max77686_ids,
+ .bind = max77686_bind,
+ .ops = &max77686_ops,
+ .platdata_auto_alloc_size = sizeof(struct pmic_platdata),
+};
diff --git a/drivers/power/pmic/pmic_max77686.c b/drivers/power/pmic/pmic_max77686.c
index 95b1a57..1ad810a 100644
--- a/drivers/power/pmic/pmic_max77686.c
+++ b/drivers/power/pmic/pmic_max77686.c
@@ -295,7 +295,7 @@ int pmic_init(unsigned char bus)

p->name = name;
p->interface = PMIC_I2C;
- p->number_of_regs = PMIC_NUM_OF_REGS;
+ p->number_of_regs = MAX77686_NUM_OF_REGS;
p->hw.i2c.tx_num = 1;

puts("Board PMIC init\n");
diff --git a/include/power/max77686_pmic.h b/include/power/max77686_pmic.h
index b0e4255..fe26d13 100644
--- a/include/power/max77686_pmic.h
+++ b/include/power/max77686_pmic.h
@@ -122,7 +122,7 @@ enum {
MAX77686_REG_PMIC_BBAT = 0x7e,
MAX77686_REG_PMIC_32KHZ,

- PMIC_NUM_OF_REGS,
+ MAX77686_NUM_OF_REGS,
};

/* I2C device address for pmic max77686 */
--
1.9.1