Merge tag 'mfd-for-linus-4.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 Ricoh RC5T619 PMIC to rn5t618
   - Add support for PM8821 PMIC to qcom-pm8xxx

  New Functionality:
   - Add support for GPIO to lpc_ich
   - Add support for GPADC to sun4i
   - Add ability for rk808 to shutdown

  Fix-ups:
   - Simplify/strip unnecessary code; tps65218, palmas, tps65217
   - Device Tree binding updates; tps65218, altera-a10sr
   - Provide/export device ID info; tps65218, axp20x-i2c, hi655x-pmic,
     fsl-imx25-tsadc, intel_soc_pmic_bxtwc
   - Use MFD API instead of of_platform_populate(); tps65218
   - Generalise name-space; pm8xxx
   - Supply/edit regmap configuration; axp20x, cs47l24-tables, axp20x
   - Enable compile testing; max77620, max77686, exynos-lpass,
     abx500-core
   - Coding style issues; wm8994-core, wm5102-tables
   - Supply endian support; syscon
   - Remove module support; ab3100-core, ab8500-debugfs, ab8500-gpadc,
     abx500-core

  Bug Fixes:
   - Fix ordering issues; wm8994
   - Fix dependencies (build-time/run-time); exynos_lpass, sun4i-gpadc
   - Fix compiler warnings; sun4i-gpadc
   - Fix leaks; mfd-core
   - Fix page fault during module unload; tps65217"

* tag 'mfd-for-linus-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (49 commits)
  mfd: tps65217: Support an interrupt pin as the system wakeup
  mfd: tps65217: Make an interrupt handler simpler
  mfd: tps65217: Update register interrupt mask bits instead of writing operation
  mfd: tps65217: Specify the IRQ name
  mfd: tps65217: Fix page fault on unloading modules
  mfd: palmas: Remove redundant check in palmas_power_off
  mfd: arizona: Disable IRQs during driver remove
  mfd: pm8xxx: add support to pm8821
  mfd: intel-lpss: Try to enable Memory-Write-Invalidate
  mfd: rn5t618: Add Ricoh RC5T619 PMIC support
  mfd: axp20x: Add address extension registers for AXP806 regmap
  mfd: intel_soc_pmic_bxtwc: Fix a typo in MODULE_DEVICE_TABLE()
  mfd: core: Fix device reference leak in mfd_clone_cell
  mfd: bcm590xx: Simplify a test
  mfd: sun4i-gpadc: Select regmap-irq
  mfd: abx500-core: drop unused MODULE_ tags from non-modular code
  mfd: ab8500: make sysctrl explicitly non-modular
  mfd: ab8500-gpadc: Make it explicitly non-modular
  mfd: ab8500-debugfs: Make it explicitly non-modular
  mfd: ab8500-core: Make it explicitly non-modular
  ...
This commit is contained in:
Linus Torvalds
2016-12-19 08:16:26 -08:00
47 changed files with 1582 additions and 1049 deletions

View File

@@ -40,6 +40,22 @@ config MFD_ACT8945A
linear regulators, along with a complete ActivePath battery
charger.
config MFD_SUN4I_GPADC
tristate "Allwinner sunxi platforms' GPADC MFD driver"
select MFD_CORE
select REGMAP_MMIO
select REGMAP_IRQ
depends on ARCH_SUNXI || COMPILE_TEST
help
Select this to get support for Allwinner SoCs (A10, A13 and A31) ADC.
This driver will only map the hardware interrupt and registers, you
have to select individual drivers based on this MFD to be able to use
the ADC or the thermal sensor. This will try to probe the ADC driver
sun4i-gpadc-iio and the hwmon driver iio_hwmon.
To compile this driver as a module, choose M here: the module will be
called sun4i-gpadc.
config MFD_AS3711
bool "AMS AS3711"
select MFD_CORE
@@ -293,6 +309,7 @@ config MFD_DLN2
config MFD_EXYNOS_LPASS
tristate "Samsung Exynos SoC Low Power Audio Subsystem"
depends on ARCH_EXYNOS || COMPILE_TEST
select MFD_CORE
select REGMAP_MMIO
help
@@ -563,7 +580,7 @@ config MFD_MAX14577
config MFD_MAX77620
bool "Maxim Semiconductor MAX77620 and MAX20024 PMIC Support"
depends on I2C=y
depends on OF
depends on OF || COMPILE_TEST
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
@@ -578,7 +595,7 @@ config MFD_MAX77620
config MFD_MAX77686
tristate "Maxim Semiconductor MAX77686/802 PMIC Support"
depends on I2C
depends on OF
depends on OF || COMPILE_TEST
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
@@ -877,7 +894,8 @@ config MFD_RN5T618
select MFD_CORE
select REGMAP_I2C
help
Say yes here to add support for the Ricoh RN5T567 or R5T618 PMIC.
Say yes here to add support for the Ricoh RN5T567,
RN5T618, RC5T619 PMIC.
This driver provides common support for accessing the device,
additional drivers must be enabled in order to use the
functionality of the device.
@@ -951,7 +969,7 @@ config MFD_SMSC
config ABX500_CORE
bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions"
default y if ARCH_U300 || ARCH_U8500
default y if ARCH_U300 || ARCH_U8500 || COMPILE_TEST
help
Say yes here if you have the ABX500 Mixed Signal IC family
chips. This core driver expose register access functions.

View File

@@ -211,3 +211,4 @@ obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
obj-$(CONFIG_MFD_MT6397) += mt6397-core.o
obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o

View File

