From 150932506af3485add62ca7bc3b984ff63012693 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 14 May 2016 19:51:28 +0200 Subject: mfd: axp20x: Extend axp22x_volatile_ranges The axp22x pmic has a bunch of volatile registers besides the interrupt ones, extend axp22x_volatile_ranges with these. Signed-off-by: Hans de Goede Signed-off-by: Lee Jones --- drivers/mfd/axp20x.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index e4e32978c377..ca04361a0ecd 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -93,7 +93,10 @@ static const struct regmap_range axp22x_writeable_ranges[] = { }; 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(AXP20X_FG_RES, AXP20X_FG_RES), }; static const struct regmap_access_table axp22x_writeable_table = { -- cgit v1.2.3-58-ga151 From 38f70da3c93205b5b47342c900b6507aa358736f Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 2 Jun 2016 20:39:50 -0400 Subject: mfd: max77843: Make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/mfd/Kconfig:config MFD_MAX77843 drivers/mfd/Kconfig: bool "Maxim Semiconductor MAX77843 PMIC Support" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_i2c_driver() uses the same init level priority as builtin_i2c_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. Signed-off-by: Paul Gortmaker Signed-off-by: Lee Jones --- drivers/mfd/max77843.c | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/max77843.c b/drivers/mfd/max77843.c index 7cfc95b49c5d..dc5caeaaa6a1 100644 --- a/drivers/mfd/max77843.c +++ b/drivers/mfd/max77843.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -171,19 +171,6 @@ err_pmic_id: return ret; } -static int max77843_remove(struct i2c_client *i2c) -{ - struct max77693_dev *max77843 = i2c_get_clientdata(i2c); - - mfd_remove_devices(max77843->dev); - - regmap_del_irq_chip(max77843->irq, max77843->irq_data_topsys); - - i2c_unregister_device(max77843->i2c_chg); - - return 0; -} - static const struct of_device_id max77843_dt_match[] = { { .compatible = "maxim,max77843", }, { }, @@ -193,7 +180,6 @@ static const struct i2c_device_id max77843_id[] = { { "max77843", TYPE_MAX77843, }, { }, }; -MODULE_DEVICE_TABLE(i2c, max77843_id); static int __maybe_unused max77843_suspend(struct device *dev) { @@ -226,9 +212,9 @@ static struct i2c_driver max77843_i2c_driver = { .name = "max77843", .pm = &max77843_pm, .of_match_table = max77843_dt_match, + .suppress_bind_attrs = true, }, .probe = max77843_probe, - .remove = max77843_remove, .id_table = max77843_id, }; @@ -237,9 +223,3 @@ static int __init max77843_i2c_init(void) return i2c_add_driver(&max77843_i2c_driver); } subsys_initcall(max77843_i2c_init); - -static void __exit max77843_i2c_exit(void) -{ - i2c_del_driver(&max77843_i2c_driver); -} -module_exit(max77843_i2c_exit); -- cgit v1.2.3-58-ga151 From c1fe7c45260d0ee0e8caca722b469bb4dbd7cdab Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 2 Jun 2016 20:39:49 -0400 Subject: mfd: max77620: Make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/mfd/Kconfig:config MFD_MAX77620 drivers/mfd/Kconfig: bool "Maxim Semiconductor MAX77620 and MAX20024 PMIC Support" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_i2c_driver() uses the same init level priority as builtin_i2c_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Signed-off-by: Paul Gortmaker Signed-off-by: Lee Jones --- drivers/mfd/max77620.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c index 199d261990be..84a830598fc9 100644 --- a/drivers/mfd/max77620.c +++ b/drivers/mfd/max77620.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -566,7 +566,6 @@ static const struct i2c_device_id max77620_id[] = { {"max20024", MAX20024}, {}, }; -MODULE_DEVICE_TABLE(i2c, max77620_id); static const struct dev_pm_ops max77620_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(max77620_i2c_suspend, max77620_i2c_resume) @@ -580,11 +579,4 @@ static struct i2c_driver max77620_driver = { .probe = max77620_probe, .id_table = max77620_id, }; - -module_i2c_driver(max77620_driver); - -MODULE_DESCRIPTION("MAX77620/MAX20024 Multi Function Device Core Driver"); -MODULE_AUTHOR("Laxman Dewangan "); -MODULE_AUTHOR("Chaitanya Bandi "); -MODULE_AUTHOR("Mallikarjun Kasoju "); -MODULE_LICENSE("GPL v2"); +builtin_i2c_driver(max77620_driver); -- cgit v1.2.3-58-ga151 From b9e38338e45af568723dcac909c30f5b7e7f5df1 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 2 Jun 2016 20:39:48 -0400 Subject: mfd: max8998: Make it explicitly non-modular The Kconfig currently controlling compilation of this code is: mfd/Kconfig:config MFD_MAX8998 mfd/Kconfig: bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. We delete the include of module.h as well as an unused include of moduleparam.h too. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Signed-off-by: Paul Gortmaker Signed-off-by: Lee Jones --- drivers/mfd/max8998.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index ab28b29400f6..4c33b8063bc3 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c @@ -21,8 +21,6 @@ */ #include -#include -#include #include #include #include @@ -138,7 +136,6 @@ static const struct of_device_id max8998_dt_match[] = { { .compatible = "ti,lp3974", .data = (void *)TYPE_LP3974 }, {}, }; -MODULE_DEVICE_TABLE(of, max8998_dt_match); #endif /* @@ -254,23 +251,11 @@ err: return ret; } -static int max8998_i2c_remove(struct i2c_client *i2c) -{ - struct max8998_dev *max8998 = i2c_get_clientdata(i2c); - - mfd_remove_devices(max8998->dev); - max8998_irq_exit(max8998); - i2c_unregister_device(max8998->rtc); - - return 0; -} - static const struct i2c_device_id max8998_i2c_id[] = { { "max8998", TYPE_MAX8998 }, { "lp3974", TYPE_LP3974}, { } }; -MODULE_DEVICE_TABLE(i2c, max8998_i2c_id); static int max8998_suspend(struct device *dev) { @@ -378,10 +363,10 @@ static struct i2c_driver max8998_i2c_driver = { .driver = { .name = "max8998", .pm = &max8998_pm, + .suppress_bind_attrs = true, .of_match_table = of_match_ptr(max8998_dt_match), }, .probe = max8998_i2c_probe, - .remove = max8998_i2c_remove, .id_table = max8998_i2c_id, }; @@ -391,13 +376,3 @@ static int __init max8998_i2c_init(void) } /* init early so consumer devices can complete system boot */ subsys_initcall(max8998_i2c_init); - -static void __exit max8998_i2c_exit(void) -{ - i2c_del_driver(&max8998_i2c_driver); -} -module_exit(max8998_i2c_exit); - -MODULE_DESCRIPTION("MAXIM 8998 multi-function core driver"); -MODULE_AUTHOR("Kyungmin Park "); -MODULE_LICENSE("GPL"); -- cgit v1.2.3-58-ga151 From 9cf0c21f4000545ec388fe7f421ac5373e657167 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 2 Jun 2016 20:39:47 -0400 Subject: mfd: max8997: Make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/mfd/Kconfig:config MFD_MAX8997 drivers/mfd/Kconfig: bool "Maxim Semiconductor MAX8997/8966 PMIC Support" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Signed-off-by: Paul Gortmaker Signed-off-by: Lee Jones --- drivers/mfd/max8997.c | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index f316348e3d98..2d6e2c392786 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -2,7 +2,7 @@ * max8997.c - mfd core driver for the Maxim 8966 and 8997 * * Copyright (C) 2011 Samsung Electronics - * MyungJoo Ham + * MyungJoo Ham * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -55,7 +55,6 @@ static const struct of_device_id max8997_pmic_dt_match[] = { { .compatible = "maxim,max8997-pmic", .data = (void *)TYPE_MAX8997 }, {}, }; -MODULE_DEVICE_TABLE(of, max8997_pmic_dt_match); #endif int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest) @@ -263,24 +262,11 @@ err_i2c_haptic: return ret; } -static int max8997_i2c_remove(struct i2c_client *i2c) -{ - struct max8997_dev *max8997 = i2c_get_clientdata(i2c); - - mfd_remove_devices(max8997->dev); - i2c_unregister_device(max8997->muic); - i2c_unregister_device(max8997->haptic); - i2c_unregister_device(max8997->rtc); - - return 0; -} - static const struct i2c_device_id max8997_i2c_id[] = { { "max8997", TYPE_MAX8997 }, { "max8966", TYPE_MAX8966 }, { } }; -MODULE_DEVICE_TABLE(i2c, max8998_i2c_id); static u8 max8997_dumpaddr_pmic[] = { MAX8997_REG_INT1MSK, @@ -510,10 +496,10 @@ static struct i2c_driver max8997_i2c_driver = { .driver = { .name = "max8997", .pm = &max8997_pm, + .suppress_bind_attrs = true, .of_match_table = of_match_ptr(max8997_pmic_dt_match), }, .probe = max8997_i2c_probe, - .remove = max8997_i2c_remove, .id_table = max8997_i2c_id, }; @@ -523,13 +509,3 @@ static int __init max8997_i2c_init(void) } /* init early so consumer devices can complete system boot */ subsys_initcall(max8997_i2c_init); - -static void __exit max8997_i2c_exit(void) -{ - i2c_del_driver(&max8997_i2c_driver); -} -module_exit(max8997_i2c_exit); - -MODULE_DESCRIPTION("MAXIM 8997 multi-function core driver"); -MODULE_AUTHOR("MyungJoo Ham "); -MODULE_LICENSE("GPL"); -- cgit v1.2.3-58-ga151 From 9eb5f9ba17e9b95b37f8eebbdef82e26123fa424 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 2 Jun 2016 20:39:46 -0400 Subject: mfd: max8925-i2c: Make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/mfd/Kconfig: config MFD_MAX8925 drivers/mfd/Kconfig: bool "Maxim Semiconductor MAX8925 PMIC Support" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Signed-off-by: Paul Gortmaker Signed-off-by: Lee Jones --- drivers/mfd/max8925-i2c.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c index 70443b161a5b..5c80aea3211f 100644 --- a/drivers/mfd/max8925-i2c.c +++ b/drivers/mfd/max8925-i2c.c @@ -9,7 +9,7 @@ * published by the Free Software Foundation. */ #include -#include +#include #include #include #include @@ -133,7 +133,6 @@ static const struct i2c_device_id max8925_id_table[] = { { "max8925", 0 }, { }, }; -MODULE_DEVICE_TABLE(i2c, max8925_id_table); static int max8925_dt_init(struct device_node *np, struct device *dev, struct max8925_platform_data *pdata) @@ -240,7 +239,6 @@ static const struct of_device_id max8925_dt_ids[] = { { .compatible = "maxim,max8925", }, {}, }; -MODULE_DEVICE_TABLE(of, max8925_dt_ids); static struct i2c_driver max8925_driver = { .driver = { @@ -264,13 +262,3 @@ static int __init max8925_i2c_init(void) return ret; } subsys_initcall(max8925_i2c_init); - -static void __exit max8925_i2c_exit(void) -{ - i2c_del_driver(&max8925_driver); -} -module_exit(max8925_i2c_exit); - -MODULE_DESCRIPTION("I2C Driver for Maxim 8925"); -MODULE_AUTHOR("Haojian Zhuang "); -MODULE_LICENSE("GPL"); -- cgit v1.2.3-58-ga151 From 521d93579f863b04fa5eb492f4b14b220d44dd19 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 4 Jun 2016 20:19:58 +0100 Subject: mfd: si476x-i2c: Fix spelling mistake "comptible" -> "compatible" trivial fix to spelling mistake in dev_err message Signed-off-by: Colin Ian King Signed-off-by: Lee Jones --- drivers/mfd/si476x-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c index fb4ce6d04c30..c180b7533bba 100644 --- a/drivers/mfd/si476x-i2c.c +++ b/drivers/mfd/si476x-i2c.c @@ -600,7 +600,7 @@ static int si476x_core_fwver_to_revision(struct si476x_core *core, unknown_revision: dev_err(&core->client->dev, "Unsupported version of the firmware: %d.%d.%d, " - "reverting to A10 comptible functions\n", + "reverting to A10 compatible functions\n", major, minor1, minor2); return SI476X_REVISION_A10; -- cgit v1.2.3-58-ga151 From 2be59755e66d34f46001ca19224ab4cefb212c51 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 5 Jun 2016 16:28:17 +0800 Subject: mfd: max77620: Constify resources tables These tables are never modified, so declare them as const. Signed-off-by: Axel Lin Signed-off-by: Lee Jones --- drivers/mfd/max77620.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c index 84a830598fc9..d4688f3cfe02 100644 --- a/drivers/mfd/max77620.c +++ b/drivers/mfd/max77620.c @@ -37,19 +37,19 @@ #include #include -static struct resource gpio_resources[] = { +static const struct resource gpio_resources[] = { DEFINE_RES_IRQ(MAX77620_IRQ_TOP_GPIO), }; -static struct resource power_resources[] = { +static const struct resource power_resources[] = { DEFINE_RES_IRQ(MAX77620_IRQ_LBT_MBATLOW), }; -static struct resource rtc_resources[] = { +static const struct resource rtc_resources[] = { DEFINE_RES_IRQ(MAX77620_IRQ_TOP_RTC), }; -static struct resource thermal_resources[] = { +static const struct resource thermal_resources[] = { DEFINE_RES_IRQ(MAX77620_IRQ_LBT_TJALRM1), DEFINE_RES_IRQ(MAX77620_IRQ_LBT_TJALRM2), }; -- cgit v1.2.3-58-ga151 From 179dc63d06c51a78483dedbdf34540af053a6269 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 5 Jun 2016 15:50:48 +0200 Subject: mfd: axp20x: Add a 500ms delay at the end of axp20x_power_off The kernel expects the power_off function to not return, and if it does it panics. Add a slight delay after the i2c write which turns off power through the PMIC, to give capacitors etc. some time to drain. Without this the kernel lives on long enough after the poweroff to print the following on the serial console on my Mele A1000G quad: [ 248.583588] reboot: Power down [ 248.600490] Kernel pa With the delay the start of printing "Kernel panic" is gone. Signed-off-by: Hans de Goede Acked-by: Chen-Yu Tsai Signed-off-by: Lee Jones --- drivers/mfd/axp20x.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index ca04361a0ecd..a1ed43ea95aa 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -667,6 +668,9 @@ static void axp20x_power_off(void) regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL, AXP20X_OFF); + + /* Give capacitors etc. time to drain to avoid kernel panic msg. */ + msleep(500); } int axp20x_match_device(struct axp20x_dev *axp20x) -- cgit v1.2.3-58-ga151 From 17ed4d2240f99ab4ebc6fbb6b94a106eed46f9df Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 8 Jun 2016 19:06:20 +0100 Subject: mfd: omap-usb-tll: Include omap-usb.h Fix the warnings about the following functions not being declared by including omap-usb.h which declares them: drivers/mfd/omap-usb-tll.c:333:5: warning: symbol 'omap_tll_init' was not declared. Should it be static? drivers/mfd/omap-usb-tll.c:408:5: warning: symbol 'omap_tll_enable' was not declared. Should it be static? drivers/mfd/omap-usb-tll.c:442:5: warning: symbol 'omap_tll_disable' was not declared. Should it be static? Signed-off-by: Ben Dooks Signed-off-by: Lee Jones --- drivers/mfd/omap-usb-tll.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index c30290f33430..1aa74c4c3ced 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c @@ -30,6 +30,8 @@ #include #include +#include "omap-usb.h" + #define USBTLL_DRIVER_NAME "usbhs_tll" /* TLL Register Set */ -- cgit v1.2.3-58-ga151 From dea1c703f12ee1d141883f4702cf1f7dee32b860 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Wed, 8 Jun 2016 10:54:36 -0500 Subject: mfd: ti_am335x_tscadc: Use variable name for sizeof() operator Fix the code formatting to use the kernel preferred style of using the actual variables to determine the size using the sizeof() operator. Signed-off-by: Andrew F. Davis Signed-off-by: Lee Jones --- drivers/mfd/ti_am335x_tscadc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index e4e4b22eebc9..3eb987fe2cf5 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -182,8 +182,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) } /* Allocate memory for device */ - tscadc = devm_kzalloc(&pdev->dev, - sizeof(struct ti_tscadc_dev), GFP_KERNEL); + tscadc = devm_kzalloc(&pdev->dev, sizeof(*tscadc), GFP_KERNEL); if (!tscadc) { dev_err(&pdev->dev, "failed to allocate memory.\n"); return -ENOMEM; -- cgit v1.2.3-58-ga151 From 86bda6a900f257c2c910894a743f27967d784fd4 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Wed, 8 Jun 2016 10:54:33 -0500 Subject: mfd: ti_am335x_tscadc: Remove use of single line functions tscadc_readl and tscadc_writel are single line functions and do not save use anything, remove these. Signed-off-by: Andrew F. Davis Signed-off-by: Lee Jones --- drivers/mfd/ti_am335x_tscadc.c | 44 ++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 3eb987fe2cf5..3d4fbc85800e 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -27,20 +27,6 @@ #include -static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg) -{ - unsigned int val; - - regmap_read(tsadc->regmap_tscadc, reg, &val); - return val; -} - -static void tscadc_writel(struct ti_tscadc_dev *tsadc, unsigned int reg, - unsigned int val) -{ - regmap_write(tsadc->regmap_tscadc, reg, val); -} - static const struct regmap_config tscadc_regmap_config = { .name = "ti_tscadc", .reg_bits = 32, @@ -57,7 +43,7 @@ void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val) if (tsadc->adc_waiting) wake_up(&tsadc->reg_se_wait); else if (!tsadc->adc_in_use) - tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); + regmap_write(tsadc->regmap_tscadc, REG_SE, tsadc->reg_se_cache); spin_unlock_irqrestore(&tsadc->reg_lock, flags); } @@ -68,7 +54,7 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc) DEFINE_WAIT(wait); u32 reg; - reg = tscadc_readl(tsadc, REG_ADCFSM); + regmap_read(tsadc->regmap_tscadc, REG_ADCFSM, ®); if (reg & SEQ_STATUS) { tsadc->adc_waiting = true; prepare_to_wait(&tsadc->reg_se_wait, &wait, @@ -84,7 +70,7 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc) * Sequencer should either be idle or * busy applying the charge step. */ - reg = tscadc_readl(tsadc, REG_ADCFSM); + regmap_read(tsadc->regmap_tscadc, REG_ADCFSM, ®); WARN_ON((reg & SEQ_STATUS) && !(reg & CHARGE_STEP)); tsadc->adc_waiting = false; } @@ -96,7 +82,7 @@ void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val) spin_lock_irq(&tsadc->reg_lock); am335x_tscadc_need_adc(tsadc); - tscadc_writel(tsadc, REG_SE, val); + regmap_write(tsadc->regmap_tscadc, REG_SE, val); spin_unlock_irq(&tsadc->reg_lock); } EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once); @@ -107,7 +93,7 @@ void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tsadc) spin_lock_irqsave(&tsadc->reg_lock, flags); tsadc->adc_in_use = false; - tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); + regmap_write(tsadc->regmap_tscadc, REG_SE, tsadc->reg_se_cache); spin_unlock_irqrestore(&tsadc->reg_lock, flags); } EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done); @@ -118,7 +104,7 @@ void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val) spin_lock_irqsave(&tsadc->reg_lock, flags); tsadc->reg_se_cache &= ~val; - tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); + regmap_write(tsadc->regmap_tscadc, REG_SE, tsadc->reg_se_cache); spin_unlock_irqrestore(&tsadc->reg_lock, flags); } EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); @@ -130,7 +116,7 @@ static void tscadc_idle_config(struct ti_tscadc_dev *config) idleconfig = STEPCONFIG_YNN | STEPCONFIG_INM_ADCREFM | STEPCONFIG_INP_ADCREFM | STEPCONFIG_YPN; - tscadc_writel(config, REG_IDLECONFIG, idleconfig); + regmap_write(config->regmap_tscadc, REG_IDLECONFIG, idleconfig); } static int ti_tscadc_probe(struct platform_device *pdev) @@ -235,11 +221,11 @@ static int ti_tscadc_probe(struct platform_device *pdev) /* TSCADC_CLKDIV needs to be configured to the value minus 1 */ tscadc->clk_div--; - tscadc_writel(tscadc, REG_CLKDIV, tscadc->clk_div); + regmap_write(tscadc->regmap_tscadc, REG_CLKDIV, tscadc->clk_div); /* Set the control register bits */ ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID; - tscadc_writel(tscadc, REG_CTRL, ctrl); + regmap_write(tscadc->regmap_tscadc, REG_CTRL, ctrl); /* Set register bits for Idle Config Mode */ if (tsc_wires > 0) { @@ -253,7 +239,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) /* Enable the TSC module enable bit */ ctrl |= CNTRLREG_TSCSSENB; - tscadc_writel(tscadc, REG_CTRL, ctrl); + regmap_write(tscadc->regmap_tscadc, REG_CTRL, ctrl); tscadc->used_cells = 0; tscadc->tsc_cell = -1; @@ -299,7 +285,7 @@ static int ti_tscadc_remove(struct platform_device *pdev) { struct ti_tscadc_dev *tscadc = platform_get_drvdata(pdev); - tscadc_writel(tscadc, REG_SE, 0x00); + regmap_write(tscadc->regmap_tscadc, REG_SE, 0x00); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -314,7 +300,7 @@ static int tscadc_suspend(struct device *dev) { struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev); - tscadc_writel(tscadc_dev, REG_SE, 0x00); + regmap_write(tscadc_dev->regmap_tscadc, REG_SE, 0x00); pm_runtime_put_sync(dev); return 0; @@ -329,7 +315,7 @@ static int tscadc_resume(struct device *dev) /* context restore */ ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID; - tscadc_writel(tscadc_dev, REG_CTRL, ctrl); + regmap_write(tscadc_dev->regmap_tscadc, REG_CTRL, ctrl); if (tscadc_dev->tsc_cell != -1) { if (tscadc_dev->tsc_wires == 5) @@ -339,9 +325,9 @@ static int tscadc_resume(struct device *dev) tscadc_idle_config(tscadc_dev); } ctrl |= CNTRLREG_TSCSSENB; - tscadc_writel(tscadc_dev, REG_CTRL, ctrl); + regmap_write(tscadc_dev->regmap_tscadc, REG_CTRL, ctrl); - tscadc_writel(tscadc_dev, REG_CLKDIV, tscadc_dev->clk_div); + regmap_write(tscadc_dev->regmap_tscadc, REG_CLKDIV, tscadc_dev->clk_div); return 0; } -- cgit v1.2.3-58-ga151 From dae936a090e5778c6c0b6494b05d1c0aba142e1c Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Wed, 8 Jun 2016 10:54:32 -0500 Subject: mfd: ti_am335x_tscadc: Use SIMPLE_DEV_PM_OPS helper macro Replace ifdefs with SIMPLE_DEV_PM_OPS helper macro. Signed-off-by: Andrew F. Davis Signed-off-by: Lee Jones --- drivers/mfd/ti_am335x_tscadc.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 3d4fbc85800e..f147fe780a0f 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -295,8 +295,7 @@ static int ti_tscadc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int tscadc_suspend(struct device *dev) +static int __maybe_unused tscadc_suspend(struct device *dev) { struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev); @@ -306,7 +305,7 @@ static int tscadc_suspend(struct device *dev) return 0; } -static int tscadc_resume(struct device *dev) +static int __maybe_unused tscadc_resume(struct device *dev) { struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev); u32 ctrl; @@ -332,14 +331,7 @@ static int tscadc_resume(struct device *dev) return 0; } -static const struct dev_pm_ops tscadc_pm_ops = { - .suspend = tscadc_suspend, - .resume = tscadc_resume, -}; -#define TSCADC_PM_OPS (&tscadc_pm_ops) -#else -#define TSCADC_PM_OPS NULL -#endif +static SIMPLE_DEV_PM_OPS(tscadc_pm_ops, tscadc_suspend, tscadc_resume); static const struct of_device_id ti_tscadc_dt_ids[] = { { .compatible = "ti,am3359-tscadc", }, @@ -350,7 +342,7 @@ MODULE_DEVICE_TABLE(of, ti_tscadc_dt_ids); static struct platform_driver ti_tscadc_driver = { .driver = { .name = "ti_am3359-tscadc", - .pm = TSCADC_PM_OPS, + .pm = &tscadc_pm_ops, .of_match_table = ti_tscadc_dt_ids, }, .probe = ti_tscadc_probe, -- cgit v1.2.3-58-ga151 From 7657c9fb1e356b89f80f5454cb12691594807234 Mon Sep 17 00:00:00 2001 From: Ben Copeland Date: Thu, 9 Jun 2016 16:25:50 +0100 Subject: mfd: tps6507: Fix white space warnings reported by checkpatch WARNING: please, no spaces at the start of a line + { "tps6507x", 0 },$ WARNING: please, no spaces at the start of a line + { }$ Signed-off-by: Ben Copeland Signed-off-by: Lee Jones --- drivers/mfd/tps6507x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index 40beb2f4350c..1f308c4e3694 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c @@ -105,8 +105,8 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c, } static const struct i2c_device_id tps6507x_i2c_id[] = { - { "tps6507x", 0 }, - { } + { "tps6507x", 0 }, + { } }; MODULE_DEVICE_TABLE(i2c, tps6507x_i2c_id); -- cgit v1.2.3-58-ga151 From 9787f5e28b50774f1d5672e33b277ba1e9aa0753 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Thu, 2 Jun 2016 12:52:23 -0500 Subject: mfd: altr_a10sr: Add Altera Arria10 DevKit System Resource Chip Add support for the Altera Arria10 Development Kit System Resource chip which is implemented using a MAX5 as a external gpio extender with the regmap framework over a SPI bus. Signed-off-by: Thor Thayer Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 11 +++ drivers/mfd/Makefile | 2 + drivers/mfd/altera-a10sr.c | 169 +++++++++++++++++++++++++++++++++++++++ include/linux/mfd/altera-a10sr.h | 85 ++++++++++++++++++++ 4 files changed, 267 insertions(+) create mode 100644 drivers/mfd/altera-a10sr.c create mode 100644 include/linux/mfd/altera-a10sr.h (limited to 'drivers') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index ff031a7735a5..9402399bb3d6 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -18,6 +18,17 @@ config MFD_CS5535 This is the core driver for CS5535/CS5536 MFD functions. This is necessary for using the board's GPIO and MFGPT functionality. +config MFD_ALTERA_A10SR + bool "Altera Arria10 DevKit System Resource chip" + depends on ARCH_SOCFPGA && SPI_MASTER=y && OF + select REGMAP_SPI + select MFD_CORE + help + Support for the Altera Arria10 DevKit MAX5 System Resource chip + using the SPI interface. This driver provides common support for + accessing the external gpio extender (LEDs & buttons) and + power supply alarms (hwmon). + config MFD_ACT8945A tristate "Active-semi ACT8945A" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 42a66e19e191..2ba3ba35f745 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -205,3 +205,5 @@ intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC) += intel_soc_pmic_bxtwc.o obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o obj-$(CONFIG_MFD_MT6397) += mt6397-core.o + +obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o diff --git a/drivers/mfd/altera-a10sr.c b/drivers/mfd/altera-a10sr.c new file mode 100644 index 000000000000..c05aa4ff57fd --- /dev/null +++ b/drivers/mfd/altera-a10sr.c @@ -0,0 +1,169 @@ +/* + * Copyright Intel Corporation (C) 2014-2016. All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * SPI access for Altera Arria10 MAX5 System Resource Chip + * + * Adapted from DA9052 + */ + +#include +#include +#include +#include +#include + +static const struct mfd_cell altr_a10sr_subdev_info[] = { + { + .name = "altr_a10sr_gpio", + .of_compatible = "altr,a10sr-gpio", + }, +}; + +static bool altr_a10sr_reg_readable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ALTR_A10SR_VERSION_READ: + case ALTR_A10SR_LED_REG: + case ALTR_A10SR_PBDSW_REG: + case ALTR_A10SR_PBDSW_IRQ_REG: + case ALTR_A10SR_PWR_GOOD1_REG: + case ALTR_A10SR_PWR_GOOD2_REG: + case ALTR_A10SR_PWR_GOOD3_REG: + case ALTR_A10SR_FMCAB_REG: + case ALTR_A10SR_HPS_RST_REG: + case ALTR_A10SR_USB_QSPI_REG: + case ALTR_A10SR_SFPA_REG: + case ALTR_A10SR_SFPB_REG: + case ALTR_A10SR_I2C_M_REG: + case ALTR_A10SR_WARM_RST_REG: + case ALTR_A10SR_WR_KEY_REG: + case ALTR_A10SR_PMBUS_REG: + return true; + default: + return false; + } +} + +static bool altr_a10sr_reg_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ALTR_A10SR_LED_REG: + case ALTR_A10SR_PBDSW_IRQ_REG: + case ALTR_A10SR_FMCAB_REG: + case ALTR_A10SR_HPS_RST_REG: + case ALTR_A10SR_USB_QSPI_REG: + case ALTR_A10SR_SFPA_REG: + case ALTR_A10SR_SFPB_REG: + case ALTR_A10SR_WARM_RST_REG: + case ALTR_A10SR_WR_KEY_REG: + case ALTR_A10SR_PMBUS_REG: + return true; + default: + return false; + } +} + +static bool altr_a10sr_reg_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ALTR_A10SR_PBDSW_REG: + case ALTR_A10SR_PBDSW_IRQ_REG: + case ALTR_A10SR_PWR_GOOD1_REG: + case ALTR_A10SR_PWR_GOOD2_REG: + case ALTR_A10SR_PWR_GOOD3_REG: + case ALTR_A10SR_HPS_RST_REG: + case ALTR_A10SR_I2C_M_REG: + case ALTR_A10SR_WARM_RST_REG: + case ALTR_A10SR_WR_KEY_REG: + case ALTR_A10SR_PMBUS_REG: + return true; + default: + return false; + } +} + +const struct regmap_config altr_a10sr_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .cache_type = REGCACHE_NONE, + + .use_single_rw = true, + .read_flag_mask = 1, + .write_flag_mask = 0, + + .max_register = ALTR_A10SR_WR_KEY_REG, + .readable_reg = altr_a10sr_reg_readable, + .writeable_reg = altr_a10sr_reg_writeable, + .volatile_reg = altr_a10sr_reg_volatile, + +}; + +static int altr_a10sr_spi_probe(struct spi_device *spi) +{ + int ret; + struct altr_a10sr *a10sr; + + a10sr = devm_kzalloc(&spi->dev, sizeof(*a10sr), + GFP_KERNEL); + if (!a10sr) + return -ENOMEM; + + spi->mode = SPI_MODE_3; + spi->bits_per_word = 8; + spi_setup(spi); + + a10sr->dev = &spi->dev; + + spi_set_drvdata(spi, a10sr); + + a10sr->regmap = devm_regmap_init_spi(spi, &altr_a10sr_regmap_config); + if (IS_ERR(a10sr->regmap)) { + ret = PTR_ERR(a10sr->regmap); + dev_err(&spi->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + ret = devm_mfd_add_devices(a10sr->dev, PLATFORM_DEVID_AUTO, + altr_a10sr_subdev_info, + ARRAY_SIZE(altr_a10sr_subdev_info), + NULL, 0, NULL); + if (ret) + dev_err(a10sr->dev, "Failed to register sub-devices: %d\n", + ret); + + return ret; +} + +static const struct of_device_id altr_a10sr_spi_of_match[] = { + { .compatible = "altr,a10sr" }, + { }, +}; +MODULE_DEVICE_TABLE(of, altr_a10sr_spi_of_match); + +static struct spi_driver altr_a10sr_spi_driver = { + .probe = altr_a10sr_spi_probe, + .driver = { + .name = "altr_a10sr", + .of_match_table = of_match_ptr(altr_a10sr_spi_of_match), + }, +}; + +module_spi_driver(altr_a10sr_spi_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Thor Thayer "); +MODULE_DESCRIPTION("Altera Arria10 DevKit System Resource MFD Driver"); diff --git a/include/linux/mfd/altera-a10sr.h b/include/linux/mfd/altera-a10sr.h new file mode 100644 index 000000000000..45a5e6e7db54 --- /dev/null +++ b/include/linux/mfd/altera-a10sr.h @@ -0,0 +1,85 @@ +/* + * Copyright Intel Corporation (C) 2014-2016. All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * Declarations for Altera Arria10 MAX5 System Resource Chip + * + * Adapted from DA9052 + */ + +#ifndef __MFD_ALTERA_A10SR_H +#define __MFD_ALTERA_A10SR_H + +#include +#include +#include +#include +#include + +/* Write registers are always on even addresses */ +#define WRITE_REG_MASK 0xFE +/* Odd registers are always on odd addresses */ +#define READ_REG_MASK 0x01 + +#define ALTR_A10SR_BITS_PER_REGISTER 8 +/* + * To find the correct register, we divide the input GPIO by + * the number of GPIO in each register. We then need to multiply + * by 2 because the reads are at odd addresses. + */ +#define ALTR_A10SR_REG_OFFSET(X) (((X) / ALTR_A10SR_BITS_PER_REGISTER) << 1) +#define ALTR_A10SR_REG_BIT(X) ((X) % ALTR_A10SR_BITS_PER_REGISTER) +#define ALTR_A10SR_REG_BIT_CHG(X, Y) ((X) << ALTR_A10SR_REG_BIT(Y)) +#define ALTR_A10SR_REG_BIT_MASK(X) (1 << ALTR_A10SR_REG_BIT(X)) + +/* Arria10 System Controller Register Defines */ +#define ALTR_A10SR_NOP 0x00 /* No Change */ +#define ALTR_A10SR_VERSION_READ 0x00 /* MAX5 Version Read */ + +#define ALTR_A10SR_LED_REG 0x02 /* LED - Upper 4 bits */ +/* LED register Bit Definitions */ +#define ALTR_A10SR_LED_VALID_SHIFT 4 /* LED - Upper 4 bits valid */ +#define ALTR_A10SR_OUT_VALID_RANGE_LO ALTR_A10SR_LED_VALID_SHIFT +#define ALTR_A10SR_OUT_VALID_RANGE_HI 7 + +#define ALTR_A10SR_PBDSW_REG 0x04 /* PB & DIP SW - Input only */ +#define ALTR_A10SR_PBDSW_IRQ_REG 0x06 /* PB & DIP SW Flag Clear */ +/* Pushbutton & DIP Switch Bit Definitions */ +#define ALTR_A10SR_IN_VALID_RANGE_LO 8 +#define ALTR_A10SR_IN_VALID_RANGE_HI 15 + +#define ALTR_A10SR_PWR_GOOD1_REG 0x08 /* Power Good1 Read */ +#define ALTR_A10SR_PWR_GOOD2_REG 0x0A /* Power Good2 Read */ +#define ALTR_A10SR_PWR_GOOD3_REG 0x0C /* Power Good3 Read */ +#define ALTR_A10SR_FMCAB_REG 0x0E /* FMCA/B & PCIe Pwr Enable */ +#define ALTR_A10SR_HPS_RST_REG 0x10 /* HPS Reset */ +#define ALTR_A10SR_USB_QSPI_REG 0x12 /* USB, BQSPI, FILE Reset */ +#define ALTR_A10SR_SFPA_REG 0x14 /* SFPA Control Reg */ +#define ALTR_A10SR_SFPB_REG 0x16 /* SFPB Control Reg */ +#define ALTR_A10SR_I2C_M_REG 0x18 /* I2C Master Select */ +#define ALTR_A10SR_WARM_RST_REG 0x1A /* HPS Warm Reset */ +#define ALTR_A10SR_WR_KEY_REG 0x1C /* HPS Warm Reset Key */ +#define ALTR_A10SR_PMBUS_REG 0x1E /* HPS PM Bus */ + +/** + * struct altr_a10sr - Altera Max5 MFD device private data structure + * @dev: : this device + * @regmap: the regmap assigned to the parent device. + */ +struct altr_a10sr { + struct device *dev; + struct regmap *regmap; +}; + +#endif /* __MFD_ALTERA_A10SR_H */ -- cgit v1.2.3-58-ga151 From ecd98ccefa1bb83865c358d96b98524bc70938a9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 2 Jun 2016 19:18:55 +0200 Subject: mfd: axp20x: Add axp20x-usb-power-supply for axp22x pmics Add axp20x-usb-power-supply for axp22x pmics. Signed-off-by: Hans de Goede Signed-off-by: Lee Jones --- drivers/mfd/axp20x.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index a1ed43ea95aa..fd80b0981f0f 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -161,6 +161,11 @@ static struct resource axp20x_usb_power_supply_resources[] = { DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"), }; +static struct resource axp22x_usb_power_supply_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"), + DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"), +}; + static struct resource axp22x_pek_resources[] = { { .name = "PEK_DBR", @@ -528,6 +533,11 @@ static struct mfd_cell axp22x_cells[] = { .resources = axp22x_pek_resources, }, { .name = "axp20x-regulator", + }, { + .name = "axp20x-usb-power-supply", + .of_compatible = "x-powers,axp221-usb-power-supply", + .num_resources = ARRAY_SIZE(axp22x_usb_power_supply_resources), + .resources = axp22x_usb_power_supply_resources, }, }; -- cgit v1.2.3-58-ga151 From 3df140d11c6dbf319f4e1bc034e202546fc5ec5c Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 9 Jun 2016 20:43:07 +0530 Subject: mfd: max77620: Mask/unmask interrupt before/after servicing it The programming guidelines of the MAX77620 for servicing interrupt is: 1. When interrupt occurs from PMIC, mask the PMIC interrupt by setting GLBLM. 2. Read IRQTOP and service the interrupt. 3. Once all interrupts has been checked and serviced, the interrupt service routine un-masks the hardware interrupt line by clearing GLBLM. Add the pre and post interrupt service handler for mask and unmask the global interrupt mask bit (for step 1 and 3) as callback from regmap-irq. Signed-off-by: Laxman Dewangan Signed-off-by: Lee Jones --- drivers/mfd/max77620.c | 55 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c index d4688f3cfe02..4276413a69c6 100644 --- a/drivers/mfd/max77620.c +++ b/drivers/mfd/max77620.c @@ -111,15 +111,6 @@ static const struct mfd_cell max20024_children[] = { }, }; -static struct regmap_irq_chip max77620_top_irq_chip = { - .name = "max77620-top", - .irqs = max77620_top_irqs, - .num_irqs = ARRAY_SIZE(max77620_top_irqs), - .num_regs = 2, - .status_base = MAX77620_REG_IRQTOP, - .mask_base = MAX77620_REG_IRQTOPM, -}; - static const struct regmap_range max77620_readable_ranges[] = { regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4), }; @@ -180,6 +171,51 @@ static const struct regmap_config max20024_regmap_config = { .volatile_table = &max77620_volatile_table, }; +/* + * MAX77620 and MAX20024 has the following steps of the interrupt handling + * for TOP interrupts: + * 1. When interrupt occurs from PMIC, mask the PMIC interrupt by setting GLBLM. + * 2. Read IRQTOP and service the interrupt. + * 3. Once all interrupts has been checked and serviced, the interrupt service + * routine un-masks the hardware interrupt line by clearing GLBLM. + */ +static int max77620_irq_global_mask(void *irq_drv_data) +{ + struct max77620_chip *chip = irq_drv_data; + int ret; + + ret = regmap_update_bits(chip->rmap, MAX77620_REG_INTENLBT, + MAX77620_GLBLM_MASK, MAX77620_GLBLM_MASK); + if (ret < 0) + dev_err(chip->dev, "Failed to set GLBLM: %d\n", ret); + + return ret; +} + +static int max77620_irq_global_unmask(void *irq_drv_data) +{ + struct max77620_chip *chip = irq_drv_data; + int ret; + + ret = regmap_update_bits(chip->rmap, MAX77620_REG_INTENLBT, + MAX77620_GLBLM_MASK, 0); + if (ret < 0) + dev_err(chip->dev, "Failed to reset GLBLM: %d\n", ret); + + return ret; +} + +static struct regmap_irq_chip max77620_top_irq_chip = { + .name = "max77620-top", + .irqs = max77620_top_irqs, + .num_irqs = ARRAY_SIZE(max77620_top_irqs), + .num_regs = 2, + .status_base = MAX77620_REG_IRQTOP, + .mask_base = MAX77620_REG_IRQTOPM, + .handle_pre_irq = max77620_irq_global_mask, + .handle_post_irq = max77620_irq_global_unmask, +}; + /* max77620_get_fps_period_reg_value: Get FPS bit field value from * requested periods. * MAX77620 supports the FPS period of 40, 80, 160, 320, 540, 1280, 2560 @@ -431,6 +467,7 @@ static int max77620_probe(struct i2c_client *client, if (ret < 0) return ret; + max77620_top_irq_chip.irq_drv_data = chip; ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq, IRQF_ONESHOT | IRQF_SHARED, chip->irq_base, &max77620_top_irq_chip, -- cgit v1.2.3-58-ga151 From a318b7d0fa9c28df057747d584caaac52115f026 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Wed, 8 Jun 2016 10:54:34 -0500 Subject: mfd: ti_am335x_tscadc: Unify variable naming when referencing ti_tscadc_dev All functions in this driver reference the same ti_tscadc_dev per device but use several different names for this structure pointer, this can be confusing when following the code. Use the name 'tscadc' everywhere. Signed-off-by: Andrew F. Davis Signed-off-by: Lee Jones --- drivers/mfd/ti_am335x_tscadc.c | 88 +++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index f147fe780a0f..e71f6092be61 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -34,89 +34,89 @@ static const struct regmap_config tscadc_regmap_config = { .val_bits = 32, }; -void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val) +void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tscadc, u32 val) { unsigned long flags; - spin_lock_irqsave(&tsadc->reg_lock, flags); - tsadc->reg_se_cache |= val; - if (tsadc->adc_waiting) - wake_up(&tsadc->reg_se_wait); - else if (!tsadc->adc_in_use) - regmap_write(tsadc->regmap_tscadc, REG_SE, tsadc->reg_se_cache); + spin_lock_irqsave(&tscadc->reg_lock, flags); + tscadc->reg_se_cache |= val; + if (tscadc->adc_waiting) + wake_up(&tscadc->reg_se_wait); + else if (!tscadc->adc_in_use) + regmap_write(tscadc->regmap_tscadc, REG_SE, tscadc->reg_se_cache); - spin_unlock_irqrestore(&tsadc->reg_lock, flags); + spin_unlock_irqrestore(&tscadc->reg_lock, flags); } EXPORT_SYMBOL_GPL(am335x_tsc_se_set_cache); -static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc) +static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tscadc) { DEFINE_WAIT(wait); u32 reg; - regmap_read(tsadc->regmap_tscadc, REG_ADCFSM, ®); + regmap_read(tscadc->regmap_tscadc, REG_ADCFSM, ®); if (reg & SEQ_STATUS) { - tsadc->adc_waiting = true; - prepare_to_wait(&tsadc->reg_se_wait, &wait, + tscadc->adc_waiting = true; + prepare_to_wait(&tscadc->reg_se_wait, &wait, TASK_UNINTERRUPTIBLE); - spin_unlock_irq(&tsadc->reg_lock); + spin_unlock_irq(&tscadc->reg_lock); schedule(); - spin_lock_irq(&tsadc->reg_lock); - finish_wait(&tsadc->reg_se_wait, &wait); + spin_lock_irq(&tscadc->reg_lock); + finish_wait(&tscadc->reg_se_wait, &wait); /* * Sequencer should either be idle or * busy applying the charge step. */ - regmap_read(tsadc->regmap_tscadc, REG_ADCFSM, ®); + regmap_read(tscadc->regmap_tscadc, REG_ADCFSM, ®); WARN_ON((reg & SEQ_STATUS) && !(reg & CHARGE_STEP)); - tsadc->adc_waiting = false; + tscadc->adc_waiting = false; } - tsadc->adc_in_use = true; + tscadc->adc_in_use = true; } -void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val) +void am335x_tsc_se_set_once(struct ti_tscadc_dev *tscadc, u32 val) { - spin_lock_irq(&tsadc->reg_lock); - am335x_tscadc_need_adc(tsadc); + spin_lock_irq(&tscadc->reg_lock); + am335x_tscadc_need_adc(tscadc); - regmap_write(tsadc->regmap_tscadc, REG_SE, val); - spin_unlock_irq(&tsadc->reg_lock); + regmap_write(tscadc->regmap_tscadc, REG_SE, val); + spin_unlock_irq(&tscadc->reg_lock); } EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once); -void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tsadc) +void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tscadc) { unsigned long flags; - spin_lock_irqsave(&tsadc->reg_lock, flags); - tsadc->adc_in_use = false; - regmap_write(tsadc->regmap_tscadc, REG_SE, tsadc->reg_se_cache); - spin_unlock_irqrestore(&tsadc->reg_lock, flags); + spin_lock_irqsave(&tscadc->reg_lock, flags); + tscadc->adc_in_use = false; + regmap_write(tscadc->regmap_tscadc, REG_SE, tscadc->reg_se_cache); + spin_unlock_irqrestore(&tscadc->reg_lock, flags); } EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done); -void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val) +void am335x_tsc_se_clr(struct ti_tscadc_dev *tscadc, u32 val) { unsigned long flags; - spin_lock_irqsave(&tsadc->reg_lock, flags); - tsadc->reg_se_cache &= ~val; - regmap_write(tsadc->regmap_tscadc, REG_SE, tsadc->reg_se_cache); - spin_unlock_irqrestore(&tsadc->reg_lock, flags); + spin_lock_irqsave(&tscadc->reg_lock, flags); + tscadc->reg_se_cache &= ~val; + regmap_write(tscadc->regmap_tscadc, REG_SE, tscadc->reg_se_cache); + spin_unlock_irqrestore(&tscadc->reg_lock, flags); } EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); -static void tscadc_idle_config(struct ti_tscadc_dev *config) +static void tscadc_idle_config(struct ti_tscadc_dev *tscadc) { unsigned int idleconfig; idleconfig = STEPCONFIG_YNN | STEPCONFIG_INM_ADCREFM | STEPCONFIG_INP_ADCREFM | STEPCONFIG_YPN; - regmap_write(config->regmap_tscadc, REG_IDLECONFIG, idleconfig); + regmap_write(tscadc->regmap_tscadc, REG_IDLECONFIG, idleconfig); } static int ti_tscadc_probe(struct platform_device *pdev) @@ -297,9 +297,9 @@ static int ti_tscadc_remove(struct platform_device *pdev) static int __maybe_unused tscadc_suspend(struct device *dev) { - struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev); + struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev); - regmap_write(tscadc_dev->regmap_tscadc, REG_SE, 0x00); + regmap_write(tscadc->regmap_tscadc, REG_SE, 0x00); pm_runtime_put_sync(dev); return 0; @@ -307,26 +307,26 @@ static int __maybe_unused tscadc_suspend(struct device *dev) static int __maybe_unused tscadc_resume(struct device *dev) { - struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev); + struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev); u32 ctrl; pm_runtime_get_sync(dev); /* context restore */ ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID; - regmap_write(tscadc_dev->regmap_tscadc, REG_CTRL, ctrl); + regmap_write(tscadc->regmap_tscadc, REG_CTRL, ctrl); - if (tscadc_dev->tsc_cell != -1) { - if (tscadc_dev->tsc_wires == 5) + if (tscadc->tsc_cell != -1) { + if (tscadc->tsc_wires == 5) ctrl |= CNTRLREG_5WIRE | CNTRLREG_TSCENB; else ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB; - tscadc_idle_config(tscadc_dev); + tscadc_idle_config(tscadc); } ctrl |= CNTRLREG_TSCSSENB; - regmap_write(tscadc_dev->regmap_tscadc, REG_CTRL, ctrl); + regmap_write(tscadc->regmap_tscadc, REG_CTRL, ctrl); - regmap_write(tscadc_dev->regmap_tscadc, REG_CLKDIV, tscadc_dev->clk_div); + regmap_write(tscadc->regmap_tscadc, REG_CLKDIV, tscadc->clk_div); return 0; } -- cgit v1.2.3-58-ga151 From 0d3a7cce3e8bc5c060b1f038984c10cb70289e1d Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Wed, 8 Jun 2016 10:54:35 -0500 Subject: mfd: ti_am335x_tscadc: Rename regmap_tscadc to regmap The regmap structure pointer is named regmap_tscadc, this is not consistent with other drivers and is redundant, it also contributes to several checkpatch warnings involving long lines. Rename this. Signed-off-by: Andrew F. Davis Signed-off-by: Lee Jones --- drivers/mfd/ti_am335x_tscadc.c | 36 ++++++++++++++++++------------------ include/linux/mfd/ti_am335x_tscadc.h | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index e71f6092be61..c8f027b4ea4c 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -43,7 +43,7 @@ void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tscadc, u32 val) if (tscadc->adc_waiting) wake_up(&tscadc->reg_se_wait); else if (!tscadc->adc_in_use) - regmap_write(tscadc->regmap_tscadc, REG_SE, tscadc->reg_se_cache); + regmap_write(tscadc->regmap, REG_SE, tscadc->reg_se_cache); spin_unlock_irqrestore(&tscadc->reg_lock, flags); } @@ -54,7 +54,7 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tscadc) DEFINE_WAIT(wait); u32 reg; - regmap_read(tscadc->regmap_tscadc, REG_ADCFSM, ®); + regmap_read(tscadc->regmap, REG_ADCFSM, ®); if (reg & SEQ_STATUS) { tscadc->adc_waiting = true; prepare_to_wait(&tscadc->reg_se_wait, &wait, @@ -70,7 +70,7 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tscadc) * Sequencer should either be idle or * busy applying the charge step. */ - regmap_read(tscadc->regmap_tscadc, REG_ADCFSM, ®); + regmap_read(tscadc->regmap, REG_ADCFSM, ®); WARN_ON((reg & SEQ_STATUS) && !(reg & CHARGE_STEP)); tscadc->adc_waiting = false; } @@ -82,7 +82,7 @@ void am335x_tsc_se_set_once(struct ti_tscadc_dev *tscadc, u32 val) spin_lock_irq(&tscadc->reg_lock); am335x_tscadc_need_adc(tscadc); - regmap_write(tscadc->regmap_tscadc, REG_SE, val); + regmap_write(tscadc->regmap, REG_SE, val); spin_unlock_irq(&tscadc->reg_lock); } EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once); @@ -93,7 +93,7 @@ void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tscadc) spin_lock_irqsave(&tscadc->reg_lock, flags); tscadc->adc_in_use = false; - regmap_write(tscadc->regmap_tscadc, REG_SE, tscadc->reg_se_cache); + regmap_write(tscadc->regmap, REG_SE, tscadc->reg_se_cache); spin_unlock_irqrestore(&tscadc->reg_lock, flags); } EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done); @@ -104,7 +104,7 @@ void am335x_tsc_se_clr(struct ti_tscadc_dev *tscadc, u32 val) spin_lock_irqsave(&tscadc->reg_lock, flags); tscadc->reg_se_cache &= ~val; - regmap_write(tscadc->regmap_tscadc, REG_SE, tscadc->reg_se_cache); + regmap_write(tscadc->regmap, REG_SE, tscadc->reg_se_cache); spin_unlock_irqrestore(&tscadc->reg_lock, flags); } EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); @@ -116,7 +116,7 @@ static void tscadc_idle_config(struct ti_tscadc_dev *tscadc) idleconfig = STEPCONFIG_YNN | STEPCONFIG_INM_ADCREFM | STEPCONFIG_INP_ADCREFM | STEPCONFIG_YPN; - regmap_write(tscadc->regmap_tscadc, REG_IDLECONFIG, idleconfig); + regmap_write(tscadc->regmap, REG_IDLECONFIG, idleconfig); } static int ti_tscadc_probe(struct platform_device *pdev) @@ -187,11 +187,11 @@ static int ti_tscadc_probe(struct platform_device *pdev) if (IS_ERR(tscadc->tscadc_base)) return PTR_ERR(tscadc->tscadc_base); - tscadc->regmap_tscadc = devm_regmap_init_mmio(&pdev->dev, + tscadc->regmap = devm_regmap_init_mmio(&pdev->dev, tscadc->tscadc_base, &tscadc_regmap_config); - if (IS_ERR(tscadc->regmap_tscadc)) { + if (IS_ERR(tscadc->regmap)) { dev_err(&pdev->dev, "regmap init failed\n"); - err = PTR_ERR(tscadc->regmap_tscadc); + err = PTR_ERR(tscadc->regmap); goto ret; } @@ -221,11 +221,11 @@ static int ti_tscadc_probe(struct platform_device *pdev) /* TSCADC_CLKDIV needs to be configured to the value minus 1 */ tscadc->clk_div--; - regmap_write(tscadc->regmap_tscadc, REG_CLKDIV, tscadc->clk_div); + regmap_write(tscadc->regmap, REG_CLKDIV, tscadc->clk_div); /* Set the control register bits */ ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID; - regmap_write(tscadc->regmap_tscadc, REG_CTRL, ctrl); + regmap_write(tscadc->regmap, REG_CTRL, ctrl); /* Set register bits for Idle Config Mode */ if (tsc_wires > 0) { @@ -239,7 +239,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) /* Enable the TSC module enable bit */ ctrl |= CNTRLREG_TSCSSENB; - regmap_write(tscadc->regmap_tscadc, REG_CTRL, ctrl); + regmap_write(tscadc->regmap, REG_CTRL, ctrl); tscadc->used_cells = 0; tscadc->tsc_cell = -1; @@ -285,7 +285,7 @@ static int ti_tscadc_remove(struct platform_device *pdev) { struct ti_tscadc_dev *tscadc = platform_get_drvdata(pdev); - regmap_write(tscadc->regmap_tscadc, REG_SE, 0x00); + regmap_write(tscadc->regmap, REG_SE, 0x00); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -299,7 +299,7 @@ static int __maybe_unused tscadc_suspend(struct device *dev) { struct ti_tscadc_dev *tscadc = dev_get_drvdata(dev); - regmap_write(tscadc->regmap_tscadc, REG_SE, 0x00); + regmap_write(tscadc->regmap, REG_SE, 0x00); pm_runtime_put_sync(dev); return 0; @@ -314,7 +314,7 @@ static int __maybe_unused tscadc_resume(struct device *dev) /* context restore */ ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID; - regmap_write(tscadc->regmap_tscadc, REG_CTRL, ctrl); + regmap_write(tscadc->regmap, REG_CTRL, ctrl); if (tscadc->tsc_cell != -1) { if (tscadc->tsc_wires == 5) @@ -324,9 +324,9 @@ static int __maybe_unused tscadc_resume(struct device *dev) tscadc_idle_config(tscadc); } ctrl |= CNTRLREG_TSCSSENB; - regmap_write(tscadc->regmap_tscadc, REG_CTRL, ctrl); + regmap_write(tscadc->regmap, REG_CTRL, ctrl); - regmap_write(tscadc->regmap_tscadc, REG_CLKDIV, tscadc->clk_div); + regmap_write(tscadc->regmap, REG_CLKDIV, tscadc->clk_div); return 0; } diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index 1fd50dcfe47c..2567a87872b0 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -153,7 +153,7 @@ struct ti_tscadc_dev { struct device *dev; - struct regmap *regmap_tscadc; + struct regmap *regmap; void __iomem *tscadc_base; int irq; int used_cells; /* 1-2 */ -- cgit v1.2.3-58-ga151 From 9835f1b70bb3890d38308b9be4fb9d7451ba67f1 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 15 Jun 2016 01:02:26 +0200 Subject: mfd: qcom_rpm: Fix offset error for msm8660 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The RPM in MSM8660/APQ8060 has different offsets to the selector ACK and request context ACK registers. Make all these register offsets part of the per-SoC data and assign the right values. The bug was found by verifying backwards to the vendor tree in the out-of-tree files : all were using offsets 3,11,15,23 and a select size of 4, except the MSM8660/APQ8060 which was using offsets 3,11,19,27 and a select size of 7. All other platforms apart from msm8660 were affected by reading excess registers, since 7 was hardcoded as the number of select words, this patch makes also this part dynamic so we only write/read as many select words as the platform actually use. Symptoms of this bug when using msm8660: the first RPM transaction would work, but the next would stall or raise an error since the previous transaction was not properly ACKed as the ACK words were read at the wrong offset. Cc: stable@vger.kernel.org Fixes: 58e214382bdd ("mfd: qcom-rpm: Driver for the Qualcomm RPM") Signed-off-by: Linus Walleij Reviewed-by: Björn Andersson Signed-off-by: Lee Jones --- drivers/mfd/qcom_rpm.c | 50 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c index 1be47ad6441b..9364f88264e5 100644 --- a/drivers/mfd/qcom_rpm.c +++ b/drivers/mfd/qcom_rpm.c @@ -34,7 +34,12 @@ struct qcom_rpm_resource { struct qcom_rpm_data { u32 version; const struct qcom_rpm_resource *resource_table; - unsigned n_resources; + unsigned int n_resources; + unsigned int req_ctx_off; + unsigned int req_sel_off; + unsigned int ack_ctx_off; + unsigned int ack_sel_off; + unsigned int sel_size; }; struct qcom_rpm { @@ -61,11 +66,7 @@ struct qcom_rpm { #define RPM_REQUEST_TIMEOUT (5 * HZ) -#define RPM_REQUEST_CONTEXT 3 -#define RPM_REQ_SELECT 11 -#define RPM_ACK_CONTEXT 15 -#define RPM_ACK_SELECTOR 23 -#define RPM_SELECT_SIZE 7 +#define RPM_MAX_SEL_SIZE 7 #define RPM_NOTIFICATION BIT(30) #define RPM_REJECTED BIT(31) @@ -157,6 +158,11 @@ static const struct qcom_rpm_data apq8064_template = { .version = 3, .resource_table = apq8064_rpm_resource_table, .n_resources = ARRAY_SIZE(apq8064_rpm_resource_table), + .req_ctx_off = 3, + .req_sel_off = 11, + .ack_ctx_off = 15, + .ack_sel_off = 23, + .sel_size = 4, }; static const struct qcom_rpm_resource msm8660_rpm_resource_table[] = { @@ -240,6 +246,11 @@ static const struct qcom_rpm_data msm8660_template = { .version = 2, .resource_table = msm8660_rpm_resource_table, .n_resources = ARRAY_SIZE(msm8660_rpm_resource_table), + .req_ctx_off = 3, + .req_sel_off = 11, + .ack_ctx_off = 19, + .ack_sel_off = 27, + .sel_size = 7, }; static const struct qcom_rpm_resource msm8960_rpm_resource_table[] = { @@ -322,6 +333,11 @@ static const struct qcom_rpm_data msm8960_template = { .version = 3, .resource_table = msm8960_rpm_resource_table, .n_resources = ARRAY_SIZE(msm8960_rpm_resource_table), + .req_ctx_off = 3, + .req_sel_off = 11, + .ack_ctx_off = 15, + .ack_sel_off = 23, + .sel_size = 4, }; static const struct qcom_rpm_resource ipq806x_rpm_resource_table[] = { @@ -362,6 +378,11 @@ static const struct qcom_rpm_data ipq806x_template = { .version = 3, .resource_table = ipq806x_rpm_resource_table, .n_resources = ARRAY_SIZE(ipq806x_rpm_resource_table), + .req_ctx_off = 3, + .req_sel_off = 11, + .ack_ctx_off = 15, + .ack_sel_off = 23, + .sel_size = 4, }; static const struct of_device_id qcom_rpm_of_match[] = { @@ -380,7 +401,7 @@ int qcom_rpm_write(struct qcom_rpm *rpm, { const struct qcom_rpm_resource *res; const struct qcom_rpm_data *data = rpm->data; - u32 sel_mask[RPM_SELECT_SIZE] = { 0 }; + u32 sel_mask[RPM_MAX_SEL_SIZE] = { 0 }; int left; int ret = 0; int i; @@ -398,12 +419,12 @@ int qcom_rpm_write(struct qcom_rpm *rpm, writel_relaxed(buf[i], RPM_REQ_REG(rpm, res->target_id + i)); bitmap_set((unsigned long *)sel_mask, res->select_id, 1); - for (i = 0; i < ARRAY_SIZE(sel_mask); i++) { + for (i = 0; i < rpm->data->sel_size; i++) { writel_relaxed(sel_mask[i], - RPM_CTRL_REG(rpm, RPM_REQ_SELECT + i)); + RPM_CTRL_REG(rpm, rpm->data->req_sel_off + i)); } - writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT)); + writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, rpm->data->req_ctx_off)); reinit_completion(&rpm->ack); regmap_write(rpm->ipc_regmap, rpm->ipc_offset, BIT(rpm->ipc_bit)); @@ -426,10 +447,11 @@ static irqreturn_t qcom_rpm_ack_interrupt(int irq, void *dev) u32 ack; int i; - ack = readl_relaxed(RPM_CTRL_REG(rpm, RPM_ACK_CONTEXT)); - for (i = 0; i < RPM_SELECT_SIZE; i++) - writel_relaxed(0, RPM_CTRL_REG(rpm, RPM_ACK_SELECTOR + i)); - writel(0, RPM_CTRL_REG(rpm, RPM_ACK_CONTEXT)); + ack = readl_relaxed(RPM_CTRL_REG(rpm, rpm->data->ack_ctx_off)); + for (i = 0; i < rpm->data->sel_size; i++) + writel_relaxed(0, + RPM_CTRL_REG(rpm, rpm->data->ack_sel_off + i)); + writel(0, RPM_CTRL_REG(rpm, rpm->data->ack_ctx_off)); if (ack & RPM_NOTIFICATION) { dev_warn(rpm->dev, "ignoring notification!\n"); -- cgit v1.2.3-58-ga151 From 1f2c39726f04906c6e97840599bc8d298c4b0eab Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 15 Jun 2016 10:28:44 +0100 Subject: mfd: arizona: Check if AOD interrupts are pending before dispatching Previously the arizona_irq_thread implementation would call handle_nested_irqs() to handle AOD interrupts without checking if any were actually pending. The kernel will see these as spurious IRQs and will eventually disable the IRQ. This patch ensures we only launch the nested handler if there are AOD interrupts pending in the codec. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Signed-off-by: Lee Jones --- drivers/mfd/arizona-irq.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c index edeb4951366a..5e18d3c77582 100644 --- a/drivers/mfd/arizona-irq.c +++ b/drivers/mfd/arizona-irq.c @@ -109,8 +109,20 @@ static irqreturn_t arizona_irq_thread(int irq, void *data) do { poll = false; - if (arizona->aod_irq_chip) - handle_nested_irq(irq_find_mapping(arizona->virq, 0)); + if (arizona->aod_irq_chip) { + /* + * Check the AOD status register to determine whether + * the nested IRQ handler should be called. + */ + ret = regmap_read(arizona->regmap, + ARIZONA_AOD_IRQ1, &val); + if (ret) + dev_warn(arizona->dev, + "Failed to read AOD IRQ1 %d\n", ret); + else if (val) + handle_nested_irq( + irq_find_mapping(arizona->virq, 0)); + } /* * Check if one of the main interrupts is asserted and only -- cgit v1.2.3-58-ga151 From 417e06bb3f281e6dddbcad4d5108779718857cc4 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 14 Jun 2016 15:43:30 -0700 Subject: mfd: hi655x-pmic: Fixup issue with un-acked interrupts While trying to get the powerkey to function, I found when pressing the key, I would get infinitely repeating interrupts. After digging around a bit, it seems we didn't set the ack_base value for the regmap irqchip logic, so nothing was acking the interrupt. This patch adds the ack_base, which seems to make things work. Signed-off-by: John Stultz Signed-off-by: Lee Jones --- drivers/mfd/hi655x-pmic.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c index 05ddc7882362..68ab3701cbf3 100644 --- a/drivers/mfd/hi655x-pmic.c +++ b/drivers/mfd/hi655x-pmic.c @@ -45,6 +45,7 @@ static const struct regmap_irq_chip hi655x_irq_chip = { .num_regs = 1, .num_irqs = ARRAY_SIZE(hi655x_irqs), .status_base = HI655X_IRQ_STAT_BASE, + .ack_base = HI655X_IRQ_STAT_BASE, .mask_base = HI655X_IRQ_MASK_BASE, }; -- cgit v1.2.3-58-ga151 From 9e3d5c996b340c1572afabe5ff2f0dd8ced1583a Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 14 Jun 2016 15:43:31 -0700 Subject: mfd: hi655x-pmic: Rename some interrupt macro names Currently the hi655x-pmic driver has names for interrupt mask values, but not for the interrupt numbers themselves. So to allow for interrupt numbers to have sane names, rename the mask values with the _MASK postfix and use the existing names as the interrupt name Signed-off-by: John Stultz Signed-off-by: Lee Jones --- drivers/mfd/hi655x-pmic.c | 16 ++++++++-------- include/linux/mfd/hi655x-pmic.h | 25 +++++++++++++++++-------- 2 files changed, 25 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c index 68ab3701cbf3..072e6feab6e9 100644 --- a/drivers/mfd/hi655x-pmic.c +++ b/drivers/mfd/hi655x-pmic.c @@ -29,14 +29,14 @@ static const struct mfd_cell hi655x_pmic_devs[] = { }; static const struct regmap_irq hi655x_irqs[] = { - { .reg_offset = 0, .mask = OTMP_D1R_INT }, - { .reg_offset = 0, .mask = VSYS_2P5_R_INT }, - { .reg_offset = 0, .mask = VSYS_UV_D3R_INT }, - { .reg_offset = 0, .mask = VSYS_6P0_D200UR_INT }, - { .reg_offset = 0, .mask = PWRON_D4SR_INT }, - { .reg_offset = 0, .mask = PWRON_D20F_INT }, - { .reg_offset = 0, .mask = PWRON_D20R_INT }, - { .reg_offset = 0, .mask = RESERVE_INT }, + { .reg_offset = 0, .mask = OTMP_D1R_INT_MASK }, + { .reg_offset = 0, .mask = VSYS_2P5_R_INT_MASK }, + { .reg_offset = 0, .mask = VSYS_UV_D3R_INT_MASK }, + { .reg_offset = 0, .mask = VSYS_6P0_D200UR_INT_MASK }, + { .reg_offset = 0, .mask = PWRON_D4SR_INT_MASK }, + { .reg_offset = 0, .mask = PWRON_D20F_INT_MASK }, + { .reg_offset = 0, .mask = PWRON_D20R_INT_MASK }, + { .reg_offset = 0, .mask = RESERVE_INT_MASK }, }; static const struct regmap_irq_chip hi655x_irq_chip = { diff --git a/include/linux/mfd/hi655x-pmic.h b/include/linux/mfd/hi655x-pmic.h index dbbe9a644622..62f03c2b1bb0 100644 --- a/include/linux/mfd/hi655x-pmic.h +++ b/include/linux/mfd/hi655x-pmic.h @@ -34,14 +34,23 @@ #define PMU_VER_START 0x10 #define PMU_VER_END 0x38 -#define RESERVE_INT BIT(7) -#define PWRON_D20R_INT BIT(6) -#define PWRON_D20F_INT BIT(5) -#define PWRON_D4SR_INT BIT(4) -#define VSYS_6P0_D200UR_INT BIT(3) -#define VSYS_UV_D3R_INT BIT(2) -#define VSYS_2P5_R_INT BIT(1) -#define OTMP_D1R_INT BIT(0) +#define RESERVE_INT 7 +#define PWRON_D20R_INT 6 +#define PWRON_D20F_INT 5 +#define PWRON_D4SR_INT 4 +#define VSYS_6P0_D200UR_INT 3 +#define VSYS_UV_D3R_INT 2 +#define VSYS_2P5_R_INT 1 +#define OTMP_D1R_INT 0 + +#define RESERVE_INT_MASK BIT(RESERVE_INT) +#define PWRON_D20R_INT_MASK BIT(PWRON_D20R_INT) +#define PWRON_D20F_INT_MASK BIT(PWRON_D20F_INT) +#define PWRON_D4SR_INT_MASK BIT(PWRON_D4SR_INT) +#define VSYS_6P0_D200UR_INT_MASK BIT(VSYS_6P0_D200UR_INT) +#define VSYS_UV_D3R_INT_MASK BIT(VSYS_UV_D3R_INT) +#define VSYS_2P5_R_INT_MASK BIT(VSYS_2P5_R_INT) +#define OTMP_D1R_INT_MASK BIT(OTMP_D1R_INT) struct hi655x_pmic { struct resource *res; -- cgit v1.2.3-58-ga151 From eb10245fb37e2d67a7b63e838ecd841f32e5dcf4 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 14 Jun 2016 15:43:32 -0700 Subject: mfd: hi655x-pmic: Add powerkey device to hi655x PMIC driver Wire up the powerkey driver functionality for the hi655x PMIC. Signed-off-by: John Stultz Signed-off-by: Lee Jones --- drivers/mfd/hi655x-pmic.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c index 072e6feab6e9..e955a0c6f40b 100644 --- a/drivers/mfd/hi655x-pmic.c +++ b/drivers/mfd/hi655x-pmic.c @@ -24,10 +24,6 @@ #include #include -static const struct mfd_cell hi655x_pmic_devs[] = { - { .name = "hi655x-regulator", }, -}; - static const struct regmap_irq hi655x_irqs[] = { { .reg_offset = 0, .mask = OTMP_D1R_INT_MASK }, { .reg_offset = 0, .mask = VSYS_2P5_R_INT_MASK }, @@ -56,6 +52,34 @@ static struct regmap_config hi655x_regmap_config = { .max_register = HI655X_BUS_ADDR(0xFFF), }; +static struct resource pwrkey_resources[] = { + { + .name = "down", + .start = PWRON_D20R_INT, + .end = PWRON_D20R_INT, + .flags = IORESOURCE_IRQ, + }, { + .name = "up", + .start = PWRON_D20F_INT, + .end = PWRON_D20F_INT, + .flags = IORESOURCE_IRQ, + }, { + .name = "hold 4s", + .start = PWRON_D4SR_INT, + .end = PWRON_D4SR_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static const struct mfd_cell hi655x_pmic_devs[] = { + { + .name = "hi65xx-powerkey", + .num_resources = ARRAY_SIZE(pwrkey_resources), + .resources = &pwrkey_resources[0], + }, + { .name = "hi655x-regulator", }, +}; + static void hi655x_local_irq_clear(struct regmap *map) { int i; @@ -124,7 +148,8 @@ static int hi655x_pmic_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pmic); ret = mfd_add_devices(dev, PLATFORM_DEVID_AUTO, hi655x_pmic_devs, - ARRAY_SIZE(hi655x_pmic_devs), NULL, 0, NULL); + ARRAY_SIZE(hi655x_pmic_devs), NULL, 0, + regmap_irq_get_domain(pmic->irq_data)); if (ret) { dev_err(dev, "Failed to register device %d\n", ret); regmap_del_irq_chip(gpio_to_irq(pmic->gpio), pmic->irq_data); -- cgit v1.2.3-58-ga151 From b9847899b3a8bd8002233e0e392909d731309c1b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 13 Jun 2016 02:34:21 +0200 Subject: mfd: qcom_rpm: Remove unused define This define RPM_SIGNAL probably pertains to the IPC signal which we ended up fetching from the device tree instead. the define is unused, remove it. Signed-off-by: Linus Walleij Reviewed-by: Stephen Boyd Signed-off-by: Lee Jones --- drivers/mfd/qcom_rpm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c index 9364f88264e5..710cae2a9b02 100644 --- a/drivers/mfd/qcom_rpm.c +++ b/drivers/mfd/qcom_rpm.c @@ -71,8 +71,6 @@ struct qcom_rpm { #define RPM_NOTIFICATION BIT(30) #define RPM_REJECTED BIT(31) -#define RPM_SIGNAL BIT(2) - static const struct qcom_rpm_resource apq8064_rpm_resource_table[] = { [QCOM_RPM_CXO_CLK] = { 25, 9, 5, 1 }, [QCOM_RPM_PXO_CLK] = { 26, 10, 6, 1 }, -- cgit v1.2.3-58-ga151 From 9961bf1876c08d3a290b0e69344c64a8cbbf8a68 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 26 May 2016 12:32:19 -0400 Subject: mfd: max14577: Use module_init() instead of subsys_initcall() The driver's init function is called at subsys init call level but the dependencies provided by the driver are looked up by drivers that have probe deferral support, so manual ordering of init calls isn't needed. Suggested-by: Krzysztof Kozlowski Signed-off-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/max14577.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c index 2280b3fdcf68..6c245128ab2e 100644 --- a/drivers/mfd/max14577.c +++ b/drivers/mfd/max14577.c @@ -561,7 +561,7 @@ static int __init max14577_i2c_init(void) return i2c_add_driver(&max14577_i2c_driver); } -subsys_initcall(max14577_i2c_init); +module_init(max14577_i2c_init); static void __exit max14577_i2c_exit(void) { -- cgit v1.2.3-58-ga151 From 59a9b273e3049c8c3b915dc70ebcf13d1f942230 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 26 May 2016 12:32:20 -0400 Subject: mfd: max14577: Allow driver to be built as a module The driver's Kconfig symbol is a boolean but nothing prevents the driver to be built as a module instead of built-in. It is true that most system integrators will choose the latter but the config should not restrict it. Suggested-by: Krzysztof Kozlowski Signed-off-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 9402399bb3d6..48ed14ae9651 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -535,8 +535,8 @@ config MFD_88PM860X battery-charger under the corresponding menus. config MFD_MAX14577 - bool "Maxim Semiconductor MAX14577/77836 MUIC + Charger Support" - depends on I2C=y + tristate "Maxim Semiconductor MAX14577/77836 MUIC + Charger Support" + depends on I2C select MFD_CORE select REGMAP_I2C select REGMAP_IRQ -- cgit v1.2.3-58-ga151 From fc1882dcb5031953169a38260a0e653910825e46 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 25 May 2016 14:22:02 +0200 Subject: mfd: stmpe: Move platform data into MFD driver The STMPE platform data is only populated from the device tree in all existing users, so push the struct and make the OF case the norm. Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/stmpe.c | 40 ++++++++++++++++++++++++++++------------ include/linux/mfd/stmpe.h | 22 +--------------------- 2 files changed, 29 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index fb8f9e8b75df..94c7cc02fdab 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -23,6 +23,27 @@ #include #include "stmpe.h" +/** + * struct stmpe_platform_data - STMPE platform data + * @id: device id to distinguish between multiple STMPEs on the same board + * @blocks: bitmask of blocks to enable (use STMPE_BLOCK_*) + * @irq_trigger: IRQ trigger to use for the interrupt to the host + * @autosleep: bool to enable/disable stmpe autosleep + * @autosleep_timeout: inactivity timeout in milliseconds for autosleep + * @irq_over_gpio: true if gpio is used to get irq + * @irq_gpio: gpio number over which irq will be requested (significant only if + * irq_over_gpio is true) + */ +struct stmpe_platform_data { + int id; + unsigned int blocks; + unsigned int irq_trigger; + bool autosleep; + bool irq_over_gpio; + int irq_gpio; + int autosleep_timeout; +}; + static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks) { return stmpe->variant->enable(stmpe, blocks, true); @@ -1187,24 +1208,19 @@ static void stmpe_of_probe(struct stmpe_platform_data *pdata, /* Called from client specific probe routines */ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) { - struct stmpe_platform_data *pdata = dev_get_platdata(ci->dev); + struct stmpe_platform_data *pdata; struct device_node *np = ci->dev->of_node; struct stmpe *stmpe; int ret; - if (!pdata) { - if (!np) - return -EINVAL; - - pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; + pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; - stmpe_of_probe(pdata, np); + stmpe_of_probe(pdata, np); - if (of_find_property(np, "interrupts", NULL) == NULL) - ci->irq = -1; - } + if (of_find_property(np, "interrupts", NULL) == NULL) + ci->irq = -1; stmpe = devm_kzalloc(ci->dev, sizeof(struct stmpe), GFP_KERNEL); if (!stmpe) diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h index cb83883918a7..de748bc7525e 100644 --- a/include/linux/mfd/stmpe.h +++ b/include/linux/mfd/stmpe.h @@ -62,6 +62,7 @@ enum { struct stmpe_variant_info; struct stmpe_client_info; +struct stmpe_platform_data; /** * struct stmpe - STMPE MFD structure @@ -117,25 +118,4 @@ extern int stmpe_disable(struct stmpe *stmpe, unsigned int blocks); #define STMPE_GPIO_NOREQ_811_TOUCH (0xf0) -/** - * struct stmpe_platform_data - STMPE platform data - * @id: device id to distinguish between multiple STMPEs on the same board - * @blocks: bitmask of blocks to enable (use STMPE_BLOCK_*) - * @irq_trigger: IRQ trigger to use for the interrupt to the host - * @autosleep: bool to enable/disable stmpe autosleep - * @autosleep_timeout: inactivity timeout in milliseconds for autosleep - * @irq_over_gpio: true if gpio is used to get irq - * @irq_gpio: gpio number over which irq will be requested (significant only if - * irq_over_gpio is true) - */ -struct stmpe_platform_data { - int id; - unsigned int blocks; - unsigned int irq_trigger; - bool autosleep; - bool irq_over_gpio; - int irq_gpio; - int autosleep_timeout; -}; - #endif -- cgit v1.2.3-58-ga151 From d347792c315171fd89dda9d6cbebea756c29b3ea Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 27 Jun 2016 15:19:11 +0100 Subject: mfd: arizona: Add missing disable of PM runtime on probe error path Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index bf2717967597..e4f97b3c824b 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -1462,7 +1462,7 @@ int arizona_dev_init(struct arizona *arizona) /* Set up for interrupts */ ret = arizona_irq_init(arizona); if (ret != 0) - goto err_reset; + goto err_pm; pm_runtime_set_autosuspend_delay(arizona->dev, 100); pm_runtime_use_autosuspend(arizona->dev); @@ -1486,6 +1486,8 @@ int arizona_dev_init(struct arizona *arizona) err_irq: arizona_irq_exit(arizona); +err_pm: + pm_runtime_disable(arizona->dev); err_reset: arizona_enable_reset(arizona); regulator_disable(arizona->dcvdd); -- cgit v1.2.3-58-ga151 From a67911d38f2deda8a48cb0e8a4b3f59afeda7b81 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sun, 26 Jun 2016 12:25:36 +0200 Subject: mfd: twl-core: Return directly after a failed platform_device_alloc() in add_numbered_child() The platform_device_put() function was called in one case by the add_numbered_child() function during error handling even if the passed variable "pdev" contained a null pointer. Return directly in this case. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Lee Jones --- drivers/mfd/twl-core.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 831696ee2472..9458c6df39ed 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -622,11 +622,8 @@ add_numbered_child(unsigned mod_no, const char *name, int num, twl = &twl_priv->twl_modules[sid]; pdev = platform_device_alloc(name, num); - if (!pdev) { - dev_dbg(&twl->client->dev, "can't alloc dev\n"); - status = -ENOMEM; - goto err; - } + if (!pdev) + return ERR_PTR(-ENOMEM); pdev->dev.parent = &twl->client->dev; -- cgit v1.2.3-58-ga151 From 8175a01c2117e13f53b258e039f3a89c58be1425 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sun, 26 Jun 2016 13:03:59 +0200 Subject: mfd: twl-core: Refactoring for add_numbered_child() Adjust jump targets according to the Linux coding style convention. Another check for the variable "status" can be omitted then at the end. Signed-off-by: Markus Elfring Signed-off-by: Lee Jones --- drivers/mfd/twl-core.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 9458c6df39ed..a49d3db6d936 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -631,7 +631,7 @@ add_numbered_child(unsigned mod_no, const char *name, int num, status = platform_device_add_data(pdev, pdata, pdata_len); if (status < 0) { dev_dbg(&pdev->dev, "can't add platform_data\n"); - goto err; + goto put_device; } } @@ -644,21 +644,22 @@ add_numbered_child(unsigned mod_no, const char *name, int num, status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1); if (status < 0) { dev_dbg(&pdev->dev, "can't add irqs\n"); - goto err; + goto put_device; } } status = platform_device_add(pdev); - if (status == 0) - device_init_wakeup(&pdev->dev, can_wakeup); + if (status) + goto put_device; + + device_init_wakeup(&pdev->dev, can_wakeup); -err: - if (status < 0) { - platform_device_put(pdev); - dev_err(&twl->client->dev, "can't add %s dev\n", name); - return ERR_PTR(status); - } return &pdev->dev; + +put_device: + platform_device_put(pdev); + dev_err(&twl->client->dev, "failed to add device %s\n", name); + return ERR_PTR(status); } static inline struct device *add_child(unsigned mod_no, const char *name, -- cgit v1.2.3-58-ga151 From d313cdde71ec9a5c327a515c37a0dca2cca00de5 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sun, 26 Jun 2016 13:40:35 +0200 Subject: mfd: dm355evm_msp: Return directly after a failed platform_device_alloc() in add_child() The platform_device_put() function was called in one case by the add_child() function during error handling even if the passed variable "pdev" contained a null pointer. Return directly in this case. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Lee Jones --- drivers/mfd/dm355evm_msp.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c index 14661ec5ef7f..270e19c0bba1 100644 --- a/drivers/mfd/dm355evm_msp.c +++ b/drivers/mfd/dm355evm_msp.c @@ -199,11 +199,8 @@ static struct device *add_child(struct i2c_client *client, const char *name, int status; pdev = platform_device_alloc(name, -1); - if (!pdev) { - dev_dbg(&client->dev, "can't alloc dev\n"); - status = -ENOMEM; - goto err; - } + if (!pdev) + return ERR_PTR(-ENOMEM); device_init_wakeup(&pdev->dev, can_wakeup); pdev->dev.parent = &client->dev; -- cgit v1.2.3-58-ga151 From 53b34b8d8860833bc672b6deb77a1769b2f79b5b Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sun, 26 Jun 2016 14:14:54 +0200 Subject: mfd: smsc-ece1099: Delete an unnecessary variable initialisation in smsc_i2c_probe() The variable "ret" will be set to an appropriate value a bit later. Thus omit the explicit initialisation at the beginning. Signed-off-by: Markus Elfring Signed-off-by: Lee Jones --- drivers/mfd/smsc-ece1099.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/smsc-ece1099.c b/drivers/mfd/smsc-ece1099.c index 7f89e89b8a5e..2aaf89fa66c3 100644 --- a/drivers/mfd/smsc-ece1099.c +++ b/drivers/mfd/smsc-ece1099.c @@ -36,7 +36,7 @@ static int smsc_i2c_probe(struct i2c_client *i2c, { struct smsc *smsc; int devid, rev, venid_l, venid_h; - int ret = 0; + int ret; smsc = devm_kzalloc(&i2c->dev, sizeof(struct smsc), GFP_KERNEL); -- cgit v1.2.3-58-ga151 From 4dc03d0abb3a27cf5842a52c796fe4e3d9541985 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sun, 26 Jun 2016 14:30:46 +0200 Subject: mfd: smsc-ece1099: Return directly after a function failure in smsc_i2c_probe() This issue was detected by using the Coccinelle software. Return directly if a call of the function "devm_regmap_init_i2c" or "regmap_write" failed. Delete the jump label "err" then. Signed-off-by: Markus Elfring Signed-off-by: Lee Jones --- drivers/mfd/smsc-ece1099.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/smsc-ece1099.c b/drivers/mfd/smsc-ece1099.c index 2aaf89fa66c3..cd18c09827ef 100644 --- a/drivers/mfd/smsc-ece1099.c +++ b/drivers/mfd/smsc-ece1099.c @@ -46,10 +46,8 @@ static int smsc_i2c_probe(struct i2c_client *i2c, } smsc->regmap = devm_regmap_init_i2c(i2c, &smsc_regmap_config); - if (IS_ERR(smsc->regmap)) { - ret = PTR_ERR(smsc->regmap); - goto err; - } + if (IS_ERR(smsc->regmap)) + return PTR_ERR(smsc->regmap); i2c_set_clientdata(i2c, smsc); smsc->dev = &i2c->dev; @@ -68,7 +66,7 @@ static int smsc_i2c_probe(struct i2c_client *i2c, ret = regmap_write(smsc->regmap, SMSC_CLK_CTRL, smsc->clk); if (ret) - goto err; + return ret; #ifdef CONFIG_OF if (i2c->dev.of_node) @@ -76,7 +74,6 @@ static int smsc_i2c_probe(struct i2c_client *i2c, NULL, NULL, &i2c->dev); #endif -err: return ret; } -- cgit v1.2.3-58-ga151 From 7e28abda8c1f08e8926ed1b9fbfb6efdfc88c19b Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 18 Jun 2016 17:26:07 +0000 Subject: mfd: hi655x: Fix return value check in hi655x_pmic_probe() In case of error, the function devm_ioremap_resource() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Also remove unneeded error handling of platform_get_resource(). Signed-off-by: Wei Yongjun Signed-off-by: Lee Jones --- drivers/mfd/hi655x-pmic.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c index e955a0c6f40b..0fc62995695b 100644 --- a/drivers/mfd/hi655x-pmic.c +++ b/drivers/mfd/hi655x-pmic.c @@ -105,12 +105,9 @@ static int hi655x_pmic_probe(struct platform_device *pdev) pmic->dev = dev; pmic->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!pmic->res) - return -ENOENT; - base = devm_ioremap_resource(dev, pmic->res); - if (!base) - return -ENOMEM; + if (IS_ERR(base)) + return PTR_ERR(base); pmic->regmap = devm_regmap_init_mmio_clk(dev, NULL, base, &hi655x_regmap_config); -- cgit v1.2.3-58-ga151 From 1db3ba2830bc2cd174f1b60da156d77214bed681 Mon Sep 17 00:00:00 2001 From: Michael Brunner Date: Sun, 19 Jun 2016 10:48:20 +0200 Subject: mfd: Add support for COMe-cSL6 and COMe-mAL10 to Kontron PLD driver This is an unmodified resend of the patch already been sent on February 17 as it seems to have fallen through the net. This patch adds the DMI system ID of the Kontron COMe-cSL6 and COME-mAL10 boards to the Kontron PLD driver. The list of supported products in the module description is also updated. Signed-off-by: Michael Brunner Acked-by: Christian Rauch Acked-by: Guenter Roeck Reviewed-by: Darren Hart Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 2 ++ drivers/mfd/kempld-core.c | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 48ed14ae9651..2d1fb6420592 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -491,6 +491,8 @@ config MFD_KEMPLD * COMe-cDC2 (microETXexpress-DC) * COMe-cHL6 * COMe-cPC2 (microETXexpress-PC) + * COMe-cSL6 + * COMe-mAL10 * COMe-mBT10 * COMe-mCT10 * COMe-mTT10 (nanoETXexpress-TT) diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c index 05b924542ee2..da5722d7c540 100644 --- a/drivers/mfd/kempld-core.c +++ b/drivers/mfd/kempld-core.c @@ -623,6 +623,14 @@ static struct dmi_system_id kempld_dmi_table[] __initdata = { }, .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 = { @@ -646,6 +654,14 @@ static struct dmi_system_id kempld_dmi_table[] __initdata = { }, .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 = "MBR1", .matches = { -- cgit v1.2.3-58-ga151 From 0a58da1e2f25f213fb72d7d6a18dff9562621215 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 20 Jun 2016 17:07:18 +0300 Subject: mfd: twl6040: Handle mclk used for HPPLL and optional internal clock source On some boards, like omap5-uevm the MCLK is gated by default and in order to be able to use the High performance modes of twl6040 it need to be enabled by SW. Add support for handling the MCLK source clock via CCF. At the same time lower the print priority of the notification that the 32K clock is not provided and it is not going to be handled by the driver. Signed-off-by: Peter Ujfalusi Acked-by: Rob Herring Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/mfd/twl6040.txt | 4 +-- drivers/mfd/twl6040.c | 41 ++++++++++++++++------- include/linux/mfd/twl6040.h | 5 +-- 3 files changed, 34 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/mfd/twl6040.txt b/Documentation/devicetree/bindings/mfd/twl6040.txt index a41157b5d930..e6afdfa3543d 100644 --- a/Documentation/devicetree/bindings/mfd/twl6040.txt +++ b/Documentation/devicetree/bindings/mfd/twl6040.txt @@ -19,8 +19,8 @@ Required properties: Optional properties, nodes: - enable-active-high: To power on the twl6040 during boot. -- clocks: phandle to the clk32k clock provider -- clock-names: Must be "clk32k" +- clocks: phandle to the clk32k and/or to mclk clock provider +- clock-names: Must be "clk32k" for the 32K clock and "mclk" for the MCLK. Vibra functionality Required properties: diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index 852d5874aabb..ab328ec49353 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -323,8 +323,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) /* Default PLL configuration after power up */ twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; - twl6040->sysclk = 19200000; - twl6040->mclk = 32768; + twl6040->sysclk_rate = 19200000; } else { /* already powered-down */ if (!twl6040->power_count) { @@ -352,8 +351,12 @@ int twl6040_power(struct twl6040 *twl6040, int on) regcache_cache_only(twl6040->regmap, true); regcache_mark_dirty(twl6040->regmap); - twl6040->sysclk = 0; - twl6040->mclk = 0; + twl6040->sysclk_rate = 0; + + if (twl6040->pll == TWL6040_SYSCLK_SEL_HPPLL) { + clk_disable_unprepare(twl6040->mclk); + twl6040->mclk_rate = 0; + } clk_disable_unprepare(twl6040->clk32k); } @@ -377,15 +380,15 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, /* Force full reconfiguration when switching between PLL */ if (pll_id != twl6040->pll) { - twl6040->sysclk = 0; - twl6040->mclk = 0; + twl6040->sysclk_rate = 0; + twl6040->mclk_rate = 0; } switch (pll_id) { case TWL6040_SYSCLK_SEL_LPPLL: /* low-power PLL divider */ /* Change the sysclk configuration only if it has been canged */ - if (twl6040->sysclk != freq_out) { + if (twl6040->sysclk_rate != freq_out) { switch (freq_out) { case 17640000: lppllctl |= TWL6040_LPLLFIN; @@ -427,6 +430,8 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, ret = -EINVAL; goto pll_out; } + + clk_disable_unprepare(twl6040->mclk); break; case TWL6040_SYSCLK_SEL_HPPLL: /* high-performance PLL can provide only 19.2 MHz */ @@ -437,7 +442,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, goto pll_out; } - if (twl6040->mclk != freq_in) { + if (twl6040->mclk_rate != freq_in) { hppllctl &= ~TWL6040_MCLK_MSK; switch (freq_in) { @@ -468,6 +473,9 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, goto pll_out; } + /* When switching to HPPLL, enable the mclk first */ + if (pll_id != twl6040->pll) + clk_prepare_enable(twl6040->mclk); /* * enable clock slicer to ensure input waveform is * square @@ -483,6 +491,8 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, lppllctl &= ~TWL6040_LPLLENA; twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); + + twl6040->mclk_rate = freq_in; } break; default: @@ -491,8 +501,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, goto pll_out; } - twl6040->sysclk = freq_out; - twl6040->mclk = freq_in; + twl6040->sysclk_rate = freq_out; twl6040->pll = pll_id; pll_out: @@ -512,7 +521,7 @@ EXPORT_SYMBOL(twl6040_get_pll); unsigned int twl6040_get_sysclk(struct twl6040 *twl6040) { - return twl6040->sysclk; + return twl6040->sysclk_rate; } EXPORT_SYMBOL(twl6040_get_sysclk); @@ -655,10 +664,18 @@ static int twl6040_probe(struct i2c_client *client, if (IS_ERR(twl6040->clk32k)) { if (PTR_ERR(twl6040->clk32k) == -EPROBE_DEFER) return -EPROBE_DEFER; - dev_info(&client->dev, "clk32k is not handled\n"); + dev_dbg(&client->dev, "clk32k is not handled\n"); twl6040->clk32k = NULL; } + twl6040->mclk = devm_clk_get(&client->dev, "mclk"); + if (IS_ERR(twl6040->mclk)) { + if (PTR_ERR(twl6040->mclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dev_dbg(&client->dev, "mclk is not handled\n"); + twl6040->mclk = NULL; + } + twl6040->supplies[0].supply = "vio"; twl6040->supplies[1].supply = "v2v1"; ret = devm_regulator_bulk_get(&client->dev, TWL6040_NUM_SUPPLIES, diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h index 8e95cd87cd74..36795a1be479 100644 --- a/include/linux/mfd/twl6040.h +++ b/include/linux/mfd/twl6040.h @@ -226,6 +226,7 @@ struct twl6040 { struct regmap_irq_chip_data *irq_data; struct regulator_bulk_data supplies[2]; /* supplies for vio, v2v1 */ struct clk *clk32k; + struct clk *mclk; struct mutex mutex; struct mutex irq_mutex; struct mfd_cell cells[TWL6040_CELLS]; @@ -237,8 +238,8 @@ struct twl6040 { /* PLL configuration */ int pll; - unsigned int sysclk; - unsigned int mclk; + unsigned int sysclk_rate; + unsigned int mclk_rate; unsigned int irq; unsigned int irq_ready; -- cgit v1.2.3-58-ga151 From f37be01e6dc606f2fcc5e95c9933d948ce19bd35 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 22 Jun 2016 08:27:17 +0200 Subject: mfd: qcom_rpm: Parametrize also ack selector size The RPM has two sets of selectors (IPC bit fields): request and acknowledge. Apparently, some models use 4*32 bit words for select and some use 7*32 bit words for request, but all use 7*32 words for acknowledge bits. So apparently you can on the models with requests of 4*32 select bits send 4*32 messages and get 7*32 different replies, so on ACK interrupt, 7*32 bit words need to be read. This is how the vendor code apparently works. Cc: stable@vger.kernel.org Reported-by: Stephen Boyd Signed-off-by: Linus Walleij Reviewed-by: Bjorn Andersson Signed-off-by: Lee Jones --- drivers/mfd/qcom_rpm.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c index 710cae2a9b02..2e44323455dd 100644 --- a/drivers/mfd/qcom_rpm.c +++ b/drivers/mfd/qcom_rpm.c @@ -39,7 +39,8 @@ struct qcom_rpm_data { unsigned int req_sel_off; unsigned int ack_ctx_off; unsigned int ack_sel_off; - unsigned int sel_size; + unsigned int req_sel_size; + unsigned int ack_sel_size; }; struct qcom_rpm { @@ -160,7 +161,8 @@ static const struct qcom_rpm_data apq8064_template = { .req_sel_off = 11, .ack_ctx_off = 15, .ack_sel_off = 23, - .sel_size = 4, + .req_sel_size = 4, + .ack_sel_size = 7, }; static const struct qcom_rpm_resource msm8660_rpm_resource_table[] = { @@ -248,7 +250,8 @@ static const struct qcom_rpm_data msm8660_template = { .req_sel_off = 11, .ack_ctx_off = 19, .ack_sel_off = 27, - .sel_size = 7, + .req_sel_size = 7, + .ack_sel_size = 7, }; static const struct qcom_rpm_resource msm8960_rpm_resource_table[] = { @@ -335,7 +338,8 @@ static const struct qcom_rpm_data msm8960_template = { .req_sel_off = 11, .ack_ctx_off = 15, .ack_sel_off = 23, - .sel_size = 4, + .req_sel_size = 4, + .ack_sel_size = 7, }; static const struct qcom_rpm_resource ipq806x_rpm_resource_table[] = { @@ -380,7 +384,8 @@ static const struct qcom_rpm_data ipq806x_template = { .req_sel_off = 11, .ack_ctx_off = 15, .ack_sel_off = 23, - .sel_size = 4, + .req_sel_size = 4, + .ack_sel_size = 7, }; static const struct of_device_id qcom_rpm_of_match[] = { @@ -417,7 +422,7 @@ int qcom_rpm_write(struct qcom_rpm *rpm, writel_relaxed(buf[i], RPM_REQ_REG(rpm, res->target_id + i)); bitmap_set((unsigned long *)sel_mask, res->select_id, 1); - for (i = 0; i < rpm->data->sel_size; i++) { + for (i = 0; i < rpm->data->req_sel_size; i++) { writel_relaxed(sel_mask[i], RPM_CTRL_REG(rpm, rpm->data->req_sel_off + i)); } @@ -446,7 +451,7 @@ static irqreturn_t qcom_rpm_ack_interrupt(int irq, void *dev) int i; ack = readl_relaxed(RPM_CTRL_REG(rpm, rpm->data->ack_ctx_off)); - for (i = 0; i < rpm->data->sel_size; i++) + for (i = 0; i < rpm->data->ack_sel_size; i++) writel_relaxed(0, RPM_CTRL_REG(rpm, rpm->data->ack_sel_off + i)); writel(0, RPM_CTRL_REG(rpm, rpm->data->ack_ctx_off)); -- cgit v1.2.3-58-ga151