uboot/drivers/power/pmic/pmic-uclass.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2014-2015 Samsung Electronics
   3 * Przemyslaw Marczak <p.marczak@samsung.com>
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <fdtdec.h>
  10#include <errno.h>
  11#include <dm.h>
  12#include <vsprintf.h>
  13#include <dm/lists.h>
  14#include <dm/device-internal.h>
  15#include <dm/uclass-internal.h>
  16#include <power/pmic.h>
  17#include <linux/ctype.h>
  18
  19DECLARE_GLOBAL_DATA_PTR;
  20
  21#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
  22int pmic_bind_children(struct udevice *pmic, int offset,
  23                       const struct pmic_child_info *child_info)
  24{
  25        const struct pmic_child_info *info;
  26        const void *blob = gd->fdt_blob;
  27        struct driver *drv;
  28        struct udevice *child;
  29        const char *node_name;
  30        int bind_count = 0;
  31        int node;
  32        int prefix_len;
  33        int ret;
  34
  35        debug("%s for '%s' at node offset: %d\n", __func__, pmic->name,
  36              pmic->of_offset);
  37
  38        for (node = fdt_first_subnode(blob, offset);
  39             node > 0;
  40             node = fdt_next_subnode(blob, node)) {
  41                node_name = fdt_get_name(blob, node, NULL);
  42
  43                debug("* Found child node: '%s' at offset:%d\n", node_name,
  44                                                                 node);
  45
  46                child = NULL;
  47                for (info = child_info; info->prefix && info->driver; info++) {
  48                        debug("  - compatible prefix: '%s'\n", info->prefix);
  49
  50                        prefix_len = strlen(info->prefix);
  51                        if (strncmp(info->prefix, node_name, prefix_len))
  52                                continue;
  53
  54                        drv = lists_driver_lookup_name(info->driver);
  55                        if (!drv) {
  56                                debug("  - driver: '%s' not found!\n",
  57                                      info->driver);
  58                                continue;
  59                        }
  60
  61                        debug("  - found child driver: '%s'\n", drv->name);
  62
  63                        ret = device_bind(pmic, drv, node_name, NULL,
  64                                          node, &child);
  65                        if (ret) {
  66                                debug("  - child binding error: %d\n", ret);
  67                                continue;
  68                        }
  69
  70                        debug("  - bound child device: '%s'\n", child->name);
  71
  72                        child->driver_data = trailing_strtol(node_name);
  73
  74                        debug("  - set 'child->driver_data': %lu\n",
  75                              child->driver_data);
  76                        break;
  77                }
  78
  79                if (child)
  80                        bind_count++;
  81                else
  82                        debug("  - compatible prefix not found\n");
  83        }
  84
  85        debug("Bound: %d childs for PMIC: '%s'\n", bind_count, pmic->name);
  86        return bind_count;
  87}
  88#endif
  89
  90int pmic_get(const char *name, struct udevice **devp)
  91{
  92        return uclass_get_device_by_name(UCLASS_PMIC, name, devp);
  93}
  94
  95int pmic_reg_count(struct udevice *dev)
  96{
  97        const struct dm_pmic_ops *ops = dev_get_driver_ops(dev);
  98
  99        if (!ops || !ops->reg_count)
 100                return -ENOSYS;
 101
 102        return ops->reg_count(dev);
 103}
 104
 105int pmic_read(struct udevice *dev, uint reg, uint8_t *buffer, int len)
 106{
 107        const struct dm_pmic_ops *ops = dev_get_driver_ops(dev);
 108
 109        if (!buffer)
 110                return -EFAULT;
 111
 112        if (!ops || !ops->read)
 113                return -ENOSYS;
 114
 115        return ops->read(dev, reg, buffer, len);
 116}
 117
 118int pmic_write(struct udevice *dev, uint reg, const uint8_t *buffer, int len)
 119{
 120        const struct dm_pmic_ops *ops = dev_get_driver_ops(dev);
 121
 122        if (!buffer)
 123                return -EFAULT;
 124
 125        if (!ops || !ops->write)
 126                return -ENOSYS;
 127
 128        return ops->write(dev, reg, buffer, len);
 129}
 130
 131int pmic_reg_read(struct udevice *dev, uint reg)
 132{
 133        u8 byte;
 134        int ret;
 135
 136        debug("%s: reg=%x", __func__, reg);
 137        ret = pmic_read(dev, reg, &byte, 1);
 138        debug(", value=%x, ret=%d\n", byte, ret);
 139
 140        return ret ? ret : byte;
 141}
 142
 143int pmic_reg_write(struct udevice *dev, uint reg, uint value)
 144{
 145        u8 byte = value;
 146        int ret;
 147
 148        debug("%s: reg=%x, value=%x", __func__, reg, value);
 149        ret = pmic_write(dev, reg, &byte, 1);
 150        debug(", ret=%d\n", ret);
 151
 152        return ret;
 153}
 154
 155int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set)
 156{
 157        u8 byte;
 158        int ret;
 159
 160        ret = pmic_reg_read(dev, reg);
 161        if (ret < 0)
 162                return ret;
 163        byte = (ret & ~clr) | set;
 164
 165        return pmic_reg_write(dev, reg, byte);
 166}
 167
 168UCLASS_DRIVER(pmic) = {
 169        .id             = UCLASS_PMIC,
 170        .name           = "pmic",
 171};
 172