[U-Boot] [PATCH v2 04/12] dm: pmic: add implementation of driver model regulator uclass

Przemyslaw Marczak
2015-03-25T16:08:24Z

Hello Robert,

On 03/10/2015 12:41 PM, Robert Baldyga wrote:
> Hi,
>
> On 03/03/2015 05:24 PM, Przemyslaw Marczak wrote:
>> This is the implementation of driver model regulator uclass api.
>> To use it, the CONFIG_DM_PMIC is required with driver implementation,
>> since it provides pmic devices basic I/O API.
>>
>> The regulator framework is based on a 'struct dm_regulator_ops'.
>> It provides a common function calls, for it's basic features:
>> - regulator_get_cnt() - number of outputs each type
>> - regulator_get_value_desc() - describe output value limits
>> - regulator_get_mode_desc() - describe output operation modes
>> - regulator_get/set_value() - output value (uV)
>> - regulator_get/set_state() - output on/off state
>> - regulator_get/set_mode() - output operation mode
>>
>> To get the regulator device:
>> - regulator_get() - by name only
>> - regulator_i2c_get() - by i2c bus address (of pmic parent)
>> - regulator_spi_get() - by spi bus address (of pmic parent)
>>
>> An optional and useful regulator framework features are two descriptors:
>> - struct regulator_desc - describes the regulator name and output value limits
>> should be defined by device driver for each regulator output.
>>
>> - struct regulator_mode_desc - (array) describes a number of operation modes
>> supported by each regulator output.
>>
>> The regulator framework features are described in file:
>> - include/power/regulator.h
>>
>> Main files:
>> - drivers/power/regulator-uclass.c - provides regulator common functions api
>> - include/power/regulator.h - define all structures required by the regulator
>>
>> Changes:
>> - new uclass-id: UCLASS_PMIC_REGULATOR
>> - new config: CONFIG_DM_REGULATOR
>>
>> Signed-off-by: Przemyslaw Marczak <p.marczak@samsung.com>
>> ---
>> Changes V2:
>> - new operations for regulator uclass:
>> -- get/set output state - for output on/off setting
>> --- add enum: REGULATOR_OFF, REGULATOR_ON
>>
>> - regulator uclass code rework and cleanup:
>> -- change name of:
>> --- enum 'regulator_desc_type' to 'regulator_type'
>> --- add type DVS
>> --- struct 'regulator_desc' to 'regulator_value_desc'
>>
>> -- regulator ops function calls:
>> --- remove 'ldo/buck' from naming
>> --- add new argument 'type' for define regulator type
>>
>> -- regulator.h - update comments
>> ---
>> drivers/power/Makefile | 1 +
>> drivers/power/regulator-uclass.c | 227 ++++++++++++++++++++++++++++
>> include/dm/uclass-id.h | 1 +
>> include/power/regulator.h | 310 +++++++++++++++++++++++++++++++++++++++
>> 4 files changed, 539 insertions(+)
>> create mode 100644 drivers/power/regulator-uclass.c
>> create mode 100644 include/power/regulator.h
>>
>> diff --git a/drivers/power/Makefile b/drivers/power/Makefile
>> index 5c9a189..a6b7012 100644
>> --- a/drivers/power/Makefile
>> +++ b/drivers/power/Makefile
>> @@ -22,3 +22,4 @@ obj-$(CONFIG_POWER_FSL) += power_fsl.o
>> obj-$(CONFIG_POWER_I2C) += power_i2c.o
>> obj-$(CONFIG_POWER_SPI) += power_spi.o
>> obj-$(CONFIG_DM_PMIC) += pmic-uclass.o
>> +obj-$(CONFIG_DM_REGULATOR) += regulator-uclass.o
>> diff --git a/drivers/power/regulator-uclass.c b/drivers/power/regulator-uclass.c
>> new file mode 100644
>> index 0000000..6b5c678
>> --- /dev/null
>> +++ b/drivers/power/regulator-uclass.c
>> @@ -0,0 +1,227 @@
>> +/*
>> + * Copyright (C) 2014-2015 Samsung Electronics
>> + * Przemyslaw Marczak <p.marczak@samsung.com>
>> + *
>> + * SPDX-License-Identifier: GPL-2.0+
>> + */
>> +#include <common.h>
>> +#include <linux/types.h>
>> +#include <fdtdec.h>
>> +#include <dm.h>
>> +#include <power/pmic.h>
>> +#include <power/regulator.h>
>> +#include <compiler.h>
>> +#include <dm/device.h>
>> +#include <dm/lists.h>
>> +#include <dm/device-internal.h>
>> +#include <errno.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +int regulator_get_cnt(struct udevice *dev, int type, int *cnt)
>> +{
>> + const struct dm_regulator_ops *ops;
>> +
>> + ops = pmic_get_uclass_ops(dev, UCLASS_PMIC_REGULATOR);
>> + if (!ops)
>> + return -ENODEV;
>> +
>> + if (!ops->get_cnt)
>> + return -EPERM;
>> +
>> + return ops->get_cnt(dev, type, cnt);
>> +}
>> +
>> +int regulator_get_value_desc(struct udevice *dev, int type, int number,
>> + struct regulator_value_desc **desc)
>> +{
>> + const struct dm_regulator_ops *ops;
>> +
>> + ops = pmic_get_uclass_ops(dev, UCLASS_PMIC_REGULATOR);
>> + if (!ops)
>> + return -ENXIO;
>> +
>> + if (!ops->get_value_desc)
>> + return -EPERM;
>> +
>> + return ops->get_value_desc(dev, type, number, desc);
>> +}
>> +
>> +int regulator_get_mode_desc(struct udevice *dev, int type, int number,
>> + int *mode_cnt, struct regulator_mode_desc **desc)
>> +{
>> + const struct dm_regulator_ops *ops;
>> +
>> + ops = pmic_get_uclass_ops(dev, UCLASS_PMIC_REGULATOR);
>> + if (!ops)
>> + return -ENXIO;
>> +
>> + if (!ops->get_mode_desc_array)
>> + return -EPERM;
>> +
>> + return ops->get_mode_desc_array(dev, type, number, mode_cnt, desc);
>> +}
>> +
>> +int regulator_get_value(struct udevice *dev, int type, int number, int *value)
>> +{
>> + const struct dm_regulator_ops *ops;
>> +
>> + ops = pmic_get_uclass_ops(dev, UCLASS_PMIC_REGULATOR);
>> + if (!ops)
>> + return -ENODEV;
>> +
>> + if (!ops->get_value)
>> + return -EPERM;
>> +
>> + return ops->get_value(dev, type, number, value);
>> +}
>> +
>> +int regulator_set_value(struct udevice *dev, int type, int number, int value)
>> +{
>> + const struct dm_regulator_ops *ops;
>> +
>> + ops = pmic_get_uclass_ops(dev, UCLASS_PMIC_REGULATOR);
>> + if (!ops)
>> + return -ENODEV;
>> +
>> + if (!ops->set_value)
>> + return -EPERM;
>> +
>> + return ops->set_value(dev, type, number, value);
>> +}
>> +
>> +int regulator_get_state(struct udevice *dev, int type, int number, int *state)
>> +{
>> + const struct dm_regulator_ops *ops;
>> +
>> + ops = pmic_get_uclass_ops(dev, UCLASS_PMIC_REGULATOR);
>> + if (!ops)
>> + return -ENODEV;
>> +
>> + if (!ops->get_state)
>> + return -EPERM;
>> +
>> + return ops->get_state(dev, type, number, state);
>> +}
>> +
>> +int regulator_set_state(struct udevice *dev, int type, int number, int state)
>> +{
>> + const struct dm_regulator_ops *ops;
>> +
>> + ops = pmic_get_uclass_ops(dev, UCLASS_PMIC_REGULATOR);
>> + if (!ops)
>> + return -ENODEV;
>> +
>> + if (!ops->set_state)
>> + return -EPERM;
>> +
>> + return ops->set_state(dev, type, number, state);
>> +}
>> +
>> +int regulator_get_mode(struct udevice *dev, int type, int number, int *mode)
>> +{
>> + const struct dm_regulator_ops *ops;
>> +
>> + ops = pmic_get_uclass_ops(dev, UCLASS_PMIC_REGULATOR);
>> + if (!ops)
>> + return -ENODEV;
>> +
>> + if (!ops->get_mode)
>> + return -EPERM;
>> +
>> + return ops->get_mode(dev, type, number, mode);
>> +}
>> +
>> +int regulator_set_mode(struct udevice *dev, int type, int number, int mode)
>> +{
>> + const struct dm_regulator_ops *ops;
>> +
>> + ops = pmic_get_uclass_ops(dev, UCLASS_PMIC_REGULATOR);
>> + if (!ops)
>> + return -ENODEV;
>> +
>> + if (!ops->set_mode)
>> + return -EPERM;
>> +
>> + return ops->set_mode(dev, type, number, mode);
>> +}
>> +
>> +int regulator_get(char *name, struct udevice **regulator)
>> +{
>> + struct udevice *dev;
>> + struct uclass *uc;
>> + int ret;
>> +
>> + ret = uclass_get(UCLASS_PMIC_REGULATOR, &uc);
>> + if (ret) {
>> + error("Regulator uclass not initialized!");
>> + return ret;
>> + }
>> +
>> + uclass_foreach_dev(dev, uc) {
>> + if (!dev)
>> + continue;
>> +
>> + if (!strncmp(name, dev->name, strlen(name))) {
>> + ret = device_probe(dev);
>> + if (ret)
>> + error("Dev: %s probe failed", dev->name);
>> + *regulator = dev;
>
> Shouldn't we set regulator=NULL if device_probe() returns an error?
>

Thanks, this is fixed in V3.

>
> Br,
> Robert
>

Best regards,
--
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com