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:
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -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");
|
||||
|
@@ -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");
|
||||
|
@@ -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");
|
||||
|
@@ -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");
|
||||
|
@@ -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");
|
||||
|
@@ -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");
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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,
|
||||
};
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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:
|
||||
|
@@ -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,
|
||||
|
@@ -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 = {
|
||||
|
@@ -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 = {
|
||||
|
@@ -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)
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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
181
drivers/mfd/sun4i-gpadc.c
Normal 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");
|
@@ -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)
|
||||
{
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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
@@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user