]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - drivers/power/pmic/pmic-uclass.c
Merge git://git.denx.de/u-boot-sunxi
[people/ms/u-boot.git] / drivers / power / pmic / pmic-uclass.c
index d82d3da51d5048978333c9809c38a0d81df8e82d..9347b4068897e8fca645f8974dc70f7a1b39b7f2 100644 (file)
@@ -9,6 +9,7 @@
 #include <fdtdec.h>
 #include <errno.h>
 #include <dm.h>
+#include <vsprintf.h>
 #include <dm/lists.h>
 #include <dm/device-internal.h>
 #include <dm/uclass-internal.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static ulong str_get_num(const char *ptr, const char *maxptr)
-{
-       if (!ptr || !maxptr)
-               return 0;
-
-       while (!isdigit(*ptr) && ptr++ < maxptr);
-
-       return simple_strtoul(ptr, NULL, 0);
-}
-
-int pmic_bind_childs(struct udevice *pmic, int offset,
-                    const struct pmic_child_info *child_info)
+#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
+int pmic_bind_children(struct udevice *pmic, ofnode parent,
+                      const struct pmic_child_info *child_info)
 {
        const struct pmic_child_info *info;
-       const void *blob = gd->fdt_blob;
        struct driver *drv;
        struct udevice *child;
        const char *node_name;
-       int node_name_len;
+       const char *reg_name;
        int bind_count = 0;
-       int node;
+       ofnode node;
        int prefix_len;
        int ret;
 
        debug("%s for '%s' at node offset: %d\n", __func__, pmic->name,
-             pmic->of_offset);
+             dev_of_offset(pmic));
 
-       for (node = fdt_first_subnode(blob, offset);
-            node > 0;
-            node = fdt_next_subnode(blob, node)) {
-               node_name = fdt_get_name(blob, node, &node_name_len);
+       ofnode_for_each_subnode(node, parent) {
+               node_name = ofnode_get_name(node);
 
-               debug("* Found child node: '%s' at offset:%d\n", node_name,
-                                                                node);
+               debug("* Found child node: '%s'\n", node_name);
 
                child = NULL;
-               info = child_info;
-               while (info->prefix) {
+               for (info = child_info; info->prefix && info->driver; info++) {
+                       debug("  - compatible prefix: '%s'\n", info->prefix);
+
                        prefix_len = strlen(info->prefix);
-                       if (strncasecmp(info->prefix, node_name, prefix_len) ||
-                           !info->driver) {
-                               info++;
-                               continue;
+                       if (strncmp(info->prefix, node_name, prefix_len)) {
+                               reg_name = ofnode_read_string(node,
+                                                             "regulator-name");
+                               if (!reg_name)
+                                       continue;
+                               if (strncmp(info->prefix, reg_name, prefix_len))
+                                       continue;
                        }
 
-                       debug("  - compatible prefix: '%s'\n", info->prefix);
-
                        drv = lists_driver_lookup_name(info->driver);
                        if (!drv) {
                                debug("  - driver: '%s' not found!\n",
@@ -73,8 +63,8 @@ int pmic_bind_childs(struct udevice *pmic, int offset,
 
                        debug("  - found child driver: '%s'\n", drv->name);
 
-                       ret = device_bind(pmic, drv, node_name, NULL,
-                                         node, &child);
+                       ret = device_bind_with_driver_data(pmic, drv, node_name,
+                                                          0, node, &child);
                        if (ret) {
                                debug("  - child binding error: %d\n", ret);
                                continue;
@@ -82,10 +72,7 @@ int pmic_bind_childs(struct udevice *pmic, int offset,
 
                        debug("  - bound child device: '%s'\n", child->name);
 
-                       child->driver_data = str_get_num(node_name +
-                                                        prefix_len,
-                                                        node_name +
-                                                        node_name_len);
+                       child->driver_data = trailing_strtol(node_name);
 
                        debug("  - set 'child->driver_data': %lu\n",
                              child->driver_data);
@@ -98,9 +85,10 @@ int pmic_bind_childs(struct udevice *pmic, int offset,
                        debug("  - compatible prefix not found\n");
        }
 
-       debug("Bound: %d childs for PMIC: '%s'\n", bind_count, pmic->name);
+       debug("Bound: %d children for PMIC: '%s'\n", bind_count, pmic->name);
        return bind_count;
 }
+#endif
 
 int pmic_get(const char *name, struct udevice **devp)
 {
@@ -110,16 +98,16 @@ int pmic_get(const char *name, struct udevice **devp)
 int pmic_reg_count(struct udevice *dev)
 {
        const struct dm_pmic_ops *ops = dev_get_driver_ops(dev);
-       if (!ops)
+
+       if (!ops || !ops->reg_count)
                return -ENOSYS;
 
-       return ops->reg_count;
+       return ops->reg_count(dev);
 }
 
 int pmic_read(struct udevice *dev, uint reg, uint8_t *buffer, int len)
 {
        const struct dm_pmic_ops *ops = dev_get_driver_ops(dev);
-       int ret;
 
        if (!buffer)
                return -EFAULT;
@@ -127,17 +115,12 @@ int pmic_read(struct udevice *dev, uint reg, uint8_t *buffer, int len)
        if (!ops || !ops->read)
                return -ENOSYS;
 
-       ret = ops->read(dev, reg, buffer, len);
-       if (ret)
-               return ret;
-
-       return 0;
+       return ops->read(dev, reg, buffer, len);
 }
 
 int pmic_write(struct udevice *dev, uint reg, const uint8_t *buffer, int len)
 {
        const struct dm_pmic_ops *ops = dev_get_driver_ops(dev);
-       int ret;
 
        if (!buffer)
                return -EFAULT;
@@ -145,11 +128,44 @@ int pmic_write(struct udevice *dev, uint reg, const uint8_t *buffer, int len)
        if (!ops || !ops->write)
                return -ENOSYS;
 
-       ret = ops->write(dev, reg, buffer, len);
-       if (ret)
+       return ops->write(dev, reg, buffer, len);
+}
+
+int pmic_reg_read(struct udevice *dev, uint reg)
+{
+       u8 byte;
+       int ret;
+
+       debug("%s: reg=%x", __func__, reg);
+       ret = pmic_read(dev, reg, &byte, 1);
+       debug(", value=%x, ret=%d\n", byte, ret);
+
+       return ret ? ret : byte;
+}
+
+int pmic_reg_write(struct udevice *dev, uint reg, uint value)
+{
+       u8 byte = value;
+       int ret;
+
+       debug("%s: reg=%x, value=%x", __func__, reg, value);
+       ret = pmic_write(dev, reg, &byte, 1);
+       debug(", ret=%d\n", ret);
+
+       return ret;
+}
+
+int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set)
+{
+       u8 byte;
+       int ret;
+
+       ret = pmic_reg_read(dev, reg);
+       if (ret < 0)
                return ret;
+       byte = (ret & ~clr) | set;
 
-       return 0;
+       return pmic_reg_write(dev, reg, byte);
 }
 
 UCLASS_DRIVER(pmic) = {