diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-05-22 10:41:14 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-05-22 10:41:14 -0700 |
commit | a85629f435a4e724c414a6ae3e2f327272ab11af (patch) | |
tree | cc6279ca271f27e55b11a12860cd14cbfc9f15a5 /drivers | |
parent | 0bfbc914d9433d8ac2763a9ce99ce7721ee5c8e0 (diff) | |
parent | 1482489b5196f4203576ae1dc2ba4ce3ada381c7 (diff) | |
download | lwn-a85629f435a4e724c414a6ae3e2f327272ab11af.tar.gz lwn-a85629f435a4e724c414a6ae3e2f327272ab11af.zip |
Merge tag 'mfd-next-6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones:
"New Device Support:
- Add support for X-Powers AXP717 PMIC to AXP22X
- Add support for Rockchip RK816 PMIC to RK8XX
- Add support for TI TPS65224 PMIC to TPS6594
New Functionality:
- Add Power Off functionality to Rohm BD71828
- Allow I2C SMBus access in Renesas RSMU
Fix-ups:
- Device Tree binding adaptions/conversions/creation
- Shift Intel support over to MSI interrupts
- Generify adding platform data away from being ACPI specific
- Use device core supplied attribute to register sysfs entries
- Replace hand-rolled functionality with generic APIs
- Utilise centrally provided helpers and macros
- Clean-up error handling
- Remove superfluous/duplicated/unused sections
- Trivial; spelling, whitespace, coding-style adaptions
- More Maple Tree conversions"
* tag 'mfd-next-6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (44 commits)
dt-bindings: mfd: Use full path to other schemas
mfd: rsmu: support I2C SMBus access
dt-bindings: mfd: Convert lp873x.txt to json-schema
dt-bindings: mfd: aspeed: Drop 'oneOf' for pinctrl node
dt-bindings: mfd: allwinner,sun6i-a31-prcm: Use hyphens in node names
mfd: ssbi: Remove unused field 'slave' from 'struct ssbi'
mfd: kempld: Remove custom DMI matching code
mfd: cs42l43: Update patching revision check
dt-bindings: mfd: qcom: pm8xxx: Add pm8901 compatible
mfd: timberdale: Remove redundant assignment to variable err
dt-bindings: mfd: qcom,spmi-pmic: Add pbs to SPMI device types
dt-bindings: mfd: syscon: Add ti,am62p-cpsw-mac-efuse compatible
dt-bindings: mfd: qcom,tcsr: Add compatible for SDX75
mfd: axp20x: Convert to use Maple Tree register cache
mfd: bd71828: Remove commented code lines
mfd: intel-m10-bmc: Change staging size to a variable
dt-bindings: mfd: Add ROHM BD71879
mfd: Tidy Kconfig dependency's parentheses
mfd: ocelot-spi: Use spi_sync_transfer()
dt-bindings: mfd: syscon: Add missing simple syscon compatibles
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/fpga/intel-m10-bmc-sec-update.c | 3 | ||||
-rw-r--r-- | drivers/mfd/Kconfig | 16 | ||||
-rw-r--r-- | drivers/mfd/axp20x.c | 2 | ||||
-rw-r--r-- | drivers/mfd/cs42l43.c | 36 | ||||
-rw-r--r-- | drivers/mfd/intel-lpss-pci.c | 2 | ||||
-rw-r--r-- | drivers/mfd/intel-m10-bmc-pmci.c | 1 | ||||
-rw-r--r-- | drivers/mfd/intel-m10-bmc-spi.c | 1 | ||||
-rw-r--r-- | drivers/mfd/kempld-core.c | 227 | ||||
-rw-r--r-- | drivers/mfd/ocelot-spi.c | 5 | ||||
-rw-r--r-- | drivers/mfd/rk8xx-core.c | 104 | ||||
-rw-r--r-- | drivers/mfd/rk8xx-i2c.c | 45 | ||||
-rw-r--r-- | drivers/mfd/rohm-bd71828.c | 36 | ||||
-rw-r--r-- | drivers/mfd/rsmu_i2c.c | 107 | ||||
-rw-r--r-- | drivers/mfd/rsmu_spi.c | 8 | ||||
-rw-r--r-- | drivers/mfd/ssbi.c | 1 | ||||
-rw-r--r-- | drivers/mfd/timberdale.c | 1 | ||||
-rw-r--r-- | drivers/mfd/tps6594-core.c | 253 | ||||
-rw-r--r-- | drivers/mfd/tps6594-i2c.c | 20 | ||||
-rw-r--r-- | drivers/mfd/tps6594-spi.c | 20 | ||||
-rw-r--r-- | drivers/misc/tps6594-pfsm.c | 48 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-rk805.c | 69 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-tps6594.c | 277 | ||||
-rw-r--r-- | drivers/regulator/Kconfig | 4 | ||||
-rw-r--r-- | drivers/regulator/rk808-regulator.c | 218 | ||||
-rw-r--r-- | drivers/regulator/tps6594-regulator.c | 334 |
25 files changed, 1437 insertions, 401 deletions
diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c b/drivers/fpga/intel-m10-bmc-sec-update.c index 89851b133709..7ac9f9f5af12 100644 --- a/drivers/fpga/intel-m10-bmc-sec-update.c +++ b/drivers/fpga/intel-m10-bmc-sec-update.c @@ -529,11 +529,12 @@ static enum fw_upload_err m10bmc_sec_prepare(struct fw_upload *fwl, const u8 *data, u32 size) { struct m10bmc_sec *sec = fwl->dd_handle; + const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; u32 ret; sec->cancel_request = false; - if (!size || size > M10BMC_STAGING_SIZE) + if (!size || size > csr_map->staging_size) return FW_UPLOAD_ERR_INVALID_SIZE; if (sec->m10bmc->flash_bulk_ops) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 4b023ee229cf..266b4f54af60 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/axp20x.c b/drivers/mfd/axp20x.c index 48ce6ea693ce..f2c0f144c0fc 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -422,7 +422,7 @@ static const struct regmap_config axp717_regmap_config = { .wr_table = &axp717_writeable_table, .volatile_table = &axp717_volatile_table, .max_register = AXP717_CPUSLDO_CONTROL, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static const struct regmap_config axp806_regmap_config = { diff --git a/drivers/mfd/cs42l43.c b/drivers/mfd/cs42l43.c index a0fb2dc6c3b2..ae8fd37afb75 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 9f4782bdbf4b..c36a101df7be 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_INTX); + 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 0392ef8b57d8..698c5933938b 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 cbeb7de9e041..d64d28199df6 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 5557f023a173..8a332852bf97 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 94f82677675b..b015c8683f1b 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/rk8xx-core.c b/drivers/mfd/rk8xx-core.c index e2261b68b844..5eda3c0dbbdf 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 75b5cf09d5a0..69a6b297d723 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 2f3826c7eef4..5b4290f116fc 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_i2c.c b/drivers/mfd/rsmu_i2c.c index 5711e512b6a2..cba64f107a2f 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 ca0a1202c3ce..39d9be1e141f 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 b0b0be483dbf..f849f2d34ec7 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 07e5aa10a146..a41e9a3e2064 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 783ee59901e8..c59f3d7e32b0 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 899c88c0fe77..4ab91c34d9fb 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 24b72847e3f5..6ebccb79f0cc 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"); diff --git a/drivers/misc/tps6594-pfsm.c b/drivers/misc/tps6594-pfsm.c index 88dcac814892..9bcca1856bfe 100644 --- a/drivers/misc/tps6594-pfsm.c +++ b/drivers/misc/tps6594-pfsm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * PFSM (Pre-configurable Finite State Machine) driver for TI TPS6594/TPS6593/LP8764 PMICs + * PFSM (Pre-configurable Finite State Machine) driver for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs * * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ */ @@ -39,10 +39,12 @@ * * @miscdev: misc device infos * @regmap: regmap for accessing the device registers + * @chip_id: chip identifier of the device */ struct tps6594_pfsm { struct miscdevice miscdev; struct regmap *regmap; + unsigned long chip_id; }; static ssize_t tps6594_pfsm_read(struct file *f, char __user *buf, @@ -133,21 +135,29 @@ static long tps6594_pfsm_ioctl(struct file *f, unsigned int cmd, unsigned long a struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f); struct pmic_state_opt state_opt; void __user *argp = (void __user *)arg; + unsigned int regmap_reg, mask; int ret = -ENOIOCTLCMD; switch (cmd) { case PMIC_GOTO_STANDBY: - /* Disable LP mode */ - ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2, - TPS6594_BIT_LP_STANDBY_SEL); - if (ret) - return ret; + /* Disable LP mode on TPS6594 Family PMIC */ + if (pfsm->chip_id != TPS65224) { + ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2, + TPS6594_BIT_LP_STANDBY_SEL); + + if (ret) + return ret; + } /* Force trigger */ ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS, TPS6594_BIT_TRIGGER_I2C(0), TPS6594_BIT_TRIGGER_I2C(0)); break; case PMIC_GOTO_LP_STANDBY: + /* TPS65224 does not support LP STANDBY */ + if (pfsm->chip_id == TPS65224) + return ret; + /* Enable LP mode */ ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2, TPS6594_BIT_LP_STANDBY_SEL); @@ -169,6 +179,10 @@ static long tps6594_pfsm_ioctl(struct file *f, unsigned int cmd, unsigned long a TPS6594_BIT_NSLEEP1B | TPS6594_BIT_NSLEEP2B); break; case PMIC_SET_MCU_ONLY_STATE: + /* TPS65224 does not support MCU_ONLY_STATE */ + if (pfsm->chip_id == TPS65224) + return ret; + if (copy_from_user(&state_opt, argp, sizeof(state_opt))) return -EFAULT; @@ -192,14 +206,20 @@ static long tps6594_pfsm_ioctl(struct file *f, unsigned int cmd, unsigned long a return -EFAULT; /* Configure wake-up destination */ + if (pfsm->chip_id == TPS65224) { + regmap_reg = TPS65224_REG_STARTUP_CTRL; + mask = TPS65224_MASK_STARTUP_DEST; + } else { + regmap_reg = TPS6594_REG_RTC_CTRL_2; + mask = TPS6594_MASK_STARTUP_DEST; + } + if (state_opt.mcu_only_startup_dest) - ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2, - TPS6594_MASK_STARTUP_DEST, - TPS6594_STARTUP_DEST_MCU_ONLY); + ret = regmap_write_bits(pfsm->regmap, regmap_reg, + mask, TPS6594_STARTUP_DEST_MCU_ONLY); else - ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2, - TPS6594_MASK_STARTUP_DEST, - TPS6594_STARTUP_DEST_ACTIVE); + ret = regmap_write_bits(pfsm->regmap, regmap_reg, + mask, TPS6594_STARTUP_DEST_ACTIVE); if (ret) return ret; @@ -211,7 +231,8 @@ static long tps6594_pfsm_ioctl(struct file *f, unsigned int cmd, unsigned long a /* Modify NSLEEP1-2 bits */ ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS, - TPS6594_BIT_NSLEEP2B); + pfsm->chip_id == TPS65224 ? + TPS6594_BIT_NSLEEP1B : TPS6594_BIT_NSLEEP2B); break; } @@ -262,6 +283,7 @@ static int tps6594_pfsm_probe(struct platform_device *pdev) tps->chip_id, tps->reg); pfsm->miscdev.fops = &tps6594_pfsm_fops; pfsm->miscdev.parent = dev->parent; + pfsm->chip_id = tps->chip_id; for (i = 0 ; i < pdev->num_resources ; i++) { irq = platform_get_irq_byname(pdev, pdev->resource[i].name); diff --git a/drivers/pinctrl/pinctrl-rk805.c b/drivers/pinctrl/pinctrl-rk805.c index 56d916f2cee6..c42f1bf93404 100644 --- a/drivers/pinctrl/pinctrl-rk805.c +++ b/drivers/pinctrl/pinctrl-rk805.c @@ -93,6 +93,11 @@ enum rk806_pinmux_option { RK806_PINMUX_FUN5, }; +enum rk816_pinmux_option { + RK816_PINMUX_THERMISTOR, + RK816_PINMUX_GPIO, +}; + enum { RK805_GPIO0, RK805_GPIO1, @@ -104,6 +109,10 @@ enum { RK806_GPIO_DVS3 }; +enum { + RK816_GPIO0, +}; + static const char *const rk805_gpio_groups[] = { "gpio0", "gpio1", @@ -115,6 +124,10 @@ static const char *const rk806_gpio_groups[] = { "gpio_pwrctrl3", }; +static const char *const rk816_gpio_groups[] = { + "gpio0", +}; + /* RK805: 2 output only GPIOs */ static const struct pinctrl_pin_desc rk805_pins_desc[] = { PINCTRL_PIN(RK805_GPIO0, "gpio0"), @@ -128,6 +141,11 @@ static const struct pinctrl_pin_desc rk806_pins_desc[] = { PINCTRL_PIN(RK806_GPIO_DVS3, "gpio_pwrctrl3"), }; +/* RK816 */ +static const struct pinctrl_pin_desc rk816_pins_desc[] = { + PINCTRL_PIN(RK816_GPIO0, "gpio0"), +}; + static const struct rk805_pin_function rk805_pin_functions[] = { { .name = "gpio", @@ -176,6 +194,21 @@ static const struct rk805_pin_function rk806_pin_functions[] = { }, }; +static const struct rk805_pin_function rk816_pin_functions[] = { + { + .name = "gpio", + .groups = rk816_gpio_groups, + .ngroups = ARRAY_SIZE(rk816_gpio_groups), + .mux_option = RK816_PINMUX_GPIO, + }, + { + .name = "thermistor", + .groups = rk816_gpio_groups, + .ngroups = ARRAY_SIZE(rk816_gpio_groups), + .mux_option = RK816_PINMUX_THERMISTOR, + }, +}; + static const struct rk805_pin_group rk805_pin_groups[] = { { .name = "gpio0", @@ -207,6 +240,14 @@ static const struct rk805_pin_group rk806_pin_groups[] = { } }; +static const struct rk805_pin_group rk816_pin_groups[] = { + { + .name = "gpio0", + .pins = { RK816_GPIO0 }, + .npins = 1, + }, +}; + #define RK805_GPIO0_VAL_MSK BIT(0) #define RK805_GPIO1_VAL_MSK BIT(1) @@ -255,6 +296,20 @@ static struct rk805_pin_config rk806_gpio_cfgs[] = { } }; +#define RK816_FUN_MASK BIT(2) +#define RK816_VAL_MASK BIT(3) +#define RK816_DIR_MASK BIT(4) + +static struct rk805_pin_config rk816_gpio_cfgs[] = { + { + .fun_reg = RK818_IO_POL_REG, + .fun_msk = RK816_FUN_MASK, + .reg = RK818_IO_POL_REG, + .val_msk = RK816_VAL_MASK, + .dir_msk = RK816_DIR_MASK, + }, +}; + /* generic gpio chip */ static int rk805_gpio_get(struct gpio_chip *chip, unsigned int offset) { @@ -439,6 +494,8 @@ static int rk805_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev, return _rk805_pinctrl_set_mux(pctldev, offset, RK805_PINMUX_GPIO); case RK806_ID: return _rk805_pinctrl_set_mux(pctldev, offset, RK806_PINMUX_FUN5); + case RK816_ID: + return _rk805_pinctrl_set_mux(pctldev, offset, RK816_PINMUX_GPIO); } return -ENOTSUPP; @@ -588,6 +645,18 @@ static int rk805_pinctrl_probe(struct platform_device *pdev) pci->pin_cfg = rk806_gpio_cfgs; pci->gpio_chip.ngpio = ARRAY_SIZE(rk806_gpio_cfgs); break; + case RK816_ID: + pci->pins = rk816_pins_desc; + pci->num_pins = ARRAY_SIZE(rk816_pins_desc); + pci->functions = rk816_pin_functions; + pci->num_functions = ARRAY_SIZE(rk816_pin_functions); + pci->groups = rk816_pin_groups; + pci->num_pin_groups = ARRAY_SIZE(rk816_pin_groups); + pci->pinctrl_desc.pins = rk816_pins_desc; + pci->pinctrl_desc.npins = ARRAY_SIZE(rk816_pins_desc); + pci->pin_cfg = rk816_gpio_cfgs; + pci->gpio_chip.ngpio = ARRAY_SIZE(rk816_gpio_cfgs); + break; default: dev_err(&pdev->dev, "unsupported RK805 ID %lu\n", pci->rk808->variant); diff --git a/drivers/pinctrl/pinctrl-tps6594.c b/drivers/pinctrl/pinctrl-tps6594.c index 66985e54b74a..085047320853 100644 --- a/drivers/pinctrl/pinctrl-tps6594.c +++ b/drivers/pinctrl/pinctrl-tps6594.c @@ -14,8 +14,6 @@ #include <linux/mfd/tps6594.h> -#define TPS6594_PINCTRL_PINS_NB 11 - #define TPS6594_PINCTRL_GPIO_FUNCTION 0 #define TPS6594_PINCTRL_SCL_I2C2_CS_SPI_FUNCTION 1 #define TPS6594_PINCTRL_TRIG_WDOG_FUNCTION 1 @@ -40,17 +38,40 @@ #define TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION_GPIO8 3 #define TPS6594_PINCTRL_CLK32KOUT_FUNCTION_GPIO9 3 +/* TPS65224 pin muxval */ +#define TPS65224_PINCTRL_SDA_I2C2_SDO_SPI_FUNCTION 1 +#define TPS65224_PINCTRL_SCL_I2C2_CS_SPI_FUNCTION 1 +#define TPS65224_PINCTRL_VMON1_FUNCTION 1 +#define TPS65224_PINCTRL_VMON2_FUNCTION 1 +#define TPS65224_PINCTRL_WKUP_FUNCTION 1 +#define TPS65224_PINCTRL_NSLEEP2_FUNCTION 2 +#define TPS65224_PINCTRL_NSLEEP1_FUNCTION 2 +#define TPS65224_PINCTRL_SYNCCLKIN_FUNCTION 2 +#define TPS65224_PINCTRL_NERR_MCU_FUNCTION 2 +#define TPS65224_PINCTRL_NINT_FUNCTION 3 +#define TPS65224_PINCTRL_TRIG_WDOG_FUNCTION 3 +#define TPS65224_PINCTRL_PB_FUNCTION 3 +#define TPS65224_PINCTRL_ADC_IN_FUNCTION 3 + +/* TPS65224 Special muxval for recalcitrant pins */ +#define TPS65224_PINCTRL_NSLEEP2_FUNCTION_GPIO5 1 +#define TPS65224_PINCTRL_WKUP_FUNCTION_GPIO5 4 +#define TPS65224_PINCTRL_SYNCCLKIN_FUNCTION_GPIO5 3 + #define TPS6594_OFFSET_GPIO_SEL 5 -#define FUNCTION(fname, v) \ +#define TPS65224_NGPIO_PER_REG 6 +#define TPS6594_NGPIO_PER_REG 8 + +#define FUNCTION(dev_name, fname, v) \ { \ .pinfunction = PINCTRL_PINFUNCTION(#fname, \ - tps6594_##fname##_func_group_names, \ - ARRAY_SIZE(tps6594_##fname##_func_group_names)),\ + dev_name##_##fname##_func_group_names, \ + ARRAY_SIZE(dev_name##_##fname##_func_group_names)),\ .muxval = v, \ } -static const struct pinctrl_pin_desc tps6594_pins[TPS6594_PINCTRL_PINS_NB] = { +static const struct pinctrl_pin_desc tps6594_pins[] = { PINCTRL_PIN(0, "GPIO0"), PINCTRL_PIN(1, "GPIO1"), PINCTRL_PIN(2, "GPIO2"), PINCTRL_PIN(3, "GPIO3"), PINCTRL_PIN(4, "GPIO4"), PINCTRL_PIN(5, "GPIO5"), @@ -143,30 +164,127 @@ static const char *const tps6594_syncclkin_func_group_names[] = { "GPIO9", }; +static const struct pinctrl_pin_desc tps65224_pins[] = { + PINCTRL_PIN(0, "GPIO0"), PINCTRL_PIN(1, "GPIO1"), + PINCTRL_PIN(2, "GPIO2"), PINCTRL_PIN(3, "GPIO3"), + PINCTRL_PIN(4, "GPIO4"), PINCTRL_PIN(5, "GPIO5"), +}; + +static const char *const tps65224_gpio_func_group_names[] = { + "GPIO0", "GPIO1", "GPIO2", "GPIO3", "GPIO4", "GPIO5", +}; + +static const char *const tps65224_sda_i2c2_sdo_spi_func_group_names[] = { + "GPIO0", +}; + +static const char *const tps65224_nsleep2_func_group_names[] = { + "GPIO0", "GPIO5", +}; + +static const char *const tps65224_nint_func_group_names[] = { + "GPIO0", +}; + +static const char *const tps65224_scl_i2c2_cs_spi_func_group_names[] = { + "GPIO1", +}; + +static const char *const tps65224_nsleep1_func_group_names[] = { + "GPIO1", "GPIO2", "GPIO3", +}; + +static const char *const tps65224_trig_wdog_func_group_names[] = { + "GPIO1", +}; + +static const char *const tps65224_vmon1_func_group_names[] = { + "GPIO2", +}; + +static const char *const tps65224_pb_func_group_names[] = { + "GPIO2", +}; + +static const char *const tps65224_vmon2_func_group_names[] = { + "GPIO3", +}; + +static const char *const tps65224_adc_in_func_group_names[] = { + "GPIO3", "GPIO4", +}; + +static const char *const tps65224_wkup_func_group_names[] = { + "GPIO4", "GPIO5", +}; + +static const char *const tps65224_syncclkin_func_group_names[] = { + "GPIO4", "GPIO5", +}; + +static const char *const tps65224_nerr_mcu_func_group_names[] = { + "GPIO5", +}; + struct tps6594_pinctrl_function { struct pinfunction pinfunction; u8 muxval; }; +struct muxval_remap { + unsigned int group; + u8 muxval; + u8 remap; +}; + +struct muxval_remap tps65224_muxval_remap[] = { + {5, TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION, TPS65224_PINCTRL_WKUP_FUNCTION_GPIO5}, + {5, TPS65224_PINCTRL_SYNCCLKIN_FUNCTION, TPS65224_PINCTRL_SYNCCLKIN_FUNCTION_GPIO5}, + {5, TPS65224_PINCTRL_NSLEEP2_FUNCTION, TPS65224_PINCTRL_NSLEEP2_FUNCTION_GPIO5}, +}; + +struct muxval_remap tps6594_muxval_remap[] = { + {8, TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION, TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION_GPIO8}, + {8, TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION, TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION_GPIO8}, + {9, TPS6594_PINCTRL_CLK32KOUT_FUNCTION, TPS6594_PINCTRL_CLK32KOUT_FUNCTION_GPIO9}, +}; + static const struct tps6594_pinctrl_function pinctrl_functions[] = { - FUNCTION(gpio, TPS6594_PINCTRL_GPIO_FUNCTION), - FUNCTION(nsleep1, TPS6594_PINCTRL_NSLEEP1_FUNCTION), - FUNCTION(nsleep2, TPS6594_PINCTRL_NSLEEP2_FUNCTION), - FUNCTION(wkup1, TPS6594_PINCTRL_WKUP1_FUNCTION), - FUNCTION(wkup2, TPS6594_PINCTRL_WKUP2_FUNCTION), - FUNCTION(scl_i2c2_cs_spi, TPS6594_PINCTRL_SCL_I2C2_CS_SPI_FUNCTION), - FUNCTION(nrstout_soc, TPS6594_PINCTRL_NRSTOUT_SOC_FUNCTION), - FUNCTION(trig_wdog, TPS6594_PINCTRL_TRIG_WDOG_FUNCTION), - FUNCTION(sda_i2c2_sdo_spi, TPS6594_PINCTRL_SDA_I2C2_SDO_SPI_FUNCTION), - FUNCTION(clk32kout, TPS6594_PINCTRL_CLK32KOUT_FUNCTION), - FUNCTION(nerr_soc, TPS6594_PINCTRL_NERR_SOC_FUNCTION), - FUNCTION(sclk_spmi, TPS6594_PINCTRL_SCLK_SPMI_FUNCTION), - FUNCTION(sdata_spmi, TPS6594_PINCTRL_SDATA_SPMI_FUNCTION), - FUNCTION(nerr_mcu, TPS6594_PINCTRL_NERR_MCU_FUNCTION), - FUNCTION(syncclkout, TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION), - FUNCTION(disable_wdog, TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION), - FUNCTION(pdog, TPS6594_PINCTRL_PDOG_FUNCTION), - FUNCTION(syncclkin, TPS6594_PINCTRL_SYNCCLKIN_FUNCTION), + FUNCTION(tps6594, gpio, TPS6594_PINCTRL_GPIO_FUNCTION), + FUNCTION(tps6594, nsleep1, TPS6594_PINCTRL_NSLEEP1_FUNCTION), + FUNCTION(tps6594, nsleep2, TPS6594_PINCTRL_NSLEEP2_FUNCTION), + FUNCTION(tps6594, wkup1, TPS6594_PINCTRL_WKUP1_FUNCTION), + FUNCTION(tps6594, wkup2, TPS6594_PINCTRL_WKUP2_FUNCTION), + FUNCTION(tps6594, scl_i2c2_cs_spi, TPS6594_PINCTRL_SCL_I2C2_CS_SPI_FUNCTION), + FUNCTION(tps6594, nrstout_soc, TPS6594_PINCTRL_NRSTOUT_SOC_FUNCTION), + FUNCTION(tps6594, trig_wdog, TPS6594_PINCTRL_TRIG_WDOG_FUNCTION), + FUNCTION(tps6594, sda_i2c2_sdo_spi, TPS6594_PINCTRL_SDA_I2C2_SDO_SPI_FUNCTION), + FUNCTION(tps6594, clk32kout, TPS6594_PINCTRL_CLK32KOUT_FUNCTION), + FUNCTION(tps6594, nerr_soc, TPS6594_PINCTRL_NERR_SOC_FUNCTION), + FUNCTION(tps6594, sclk_spmi, TPS6594_PINCTRL_SCLK_SPMI_FUNCTION), + FUNCTION(tps6594, sdata_spmi, TPS6594_PINCTRL_SDATA_SPMI_FUNCTION), + FUNCTION(tps6594, nerr_mcu, TPS6594_PINCTRL_NERR_MCU_FUNCTION), + FUNCTION(tps6594, syncclkout, TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION), + FUNCTION(tps6594, disable_wdog, TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION), + FUNCTION(tps6594, pdog, TPS6594_PINCTRL_PDOG_FUNCTION), + FUNCTION(tps6594, syncclkin, TPS6594_PINCTRL_SYNCCLKIN_FUNCTION), +}; + +static const struct tps6594_pinctrl_function tps65224_pinctrl_functions[] = { + FUNCTION(tps65224, gpio, TPS6594_PINCTRL_GPIO_FUNCTION), + FUNCTION(tps65224, sda_i2c2_sdo_spi, TPS65224_PINCTRL_SDA_I2C2_SDO_SPI_FUNCTION), + FUNCTION(tps65224, nsleep2, TPS65224_PINCTRL_NSLEEP2_FUNCTION), + FUNCTION(tps65224, nint, TPS65224_PINCTRL_NINT_FUNCTION), + FUNCTION(tps65224, scl_i2c2_cs_spi, TPS65224_PINCTRL_SCL_I2C2_CS_SPI_FUNCTION), + FUNCTION(tps65224, nsleep1, TPS65224_PINCTRL_NSLEEP1_FUNCTION), + FUNCTION(tps65224, trig_wdog, TPS65224_PINCTRL_TRIG_WDOG_FUNCTION), + FUNCTION(tps65224, vmon1, TPS65224_PINCTRL_VMON1_FUNCTION), + FUNCTION(tps65224, pb, TPS65224_PINCTRL_PB_FUNCTION), + FUNCTION(tps65224, vmon2, TPS65224_PINCTRL_VMON2_FUNCTION), + FUNCTION(tps65224, adc_in, TPS65224_PINCTRL_ADC_IN_FUNCTION), + FUNCTION(tps65224, wkup, TPS65224_PINCTRL_WKUP_FUNCTION), + FUNCTION(tps65224, syncclkin, TPS65224_PINCTRL_SYNCCLKIN_FUNCTION), + FUNCTION(tps65224, nerr_mcu, TPS65224_PINCTRL_NERR_MCU_FUNCTION), }; struct tps6594_pinctrl { @@ -175,6 +293,31 @@ struct tps6594_pinctrl { struct pinctrl_dev *pctl_dev; const struct tps6594_pinctrl_function *funcs; const struct pinctrl_pin_desc *pins; + int func_cnt; + int num_pins; + u8 mux_sel_mask; + unsigned int remap_cnt; + struct muxval_remap *remap; +}; + +static struct tps6594_pinctrl tps65224_template_pinctrl = { + .funcs = tps65224_pinctrl_functions, + .func_cnt = ARRAY_SIZE(tps65224_pinctrl_functions), + .pins = tps65224_pins, + .num_pins = ARRAY_SIZE(tps65224_pins), + .mux_sel_mask = TPS65224_MASK_GPIO_SEL, + .remap = tps65224_muxval_remap, + .remap_cnt = ARRAY_SIZE(tps65224_muxval_remap), +}; + +static struct tps6594_pinctrl tps6594_template_pinctrl = { + .funcs = pinctrl_functions, + .func_cnt = ARRAY_SIZE(pinctrl_functions), + .pins = tps6594_pins, + .num_pins = ARRAY_SIZE(tps6594_pins), + .mux_sel_mask = TPS6594_MASK_GPIO_SEL, + .remap = tps6594_muxval_remap, + .remap_cnt = ARRAY_SIZE(tps6594_muxval_remap), }; static int tps6594_gpio_regmap_xlate(struct gpio_regmap *gpio, @@ -201,7 +344,9 @@ static int tps6594_gpio_regmap_xlate(struct gpio_regmap *gpio, static int tps6594_pmx_func_cnt(struct pinctrl_dev *pctldev) { - return ARRAY_SIZE(pinctrl_functions); + struct tps6594_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); + + return pinctrl->func_cnt; } static const char *tps6594_pmx_func_name(struct pinctrl_dev *pctldev, @@ -229,10 +374,16 @@ static int tps6594_pmx_set(struct tps6594_pinctrl *pinctrl, unsigned int pin, u8 muxval) { u8 mux_sel_val = muxval << TPS6594_OFFSET_GPIO_SEL; + u8 mux_sel_mask = pinctrl->mux_sel_mask; + + if (pinctrl->tps->chip_id == TPS65224 && pin == 5) { + /* GPIO6 has a different mask in TPS65224*/ + mux_sel_mask = TPS65224_MASK_GPIO_SEL_GPIO6; + } return regmap_update_bits(pinctrl->tps->regmap, TPS6594_REG_GPIOX_CONF(pin), - TPS6594_MASK_GPIO_SEL, mux_sel_val); + mux_sel_mask, mux_sel_val); } static int tps6594_pmx_set_mux(struct pinctrl_dev *pctldev, @@ -240,16 +391,14 @@ static int tps6594_pmx_set_mux(struct pinctrl_dev *pctldev, { struct tps6594_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); u8 muxval = pinctrl->funcs[function].muxval; - - /* Some pins don't have the same muxval for the same function... */ - if (group == 8) { - if (muxval == TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION) - muxval = TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION_GPIO8; - else if (muxval == TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION) - muxval = TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION_GPIO8; - } else if (group == 9) { - if (muxval == TPS6594_PINCTRL_CLK32KOUT_FUNCTION) - muxval = TPS6594_PINCTRL_CLK32KOUT_FUNCTION_GPIO9; + unsigned int remap_cnt = pinctrl->remap_cnt; + struct muxval_remap *remap = pinctrl->remap; + + for (unsigned int i = 0; i < remap_cnt; i++) { + if (group == remap[i].group && muxval == remap[i].muxval) { + muxval = remap[i].remap; + break; + } } return tps6594_pmx_set(pinctrl, group, muxval); @@ -276,7 +425,9 @@ static const struct pinmux_ops tps6594_pmx_ops = { static int tps6594_groups_cnt(struct pinctrl_dev *pctldev) { - return ARRAY_SIZE(tps6594_pins); + struct tps6594_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); + + return pinctrl->num_pins; } static int tps6594_group_pins(struct pinctrl_dev *pctldev, @@ -318,33 +469,54 @@ static int tps6594_pinctrl_probe(struct platform_device *pdev) pctrl_desc = devm_kzalloc(dev, sizeof(*pctrl_desc), GFP_KERNEL); if (!pctrl_desc) return -ENOMEM; - pctrl_desc->name = dev_name(dev); - pctrl_desc->owner = THIS_MODULE; - pctrl_desc->pins = tps6594_pins; - pctrl_desc->npins = ARRAY_SIZE(tps6594_pins); - pctrl_desc->pctlops = &tps6594_pctrl_ops; - pctrl_desc->pmxops = &tps6594_pmx_ops; pinctrl = devm_kzalloc(dev, sizeof(*pinctrl), GFP_KERNEL); if (!pinctrl) return -ENOMEM; - pinctrl->tps = dev_get_drvdata(dev->parent); - pinctrl->funcs = pinctrl_functions; - pinctrl->pins = tps6594_pins; - pinctrl->pctl_dev = devm_pinctrl_register(dev, pctrl_desc, pinctrl); - if (IS_ERR(pinctrl->pctl_dev)) - return dev_err_probe(dev, PTR_ERR(pinctrl->pctl_dev), - "Couldn't register pinctrl driver\n"); + + switch (tps->chip_id) { + case TPS65224: + pctrl_desc->pins = tps65224_pins; + pctrl_desc->npins = ARRAY_SIZE(tps65224_pins); + + *pinctrl = tps65224_template_pinctrl; + + config.ngpio = ARRAY_SIZE(tps65224_gpio_func_group_names); + config.ngpio_per_reg = TPS65224_NGPIO_PER_REG; + break; + case TPS6593: + case TPS6594: + pctrl_desc->pins = tps6594_pins; + pctrl_desc->npins = ARRAY_SIZE(tps6594_pins); + + *pinctrl = tps6594_template_pinctrl; + + config.ngpio = ARRAY_SIZE(tps6594_gpio_func_group_names); + config.ngpio_per_reg = TPS6594_NGPIO_PER_REG; + break; + default: + break; + } + + pinctrl->tps = tps; + + pctrl_desc->name = dev_name(dev); + pctrl_desc->owner = THIS_MODULE; + pctrl_desc->pctlops = &tps6594_pctrl_ops; + pctrl_desc->pmxops = &tps6594_pmx_ops; config.parent = tps->dev; config.regmap = tps->regmap; - config.ngpio = TPS6594_PINCTRL_PINS_NB; - config.ngpio_per_reg = 8; config.reg_dat_base = TPS6594_REG_GPIO_IN_1; config.reg_set_base = TPS6594_REG_GPIO_OUT_1; config.reg_dir_out_base = TPS6594_REG_GPIOX_CONF(0); config.reg_mask_xlate = tps6594_gpio_regmap_xlate; + pinctrl->pctl_dev = devm_pinctrl_register(dev, pctrl_desc, pinctrl); + if (IS_ERR(pinctrl->pctl_dev)) + return dev_err_probe(dev, PTR_ERR(pinctrl->pctl_dev), + "Couldn't register pinctrl driver\n"); + pinctrl->gpio_regmap = devm_gpio_regmap_register(dev, &config); if (IS_ERR(pinctrl->gpio_regmap)) return dev_err_probe(dev, PTR_ERR(pinctrl->gpio_regmap), @@ -369,5 +541,6 @@ static struct platform_driver tps6594_pinctrl_driver = { module_platform_driver(tps6594_pinctrl_driver); MODULE_AUTHOR("Esteban Blanc <eblanc@baylibre.com>"); +MODULE_AUTHOR("Nirmala Devi Mal Nadar <m.nirmaladevi@ltts.com>"); MODULE_DESCRIPTION("TPS6594 pinctrl and GPIO driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index acdb02a4ac0c..d333be2bea3b 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -1571,13 +1571,15 @@ config REGULATOR_TPS6594 depends on MFD_TPS6594 && OF default MFD_TPS6594 help - This driver supports TPS6594 voltage regulator chips. + This driver supports TPS6594 series and TPS65224 voltage regulator chips. TPS6594 series of PMICs have 5 BUCKs and 4 LDOs voltage regulators. BUCKs 1,2,3,4 can be used in single phase or multiphase mode. Part number defines which single or multiphase mode is i used. It supports software based voltage control for different voltage domains. + TPS65224 PMIC has 4 BUCKs and 3 LDOs. BUCK12 can be used in dual phase. + All BUCKs and LDOs volatge can be controlled through software. config REGULATOR_TPS6524X tristate "TI TPS6524X Power regulators" diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index d89ae7f16d7a..14b60abd6afc 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -158,6 +158,11 @@ RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \ _vmask, _ereg, _emask, 0, 0, _etime, &rk808_reg_ops) +#define RK816_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask, _disval, _etime) \ + RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask, _emask, _disval, _etime, &rk816_reg_ops) + #define RK817_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \ _vmask, _ereg, _emask, _disval, _etime) \ RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \ @@ -258,7 +263,7 @@ static const unsigned int rk808_buck1_2_ramp_table[] = { 2000, 4000, 6000, 10000 }; -/* RK817 RK809 */ +/* RK817/RK809/RK816 (buck 1/2 only) */ static const unsigned int rk817_buck1_4_ramp_table[] = { 3000, 6300, 12500, 25000 }; @@ -534,15 +539,25 @@ static int rk808_set_suspend_voltage_range(struct regulator_dev *rdev, int uv) { unsigned int reg; int sel = regulator_map_voltage_linear_range(rdev, uv, uv); + int ret; if (sel < 0) return -EINVAL; reg = rdev->desc->vsel_reg + RK808_SLP_REG_OFFSET; - return regmap_update_bits(rdev->regmap, reg, - rdev->desc->vsel_mask, - sel); + ret = regmap_update_bits(rdev->regmap, reg, + rdev->desc->vsel_mask, + sel); + if (ret) + return ret; + + if (rdev->desc->apply_bit) + ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg, + rdev->desc->apply_bit, + rdev->desc->apply_bit); + + return ret; } static int rk805_set_suspend_enable(struct regulator_dev *rdev) @@ -630,6 +645,38 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev) rdev->desc->enable_mask); } +static const struct rk8xx_register_bit rk816_suspend_bits[] = { + RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG1, 0), + RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG1, 1), + RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG1, 2), + RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG1, 3), + RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG2, 0), + RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG2, 1), + RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG2, 2), + RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG2, 3), + RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG2, 4), + RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG2, 5), + RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG1, 5), + RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG1, 6), +}; + +static int rk816_set_suspend_enable(struct regulator_dev *rdev) +{ + int rid = rdev_get_id(rdev); + + return regmap_update_bits(rdev->regmap, rk816_suspend_bits[rid].reg, + rk816_suspend_bits[rid].bit, + rk816_suspend_bits[rid].bit); +} + +static int rk816_set_suspend_disable(struct regulator_dev *rdev) +{ + int rid = rdev_get_id(rdev); + + return regmap_update_bits(rdev->regmap, rk816_suspend_bits[rid].reg, + rk816_suspend_bits[rid].bit, 0); +} + static int rk817_set_suspend_enable_ctrl(struct regulator_dev *rdev, unsigned int en) { @@ -903,6 +950,54 @@ static const struct regulator_ops rk809_buck5_ops_range = { .set_suspend_disable = rk817_set_suspend_disable, }; +static const struct regulator_ops rk816_buck1_2_ops_ranges = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_mode = rk8xx_set_mode, + .get_mode = rk8xx_get_mode, + .set_suspend_mode = rk8xx_set_suspend_mode, + .set_ramp_delay = regulator_set_ramp_delay_regmap, + .set_suspend_voltage = rk808_set_suspend_voltage_range, + .set_suspend_enable = rk816_set_suspend_enable, + .set_suspend_disable = rk816_set_suspend_disable, +}; + +static const struct regulator_ops rk816_buck4_ops_ranges = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_mode = rk8xx_set_mode, + .get_mode = rk8xx_get_mode, + .set_suspend_mode = rk8xx_set_suspend_mode, + .set_suspend_voltage = rk808_set_suspend_voltage_range, + .set_suspend_enable = rk816_set_suspend_enable, + .set_suspend_disable = rk816_set_suspend_disable, +}; + +static const struct regulator_ops rk816_reg_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = rk8xx_is_enabled_wmsk_regmap, + .set_suspend_voltage = rk808_set_suspend_voltage, + .set_suspend_enable = rk816_set_suspend_enable, + .set_suspend_disable = rk816_set_suspend_disable, +}; + static const struct regulator_ops rk817_reg_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, @@ -1382,6 +1477,117 @@ static const struct regulator_desc rk809_reg[] = { DISABLE_VAL(3)), }; +static const struct linear_range rk816_buck_4_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(800000, 0, 26, 100000), + REGULATOR_LINEAR_RANGE(3500000, 27, 31, 0), +}; + +static const struct regulator_desc rk816_reg[] = { + { + .name = "dcdc1", + .supply_name = "vcc1", + .of_match = of_match_ptr("dcdc1"), + .regulators_node = of_match_ptr("regulators"), + .id = RK816_ID_DCDC1, + .ops = &rk816_buck1_2_ops_ranges, + .type = REGULATOR_VOLTAGE, + .n_voltages = 64, + .linear_ranges = rk805_buck_1_2_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk805_buck_1_2_voltage_ranges), + .vsel_reg = RK818_BUCK1_ON_VSEL_REG, + .vsel_mask = RK818_BUCK_VSEL_MASK, + .apply_reg = RK816_DCDC_EN_REG2, + .apply_bit = RK816_BUCK_DVS_CONFIRM, + .enable_reg = RK816_DCDC_EN_REG1, + .enable_mask = BIT(4) | BIT(0), + .enable_val = BIT(4) | BIT(0), + .disable_val = BIT(4), + .ramp_reg = RK818_BUCK1_CONFIG_REG, + .ramp_mask = RK808_RAMP_RATE_MASK, + .ramp_delay_table = rk817_buck1_4_ramp_table, + .n_ramp_values = ARRAY_SIZE(rk817_buck1_4_ramp_table), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, { + .name = "dcdc2", + .supply_name = "vcc2", + .of_match = of_match_ptr("dcdc2"), + .regulators_node = of_match_ptr("regulators"), + .id = RK816_ID_DCDC2, + .ops = &rk816_buck1_2_ops_ranges, + .type = REGULATOR_VOLTAGE, + .n_voltages = 64, + .linear_ranges = rk805_buck_1_2_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk805_buck_1_2_voltage_ranges), + .vsel_reg = RK818_BUCK2_ON_VSEL_REG, + .vsel_mask = RK818_BUCK_VSEL_MASK, + .apply_reg = RK816_DCDC_EN_REG2, + .apply_bit = RK816_BUCK_DVS_CONFIRM, + .enable_reg = RK816_DCDC_EN_REG1, + .enable_mask = BIT(5) | BIT(1), + .enable_val = BIT(5) | BIT(1), + .disable_val = BIT(5), + .ramp_reg = RK818_BUCK2_CONFIG_REG, + .ramp_mask = RK808_RAMP_RATE_MASK, + .ramp_delay_table = rk817_buck1_4_ramp_table, + .n_ramp_values = ARRAY_SIZE(rk817_buck1_4_ramp_table), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, { + .name = "dcdc3", + .supply_name = "vcc3", + .of_match = of_match_ptr("dcdc3"), + .regulators_node = of_match_ptr("regulators"), + .id = RK816_ID_DCDC3, + .ops = &rk808_switch_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 1, + .enable_reg = RK816_DCDC_EN_REG1, + .enable_mask = BIT(6) | BIT(2), + .enable_val = BIT(6) | BIT(2), + .disable_val = BIT(6), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, { + .name = "dcdc4", + .supply_name = "vcc4", + .of_match = of_match_ptr("dcdc4"), + .regulators_node = of_match_ptr("regulators"), + .id = RK816_ID_DCDC4, + .ops = &rk816_buck4_ops_ranges, + .type = REGULATOR_VOLTAGE, + .n_voltages = 32, + .linear_ranges = rk816_buck_4_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk816_buck_4_voltage_ranges), + .vsel_reg = RK818_BUCK4_ON_VSEL_REG, + .vsel_mask = RK818_BUCK4_VSEL_MASK, + .enable_reg = RK816_DCDC_EN_REG1, + .enable_mask = BIT(7) | BIT(3), + .enable_val = BIT(7) | BIT(3), + .disable_val = BIT(7), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, + RK816_DESC(RK816_ID_LDO1, "ldo1", "vcc5", 800, 3400, 100, + RK818_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG1, ENABLE_MASK(0), DISABLE_VAL(0), 400), + RK816_DESC(RK816_ID_LDO2, "ldo2", "vcc5", 800, 3400, 100, + RK818_LDO2_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG1, ENABLE_MASK(1), DISABLE_VAL(1), 400), + RK816_DESC(RK816_ID_LDO3, "ldo3", "vcc5", 800, 3400, 100, + RK818_LDO3_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG1, ENABLE_MASK(2), DISABLE_VAL(2), 400), + RK816_DESC(RK816_ID_LDO4, "ldo4", "vcc6", 800, 3400, 100, + RK818_LDO4_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG1, ENABLE_MASK(3), DISABLE_VAL(3), 400), + RK816_DESC(RK816_ID_LDO5, "ldo5", "vcc6", 800, 3400, 100, + RK818_LDO5_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG2, ENABLE_MASK(0), DISABLE_VAL(0), 400), + RK816_DESC(RK816_ID_LDO6, "ldo6", "vcc6", 800, 3400, 100, + RK818_LDO6_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG2, ENABLE_MASK(1), DISABLE_VAL(1), 400), +}; + static const struct regulator_desc rk817_reg[] = { { .name = "DCDC_REG1", @@ -1704,6 +1910,10 @@ static int rk808_regulator_probe(struct platform_device *pdev) regulators = rk809_reg; nregulators = RK809_NUM_REGULATORS; break; + case RK816_ID: + regulators = rk816_reg; + nregulators = ARRAY_SIZE(rk816_reg); + break; case RK817_ID: regulators = rk817_reg; nregulators = RK817_NUM_REGULATORS; diff --git a/drivers/regulator/tps6594-regulator.c b/drivers/regulator/tps6594-regulator.c index b7f0c8779757..9e7886bd4149 100644 --- a/drivers/regulator/tps6594-regulator.c +++ b/drivers/regulator/tps6594-regulator.c @@ -18,10 +18,13 @@ #include <linux/mfd/tps6594.h> -#define BUCK_NB 5 -#define LDO_NB 4 -#define MULTI_PHASE_NB 4 -#define REGS_INT_NB 4 +#define BUCK_NB 5 +#define LDO_NB 4 +#define MULTI_PHASE_NB 4 +/* TPS6593 and LP8764 supports OV, UV, SC, ILIM */ +#define REGS_INT_NB 4 +/* TPS65224 supports OV or UV */ +#define TPS65224_REGS_INT_NB 1 enum tps6594_regulator_id { /* DCDC's */ @@ -66,6 +69,15 @@ static struct tps6594_regulator_irq_type tps6594_ext_regulator_irq_types[] = { REGULATOR_EVENT_OVER_VOLTAGE_WARN }, }; +static struct tps6594_regulator_irq_type tps65224_ext_regulator_irq_types[] = { + { TPS65224_IRQ_NAME_VCCA_UVOV, "VCCA", "voltage out of range", + REGULATOR_EVENT_REGULATION_OUT }, + { TPS65224_IRQ_NAME_VMON1_UVOV, "VMON1", "voltage out of range", + REGULATOR_EVENT_REGULATION_OUT }, + { TPS65224_IRQ_NAME_VMON2_UVOV, "VMON2", "voltage out of range", + REGULATOR_EVENT_REGULATION_OUT }, +}; + struct tps6594_regulator_irq_data { struct device *dev; struct tps6594_regulator_irq_type *type; @@ -122,6 +134,27 @@ static const struct linear_range ldos_4_ranges[] = { REGULATOR_LINEAR_RANGE(1200000, 0x20, 0x74, 25000), }; +/* Voltage range for TPS65224 Bucks and LDOs */ +static const struct linear_range tps65224_bucks_1_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0x0a, 0x0e, 20000), + REGULATOR_LINEAR_RANGE(600000, 0x0f, 0x72, 5000), + REGULATOR_LINEAR_RANGE(1100000, 0x73, 0xaa, 10000), + REGULATOR_LINEAR_RANGE(1660000, 0xab, 0xfd, 20000), +}; + +static const struct linear_range tps65224_bucks_2_3_4_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0x0, 0x1a, 25000), + REGULATOR_LINEAR_RANGE(1200000, 0x1b, 0x45, 50000), +}; + +static const struct linear_range tps65224_ldos_1_ranges[] = { + REGULATOR_LINEAR_RANGE(1200000, 0xC, 0x36, 50000), +}; + +static const struct linear_range tps65224_ldos_2_3_ranges[] = { + REGULATOR_LINEAR_RANGE(600000, 0x0, 0x38, 50000), +}; + /* Operations permitted on BUCK1/2/3/4/5 */ static const struct regulator_ops tps6594_bucks_ops = { .is_enabled = regulator_is_enabled_regmap, @@ -197,6 +230,38 @@ static const struct regulator_desc buck_regs[] = { 4, 0, 0, NULL, 0, 0), }; +/* Buck configuration for TPS65224 */ +static const struct regulator_desc tps65224_buck_regs[] = { + TPS6594_REGULATOR("BUCK1", "buck1", TPS6594_BUCK_1, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS65224_MASK_BUCK1_VSET, + TPS6594_REG_BUCKX_VOUT_1(0), + TPS65224_MASK_BUCK1_VSET, + TPS6594_REG_BUCKX_CTRL(0), + TPS6594_BIT_BUCK_EN, 0, 0, tps65224_bucks_1_ranges, + 4, 0, 0, NULL, 0, 0), + TPS6594_REGULATOR("BUCK2", "buck2", TPS6594_BUCK_2, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS65224_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_VOUT_1(1), + TPS65224_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_CTRL(1), + TPS6594_BIT_BUCK_EN, 0, 0, tps65224_bucks_2_3_4_ranges, + 4, 0, 0, NULL, 0, 0), + TPS6594_REGULATOR("BUCK3", "buck3", TPS6594_BUCK_3, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS65224_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_VOUT_1(2), + TPS65224_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_CTRL(2), + TPS6594_BIT_BUCK_EN, 0, 0, tps65224_bucks_2_3_4_ranges, + 4, 0, 0, NULL, 0, 0), + TPS6594_REGULATOR("BUCK4", "buck4", TPS6594_BUCK_4, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS65224_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_VOUT_1(3), + TPS65224_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_CTRL(3), + TPS6594_BIT_BUCK_EN, 0, 0, tps65224_bucks_2_3_4_ranges, + 4, 0, 0, NULL, 0, 0), +}; + static struct tps6594_regulator_irq_type tps6594_buck1_irq_types[] = { { TPS6594_IRQ_NAME_BUCK1_OV, "BUCK1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, { TPS6594_IRQ_NAME_BUCK1_UV, "BUCK1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, @@ -269,6 +334,41 @@ static struct tps6594_regulator_irq_type tps6594_ldo4_irq_types[] = { REGULATOR_EVENT_OVER_CURRENT }, }; +static struct tps6594_regulator_irq_type tps65224_buck1_irq_types[] = { + { TPS65224_IRQ_NAME_BUCK1_UVOV, "BUCK1", "voltage out of range", + REGULATOR_EVENT_REGULATION_OUT }, +}; + +static struct tps6594_regulator_irq_type tps65224_buck2_irq_types[] = { + { TPS65224_IRQ_NAME_BUCK2_UVOV, "BUCK2", "voltage out of range", + REGULATOR_EVENT_REGULATION_OUT }, +}; + +static struct tps6594_regulator_irq_type tps65224_buck3_irq_types[] = { + { TPS65224_IRQ_NAME_BUCK3_UVOV, "BUCK3", "voltage out of range", + REGULATOR_EVENT_REGULATION_OUT }, +}; + +static struct tps6594_regulator_irq_type tps65224_buck4_irq_types[] = { + { TPS65224_IRQ_NAME_BUCK4_UVOV, "BUCK4", "voltage out of range", + REGULATOR_EVENT_REGULATION_OUT }, +}; + +static struct tps6594_regulator_irq_type tps65224_ldo1_irq_types[] = { + { TPS65224_IRQ_NAME_LDO1_UVOV, "LDO1", "voltage out of range", + REGULATOR_EVENT_REGULATION_OUT }, +}; + +static struct tps6594_regulator_irq_type tps65224_ldo2_irq_types[] = { + { TPS65224_IRQ_NAME_LDO2_UVOV, "LDO2", "voltage out of range", + REGULATOR_EVENT_REGULATION_OUT }, +}; + +static struct tps6594_regulator_irq_type tps65224_ldo3_irq_types[] = { + { TPS65224_IRQ_NAME_LDO3_UVOV, "LDO3", "voltage out of range", + REGULATOR_EVENT_REGULATION_OUT }, +}; + static struct tps6594_regulator_irq_type *tps6594_bucks_irq_types[] = { tps6594_buck1_irq_types, tps6594_buck2_irq_types, @@ -284,7 +384,20 @@ static struct tps6594_regulator_irq_type *tps6594_ldos_irq_types[] = { tps6594_ldo4_irq_types, }; -static const struct regulator_desc multi_regs[] = { +static struct tps6594_regulator_irq_type *tps65224_bucks_irq_types[] = { + tps65224_buck1_irq_types, + tps65224_buck2_irq_types, + tps65224_buck3_irq_types, + tps65224_buck4_irq_types, +}; + +static struct tps6594_regulator_irq_type *tps65224_ldos_irq_types[] = { + tps65224_ldo1_irq_types, + tps65224_ldo2_irq_types, + tps65224_ldo3_irq_types, +}; + +static const struct regulator_desc tps6594_multi_regs[] = { TPS6594_REGULATOR("BUCK12", "buck12", TPS6594_BUCK_1, REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, TPS6594_REG_BUCKX_VOUT_1(1), @@ -315,7 +428,17 @@ static const struct regulator_desc multi_regs[] = { 4, 4000, 0, NULL, 0, 0), }; -static const struct regulator_desc ldo_regs[] = { +static const struct regulator_desc tps65224_multi_regs[] = { + TPS6594_REGULATOR("BUCK12", "buck12", TPS6594_BUCK_1, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS65224_MASK_BUCK1_VSET, + TPS6594_REG_BUCKX_VOUT_1(0), + TPS65224_MASK_BUCK1_VSET, + TPS6594_REG_BUCKX_CTRL(0), + TPS6594_BIT_BUCK_EN, 0, 0, tps65224_bucks_1_ranges, + 4, 4000, 0, NULL, 0, 0), +}; + +static const struct regulator_desc tps6594_ldo_regs[] = { TPS6594_REGULATOR("LDO1", "ldo1", TPS6594_LDO_1, REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET, TPS6594_REG_LDOX_VOUT(0), @@ -346,6 +469,30 @@ static const struct regulator_desc ldo_regs[] = { 1, 0, 0, NULL, 0, 0), }; +static const struct regulator_desc tps65224_ldo_regs[] = { + TPS6594_REGULATOR("LDO1", "ldo1", TPS6594_LDO_1, + REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET, + TPS6594_REG_LDOX_VOUT(0), + TPS6594_MASK_LDO123_VSET, + TPS6594_REG_LDOX_CTRL(0), + TPS6594_BIT_LDO_EN, 0, 0, tps65224_ldos_1_ranges, + 1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS), + TPS6594_REGULATOR("LDO2", "ldo2", TPS6594_LDO_2, + REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET, + TPS6594_REG_LDOX_VOUT(1), + TPS6594_MASK_LDO123_VSET, + TPS6594_REG_LDOX_CTRL(1), + TPS6594_BIT_LDO_EN, 0, 0, tps65224_ldos_2_3_ranges, + 1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS), + TPS6594_REGULATOR("LDO3", "ldo3", TPS6594_LDO_3, + REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET, + TPS6594_REG_LDOX_VOUT(2), + TPS6594_MASK_LDO123_VSET, + TPS6594_REG_LDOX_CTRL(2), + TPS6594_BIT_LDO_EN, 0, 0, tps65224_ldos_2_3_ranges, + 1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS), +}; + static irqreturn_t tps6594_regulator_irq_handler(int irq, void *data) { struct tps6594_regulator_irq_data *irq_data = data; @@ -369,17 +516,18 @@ static irqreturn_t tps6594_regulator_irq_handler(int irq, void *data) static int tps6594_request_reg_irqs(struct platform_device *pdev, struct regulator_dev *rdev, struct tps6594_regulator_irq_data *irq_data, - struct tps6594_regulator_irq_type *tps6594_regs_irq_types, + struct tps6594_regulator_irq_type *regs_irq_types, + size_t interrupt_cnt, int *irq_idx) { struct tps6594_regulator_irq_type *irq_type; struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent); - int j; + size_t j; int irq; int error; - for (j = 0; j < REGS_INT_NB; j++) { - irq_type = &tps6594_regs_irq_types[j]; + for (j = 0; j < interrupt_cnt; j++) { + irq_type = ®s_irq_types[j]; irq = platform_get_irq_byname(pdev, irq_type->irq_name); if (irq < 0) return -EINVAL; @@ -411,23 +559,47 @@ static int tps6594_regulator_probe(struct platform_device *pdev) struct tps6594_regulator_irq_data *irq_data; struct tps6594_ext_regulator_irq_data *irq_ext_reg_data; struct tps6594_regulator_irq_type *irq_type; - u8 buck_configured[BUCK_NB] = { 0 }; - u8 buck_multi[MULTI_PHASE_NB] = { 0 }; - static const char * const multiphases[] = {"buck12", "buck123", "buck1234", "buck34"}; + struct tps6594_regulator_irq_type *irq_types; + bool buck_configured[BUCK_NB] = { false }; + bool buck_multi[MULTI_PHASE_NB] = { false }; + static const char *npname; - int error, i, irq, multi, delta; + int error, i, irq, multi; int irq_idx = 0; int buck_idx = 0; - size_t ext_reg_irq_nb = 2; + int nr_ldo; + int nr_buck; + int nr_types; + unsigned int irq_count; + unsigned int multi_phase_cnt; size_t reg_irq_nb; + struct tps6594_regulator_irq_type **bucks_irq_types; + const struct regulator_desc *multi_regs; + struct tps6594_regulator_irq_type **ldos_irq_types; + const struct regulator_desc *ldo_regs; + size_t interrupt_count; + + if (tps->chip_id == TPS65224) { + bucks_irq_types = tps65224_bucks_irq_types; + interrupt_count = ARRAY_SIZE(tps65224_buck1_irq_types); + multi_regs = tps65224_multi_regs; + ldos_irq_types = tps65224_ldos_irq_types; + ldo_regs = tps65224_ldo_regs; + multi_phase_cnt = ARRAY_SIZE(tps65224_multi_regs); + } else { + bucks_irq_types = tps6594_bucks_irq_types; + interrupt_count = ARRAY_SIZE(tps6594_buck1_irq_types); + multi_regs = tps6594_multi_regs; + ldos_irq_types = tps6594_ldos_irq_types; + ldo_regs = tps6594_ldo_regs; + multi_phase_cnt = ARRAY_SIZE(tps6594_multi_regs); + } + enum { MULTI_BUCK12, + MULTI_BUCK12_34, MULTI_BUCK123, MULTI_BUCK1234, - MULTI_BUCK12_34, - MULTI_FIRST = MULTI_BUCK12, - MULTI_LAST = MULTI_BUCK12_34, - MULTI_NUM = MULTI_LAST - MULTI_FIRST + 1 }; config.dev = tps->dev; @@ -442,61 +614,68 @@ static int tps6594_regulator_probe(struct platform_device *pdev) * In case of Multiphase configuration, value should be defined for * buck_configured to avoid creating bucks for every buck in multiphase */ - for (multi = MULTI_FIRST; multi < MULTI_NUM; multi++) { - np = of_find_node_by_name(tps->dev->of_node, multiphases[multi]); + for (multi = 0; multi < multi_phase_cnt; multi++) { + np = of_find_node_by_name(tps->dev->of_node, multi_regs[multi].supply_name); npname = of_node_full_name(np); np_pmic_parent = of_get_parent(of_get_parent(np)); if (of_node_cmp(of_node_full_name(np_pmic_parent), tps->dev->of_node->full_name)) continue; - delta = strcmp(npname, multiphases[multi]); - if (!delta) { + if (strcmp(npname, multi_regs[multi].supply_name) == 0) { switch (multi) { case MULTI_BUCK12: - buck_multi[0] = 1; - buck_configured[0] = 1; - buck_configured[1] = 1; + buck_multi[0] = true; + buck_configured[0] = true; + buck_configured[1] = true; break; /* multiphase buck34 is supported only with buck12 */ case MULTI_BUCK12_34: - buck_multi[0] = 1; - buck_multi[1] = 1; - buck_configured[0] = 1; - buck_configured[1] = 1; - buck_configured[2] = 1; - buck_configured[3] = 1; + buck_multi[0] = true; + buck_multi[1] = true; + buck_configured[0] = true; + buck_configured[1] = true; + buck_configured[2] = true; + buck_configured[3] = true; break; case MULTI_BUCK123: - buck_multi[2] = 1; - buck_configured[0] = 1; - buck_configured[1] = 1; - buck_configured[2] = 1; + buck_multi[2] = true; + buck_configured[0] = true; + buck_configured[1] = true; + buck_configured[2] = true; break; case MULTI_BUCK1234: - buck_multi[3] = 1; - buck_configured[0] = 1; - buck_configured[1] = 1; - buck_configured[2] = 1; - buck_configured[3] = 1; + buck_multi[3] = true; + buck_configured[0] = true; + buck_configured[1] = true; + buck_configured[2] = true; + buck_configured[3] = true; break; } } } if (tps->chip_id == LP8764) { - /* There is only 4 buck on LP8764 */ - buck_configured[4] = 1; - reg_irq_nb = size_mul(REGS_INT_NB, (BUCK_NB - 1)); + nr_buck = ARRAY_SIZE(buck_regs); + nr_ldo = 0; + nr_types = REGS_INT_NB; + } else if (tps->chip_id == TPS65224) { + nr_buck = ARRAY_SIZE(tps65224_buck_regs); + nr_ldo = ARRAY_SIZE(tps65224_ldo_regs); + nr_types = REGS_INT_NB; } else { - reg_irq_nb = size_mul(REGS_INT_NB, (size_add(BUCK_NB, LDO_NB))); + nr_buck = ARRAY_SIZE(buck_regs); + nr_ldo = ARRAY_SIZE(tps6594_ldo_regs); + nr_types = TPS65224_REGS_INT_NB; } + reg_irq_nb = nr_types * (nr_buck + nr_ldo); + irq_data = devm_kmalloc_array(tps->dev, reg_irq_nb, sizeof(struct tps6594_regulator_irq_data), GFP_KERNEL); if (!irq_data) return -ENOMEM; - for (i = 0; i < MULTI_PHASE_NB; i++) { - if (buck_multi[i] == 0) + for (i = 0; i < multi_phase_cnt; i++) { + if (!buck_multi[i]) continue; rdev = devm_regulator_register(&pdev->dev, &multi_regs[i], &config); @@ -506,52 +685,60 @@ static int tps6594_regulator_probe(struct platform_device *pdev) pdev->name); /* config multiphase buck12+buck34 */ - if (i == 1) + if (i == MULTI_BUCK12_34) buck_idx = 2; + error = tps6594_request_reg_irqs(pdev, rdev, irq_data, - tps6594_bucks_irq_types[buck_idx], &irq_idx); + bucks_irq_types[buck_idx], + interrupt_count, &irq_idx); if (error) return error; + error = tps6594_request_reg_irqs(pdev, rdev, irq_data, - tps6594_bucks_irq_types[buck_idx + 1], &irq_idx); + bucks_irq_types[buck_idx + 1], + interrupt_count, &irq_idx); if (error) return error; - if (i == 2 || i == 3) { + if (i == MULTI_BUCK123 || i == MULTI_BUCK1234) { error = tps6594_request_reg_irqs(pdev, rdev, irq_data, tps6594_bucks_irq_types[buck_idx + 2], + interrupt_count, &irq_idx); if (error) return error; } - if (i == 3) { + if (i == MULTI_BUCK1234) { error = tps6594_request_reg_irqs(pdev, rdev, irq_data, tps6594_bucks_irq_types[buck_idx + 3], + interrupt_count, &irq_idx); if (error) return error; } } - for (i = 0; i < BUCK_NB; i++) { - if (buck_configured[i] == 1) + for (i = 0; i < nr_buck; i++) { + if (buck_configured[i]) continue; - rdev = devm_regulator_register(&pdev->dev, &buck_regs[i], &config); + const struct regulator_desc *buck_cfg = (tps->chip_id == TPS65224) ? + tps65224_buck_regs : buck_regs; + + rdev = devm_regulator_register(&pdev->dev, &buck_cfg[i], &config); if (IS_ERR(rdev)) return dev_err_probe(tps->dev, PTR_ERR(rdev), - "failed to register %s regulator\n", - pdev->name); + "failed to register %s regulator\n", pdev->name); error = tps6594_request_reg_irqs(pdev, rdev, irq_data, - tps6594_bucks_irq_types[i], &irq_idx); + bucks_irq_types[i], interrupt_count, &irq_idx); if (error) return error; } - /* LP8764 dosen't have LDO */ + /* LP8764 doesn't have LDO */ if (tps->chip_id != LP8764) { - for (i = 0; i < ARRAY_SIZE(ldo_regs); i++) { + for (i = 0; i < nr_ldo; i++) { rdev = devm_regulator_register(&pdev->dev, &ldo_regs[i], &config); if (IS_ERR(rdev)) return dev_err_probe(tps->dev, PTR_ERR(rdev), @@ -559,26 +746,34 @@ static int tps6594_regulator_probe(struct platform_device *pdev) pdev->name); error = tps6594_request_reg_irqs(pdev, rdev, irq_data, - tps6594_ldos_irq_types[i], + ldos_irq_types[i], interrupt_count, &irq_idx); if (error) return error; } } - if (tps->chip_id == LP8764) - ext_reg_irq_nb = ARRAY_SIZE(tps6594_ext_regulator_irq_types); + if (tps->chip_id == TPS65224) { + irq_types = tps65224_ext_regulator_irq_types; + irq_count = ARRAY_SIZE(tps65224_ext_regulator_irq_types); + } else { + irq_types = tps6594_ext_regulator_irq_types; + if (tps->chip_id == LP8764) + irq_count = ARRAY_SIZE(tps6594_ext_regulator_irq_types); + else + /* TPS6593 supports only VCCA OV and UV */ + irq_count = 2; + } irq_ext_reg_data = devm_kmalloc_array(tps->dev, - ext_reg_irq_nb, - sizeof(struct tps6594_ext_regulator_irq_data), - GFP_KERNEL); + irq_count, + sizeof(struct tps6594_ext_regulator_irq_data), + GFP_KERNEL); if (!irq_ext_reg_data) return -ENOMEM; - for (i = 0; i < ext_reg_irq_nb; ++i) { - irq_type = &tps6594_ext_regulator_irq_types[i]; - + for (i = 0; i < irq_count; ++i) { + irq_type = &irq_types[i]; irq = platform_get_irq_byname(pdev, irq_type->irq_name); if (irq < 0) return -EINVAL; @@ -610,5 +805,6 @@ module_platform_driver(tps6594_regulator_driver); MODULE_ALIAS("platform:tps6594-regulator"); MODULE_AUTHOR("Jerome Neanne <jneanne@baylibre.com>"); +MODULE_AUTHOR("Nirmala Devi Mal Nadar <m.nirmaladevi@ltts.com>"); MODULE_DESCRIPTION("TPS6594 voltage regulator driver"); MODULE_LICENSE("GPL"); |