Commit d308c0136d8a530d4846ab08ce02e6d40614d7e7

Authored by Simon Glass
1 parent 1c88b67ec8

dm: power: Add support for the S5M8767 PMIC

This PMIC is used with SoCs which need a combination of BUCKs and LDOs. The
driver supports probing and basic register access. It supports the standard
device tree binding and supports driver model. A regulator driver can be
provided also.

Signed-off-by: Simon Glass <sjg@chromium.org>
Acked-by: Przemyslaw Marczak <p.marczak@samsung.com>

Showing 4 changed files with 191 additions and 0 deletions Side-by-side Diff

drivers/power/pmic/Kconfig
... ... @@ -42,6 +42,15 @@
42 42  
43 43 Driver binding info: doc/device-tree-bindings/pmic/sandbox.txt
44 44  
  45 +config PMIC_S5M8767
  46 + bool "Enable Driver Model for the Samsung S5M8767 PMIC"
  47 + depends on DM_PMIC
  48 + ---help---
  49 + The S5M8767 PMIC provides a large array of LDOs and BUCKs for use
  50 + as a SoC power controller. It also provides 32KHz clock outputs. This
  51 + driver provides basic register access and sets up the attached
  52 + regulators if regulator support is enabled.
  53 +
45 54 config PMIC_TPS65090
46 55 bool "Enable driver for Texas Instruments TPS65090 PMIC"
47 56 depends on DM_PMIC
drivers/power/pmic/Makefile
... ... @@ -9,6 +9,8 @@
9 9 obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
10 10 obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
11 11 obj-$(CONFIG_PMIC_TPS65090) += tps65090.o
  12 +obj-$(CONFIG_PMIC_S5M8767) += s5m8767.o
  13 +
12 14 obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o
13 15 obj-$(CONFIG_POWER_MAX77696) += pmic_max77696.o
14 16 obj-$(CONFIG_POWER_MAX8998) += pmic_max8998.o
drivers/power/pmic/s5m8767.c
  1 +/*
  2 + * Copyright (C) 2015 Google, Inc
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + */
  6 +
  7 +#include <common.h>
  8 +#include <fdtdec.h>
  9 +#include <errno.h>
  10 +#include <dm.h>
  11 +#include <i2c.h>
  12 +#include <power/pmic.h>
  13 +#include <power/regulator.h>
  14 +#include <power/s5m8767.h>
  15 +
  16 +DECLARE_GLOBAL_DATA_PTR;
  17 +
  18 +static const struct pmic_child_info pmic_children_info[] = {
  19 + { .prefix = "LDO", .driver = S5M8767_LDO_DRIVER },
  20 + { .prefix = "BUCK", .driver = S5M8767_BUCK_DRIVER },
  21 + { },
  22 +};
  23 +
  24 +static int s5m8767_reg_count(struct udevice *dev)
  25 +{
  26 + return S5M8767_NUM_OF_REGS;
  27 +}
  28 +
  29 +static int s5m8767_write(struct udevice *dev, uint reg, const uint8_t *buff,
  30 + int len)
  31 +{
  32 + if (dm_i2c_write(dev, reg, buff, len)) {
  33 + error("write error to device: %p register: %#x!", dev, reg);
  34 + return -EIO;
  35 + }
  36 +
  37 + return 0;
  38 +}
  39 +
  40 +static int s5m8767_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
  41 +{
  42 + if (dm_i2c_read(dev, reg, buff, len)) {
  43 + error("read error from device: %p register: %#x!", dev, reg);
  44 + return -EIO;
  45 + }
  46 +
  47 + return 0;
  48 +}
  49 +
  50 +int s5m8767_enable_32khz_cp(struct udevice *dev)
  51 +{
  52 + return pmic_clrsetbits(dev, S5M8767_EN32KHZ_CP, 0, 1 << 1);
  53 +}
  54 +
  55 +static int s5m8767_bind(struct udevice *dev)
  56 +{
  57 + int node;
  58 + const void *blob = gd->fdt_blob;
  59 + int children;
  60 +
  61 + node = fdt_subnode_offset(blob, dev->of_offset, "regulators");
  62 + if (node <= 0) {
  63 + debug("%s: %s regulators subnode not found!", __func__,
  64 + dev->name);
  65 + return -ENXIO;
  66 + }
  67 +
  68 + debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
  69 +
  70 + children = pmic_bind_children(dev, node, pmic_children_info);
  71 + if (!children)
  72 + debug("%s: %s - no child found\n", __func__, dev->name);
  73 +
  74 + /* Always return success for this device */
  75 + return 0;
  76 +}
  77 +
  78 +static struct dm_pmic_ops s5m8767_ops = {
  79 + .reg_count = s5m8767_reg_count,
  80 + .read = s5m8767_read,
  81 + .write = s5m8767_write,
  82 +};
  83 +
  84 +static const struct udevice_id s5m8767_ids[] = {
  85 + { .compatible = "samsung,s5m8767-pmic" },
  86 + { }
  87 +};
  88 +
  89 +U_BOOT_DRIVER(pmic_s5m8767) = {
  90 + .name = "s5m8767_pmic",
  91 + .id = UCLASS_PMIC,
  92 + .of_match = s5m8767_ids,
  93 + .bind = s5m8767_bind,
  94 + .ops = &s5m8767_ops,
  95 +};
