nxe2100芯片是nxe2000的升级芯片,它提供5个DCDC,10个LDO,2个LDORTC。
High Efficiency Step-down DC/DC Converters
* DCDC1 -3 0.6V-3.5V Max 3000mA
* DCDC4-5 0.6V-3.5V Max 2000mA
* Soft-start circuit
●Low Drop Voltage Regulators
* LDO1 -4 with ECO 0.9V-3.5V Max 300mA
* LDO5-6 with ECO 0.6V-3.5V Max 300mA
* LDO7-10 0.9V-3.5V Max 200mA
* LDORTC1 1.7-3.5V Max 10mA (AlwaysOn, For coin battery)
* LDORTC2 0.9-3.5V Max 10mA (AlwaysOn)
NXE2100的驱动可以在NXE2000的驱动上修改:
linux配置中有以下配置包含了NXE2000:
(1)drivers/power下的kconfig:
config BATTERY_NXE2000(drivers/power/nxe2000-battery.c)。选择它同时会选择MFD_NXE2000(drivers/mfd/nxe2000.c和nxe2000-irq.c)和REGULATOR_NXE2000。
(2)drivers/mfd下的kconfig
config MFD_NXE2000。选择它同时会选择MFD_CORE
(4) drivers/regulator下的kconfig
config REGULATOR_NXE2000(drivers/regulator/nxe2000-regulator.c)。选择它同时会选择MFD_NXE2000
nxe2000是一个I2C设备,它的驱动挂载到I2C总线上:
static struct i2c_board_info __initdata nxe2000_i2c_boardinfo[] = {
{
I2C_BOARD_INFO("nxe2000", NXE2000_I2C_ADDR),
.irq = CFG_GPIO_PMIC_INTR,
.platform_data = &nxe2000_platform,
},
};
NXE2000.c是它的驱动,其中probe的实现如下:
static int nxe2000_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct nxe2000 *nxe2000;
struct nxe2000_platform_data *pdata = client->dev.platform_data;
int ret;
nxe2000 = kzalloc(sizeof(struct nxe2000), GFP_KERNEL);
if (nxe2000 == NULL)
return -ENOMEM;
nxe2000->client = client;
nxe2000->dev = &client->dev;
i2c_set_clientdata(client, nxe2000);
mutex_init(&nxe2000->io_lock);
nxe2000->bank_num = 0;
/* For init PMIC_IRQ port */
// ret = pdata->init_port(client->irq);
if (client->irq) {
nxe2000->irq_base = pdata->irq_base;
nxe2000->chip_irq = gpio_to_irq(client->irq);
nxe2000->chip_irq_type = pdata->irq_type;
ret = nxe2000_irq_init(nxe2000);
if (ret) {
dev_err(&client->dev, "IRQ init failed: %d\n", ret);
goto err_irq_init;
}
}
ret = nxe2000_add_subdevs(nxe2000, pdata);
if (ret) {
dev_err(&client->dev, "add devices failed: %d\n", ret);
goto err_add_devs;
}
nxe2000_noe_init(nxe2000);
nxe2000_gpio_init(nxe2000, pdata);
nxe2000_debuginit(nxe2000);
#ifdef CONFIG_NXE2000_WDG_TEST
nxe2000_watchdog_init(nxe2000);
#endif
nxe2000_i2c_client = client;
backup_pm_power_off = pm_power_off;
pm_power_off = nxe2000_power_off;
#if (NXE2000_PM_RESTART == 1)
backup_pm_restart = arm_pm_restart;
arm_pm_restart = nxe2000_restart;
#endif
return 0;
err_add_devs:
if (client->irq)
nxe2000_irq_exit(nxe2000);
err_irq_init:
kfree(nxe2000);
return ret;
}
nxe2000_add_subdevs函数的功能是添加子设备,子设备的定义在结构nxe2000_devs_dcdc中:
#define NXE2000_DEV_REG \
NXE2000_REG(DC1, dc1, 0), \
NXE2000_REG(DC2, dc2, 0), \
NXE2000_REG(DC3, dc3, 0), \
NXE2000_REG(DC4, dc4, 0), \
NXE2000_REG(DC5, dc5, 0), \
NXE2000_REG(LDO1, ldo1, 0), \
NXE2000_REG(LDO2, ldo2, 0), \
NXE2000_REG(LDO3, ldo3, 0), \
NXE2000_REG(LDO4, ldo4, 0), \
NXE2000_REG(LDO5, ldo5, 0), \
NXE2000_REG(LDO6, ldo6, 0), \
NXE2000_REG(LDO7, ldo7, 0), \
NXE2000_REG(LDO8, ldo8, 0), \
NXE2000_REG(LDO9, ldo9, 0), \
NXE2000_REG(LDO10, ldo10, 0), \
NXE2000_REG(LDORTC1, ldortc1, 0), \
NXE2000_REG(LDORTC2, ldortc2, 0)
static struct nxe2000_subdev_info nxe2000_devs_dcdc[] = {
NXE2000_DEV_REG,
NXE2000_BATTERY_REG,
NXE2000_PWRKEY_REG,
#ifdef CONFIG_NXE2000_RTC
NXE2000_RTC_REG,
#endif
};
nxe2000_subdev_info:
struct nxe2000_subdev_info {
int id;
const char *name;
void *platform_data;
};
nxe2000_add_subdevs函数为上面定义的数组中定义的项新建一个设备:
static int nxe2000_add_subdevs(struct nxe2000 *nxe2000,
struct nxe2000_platform_data *pdata)
{
struct nxe2000_subdev_info *subdev;
struct platform_device *pdev;
int i, ret = 0;
for (i = 0; i < pdata->num_subdevs; i++) {
subdev = &pdata->subdevs[i];
pdev = platform_device_alloc(subdev->name, subdev->id);
pdev->dev.parent = nxe2000->dev;
pdev->dev.platform_data = subdev->platform_data;
ret = platform_device_add(pdev);
if (ret)
goto failed;
}
return 0;
failed:
nxe2000_remove_subdevs(nxe2000);
return ret;
}
其中,每个DCDC、LDO设备是一个nxe2000-regulator设备:
#define NXE2000_REG(_id, _name, _sname) \
{ \
.id = NXE2000_ID_##_id, \
.name = "nxe2000-regulator", \
.platform_data = &pdata_##_name##_##_sname, \
}
在nxe2000-regulator.c中定义了这个设备。
static int __devinit nxe2000_regulator_probe(struct platform_device *pdev)
{
struct nxe2000_regulator *ri = NULL;
struct regulator_dev *rdev;
struct nxe2000_regulator_platform_data *tps_pdata;
int id = pdev->id;
int err;
ri = find_regulator_info(id);
if (ri == NULL) {
dev_err(&pdev->dev, "invalid regulator ID specified\n");
return -EINVAL;
}
tps_pdata = pdev->dev.platform_data;
ri->dev = &pdev->dev;
nxe2000_suspend_status = 0;
err = nxe2000_cache_regulator_register(pdev->dev.parent, ri);
if (err) {
dev_err(&pdev->dev, "Fail in caching register\n");
return err;
}
err = nxe2000_regulator_preinit(pdev->dev.parent, ri, tps_pdata);
if (err) {
dev_err(&pdev->dev, "Fail in pre-initialisation\n");
return err;
}
rdev = regulator_register(&ri->desc, &pdev->dev,
&tps_pdata->regulator, ri, NULL);
if (IS_ERR_OR_NULL(rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
ri->desc.name);
return PTR_ERR(rdev);
}
platform_set_drvdata(pdev, rdev);
return 0;
}