@@ -12,7 +12,7 @@
#include <linux/notifier.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/interrupt.h>
@@ -628,20 +628,10 @@ static void ab3100_setup_debugfs(struct ab3100 *ab3100)
exit_no_debugfs:
return;
}
static inline void ab3100_remove_debugfs(void)
{
debugfs_remove(ab3100_set_reg_file);
debugfs_remove(ab3100_get_reg_file);
debugfs_remove(ab3100_reg_file);
debugfs_remove(ab3100_dir);
}
#else
static inline void ab3100_setup_debugfs(struct ab3100 *ab3100)
{
}
static inline void ab3100_remove_debugfs(void)
{
}
#endif
/*
@@ -949,45 +939,22 @@ static int ab3100_probe(struct i2c_client *client,
return err;
}
static int ab3100_remove(struct i2c_client *client)
{
struct ab3100 *ab3100 = i2c_get_clientdata(client);
/* Unregister subdevices */
mfd_remove_devices(&client->dev);
ab3100_remove_debugfs();
i2c_unregister_device(ab3100->testreg_client);
return 0;
}
static const struct i2c_device_id ab3100_id[] = {
{ "ab3100", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ab3100_id);
static struct i2c_driver ab3100_driver = {
.driver = {
.name = "ab3100",
.name = "ab3100",
.suppress_bind_attrs = true,
},
.id_table = ab3100_id,
.probe = ab3100_probe,
.remove = ab3100_remove,
};
static int __init ab3100_i2c_init(void)
{
return i2c_add_driver(&ab3100_driver);
}
static void __exit ab3100_i2c_exit(void)
{
i2c_del_driver(&ab3100_driver);
}
subsys_initcall(ab3100_i2c_init);
module_exit(ab3100_i2c_exit);
MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
MODULE_DESCRIPTION("AB3100 core driver");
MODULE_LICENSE("GPL");

View File

@@ -14,7 +14,7 @@
#include <linux/irqdomain.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/abx500.h>
@@ -123,6 +123,10 @@ static DEFINE_SPINLOCK(on_stat_lock);
static u8 turn_on_stat_mask = 0xFF;
static u8 turn_on_stat_set;
static bool no_bm; /* No battery management */
/*
* not really modular, but the easiest way to keep compat with existing
* bootargs behaviour is to continue using module_param here.
*/
module_param(no_bm, bool, S_IRUGO);
#define AB9540_MODEM_CTRL2_REG 0x23
@@ -1324,25 +1328,6 @@ static int ab8500_probe(struct platform_device *pdev)
return ret;
}
static int ab8500_remove(struct platform_device *pdev)
{
struct ab8500 *ab8500 = platform_get_drvdata(pdev);
if (((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500))
sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
else
sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
if ((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
ab8500->chip_id >= AB8500_CUT2P0)
sysfs_remove_group(&ab8500->dev->kobj, &ab8505_attr_group);
mfd_remove_devices(ab8500->dev);
return 0;
}
static const struct platform_device_id ab8500_id[] = {
{ "ab8500-core", AB8500_VERSION_AB8500 },
{ "ab8505-i2c", AB8500_VERSION_AB8505 },
@@ -1354,9 +1339,9 @@ static const struct platform_device_id ab8500_id[] = {
static struct platform_driver ab8500_core_driver = {
.driver = {
.name = "ab8500-core",
.suppress_bind_attrs = true,
},
.probe = ab8500_probe,
.remove = ab8500_remove,
.id_table = ab8500_id,
};
@@ -1364,14 +1349,4 @@ static int __init ab8500_core_init(void)
{
return platform_driver_register(&ab8500_core_driver);
}
static void __exit ab8500_core_exit(void)
{
platform_driver_unregister(&ab8500_core_driver);
}
core_initcall(ab8500_core_init);
module_exit(ab8500_core_exit);
MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
MODULE_DESCRIPTION("AB8500 MFD core");
MODULE_LICENSE("GPL v2");

View File

@@ -74,7 +74,7 @@
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/debugfs.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
@@ -3234,33 +3234,16 @@ err:
return -ENOMEM;
}
static int ab8500_debug_remove(struct platform_device *plf)
{
debugfs_remove_recursive(ab8500_dir);
return 0;
}
static struct platform_driver ab8500_debug_driver = {
.driver = {
.name = "ab8500-debug",
.suppress_bind_attrs = true,
},
.probe = ab8500_debug_probe,
.remove = ab8500_debug_remove
};
static int __init ab8500_debug_init(void)
{
return platform_driver_register(&ab8500_debug_driver);
}
static void __exit ab8500_debug_exit(void)
{
platform_driver_unregister(&ab8500_debug_driver);
}
subsys_initcall(ab8500_debug_init);
module_exit(ab8500_debug_exit);
MODULE_AUTHOR("Mattias WALLIN <mattias.wallin@stericsson.com");
MODULE_DESCRIPTION("AB8500 DEBUG");
MODULE_LICENSE("GPL v2");

View File

@@ -5,9 +5,9 @@
* Author: Arun R Murthy <arun.murthy@stericsson.com>
* Author: Daniel Willerud <daniel.willerud@stericsson.com>
* Author: Johan Palsson <johan.palsson@stericsson.com>
* Author: M'boumba Cedric Madianga
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
@@ -1054,11 +1054,7 @@ static int __init ab8500_gpadc_init(void)
{
return platform_driver_register(&ab8500_gpadc_driver);
}
static void __exit ab8500_gpadc_exit(void)
{
platform_driver_unregister(&ab8500_gpadc_driver);
}
subsys_initcall_sync(ab8500_gpadc_init);
/**
* ab8540_gpadc_get_otp() - returns OTP values
@@ -1077,14 +1073,3 @@ void ab8540_gpadc_get_otp(struct ab8500_gpadc *gpadc,
*ibat_l = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_lo;
*ibat_h = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_hi;
}
subsys_initcall_sync(ab8500_gpadc_init);
module_exit(ab8500_gpadc_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Arun R Murthy");
MODULE_AUTHOR("Daniel Willerud");
MODULE_AUTHOR("Johan Palsson");
MODULE_AUTHOR("M'boumba Cedric Madianga");
MODULE_ALIAS("platform:ab8500_gpadc");
MODULE_DESCRIPTION("AB8500 GPADC driver");

View File

@@ -1,11 +1,14 @@
/*
* AB8500 system control driver
*
* Copyright (C) ST-Ericsson SA 2010
* Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> for ST Ericsson.
* License terms: GNU General Public License (GPL) version 2
*/
#include <linux/err.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/export.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/reboot.h>
@@ -158,7 +161,3 @@ static int __init ab8500_sysctrl_init(void)
return platform_driver_register(&ab8500_sysctrl_driver);
}
arch_initcall(ab8500_sysctrl_init);
MODULE_AUTHOR("Mattias Nilsson <mattias.i.nilsson@stericsson.com");
MODULE_DESCRIPTION("AB8500 system control driver");
MODULE_LICENSE("GPL v2");

View File

@@ -8,7 +8,8 @@
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/export.h>
#include <linux/mfd/abx500.h>
static LIST_HEAD(abx500_list);
@@ -150,7 +151,3 @@ int abx500_startup_irq_enabled(struct device *dev, unsigned int irq)
return -ENOTSUPP;
}
EXPORT_SYMBOL(abx500_startup_irq_enabled);
MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>");
MODULE_DESCRIPTION("ABX500 core driver");
MODULE_LICENSE("GPL");

View File

@@ -1553,6 +1553,7 @@ EXPORT_SYMBOL_GPL(arizona_dev_init);
int arizona_dev_exit(struct arizona *arizona)
{
disable_irq(arizona->irq);
pm_runtime_disable(arizona->dev);
regulator_disable(arizona->dcvdd);

View File

@@ -398,10 +398,10 @@ err_ctrlif:
err_boot_done:
free_irq(arizona->irq, arizona);
err_main_irq:
regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1),
regmap_del_irq_chip(irq_find_mapping(arizona->virq, 1),
arizona->irq_chip);
err_aod:
regmap_del_irq_chip(irq_create_mapping(arizona->virq, 0),
regmap_del_irq_chip(irq_find_mapping(arizona->virq, 0),
arizona->aod_irq_chip);
err:
return ret;
@@ -413,9 +413,9 @@ int arizona_irq_exit(struct arizona *arizona)
free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR),
arizona);
free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona);
regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1),
regmap_del_irq_chip(irq_find_mapping(arizona->virq, 1),
arizona->irq_chip);
regmap_del_irq_chip(irq_create_mapping(arizona->virq, 0),
regmap_del_irq_chip(irq_find_mapping(arizona->virq, 0),
arizona->aod_irq_chip);
free_irq(arizona->irq, arizona);

View File

@@ -69,10 +69,11 @@ static const struct of_device_id axp20x_i2c_of_match[] = {
};
MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
/*
* This is useless for OF-enabled devices, but it is needed by I2C subsystem
*/
static const struct i2c_device_id axp20x_i2c_id[] = {
{ "axp152", 0 },
{ "axp202", 0 },
{ "axp209", 0 },
{ "axp221", 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);

View File

@@ -98,6 +98,7 @@ static const struct regmap_range axp22x_volatile_ranges[] = {
regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
regmap_reg_range(AXP22X_PMIC_ADC_H, AXP20X_IPSOUT_V_HIGH_L),
regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
};
@@ -135,6 +136,7 @@ static const struct regmap_range axp806_writeable_ranges[] = {
regmap_reg_range(AXP806_PWR_OUT_CTRL1, AXP806_CLDO3_V_CTRL),
regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ2_EN),
regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT),
};
static const struct regmap_range axp806_volatile_ranges[] = {
@@ -305,7 +307,7 @@ static const struct regmap_config axp806_regmap_config = {
.val_bits = 8,
.wr_table = &axp806_writeable_table,
.volatile_table = &axp806_volatile_table,
.max_register = AXP806_VREF_TEMP_WARN_L,
.max_register = AXP806_REG_ADDR_EXT,
.cache_type = REGCACHE_RBTREE,
};

View File

@@ -67,7 +67,7 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri,
/* Secondary I2C slave address is the base address with A(2) asserted */
bcm590xx->i2c_sec = i2c_new_dummy(i2c_pri->adapter,
i2c_pri->addr | BIT(2));
if (IS_ERR_OR_NULL(bcm590xx->i2c_sec)) {
if (!bcm590xx->i2c_sec) {
dev_err(&i2c_pri->dev, "failed to add secondary I2C device\n");
return -ENODEV;
}

View File

@@ -292,6 +292,7 @@ static const struct reg_default cs47l24_reg_default[] = {
{ 0x00000502, 0x0000 }, /* R1282 - AIF1 Rx Pin Ctrl */
{ 0x00000503, 0x0000 }, /* R1283 - AIF1 Rate Ctrl */
{ 0x00000504, 0x0000 }, /* R1284 - AIF1 Format */
{ 0x00000505, 0x0040 }, /* R1285 - AIF1 Tx BCLK Rate */
{ 0x00000506, 0x0040 }, /* R1286 - AIF1 Rx BCLK Rate */
{ 0x00000507, 0x1818 }, /* R1287 - AIF1 Frame Ctrl 1 */
{ 0x00000508, 0x1818 }, /* R1288 - AIF1 Frame Ctrl 2 */
@@ -318,6 +319,7 @@ static const struct reg_default cs47l24_reg_default[] = {
{ 0x00000542, 0x0000 }, /* R1346 - AIF2 Rx Pin Ctrl */
{ 0x00000543, 0x0000 }, /* R1347 - AIF2 Rate Ctrl */
{ 0x00000544, 0x0000 }, /* R1348 - AIF2 Format */
{ 0x00000545, 0x0040 }, /* R1349 - AIF2 Tx BCLK Rate */
{ 0x00000546, 0x0040 }, /* R1350 - AIF2 Rx BCLK Rate */
{ 0x00000547, 0x1818 }, /* R1351 - AIF2 Frame Ctrl 1 */
{ 0x00000548, 0x1818 }, /* R1352 - AIF2 Frame Ctrl 2 */
@@ -340,6 +342,7 @@ static const struct reg_default cs47l24_reg_default[] = {
{ 0x00000582, 0x0000 }, /* R1410 - AIF3 Rx Pin Ctrl */
{ 0x00000583, 0x0000 }, /* R1411 - AIF3 Rate Ctrl */
{ 0x00000584, 0x0000 }, /* R1412 - AIF3 Format */
{ 0x00000585, 0x0040 }, /* R1413 - AIF3 Tx BCLK Rate */
{ 0x00000586, 0x0040 }, /* R1414 - AIF3 Rx BCLK Rate */
{ 0x00000587, 0x1818 }, /* R1415 - AIF3 Frame Ctrl 1 */
{ 0x00000588, 0x1818 }, /* R1416 - AIF3 Frame Ctrl 2 */
@@ -923,6 +926,7 @@ static bool cs47l24_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_AIF1_RX_PIN_CTRL:
case ARIZONA_AIF1_RATE_CTRL:
case ARIZONA_AIF1_FORMAT:
case ARIZONA_AIF1_TX_BCLK_RATE:
case ARIZONA_AIF1_RX_BCLK_RATE:
case ARIZONA_AIF1_FRAME_CTRL_1:
case ARIZONA_AIF1_FRAME_CTRL_2:
@@ -949,6 +953,7 @@ static bool cs47l24_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_AIF2_RX_PIN_CTRL:
case ARIZONA_AIF2_RATE_CTRL:
case ARIZONA_AIF2_FORMAT:
case ARIZONA_AIF2_TX_BCLK_RATE:
case ARIZONA_AIF2_RX_BCLK_RATE:
case ARIZONA_AIF2_FRAME_CTRL_1:
case ARIZONA_AIF2_FRAME_CTRL_2:
@@ -971,6 +976,7 @@ static bool cs47l24_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_AIF3_RX_PIN_CTRL:
case ARIZONA_AIF3_RATE_CTRL:
case ARIZONA_AIF3_FORMAT:
case ARIZONA_AIF3_TX_BCLK_RATE:
case ARIZONA_AIF3_RX_BCLK_RATE:
case ARIZONA_AIF3_FRAME_CTRL_1:
case ARIZONA_AIF3_FRAME_CTRL_2:

View File

@@ -32,6 +32,7 @@
#include <sound/pcm.h>
#include <linux/mfd/davinci_voicecodec.h>
#include <mach/hardware.h>
static const struct regmap_config davinci_vc_regmap = {
.reg_bits = 32,

View File

@@ -187,6 +187,7 @@ static const struct of_device_id mx25_tsadc_ids[] = {
{ .compatible = "fsl,imx25-tsadc" },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, mx25_tsadc_ids);
static struct platform_driver mx25_tsadc_driver = {
.driver = {

View File

@@ -169,6 +169,7 @@ static const struct of_device_id hi655x_pmic_match[] = {
{ .compatible = "hisilicon,hi655x-pmic", },
{},
};
MODULE_DEVICE_TABLE(of, hi655x_pmic_match);
static struct platform_driver hi655x_pmic_driver = {
.driver = {

View File

@@ -41,6 +41,7 @@ static int intel_lpss_pci_probe(struct pci_dev *pdev,
/* Probably it is enough to set this for iDMA capable devices only */
pci_set_master(pdev);
pci_try_set_mwi(pdev);
ret = intel_lpss_probe(&pdev->dev, info);
if (ret)

View File

@@ -519,7 +519,7 @@ static const struct acpi_device_id bxtwc_acpi_ids[] = {
{ "INT34D3", },
{ }
};
MODULE_DEVICE_TABLE(acpi, pmic_acpi_ids);
MODULE_DEVICE_TABLE(acpi, bxtwc_acpi_ids);
static struct platform_driver bxtwc_driver = {
.probe = bxtwc_probe,

View File

@@ -493,6 +493,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
[LPC_LPT] = {
.name = "Lynx Point",
.iTCO_version = 2,
.gpio_version = ICH_V5_GPIO,
},
[LPC_LPT_LP] = {
.name = "Lynx Point_LP",
@@ -530,6 +531,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
[LPC_9S] = {
.name = "9 Series",
.iTCO_version = 2,
.gpio_version = ICH_V5_GPIO,
},
};

View File

@@ -431,9 +431,6 @@ static void palmas_power_off(void)
unsigned int addr;
int ret, slave;
if (!palmas_dev)
return;
slave = PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE);
addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_DEV_CTRL);

View File

@@ -39,6 +39,20 @@
#define SSBI_REG_ADDR_IRQ_CONFIG (SSBI_REG_ADDR_IRQ_BASE + 7)
#define SSBI_REG_ADDR_IRQ_RT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 8)
#define PM8821_SSBI_REG_ADDR_IRQ_BASE 0x100
#define PM8821_SSBI_REG_ADDR_IRQ_MASTER0 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0x30)
#define PM8821_SSBI_REG_ADDR_IRQ_MASTER1 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0xb0)
#define PM8821_SSBI_REG(m, b, offset) \
((m == 0) ? \
(PM8821_SSBI_REG_ADDR_IRQ_MASTER0 + b + offset) : \
(PM8821_SSBI_REG_ADDR_IRQ_MASTER1 + b + offset))
#define PM8821_SSBI_ADDR_IRQ_ROOT(m, b) PM8821_SSBI_REG(m, b, 0x0)
#define PM8821_SSBI_ADDR_IRQ_CLEAR(m, b) PM8821_SSBI_REG(m, b, 0x01)
#define PM8821_SSBI_ADDR_IRQ_MASK(m, b) PM8821_SSBI_REG(m, b, 0x08)
#define PM8821_SSBI_ADDR_IRQ_RT_STATUS(m, b) PM8821_SSBI_REG(m, b, 0x0f)
#define PM8821_BLOCKS_PER_MASTER 7
#define PM_IRQF_LVL_SEL 0x01 /* level select */
#define PM_IRQF_MASK_FE 0x02 /* mask falling edge */
#define PM_IRQF_MASK_RE 0x04 /* mask rising edge */
@@ -54,6 +68,7 @@
#define REG_HWREV_2 0x0E8 /* PMIC4 revision 2 */
#define PM8XXX_NR_IRQS 256
#define PM8821_NR_IRQS 112
struct pm_irq_chip {
struct regmap *regmap;
@@ -65,6 +80,12 @@ struct pm_irq_chip {
u8 config[0];
};
struct pm_irq_data {
int num_irqs;
const struct irq_domain_ops *irq_domain_ops;
void (*irq_handler)(struct irq_desc *desc);
};
static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
unsigned int *ip)
{
@@ -182,6 +203,78 @@ static void pm8xxx_irq_handler(struct irq_desc *desc)
chained_irq_exit(irq_chip, desc);
}
static void pm8821_irq_block_handler(struct pm_irq_chip *chip,
int master, int block)
{
int pmirq, irq, i, ret;
unsigned int bits;
ret = regmap_read(chip->regmap,
PM8821_SSBI_ADDR_IRQ_ROOT(master, block), &bits);
if (ret) {
pr_err("Reading block %d failed ret=%d", block, ret);
return;
}
/* Convert block offset to global block number */
block += (master * PM8821_BLOCKS_PER_MASTER) - 1;
/* Check IRQ bits */
for (i = 0; i < 8; i++) {
if (bits & BIT(i)) {
pmirq = block * 8 + i;
irq = irq_find_mapping(chip->irqdomain, pmirq);
generic_handle_irq(irq);
}
}
}
static inline void pm8821_irq_master_handler(struct pm_irq_chip *chip,
int master, u8 master_val)
{
int block;
for (block = 1; block < 8; block++)
if (master_val & BIT(block))
pm8821_irq_block_handler(chip, master, block);
}
static void pm8821_irq_handler(struct irq_desc *desc)
{
struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
struct irq_chip *irq_chip = irq_desc_get_chip(desc);
unsigned int master;
int ret;
chained_irq_enter(irq_chip, desc);
ret = regmap_read(chip->regmap,
PM8821_SSBI_REG_ADDR_IRQ_MASTER0, &master);
if (ret) {
pr_err("Failed to read master 0 ret=%d\n", ret);
goto done;
}
/* bits 1 through 7 marks the first 7 blocks in master 0 */
if (master & GENMASK(7, 1))
pm8821_irq_master_handler(chip, 0, master);
/* bit 0 marks if master 1 contains any bits */
if (!(master & BIT(0)))
goto done;
ret = regmap_read(chip->regmap,
PM8821_SSBI_REG_ADDR_IRQ_MASTER1, &master);
if (ret) {
pr_err("Failed to read master 1 ret=%d\n", ret);
goto done;
}
pm8821_irq_master_handler(chip, 1, master);
done:
chained_irq_exit(irq_chip, desc);
}
static void pm8xxx_irq_mask_ack(struct irq_data *d)
{
struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
@@ -299,6 +392,104 @@ static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
.map = pm8xxx_irq_domain_map,
};
static void pm8821_irq_mask_ack(struct irq_data *d)
{
struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
unsigned int pmirq = irqd_to_hwirq(d);
u8 block, master;
int irq_bit, rc;
block = pmirq / 8;
master = block / PM8821_BLOCKS_PER_MASTER;
irq_bit = pmirq % 8;
block %= PM8821_BLOCKS_PER_MASTER;
rc = regmap_update_bits(chip->regmap,
PM8821_SSBI_ADDR_IRQ_MASK(master, block),
BIT(irq_bit), BIT(irq_bit));
if (rc) {
pr_err("Failed to mask IRQ:%d rc=%d\n", pmirq, rc);
return;
}
rc = regmap_update_bits(chip->regmap,
PM8821_SSBI_ADDR_IRQ_CLEAR(master, block),
BIT(irq_bit), BIT(irq_bit));
if (rc)
pr_err("Failed to CLEAR IRQ:%d rc=%d\n", pmirq, rc);
}
static void pm8821_irq_unmask(struct irq_data *d)
{
struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
unsigned int pmirq = irqd_to_hwirq(d);
int irq_bit, rc;
u8 block, master;
block = pmirq / 8;
master = block / PM8821_BLOCKS_PER_MASTER;
irq_bit = pmirq % 8;
block %= PM8821_BLOCKS_PER_MASTER;
rc = regmap_update_bits(chip->regmap,
PM8821_SSBI_ADDR_IRQ_MASK(master, block),
BIT(irq_bit), ~BIT(irq_bit));
if (rc)
pr_err("Failed to read/write unmask IRQ:%d rc=%d\n", pmirq, rc);
}
static int pm8821_irq_get_irqchip_state(struct irq_data *d,
enum irqchip_irq_state which,
bool *state)
{
struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
int rc, pmirq = irqd_to_hwirq(d);
u8 block, irq_bit, master;
unsigned int bits;
block = pmirq / 8;
master = block / PM8821_BLOCKS_PER_MASTER;
irq_bit = pmirq % 8;
block %= PM8821_BLOCKS_PER_MASTER;
rc = regmap_read(chip->regmap,
PM8821_SSBI_ADDR_IRQ_RT_STATUS(master, block), &bits);
if (rc) {
pr_err("Reading Status of IRQ %d failed rc=%d\n", pmirq, rc);
return rc;
}
*state = !!(bits & BIT(irq_bit));
return rc;
}
static struct irq_chip pm8821_irq_chip = {
.name = "pm8821",
.irq_mask_ack = pm8821_irq_mask_ack,
.irq_unmask = pm8821_irq_unmask,
.irq_get_irqchip_state = pm8821_irq_get_irqchip_state,
.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
};
static int pm8821_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
struct pm_irq_chip *chip = d->host_data;
irq_set_chip_and_handler(irq, &pm8821_irq_chip, handle_level_irq);
irq_set_chip_data(irq, chip);
irq_set_noprobe(irq);
return 0;
}
static const struct irq_domain_ops pm8821_irq_domain_ops = {
.xlate = irq_domain_xlate_twocell,
.map = pm8821_irq_domain_map,
};
static const struct regmap_config ssbi_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
@@ -308,22 +499,41 @@ static const struct regmap_config ssbi_regmap_config = {
.reg_write = ssbi_reg_write
};
static const struct pm_irq_data pm8xxx_data = {
.num_irqs = PM8XXX_NR_IRQS,
.irq_domain_ops = &pm8xxx_irq_domain_ops,
.irq_handler = pm8xxx_irq_handler,
};
static const struct pm_irq_data pm8821_data = {
.num_irqs = PM8821_NR_IRQS,
.irq_domain_ops = &pm8821_irq_domain_ops,
.irq_handler = pm8821_irq_handler,
};
static const struct of_device_id pm8xxx_id_table[] = {
{ .compatible = "qcom,pm8018", },
{ .compatible = "qcom,pm8058", },
{ .compatible = "qcom,pm8921", },
{ .compatible = "qcom,pm8018", .data = &pm8xxx_data},
{ .compatible = "qcom,pm8058", .data = &pm8xxx_data},
{ .compatible = "qcom,pm8821", .data = &pm8821_data},
{ .compatible = "qcom,pm8921", .data = &pm8xxx_data},
{ }
};
MODULE_DEVICE_TABLE(of, pm8xxx_id_table);
static int pm8xxx_probe(struct platform_device *pdev)
{
const struct pm_irq_data *data;
struct regmap *regmap;
int irq, rc;
unsigned int val;
u32 rev;
struct pm_irq_chip *chip;
unsigned int nirqs = PM8XXX_NR_IRQS;
data = of_device_get_match_data(&pdev->dev);
if (!data) {
dev_err(&pdev->dev, "No matching driver data found\n");
return -EINVAL;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@@ -354,25 +564,26 @@ static int pm8xxx_probe(struct platform_device *pdev)
rev |= val << BITS_PER_BYTE;
chip = devm_kzalloc(&pdev->dev, sizeof(*chip) +
sizeof(chip->config[0]) * nirqs,
GFP_KERNEL);
sizeof(chip->config[0]) * data->num_irqs,
GFP_KERNEL);
if (!chip)
return -ENOMEM;
platform_set_drvdata(pdev, chip);
chip->regmap = regmap;
chip->num_irqs = nirqs;
chip->num_irqs = data->num_irqs;
chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
spin_lock_init(&chip->pm_irq_lock);
chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node, nirqs,
&pm8xxx_irq_domain_ops,
chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node,
data->num_irqs,
data->irq_domain_ops,
chip);
if (!chip->irqdomain)
return -ENODEV;
irq_set_chained_handler_and_data(irq, pm8xxx_irq_handler, chip);
irq_set_chained_handler_and_data(irq, data->irq_handler, chip);
irq_set_irq_wake(irq, 1);
rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);

View File

@@ -290,6 +290,24 @@ static void rk808_device_shutdown(void)
dev_err(&rk808_i2c_client->dev, "power off error!\n");
}
static void rk818_device_shutdown(void)
{
int ret;
struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
if (!rk808) {
dev_warn(&rk808_i2c_client->dev,
"have no rk818, so do nothing here\n");
return;
}
ret = regmap_update_bits(rk808->regmap,
RK818_DEVCTRL_REG,
DEV_OFF, DEV_OFF);
if (ret)
dev_err(&rk808_i2c_client->dev, "power off error!\n");
}
static const struct of_device_id rk808_of_match[] = {
{ .compatible = "rockchip,rk808" },
{ .compatible = "rockchip,rk818" },
@@ -304,6 +322,7 @@ static int rk808_probe(struct i2c_client *client,
struct rk808 *rk808;
const struct rk808_reg_data *pre_init_reg;
const struct mfd_cell *cells;
void (*pm_pwroff_fn)(void);
int nr_pre_init_regs;
int nr_cells;
int pm_off = 0;
@@ -331,6 +350,7 @@ static int rk808_probe(struct i2c_client *client,
nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg);
cells = rk808s;
nr_cells = ARRAY_SIZE(rk808s);
pm_pwroff_fn = rk808_device_shutdown;
break;
case RK818_ID:
rk808->regmap_cfg = &rk818_regmap_config;
@@ -339,6 +359,7 @@ static int rk808_probe(struct i2c_client *client,
nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg);
cells = rk818s;
nr_cells = ARRAY_SIZE(rk818s);
pm_pwroff_fn = rk818_device_shutdown;
break;
default:
dev_err(&client->dev, "Unsupported RK8XX ID %lu\n",
@@ -393,7 +414,7 @@ static int rk808_probe(struct i2c_client *client,
"rockchip,system-power-controller");
if (pm_off && !pm_power_off) {
rk808_i2c_client = client;
pm_power_off = rk808_device_shutdown;
pm_power_off = pm_pwroff_fn;
}
return 0;

View File

@@ -87,6 +87,7 @@ static int rn5t618_restart(struct notifier_block *this,
static const struct of_device_id rn5t618_of_match[] = {
{ .compatible = "ricoh,rn5t567", .data = (void *)RN5T567 },
{ .compatible = "ricoh,rn5t618", .data = (void *)RN5T618 },
{ .compatible = "ricoh,rc5t619", .data = (void *)RC5T619 },
{ }
};
MODULE_DEVICE_TABLE(of, rn5t618_of_match);

View File

@@ -753,7 +753,7 @@ static int si476x_core_probe(struct i2c_client *client,
ARRAY_SIZE(core->supplies),
core->supplies);
if (rval) {
dev_err(&client->dev, "Failet to gett all of the regulators\n");
dev_err(&client->dev, "Failed to get all of the regulators\n");
goto free_gpio;
}

181
drivers/mfd/sun4i-gpadc.c Normal file
View File

@@ -0,0 +1,181 @@
/* ADC MFD core driver for sunxi platforms
*
* Copyright (c) 2016 Quentin Schulz <quentin.schulz@free-electrons.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/regmap.h>
#include <linux/mfd/sun4i-gpadc.h>
#define ARCH_SUN4I_A10 0
#define ARCH_SUN5I_A13 1
#define ARCH_SUN6I_A31 2
static struct resource adc_resources[] = {
DEFINE_RES_IRQ_NAMED(SUN4I_GPADC_IRQ_FIFO_DATA, "FIFO_DATA_PENDING"),
DEFINE_RES_IRQ_NAMED(SUN4I_GPADC_IRQ_TEMP_DATA, "TEMP_DATA_PENDING"),
};
static const struct regmap_irq sun4i_gpadc_regmap_irq[] = {
REGMAP_IRQ_REG(SUN4I_GPADC_IRQ_FIFO_DATA, 0,
SUN4I_GPADC_INT_FIFOC_TP_DATA_IRQ_EN),
REGMAP_IRQ_REG(SUN4I_GPADC_IRQ_TEMP_DATA, 0,
SUN4I_GPADC_INT_FIFOC_TEMP_IRQ_EN),
};
static const struct regmap_irq_chip sun4i_gpadc_regmap_irq_chip = {
.name = "sun4i_gpadc_irq_chip",
.status_base = SUN4I_GPADC_INT_FIFOS,
.ack_base = SUN4I_GPADC_INT_FIFOS,
.mask_base = SUN4I_GPADC_INT_FIFOC,
.init_ack_masked = true,
.mask_invert = true,
.irqs = sun4i_gpadc_regmap_irq,
.num_irqs = ARRAY_SIZE(sun4i_gpadc_regmap_irq),
.num_regs = 1,
};
static struct mfd_cell sun4i_gpadc_cells[] = {
{
.name = "sun4i-a10-gpadc-iio",
.resources = adc_resources,
.num_resources = ARRAY_SIZE(adc_resources),
},
{ .name = "iio_hwmon" }
};
static struct mfd_cell sun5i_gpadc_cells[] = {
{
.name = "sun5i-a13-gpadc-iio",
.resources = adc_resources,
.num_resources = ARRAY_SIZE(adc_resources),
},
{ .name = "iio_hwmon" },
};
static struct mfd_cell sun6i_gpadc_cells[] = {
{
.name = "sun6i-a31-gpadc-iio",
.resources = adc_resources,
.num_resources = ARRAY_SIZE(adc_resources),
},
{ .name = "iio_hwmon" },
};
static const struct regmap_config sun4i_gpadc_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.fast_io = true,
};
static const struct of_device_id sun4i_gpadc_of_match[] = {
{
.compatible = "allwinner,sun4i-a10-ts",
.data = (void *)ARCH_SUN4I_A10,
}, {
.compatible = "allwinner,sun5i-a13-ts",
.data = (void *)ARCH_SUN5I_A13,
}, {
.compatible = "allwinner,sun6i-a31-ts",
.data = (void *)ARCH_SUN6I_A31,
}, { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_match);
static int sun4i_gpadc_probe(struct platform_device *pdev)
{
struct sun4i_gpadc_dev *dev;
struct resource *mem;
const struct of_device_id *of_id;
const struct mfd_cell *cells;
unsigned int irq, size;
int ret;
of_id = of_match_node(sun4i_gpadc_of_match, pdev->dev.of_node);
if (!of_id)
return -EINVAL;
switch ((long)of_id->data) {
case ARCH_SUN4I_A10:
cells = sun4i_gpadc_cells;
size = ARRAY_SIZE(sun4i_gpadc_cells);
break;
case ARCH_SUN5I_A13:
cells = sun5i_gpadc_cells;
size = ARRAY_SIZE(sun5i_gpadc_cells);
break;
case ARCH_SUN6I_A31:
cells = sun6i_gpadc_cells;
size = ARRAY_SIZE(sun6i_gpadc_cells);
break;
default:
return -EINVAL;
}
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(dev->base))
return PTR_ERR(dev->base);
dev->dev = &pdev->dev;
dev_set_drvdata(dev->dev, dev);
dev->regmap = devm_regmap_init_mmio(dev->dev, dev->base,
&sun4i_gpadc_regmap_config);
if (IS_ERR(dev->regmap)) {
ret = PTR_ERR(dev->regmap);
dev_err(&pdev->dev, "failed to init regmap: %d\n", ret);
return ret;
}
/* Disable all interrupts */
regmap_write(dev->regmap, SUN4I_GPADC_INT_FIFOC, 0);
irq = platform_get_irq(pdev, 0);
ret = devm_regmap_add_irq_chip(&pdev->dev, dev->regmap, irq,
IRQF_ONESHOT, 0,
&sun4i_gpadc_regmap_irq_chip,
&dev->regmap_irqc);
if (ret) {
dev_err(&pdev->dev, "failed to add irq chip: %d\n", ret);
return ret;
}
ret = devm_mfd_add_devices(dev->dev, 0, cells, size, NULL, 0, NULL);
if (ret) {
dev_err(&pdev->dev, "failed to add MFD devices: %d\n", ret);
return ret;
}
return 0;
}
static struct platform_driver sun4i_gpadc_driver = {
.driver = {
.name = "sun4i-gpadc",
.of_match_table = of_match_ptr(sun4i_gpadc_of_match),
},
.probe = sun4i_gpadc_probe,
};
module_platform_driver(sun4i_gpadc_driver);
MODULE_DESCRIPTION("Allwinner sunxi platforms' GPADC MFD core driver");
MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
MODULE_LICENSE("GPL v2");

View File

@@ -53,7 +53,7 @@ int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg)
EXPORT_SYMBOL_GPL(tc3589x_reg_read);
/**
* tc3589x_reg_read() - write a single TC3589x register
* tc3589x_reg_write() - write a single TC3589x register
* @tc3589x: Device to write to
* @reg: Register to read
* @data: Value to write
@@ -118,7 +118,7 @@ EXPORT_SYMBOL_GPL(tc3589x_block_write);
* @tc3589x: Device to write to
* @reg: Register to write
* @mask: Mask of bits to set
* @values: Value to set
* @val: Value to set
*/
int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val)
{

View File

@@ -42,26 +42,6 @@ static struct resource pb_resources[] = {
DEFINE_RES_IRQ_NAMED(TPS65217_IRQ_PB, "PB"),
};
struct tps65217_irq {
int mask;
int interrupt;
};
static const struct tps65217_irq tps65217_irqs[] = {
[TPS65217_IRQ_PB] = {
.mask = TPS65217_INT_PBM,
.interrupt = TPS65217_INT_PBI,
},
[TPS65217_IRQ_AC] = {
.mask = TPS65217_INT_ACM,
.interrupt = TPS65217_INT_ACI,
},
[TPS65217_IRQ_USB] = {
.mask = TPS65217_INT_USBM,
.interrupt = TPS65217_INT_USBI,
},
};
static void tps65217_irq_lock(struct irq_data *data)
{
struct tps65217 *tps = irq_data_get_irq_chip_data(data);
@@ -74,37 +54,32 @@ static void tps65217_irq_sync_unlock(struct irq_data *data)
struct tps65217 *tps = irq_data_get_irq_chip_data(data);
int ret;
ret = tps65217_reg_write(tps, TPS65217_REG_INT, tps->irq_mask,
TPS65217_PROTECT_NONE);
ret = tps65217_set_bits(tps, TPS65217_REG_INT, TPS65217_INT_MASK,
tps->irq_mask, TPS65217_PROTECT_NONE);
if (ret != 0)
dev_err(tps->dev, "Failed to sync IRQ masks\n");
mutex_unlock(&tps->irq_lock);
}
static inline const struct tps65217_irq *
irq_to_tps65217_irq(struct tps65217 *tps, struct irq_data *data)
{
return &tps65217_irqs[data->hwirq];
}
static void tps65217_irq_enable(struct irq_data *data)
{
struct tps65217 *tps = irq_data_get_irq_chip_data(data);
const struct tps65217_irq *irq_data = irq_to_tps65217_irq(tps, data);
u8 mask = BIT(data->hwirq) << TPS65217_INT_SHIFT;
tps->irq_mask &= ~irq_data->mask;
tps->irq_mask &= ~mask;
}
static void tps65217_irq_disable(struct irq_data *data)
{
struct tps65217 *tps = irq_data_get_irq_chip_data(data);
const struct tps65217_irq *irq_data = irq_to_tps65217_irq(tps, data);
u8 mask = BIT(data->hwirq) << TPS65217_INT_SHIFT;
tps->irq_mask |= irq_data->mask;
tps->irq_mask |= mask;
}
static struct irq_chip tps65217_irq_chip = {
.name = "tps65217",
.irq_bus_lock = tps65217_irq_lock,
.irq_bus_sync_unlock = tps65217_irq_sync_unlock,
.irq_enable = tps65217_irq_enable,
@@ -149,8 +124,8 @@ static irqreturn_t tps65217_irq_thread(int irq, void *data)
return IRQ_NONE;
}
for (i = 0; i < ARRAY_SIZE(tps65217_irqs); i++) {
if (status & tps65217_irqs[i].interrupt) {
for (i = 0; i < TPS65217_NUM_IRQ; i++) {
if (status & BIT(i)) {
handle_nested_irq(irq_find_mapping(tps->irq_domain, i));
handled = true;
}
@@ -188,10 +163,9 @@ static int tps65217_irq_init(struct tps65217 *tps, int irq)
tps->irq = irq;
/* Mask all interrupt sources */
tps->irq_mask = (TPS65217_INT_RESERVEDM | TPS65217_INT_PBM
| TPS65217_INT_ACM | TPS65217_INT_USBM);
tps65217_reg_write(tps, TPS65217_REG_INT, tps->irq_mask,
TPS65217_PROTECT_NONE);
tps->irq_mask = TPS65217_INT_MASK;
tps65217_set_bits(tps, TPS65217_REG_INT, TPS65217_INT_MASK,
TPS65217_INT_MASK, TPS65217_PROTECT_NONE);
tps->irq_domain = irq_domain_add_linear(tps->dev->of_node,
TPS65217_NUM_IRQ, &tps65217_irq_domain_ops, tps);
@@ -209,6 +183,8 @@ static int tps65217_irq_init(struct tps65217 *tps, int irq)
return ret;
}
enable_irq_wake(irq);
return 0;
}
@@ -424,6 +400,24 @@ static int tps65217_probe(struct i2c_client *client,
return 0;
}
static int tps65217_remove(struct i2c_client *client)
{
struct tps65217 *tps = i2c_get_clientdata(client);
unsigned int virq;
int i;
for (i = 0; i < TPS65217_NUM_IRQ; i++) {
virq = irq_find_mapping(tps->irq_domain, i);
if (virq)
irq_dispose_mapping(virq);
}
irq_domain_remove(tps->irq_domain);
tps->irq_domain = NULL;
return 0;
}
static const struct i2c_device_id tps65217_id_table[] = {
{"tps65217", TPS65217},
{ /* sentinel */ }
@@ -437,6 +431,7 @@ static struct i2c_driver tps65217_driver = {
},
.id_table = tps65217_id_table,
.probe = tps65217_probe,
.remove = tps65217_remove,
};
static int __init tps65217_init(void)

View File

@@ -33,19 +33,17 @@
#define TPS65218_PASSWORD_REGS_UNLOCK 0x7D
/**
* tps65218_reg_read: Read a single tps65218 register.
*
* @tps: Device to read from.
* @reg: Register to read.
* @val: Contians the value
*/
int tps65218_reg_read(struct tps65218 *tps, unsigned int reg,
unsigned int *val)
{
return regmap_read(tps->regmap, reg, val);
}
EXPORT_SYMBOL_GPL(tps65218_reg_read);
static const struct mfd_cell tps65218_cells[] = {
{
.name = "tps65218-pwrbutton",
.of_compatible = "ti,tps65218-pwrbutton",
},
{
.name = "tps65218-gpio",
.of_compatible = "ti,tps65218-gpio",
},
{ .name = "tps65218-regulator", },
};
/**
* tps65218_reg_write: Write a single tps65218 register.
@@ -93,7 +91,7 @@ static int tps65218_update_bits(struct tps65218 *tps, unsigned int reg,
int ret;
unsigned int data;
ret = tps65218_reg_read(tps, reg, &data);
ret = regmap_read(tps->regmap, reg, &data);
if (ret) {
dev_err(tps->dev, "Read from reg 0x%x failed\n", reg);
return ret;
@@ -251,7 +249,7 @@ static int tps65218_probe(struct i2c_client *client,
if (ret < 0)
return ret;
ret = tps65218_reg_read(tps, TPS65218_REG_CHIPID, &chipid);
ret = regmap_read(tps->regmap, TPS65218_REG_CHIPID, &chipid);
if (ret) {
dev_err(tps->dev, "Failed to read chipid: %d\n", ret);
return ret;
@@ -259,8 +257,10 @@ static int tps65218_probe(struct i2c_client *client,
tps->rev = chipid & TPS65218_CHIPID_REV_MASK;
ret = of_platform_populate(client->dev.of_node, NULL, NULL,
&client->dev);
ret = mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, tps65218_cells,
ARRAY_SIZE(tps65218_cells), NULL, 0,
regmap_irq_get_domain(tps->irq_data));
if (ret < 0)
goto err_irq;

View File

@@ -77,6 +77,23 @@ static struct regmap_irq_chip tps65912_irq_chip = {
.init_ack_masked = true,
};
static const struct regmap_range tps65912_yes_ranges[] = {
regmap_reg_range(TPS65912_INT_STS, TPS65912_GPIO5),
};
static const struct regmap_access_table tps65912_volatile_table = {
.yes_ranges = tps65912_yes_ranges,
.n_yes_ranges = ARRAY_SIZE(tps65912_yes_ranges),
};
const struct regmap_config tps65912_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.cache_type = REGCACHE_RBTREE,
.volatile_table = &tps65912_volatile_table,
};
EXPORT_SYMBOL_GPL(tps65912_regmap_config);
int tps65912_device_init(struct tps65912 *tps)
{
int ret;

File diff suppressed because it is too large Load Diff

View File

@@ -406,8 +406,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
goto err;
}
ret = regulator_bulk_enable(wm8994->num_supplies,
wm8994->supplies);
ret = regulator_bulk_enable(wm8994->num_supplies, wm8994->supplies);
if (ret != 0) {
dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret);
goto err_regulator_free;
@@ -612,8 +611,7 @@ static void wm8994_device_exit(struct wm8994 *wm8994)
{
pm_runtime_disable(wm8994->dev);
wm8994_irq_exit(wm8994);
regulator_bulk_disable(wm8994->num_supplies,
wm8994->supplies);
regulator_bulk_disable(wm8994->num_supplies, wm8994->supplies);
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
mfd_remove_devices(wm8994->dev);
}