dm: pmic: add max77686 pmic driver
authorPrzemyslaw Marczak <p.marczak@samsung.com>
Mon, 20 Apr 2015 18:07:46 +0000 (20:07 +0200)
committerSimon Glass <sjg@chromium.org>
Fri, 15 May 2015 00:49:38 +0000 (18:49 -0600)
This is the implementation of driver model PMIC driver.
The max77686 PMIC driver implements read/write operations and driver
bind method - to bind its childs.

This driver will try to bind the regulator devices by using it's child
info array with regulator prefixes and driver names. This should succeed
when compatible regulator driver is compiled. If no regulator driver found,
then the pmic can still provide read/write operations, and can be used with
PMIC function calls.

Signed-off-by: Przemyslaw Marczak <p.marczak@samsung.com>
Acked-by: Simon Glass <sjg@chromium.org>
doc/device-tree-bindings/pmic/max77686.txt [new file with mode: 0644]
drivers/power/pmic/Kconfig
drivers/power/pmic/Makefile
drivers/power/pmic/max77686.c [new file with mode: 0644]
drivers/power/pmic/pmic_max77686.c
include/power/max77686_pmic.h

diff --git a/doc/device-tree-bindings/pmic/max77686.txt b/doc/device-tree-bindings/pmic/max77686.txt
new file mode 100644 (file)
index 0000000..09aee64
--- /dev/null
@@ -0,0 +1,35 @@
+MAXIM, MAX77686 pmic
+
+This device uses two drivers:
+- drivers/power/pmic/max77686.c (for parent device)
+- drivers/power/regulator/max77686.c (for child regulators)
+
+This file describes the binding info for the PMIC driver.
+
+To bind the regulators, please read the additional binding info:
+- doc/device-tree-bindings/regulator/max77686.txt
+
+Required properties:
+- compatible: "maxim,max77686"
+- reg = 0x9
+
+With those two properties, the pmic device can be used for read/write only.
+To bind each regulator, the optional regulators subnode should exists.
+
+Optional subnode:
+- voltage-regulators: subnode list of each device's regulator
+  (see max77686.txt - regulator binding info)
+
+Example:
+
+max77686@09 {
+       compatible = "maxim,max77686";
+       reg = <0x09>;
+
+       voltage-regulators {
+               ldo1 {
+                       ...
+               };
+               ...
+       };
+};
index d06d632e897e8fb13be6b834d95def9e1fc09689..af68783987211cbf915ed93f78be39aa284e1cca 100644 (file)
@@ -9,3 +9,10 @@ config DM_PMIC
        for read/write. For detailed description, please refer to the files:
        - 'drivers/power/pmic/pmic-uclass.c'
        - 'include/power/pmic.h'
+
+config DM_PMIC_MAX77686
+       bool "Enable Driver Model for PMIC MAX77686"
+       depends on DM_PMIC
+       ---help---
+       This config enables implementation of driver-model pmic uclass features
+       for PMIC MAX77686. The driver implements read/write operations.
\ No newline at end of file
index 594f62021880b6f80580409c164d295cba7344d0..8cb993d0a7bb4d9decaac34c8b850de2819025d9 100644 (file)
@@ -11,6 +11,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 (file)
index 0000000..e9503e2
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *  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 <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/max77686_pmic.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct pmic_child_info pmic_childs_info[] = {
+       { .prefix = "ldo", .driver = MAX77686_LDO_DRIVER },
+       { .prefix = "buck", .driver = MAX77686_BUCK_DRIVER },
+       { },
+};
+
+static int max77686_write(struct udevice *dev, uint reg, const uint8_t *buff,
+                         int len)
+{
+       if (dm_i2c_write(dev, reg, buff, len)) {
+               error("write error to device: %p register: %#x!", dev, reg);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int max77686_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+       if (dm_i2c_read(dev, reg, buff, len)) {
+               error("read error from device: %p register: %#x!", dev, reg);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int max77686_bind(struct udevice *dev)
+{
+       int regulators_node;
+       const void *blob = gd->fdt_blob;
+       int childs;
+
+       regulators_node = fdt_subnode_offset(blob, dev->of_offset,
+                                            "voltage-regulators");
+       if (regulators_node <= 0) {
+               debug("%s: %s regulators subnode not found!", __func__,
+                                                            dev->name);
+               return -ENXIO;
+       }
+
+       debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+       childs = pmic_bind_childs(dev, regulators_node, pmic_childs_info);
+       if (!childs)
+               debug("%s: %s - no child found\n", __func__, dev->name);
+
+       /* Always return success for this device */
+       return 0;
+}
+
+static struct dm_pmic_ops max77686_ops = {
+       .reg_count = MAX77686_NUM_OF_REGS,
+       .read = max77686_read,
+       .write = max77686_write,
+};
+
+static const struct udevice_id max77686_ids[] = {
+       { .compatible = "maxim,max77686" },
+       { }
+};
+
+U_BOOT_DRIVER(pmic_max77686) = {
+       .name = "max77686 pmic",
+       .id = UCLASS_PMIC,
+       .of_match = max77686_ids,
+       .bind = max77686_bind,
+       .ops = &max77686_ops,
+};
index 95b1a57ca2bf10829befad0022948d608bfe39b3..1ad810acc266cb41cfbc5071c633c464d6418865 100644 (file)
@@ -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");
index b0e42550a2a4eb3bfd591aca3de0a67c1c1f4e34..95597db503225771fdff3c3745005eb883d449d5 100644 (file)
@@ -122,11 +122,17 @@ enum {
        MAX77686_REG_PMIC_BBAT          = 0x7e,
        MAX77686_REG_PMIC_32KHZ,
 
-       PMIC_NUM_OF_REGS,
+       MAX77686_NUM_OF_REGS,
 };
 
 /* I2C device address for pmic max77686 */
-#define MAX77686_I2C_ADDR (0x12 >> 1)
+#define MAX77686_I2C_ADDR      (0x12 >> 1)
+#define MAX77686_LDO_NUM       26
+#define MAX77686_BUCK_NUM      9
+
+/* Drivers name */
+#define MAX77686_LDO_DRIVER    "max77686_ldo"
+#define MAX77686_BUCK_DRIVER   "max77686_buck"
 
 enum {
        REG_DISABLE = 0,