Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions components/drivers/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ rsource "ata/Kconfig"
rsource "block/Kconfig"
rsource "nvme/Kconfig"
rsource "scsi/Kconfig"
rsource "regulator/Kconfig"
rsource "reset/Kconfig"
rsource "virtio/Kconfig"
rsource "dma/Kconfig"
Expand Down
153 changes: 153 additions & 0 deletions components/drivers/include/drivers/regulator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-09-23 GuEe-GUI first version
*/

#ifndef __REGULATOR_H__
#define __REGULATOR_H__

#include <ref.h>
#include <rthw.h>
#include <rtthread.h>

#include <drivers/misc.h>

#define RT_REGULATOR_UVOLT_INVALID (((int)(RT_UINT32_MAX >> 1)))

struct rt_regulator_param
{
const char *name;

int min_uvolt; /* In uV */
int max_uvolt; /* In uV */
int min_uamp; /* In uA */
int max_uamp; /* In uA */
int ramp_delay; /* In uV/usec */
int enable_delay; /* In usec */
int off_on_delay; /* In usec */

rt_uint32_t enable_active_high:1;
rt_uint32_t boot_on:1; /* Is enabled on boot */
rt_uint32_t always_on:1; /* Must be enabled */
rt_uint32_t soft_start:1; /* Ramp voltage slowly */
rt_uint32_t pull_down:1; /* Pull down resistor when regulator off */
rt_uint32_t over_current_protection:1; /* Auto disable on over current */
};

struct rt_regulator_ops;

struct rt_regulator_node
{
rt_list_t list;
rt_list_t children_nodes;

struct rt_device *dev;
struct rt_regulator_node *parent;

const char *supply_name;
const struct rt_regulator_ops *ops;

struct rt_ref ref;
rt_atomic_t enabled_count;

const struct rt_regulator_param *param;

rt_list_t notifier_nodes;

void *priv;
};

/*
* NOTE: Power regulator control is dangerous work. We don't want non-internal
* consumer could access the power regulator tree without regulator's API. So
* we defined the `rt_regulator` member in core instead of here.
*/
struct rt_regulator;

#define RT_REGULATOR_MODE_INVALID 0
#define RT_REGULATOR_MODE_FAST RT_BIT(0)
#define RT_REGULATOR_MODE_NORMAL RT_BIT(1)
#define RT_REGULATOR_MODE_IDLE RT_BIT(2)
#define RT_REGULATOR_MODE_STANDBY RT_BIT(3)

struct rt_regulator_ops
{
rt_err_t (*enable)(struct rt_regulator_node *reg);
rt_err_t (*disable)(struct rt_regulator_node *reg);
rt_bool_t (*is_enabled)(struct rt_regulator_node *reg);
rt_err_t (*set_voltage)(struct rt_regulator_node *reg, int min_uvolt, int max_uvolt);
int (*get_voltage)(struct rt_regulator_node *reg);
rt_err_t (*set_mode)(struct rt_regulator_node *reg, rt_uint32_t mode);
rt_int32_t (*get_mode)(struct rt_regulator_node *reg);
rt_err_t (*set_ramp_delay)(struct rt_regulator_node *reg, int ramp);
rt_uint32_t (*enable_time)(struct rt_regulator_node *reg);
};

struct rt_regulator_notifier;

#define RT_REGULATOR_MSG_ENABLE RT_BIT(0)
#define RT_REGULATOR_MSG_DISABLE RT_BIT(1)
#define RT_REGULATOR_MSG_VOLTAGE_CHANGE RT_BIT(2)
#define RT_REGULATOR_MSG_VOLTAGE_CHANGE_ERR RT_BIT(3)

union rt_regulator_notifier_args
{
struct
{
int old_uvolt;
int min_uvolt;
int max_uvolt;
};
};

typedef rt_err_t (*rt_regulator_notifier_callback)(struct rt_regulator_notifier *notifier,
rt_ubase_t msg, void *data);

struct rt_regulator_notifier
{
rt_list_t list;

struct rt_regulator *regulator;
rt_regulator_notifier_callback callback;
void *priv;
};

