From 796f5692daac4ea47fa5252af742976cd1955f0b Mon Sep 17 00:00:00 2001 From: Andrew F. Davis Date: Mon, 25 Jan 2016 09:43:45 -0600 Subject: mfd: tps65912: Add driver for the TPS65912 PMIC This patch adds support for TPS65912 PMIC MFD core. It provides communication through the I2C and SPI interfaces. It contains the following components: - Regulators - GPIO controller Signed-off-by: Andrew F. Davis Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 24 ++++++++++ drivers/mfd/Makefile | 3 ++ drivers/mfd/tps65912-core.c | 111 ++++++++++++++++++++++++++++++++++++++++++++ drivers/mfd/tps65912-i2c.c | 79 +++++++++++++++++++++++++++++++ drivers/mfd/tps65912-spi.c | 78 +++++++++++++++++++++++++++++++ 5 files changed, 295 insertions(+) create mode 100644 drivers/mfd/tps65912-core.c create mode 100644 drivers/mfd/tps65912-i2c.c create mode 100644 drivers/mfd/tps65912-spi.c (limited to 'drivers/mfd') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index dd2fc0158c7a..1bc97c2761e4 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1180,6 +1180,30 @@ config MFD_TPS65910 if you say yes here you get support for the TPS65910 series of Power Management chips. +config MFD_TPS65912 + tristate + select MFD_CORE + select REGMAP + select REGMAP_IRQ + +config MFD_TPS65912_I2C + tristate "TI TPS65912 Power Management chip with I2C" + select MFD_TPS65912 + select REGMAP_I2C + depends on I2C + help + If you say yes here you get support for the TPS65912 series of + PM chips with I2C interface. + +config MFD_TPS65912_SPI + tristate "TI TPS65912 Power Management chip with SPI" + select MFD_TPS65912 + select REGMAP_SPI + depends on SPI_MASTER + help + If you say yes here you get support for the TPS65912 series of + PM chips with SPI interface. + config MFD_TPS80031 bool "TI TPS80031/TPS80032 Power Management chips" depends on I2C=y diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index e33e0b48f591..1811202cee19 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -73,6 +73,9 @@ obj-$(CONFIG_TPS6507X) += tps6507x.o obj-$(CONFIG_MFD_TPS65217) += tps65217.o obj-$(CONFIG_MFD_TPS65218) += tps65218.o obj-$(CONFIG_MFD_TPS65910) += tps65910.o +obj-$(CONFIG_MFD_TPS65912) += tps65912-core.o +obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o +obj-$(CONFIG_MFD_TPS65912_SPI) += tps65912-spi.o obj-$(CONFIG_MFD_TPS80031) += tps80031.o obj-$(CONFIG_MENELAUS) += menelaus.o diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c new file mode 100644 index 000000000000..a88cfa80dbc4 --- /dev/null +++ b/drivers/mfd/tps65912-core.c @@ -0,0 +1,111 @@ +/* + * Core functions for TI TPS65912x PMICs + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether expressed or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. + * + * Based on the TPS65218 driver and the previous TPS65912 driver by + * Margarita Olaya Cabrera + */ + +#include +#include +#include + +#include + +static const struct mfd_cell tps65912_cells[] = { + { .name = "tps65912-regulator", }, + { .name = "tps65912-gpio", }, +}; + +static const struct regmap_irq tps65912_irqs[] = { + /* INT_STS IRQs */ + REGMAP_IRQ_REG(TPS65912_IRQ_PWRHOLD_F, 0, TPS65912_INT_STS_PWRHOLD_F), + REGMAP_IRQ_REG(TPS65912_IRQ_VMON, 0, TPS65912_INT_STS_VMON), + REGMAP_IRQ_REG(TPS65912_IRQ_PWRON, 0, TPS65912_INT_STS_PWRON), + REGMAP_IRQ_REG(TPS65912_IRQ_PWRON_LP, 0, TPS65912_INT_STS_PWRON_LP), + REGMAP_IRQ_REG(TPS65912_IRQ_PWRHOLD_R, 0, TPS65912_INT_STS_PWRHOLD_R), + REGMAP_IRQ_REG(TPS65912_IRQ_HOTDIE, 0, TPS65912_INT_STS_HOTDIE), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO1_R, 0, TPS65912_INT_STS_GPIO1_R), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO1_F, 0, TPS65912_INT_STS_GPIO1_F), + /* INT_STS2 IRQs */ + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO2_R, 1, TPS65912_INT_STS2_GPIO2_R), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO2_F, 1, TPS65912_INT_STS2_GPIO2_F), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO3_R, 1, TPS65912_INT_STS2_GPIO3_R), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO3_F, 1, TPS65912_INT_STS2_GPIO3_F), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO4_R, 1, TPS65912_INT_STS2_GPIO4_R), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO4_F, 1, TPS65912_INT_STS2_GPIO4_F), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO5_R, 1, TPS65912_INT_STS2_GPIO5_R), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO5_F, 1, TPS65912_INT_STS2_GPIO5_F), + /* INT_STS3 IRQs */ + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_DCDC1, 2, TPS65912_INT_STS3_PGOOD_DCDC1), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_DCDC2, 2, TPS65912_INT_STS3_PGOOD_DCDC2), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_DCDC3, 2, TPS65912_INT_STS3_PGOOD_DCDC3), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_DCDC4, 2, TPS65912_INT_STS3_PGOOD_DCDC4), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO1, 2, TPS65912_INT_STS3_PGOOD_LDO1), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO2, 2, TPS65912_INT_STS3_PGOOD_LDO2), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO3, 2, TPS65912_INT_STS3_PGOOD_LDO3), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO4, 2, TPS65912_INT_STS3_PGOOD_LDO4), + /* INT_STS4 IRQs */ + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO5, 3, TPS65912_INT_STS4_PGOOD_LDO5), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO6, 3, TPS65912_INT_STS4_PGOOD_LDO6), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO7, 3, TPS65912_INT_STS4_PGOOD_LDO7), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO8, 3, TPS65912_INT_STS4_PGOOD_LDO8), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO9, 3, TPS65912_INT_STS4_PGOOD_LDO9), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO10, 3, TPS65912_INT_STS4_PGOOD_LDO10), +}; + +static struct regmap_irq_chip tps65912_irq_chip = { + .name = "tps65912", + .irqs = tps65912_irqs, + .num_irqs = ARRAY_SIZE(tps65912_irqs), + .num_regs = 4, + .irq_reg_stride = 2, + .mask_base = TPS65912_INT_MSK, + .status_base = TPS65912_INT_STS, + .ack_base = TPS65912_INT_STS, + .init_ack_masked = true, +}; + +int tps65912_device_init(struct tps65912 *tps) +{ + int ret; + + ret = regmap_add_irq_chip(tps->regmap, tps->irq, IRQF_ONESHOT, 0, + &tps65912_irq_chip, &tps->irq_data); + if (ret) + return ret; + + ret = mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, tps65912_cells, + ARRAY_SIZE(tps65912_cells), NULL, 0, + regmap_irq_get_domain(tps->irq_data)); + if (ret) { + regmap_del_irq_chip(tps->irq, tps->irq_data); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(tps65912_device_init); + +int tps65912_device_exit(struct tps65912 *tps) +{ + regmap_del_irq_chip(tps->irq, tps->irq_data); + + return 0; +} +EXPORT_SYMBOL_GPL(tps65912_device_exit); + +MODULE_AUTHOR("Andrew F. Davis "); +MODULE_DESCRIPTION("TPS65912x MFD Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/tps65912-i2c.c b/drivers/mfd/tps65912-i2c.c new file mode 100644 index 000000000000..45871403f995 --- /dev/null +++ b/drivers/mfd/tps65912-i2c.c @@ -0,0 +1,79 @@ +/* + * I2C access driver for TI TPS65912x PMICs + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether expressed or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. + * + * Based on the TPS65218 driver and the previous TPS65912 driver by + * Margarita Olaya Cabrera + */ + +#include +#include +#include + +#include + +static const struct of_device_id tps65912_i2c_of_match_table[] = { + { .compatible = "ti,tps65912", }, + { /* sentinel */ } +}; + +static int tps65912_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *ids) +{ + struct tps65912 *tps; + + tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); + if (!tps) + return -ENOMEM; + + i2c_set_clientdata(client, tps); + tps->dev = &client->dev; + tps->irq = client->irq; + + tps->regmap = devm_regmap_init_i2c(client, &tps65912_regmap_config); + if (IS_ERR(tps->regmap)) { + dev_err(tps->dev, "Failed to initialize register map\n"); + return PTR_ERR(tps->regmap); + } + + return tps65912_device_init(tps); +} + +static int tps65912_i2c_remove(struct i2c_client *client) +{ + struct tps65912 *tps = i2c_get_clientdata(client); + + return tps65912_device_exit(tps); +} + +static const struct i2c_device_id tps65912_i2c_id_table[] = { + { "tps65912", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, tps65912_i2c_id_table); + +static struct i2c_driver tps65912_i2c_driver = { + .driver = { + .name = "tps65912", + .of_match_table = tps65912_i2c_of_match_table, + }, + .probe = tps65912_i2c_probe, + .remove = tps65912_i2c_remove, + .id_table = tps65912_i2c_id_table, +}; +module_i2c_driver(tps65912_i2c_driver); + +MODULE_AUTHOR("Andrew F. Davis "); +MODULE_DESCRIPTION("TPS65912x I2C Interface Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c new file mode 100644 index 000000000000..4aeba9b6942a --- /dev/null +++ b/drivers/mfd/tps65912-spi.c @@ -0,0 +1,78 @@ +/* + * SPI access driver for TI TPS65912x PMICs + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether expressed or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. + * + * Based on the TPS65218 driver and the previous TPS65912 driver by + * Margarita Olaya Cabrera + */ + +#include +#include +#include + +#include + +static const struct of_device_id tps65912_spi_of_match_table[] = { + { .compatible = "ti,tps65912", }, + { /* sentinel */ } +}; + +static int tps65912_spi_probe(struct spi_device *spi) +{ + struct tps65912 *tps; + + tps = devm_kzalloc(&spi->dev, sizeof(*tps), GFP_KERNEL); + if (!tps) + return -ENOMEM; + + spi_set_drvdata(spi, tps); + tps->dev = &spi->dev; + tps->irq = spi->irq; + + tps->regmap = devm_regmap_init_spi(spi, &tps65912_regmap_config); + if (IS_ERR(tps->regmap)) { + dev_err(tps->dev, "Failed to initialize register map\n"); + return PTR_ERR(tps->regmap); + } + + return tps65912_device_init(tps); +} + +static int tps65912_spi_remove(struct spi_device *client) +{ + struct tps65912 *tps = spi_get_drvdata(client); + + return tps65912_device_exit(tps); +} + +static const struct spi_device_id tps65912_spi_id_table[] = { + { "tps65912", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(spi, tps65912_spi_id_table); + +static struct spi_driver tps65912_spi_driver = { + .driver = { + .name = "tps65912", + .of_match_table = tps65912_spi_of_match_table, + }, + .probe = tps65912_spi_probe, + .remove = tps65912_spi_remove, + .id_table = tps65912_spi_id_table, +}; +module_spi_driver(tps65912_spi_driver); + +MODULE_AUTHOR("Andrew F. Davis "); +MODULE_DESCRIPTION("TPS65912x SPI Interface Driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3-55-g7522