summaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/Kconfig16
-rw-r--r--drivers/mfd/Makefile6
-rw-r--r--drivers/mfd/axp20x-i2c.c2
-rw-r--r--drivers/mfd/axp20x-rsb.c1
-rw-r--r--drivers/mfd/axp20x.c91
-rw-r--r--drivers/mfd/cs42l43.c36
-rw-r--r--drivers/mfd/intel-lpss-pci.c2
-rw-r--r--drivers/mfd/intel-m10-bmc-pmci.c1
-rw-r--r--drivers/mfd/intel-m10-bmc-spi.c1
-rw-r--r--drivers/mfd/kempld-core.c227
-rw-r--r--drivers/mfd/ocelot-spi.c5
-rw-r--r--drivers/mfd/omap-usb-tll.c3
-rw-r--r--drivers/mfd/rk8xx-core.c104
-rw-r--r--drivers/mfd/rk8xx-i2c.c45
-rw-r--r--drivers/mfd/rohm-bd71828.c36
-rw-r--r--drivers/mfd/rsmu_core.c2
-rw-r--r--drivers/mfd/rsmu_i2c.c107
-rw-r--r--drivers/mfd/rsmu_spi.c8
-rw-r--r--drivers/mfd/ssbi.c1
-rw-r--r--drivers/mfd/timberdale.c1
-rw-r--r--drivers/mfd/tps6594-core.c253
-rw-r--r--drivers/mfd/tps6594-i2c.c20
-rw-r--r--drivers/mfd/tps6594-spi.c20
23 files changed, 722 insertions, 266 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 4b023ee229..266b4f54af 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -292,7 +292,7 @@ config MFD_MADERA_SPI
config MFD_MAX5970
tristate "Maxim 5970/5978 power switch and monitor"
- depends on (I2C && OF)
+ depends on I2C && OF
select MFD_SIMPLE_MFD_I2C
help
This driver controls a Maxim 5970/5978 switch via I2C bus.
@@ -458,7 +458,7 @@ config MFD_EXYNOS_LPASS
config MFD_GATEWORKS_GSC
tristate "Gateworks System Controller"
- depends on (I2C && OF)
+ depends on I2C && OF
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
@@ -473,7 +473,7 @@ config MFD_GATEWORKS_GSC
config MFD_MC13XXX
tristate
- depends on (SPI_MASTER || I2C)
+ depends on SPI_MASTER || I2C
select MFD_CORE
select REGMAP_IRQ
help
@@ -1109,7 +1109,7 @@ config PCF50633_GPIO
config MFD_PM8XXX
tristate "Qualcomm PM8xxx PMIC chips driver"
- depends on (ARM || HEXAGON || COMPILE_TEST)
+ depends on ARM || HEXAGON || COMPILE_TEST
select IRQ_DOMAIN_HIERARCHY
select MFD_CORE
select REGMAP
@@ -1225,7 +1225,7 @@ config MFD_RK8XX
select MFD_CORE
config MFD_RK8XX_I2C
- tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power Management Chip"
+ tristate "Rockchip RK805/RK808/RK809/RK816/RK817/RK818 Power Management Chip"
depends on I2C && OF
select MFD_CORE
select REGMAP_I2C
@@ -1233,7 +1233,7 @@ config MFD_RK8XX_I2C
select MFD_RK8XX
help
If you say yes here you get support for the RK805, RK808, RK809,
- RK817 and RK818 Power Management chips.
+ RK816, RK817 and RK818 Power Management chips.
This driver provides common support for accessing the device
through I2C interface. The device supports multiple sub-devices
including interrupts, RTC, LDO & DCDC regulators, and onkey.
@@ -1418,7 +1418,7 @@ config MFD_DB8500_PRCMU
config MFD_STMPE
bool "STMicroelectronics STMPE"
- depends on (I2C=y || SPI_MASTER=y)
+ depends on I2C=y || SPI_MASTER=y
depends on OF
select MFD_CORE
help
@@ -2116,7 +2116,7 @@ config MFD_STM32_TIMERS
config MFD_STPMIC1
tristate "Support for STPMIC1 PMIC"
- depends on (I2C=y && OF)
+ depends on I2C=y && OF
select REGMAP_I2C
select REGMAP_IRQ
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index c66f07edcd..db1ba39de3 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -280,7 +280,5 @@ obj-$(CONFIG_MFD_INTEL_M10_BMC_PMCI) += intel-m10-bmc-pmci.o
obj-$(CONFIG_MFD_ATC260X) += atc260x-core.o
obj-$(CONFIG_MFD_ATC260X_I2C) += atc260x-i2c.o
-rsmu-i2c-objs := rsmu_core.o rsmu_i2c.o
-rsmu-spi-objs := rsmu_core.o rsmu_spi.o
-obj-$(CONFIG_MFD_RSMU_I2C) += rsmu-i2c.o
-obj-$(CONFIG_MFD_RSMU_SPI) += rsmu-spi.o
+obj-$(CONFIG_MFD_RSMU_I2C) += rsmu_i2c.o rsmu_core.o
+obj-$(CONFIG_MFD_RSMU_SPI) += rsmu_spi.o rsmu_core.o
diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c
index 68d3560cfe..b8e7ac89f6 100644
--- a/drivers/mfd/axp20x-i2c.c
+++ b/drivers/mfd/axp20x-i2c.c
@@ -65,6 +65,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = {
{ .compatible = "x-powers,axp221", .data = (void *)AXP221_ID },
{ .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
{ .compatible = "x-powers,axp313a", .data = (void *)AXP313A_ID },
+ { .compatible = "x-powers,axp717", .data = (void *)AXP717_ID },
{ .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
{ .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
{ .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID },
@@ -81,6 +82,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
{ "axp221", 0 },
{ "axp223", 0 },
{ "axp313a", 0 },
+ { "axp717", 0 },
{ "axp803", 0 },
{ "axp806", 0 },
{ "axp15060", 0 },
diff --git a/drivers/mfd/axp20x-rsb.c b/drivers/mfd/axp20x-rsb.c
index 214bc0d84d..059656f2a1 100644
--- a/drivers/mfd/axp20x-rsb.c
+++ b/drivers/mfd/axp20x-rsb.c
@@ -58,6 +58,7 @@ static void axp20x_rsb_remove(struct sunxi_rsb_device *rdev)
static const struct of_device_id axp20x_rsb_of_match[] = {
{ .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
+ { .compatible = "x-powers,axp717", .data = (void *)AXP717_ID },
{ .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
{ .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
{ .compatible = "x-powers,axp809", .data = (void *)AXP809_ID },
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index d8daa593eb..dacd3c96c9 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -42,6 +42,7 @@ static const char * const axp20x_model_names[] = {
"AXP223",
"AXP288",
"AXP313a",
+ "AXP717",
"AXP803",
"AXP806",
"AXP809",
@@ -207,6 +208,26 @@ static const struct regmap_access_table axp313a_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(axp313a_volatile_ranges),
};
+static const struct regmap_range axp717_writeable_ranges[] = {
+ regmap_reg_range(AXP717_IRQ0_EN, AXP717_IRQ4_EN),
+ regmap_reg_range(AXP717_IRQ0_STATE, AXP717_IRQ4_STATE),
+ regmap_reg_range(AXP717_DCDC_OUTPUT_CONTROL, AXP717_CPUSLDO_CONTROL),
+};
+
+static const struct regmap_range axp717_volatile_ranges[] = {
+ regmap_reg_range(AXP717_IRQ0_STATE, AXP717_IRQ4_STATE),
+};
+
+static const struct regmap_access_table axp717_writeable_table = {
+ .yes_ranges = axp717_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp717_writeable_ranges),
+};
+
+static const struct regmap_access_table axp717_volatile_table = {
+ .yes_ranges = axp717_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp717_volatile_ranges),
+};
+
static const struct regmap_range axp806_volatile_ranges[] = {
regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
};
@@ -317,6 +338,11 @@ static const struct resource axp313a_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
+static const struct resource axp717_pek_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP717_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
+ DEFINE_RES_IRQ_NAMED(AXP717_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
+};
+
static const struct resource axp803_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
@@ -391,6 +417,15 @@ static const struct regmap_config axp313a_regmap_config = {
.cache_type = REGCACHE_MAPLE,
};
+static const struct regmap_config axp717_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .wr_table = &axp717_writeable_table,
+ .volatile_table = &axp717_volatile_table,
+ .max_register = AXP717_CPUSLDO_CONTROL,
+ .cache_type = REGCACHE_MAPLE,
+};
+
static const struct regmap_config axp806_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -589,6 +624,40 @@ static const struct regmap_irq axp313a_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP313A, DIE_TEMP_HIGH, 0, 0),
};
+static const struct regmap_irq axp717_regmap_irqs[] = {
+ INIT_REGMAP_IRQ(AXP717, SOC_DROP_LVL2, 0, 7),
+ INIT_REGMAP_IRQ(AXP717, SOC_DROP_LVL1, 0, 6),
+ INIT_REGMAP_IRQ(AXP717, GAUGE_NEW_SOC, 0, 4),
+ INIT_REGMAP_IRQ(AXP717, BOOST_OVER_V, 0, 2),
+ INIT_REGMAP_IRQ(AXP717, VBUS_OVER_V, 0, 1),
+ INIT_REGMAP_IRQ(AXP717, VBUS_FAULT, 0, 0),
+ INIT_REGMAP_IRQ(AXP717, VBUS_PLUGIN, 1, 7),
+ INIT_REGMAP_IRQ(AXP717, VBUS_REMOVAL, 1, 6),
+ INIT_REGMAP_IRQ(AXP717, BATT_PLUGIN, 1, 5),
+ INIT_REGMAP_IRQ(AXP717, BATT_REMOVAL, 1, 4),
+ INIT_REGMAP_IRQ(AXP717, PEK_SHORT, 1, 3),
+ INIT_REGMAP_IRQ(AXP717, PEK_LONG, 1, 2),
+ INIT_REGMAP_IRQ(AXP717, PEK_FAL_EDGE, 1, 1),
+ INIT_REGMAP_IRQ(AXP717, PEK_RIS_EDGE, 1, 0),
+ INIT_REGMAP_IRQ(AXP717, WDOG_EXPIRE, 2, 7),
+ INIT_REGMAP_IRQ(AXP717, LDO_OVER_CURR, 2, 6),
+ INIT_REGMAP_IRQ(AXP717, BATT_OVER_CURR, 2, 5),
+ INIT_REGMAP_IRQ(AXP717, CHARG_DONE, 2, 4),
+ INIT_REGMAP_IRQ(AXP717, CHARG, 2, 3),
+ INIT_REGMAP_IRQ(AXP717, DIE_TEMP_HIGH, 2, 2),
+ INIT_REGMAP_IRQ(AXP717, CHARG_TIMER, 2, 1),
+ INIT_REGMAP_IRQ(AXP717, BATT_OVER_V, 2, 0),
+ INIT_REGMAP_IRQ(AXP717, BC_USB_DONE, 3, 7),
+ INIT_REGMAP_IRQ(AXP717, BC_USB_CHNG, 3, 6),
+ INIT_REGMAP_IRQ(AXP717, BATT_QUIT_TEMP_HIGH, 3, 4),
+ INIT_REGMAP_IRQ(AXP717, BATT_CHG_TEMP_HIGH, 3, 3),
+ INIT_REGMAP_IRQ(AXP717, BATT_CHG_TEMP_LOW, 3, 2),
+ INIT_REGMAP_IRQ(AXP717, BATT_ACT_TEMP_HIGH, 3, 1),
+ INIT_REGMAP_IRQ(AXP717, BATT_ACT_TEMP_LOW, 3, 0),
+ INIT_REGMAP_IRQ(AXP717, TYPEC_REMOVE, 4, 6),
+ INIT_REGMAP_IRQ(AXP717, TYPEC_PLUGIN, 4, 5),
+};
+
static const struct regmap_irq axp803_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP803, ACIN_OVER_V, 0, 7),
INIT_REGMAP_IRQ(AXP803, ACIN_PLUGIN, 0, 6),
@@ -776,6 +845,17 @@ static const struct regmap_irq_chip axp313a_regmap_irq_chip = {
.num_regs = 1,
};
+static const struct regmap_irq_chip axp717_regmap_irq_chip = {
+ .name = "axp717_irq_chip",
+ .status_base = AXP717_IRQ0_STATE,
+ .ack_base = AXP717_IRQ0_STATE,
+ .unmask_base = AXP717_IRQ0_EN,
+ .init_ack_masked = true,
+ .irqs = axp717_regmap_irqs,
+ .num_irqs = ARRAY_SIZE(axp717_regmap_irqs),
+ .num_regs = 5,
+};
+
static const struct regmap_irq_chip axp803_regmap_irq_chip = {
.name = "axp803",
.status_base = AXP20X_IRQ1_STATE,
@@ -941,6 +1021,11 @@ static struct mfd_cell axp313a_cells[] = {
MFD_CELL_RES("axp313a-pek", axp313a_pek_resources),
};
+static struct mfd_cell axp717_cells[] = {
+ MFD_CELL_NAME("axp20x-regulator"),
+ MFD_CELL_RES("axp20x-pek", axp717_pek_resources),
+};
+
static const struct resource axp288_adc_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"),
};
@@ -1181,6 +1266,12 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
axp20x->regmap_cfg = &axp313a_regmap_config;
axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip;
break;
+ case AXP717_ID:
+ axp20x->nr_cells = ARRAY_SIZE(axp717_cells);
+ axp20x->cells = axp717_cells;
+ axp20x->regmap_cfg = &axp717_regmap_config;
+ axp20x->regmap_irq_chip = &axp717_regmap_irq_chip;
+ break;
case AXP803_ID:
axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
axp20x->cells = axp803_cells;
diff --git a/drivers/mfd/cs42l43.c b/drivers/mfd/cs42l43.c
index a0fb2dc6c3..ae8fd37afb 100644
--- a/drivers/mfd/cs42l43.c
+++ b/drivers/mfd/cs42l43.c
@@ -43,6 +43,9 @@
#define CS42L43_MCU_UPDATE_TIMEOUT_US 500000
#define CS42L43_MCU_UPDATE_RETRIES 5
+#define CS42L43_MCU_ROM_REV 0x2001
+#define CS42L43_MCU_ROM_BIOS_REV 0x0000
+
#define CS42L43_MCU_SUPPORTED_REV 0x2105
#define CS42L43_MCU_SHADOW_REGS_REQUIRED_REV 0x2200
#define CS42L43_MCU_SUPPORTED_BIOS_REV 0x0001
@@ -709,6 +712,23 @@ err:
complete(&cs42l43->firmware_download);
}
+static int cs42l43_mcu_is_hw_compatible(struct cs42l43 *cs42l43,
+ unsigned int mcu_rev,
+ unsigned int bios_rev)
+{
+ /*
+ * The firmware has two revision numbers bringing either of them up to a
+ * supported version will provide the disable the driver requires.
+ */
+ if (mcu_rev < CS42L43_MCU_SUPPORTED_REV &&
+ bios_rev < CS42L43_MCU_SUPPORTED_BIOS_REV) {
+ dev_err(cs42l43->dev, "Firmware too old to support disable\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/*
* The process of updating the firmware is split into a series of steps, at the
* end of each step a soft reset of the device might be required which will
@@ -745,11 +765,10 @@ static int cs42l43_mcu_update_step(struct cs42l43 *cs42l43)
((mcu_rev & CS42L43_FW_SUBMINOR_REV_MASK) >> 8);
/*
- * The firmware has two revision numbers bringing either of them up to a
- * supported version will provide the features the driver requires.
+ * The firmware has two revision numbers both of them being at the ROM
+ * revision indicates no patch has been applied.
*/
- patched = mcu_rev >= CS42L43_MCU_SUPPORTED_REV ||
- bios_rev >= CS42L43_MCU_SUPPORTED_BIOS_REV;
+ patched = mcu_rev != CS42L43_MCU_ROM_REV || bios_rev != CS42L43_MCU_ROM_BIOS_REV;
/*
* Later versions of the firmwware require the driver to access some
* features through a set of shadow registers.
@@ -794,10 +813,15 @@ static int cs42l43_mcu_update_step(struct cs42l43 *cs42l43)
return cs42l43_mcu_stage_2_3(cs42l43, shadow);
}
case CS42L43_MCU_BOOT_STAGE3:
- if (patched)
+ if (patched) {
+ ret = cs42l43_mcu_is_hw_compatible(cs42l43, mcu_rev, bios_rev);
+ if (ret)
+ return ret;
+
return cs42l43_mcu_disable(cs42l43);
- else
+ } else {
return cs42l43_mcu_stage_3_2(cs42l43);
+ }
case CS42L43_MCU_BOOT_STAGE4:
return 0;
default:
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c
index 8c00e0c695..c36a101df7 100644
--- a/drivers/mfd/intel-lpss-pci.c
+++ b/drivers/mfd/intel-lpss-pci.c
@@ -54,7 +54,7 @@ static int intel_lpss_pci_probe(struct pci_dev *pdev,
if (ret)
return ret;
- ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_LEGACY);
+ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
if (ret < 0)
return ret;
diff --git a/drivers/mfd/intel-m10-bmc-pmci.c b/drivers/mfd/intel-m10-bmc-pmci.c
index 0392ef8b57..698c593393 100644
--- a/drivers/mfd/intel-m10-bmc-pmci.c
+++ b/drivers/mfd/intel-m10-bmc-pmci.c
@@ -370,6 +370,7 @@ static const struct m10bmc_csr_map m10bmc_n6000_csr_map = {
.pr_reh_addr = M10BMC_N6000_PR_REH_ADDR,
.pr_magic = M10BMC_N6000_PR_PROG_MAGIC,
.rsu_update_counter = M10BMC_N6000_STAGING_FLASH_COUNT,
+ .staging_size = M10BMC_STAGING_SIZE,
};
static const struct intel_m10bmc_platform_info m10bmc_pmci_n6000 = {
diff --git a/drivers/mfd/intel-m10-bmc-spi.c b/drivers/mfd/intel-m10-bmc-spi.c
index cbeb7de9e0..d64d28199d 100644
--- a/drivers/mfd/intel-m10-bmc-spi.c
+++ b/drivers/mfd/intel-m10-bmc-spi.c
@@ -109,6 +109,7 @@ static const struct m10bmc_csr_map m10bmc_n3000_csr_map = {
.pr_reh_addr = M10BMC_N3000_PR_REH_ADDR,
.pr_magic = M10BMC_N3000_PR_PROG_MAGIC,
.rsu_update_counter = M10BMC_N3000_STAGING_FLASH_COUNT,
+ .staging_size = M10BMC_STAGING_SIZE,
};
static struct mfd_cell m10bmc_d5005_subdevs[] = {
diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c
index 5557f023a1..8a332852bf 100644
--- a/drivers/mfd/kempld-core.c
+++ b/drivers/mfd/kempld-core.c
@@ -6,14 +6,17 @@
* Author: Michael Brunner <michael.brunner@kontron.com>
*/
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/kempld.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
+#include <linux/property.h>
#include <linux/dmi.h>
#include <linux/io.h>
#include <linux/delay.h>
-#include <linux/acpi.h>
+#include <linux/sysfs.h>
#define MAX_ID_LEN 4
static char force_device_id[MAX_ID_LEN + 1] = "";
@@ -106,7 +109,7 @@ static int kempld_register_cells_generic(struct kempld_device_data *pld)
if (pld->feature_mask & KEMPLD_FEATURE_MASK_UART)
devs[i++].name = kempld_dev_names[KEMPLD_UART];
- return mfd_add_devices(pld->dev, -1, devs, i, NULL, 0, NULL);
+ return mfd_add_devices(pld->dev, PLATFORM_DEVID_NONE, devs, i, NULL, 0, NULL);
}
static struct resource kempld_ioresource = {
@@ -126,31 +129,22 @@ static const struct kempld_platform_data kempld_platform_data_generic = {
static struct platform_device *kempld_pdev;
-static int kempld_create_platform_device(const struct dmi_system_id *id)
+static int kempld_create_platform_device(const struct kempld_platform_data *pdata)
{
- const struct kempld_platform_data *pdata = id->driver_data;
- int ret;
-
- kempld_pdev = platform_device_alloc("kempld", -1);
- if (!kempld_pdev)
- return -ENOMEM;
-
- ret = platform_device_add_data(kempld_pdev, pdata, sizeof(*pdata));
- if (ret)
- goto err;
-
- ret = platform_device_add_resources(kempld_pdev, pdata->ioresource, 1);
- if (ret)
- goto err;
-
- ret = platform_device_add(kempld_pdev);
- if (ret)
- goto err;
+ const struct platform_device_info pdevinfo = {
+ .name = "kempld",
+ .id = PLATFORM_DEVID_NONE,
+ .res = pdata->ioresource,
+ .num_res = 1,
+ .data = pdata,
+ .size_data = sizeof(*pdata),
+ };
+
+ kempld_pdev = platform_device_register_full(&pdevinfo);
+ if (IS_ERR(kempld_pdev))
+ return PTR_ERR(kempld_pdev);
return 0;
-err:
- platform_device_put(kempld_pdev);
- return ret;
}
/**
@@ -299,11 +293,8 @@ static int kempld_get_info(struct kempld_device_data *pld)
else
minor = (pld->info.minor - 10) + 'A';
- ret = scnprintf(pld->info.version, sizeof(pld->info.version),
- "P%X%c%c.%04X", pld->info.number, major, minor,
- pld->info.buildnr);
- if (ret < 0)
- return ret;
+ scnprintf(pld->info.version, sizeof(pld->info.version), "P%X%c%c.%04X",
+ pld->info.number, major, minor, pld->info.buildnr);
return 0;
}
@@ -372,16 +363,13 @@ static DEVICE_ATTR_RO(pld_version);
static DEVICE_ATTR_RO(pld_specification);
static DEVICE_ATTR_RO(pld_type);
-static struct attribute *pld_attributes[] = {
+static struct attribute *pld_attrs[] = {
&dev_attr_pld_version.attr,
&dev_attr_pld_specification.attr,
&dev_attr_pld_type.attr,
NULL
};
-
-static const struct attribute_group pld_attr_group = {
- .attrs = pld_attributes,
-};
+ATTRIBUTE_GROUPS(pld);
static int kempld_detect_device(struct kempld_device_data *pld)
{
@@ -414,36 +402,8 @@ static int kempld_detect_device(struct kempld_device_data *pld)
pld->info.version, kempld_get_type_string(pld),
pld->info.spec_major, pld->info.spec_minor);
- ret = sysfs_create_group(&pld->dev->kobj, &pld_attr_group);
- if (ret)
- return ret;
-
- ret = kempld_register_cells(pld);
- if (ret)
- sysfs_remove_group(&pld->dev->kobj, &pld_attr_group);
-
- return ret;
-}
-
-#ifdef CONFIG_ACPI
-static int kempld_get_acpi_data(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- const struct kempld_platform_data *pdata;
- int ret;
-
- pdata = acpi_device_get_match_data(dev);
- ret = platform_device_add_data(pdev, pdata,
- sizeof(struct kempld_platform_data));
-
- return ret;
+ return kempld_register_cells(pld);
}
-#else
-static int kempld_get_acpi_data(struct platform_device *pdev)
-{
- return -ENODEV;
-}
-#endif /* CONFIG_ACPI */
static int kempld_probe(struct platform_device *pdev)
{
@@ -453,15 +413,21 @@ static int kempld_probe(struct platform_device *pdev)
struct resource *ioport;
int ret;
- if (kempld_pdev == NULL) {
+ if (IS_ERR_OR_NULL(kempld_pdev)) {
/*
* No kempld_pdev device has been registered in kempld_init,
* so we seem to be probing an ACPI platform device.
*/
- ret = kempld_get_acpi_data(pdev);
+ pdata = device_get_match_data(dev);
+ if (!pdata)
+ return -ENODEV;
+
+ ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
if (ret)
return ret;
- } else if (kempld_pdev != pdev) {
+ } else if (kempld_pdev == pdev) {
+ pdata = dev_get_platdata(dev);
+ } else {
/*
* The platform device we are probing is not the one we
* registered in kempld_init using the DMI table, so this one
@@ -472,7 +438,6 @@ static int kempld_probe(struct platform_device *pdev)
dev_notice(dev, "platform device exists - not using ACPI\n");
return -ENODEV;
}
- pdata = dev_get_platdata(dev);
pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL);
if (!pld)
@@ -503,25 +468,22 @@ static void kempld_remove(struct platform_device *pdev)
struct kempld_device_data *pld = platform_get_drvdata(pdev);
const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
- sysfs_remove_group(&pld->dev->kobj, &pld_attr_group);
-
mfd_remove_devices(&pdev->dev);
pdata->release_hardware_mutex(pld);
}
-#ifdef CONFIG_ACPI
static const struct acpi_device_id kempld_acpi_table[] = {
{ "KEM0000", (kernel_ulong_t)&kempld_platform_data_generic },
{ "KEM0001", (kernel_ulong_t)&kempld_platform_data_generic },
{}
};
MODULE_DEVICE_TABLE(acpi, kempld_acpi_table);
-#endif
static struct platform_driver kempld_driver = {
.driver = {
.name = "kempld",
- .acpi_match_table = ACPI_PTR(kempld_acpi_table),
+ .acpi_match_table = kempld_acpi_table,
+ .dev_groups = pld_groups,
},
.probe = kempld_probe,
.remove_new = kempld_remove,
@@ -534,375 +496,281 @@ static const struct dmi_system_id kempld_dmi_table[] __initconst = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bBD"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "BBL6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bBL6"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "BDV7",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bDV7"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "BHL6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bHL6"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "BKL6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bKL6"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "BSL6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bSL6"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CAL6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cAL"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CBL6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cBL6"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CBW6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cBW6"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CCR2",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP2"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CCR6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP6"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CDV7",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cDV7"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CHL6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cHL6"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CHR2",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T2"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CHR2",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T2"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CHR2",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC2"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CHR6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T6"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CHR6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T6"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CHR6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC6"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CKL6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cKL6"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CNTG",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-PC"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CNTG",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bPC2"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CNTX",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "PXT"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CSL6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cSL6"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "CVV6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cBT"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "FRI2",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BIOS_VERSION, "FRI2"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "FRI2",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "Fish River Island II"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "A203",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "KBox A-203"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "M4A1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-m4AL"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "MAL1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-mAL10"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "MAPL",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "mITX-APL"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "MBR1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "ETX-OH"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "MVV1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-mBT"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "NTC1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "nanoETXexpress-TT"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "NTC1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "nETXe-TT"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "NTC1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-mTT"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "NUP1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-mCT"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "PAPL",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "pITX-APL"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "SXAL",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "SMARC-sXAL"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "SXAL4",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "SMARC-sXA4"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "UNP1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-DC"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "UNP1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cDC2"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "UNTG",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-PC"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "UNTG",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cPC2"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "UUP6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cCT6"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "UTH6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cTH6"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
}, {
.ident = "Q7AL",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "Qseven-Q7AL"),
},
- .driver_data = (void *)&kempld_platform_data_generic,
- .callback = kempld_create_platform_device,
},
{}
};
@@ -911,27 +779,28 @@ MODULE_DEVICE_TABLE(dmi, kempld_dmi_table);
static int __init kempld_init(void)
{
const struct dmi_system_id *id;
+ int ret = -ENODEV;
- if (force_device_id[0]) {
- for (id = kempld_dmi_table;
- id->matches[0].slot != DMI_NONE; id++)
- if (strstr(id->ident, force_device_id))
- if (id->callback && !id->callback(id))
- break;
- if (id->matches[0].slot == DMI_NONE)
- return -ENODEV;
- } else {
- dmi_check_system(kempld_dmi_table);
+ for (id = dmi_first_match(kempld_dmi_table); id; id = dmi_first_match(id + 1)) {
+ /* Check, if user asked for the exact device ID match */
+ if (force_device_id[0] && !strstr(id->ident, force_device_id))
+ continue;
+
+ ret = kempld_create_platform_device(&kempld_platform_data_generic);
+ if (ret)
+ continue;
+
+ break;
}
+ if (ret)
+ return ret;
return platform_driver_register(&kempld_driver);
}
static void __exit kempld_exit(void)
{
- if (kempld_pdev)
- platform_device_unregister(kempld_pdev);
-
+ platform_device_unregister(kempld_pdev);
platform_driver_unregister(&kempld_driver);
}
diff --git a/drivers/mfd/ocelot-spi.c b/drivers/mfd/ocelot-spi.c
index 94f8267767..b015c8683f 100644
--- a/drivers/mfd/ocelot-spi.c
+++ b/drivers/mfd/ocelot-spi.c
@@ -145,7 +145,6 @@ static int ocelot_spi_regmap_bus_read(void *context, const void *reg, size_t reg
struct device *dev = context;
struct ocelot_ddata *ddata;
struct spi_device *spi;
- struct spi_message msg;
unsigned int index = 0;
ddata = dev_get_drvdata(dev);
@@ -166,9 +165,7 @@ static int ocelot_spi_regmap_bus_read(void *context, const void *reg, size_t reg
xfers[index].len = val_size;
index++;
- spi_message_init_with_transfers(&msg, xfers, index);
-
- return spi_sync(spi, &msg);
+ return spi_sync_transfer(spi, xfers, index);
}
static int ocelot_spi_regmap_bus_write(void *context, const void *data, size_t count)
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index b6303ddb01..f68dd02814 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -230,8 +230,7 @@ static int usbtll_omap_probe(struct platform_device *pdev)
break;
}
- tll = devm_kzalloc(dev, sizeof(*tll) + sizeof(tll->ch_clk[nch]),
- GFP_KERNEL);
+ tll = devm_kzalloc(dev, struct_size(tll, ch_clk, nch), GFP_KERNEL);
if (!tll) {
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
diff --git a/drivers/mfd/rk8xx-core.c b/drivers/mfd/rk8xx-core.c
index e2261b68b8..5eda3c0dbb 100644
--- a/drivers/mfd/rk8xx-core.c
+++ b/drivers/mfd/rk8xx-core.c
@@ -28,6 +28,10 @@ static const struct resource rtc_resources[] = {
DEFINE_RES_IRQ(RK808_IRQ_RTC_ALARM),
};
+static const struct resource rk816_rtc_resources[] = {
+ DEFINE_RES_IRQ(RK816_IRQ_RTC_ALARM),
+};
+
static const struct resource rk817_rtc_resources[] = {
DEFINE_RES_IRQ(RK817_IRQ_RTC_ALARM),
};
@@ -87,6 +91,22 @@ static const struct mfd_cell rk808s[] = {
},
};
+static const struct mfd_cell rk816s[] = {
+ { .name = "rk805-pinctrl", },
+ { .name = "rk808-clkout", },
+ { .name = "rk808-regulator", },
+ {
+ .name = "rk805-pwrkey",
+ .num_resources = ARRAY_SIZE(rk805_key_resources),
+ .resources = rk805_key_resources,
+ },
+ {
+ .name = "rk808-rtc",
+ .num_resources = ARRAY_SIZE(rk816_rtc_resources),
+ .resources = rk816_rtc_resources,
+ },
+};
+
static const struct mfd_cell rk817s[] = {
{ .name = "rk808-clkout", },
{ .name = "rk808-regulator", },
@@ -148,6 +168,17 @@ static const struct rk808_reg_data rk808_pre_init_reg[] = {
VB_LO_SEL_3500MV },
};
+static const struct rk808_reg_data rk816_pre_init_reg[] = {
+ { RK818_BUCK1_CONFIG_REG, RK817_RAMP_RATE_MASK,
+ RK817_RAMP_RATE_12_5MV_PER_US },
+ { RK818_BUCK2_CONFIG_REG, RK817_RAMP_RATE_MASK,
+ RK817_RAMP_RATE_12_5MV_PER_US },
+ { RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA },
+ { RK808_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP105C},
+ { RK808_VB_MON_REG, VBAT_LOW_VOL_MASK | VBAT_LOW_ACT_MASK,
+ RK808_VBAT_LOW_3V0 | EN_VABT_LOW_SHUT_DOWN },
+};
+
static const struct rk808_reg_data rk817_pre_init_reg[] = {
{RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP},
/* Codec specific registers */
@@ -350,6 +381,59 @@ static const struct regmap_irq rk808_irqs[] = {
},
};
+static const unsigned int rk816_irq_status_offsets[] = {
+ RK816_IRQ_STS_OFFSET(RK816_INT_STS_REG1),
+ RK816_IRQ_STS_OFFSET(RK816_INT_STS_REG2),
+ RK816_IRQ_STS_OFFSET(RK816_INT_STS_REG3),
+};
+
+static const unsigned int rk816_irq_mask_offsets[] = {
+ RK816_IRQ_MSK_OFFSET(RK816_INT_STS_MSK_REG1),
+ RK816_IRQ_MSK_OFFSET(RK816_INT_STS_MSK_REG2),
+ RK816_IRQ_MSK_OFFSET(RK816_INT_STS_MSK_REG3),
+};
+
+static unsigned int rk816_get_irq_reg(struct regmap_irq_chip_data *data,
+ unsigned int base, int index)
+{
+ unsigned int irq_reg = base;
+
+ switch (base) {
+ case RK816_INT_STS_REG1:
+ irq_reg += rk816_irq_status_offsets[index];
+ break;
+ case RK816_INT_STS_MSK_REG1:
+ irq_reg += rk816_irq_mask_offsets[index];
+ break;
+ }
+
+ return irq_reg;
+};
+
+static const struct regmap_irq rk816_irqs[] = {
+ /* INT_STS_REG1 IRQs */
+ REGMAP_IRQ_REG(RK816_IRQ_PWRON_FALL, 0, RK816_INT_STS_PWRON_FALL),
+ REGMAP_IRQ_REG(RK816_IRQ_PWRON_RISE, 0, RK816_INT_STS_PWRON_RISE),
+
+ /* INT_STS_REG2 IRQs */
+ REGMAP_IRQ_REG(RK816_IRQ_VB_LOW, 1, RK816_INT_STS_VB_LOW),
+ REGMAP_IRQ_REG(RK816_IRQ_PWRON, 1, RK816_INT_STS_PWRON),
+ REGMAP_IRQ_REG(RK816_IRQ_PWRON_LP, 1, RK816_INT_STS_PWRON_LP),
+ REGMAP_IRQ_REG(RK816_IRQ_HOTDIE, 1, RK816_INT_STS_HOTDIE),
+ REGMAP_IRQ_REG(RK816_IRQ_RTC_ALARM, 1, RK816_INT_STS_RTC_ALARM),
+ REGMAP_IRQ_REG(RK816_IRQ_RTC_PERIOD, 1, RK816_INT_STS_RTC_PERIOD),
+ REGMAP_IRQ_REG(RK816_IRQ_USB_OV, 1, RK816_INT_STS_USB_OV),
+
+ /* INT_STS3 IRQs */
+ REGMAP_IRQ_REG(RK816_IRQ_PLUG_IN, 2, RK816_INT_STS_PLUG_IN),
+ REGMAP_IRQ_REG(RK816_IRQ_PLUG_OUT, 2, RK816_INT_STS_PLUG_OUT),
+ REGMAP_IRQ_REG(RK816_IRQ_CHG_OK, 2, RK816_INT_STS_CHG_OK),
+ REGMAP_IRQ_REG(RK816_IRQ_CHG_TE, 2, RK816_INT_STS_CHG_TE),
+ REGMAP_IRQ_REG(RK816_IRQ_CHG_TS, 2, RK816_INT_STS_CHG_TS),
+ REGMAP_IRQ_REG(RK816_IRQ_CHG_CVTLIM, 2, RK816_INT_STS_CHG_CVTLIM),
+ REGMAP_IRQ_REG(RK816_IRQ_DISCHG_ILIM, 2, RK816_INT_STS_DISCHG_ILIM),
+};
+
static const struct regmap_irq rk818_irqs[] = {
/* INT_STS */
[RK818_IRQ_VOUT_LO] = {
@@ -482,6 +566,18 @@ static const struct regmap_irq_chip rk808_irq_chip = {
.init_ack_masked = true,
};
+static const struct regmap_irq_chip rk816_irq_chip = {
+ .name = "rk816",
+ .irqs = rk816_irqs,
+ .num_irqs = ARRAY_SIZE(rk816_irqs),
+ .num_regs = 3,
+ .get_irq_reg = rk816_get_irq_reg,
+ .status_base = RK816_INT_STS_REG1,
+ .mask_base = RK816_INT_STS_MSK_REG1,
+ .ack_base = RK816_INT_STS_REG1,
+ .init_ack_masked = true,
+};
+
static struct regmap_irq_chip rk817_irq_chip = {
.name = "rk817",
.irqs = rk817_irqs,
@@ -530,6 +626,7 @@ static int rk808_power_off(struct sys_off_data *data)
reg = RK817_SYS_CFG(3);
bit = DEV_OFF;
break;
+ case RK816_ID:
case RK818_ID:
reg = RK818_DEVCTRL_REG;
bit = DEV_OFF;
@@ -637,6 +734,13 @@ int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap
cells = rk808s;
nr_cells = ARRAY_SIZE(rk808s);
break;
+ case RK816_ID:
+ rk808->regmap_irq_chip = &rk816_irq_chip;
+ pre_init_reg = rk816_pre_init_reg;
+ nr_pre_init_regs = ARRAY_SIZE(rk816_pre_init_reg);
+ cells = rk816s;
+ nr_cells = ARRAY_SIZE(rk816s);
+ break;
case RK818_ID:
rk808->regmap_irq_chip = &rk818_irq_chip;
pre_init_reg = rk818_pre_init_reg;
diff --git a/drivers/mfd/rk8xx-i2c.c b/drivers/mfd/rk8xx-i2c.c
index 75b5cf09d5..69a6b297d7 100644
--- a/drivers/mfd/rk8xx-i2c.c
+++ b/drivers/mfd/rk8xx-i2c.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Rockchip RK808/RK818 Core (I2C) driver
+ * Rockchip RK805/RK808/RK816/RK817/RK818 Core (I2C) driver
*
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
* Copyright (C) 2016 PHYTEC Messtechnik GmbH
@@ -49,6 +49,35 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
return false;
}
+static bool rk816_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ /*
+ * Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
+ * we don't use that feature. It's better to cache.
+ */
+
+ switch (reg) {
+ case RK808_SECONDS_REG ... RK808_WEEKS_REG:
+ case RK808_RTC_STATUS_REG:
+ case RK808_VB_MON_REG:
+ case RK808_THERMAL_REG:
+ case RK816_DCDC_EN_REG1:
+ case RK816_DCDC_EN_REG2:
+ case RK816_INT_STS_REG1:
+ case RK816_INT_STS_REG2:
+ case RK816_INT_STS_REG3:
+ case RK808_DEVCTRL_REG:
+ case RK816_SUP_STS_REG:
+ case RK816_GGSTS_REG:
+ case RK816_ZERO_CUR_ADC_REGH:
+ case RK816_ZERO_CUR_ADC_REGL:
+ case RK816_GASCNT_REG(0) ... RK816_BAT_VOL_REGL:
+ return true;
+ }
+
+ return false;
+}
+
static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
{
/*
@@ -100,6 +129,14 @@ static const struct regmap_config rk808_regmap_config = {
.volatile_reg = rk808_is_volatile_reg,
};
+static const struct regmap_config rk816_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = RK816_DATA_REG(18),
+ .cache_type = REGCACHE_MAPLE,
+ .volatile_reg = rk816_is_volatile_reg,
+};
+
static const struct regmap_config rk817_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -123,6 +160,11 @@ static const struct rk8xx_i2c_platform_data rk809_data = {
.variant = RK809_ID,
};
+static const struct rk8xx_i2c_platform_data rk816_data = {
+ .regmap_cfg = &rk816_regmap_config,
+ .variant = RK816_ID,
+};
+
static const struct rk8xx_i2c_platform_data rk817_data = {
.regmap_cfg = &rk817_regmap_config,
.variant = RK817_ID,
@@ -161,6 +203,7 @@ static const struct of_device_id rk8xx_i2c_of_match[] = {
{ .compatible = "rockchip,rk805", .data = &rk805_data },
{ .compatible = "rockchip,rk808", .data = &rk808_data },
{ .compatible = "rockchip,rk809", .data = &rk809_data },
+ { .compatible = "rockchip,rk816", .data = &rk816_data },
{ .compatible = "rockchip,rk817", .data = &rk817_data },
{ .compatible = "rockchip,rk818", .data = &rk818_data },
{ },
diff --git a/drivers/mfd/rohm-bd71828.c b/drivers/mfd/rohm-bd71828.c
index 2f3826c7ee..5b4290f116 100644
--- a/drivers/mfd/rohm-bd71828.c
+++ b/drivers/mfd/rohm-bd71828.c
@@ -464,6 +464,27 @@ static int set_clk_mode(struct device *dev, struct regmap *regmap,
OUT32K_MODE_CMOS);
}
+static struct i2c_client *bd71828_dev;
+static void bd71828_power_off(void)
+{
+ while (true) {
+ s32 val;
+
+ /* We are not allowed to sleep, so do not use regmap involving mutexes here. */
+ val = i2c_smbus_read_byte_data(bd71828_dev, BD71828_REG_PS_CTRL_1);
+ if (val >= 0)
+ i2c_smbus_write_byte_data(bd71828_dev,
+ BD71828_REG_PS_CTRL_1,
+ BD71828_MASK_STATE_HBNT | (u8)val);
+ mdelay(500);
+ }
+}
+
+static void bd71828_remove_poweroff(void *data)
+{
+ pm_power_off = NULL;
+}
+
static int bd71828_i2c_probe(struct i2c_client *i2c)
{
struct regmap_irq_chip_data *irq_data;
@@ -542,7 +563,20 @@ static int bd71828_i2c_probe(struct i2c_client *i2c)
ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO, mfd, cells,
NULL, 0, regmap_irq_get_domain(irq_data));
if (ret)
- dev_err_probe(&i2c->dev, ret, "Failed to create subdevices\n");
+ return dev_err_probe(&i2c->dev, ret, "Failed to create subdevices\n");
+
+ if (of_device_is_system_power_controller(i2c->dev.of_node) &&
+ chip_type == ROHM_CHIP_TYPE_BD71828) {
+ if (!pm_power_off) {
+ bd71828_dev = i2c;
+ pm_power_off = bd71828_power_off;
+ ret = devm_add_action_or_reset(&i2c->dev,
+ bd71828_remove_poweroff,
+ NULL);
+ } else {
+ dev_warn(&i2c->dev, "Poweroff callback already assigned\n");
+ }
+ }
return ret;
}
diff --git a/drivers/mfd/rsmu_core.c b/drivers/mfd/rsmu_core.c
index 29437fd0bd..fd04a6e5df 100644
--- a/drivers/mfd/rsmu_core.c
+++ b/drivers/mfd/rsmu_core.c
@@ -78,11 +78,13 @@ int rsmu_core_init(struct rsmu_ddata *rsmu)
return ret;
}
+EXPORT_SYMBOL_GPL(rsmu_core_init);
void rsmu_core_exit(struct rsmu_ddata *rsmu)
{
mutex_destroy(&rsmu->lock);
}
+EXPORT_SYMBOL_GPL(rsmu_core_exit);
MODULE_DESCRIPTION("Renesas SMU core driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/rsmu_i2c.c b/drivers/mfd/rsmu_i2c.c
index 5711e512b6..cba64f107a 100644
--- a/drivers/mfd/rsmu_i2c.c
+++ b/drivers/mfd/rsmu_i2c.c
@@ -32,6 +32,8 @@
#define RSMU_SABRE_PAGE_ADDR 0x7F
#define RSMU_SABRE_PAGE_WINDOW 128
+typedef int (*rsmu_rw_device)(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u8 bytes);
+
static const struct regmap_range_cfg rsmu_sabre_range_cfg[] = {
{
.range_min = 0,
@@ -54,7 +56,28 @@ static bool rsmu_sabre_volatile_reg(struct device *dev, unsigned int reg)
}
}
-static int rsmu_read_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes)
+static int rsmu_smbus_i2c_write_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u8 bytes)
+{
+ struct i2c_client *client = to_i2c_client(rsmu->dev);
+
+ return i2c_smbus_write_i2c_block_data(client, reg, bytes, buf);
+}
+
+static int rsmu_smbus_i2c_read_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u8 bytes)
+{
+ struct i2c_client *client = to_i2c_client(rsmu->dev);
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(client, reg, bytes, buf);
+ if (ret == bytes)
+ return 0;
+ else if (ret < 0)
+ return ret;
+ else
+ return -EIO;
+}
+
+static int rsmu_i2c_read_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u8 bytes)
{
struct i2c_client *client = to_i2c_client(rsmu->dev);
struct i2c_msg msg[2];
@@ -84,10 +107,11 @@ static int rsmu_read_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes)
return 0;
}
-static int rsmu_write_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes)
+static int rsmu_i2c_write_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u8 bytes)
{
struct i2c_client *client = to_i2c_client(rsmu->dev);
- u8 msg[RSMU_MAX_WRITE_COUNT + 1]; /* 1 Byte added for the device register */
+ /* we add 1 byte for device register */
+ u8 msg[RSMU_MAX_WRITE_COUNT + 1];
int cnt;
if (bytes > RSMU_MAX_WRITE_COUNT)
@@ -107,7 +131,8 @@ static int rsmu_write_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes
return 0;
}
-static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u32 reg)
+static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u32 reg,
+ rsmu_rw_device rsmu_write_device)
{
u32 page = reg & RSMU_CM_PAGE_MASK;
u8 buf[4];
@@ -136,35 +161,35 @@ static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u32 reg)
return err;
}
-static int rsmu_reg_read(void *context, unsigned int reg, unsigned int *val)
+static int rsmu_i2c_reg_read(void *context, unsigned int reg, unsigned int *val)
{
struct rsmu_ddata *rsmu = i2c_get_clientdata((struct i2c_client *)context);
u8 addr = (u8)(reg & RSMU_CM_ADDRESS_MASK);
int err;
- err = rsmu_write_page_register(rsmu, reg);
+ err = rsmu_write_page_register(rsmu, reg, rsmu_i2c_write_device);
if (err)
return err;
- err = rsmu_read_device(rsmu, addr, (u8 *)val, 1);
+ err = rsmu_i2c_read_device(rsmu, addr, (u8 *)val, 1);
if (err)
dev_err(rsmu->dev, "Failed to read offset address 0x%x\n", addr);
return err;
}
-static int rsmu_reg_write(void *context, unsigned int reg, unsigned int val)
+static int rsmu_i2c_reg_write(void *context, unsigned int reg, unsigned int val)
{
struct rsmu_ddata *rsmu = i2c_get_clientdata((struct i2c_client *)context);
u8 addr = (u8)(reg & RSMU_CM_ADDRESS_MASK);
u8 data = (u8)val;
int err;
- err = rsmu_write_page_register(rsmu, reg);
+ err = rsmu_write_page_register(rsmu, reg, rsmu_i2c_write_device);
if (err)
return err;
- err = rsmu_write_device(rsmu, addr, &data, 1);
+ err = rsmu_i2c_write_device(rsmu, addr, &data, 1);
if (err)
dev_err(rsmu->dev,
"Failed to write offset address 0x%x\n", addr);
@@ -172,12 +197,57 @@ static int rsmu_reg_write(void *context, unsigned int reg, unsigned int val)
return err;
}
-static const struct regmap_config rsmu_cm_regmap_config = {
+static int rsmu_smbus_i2c_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct rsmu_ddata *rsmu = i2c_get_clientdata((struct i2c_client *)context);
+ u8 addr = (u8)(reg & RSMU_CM_ADDRESS_MASK);
+ int err;
+
+ err = rsmu_write_page_register(rsmu, reg, rsmu_smbus_i2c_write_device);
+ if (err)
+ return err;
+
+ err = rsmu_smbus_i2c_read_device(rsmu, addr, (u8 *)val, 1);
+ if (err)
+ dev_err(rsmu->dev, "Failed to read offset address 0x%x\n", addr);
+
+ return err;
+}
+
+static int rsmu_smbus_i2c_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct rsmu_ddata *rsmu = i2c_get_clientdata((struct i2c_client *)context);
+ u8 addr = (u8)(reg & RSMU_CM_ADDRESS_MASK);
+ u8 data = (u8)val;
+ int err;
+
+ err = rsmu_write_page_register(rsmu, reg, rsmu_smbus_i2c_write_device);
+ if (err)
+ return err;
+
+ err = rsmu_smbus_i2c_write_device(rsmu, addr, &data, 1);
+ if (err)
+ dev_err(rsmu->dev,
+ "Failed to write offset address 0x%x\n", addr);
+
+ return err;
+}
+
+static const struct regmap_config rsmu_i2c_cm_regmap_config = {
.reg_bits = 32,
.val_bits = 8,
.max_register = 0x20120000,
- .reg_read = rsmu_reg_read,
- .reg_write = rsmu_reg_write,
+ .reg_read = rsmu_i2c_reg_read,
+ .reg_write = rsmu_i2c_reg_write,
+ .cache_type = REGCACHE_NONE,
+};
+
+static const struct regmap_config rsmu_smbus_i2c_cm_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 8,
+ .max_register = 0x20120000,
+ .reg_read = rsmu_smbus_i2c_reg_read,
+ .reg_write = rsmu_smbus_i2c_reg_write,
.cache_type = REGCACHE_NONE,
};
@@ -219,7 +289,15 @@ static int rsmu_i2c_probe(struct i2c_client *client)
switch (rsmu->type) {
case RSMU_CM:
- cfg = &rsmu_cm_regmap_config;
+ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ cfg = &rsmu_i2c_cm_regmap_config;
+ } else if (i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_I2C_BLOCK)) {
+ cfg = &rsmu_smbus_i2c_cm_regmap_config;
+ } else {
+ dev_err(rsmu->dev, "Unsupported i2c adapter\n");
+ return -ENOTSUPP;
+ }
break;
case RSMU_SABRE:
cfg = &rsmu_sabre_regmap_config;
@@ -236,6 +314,7 @@ static int rsmu_i2c_probe(struct i2c_client *client)
rsmu->regmap = devm_regmap_init(&client->dev, NULL, client, cfg);
else
rsmu->regmap = devm_regmap_init_i2c(client, cfg);
+
if (IS_ERR(rsmu->regmap)) {
ret = PTR_ERR(rsmu->regmap);
dev_err(rsmu->dev, "Failed to allocate register map: %d\n", ret);
diff --git a/drivers/mfd/rsmu_spi.c b/drivers/mfd/rsmu_spi.c
index ca0a1202c3..39d9be1e14 100644
--- a/drivers/mfd/rsmu_spi.c
+++ b/drivers/mfd/rsmu_spi.c
@@ -106,10 +106,10 @@ static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u32 reg)
return 0;
page_reg = RSMU_CM_PAGE_ADDR;
page = reg & RSMU_PAGE_MASK;
- buf[0] = (u8)(page & 0xff);
- buf[1] = (u8)((page >> 8) & 0xff);
- buf[2] = (u8)((page >> 16) & 0xff);
- buf[3] = (u8)((page >> 24) & 0xff);
+ buf[0] = (u8)(page & 0xFF);
+ buf[1] = (u8)((page >> 8) & 0xFF);
+ buf[2] = (u8)((page >> 16) & 0xFF);
+ buf[3] = (u8)((page >> 24) & 0xFF);
bytes = 4;
break;
case RSMU_SABRE:
diff --git a/drivers/mfd/ssbi.c b/drivers/mfd/ssbi.c
index b0b0be483d..f849f2d34e 100644
--- a/drivers/mfd/ssbi.c
+++ b/drivers/mfd/ssbi.c
@@ -64,7 +64,6 @@ enum ssbi_controller_type {
};
struct ssbi {
- struct device *slave;
void __iomem *base;
spinlock_t lock;
enum ssbi_controller_type controller_type;
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
index 07e5aa10a1..a41e9a3e20 100644
--- a/drivers/mfd/timberdale.c
+++ b/drivers/mfd/timberdale.c
@@ -765,7 +765,6 @@ static int timb_probe(struct pci_dev *dev,
default:
dev_err(&dev->dev, "Unknown IP setup: %d.%d.%d\n",
priv->fw.major, priv->fw.minor, ip_setup);
- err = -ENODEV;
goto err_mfd;
}
diff --git a/drivers/mfd/tps6594-core.c b/drivers/mfd/tps6594-core.c
index 783ee59901..c59f3d7e32 100644
--- a/drivers/mfd/tps6594-core.c
+++ b/drivers/mfd/tps6594-core.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Core functions for TI TPS6594/TPS6593/LP8764 PMICs
+ * Core functions for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs
*
* Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
*/
@@ -278,16 +278,159 @@ static const unsigned int tps6594_irq_reg[] = {
TPS6594_REG_RTC_STATUS,
};
+/* TPS65224 Resources */
+
+static const struct resource tps65224_regulator_resources[] = {
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_BUCK1_UVOV, TPS65224_IRQ_NAME_BUCK1_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_BUCK2_UVOV, TPS65224_IRQ_NAME_BUCK2_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_BUCK3_UVOV, TPS65224_IRQ_NAME_BUCK3_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_BUCK4_UVOV, TPS65224_IRQ_NAME_BUCK4_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_LDO1_UVOV, TPS65224_IRQ_NAME_LDO1_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_LDO2_UVOV, TPS65224_IRQ_NAME_LDO2_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_LDO3_UVOV, TPS65224_IRQ_NAME_LDO3_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_VCCA_UVOV, TPS65224_IRQ_NAME_VCCA_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_VMON1_UVOV, TPS65224_IRQ_NAME_VMON1_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_VMON2_UVOV, TPS65224_IRQ_NAME_VMON2_UVOV),
+};
+
+static const struct resource tps65224_pinctrl_resources[] = {
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_GPIO1, TPS65224_IRQ_NAME_GPIO1),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_GPIO2, TPS65224_IRQ_NAME_GPIO2),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_GPIO3, TPS65224_IRQ_NAME_GPIO3),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_GPIO4, TPS65224_IRQ_NAME_GPIO4),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_GPIO5, TPS65224_IRQ_NAME_GPIO5),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_GPIO6, TPS65224_IRQ_NAME_GPIO6),
+};
+
+static const struct resource tps65224_pfsm_resources[] = {
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_VSENSE, TPS65224_IRQ_NAME_VSENSE),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_ENABLE, TPS65224_IRQ_NAME_ENABLE),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_PB_SHORT, TPS65224_IRQ_NAME_PB_SHORT),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_FSD, TPS65224_IRQ_NAME_FSD),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_SOFT_REBOOT, TPS65224_IRQ_NAME_SOFT_REBOOT),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_BIST_PASS, TPS65224_IRQ_NAME_BIST_PASS),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_EXT_CLK, TPS65224_IRQ_NAME_EXT_CLK),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_REG_UNLOCK, TPS65224_IRQ_NAME_REG_UNLOCK),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_TWARN, TPS65224_IRQ_NAME_TWARN),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_PB_LONG, TPS65224_IRQ_NAME_PB_LONG),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_PB_FALL, TPS65224_IRQ_NAME_PB_FALL),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_PB_RISE, TPS65224_IRQ_NAME_PB_RISE),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_TSD_ORD, TPS65224_IRQ_NAME_TSD_ORD),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_BIST_FAIL, TPS65224_IRQ_NAME_BIST_FAIL),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_REG_CRC_ERR, TPS65224_IRQ_NAME_REG_CRC_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_RECOV_CNT, TPS65224_IRQ_NAME_RECOV_CNT),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_TSD_IMM, TPS65224_IRQ_NAME_TSD_IMM),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_VCCA_OVP, TPS65224_IRQ_NAME_VCCA_OVP),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_PFSM_ERR, TPS65224_IRQ_NAME_PFSM_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_BG_XMON, TPS65224_IRQ_NAME_BG_XMON),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_IMM_SHUTDOWN, TPS65224_IRQ_NAME_IMM_SHUTDOWN),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_ORD_SHUTDOWN, TPS65224_IRQ_NAME_ORD_SHUTDOWN),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_MCU_PWR_ERR, TPS65224_IRQ_NAME_MCU_PWR_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_SOC_PWR_ERR, TPS65224_IRQ_NAME_SOC_PWR_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_COMM_ERR, TPS65224_IRQ_NAME_COMM_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_I2C2_ERR, TPS65224_IRQ_NAME_I2C2_ERR),
+};
+
+static const struct resource tps65224_adc_resources[] = {
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_ADC_CONV_READY, TPS65224_IRQ_NAME_ADC_CONV_READY),
+};
+
+static const struct mfd_cell tps65224_common_cells[] = {
+ MFD_CELL_RES("tps65224-adc", tps65224_adc_resources),
+ MFD_CELL_RES("tps6594-pfsm", tps65224_pfsm_resources),
+ MFD_CELL_RES("tps6594-pinctrl", tps65224_pinctrl_resources),
+ MFD_CELL_RES("tps6594-regulator", tps65224_regulator_resources),
+};
+
+static const struct regmap_irq tps65224_irqs[] = {
+ /* INT_BUCK register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_BUCK1_UVOV, 0, TPS65224_BIT_BUCK1_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_BUCK2_UVOV, 0, TPS65224_BIT_BUCK2_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_BUCK3_UVOV, 0, TPS65224_BIT_BUCK3_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_BUCK4_UVOV, 0, TPS65224_BIT_BUCK4_UVOV_INT),
+
+ /* INT_VMON_LDO register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_LDO1_UVOV, 1, TPS65224_BIT_LDO1_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_LDO2_UVOV, 1, TPS65224_BIT_LDO2_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_LDO3_UVOV, 1, TPS65224_BIT_LDO3_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_VCCA_UVOV, 1, TPS65224_BIT_VCCA_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_VMON1_UVOV, 1, TPS65224_BIT_VMON1_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_VMON2_UVOV, 1, TPS65224_BIT_VMON2_UVOV_INT),
+
+ /* INT_GPIO register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_GPIO1, 2, TPS65224_BIT_GPIO1_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_GPIO2, 2, TPS65224_BIT_GPIO2_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_GPIO3, 2, TPS65224_BIT_GPIO3_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_GPIO4, 2, TPS65224_BIT_GPIO4_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_GPIO5, 2, TPS65224_BIT_GPIO5_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_GPIO6, 2, TPS65224_BIT_GPIO6_INT),
+
+ /* INT_STARTUP register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_VSENSE, 3, TPS65224_BIT_VSENSE_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_ENABLE, 3, TPS6594_BIT_ENABLE_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_PB_SHORT, 3, TPS65224_BIT_PB_SHORT_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_FSD, 3, TPS6594_BIT_FSD_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_SOFT_REBOOT, 3, TPS6594_BIT_SOFT_REBOOT_INT),
+
+ /* INT_MISC register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_BIST_PASS, 4, TPS6594_BIT_BIST_PASS_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_EXT_CLK, 4, TPS6594_BIT_EXT_CLK_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_REG_UNLOCK, 4, TPS65224_BIT_REG_UNLOCK_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_TWARN, 4, TPS6594_BIT_TWARN_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_PB_LONG, 4, TPS65224_BIT_PB_LONG_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_PB_FALL, 4, TPS65224_BIT_PB_FALL_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_PB_RISE, 4, TPS65224_BIT_PB_RISE_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_ADC_CONV_READY, 4, TPS65224_BIT_ADC_CONV_READY_INT),
+
+ /* INT_MODERATE_ERR register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_TSD_ORD, 5, TPS6594_BIT_TSD_ORD_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_BIST_FAIL, 5, TPS6594_BIT_BIST_FAIL_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_REG_CRC_ERR, 5, TPS6594_BIT_REG_CRC_ERR_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_RECOV_CNT, 5, TPS6594_BIT_RECOV_CNT_INT),
+
+ /* INT_SEVERE_ERR register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_TSD_IMM, 6, TPS6594_BIT_TSD_IMM_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_VCCA_OVP, 6, TPS6594_BIT_VCCA_OVP_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_PFSM_ERR, 6, TPS6594_BIT_PFSM_ERR_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_BG_XMON, 6, TPS65224_BIT_BG_XMON_INT),
+
+ /* INT_FSM_ERR register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_IMM_SHUTDOWN, 7, TPS6594_BIT_IMM_SHUTDOWN_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_ORD_SHUTDOWN, 7, TPS6594_BIT_ORD_SHUTDOWN_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_MCU_PWR_ERR, 7, TPS6594_BIT_MCU_PWR_ERR_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_SOC_PWR_ERR, 7, TPS6594_BIT_SOC_PWR_ERR_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_COMM_ERR, 7, TPS6594_BIT_COMM_ERR_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_I2C2_ERR, 7, TPS65224_BIT_I2C2_ERR_INT),
+};
+
+static const unsigned int tps65224_irq_reg[] = {
+ TPS6594_REG_INT_BUCK,
+ TPS6594_REG_INT_LDO_VMON,
+ TPS6594_REG_INT_GPIO,
+ TPS6594_REG_INT_STARTUP,
+ TPS6594_REG_INT_MISC,
+ TPS6594_REG_INT_MODERATE_ERR,
+ TPS6594_REG_INT_SEVERE_ERR,
+ TPS6594_REG_INT_FSM_ERR,
+};
+
static inline unsigned int tps6594_get_irq_reg(struct regmap_irq_chip_data *data,
unsigned int base, int index)
{
return tps6594_irq_reg[index];
};
+static inline unsigned int tps65224_get_irq_reg(struct regmap_irq_chip_data *data,
+ unsigned int base, int index)
+{
+ return tps65224_irq_reg[index];
+};
+
static int tps6594_handle_post_irq(void *irq_drv_data)
{
struct tps6594 *tps = irq_drv_data;
int ret = 0;
+ unsigned int regmap_reg, mask_val;
/*
* When CRC is enabled, writing to a read-only bit triggers an error,
@@ -299,10 +442,17 @@ static int tps6594_handle_post_irq(void *irq_drv_data)
* COMM_ADR_ERR_INT bit set. Clear immediately this bit to avoid raising
* a new interrupt.
*/
- if (tps->use_crc)
- ret = regmap_write_bits(tps->regmap, TPS6594_REG_INT_COMM_ERR,
- TPS6594_BIT_COMM_ADR_ERR_INT,
- TPS6594_BIT_COMM_ADR_ERR_INT);
+ if (tps->use_crc) {
+ if (tps->chip_id == TPS65224) {
+ regmap_reg = TPS6594_REG_INT_FSM_ERR;
+ mask_val = TPS6594_BIT_COMM_ERR_INT;
+ } else {
+ regmap_reg = TPS6594_REG_INT_COMM_ERR;
+ mask_val = TPS6594_BIT_COMM_ADR_ERR_INT;
+ }
+
+ ret = regmap_write_bits(tps->regmap, regmap_reg, mask_val, mask_val);
+ }
return ret;
};
@@ -319,24 +469,58 @@ static struct regmap_irq_chip tps6594_irq_chip = {
.handle_post_irq = tps6594_handle_post_irq,
};
-bool tps6594_is_volatile_reg(struct device *dev, unsigned int reg)
-{
- return (reg >= TPS6594_REG_INT_TOP && reg <= TPS6594_REG_STAT_READBACK_ERR) ||
- reg == TPS6594_REG_RTC_STATUS;
-}
-EXPORT_SYMBOL_GPL(tps6594_is_volatile_reg);
+static struct regmap_irq_chip tps65224_irq_chip = {
+ .ack_base = TPS6594_REG_INT_BUCK,
+ .ack_invert = 1,
+ .clear_ack = 1,
+ .init_ack_masked = 1,
+ .num_regs = ARRAY_SIZE(tps65224_irq_reg),
+ .irqs = tps65224_irqs,
+ .num_irqs = ARRAY_SIZE(tps65224_irqs),
+ .get_irq_reg = tps65224_get_irq_reg,
+ .handle_post_irq = tps6594_handle_post_irq,
+};
+
+static const struct regmap_range tps6594_volatile_ranges[] = {
+ regmap_reg_range(TPS6594_REG_INT_TOP, TPS6594_REG_STAT_READBACK_ERR),
+ regmap_reg_range(TPS6594_REG_RTC_STATUS, TPS6594_REG_RTC_STATUS),
+};
+
+const struct regmap_access_table tps6594_volatile_table = {
+ .yes_ranges = tps6594_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(tps6594_volatile_ranges),
+};
+EXPORT_SYMBOL_GPL(tps6594_volatile_table);
+
+static const struct regmap_range tps65224_volatile_ranges[] = {
+ regmap_reg_range(TPS6594_REG_INT_TOP, TPS6594_REG_STAT_SEVERE_ERR),
+};
+
+const struct regmap_access_table tps65224_volatile_table = {
+ .yes_ranges = tps65224_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(tps65224_volatile_ranges),
+};
+EXPORT_SYMBOL_GPL(tps65224_volatile_table);
static int tps6594_check_crc_mode(struct tps6594 *tps, bool primary_pmic)
{
int ret;
+ unsigned int regmap_reg, mask_val;
+
+ if (tps->chip_id == TPS65224) {
+ regmap_reg = TPS6594_REG_CONFIG_2;
+ mask_val = TPS65224_BIT_I2C1_SPI_CRC_EN;
+ } else {
+ regmap_reg = TPS6594_REG_SERIAL_IF_CONFIG;
+ mask_val = TPS6594_BIT_I2C1_SPI_CRC_EN;
+ };
/*
* Check if CRC is enabled.
* Once CRC is enabled, it can't be disabled until next power cycle.
*/
tps->use_crc = true;
- ret = regmap_test_bits(tps->regmap, TPS6594_REG_SERIAL_IF_CONFIG,
- TPS6594_BIT_I2C1_SPI_CRC_EN);
+ ret = regmap_test_bits(tps->regmap, regmap_reg, mask_val);
if (ret == 0) {
ret = -EIO;
} else if (ret > 0) {
@@ -351,6 +535,15 @@ static int tps6594_check_crc_mode(struct tps6594 *tps, bool primary_pmic)
static int tps6594_set_crc_feature(struct tps6594 *tps)
{
int ret;
+ unsigned int regmap_reg, mask_val;
+
+ if (tps->chip_id == TPS65224) {
+ regmap_reg = TPS6594_REG_CONFIG_2;
+ mask_val = TPS65224_BIT_I2C1_SPI_CRC_EN;
+ } else {
+ regmap_reg = TPS6594_REG_FSM_I2C_TRIGGERS;
+ mask_val = TPS6594_BIT_TRIGGER_I2C(2);
+ }
ret = tps6594_check_crc_mode(tps, true);
if (ret) {
@@ -359,8 +552,7 @@ static int tps6594_set_crc_feature(struct tps6594 *tps)
* on primary PMIC.
*/
tps->use_crc = false;
- ret = regmap_write_bits(tps->regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
- TPS6594_BIT_TRIGGER_I2C(2), TPS6594_BIT_TRIGGER_I2C(2));
+ ret = regmap_write_bits(tps->regmap, regmap_reg, mask_val, mask_val);
if (ret)
return ret;
@@ -416,6 +608,9 @@ int tps6594_device_init(struct tps6594 *tps, bool enable_crc)
{
struct device *dev = tps->dev;
int ret;
+ struct regmap_irq_chip *irq_chip;
+ const struct mfd_cell *cells;
+ int n_cells;
if (enable_crc) {
ret = tps6594_enable_crc(tps);
@@ -429,26 +624,35 @@ int tps6594_device_init(struct tps6594 *tps, bool enable_crc)
if (ret)
return dev_err_probe(dev, ret, "Failed to set PMIC state\n");
- tps6594_irq_chip.irq_drv_data = tps;
- tps6594_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL, "%s-%ld-0x%02x",
- dev->driver->name, tps->chip_id, tps->reg);
+ if (tps->chip_id == TPS65224) {
+ irq_chip = &tps65224_irq_chip;
+ n_cells = ARRAY_SIZE(tps65224_common_cells);
+ cells = tps65224_common_cells;
+ } else {
+ irq_chip = &tps6594_irq_chip;
+ n_cells = ARRAY_SIZE(tps6594_common_cells);
+ cells = tps6594_common_cells;
+ }
+
+ irq_chip->irq_drv_data = tps;
+ irq_chip->name = devm_kasprintf(dev, GFP_KERNEL, "%s-%ld-0x%02x",
+ dev->driver->name, tps->chip_id, tps->reg);
- if (!tps6594_irq_chip.name)
+ if (!irq_chip->name)
return -ENOMEM;
ret = devm_regmap_add_irq_chip(dev, tps->regmap, tps->irq, IRQF_SHARED | IRQF_ONESHOT,
- 0, &tps6594_irq_chip, &tps->irq_data);
+ 0, irq_chip, &tps->irq_data);
if (ret)
return dev_err_probe(dev, ret, "Failed to add regmap IRQ\n");
- ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, tps6594_common_cells,
- ARRAY_SIZE(tps6594_common_cells), NULL, 0,
+ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, cells, n_cells, NULL, 0,
regmap_irq_get_domain(tps->irq_data));
if (ret)
return dev_err_probe(dev, ret, "Failed to add common child devices\n");
- /* No RTC for LP8764 */
- if (tps->chip_id != LP8764) {
+ /* No RTC for LP8764 and TPS65224 */
+ if (tps->chip_id != LP8764 && tps->chip_id != TPS65224) {
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, tps6594_rtc_cells,
ARRAY_SIZE(tps6594_rtc_cells), NULL, 0,
regmap_irq_get_domain(tps->irq_data));
@@ -461,5 +665,6 @@ int tps6594_device_init(struct tps6594 *tps, bool enable_crc)
EXPORT_SYMBOL_GPL(tps6594_device_init);
MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_AUTHOR("Bhargav Raviprakash <bhargav.r@ltts.com");
MODULE_DESCRIPTION("TPS6594 Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/tps6594-i2c.c b/drivers/mfd/tps6594-i2c.c
index 899c88c0fe..4ab91c34d9 100644
--- a/drivers/mfd/tps6594-i2c.c
+++ b/drivers/mfd/tps6594-i2c.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * I2C access driver for TI TPS6594/TPS6593/LP8764 PMICs
+ * I2C access driver for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs
*
* Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
*/
@@ -183,11 +183,11 @@ static int tps6594_i2c_write(void *context, const void *data, size_t count)
return ret;
}
-static const struct regmap_config tps6594_i2c_regmap_config = {
+static struct regmap_config tps6594_i2c_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.max_register = TPS6594_REG_DWD_FAIL_CNT_REG,
- .volatile_reg = tps6594_is_volatile_reg,
+ .volatile_table = &tps6594_volatile_table,
.read = tps6594_i2c_read,
.write = tps6594_i2c_write,
};
@@ -196,6 +196,7 @@ static const struct of_device_id tps6594_i2c_of_match_table[] = {
{ .compatible = "ti,tps6594-q1", .data = (void *)TPS6594, },
{ .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, },
{ .compatible = "ti,lp8764-q1", .data = (void *)LP8764, },
+ { .compatible = "ti,tps65224-q1", .data = (void *)TPS65224, },
{}
};
MODULE_DEVICE_TABLE(of, tps6594_i2c_of_match_table);
@@ -216,15 +217,18 @@ static int tps6594_i2c_probe(struct i2c_client *client)
tps->reg = client->addr;
tps->irq = client->irq;
- tps->regmap = devm_regmap_init(dev, NULL, client, &tps6594_i2c_regmap_config);
- if (IS_ERR(tps->regmap))
- return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
-
match = of_match_device(tps6594_i2c_of_match_table, dev);
if (!match)
return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n");
tps->chip_id = (unsigned long)match->data;
+ if (tps->chip_id == TPS65224)
+ tps6594_i2c_regmap_config.volatile_table = &tps65224_volatile_table;
+
+ tps->regmap = devm_regmap_init(dev, NULL, client, &tps6594_i2c_regmap_config);
+ if (IS_ERR(tps->regmap))
+ return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
+
crc8_populate_msb(tps6594_i2c_crc_table, TPS6594_CRC8_POLYNOMIAL);
return tps6594_device_init(tps, enable_crc);
@@ -240,5 +244,5 @@ static struct i2c_driver tps6594_i2c_driver = {
module_i2c_driver(tps6594_i2c_driver);
MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
-MODULE_DESCRIPTION("TPS6594 I2C Interface Driver");
+MODULE_DESCRIPTION("I2C Interface Driver for TPS65224, TPS6594/3, and LP8764");
MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/tps6594-spi.c b/drivers/mfd/tps6594-spi.c
index 24b72847e3..6ebccb79f0 100644
--- a/drivers/mfd/tps6594-spi.c
+++ b/drivers/mfd/tps6594-spi.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * SPI access driver for TI TPS6594/TPS6593/LP8764 PMICs
+ * SPI access driver for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs
*
* Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
*/
@@ -66,11 +66,11 @@ static int tps6594_spi_reg_write(void *context, unsigned int reg, unsigned int v
return spi_write(spi, buf, count);
}
-static const struct regmap_config tps6594_spi_regmap_config = {
+static struct regmap_config tps6594_spi_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.max_register = TPS6594_REG_DWD_FAIL_CNT_REG,
- .volatile_reg = tps6594_is_volatile_reg,
+ .volatile_table = &tps6594_volatile_table,
.reg_read = tps6594_spi_reg_read,
.reg_write = tps6594_spi_reg_write,
.use_single_read = true,
@@ -81,6 +81,7 @@ static const struct of_device_id tps6594_spi_of_match_table[] = {
{ .compatible = "ti,tps6594-q1", .data = (void *)TPS6594, },
{ .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, },
{ .compatible = "ti,lp8764-q1", .data = (void *)LP8764, },
+ { .compatible = "ti,tps65224-q1", .data = (void *)TPS65224, },
{}
};
MODULE_DEVICE_TABLE(of, tps6594_spi_of_match_table);
@@ -101,15 +102,18 @@ static int tps6594_spi_probe(struct spi_device *spi)
tps->reg = spi_get_chipselect(spi, 0);
tps->irq = spi->irq;
- tps->regmap = devm_regmap_init(dev, NULL, spi, &tps6594_spi_regmap_config);
- if (IS_ERR(tps->regmap))
- return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
-
match = of_match_device(tps6594_spi_of_match_table, dev);
if (!match)
return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n");
tps->chip_id = (unsigned long)match->data;
+ if (tps->chip_id == TPS65224)
+ tps6594_spi_regmap_config.volatile_table = &tps65224_volatile_table;
+
+ tps->regmap = devm_regmap_init(dev, NULL, spi, &tps6594_spi_regmap_config);
+ if (IS_ERR(tps->regmap))
+ return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
+
crc8_populate_msb(tps6594_spi_crc_table, TPS6594_CRC8_POLYNOMIAL);
return tps6594_device_init(tps, enable_crc);
@@ -125,5 +129,5 @@ static struct spi_driver tps6594_spi_driver = {
module_spi_driver(tps6594_spi_driver);
MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
-MODULE_DESCRIPTION("TPS6594 SPI Interface Driver");
+MODULE_DESCRIPTION("SPI Interface Driver for TPS65224, TPS6594/3, and LP8764");
MODULE_LICENSE("GPL");