rt_err_t rt_regulator_register(struct rt_regulator_node *reg_np);
rt_err_t rt_regulator_unregister(struct rt_regulator_node *reg_np);

rt_err_t rt_regulator_notifier_register(struct rt_regulator *reg,
struct rt_regulator_notifier *notifier);
rt_err_t rt_regulator_notifier_unregister(struct rt_regulator *reg,
struct rt_regulator_notifier *notifier);

struct rt_regulator *rt_regulator_get(struct rt_device *dev, const char *id);
void rt_regulator_put(struct rt_regulator *reg);

rt_err_t rt_regulator_enable(struct rt_regulator *reg);
rt_err_t rt_regulator_disable(struct rt_regulator *reg);
rt_bool_t rt_regulator_is_enabled(struct rt_regulator *reg);

rt_bool_t rt_regulator_is_supported_voltage(struct rt_regulator *reg, int min_uvolt, int max_uvolt);
rt_err_t rt_regulator_set_voltage(struct rt_regulator *reg, int min_uvolt, int max_uvolt);
int rt_regulator_get_voltage(struct rt_regulator *reg);

rt_err_t rt_regulator_set_mode(struct rt_regulator *reg, rt_uint32_t mode);
rt_int32_t rt_regulator_get_mode(struct rt_regulator *reg);

rt_inline rt_err_t rt_regulator_set_voltage_triplet(struct rt_regulator *reg,
int min_uvolt, int target_uvolt, int max_uvolt)
{
if (!rt_regulator_set_voltage(reg, target_uvolt, max_uvolt))
{
return RT_EOK;
}

return rt_regulator_set_voltage(reg, min_uvolt, max_uvolt);
}

#endif /* __REGULATOR_H__ */
4 changes: 4 additions & 0 deletions components/drivers/include/rtdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ extern "C" {
#include "drivers/pic.h"
#endif /* RT_USING_PIC */

#ifdef RT_USING_REGULATOR
#include "drivers/regulator.h"
#endif /* RT_USING_REGULATOR */

#ifdef RT_USING_RESET
#include "drivers/reset.h"
#endif /* RT_USING_RESET */
Expand Down
23 changes: 23 additions & 0 deletions components/drivers/regulator/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
menuconfig RT_USING_REGULATOR
bool "Using Voltage and Current Regulator"
select RT_USING_ADT
select RT_USING_ADT_REF
depends on RT_USING_DM
default n

config RT_REGULATOR_FIXED
bool "Fixed regulator support"
depends on RT_USING_REGULATOR
depends on RT_USING_PIN
depends on RT_USING_PINCTRL
default y

config RT_REGULATOR_GPIO
bool "GPIO regulator support"
depends on RT_USING_REGULATOR
depends on RT_USING_PIN
default y

if RT_USING_REGULATOR
osource "$(SOC_DM_REGULATOR_DIR)/Kconfig"
endif
21 changes: 21 additions & 0 deletions components/drivers/regulator/SConscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from building import *

group = []

if not GetDepend(['RT_USING_REGULATOR']):
Return('group')

cwd = GetCurrentDir()
CPPPATH = [cwd + '/../include']

src = ['regulator.c', 'regulator_dm.c']

if GetDepend(['RT_REGULATOR_FIXED']):
src += ['regulator-fixed.c']

if GetDepend(['RT_REGULATOR_GPIO']):
src += ['regulator-gpio.c']

group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)

Return('group')
171 changes: 171 additions & 0 deletions components/drivers/regulator/regulator-fixed.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-09-23 GuEe-GUI first version
*/

#include "regulator_dm.h"

struct regulator_fixed
{
struct rt_regulator_node parent;
struct rt_regulator_param param;

rt_base_t enable_pin;
const char *input_supply;
};

#define raw_to_regulator_fixed(raw) rt_container_of(raw, struct regulator_fixed, parent)

