driver:power:add regulator framework
N/A Signed-off-by: zhuyanlin <zhuyanlin1@xiaomi.com>
This commit is contained in:
parent
bec9058b4c
commit
c8f1a9e430
@ -343,6 +343,14 @@ menuconfig POWER
|
||||
|
||||
if POWER
|
||||
|
||||
config REGULATOR
|
||||
bool "Regulator core driver support"
|
||||
default n
|
||||
---help---
|
||||
The regulator core driver implements the uper layer framework that the lower
|
||||
layer driver can register with, and the common regulator APIs that are easy
|
||||
for other drivers to call for the control of their power supply.
|
||||
|
||||
config BATTERY_CHARGER
|
||||
bool "Battery Charger support"
|
||||
default n
|
||||
|
@ -71,6 +71,16 @@ POWER_CFLAGS := ${shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)power}
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_REGULATOR), y)
|
||||
|
||||
CSRCS += regulator.c
|
||||
|
||||
POWER_DEPPATH := --dep-path power
|
||||
POWER_VPATH := :power
|
||||
POWER_CFLAGS := ${shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)power}
|
||||
|
||||
endif
|
||||
|
||||
# Add battery charger drivers
|
||||
|
||||
ifeq ($(CONFIG_BATTERY_CHARGER),y)
|
||||
|
772
drivers/power/regulator.c
Normal file
772
drivers/power/regulator.c
Normal file
@ -0,0 +1,772 @@
|
||||
/****************************************************************************
|
||||
* drivers/power/regulator.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/power/regulator.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int _regulator_is_enabled(FAR struct regulator_dev_s *rdev);
|
||||
static int _regulator_do_enable(FAR struct regulator_dev_s *rdev);
|
||||
static int _regulator_do_disable(FAR struct regulator_dev_s *rdev);
|
||||
static int regulator_check_consumers(FAR struct regulator_dev_s *rdev,
|
||||
FAR int *min_uv, FAR int *max_uv);
|
||||
static FAR struct regulator_dev_s *regulator_dev_lookup(const char *supply);
|
||||
static int regulator_map_voltage_iterate(FAR struct regulator_dev_s *rdev,
|
||||
int min_uv, int max_uv);
|
||||
static int _regulator_get_voltage(FAR struct regulator_dev_s *rdev);
|
||||
static int _regulator_do_set_voltage(FAR struct regulator_dev_s *rdev,
|
||||
int min_uv, int max_uv);
|
||||
static int _regulator_set_voltage_unlocked(FAR struct regulator_s *regulator,
|
||||
int min_uv, int max_uv);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct list_node g_reg_list = LIST_INITIAL_VALUE(g_reg_list);
|
||||
static sem_t g_reg_sem = SEM_INITIALIZER(1);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int _regulator_is_enabled(FAR struct regulator_dev_s *rdev)
|
||||
{
|
||||
if (!rdev->ops->is_enabled)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return rdev->ops->is_enabled(rdev);
|
||||
}
|
||||
|
||||
static int _regulator_do_enable(FAR struct regulator_dev_s *rdev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (rdev->ops->enable)
|
||||
{
|
||||
ret = rdev->ops->enable(rdev);
|
||||
if (ret < 0)
|
||||
{
|
||||
pwrerr("failed to enable %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (rdev->desc->enable_time > 0)
|
||||
{
|
||||
up_udelay(rdev->desc->enable_time);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _regulator_do_disable(FAR struct regulator_dev_s *rdev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (rdev->ops->disable)
|
||||
{
|
||||
ret = rdev->ops->disable(rdev);
|
||||
if (ret < 0)
|
||||
{
|
||||
pwrerr("failed to disable %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int regulator_check_consumers(FAR struct regulator_dev_s *rdev,
|
||||
FAR int *min_uv, FAR int *max_uv)
|
||||
{
|
||||
FAR struct regulator_s *regulator;
|
||||
|
||||
list_for_every_entry(&rdev->consumer_list, regulator,
|
||||
struct regulator_s, list)
|
||||
{
|
||||
if (!regulator->min_uv && !regulator->max_uv)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*max_uv > regulator->max_uv)
|
||||
{
|
||||
*max_uv = regulator->max_uv;
|
||||
}
|
||||
|
||||
if (*min_uv < regulator->min_uv)
|
||||
{
|
||||
*min_uv = regulator->min_uv;
|
||||
}
|
||||
}
|
||||
|
||||
if (*min_uv > *max_uv)
|
||||
{
|
||||
pwrerr("Restricting voltage, %d-%d uv\n", *min_uv, *max_uv);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FAR struct regulator_dev_s *regulator_dev_lookup(const char *supply)
|
||||
{
|
||||
FAR struct regulator_dev_s *rdev;
|
||||
FAR struct regulator_dev_s *rdev_found = NULL;
|
||||
|
||||
nxsem_wait_uninterruptible(&g_reg_sem);
|
||||
list_for_every_entry(&g_reg_list, rdev, struct regulator_dev_s, list)
|
||||
{
|
||||
if (rdev->desc->name && strcmp(rdev->desc->name, supply) == 0)
|
||||
{
|
||||
rdev_found = rdev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nxsem_post(&g_reg_sem);
|
||||
|
||||
return rdev_found;
|
||||
}
|
||||
|
||||
static int regulator_map_voltage_iterate(FAR struct regulator_dev_s *rdev,
|
||||
int min_uv, int max_uv)
|
||||
{
|
||||
int best_val = INT_MAX;
|
||||
int selector = 0;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < rdev->desc->n_voltages; i++)
|
||||
{
|
||||
ret = rdev->ops->list_voltage(rdev, i);
|
||||
if (ret < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret < best_val && ret >= min_uv && ret <= max_uv)
|
||||
{
|
||||
best_val = ret;
|
||||
selector = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (best_val != INT_MAX)
|
||||
{
|
||||
return selector;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int _regulator_get_voltage(FAR struct regulator_dev_s *rdev)
|
||||
{
|
||||
int sel;
|
||||
int ret;
|
||||
|
||||
if (rdev->ops->get_voltage_sel)
|
||||
{
|
||||
sel = rdev->ops->get_voltage_sel(rdev);
|
||||
if (sel < 0)
|
||||
{
|
||||
return sel;
|
||||
}
|
||||
|
||||
ret = rdev->ops->list_voltage(rdev, sel);
|
||||
}
|
||||
else if (rdev->ops->get_voltage)
|
||||
{
|
||||
ret = rdev->ops->get_voltage(rdev);
|
||||
}
|
||||
else if (rdev->ops->list_voltage)
|
||||
{
|
||||
ret = rdev->ops->list_voltage(rdev, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _regulator_do_set_voltage(FAR struct regulator_dev_s *rdev,
|
||||
int min_uv, int max_uv)
|
||||
{
|
||||
FAR const struct regulator_ops_s *ops = rdev->ops;
|
||||
unsigned int selector;
|
||||
int new_uv = 0;
|
||||
int old_uv = _regulator_get_voltage(rdev);
|
||||
int ret = 0;
|
||||
int delay = 0;
|
||||
int best_val;
|
||||
|
||||
if (ops->set_voltage)
|
||||
{
|
||||
ret = ops->set_voltage(rdev, min_uv, max_uv, &selector);
|
||||
if (ret >= 0)
|
||||
{
|
||||
if (ops->list_voltage)
|
||||
{
|
||||
new_uv = ops->list_voltage(rdev, selector);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_uv = _regulator_get_voltage(rdev);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ops->set_voltage_sel)
|
||||
{
|
||||
ret = regulator_map_voltage_iterate(rdev, min_uv, max_uv);
|
||||
if (ret >= 0)
|
||||
{
|
||||
best_val = ops->list_voltage(rdev, ret);
|
||||
if (min_uv <= best_val && max_uv >= best_val)
|
||||
{
|
||||
selector = ret;
|
||||
ret = ops->set_voltage_sel(rdev, selector);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -EINVAL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rdev->desc->ramp_delay)
|
||||
{
|
||||
delay = abs(new_uv - old_uv) / rdev->desc->ramp_delay + 1;
|
||||
}
|
||||
|
||||
up_udelay(delay);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _regulator_set_voltage_unlocked(FAR struct regulator_s *regulator,
|
||||
int min_uv, int max_uv)
|
||||
{
|
||||
FAR struct regulator_dev_s *rdev = regulator->rdev;
|
||||
FAR const struct regulator_ops_s *ops = rdev->ops;
|
||||
int old_min_uv;
|
||||
int old_max_uv;
|
||||
int ret = 0;
|
||||
|
||||
if (min_uv > max_uv)
|
||||
{
|
||||
pwrerr("invalid min %d max %d\n", min_uv, max_uv);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (regulator->min_uv == min_uv && regulator->max_uv == max_uv)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ops->set_voltage && !ops->set_voltage_sel)
|
||||
{
|
||||
pwrerr("set voltage is null\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (max_uv > rdev->desc->max_uv)
|
||||
{
|
||||
max_uv = rdev->desc->max_uv;
|
||||
}
|
||||
|
||||
if (min_uv < rdev->desc->min_uv)
|
||||
{
|
||||
min_uv = rdev->desc->min_uv;
|
||||
}
|
||||
|
||||
if (min_uv > max_uv)
|
||||
{
|
||||
pwrerr("invalid min %d max %d\n", min_uv, max_uv);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
old_min_uv = regulator->min_uv;
|
||||
old_max_uv = regulator->max_uv;
|
||||
regulator->min_uv = min_uv;
|
||||
regulator->max_uv = max_uv;
|
||||
|
||||
ret = regulator_check_consumers(rdev, &min_uv, &max_uv);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto out2;
|
||||
}
|
||||
|
||||
ret = _regulator_do_set_voltage(rdev, min_uv, max_uv);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto out2;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
||||
out2:
|
||||
regulator->min_uv = old_min_uv;
|
||||
regulator->max_uv = old_max_uv;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: regulator_get
|
||||
*
|
||||
* Description:
|
||||
* Lookup and obtain a reference to a regulator.
|
||||
*
|
||||
* Input parameters:
|
||||
* id - Supply name or the regulator ID.
|
||||
*
|
||||
* Returned value:
|
||||
* A struct regulator_s pointer on success or NULL on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct regulator_s *regulator_get(FAR const char *id)
|
||||
{
|
||||
FAR struct regulator_dev_s *rdev;
|
||||
FAR struct regulator_s *regulator = NULL;
|
||||
|
||||
if (id == NULL)
|
||||
{
|
||||
pwrerr("get() with no identifier\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rdev = regulator_dev_lookup(id);
|
||||
if (rdev == NULL)
|
||||
{
|
||||
pwrerr("regulator %s not found\n", id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
regulator = kmm_zalloc(sizeof(struct regulator_s));
|
||||
if (regulator == NULL)
|
||||
{
|
||||
pwrerr("failed to get memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
regulator->rdev = rdev;
|
||||
list_initialize(®ulator->list);
|
||||
|
||||
nxsem_wait_uninterruptible(&rdev->regulator_sem);
|
||||
rdev->open_count++;
|
||||
list_add_tail(&rdev->consumer_list, ®ulator->list);
|
||||
nxsem_post(&rdev->regulator_sem);
|
||||
|
||||
return regulator;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: regulator_put
|
||||
*
|
||||
* Description:
|
||||
* Free the regulator resource.
|
||||
*
|
||||
* Input parameters:
|
||||
* regulator - The regulator consumer representative
|
||||
*
|
||||
* Returned value:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void regulator_put(FAR struct regulator_s *regulator)
|
||||
{
|
||||
FAR struct regulator_dev_s *rdev;
|
||||
|
||||
if (regulator == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rdev = regulator->rdev;
|
||||
|
||||
nxsem_wait_uninterruptible(&g_reg_sem);
|
||||
|
||||
nxsem_wait_uninterruptible(&rdev->regulator_sem);
|
||||
list_delete(®ulator->list);
|
||||
rdev->open_count--;
|
||||
nxsem_post(&rdev->regulator_sem);
|
||||
|
||||
nxsem_post(&g_reg_sem);
|
||||
|
||||
kmm_free(regulator);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: regulator_is_enabled
|
||||
*
|
||||
* Description:
|
||||
* Is the regulator output enabled.
|
||||
*
|
||||
* Input parameters:
|
||||
* regulator - The regulator consumer representative
|
||||
*
|
||||
* Returned value:
|
||||
* 1 is enabled and zero for disabled.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int regulator_is_enabled(FAR struct regulator_s *regulator)
|
||||
{
|
||||
FAR struct regulator_dev_s *rdev;
|
||||
int ret = 0;
|
||||
|
||||
if (regulator == NULL)
|
||||
{
|
||||
pwrerr("regulator is null\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rdev = regulator->rdev;
|
||||
|
||||
nxsem_wait_uninterruptible(&rdev->regulator_sem);
|
||||
ret = _regulator_is_enabled(rdev);
|
||||
nxsem_post(&rdev->regulator_sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: regulator_enable
|
||||
*
|
||||
* Description:
|
||||
* Enable the regulator output.
|
||||
*
|
||||
* Input parameters:
|
||||
* regulator - The regulator consumer representative
|
||||
*
|
||||
* Returned value:
|
||||
* Zero on success or a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int regulator_enable(FAR struct regulator_s *regulator)
|
||||
{
|
||||
FAR struct regulator_dev_s *rdev;
|
||||
int ret = 0;
|
||||
|
||||
if (regulator == NULL)
|
||||
{
|
||||
pwrerr("enable regulator is null\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rdev = regulator->rdev;
|
||||
|
||||
nxsem_wait_uninterruptible(&rdev->regulator_sem);
|
||||
if (rdev->use_count == 0)
|
||||
{
|
||||
ret = _regulator_do_enable(rdev);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
rdev->use_count++;
|
||||
nxsem_post(&rdev->regulator_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: regulator_disable
|
||||
*
|
||||
* Description:
|
||||
* Disable the regulator output.
|
||||
*
|
||||
* Input parameters:
|
||||
* regulator - The regulator consumer representative
|
||||
*
|
||||
* Returned value:
|
||||
* Zero on success or a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int regulator_disable(FAR struct regulator_s *regulator)
|
||||
{
|
||||
FAR struct regulator_dev_s *rdev;
|
||||
int ret = 0;
|
||||
|
||||
if (regulator == NULL)
|
||||
{
|
||||
pwrerr("disable regulator is null\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rdev = regulator->rdev;
|
||||
|
||||
nxsem_wait_uninterruptible(&rdev->regulator_sem);
|
||||
if (rdev->use_count <= 0)
|
||||
{
|
||||
ret = -EIO;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (rdev->use_count == 1)
|
||||
{
|
||||
ret = _regulator_do_disable(rdev);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
rdev->use_count--;
|
||||
|
||||
err:
|
||||
nxsem_post(&rdev->regulator_sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: regulator_set_voltage
|
||||
*
|
||||
* Description:
|
||||
* Set the regulator output voltage.
|
||||
*
|
||||
* Input parameters:
|
||||
* regulator - The regulator consumer representative
|
||||
* min_uv - Minimum required voltage in uv
|
||||
* max_uv - Maximum acceptable voltage in uv
|
||||
*
|
||||
* Returned value:
|
||||
* Zero on success or a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int regulator_set_voltage(FAR struct regulator_s *regulator,
|
||||
int min_uv, int max_uv)
|
||||
{
|
||||
FAR struct regulator_dev_s *rdev;
|
||||
int ret = 0;
|
||||
|
||||
if (regulator == NULL)
|
||||
{
|
||||
pwrerr("get regulator is null\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rdev = regulator->rdev;
|
||||
|
||||
nxsem_wait_uninterruptible(&rdev->regulator_sem);
|
||||
ret = _regulator_set_voltage_unlocked(regulator, min_uv, max_uv);
|
||||
nxsem_post(&rdev->regulator_sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: regulator_get_voltage
|
||||
*
|
||||
* Description:
|
||||
* Obtain the regulator output voltage.
|
||||
*
|
||||
* Input parameters:
|
||||
* regulator - The regulator consumer representative
|
||||
*
|
||||
* Returned value:
|
||||
* Positive on success or a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int regulator_get_voltage(FAR struct regulator_s *regulator)
|
||||
{
|
||||
FAR struct regulator_dev_s *rdev;
|
||||
int ret = 0;
|
||||
|
||||
if (regulator == NULL)
|
||||
{
|
||||
pwrerr("get regulator is null\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rdev = regulator->rdev;
|
||||
|
||||
nxsem_wait_uninterruptible(&rdev->regulator_sem);
|
||||
ret = _regulator_get_voltage(rdev);
|
||||
nxsem_post(&rdev->regulator_sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: regulator_register
|
||||
*
|
||||
* Description:
|
||||
* This routine is called by the specific regulator drivers to register a
|
||||
* regulator.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct regulator_dev_s *
|
||||
regulator_register(const FAR struct regulator_desc_s *regulator_desc,
|
||||
const struct regulator_ops_s *regulator_ops,
|
||||
void *priv)
|
||||
{
|
||||
FAR struct regulator_dev_s *rdev;
|
||||
|
||||
if (regulator_desc == NULL)
|
||||
{
|
||||
pwrerr("regulator desc is null\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (regulator_desc->name == NULL || regulator_ops == NULL)
|
||||
{
|
||||
pwrerr("regulator name or ops is null\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (regulator_ops->get_voltage && regulator_ops->get_voltage_sel)
|
||||
{
|
||||
pwrerr("get_voltage and get_voltage_sel are assigned\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (regulator_ops->set_voltage && regulator_ops->set_voltage_sel)
|
||||
{
|
||||
pwrerr("set_voltage and set_voltage_sel are assigned\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (regulator_ops->get_voltage_sel && !regulator_ops->list_voltage)
|
||||
{
|
||||
pwrerr("list voltage is null\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (regulator_ops->set_voltage_sel && !regulator_ops->list_voltage)
|
||||
{
|
||||
pwrerr("list voltage is null\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rdev = kmm_zalloc(sizeof(struct regulator_dev_s));
|
||||
if (rdev == NULL)
|
||||
{
|
||||
pwrerr("failed to get memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rdev->desc = regulator_desc;
|
||||
rdev->ops = regulator_ops;
|
||||
rdev->priv = priv;
|
||||
nxsem_init(&rdev->regulator_sem, 0, 1);
|
||||
list_initialize(&rdev->consumer_list);
|
||||
list_initialize(&rdev->list);
|
||||
|
||||
if (rdev->desc->boot_on && !_regulator_is_enabled(rdev))
|
||||
{
|
||||
_regulator_do_enable(rdev);
|
||||
}
|
||||
else if (!rdev->desc->boot_on && _regulator_is_enabled(rdev))
|
||||
{
|
||||
_regulator_do_disable(rdev);
|
||||
}
|
||||
|
||||
if (rdev->desc->apply_uv)
|
||||
{
|
||||
_regulator_do_set_voltage(rdev, rdev->desc->apply_uv,
|
||||
rdev->desc->apply_uv);
|
||||
}
|
||||
|
||||
nxsem_wait_uninterruptible(&g_reg_sem);
|
||||
list_add_tail(&g_reg_list, &rdev->list);
|
||||
nxsem_post(&g_reg_sem);
|
||||
|
||||
return rdev;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: regulator_unregister
|
||||
*
|
||||
* Description:
|
||||
* This routine is called by the specific regulator drivers to unregister a
|
||||
* regulator.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void regulator_unregister(FAR struct regulator_dev_s *rdev)
|
||||
{
|
||||
if (rdev == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
nxsem_wait_uninterruptible(&g_reg_sem);
|
||||
if (rdev->open_count)
|
||||
{
|
||||
pwrerr("unregister, open %PRIu32\n", rdev->open_count);
|
||||
nxsem_post(&g_reg_sem);
|
||||
return;
|
||||
}
|
||||
|
||||
list_delete(&rdev->list);
|
||||
nxsem_post(&g_reg_sem);
|
||||
|
||||
kmm_free(rdev);
|
||||
}
|
75
include/nuttx/power/consumer.h
Normal file
75
include/nuttx/power/consumer.h
Normal file
@ -0,0 +1,75 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/power/consumer.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_POWER_CONSUMER_H
|
||||
#define __INCLUDE_NUTTX_POWER_CONSUMER_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <semaphore.h>
|
||||
#include <nuttx/power/regulator.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct regulator_s *regulator_get(const char *id);
|
||||
void regulator_put(FAR struct regulator_s *regulator);
|
||||
int regulator_is_enabled(FAR struct regulator_s *regulator);
|
||||
int regulator_enable(FAR struct regulator_s *regulator);
|
||||
int regulator_disable(FAR struct regulator_s *regulator);
|
||||
int regulator_set_voltage(FAR struct regulator_s *regulator, int min_uv,
|
||||
int max_uv);
|
||||
int regulator_get_voltage(FAR struct regulator_s *regulator);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __INCLUDE_NUTTX_POWER_CONSUMER_H */
|
162
include/nuttx/power/regulator.h
Normal file
162
include/nuttx/power/regulator.h
Normal file
@ -0,0 +1,162 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/power/regulator.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_POWER_REGULATOR_H
|
||||
#define __INCLUDE_NUTTX_POWER_REGULATOR_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#include <nuttx/list.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
struct regulator_dev_s;
|
||||
|
||||
struct regulator_s
|
||||
{
|
||||
int min_uv;
|
||||
int max_uv;
|
||||
struct list_node list;
|
||||
struct regulator_dev_s *rdev;
|
||||
};
|
||||
|
||||
struct regulator_ops_s
|
||||
{
|
||||
CODE int (*list_voltage)(FAR struct regulator_dev_s *rdev,
|
||||
unsigned selector);
|
||||
CODE int (*set_voltage)(FAR struct regulator_dev_s *rdev, int min_uv,
|
||||
int max_uv, FAR unsigned *selector);
|
||||
CODE int (*set_voltage_sel)(FAR struct regulator_dev_s *rdev,
|
||||
unsigned selector);
|
||||
CODE int (*get_voltage)(FAR struct regulator_dev_s *rdev);
|
||||
CODE int (*get_voltage_sel)(FAR struct regulator_dev_s *rdev);
|
||||
CODE int (*enable)(FAR struct regulator_dev_s *rdev);
|
||||
CODE int (*is_enabled)(FAR struct regulator_dev_s *rdev);
|
||||
CODE int (*disable)(FAR struct regulator_dev_s *rdev);
|
||||
};
|
||||
|
||||
/* This structure defines the regulator state structure */
|
||||
|
||||
struct regulator_desc_s
|
||||
{
|
||||
const char *name;
|
||||
unsigned int n_voltages;
|
||||
unsigned int vsel_reg;
|
||||
unsigned int vsel_mask;
|
||||
unsigned int enable_reg;
|
||||
unsigned int enable_mask;
|
||||
unsigned int enable_time;
|
||||
unsigned int ramp_delay;
|
||||
unsigned int uv_step;
|
||||
unsigned int min_uv;
|
||||
unsigned int max_uv;
|
||||
unsigned int apply_uv;
|
||||
bool boot_on;
|
||||
};
|
||||
|
||||
struct regulator_dev_s
|
||||
{
|
||||
FAR const struct regulator_desc_s *desc;
|
||||
FAR const struct regulator_ops_s *ops;
|
||||
uint32_t use_count;
|
||||
uint32_t open_count;
|
||||
sem_t regulator_sem;
|
||||
struct list_node list;
|
||||
struct list_node consumer_list;
|
||||
|
||||
FAR void *priv;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: regulator_register
|
||||
*
|
||||
* Description:
|
||||
* Register a lower half regulator driver with the common, upper-half
|
||||
* regulator driver.
|
||||
*
|
||||
* Input parameters:
|
||||
* desc - The regulator descriptor struct.
|
||||
* ops - The regulator operations pointer
|
||||
*
|
||||
* Returned value:
|
||||
* The pointer to struct regulator_dev_s on success or NULL on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
struct regulator_dev_s *
|
||||
regulator_register(FAR const struct regulator_desc_s *desc,
|
||||
FAR const struct regulator_ops_s *ops,
|
||||
FAR void *priv);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: regulator_unregister
|
||||
*
|
||||
* Description:
|
||||
* Unregister a lower half regulator driver with the common, upper-half
|
||||
* regulator driver.
|
||||
*
|
||||
* Input parameters:
|
||||
* rdev - The regulator dev pointer.
|
||||
*
|
||||
* Returned value:
|
||||
* N/A
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void regulator_unregister(FAR struct regulator_dev_s *rdev);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __INCLUDE_NUTTX_POWER_REGULATOR_H */
|
Loading…
Reference in New Issue
Block a user