include/power/s5m8767.h
  1 +/*
  2 + * Copyright (c) 2015 Google, Inc
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + */
  6 +
  7 +#ifndef __S5M8767_H_
  8 +#define __S5M8767_H_
  9 +
  10 +enum s5m8767_regnum {
  11 + S5M8767_BUCK1 = 0,
  12 + S5M8767_BUCK2,
  13 + S5M8767_BUCK3,
  14 + S5M8767_BUCK4,
  15 + S5M8767_BUCK5,
  16 + S5M8767_BUCK6,
  17 + S5M8767_BUCK7,
  18 + S5M8767_BUCK8,
  19 + S5M8767_BUCK9,
  20 + S5M8767_LDO1,
  21 + S5M8767_LDO2,
  22 + S5M8767_LDO3,
  23 + S5M8767_LDO4,
  24 + S5M8767_LDO5,
  25 + S5M8767_LDO6,
  26 + S5M8767_LDO7,
  27 + S5M8767_LDO8,
  28 + S5M8767_LDO9,
  29 + S5M8767_LDO10,
  30 + S5M8767_LDO11,
  31 + S5M8767_LDO12,
  32 + S5M8767_LDO13,
  33 + S5M8767_LDO14,
  34 + S5M8767_LDO15,
  35 + S5M8767_LDO16,
  36 + S5M8767_LDO17,
  37 + S5M8767_LDO18,
  38 + S5M8767_LDO19,
  39 + S5M8767_LDO20,
  40 + S5M8767_LDO21,
  41 + S5M8767_LDO22,
  42 + S5M8767_LDO23,
  43 + S5M8767_LDO24,
  44 + S5M8767_LDO25,
  45 + S5M8767_LDO26,
  46 + S5M8767_LDO27,
  47 + S5M8767_LDO28,
  48 + S5M8767_EN32KHZ_CP,
  49 +
  50 + S5M8767_NUM_OF_REGS,
  51 +};
  52 +
  53 +struct sec_voltage_desc {
  54 + int max;
  55 + int min;
  56 + int step;
  57 +};
  58 +
  59 +/**
  60 + * struct s5m8767_para - s5m8767 register parameters
  61 + * @param vol_addr i2c address of the given buck/ldo register
  62 + * @param vol_bitpos bit position to be set or clear within register
  63 + * @param vol_bitmask bit mask value
  64 + * @param reg_enaddr control register address, which enable the given
  65 + * given buck/ldo.
  66 + * @param reg_enbiton value to be written to buck/ldo to make it ON
  67 + * @param vol Voltage information
  68 + */
  69 +struct s5m8767_para {
  70 + enum s5m8767_regnum regnum;
  71 + u8 vol_addr;
  72 + u8 vol_bitpos;
  73 + u8 vol_bitmask;
  74 + u8 reg_enaddr;
  75 + u8 reg_enbiton;
  76 + const struct sec_voltage_desc *vol;
  77 +};
  78 +
  79 +/* Drivers name */
  80 +#define S5M8767_LDO_DRIVER "s5m8767_ldo"
  81 +#define S5M8767_BUCK_DRIVER "s5m8767_buck"
  82 +
  83 +int s5m8767_enable_32khz_cp(struct udevice *dev);
  84 +
  85 +#endif /* __S5M8767_PMIC_H_ */