static rt_err_t regulator_fixed_enable(struct rt_regulator_node *reg_np)
{
struct regulator_fixed *rf = raw_to_regulator_fixed(reg_np);
struct rt_regulator_param *param = &rf->param;

if (rf->enable_pin < 0 || param->always_on)
{
return RT_EOK;
}

rt_pin_mode(rf->enable_pin, PIN_MODE_OUTPUT);
rt_pin_write(rf->enable_pin, param->enable_active_high ? PIN_HIGH : PIN_LOW);

return RT_EOK;
}

static rt_err_t regulator_fixed_disable(struct rt_regulator_node *reg_np)
{
struct regulator_fixed *rf = raw_to_regulator_fixed(reg_np);
struct rt_regulator_param *param = &rf->param;

if (rf->enable_pin < 0 || param->always_on)
{
return RT_EOK;
}

rt_pin_mode(rf->enable_pin, PIN_MODE_OUTPUT);
rt_pin_write(rf->enable_pin, param->enable_active_high ? PIN_LOW: PIN_HIGH);

return RT_EOK;
}

static rt_bool_t regulator_fixed_is_enabled(struct rt_regulator_node *reg_np)
{
rt_uint8_t active;
struct regulator_fixed *rf = raw_to_regulator_fixed(reg_np);
struct rt_regulator_param *param = &rf->param;

if (rf->enable_pin < 0 || param->always_on)
{
return RT_TRUE;
}

rt_pin_mode(rf->enable_pin, PIN_MODE_INPUT);
active = rt_pin_read(rf->enable_pin);

if (param->enable_active_high)
{
return active == PIN_HIGH;
}

return active == PIN_LOW;
}

static int regulator_fixed_get_voltage(struct rt_regulator_node *reg_np)
{
struct regulator_fixed *rf = raw_to_regulator_fixed(reg_np);

return rf->param.min_uvolt + (rf->param.max_uvolt - rf->param.min_uvolt) / 2;
}

static const struct rt_regulator_ops regulator_fixed_ops =
{
.enable = regulator_fixed_enable,
.disable = regulator_fixed_disable,
.is_enabled = regulator_fixed_is_enabled,
.get_voltage = regulator_fixed_get_voltage,
};

static rt_err_t regulator_fixed_probe(struct rt_platform_device *pdev)
{
rt_err_t err;
rt_uint32_t val;
struct rt_device *dev = &pdev->parent;
struct regulator_fixed *rf = rt_calloc(1, sizeof(*rf));
struct rt_regulator_node *rnp;

if (!rf)
{
return -RT_ENOMEM;
}

regulator_ofw_parse(dev->ofw_node, &rf->param);

rnp = &rf->parent;
rnp->supply_name = rf->param.name;
rnp->ops = &regulator_fixed_ops;
rnp->param = &rf->param;
rnp->dev = &pdev->parent;

rf->enable_pin = rt_pin_get_named_pin(dev, "enable", 0, RT_NULL, RT_NULL);

if (rf->enable_pin < 0)
{
rf->enable_pin = rt_pin_get_named_pin(dev, RT_NULL, 0, RT_NULL, RT_NULL);
}

if (rf->enable_pin < 0)
{
rf->enable_pin = -1;
}

rt_pin_ctrl_confs_apply(dev, 0);

if (!rt_dm_dev_prop_read_u32(dev, "startup-delay-us", &val))
{
rf->param.enable_delay = val;
}

if (!rt_dm_dev_prop_read_u32(dev, "off-on-delay-us", &val))
{
rf->param.off_on_delay = val;
}

if ((err = rt_regulator_register(rnp)))
{
goto _fail;
}

return RT_EOK;

_fail:
rt_free(rf);

return err;
}

static const struct rt_ofw_node_id regulator_fixed_ofw_ids[] =
{
{ .compatible = "regulator-fixed" },
{ /* sentinel */ }
};

static struct rt_platform_driver regulator_fixed_driver =
{
.name = "reg-fixed-voltage",
.ids = regulator_fixed_ofw_ids,

.probe = regulator_fixed_probe,
};

static int regulator_fixed_register(void)
{
rt_platform_driver_register(&regulator_fixed_driver);

return 0;
}
INIT_SUBSYS_EXPORT(regulator_fixed_register);
Loading
Loading