MLK-18205-9 Support BD71837 PMIC chip on i.MX platforms
Signed-off-by: Haoran.Wang <elven.wang@nxp.com> Signed-off-by: Robin Gong <yibin.gong@nxp.com> Signed-off-by: Anson Huang <Anson.Huang@nxp.com> (cherry picked from commit 37f67d291e74a3428310cb5c98f556411042f810)pull/10/head
parent
2535028723
commit
61200c6925
|
@ -1810,6 +1810,14 @@ config MFD_STM32_TIMERS
|
|||
for PWM and IIO Timer. This driver allow to share the
|
||||
registers between the others drivers.
|
||||
|
||||
config MFD_BD71837
|
||||
bool "BD71837 Power Management chip"
|
||||
depends on I2C=y
|
||||
select MFD_CORE
|
||||
help
|
||||
if you say yes here you get support for the BD71837
|
||||
Power Management chips.
|
||||
|
||||
menu "Multimedia Capabilities Port drivers"
|
||||
depends on ARCH_SA1100
|
||||
|
||||
|
|
|
@ -231,3 +231,4 @@ obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o
|
|||
obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o
|
||||
obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o
|
||||
obj-$(CONFIG_MFD_MXS_LRADC) += mxs-lradc.o
|
||||
obj-$(CONFIG_MFD_BD71837) += bd71837.o
|
||||
|
|
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
* @file bd71837.c -- ROHM BD71837MWV mfd driver
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* @author: cpham2403@gmail.com
|
||||
* Copyright 2017.
|
||||
*/
|
||||
#define DEBUG
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/bd71837.h>
|
||||
|
||||
/* Default enable debug message All Level */
|
||||
unsigned int bd71837_debug_mask = BD71837_DBG0;
|
||||
|
||||
/** @brief bd71837 irq resource */
|
||||
static struct resource pmic_resources[] = {
|
||||
// irq# 0
|
||||
{
|
||||
.start = BD71837_IRQ,
|
||||
.end = BD71837_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
/** @brief bd71837 multi function cells */
|
||||
static struct mfd_cell bd71837_mfd_cells[] = {
|
||||
{
|
||||
.name = "bd71837-pmic",
|
||||
.num_resources = ARRAY_SIZE(pmic_resources),
|
||||
.resources = &pmic_resources[0],
|
||||
},
|
||||
};
|
||||
|
||||
/** @brief bd71837 irqs */
|
||||
static const struct regmap_irq bd71837_irqs[] = {
|
||||
[BD71837_IRQ] = {
|
||||
.mask = BD71837_INT_MASK,
|
||||
.reg_offset = 0,
|
||||
},
|
||||
};
|
||||
|
||||
/** @brief bd71837 irq chip definition */
|
||||
static struct regmap_irq_chip bd71837_irq_chip = {
|
||||
.name = "bd71837",
|
||||
.irqs = bd71837_irqs,
|
||||
.num_irqs = ARRAY_SIZE(bd71837_irqs),
|
||||
.num_regs = 1,
|
||||
.irq_reg_stride = 1,
|
||||
.status_base = BD71837_REG_IRQ,
|
||||
.mask_base = BD71837_REG_MIRQ,
|
||||
.mask_invert = true,
|
||||
// .ack_base = BD71837_REG_IRQ,
|
||||
};
|
||||
|
||||
/** @brief bd71837 irq initialize
|
||||
* @param bd71837 bd71837 device to init
|
||||
* @param bdinfo platform init data
|
||||
* @retval 0 probe success
|
||||
* @retval negative error number
|
||||
*/
|
||||
static int bd71837_irq_init(struct bd71837 *bd71837, struct bd71837_board *bdinfo)
|
||||
{
|
||||
int irq;
|
||||
int ret = 0;
|
||||
|
||||
if (!bdinfo) {
|
||||
dev_warn(bd71837->dev, "No interrupt support, no pdata\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_info(bd71837->dev, "gpio_intr = %d \n", bdinfo->gpio_intr);
|
||||
irq = gpio_to_irq(bdinfo->gpio_intr);
|
||||
|
||||
bd71837->chip_irq = irq;
|
||||
dev_info(bd71837->dev, "chip_irq=%d \n", bd71837->chip_irq);
|
||||
ret = regmap_add_irq_chip(bd71837->regmap, bd71837->chip_irq,
|
||||
IRQF_ONESHOT | IRQF_TRIGGER_FALLING, bdinfo->irq_base,
|
||||
&bd71837_irq_chip, &bd71837->irq_data);
|
||||
if (ret < 0) {
|
||||
dev_warn(bd71837->dev, "Failed to add irq_chip %d\n", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief bd71837 irq initialize
|
||||
* @param bd71837 bd71837 device to init
|
||||
* @retval 0 probe success
|
||||
* @retval negative error number
|
||||
*/
|
||||
static int bd71837_irq_exit(struct bd71837 *bd71837)
|
||||
{
|
||||
if (bd71837->chip_irq > 0)
|
||||
regmap_del_irq_chip(bd71837->chip_irq, bd71837->irq_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief check whether volatile register
|
||||
* @param dev kernel device pointer
|
||||
* @param reg register index
|
||||
*/
|
||||
static bool is_volatile_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
// struct bd71837 *bd71837 = dev_get_drvdata(dev);
|
||||
|
||||
/*
|
||||
* Caching all regulator registers.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @brief regmap configures */
|
||||
static const struct regmap_config bd71837_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.volatile_reg = is_volatile_reg,
|
||||
.max_register = BD71837_MAX_REGISTER - 1,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct of_device_id bd71837_of_match[] = {
|
||||
{ .compatible = "rohm,bd71837", .data = (void *)0},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bd71837_of_match);
|
||||
|
||||
|
||||
/** @brief parse device tree data of bd71837
|
||||
* @param client client object provided by system
|
||||
* @param chip_id return chip id back to caller
|
||||
* @return board initialize data
|
||||
*/
|
||||
static struct bd71837_board *bd71837_parse_dt(struct i2c_client *client,
|
||||
int *chip_id)
|
||||
{
|
||||
struct device_node *np = client->dev.of_node;
|
||||
struct bd71837_board *board_info;
|
||||
unsigned int prop;
|
||||
const struct of_device_id *match;
|
||||
int r = 0;
|
||||
|
||||
match = of_match_device(bd71837_of_match, &client->dev);
|
||||
if (!match) {
|
||||
dev_err(&client->dev, "Failed to find matching dt id\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chip_id = (int *)match->data;
|
||||
|
||||
board_info = devm_kzalloc(&client->dev, sizeof(*board_info),
|
||||
GFP_KERNEL);
|
||||
if (!board_info) {
|
||||
dev_err(&client->dev, "Failed to allocate pdata\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
board_info->gpio_intr = of_get_named_gpio(np, "gpio_intr", 0);
|
||||
if (!gpio_is_valid(board_info->gpio_intr)) {
|
||||
dev_err(&client->dev, "no pmic intr pin available\n");
|
||||
goto err_intr;
|
||||
}
|
||||
|
||||
r = of_property_read_u32(np, "irq_base", &prop);
|
||||
if (!r) {
|
||||
board_info->irq_base = prop;
|
||||
} else {
|
||||
board_info->irq_base = -1;
|
||||
}
|
||||
|
||||
return board_info;
|
||||
|
||||
err_intr:
|
||||
devm_kfree(&client->dev, board_info);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @brief probe bd71837 device
|
||||
* @param i2c client object provided by system
|
||||
* @param id chip id
|
||||
* @retval 0 probe success
|
||||
* @retval negative error number
|
||||
*/
|
||||
static int bd71837_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct bd71837 *bd71837;
|
||||
struct bd71837_board *pmic_plat_data;
|
||||
struct bd71837_board *of_pmic_plat_data = NULL;
|
||||
int chip_id = id->driver_data;
|
||||
int ret = 0;
|
||||
|
||||
pmic_plat_data = dev_get_platdata(&i2c->dev);
|
||||
|
||||
if (!pmic_plat_data && i2c->dev.of_node) {
|
||||
pmic_plat_data = bd71837_parse_dt(i2c, &chip_id);
|
||||
of_pmic_plat_data = pmic_plat_data;
|
||||
}
|
||||
|
||||
if (!pmic_plat_data)
|
||||
return -EINVAL;
|
||||
|
||||
bd71837 = kzalloc(sizeof(struct bd71837), GFP_KERNEL);
|
||||
if (bd71837 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
bd71837->of_plat_data = of_pmic_plat_data;
|
||||
i2c_set_clientdata(i2c, bd71837);
|
||||
bd71837->dev = &i2c->dev;
|
||||
bd71837->i2c_client = i2c;
|
||||
bd71837->id = chip_id;
|
||||
mutex_init(&bd71837->io_mutex);
|
||||
|
||||
bd71837->regmap = devm_regmap_init_i2c(i2c, &bd71837_regmap_config);
|
||||
if (IS_ERR(bd71837->regmap)) {
|
||||
ret = PTR_ERR(bd71837->regmap);
|
||||
dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = bd71837_reg_read(bd71837, BD71837_REG_REV);
|
||||
if (ret < 0) {
|
||||
dev_err(bd71837->dev, "%s(): Read BD71837_REG_DEVICE failed!\n", __func__);
|
||||
goto err;
|
||||
}
|
||||
dev_info(bd71837->dev, "Device ID=0x%X\n", ret);
|
||||
|
||||
bd71837_irq_init(bd71837, of_pmic_plat_data);
|
||||
|
||||
ret = mfd_add_devices(bd71837->dev, -1,
|
||||
bd71837_mfd_cells, ARRAY_SIZE(bd71837_mfd_cells),
|
||||
NULL, 0,
|
||||
regmap_irq_get_domain(bd71837->irq_data));
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
return ret;
|
||||
|
||||
err:
|
||||
mfd_remove_devices(bd71837->dev);
|
||||
kfree(bd71837);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief remove bd71837 device
|
||||
* @param i2c client object provided by system
|
||||
* @return 0
|
||||
*/
|
||||
static int bd71837_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct bd71837 *bd71837 = i2c_get_clientdata(i2c);
|
||||
|
||||
bd71837_irq_exit(bd71837);
|
||||
mfd_remove_devices(bd71837->dev);
|
||||
kfree(bd71837);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id bd71837_i2c_id[] = {
|
||||
{ "bd71837", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bd71837_i2c_id);
|
||||
|
||||
static struct i2c_driver bd71837_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "bd71837",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(bd71837_of_match),
|
||||
},
|
||||
.probe = bd71837_i2c_probe,
|
||||
.remove = bd71837_i2c_remove,
|
||||
.id_table = bd71837_i2c_id,
|
||||
};
|
||||
|
||||
static int __init bd71837_i2c_init(void)
|
||||
{
|
||||
return i2c_add_driver(&bd71837_i2c_driver);
|
||||
}
|
||||
/* init early so consumer devices can complete system boot */
|
||||
subsys_initcall(bd71837_i2c_init);
|
||||
|
||||
static void __exit bd71837_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&bd71837_i2c_driver);
|
||||
}
|
||||
module_exit(bd71837_i2c_exit);
|
||||
|
||||
MODULE_AUTHOR("Cong Pham <cpham2403@gmail.com>");
|
||||
MODULE_DESCRIPTION("BD71837 chip multi-function driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -977,5 +977,11 @@ config REGULATOR_WM8994
|
|||
This driver provides support for the voltage regulators on the
|
||||
WM8994 CODEC.
|
||||
|
||||
config REGULATOR_BD71837
|
||||
tristate "RoHM BD71837 Power Regulator"
|
||||
depends on MFD_BD71837
|
||||
help
|
||||
This driver supports BD71837 voltage regulator chips.
|
||||
|
||||
endif
|
||||
|
||||
|
|
|
@ -125,6 +125,7 @@ obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
|
|||
obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_BD71837) += bd71837-regulator.o
|
||||
|
||||
|
||||
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -22,6 +22,8 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/regulator/userspace-consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct userspace_consumer_data {
|
||||
|
@ -105,6 +107,39 @@ static const struct attribute_group attr_group = {
|
|||
.attrs = attributes,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
static struct regulator_userspace_consumer_data*
|
||||
of_get_uc_config(struct device *dev, struct device_node *np)
|
||||
{
|
||||
struct regulator_userspace_consumer_data *ucd;
|
||||
int r;
|
||||
|
||||
ucd = devm_kzalloc(dev, sizeof(struct regulator_userspace_consumer_data)
|
||||
+ sizeof(struct regulator_bulk_data),
|
||||
GFP_KERNEL);
|
||||
if (ucd == NULL)
|
||||
return NULL;
|
||||
|
||||
r = of_property_read_string(np, "uc-name", &ucd->name);
|
||||
if (r) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ucd->num_supplies = 1;
|
||||
ucd->supplies = (struct regulator_bulk_data *)&ucd[1];
|
||||
|
||||
r = of_property_read_string(np, "suck-supply", &ucd->supplies->supply);
|
||||
if (r) {
|
||||
goto err;
|
||||
}
|
||||
return ucd;
|
||||
|
||||
err:
|
||||
devm_kfree(dev, ucd);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int regulator_userspace_consumer_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_userspace_consumer_data *pdata;
|
||||
|
@ -112,6 +147,11 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev)
|
|||
int ret;
|
||||
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
#if defined(CONFIG_OF)
|
||||
if (!pdata && pdev->dev.of_node) {
|
||||
pdata = of_get_uc_config(&pdev->dev, pdev->dev.of_node);
|
||||
}
|
||||
#endif
|
||||
if (!pdata)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -151,6 +191,8 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev)
|
|||
drvdata->enabled = pdata->init_on;
|
||||
platform_set_drvdata(pdev, drvdata);
|
||||
|
||||
dev_info(&pdev->dev, "attached: %s\n", drvdata->name);
|
||||
|
||||
return 0;
|
||||
|
||||
err_enable:
|
||||
|
@ -171,11 +213,22 @@ static int regulator_userspace_consumer_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
static const struct of_device_id uc_of_match[] = {
|
||||
{ .compatible = "userspace_consumer", },
|
||||
{},
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct platform_driver regulator_userspace_consumer_driver = {
|
||||
.probe = regulator_userspace_consumer_probe,
|
||||
.remove = regulator_userspace_consumer_remove,
|
||||
.driver = {
|
||||
.name = "reg-userspace-consumer",
|
||||
.owner = THIS_MODULE,
|
||||
#if defined(CONFIG_OF)
|
||||
.of_match_table = of_match_ptr(uc_of_match),
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -15,8 +15,11 @@
|
|||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
|
||||
struct virtual_consumer_data {
|
||||
struct mutex lock;
|
||||
|
@ -285,9 +288,22 @@ static const struct attribute_group regulator_virtual_attr_group = {
|
|||
.attrs = regulator_virtual_attributes,
|
||||
};
|
||||
|
||||
static const char *of_get_virt_regulator_config(struct device *dev, struct device_node *np)
|
||||
{
|
||||
const char *reg_id;
|
||||
int r;
|
||||
|
||||
r = of_property_read_string(np, "virtual-supply", ®_id);
|
||||
if (r) {
|
||||
return NULL;
|
||||
}
|
||||
return reg_id;
|
||||
}
|
||||
|
||||
static int regulator_virtual_probe(struct platform_device *pdev)
|
||||
{
|
||||
char *reg_id = dev_get_platdata(&pdev->dev);
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct virtual_consumer_data *drvdata;
|
||||
int ret;
|
||||
|
||||
|
@ -296,6 +312,15 @@ static int regulator_virtual_probe(struct platform_device *pdev)
|
|||
if (drvdata == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (np) {
|
||||
reg_id = (char *)of_get_virt_regulator_config(&pdev->dev, np);
|
||||
}
|
||||
|
||||
if (reg_id == NULL) {
|
||||
dev_err(&pdev->dev, "Fail to get reg_id");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_init(&drvdata->lock);
|
||||
|
||||
drvdata->regulator = devm_regulator_get(&pdev->dev, reg_id);
|
||||
|
@ -318,6 +343,8 @@ static int regulator_virtual_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, drvdata);
|
||||
|
||||
dev_info(&pdev->dev, "attached: %s\n", reg_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -330,14 +357,25 @@ static int regulator_virtual_remove(struct platform_device *pdev)
|
|||
if (drvdata->enabled)
|
||||
regulator_disable(drvdata->regulator);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
static const struct of_device_id regulator_virtual_of_match[] = {
|
||||
{ .compatible = "regulator-virtual", },
|
||||
{},
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct platform_driver regulator_virtual_consumer_driver = {
|
||||
.probe = regulator_virtual_probe,
|
||||
.remove = regulator_virtual_remove,
|
||||
.driver = {
|
||||
.name = "reg-virt-consumer",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(regulator_virtual_of_match),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,413 @@
|
|||
/**
|
||||
* @file bd71837.h ROHM BD71837MWV header file
|
||||
*
|
||||
* Copyright 2017
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* @author cpham2403@gmail.com
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_MFD_BD71837_H
|
||||
#define __LINUX_MFD_BD71837_H
|
||||
|
||||
#include <linux/regmap.h>
|
||||
|
||||
enum {
|
||||
BD71837_BUCK1 = 0,
|
||||
BD71837_BUCK2,
|
||||
BD71837_BUCK3,
|
||||
BD71837_BUCK4,
|
||||
BD71837_BUCK5,
|
||||
BD71837_BUCK6,
|
||||
BD71837_BUCK7,
|
||||
BD71837_BUCK8,
|
||||
// General Purpose
|
||||
BD71837_LDO1,
|
||||
BD71837_LDO2,
|
||||
BD71837_LDO3,
|
||||
BD71837_LDO4,
|
||||
BD71837_LDO5,
|
||||
BD71837_LDO6,
|
||||
BD71837_LDO7,
|
||||
BD71837_REGULATOR_CNT,
|
||||
};
|
||||
|
||||
#define BD71837_SUPPLY_STATE_ENABLED 0x1
|
||||
|
||||
#define BD71837_BUCK1_VOLTAGE_NUM 0x40
|
||||
#define BD71837_BUCK2_VOLTAGE_NUM 0x40
|
||||
#define BD71837_BUCK3_VOLTAGE_NUM 0x40
|
||||
#define BD71837_BUCK4_VOLTAGE_NUM 0x40
|
||||
|
||||
#define BD71837_BUCK5_VOLTAGE_NUM 0x08
|
||||
#define BD71837_BUCK6_VOLTAGE_NUM 0x04
|
||||
#define BD71837_BUCK7_VOLTAGE_NUM 0x08
|
||||
#define BD71837_BUCK8_VOLTAGE_NUM 0x40
|
||||
|
||||
#define BD71837_LDO1_VOLTAGE_NUM 0x04
|
||||
#define BD71837_LDO2_VOLTAGE_NUM 0x02
|
||||
#define BD71837_LDO3_VOLTAGE_NUM 0x10
|
||||
#define BD71837_LDO4_VOLTAGE_NUM 0x10
|
||||
#define BD71837_LDO5_VOLTAGE_NUM 0x10
|
||||
#define BD71837_LDO6_VOLTAGE_NUM 0x10
|
||||
#define BD71837_LDO7_VOLTAGE_NUM 0x10
|
||||
|
||||
enum {
|
||||
BD71837_REG_REV = 0x00,
|
||||
BD71837_REG_SWRESET = 0x01,
|
||||
BD71837_REG_I2C_DEV = 0x02,
|
||||
BD71837_REG_PWRCTRL0 = 0x03,
|
||||
BD71837_REG_PWRCTRL1 = 0x04,
|
||||
BD71837_REG_BUCK1_CTRL = 0x05,
|
||||
BD71837_REG_BUCK2_CTRL = 0x06,
|
||||
BD71837_REG_BUCK3_CTRL = 0x07,
|
||||
BD71837_REG_BUCK4_CTRL = 0x08,
|
||||
BD71837_REG_BUCK5_CTRL = 0x09,
|
||||
BD71837_REG_BUCK6_CTRL = 0x0A,
|
||||
BD71837_REG_BUCK7_CTRL = 0x0B,
|
||||
BD71837_REG_BUCK8_CTRL = 0x0C,
|
||||
BD71837_REG_BUCK1_VOLT_RUN = 0x0D,
|
||||
BD71837_REG_BUCK1_VOLT_IDLE = 0x0E,
|
||||
BD71837_REG_BUCK1_VOLT_SUSP = 0x0F,
|
||||
BD71837_REG_BUCK2_VOLT_RUN = 0x10,
|
||||
BD71837_REG_BUCK2_VOLT_IDLE = 0x11,
|
||||
BD71837_REG_BUCK3_VOLT_RUN = 0x12,
|
||||
BD71837_REG_BUCK4_VOLT_RUN = 0x13,
|
||||
BD71837_REG_BUCK5_VOLT = 0x14,
|
||||
BD71837_REG_BUCK6_VOLT = 0x15,
|
||||
BD71837_REG_BUCK7_VOLT = 0x16,
|
||||
BD71837_REG_BUCK8_VOLT = 0x17,
|
||||
BD71837_REG_LDO1_VOLT = 0x18,
|
||||
BD71837_REG_LDO2_VOLT = 0x19,
|
||||
BD71837_REG_LDO3_VOLT = 0x1A,
|
||||
BD71837_REG_LDO4_VOLT = 0x1B,
|
||||
BD71837_REG_LDO5_VOLT = 0x1C,
|
||||
BD71837_REG_LDO6_VOLT = 0x1D,
|
||||
BD71837_REG_LDO7_VOLT = 0x1E,
|
||||
BD71837_REG_TRANS_COND0 = 0x1F,
|
||||
BD71837_REG_TRANS_COND1 = 0x20,
|
||||
BD71837_REG_VRFAULTEN = 0x21,
|
||||
BD71837_REG_MVRFLTMASK0 = 0x22,
|
||||
BD71837_REG_MVRFLTMASK1 = 0x23,
|
||||
BD71837_REG_MVRFLTMASK2 = 0x24,
|
||||
BD71837_REG_RCVCFG = 0x25,
|
||||
BD71837_REG_RCVNUM = 0x26,
|
||||
BD71837_REG_PWRONCONFIG0 = 0x27,
|
||||
BD71837_REG_PWRONCONFIG1 = 0x28,
|
||||
BD71837_REG_RESETSRC = 0x29,
|
||||
BD71837_REG_MIRQ = 0x2A,
|
||||
BD71837_REG_IRQ = 0x2B,
|
||||
BD71837_REG_IN_MON = 0x2C,
|
||||
BD71837_REG_POW_STATE = 0x2D,
|
||||
BD71837_REG_OUT32K = 0x2E,
|
||||
BD71837_REG_REGLOCK = 0x2F,
|
||||
BD71837_REG_OTPVER = 0xFF,
|
||||
BD71837_MAX_REGISTER = 0x100,
|
||||
};
|
||||
|
||||
/* BD71837_REG_BUCK1_CTRL bits */
|
||||
#define BUCK1_RAMPRATE_MASK 0xC0
|
||||
#define BUCK1_RAMPRATE_10P00MV 0x0
|
||||
#define BUCK1_RAMPRATE_5P00MV 0x1
|
||||
#define BUCK1_RAMPRATE_2P50MV 0x2
|
||||
#define BUCK1_RAMPRATE_1P25MV 0x3
|
||||
#define BUCK1_SEL 0x02
|
||||
#define BUCK1_EN 0x01
|
||||
|
||||
/* BD71837_REG_BUCK2_CTRL bits */
|
||||
#define BUCK2_RAMPRATE_MASK 0xC0
|
||||
#define BUCK2_RAMPRATE_10P00MV 0x0
|
||||
#define BUCK2_RAMPRATE_5P00MV 0x1
|
||||
#define BUCK2_RAMPRATE_2P50MV 0x2
|
||||
#define BUCK2_RAMPRATE_1P25MV 0x3
|
||||
#define BUCK2_SEL 0x02
|
||||
#define BUCK2_EN 0x01
|
||||
|
||||
/* BD71837_REG_BUCK3_CTRL bits */
|
||||
#define BUCK3_RAMPRATE_MASK 0xC0
|
||||
#define BUCK3_RAMPRATE_10P00MV 0x0
|
||||
#define BUCK3_RAMPRATE_5P00MV 0x1
|
||||
#define BUCK3_RAMPRATE_2P50MV 0x2
|
||||
#define BUCK3_RAMPRATE_1P25MV 0x3
|
||||
#define BUCK3_SEL 0x02
|
||||
#define BUCK3_EN 0x01
|
||||
|
||||
/* BD71837_REG_BUCK4_CTRL bits */
|
||||
#define BUCK4_RAMPRATE_MASK 0xC0
|
||||
#define BUCK4_RAMPRATE_10P00MV 0x0
|
||||
#define BUCK4_RAMPRATE_5P00MV 0x1
|
||||
#define BUCK4_RAMPRATE_2P50MV 0x2
|
||||
#define BUCK4_RAMPRATE_1P25MV 0x3
|
||||
#define BUCK4_SEL 0x02
|
||||
#define BUCK4_EN 0x01
|
||||
|
||||
/* BD71837_REG_BUCK5_CTRL bits */
|
||||
#define BUCK5_SEL 0x02
|
||||
#define BUCK5_EN 0x01
|
||||
|
||||
/* BD71837_REG_BUCK6_CTRL bits */
|
||||
#define BUCK6_SEL 0x02
|
||||
#define BUCK6_EN 0x01
|
||||
|
||||
/* BD71837_REG_BUCK7_CTRL bits */
|
||||
#define BUCK7_SEL 0x02
|
||||
#define BUCK7_EN 0x01
|
||||
|
||||
/* BD71837_REG_BUCK8_CTRL bits */
|
||||
#define BUCK8_SEL 0x02
|
||||
#define BUCK8_EN 0x01
|
||||
|
||||
/* BD71837_REG_BUCK1_VOLT_RUN bits */
|
||||
#define BUCK1_RUN_MASK 0x3F
|
||||
#define BUCK1_RUN_DEFAULT 0x14
|
||||
|
||||
/* BD71837_REG_BUCK1_VOLT_SUSP bits */
|
||||
#define BUCK1_SUSP_MASK 0x3F
|
||||
#define BUCK1_SUSP_DEFAULT 0x14
|
||||
|
||||
/* BD71837_REG_BUCK1_VOLT_IDLE bits */
|
||||
#define BUCK1_IDLE_MASK 0x3F
|
||||
#define BUCK1_IDLE_DEFAULT 0x14
|
||||
|
||||
/* BD71837_REG_BUCK2_VOLT_RUN bits */
|
||||
#define BUCK2_RUN_MASK 0x3F
|
||||
#define BUCK2_RUN_DEFAULT 0x1E
|
||||
|
||||
/* BD71837_REG_BUCK2_VOLT_IDLE bits */
|
||||
#define BUCK2_IDLE_MASK 0x3F
|
||||
#define BUCK2_IDLE_DEFAULT 0x14
|
||||
|
||||
/* BD71837_REG_BUCK3_VOLT_RUN bits */
|
||||
#define BUCK3_RUN_MASK 0x3F
|
||||
#define BUCK3_RUN_DEFAULT 0x1E
|
||||
|
||||
/* BD71837_REG_BUCK4_VOLT_RUN bits */
|
||||
#define BUCK4_RUN_MASK 0x3F
|
||||
#define BUCK4_RUN_DEFAULT 0x1E
|
||||
|
||||
/* BD71837_REG_BUCK5_VOLT bits */
|
||||
#define BUCK5_MASK 0x07
|
||||
#define BUCK5_DEFAULT 0x02
|
||||
|
||||
/* BD71837_REG_BUCK6_VOLT bits */
|
||||
#define BUCK6_MASK 0x03
|
||||
#define BUCK6_DEFAULT 0x03
|
||||
|
||||
/* BD71837_REG_BUCK7_VOLT bits */
|
||||
#define BUCK7_MASK 0x07
|
||||
#define BUCK7_DEFAULT 0x03
|
||||
|
||||
/* BD71837_REG_BUCK8_VOLT bits */
|
||||
#define BUCK8_MASK 0x3F
|
||||
#define BUCK8_DEFAULT 0x1E
|
||||
|
||||
/* BD71837_REG_IRQ bits */
|
||||
#define IRQ_SWRST 0x40
|
||||
#define IRQ_PWRON_S 0x20
|
||||
#define IRQ_PWRON_L 0x10
|
||||
#define IRQ_PWRON 0x08
|
||||
#define IRQ_WDOG 0x04
|
||||
#define IRQ_ON_REQ 0x02
|
||||
#define IRQ_STBY_REQ 0x01
|
||||
|
||||
/* BD71837_REG_OUT32K bits */
|
||||
#define OUT32K_EN 0x01
|
||||
|
||||
/* BD71837 interrupt masks */
|
||||
enum {
|
||||
BD71837_INT_MASK = 0x7F,
|
||||
};
|
||||
/* BD71837 interrupt irqs */
|
||||
enum {
|
||||
BD71837_IRQ = 0x0,
|
||||
};
|
||||
|
||||
/* BD71837_REG_LDO1_VOLT bits */
|
||||
#define LDO1_SEL 0x80
|
||||
#define LDO1_EN 0x40
|
||||
#define LDO1_MASK 0x03
|
||||
|
||||
/* BD71837_REG_LDO2_VOLT bits */
|
||||
#define LDO2_SEL 0x80
|
||||
#define LDO2_EN 0x40
|
||||
|
||||
/* BD71837_REG_LDO3_VOLT bits */
|
||||
#define LDO3_SEL 0x80
|
||||
#define LDO3_EN 0x40
|
||||
#define LDO3_MASK 0x0F
|
||||
|
||||
/* BD71837_REG_LDO4_VOLT bits */
|
||||
#define LDO4_SEL 0x80
|
||||
#define LDO4_EN 0x40
|
||||
#define LDO4_MASK 0x0F
|
||||
|
||||
/* BD71837_REG_LDO5_VOLT bits */
|
||||
#define LDO5_EN 0x40
|
||||
#define LDO5_MASK 0x0F
|
||||
|
||||
/* BD71837_REG_LDO6_VOLT bits */
|
||||
#define LDO6_EN 0x40
|
||||
#define LDO6_MASK 0x0F
|
||||
|
||||
/* BD71837_REG_LDO7_VOLT bits */
|
||||
#define LDO7_EN 0x40
|
||||
#define LDO7_MASK 0x0F
|
||||
|
||||
/** @brief charge state enumuration */
|
||||
enum CHG_STATE {
|
||||
CHG_STATE_SUSPEND = 0x0, /**< suspend state */
|
||||
CHG_STATE_TRICKLE_CHARGE, /**< trickle charge state */
|
||||
CHG_STATE_PRE_CHARGE, /**< precharge state */
|
||||
CHG_STATE_FAST_CHARGE, /**< fast charge state */
|
||||
CHG_STATE_TOP_OFF, /**< top off state */
|
||||
CHG_STATE_DONE, /**< charge complete */
|
||||
};
|
||||
|
||||
struct bd71837;
|
||||
|
||||
/**
|
||||
* @brief Board platform data may be used to initialize regulators.
|
||||
*/
|
||||
|
||||
struct bd71837_board {
|
||||
struct regulator_init_data *init_data[BD71837_REGULATOR_CNT];
|
||||
/**< regulator initialize data */
|
||||
int gpio_intr; /**< gpio connected to bd71837 INTB */
|
||||
int irq_base; /**< bd71837 sub irqs base # */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief bd71837 sub-driver chip access routines
|
||||
*/
|
||||
|
||||
struct bd71837 {
|
||||
struct device *dev;
|
||||
struct i2c_client *i2c_client;
|
||||
struct regmap *regmap;
|
||||
struct mutex io_mutex;
|
||||
unsigned int id;
|
||||
|
||||
/* IRQ Handling */
|
||||
int chip_irq; /**< bd71837 irq to host cpu */
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
|
||||
/* Client devices */
|
||||
struct bd71837_pmic *pmic; /**< client device regulator */
|
||||
struct bd71837_power *power; /**< client device battery */
|
||||
|
||||
struct bd71837_board *of_plat_data;
|
||||
/**< Device node parsed board data */
|
||||
};
|
||||
|
||||
static inline int bd71837_chip_id(struct bd71837 *bd71837)
|
||||
{
|
||||
return bd71837->id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief bd71837_reg_read
|
||||
* read single register's value of bd71837
|
||||
* @param bd71837 device to read
|
||||
* @param reg register address
|
||||
* @return register value if success
|
||||
* error number if fail
|
||||
*/
|
||||
static inline int bd71837_reg_read(struct bd71837 *bd71837, u8 reg)
|
||||
{
|
||||
int r, val;
|
||||
|
||||
r = regmap_read(bd71837->regmap, reg, &val);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief bd71837_reg_write
|
||||
* write single register of bd71837
|
||||
* @param bd71837 device to write
|
||||
* @param reg register address
|
||||
* @param val value to write
|
||||
* @retval 0 if success
|
||||
* @retval negative error number if fail
|
||||
*/
|
||||
|
||||
static inline int bd71837_reg_write(struct bd71837 *bd71837, u8 reg,
|
||||
unsigned int val)
|
||||
{
|
||||
return regmap_write(bd71837->regmap, reg, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief bd71837_set_bits
|
||||
* set bits in one register of bd71837
|
||||
* @param bd71837 device to read
|
||||
* @param reg register address
|
||||
* @param mask mask bits
|
||||
* @retval 0 if success
|
||||
* @retval negative error number if fail
|
||||
*/
|
||||
static inline int bd71837_set_bits(struct bd71837 *bd71837, u8 reg, u8 mask)
|
||||
{
|
||||
return regmap_update_bits(bd71837->regmap, reg, mask, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief bd71837_clear_bits
|
||||
* clear bits in one register of bd71837
|
||||
* @param bd71837 device to read
|
||||
* @param reg register address
|
||||
* @param mask mask bits
|
||||
* @retval 0 if success
|
||||
* @retval negative error number if fail
|
||||
*/
|
||||
|
||||
static inline int bd71837_clear_bits(struct bd71837 *bd71837, u8 reg,
|
||||
u8 mask)
|
||||
{
|
||||
return regmap_update_bits(bd71837->regmap, reg, mask, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief bd71837_update_bits
|
||||
* update bits in one register of bd71837
|
||||
* @param bd71837 device to read
|
||||
* @param reg register address
|
||||
* @param mask mask bits
|
||||
* @param val value to update
|
||||
* @retval 0 if success
|
||||
* @retval negative error number if fail
|
||||
*/
|
||||
|
||||
static inline int bd71837_update_bits(struct bd71837 *bd71837, u8 reg,
|
||||
u8 mask, u8 val)
|
||||
{
|
||||
return regmap_update_bits(bd71837->regmap, reg, mask, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief bd71837 platform data type
|
||||
*/
|
||||
struct bd71837_gpo_plat_data {
|
||||
u32 drv; ///< gpo output drv
|
||||
int gpio_base; ///< base gpio number in system
|
||||
};
|
||||
|
||||
u8 ext_bd71837_reg_read8(u8 reg);
|
||||
int ext_bd71837_reg_write8(int reg, u8 val);
|
||||
|
||||
#define BD71837_DBG0 0x0001
|
||||
#define BD71837_DBG1 0x0002
|
||||
#define BD71837_DBG2 0x0004
|
||||
#define BD71837_DBG3 0x0008
|
||||
|
||||
extern unsigned int bd71837_debug_mask;
|
||||
#define bd71837_debug(debug, fmt, arg...) do { if (debug & bd71837_debug_mask) printk("BD71837:" fmt, ##arg); } while (0)
|
||||
|
||||
#endif /* __LINUX_MFD_BD71837_H */
|
Loading…
Reference in New Issue