summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-11 07:20:17 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-11 07:20:17 -0700
commit883cad5ba8cc2d9b740b4ad0a8a91063c99c75a3 (patch)
treef91886f6747bbcf239c42cd1c8d55f86f546e8e7 /drivers
parent8d08c0554244f95076cfe2a722e5207d974cd92d (diff)
parent556c242045f0c1613aac2e64dc5b2ff0e4bc89e1 (diff)
downloadlinux-883cad5ba8cc2d9b740b4ad0a8a91063c99c75a3.tar.bz2
Merge tag 'mfd-next-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones: "New Device Support: - Add support for AXP813 ADC to AXP20x - Add support for PM8005, PM8998 and PMI8998 New Functionality: - Add support for Battery Power Supply to AXP813 - Add support for SYSCON to SPARD SC27XX SPI - Add support for RTC to ChromeOS Embedded-Controller Fix-ups: - Remove unused code; exynos{4,5}-pmu, cros_ec, cros_ec_acpi_gpe - Remove duplicate error messages (-ENOMEM, etc); htc-i2cpld, janz-cmodio, max8997, rc5t583, sm501, smsc-ece1099, abx500-core, si476x-i2c, ti_am335x_tscadc, tps65090, tps6586x, tps65910, tps80031, twl6030-irq, viperboard - Succinctly use ptr to struct in sizeof(); rc5t583, abx500-core, sm501, smsc-ece1099 - Simplify syntax for NULL ptr checking; abx500-core, sm501 - No not unnecessarily initialise variables; tps65910, tps65910 - Reorganise and simplify driver data; omap-usb-tll - Move to SPDX license statement; tps68470 - Probe ADCs via DT; axp20x - Use new GPIOD API; arizona-core - Constify things; axp20x - Reduce code-size (use MACROS, etc); axp20x, omap-usb-host - Add DT support/docs; motorola-cpcap - Remove VLAs; rave-sp - Use devm_* managed resources; cros_ec - Interrogate HW for firmware version; rave-sp - Provide ACPI support for ChromeOS Embedded-Controller Bug Fixes: - Reorder ordered (enum) device list; tps65218 - Only accept valid data from the offset; rave-sp - Refrain from copying junk from failed SPI read; cros_ec_dev - Fix potential memory leaks; pcf50633-core - Fix clock initialisation; twl-core - Fix build-issue; tps65911 - Fix off-by-one error; tps65911 - Fix code ordering issues; intel-lpss - Fix COMPILE_TEST related issues; pwm-stm32 - Fix broken MMC card detection; asic3 - Fix clocking related issues; intel-lpss-pci" * tag 'mfd-next-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (84 commits) mfd: cros_ec: Remove unused __remove function mfd: wm97xx-core: Platform data can be NULL mfd: cros_ec_dev: Don't advertise junk features on failure mfd: cros_ec: Use devm_kzalloc for private data mfd: intel-lpss: Fix Intel Cannon Lake LPSS I2C input clock mfd: asic3: Fix broken MMC card detection mfd: timberdale: Fix spelling mistake "Uknown" -> "Unknown" mfd: omap-usb-host: Use match_string() helper mfd: stm32-timers: Fix pwm-stm32 linker issue with COMPILE_TEST pwm: stm32: Initialize raw local variables mfd: arizona: Update DT doc to support more standard Reset binding dt-bindings: mfd: Add bindings for DA9063L mfd: intel-lpss: Correct names of RESETS register bits mfd: qcom-spmi-pmic: Add support for pm8005, pm8998 and pmi8998 mfd: intel-lpss: Program REMAP register in PIO mode mfd: cros_ec_i2c: Moving the system sleep pm ops to late mfd: cros_ec_i2c: Add ACPI module device table mfd: cros_ec_dev: Register shutdown function for debugfs mfd: cros_ec_dev: Register cros-ec-rtc driver as a subdevice mfd: cros_ec: Don't try to grab log when suspended ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/keyboard/Kconfig9
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/mtk-pmic-keys.c339
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/ab8500-debugfs.c3
-rw-r--r--drivers/mfd/abx500-core.c25
-rw-r--r--drivers/mfd/arizona-core.c53
-rw-r--r--drivers/mfd/asic3.c3
-rw-r--r--drivers/mfd/atmel-smc.c1
-rw-r--r--drivers/mfd/axp20x.c252
-rw-r--r--drivers/mfd/cros_ec.c41
-rw-r--r--drivers/mfd/cros_ec_acpi_gpe.c103
-rw-r--r--drivers/mfd/cros_ec_dev.c45
-rw-r--r--drivers/mfd/cros_ec_i2c.c17
-rw-r--r--drivers/mfd/da9062-core.c462
-rw-r--r--drivers/mfd/htc-i2cpld.c4
-rw-r--r--drivers/mfd/intel-lpss-pci.c25
-rw-r--r--drivers/mfd/intel-lpss.c8
-rw-r--r--drivers/mfd/janz-cmodio.c4
-rw-r--r--drivers/mfd/jz4740-adc.c4
-rw-r--r--drivers/mfd/max8997.c4
-rw-r--r--drivers/mfd/mt6397-core.c26
-rw-r--r--drivers/mfd/omap-usb-host.c24
-rw-r--r--drivers/mfd/omap-usb-tll.c60
-rw-r--r--drivers/mfd/pcf50633-core.c7
-rw-r--r--drivers/mfd/qcom-spmi-pmic.c6
-rw-r--r--drivers/mfd/rave-sp.c118
-rw-r--r--drivers/mfd/rc5t583.c6
-rw-r--r--drivers/mfd/si476x-i2c.c6
-rw-r--r--drivers/mfd/sm501.c32
-rw-r--r--drivers/mfd/smsc-ece1099.c7
-rw-r--r--drivers/mfd/sprd-sc27xx-spi.c3
-rw-r--r--drivers/mfd/stm32-timers.c201
-rw-r--r--drivers/mfd/syscon.c2
-rw-r--r--drivers/mfd/ti_am335x_tscadc.c5
-rw-r--r--drivers/mfd/timberdale.c2
-rw-r--r--drivers/mfd/tps65090.c4
-rw-r--r--drivers/mfd/tps6586x.c4
-rw-r--r--drivers/mfd/tps65910.c18
-rw-r--r--drivers/mfd/tps65911-comparator.c17
-rw-r--r--drivers/mfd/tps68470.c10
-rw-r--r--drivers/mfd/tps80031.c4
-rw-r--r--drivers/mfd/twl-core.c2
-rw-r--r--drivers/mfd/twl6030-irq.c4
-rw-r--r--drivers/mfd/viperboard.c4
-rw-r--r--drivers/mfd/wm97xx-core.c2
-rw-r--r--drivers/platform/chrome/cros_ec_debugfs.c20
-rw-r--r--drivers/pwm/pwm-stm32.c257
-rw-r--r--drivers/rtc/rtc-mt6397.c7
49 files changed, 1364 insertions, 898 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 2b469cc47a78..6bd97ffee761 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -747,4 +747,13 @@ config KEYBOARD_BCM
To compile this driver as a module, choose M here: the
module will be called bcm-keypad.
+config KEYBOARD_MTK_PMIC
+ tristate "MediaTek PMIC keys support"
+ depends on MFD_MT6397
+ help
+ Say Y here if you want to use the pmic keys (powerkey/homekey).
+
+ To compile this driver as a module, choose M here: the
+ module will be called pmic-keys.
+
endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 8fab920afa58..182e92985dbf 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o
obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o
obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o
obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_touchkey.o
+obj-$(CONFIG_KEYBOARD_MTK_PMIC) += mtk-pmic-keys.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o
obj-$(CONFIG_KEYBOARD_NSPIRE) += nspire-keypad.o
diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c
new file mode 100644
index 000000000000..02c67a1749fc
--- /dev/null
+++ b/drivers/input/keyboard/mtk-pmic-keys.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2017 MediaTek, Inc.
+ *
+ * Author: Chen Zhong <chen.zhong@mediatek.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/mt6323/registers.h>
+#include <linux/mfd/mt6397/registers.h>
+#include <linux/mfd/mt6397/core.h>
+
+#define MTK_PMIC_PWRKEY_RST_EN_MASK 0x1
+#define MTK_PMIC_PWRKEY_RST_EN_SHIFT 6
+#define MTK_PMIC_HOMEKEY_RST_EN_MASK 0x1
+#define MTK_PMIC_HOMEKEY_RST_EN_SHIFT 5
+#define MTK_PMIC_RST_DU_MASK 0x3
+#define MTK_PMIC_RST_DU_SHIFT 8
+
+#define MTK_PMIC_PWRKEY_RST \
+ (MTK_PMIC_PWRKEY_RST_EN_MASK << MTK_PMIC_PWRKEY_RST_EN_SHIFT)
+#define MTK_PMIC_HOMEKEY_RST \
+ (MTK_PMIC_HOMEKEY_RST_EN_MASK << MTK_PMIC_HOMEKEY_RST_EN_SHIFT)
+
+#define MTK_PMIC_PWRKEY_INDEX 0
+#define MTK_PMIC_HOMEKEY_INDEX 1
+#define MTK_PMIC_MAX_KEY_COUNT 2
+
+struct mtk_pmic_keys_regs {
+ u32 deb_reg;
+ u32 deb_mask;
+ u32 intsel_reg;
+ u32 intsel_mask;
+};
+
+#define MTK_PMIC_KEYS_REGS(_deb_reg, _deb_mask, \
+ _intsel_reg, _intsel_mask) \
+{ \
+ .deb_reg = _deb_reg, \
+ .deb_mask = _deb_mask, \
+ .intsel_reg = _intsel_reg, \
+ .intsel_mask = _intsel_mask, \
+}
+
+struct mtk_pmic_regs {
+ const struct mtk_pmic_keys_regs keys_regs[MTK_PMIC_MAX_KEY_COUNT];
+ u32 pmic_rst_reg;
+};
+
+static const struct mtk_pmic_regs mt6397_regs = {
+ .keys_regs[MTK_PMIC_PWRKEY_INDEX] =
+ MTK_PMIC_KEYS_REGS(MT6397_CHRSTATUS,
+ 0x8, MT6397_INT_RSV, 0x10),
+ .keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
+ MTK_PMIC_KEYS_REGS(MT6397_OCSTATUS2,
+ 0x10, MT6397_INT_RSV, 0x8),
+ .pmic_rst_reg = MT6397_TOP_RST_MISC,
+};
+
+static const struct mtk_pmic_regs mt6323_regs = {
+ .keys_regs[MTK_PMIC_PWRKEY_INDEX] =
+ MTK_PMIC_KEYS_REGS(MT6323_CHRSTATUS,
+ 0x2, MT6323_INT_MISC_CON, 0x10),
+ .keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
+ MTK_PMIC_KEYS_REGS(MT6323_CHRSTATUS,
+ 0x4, MT6323_INT_MISC_CON, 0x8),
+ .pmic_rst_reg = MT6323_TOP_RST_MISC,
+};
+
+struct mtk_pmic_keys_info {
+ struct mtk_pmic_keys *keys;
+ const struct mtk_pmic_keys_regs *regs;
+ unsigned int keycode;
+ int irq;
+ bool wakeup:1;
+};
+
+struct mtk_pmic_keys {
+ struct input_dev *input_dev;
+ struct device *dev;
+ struct regmap *regmap;
+ struct mtk_pmic_keys_info keys[MTK_PMIC_MAX_KEY_COUNT];
+};
+
+enum mtk_pmic_keys_lp_mode {
+ LP_DISABLE,
+ LP_ONEKEY,
+ LP_TWOKEY,
+};
+
+static void mtk_pmic_keys_lp_reset_setup(struct mtk_pmic_keys *keys,
+ u32 pmic_rst_reg)
+{
+ int ret;
+ u32 long_press_mode, long_press_debounce;
+
+ ret = of_property_read_u32(keys->dev->of_node,
+ "power-off-time-sec", &long_press_debounce);
+ if (ret)
+ long_press_debounce = 0;
+
+ regmap_update_bits(keys->regmap, pmic_rst_reg,
+ MTK_PMIC_RST_DU_MASK << MTK_PMIC_RST_DU_SHIFT,
+ long_press_debounce << MTK_PMIC_RST_DU_SHIFT);
+
+ ret = of_property_read_u32(keys->dev->of_node,
+ "mediatek,long-press-mode", &long_press_mode);
+ if (ret)
+ long_press_mode = LP_DISABLE;
+
+ switch (long_press_mode) {
+ case LP_ONEKEY:
+ regmap_update_bits(keys->regmap, pmic_rst_reg,
+ MTK_PMIC_PWRKEY_RST,
+ MTK_PMIC_PWRKEY_RST);
+ regmap_update_bits(keys->regmap, pmic_rst_reg,
+ MTK_PMIC_HOMEKEY_RST,
+ 0);
+ break;
+ case LP_TWOKEY:
+ regmap_update_bits(keys->regmap, pmic_rst_reg,
+ MTK_PMIC_PWRKEY_RST,
+ MTK_PMIC_PWRKEY_RST);
+ regmap_update_bits(keys->regmap, pmic_rst_reg,
+ MTK_PMIC_HOMEKEY_RST,
+ MTK_PMIC_HOMEKEY_RST);
+ break;
+ case LP_DISABLE:
+ regmap_update_bits(keys->regmap, pmic_rst_reg,
+ MTK_PMIC_PWRKEY_RST,
+ 0);
+ regmap_update_bits(keys->regmap, pmic_rst_reg,
+ MTK_PMIC_HOMEKEY_RST,
+ 0);
+ break;
+ default:
+ break;
+ }
+}
+
+static irqreturn_t mtk_pmic_keys_irq_handler_thread(int irq, void *data)
+{
+ struct mtk_pmic_keys_info *info = data;
+ u32 key_deb, pressed;
+
+ regmap_read(info->keys->regmap, info->regs->deb_reg, &key_deb);
+
+ key_deb &= info->regs->deb_mask;
+
+ pressed = !key_deb;
+
+ input_report_key(info->keys->input_dev, info->keycode, pressed);
+ input_sync(info->keys->input_dev);
+
+ dev_dbg(info->keys->dev, "(%s) key =%d using PMIC\n",
+ pressed ? "pressed" : "released", info->keycode);
+
+ return IRQ_HANDLED;
+}
+
+static int mtk_pmic_key_setup(struct mtk_pmic_keys *keys,
+ struct mtk_pmic_keys_info *info)
+{
+ int ret;
+
+ info->keys = keys;
+
+ ret = regmap_update_bits(keys->regmap, info->regs->intsel_reg,
+ info->regs->intsel_mask,
+ info->regs->intsel_mask);
+ if (ret < 0)
+ return ret;
+
+ ret = devm_request_threaded_irq(keys->dev, info->irq, NULL,
+ mtk_pmic_keys_irq_handler_thread,
+ IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
+ "mtk-pmic-keys", info);
+ if (ret) {
+ dev_err(keys->dev, "Failed to request IRQ: %d: %d\n",
+ info->irq, ret);
+ return ret;
+ }
+
+ input_set_capability(keys->input_dev, EV_KEY, info->keycode);
+
+ return 0;
+}
+
+static int __maybe_unused mtk_pmic_keys_suspend(struct device *dev)
+{
+ struct mtk_pmic_keys *keys = dev_get_drvdata(dev);
+ int index;
+
+ for (index = 0; index < MTK_PMIC_MAX_KEY_COUNT; index++) {
+ if (keys->keys[index].wakeup)
+ enable_irq_wake(keys->keys[index].irq);
+ }
+
+ return 0;
+}
+
+static int __maybe_unused mtk_pmic_keys_resume(struct device *dev)
+{
+ struct mtk_pmic_keys *keys = dev_get_drvdata(dev);
+ int index;
+
+ for (index = 0; index < MTK_PMIC_MAX_KEY_COUNT; index++) {
+ if (keys->keys[index].wakeup)
+ disable_irq_wake(keys->keys[index].irq);
+ }
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(mtk_pmic_keys_pm_ops, mtk_pmic_keys_suspend,
+ mtk_pmic_keys_resume);
+
+static const struct of_device_id of_mtk_pmic_keys_match_tbl[] = {
+ {
+ .compatible = "mediatek,mt6397-keys",
+ .data = &mt6397_regs,
+ }, {
+ .compatible = "mediatek,mt6323-keys",
+ .data = &mt6323_regs,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, of_mtk_pmic_keys_match_tbl);
+
+static int mtk_pmic_keys_probe(struct platform_device *pdev)
+{
+ int error, index = 0;
+ unsigned int keycount;
+ struct mt6397_chip *pmic_chip = dev_get_drvdata(pdev->dev.parent);
+ struct device_node *node = pdev->dev.of_node, *child;
+ struct mtk_pmic_keys *keys;
+ const struct mtk_pmic_regs *mtk_pmic_regs;
+ struct input_dev *input_dev;
+ const struct of_device_id *of_id =
+ of_match_device(of_mtk_pmic_keys_match_tbl, &pdev->dev);
+
+ keys = devm_kzalloc(&pdev->dev, sizeof(*keys), GFP_KERNEL);
+ if (!keys)
+ return -ENOMEM;
+
+ keys->dev = &pdev->dev;
+ keys->regmap = pmic_chip->regmap;
+ mtk_pmic_regs = of_id->data;
+
+ keys->input_dev = input_dev = devm_input_allocate_device(keys->dev);
+ if (!input_dev) {
+ dev_err(keys->dev, "input allocate device fail.\n");
+ return -ENOMEM;
+ }
+
+ input_dev->name = "mtk-pmic-keys";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0001;
+
+ keycount = of_get_available_child_count(node);
+ if (keycount > MTK_PMIC_MAX_KEY_COUNT) {
+ dev_err(keys->dev, "too many keys defined (%d)\n", keycount);
+ return -EINVAL;
+ }
+
+ for_each_child_of_node(node, child) {
+ keys->keys[index].regs = &mtk_pmic_regs->keys_regs[index];
+
+ keys->keys[index].irq = platform_get_irq(pdev, index);
+ if (keys->keys[index].irq < 0)
+ return keys->keys[index].irq;
+
+ error = of_property_read_u32(child,
+ "linux,keycodes", &keys->keys[index].keycode);
+ if (error) {
+ dev_err(keys->dev,
+ "failed to read key:%d linux,keycode property: %d\n",
+ index, error);
+ return error;
+ }
+
+ if (of_property_read_bool(child, "wakeup-source"))
+ keys->keys[index].wakeup = true;
+
+ error = mtk_pmic_key_setup(keys, &keys->keys[index]);
+ if (error)
+ return error;
+
+ index++;
+ }
+
+ error = input_register_device(input_dev);
+ if (error) {
+ dev_err(&pdev->dev,
+ "register input device failed (%d)\n", error);
+ return error;
+ }
+
+ mtk_pmic_keys_lp_reset_setup(keys, mtk_pmic_regs->pmic_rst_reg);
+
+ platform_set_drvdata(pdev, keys);
+
+ return 0;
+}
+
+static struct platform_driver pmic_keys_pdrv = {
+ .probe = mtk_pmic_keys_probe,
+ .driver = {
+ .name = "mtk-pmic-keys",
+ .of_match_table = of_mtk_pmic_keys_match_tbl,
+ .pm = &mtk_pmic_keys_pm_ops,
+ },
+};
+
+module_platform_driver(pmic_keys_pdrv);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Chen Zhong <chen.zhong@mediatek.com>");
+MODULE_DESCRIPTION("MTK pmic-keys driver v0.1");
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index d9d2cf0d32ef..e9fd20dba18d 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
cros_ec_core-objs := cros_ec.o
-cros_ec_core-$(CONFIG_ACPI) += cros_ec_acpi_gpe.o
obj-$(CONFIG_MFD_CROS_EC) += cros_ec_core.o
obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
index 8ba41073dd89..831a1ceb2ed2 100644
--- a/drivers/mfd/ab8500-debugfs.c
+++ b/drivers/mfd/ab8500-debugfs.c
@@ -2519,11 +2519,10 @@ static ssize_t ab8500_subscribe_write(struct file *file,
if (!dev_attr[irq_index])
return -ENOMEM;
- event_name[irq_index] = kmalloc(count, GFP_KERNEL);
+ event_name[irq_index] = kasprintf(GFP_KERNEL, "%lu", user_val);
if (!event_name[irq_index])
return -ENOMEM;
- sprintf(event_name[irq_index], "%lu", user_val);
dev_attr[irq_index]->show = show_irq;
dev_attr[irq_index]->store = NULL;
dev_attr[irq_index]->attr.name = event_name[irq_index];
diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c
index 0d3846a4767c..f282d39a5917 100644
--- a/drivers/mfd/abx500-core.c
+++ b/drivers/mfd/abx500-core.c
@@ -37,15 +37,12 @@ int abx500_register_ops(struct device *dev, struct abx500_ops *ops)
{
struct abx500_device_entry *dev_entry;
- dev_entry = devm_kzalloc(dev,
- sizeof(struct abx500_device_entry),
- GFP_KERNEL);
- if (!dev_entry) {
- dev_err(dev, "register_ops kzalloc failed");
+ dev_entry = devm_kzalloc(dev, sizeof(*dev_entry), GFP_KERNEL);
+ if (!dev_entry)
return -ENOMEM;
- }
+
dev_entry->dev = dev;
- memcpy(&dev_entry->ops, ops, sizeof(struct abx500_ops));
+ memcpy(&dev_entry->ops, ops, sizeof(*ops));
list_add_tail(&dev_entry->list, &abx500_list);
return 0;
@@ -68,7 +65,7 @@ int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
struct abx500_ops *ops;
lookup_ops(dev->parent, &ops);
- if ((ops != NULL) && (ops->set_register != NULL))
+ if (ops && ops->set_register)
return ops->set_register(dev, bank, reg, value);
else
return -ENOTSUPP;
@@ -81,7 +78,7 @@ int abx500_get_register_interruptible(struct device *dev, u8 bank, u8 reg,
struct abx500_ops *ops;
lookup_ops(dev->parent, &ops);
- if ((ops != NULL) && (ops->get_register != NULL))
+ if (ops && ops->get_register)
return ops->get_register(dev, bank, reg, value);
else
return -ENOTSUPP;
@@ -94,7 +91,7 @@ int abx500_get_register_page_interruptible(struct device *dev, u8 bank,
struct abx500_ops *ops;
lookup_ops(dev->parent, &ops);
- if ((ops != NULL) && (ops->get_register_page != NULL))
+ if (ops && ops->get_register_page)
return ops->get_register_page(dev, bank,
first_reg, regvals, numregs);
else
@@ -108,7 +105,7 @@ int abx500_mask_and_set_register_interruptible(struct device *dev, u8 bank,
struct abx500_ops *ops;
lookup_ops(dev->parent, &ops);
- if ((ops != NULL) && (ops->mask_and_set_register != NULL))
+ if (ops && ops->mask_and_set_register)
return ops->mask_and_set_register(dev, bank,
reg, bitmask, bitvalues);
else
@@ -121,7 +118,7 @@ int abx500_get_chip_id(struct device *dev)
struct abx500_ops *ops;
lookup_ops(dev->parent, &ops);
- if ((ops != NULL) && (ops->get_chip_id != NULL))
+ if (ops && ops->get_chip_id)
return ops->get_chip_id(dev);
else
return -ENOTSUPP;
@@ -133,7 +130,7 @@ int abx500_event_registers_startup_state_get(struct device *dev, u8 *event)
struct abx500_ops *ops;
lookup_ops(dev->parent, &ops);
- if ((ops != NULL) && (ops->event_registers_startup_state_get != NULL))
+ if (ops && ops->event_registers_startup_state_get)
return ops->event_registers_startup_state_get(dev, event);
else
return -ENOTSUPP;
@@ -145,7 +142,7 @@ int abx500_startup_irq_enabled(struct device *dev, unsigned int irq)
struct abx500_ops *ops;
lookup_ops(dev->parent, &ops);
- if ((ops != NULL) && (ops->startup_irq_enabled != NULL))
+ if (ops && ops->startup_irq_enabled)
return ops->startup_irq_enabled(dev, irq);
else
return -ENOTSUPP;
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 77875250abe5..83f1c5a516d9 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -13,13 +13,12 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/of_gpio.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -279,7 +278,7 @@ static int arizona_wait_for_boot(struct arizona *arizona)
static inline void arizona_enable_reset(struct arizona *arizona)
{
if (arizona->pdata.reset)
- gpio_set_value_cansleep(arizona->pdata.reset, 0);
+ gpiod_set_raw_value_cansleep(arizona->pdata.reset, 0);
}
static void arizona_disable_reset(struct arizona *arizona)
@@ -295,7 +294,7 @@ static void arizona_disable_reset(struct arizona *arizona)
break;
}
- gpio_set_value_cansleep(arizona->pdata.reset, 1);
+ gpiod_set_raw_value_cansleep(arizona->pdata.reset, 1);
usleep_range(1000, 5000);
}
}
@@ -799,14 +798,27 @@ static int arizona_of_get_core_pdata(struct arizona *arizona)
struct arizona_pdata *pdata = &arizona->pdata;
int ret, i;
- pdata->reset = of_get_named_gpio(arizona->dev->of_node, "wlf,reset", 0);
- if (pdata->reset == -EPROBE_DEFER) {
- return pdata->reset;
- } else if (pdata->reset < 0) {
- dev_err(arizona->dev, "Reset GPIO missing/malformed: %d\n",
- pdata->reset);
+ /* Handle old non-standard DT binding */
+ pdata->reset = devm_gpiod_get_from_of_node(arizona->dev,
+ arizona->dev->of_node,
+ "wlf,reset", 0,
+ GPIOD_OUT_LOW,
+ "arizona /RESET");
+ if (IS_ERR(pdata->reset)) {
+ ret = PTR_ERR(pdata->reset);
- pdata->reset = 0;
+ /*
+ * Reset missing will be caught when other binding is read
+ * but all other errors imply this binding is in use but has
+ * encountered a problem so should be handled.
+ */
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ else if (ret != -ENOENT && ret != -ENOSYS)
+ dev_err(arizona->dev, "Reset GPIO malformed: %d\n",
+ ret);
+
+ pdata->reset = NULL;
}
ret = of_property_read_u32_array(arizona->dev->of_node,
@@ -1050,14 +1062,19 @@ int arizona_dev_init(struct arizona *arizona)
goto err_early;
}
- if (arizona->pdata.reset) {
+ if (!arizona->pdata.reset) {
/* Start out with /RESET low to put the chip into reset */
- ret = devm_gpio_request_one(arizona->dev, arizona->pdata.reset,
- GPIOF_DIR_OUT | GPIOF_INIT_LOW,
- "arizona /RESET");
- if (ret != 0) {
- dev_err(dev, "Failed to request /RESET: %d\n", ret);
- goto err_dcvdd;
+ arizona->pdata.reset = devm_gpiod_get(arizona->dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(arizona->pdata.reset)) {
+ ret = PTR_ERR(arizona->pdata.reset);
+ if (ret == -EPROBE_DEFER)
+ goto err_dcvdd;
+
+ dev_err(arizona->dev,
+ "Reset GPIO missing/malformed: %d\n", ret);
+
+ arizona->pdata.reset = NULL;
}
}
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index cf2e25ab2940..1531302a50ec 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -31,6 +31,8 @@
#include <linux/mfd/ds1wm.h>
#include <linux/mfd/tmio.h>
+#include <linux/mmc/host.h>
+
enum {
ASIC3_CLOCK_SPI,
ASIC3_CLOCK_OWM,
@@ -719,6 +721,7 @@ static void asic3_mmc_clk_div(struct platform_device *pdev, int state)
static struct tmio_mmc_data asic3_mmc_data = {
.hclk = 24576000,
+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
.set_pwr = asic3_mmc_pwr,
.set_clk_div = asic3_mmc_clk_div,
};
diff --git a/drivers/mfd/atmel-smc.c b/drivers/mfd/atmel-smc.c
index 7d77948567d7..0adbd2e796fe 100644
--- a/drivers/mfd/atmel-smc.c
+++ b/drivers/mfd/atmel-smc.c
@@ -12,6 +12,7 @@
*/
#include <linux/mfd/syscon/atmel-smc.h>
+#include <linux/string.h>
/**
* atmel_smc_cs_conf_init - initialize a SMC CS conf
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index e94c72c2faa2..9a2ef3d9b8f8 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -169,131 +169,61 @@ static const struct regmap_access_table axp806_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges),
};
-static struct resource axp152_pek_resources[] = {
+static const struct resource axp152_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
-static struct resource axp20x_ac_power_supply_resources[] = {
+static const struct resource axp20x_ac_power_supply_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"),
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"),
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_OVER_V, "ACIN_OVER_V"),
};
-static struct resource axp20x_pek_resources[] = {
- {
- .name = "PEK_DBR",
- .start = AXP20X_IRQ_PEK_RIS_EDGE,
- .end = AXP20X_IRQ_PEK_RIS_EDGE,
- .flags = IORESOURCE_IRQ,
- }, {
- .name = "PEK_DBF",
- .start = AXP20X_IRQ_PEK_FAL_EDGE,
- .end = AXP20X_IRQ_PEK_FAL_EDGE,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp20x_pek_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
+ DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
-static struct resource axp20x_usb_power_supply_resources[] = {
+static const struct resource axp20x_usb_power_supply_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_VALID, "VBUS_VALID"),
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"),
};
-static struct resource axp22x_usb_power_supply_resources[] = {
+static const 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",
- .start = AXP22X_IRQ_PEK_RIS_EDGE,
- .end = AXP22X_IRQ_PEK_RIS_EDGE,
- .flags = IORESOURCE_IRQ,
- }, {
- .name = "PEK_DBF",
- .start = AXP22X_IRQ_PEK_FAL_EDGE,
- .end = AXP22X_IRQ_PEK_FAL_EDGE,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp22x_pek_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
-static struct resource axp288_power_button_resources[] = {
- {
- .name = "PEK_DBR",
- .start = AXP288_IRQ_POKP,
- .end = AXP288_IRQ_POKP,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "PEK_DBF",
- .start = AXP288_IRQ_POKN,
- .end = AXP288_IRQ_POKN,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp288_power_button_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP288_IRQ_POKP, "PEK_DBR"),
+ DEFINE_RES_IRQ_NAMED(AXP288_IRQ_POKN, "PEK_DBF"),
};
-static struct resource axp288_fuel_gauge_resources[] = {
- {
- .start = AXP288_IRQ_QWBTU,
- .end = AXP288_IRQ_QWBTU,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_WBTU,
- .end = AXP288_IRQ_WBTU,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_QWBTO,
- .end = AXP288_IRQ_QWBTO,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_WBTO,
- .end = AXP288_IRQ_WBTO,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_WL2,
- .end = AXP288_IRQ_WL2,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_WL1,
- .end = AXP288_IRQ_WL1,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp288_fuel_gauge_resources[] = {
+ DEFINE_RES_IRQ(AXP288_IRQ_QWBTU),
+ DEFINE_RES_IRQ(AXP288_IRQ_WBTU),
+ DEFINE_RES_IRQ(AXP288_IRQ_QWBTO),
+ DEFINE_RES_IRQ(AXP288_IRQ_WBTO),
+ DEFINE_RES_IRQ(AXP288_IRQ_WL2),
+ DEFINE_RES_IRQ(AXP288_IRQ_WL1),
};
-static struct resource axp803_pek_resources[] = {
- {
- .name = "PEK_DBR",
- .start = AXP803_IRQ_PEK_RIS_EDGE,
- .end = AXP803_IRQ_PEK_RIS_EDGE,
- .flags = IORESOURCE_IRQ,
- }, {
- .name = "PEK_DBF",
- .start = AXP803_IRQ_PEK_FAL_EDGE,
- .end = AXP803_IRQ_PEK_FAL_EDGE,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp803_pek_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
+ DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
-static struct resource axp809_pek_resources[] = {
- {
- .name = "PEK_DBR",
- .start = AXP809_IRQ_PEK_RIS_EDGE,
- .end = AXP809_IRQ_PEK_RIS_EDGE,
- .flags = IORESOURCE_IRQ,
- }, {
- .name = "PEK_DBF",
- .start = AXP809_IRQ_PEK_FAL_EDGE,
- .end = AXP809_IRQ_PEK_FAL_EDGE,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp809_pek_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
+ DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
static const struct regmap_config axp152_regmap_config = {
@@ -520,11 +450,11 @@ static const struct regmap_irq axp806_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP806, DCDCC_V_LOW, 0, 5),
INIT_REGMAP_IRQ(AXP806, DCDCD_V_LOW, 0, 6),
INIT_REGMAP_IRQ(AXP806, DCDCE_V_LOW, 0, 7),
- INIT_REGMAP_IRQ(AXP806, PWROK_LONG, 1, 0),
- INIT_REGMAP_IRQ(AXP806, PWROK_SHORT, 1, 1),
+ INIT_REGMAP_IRQ(AXP806, POK_LONG, 1, 0),
+ INIT_REGMAP_IRQ(AXP806, POK_SHORT, 1, 1),
INIT_REGMAP_IRQ(AXP806, WAKEUP, 1, 4),
- INIT_REGMAP_IRQ(AXP806, PWROK_FALL, 1, 5),
- INIT_REGMAP_IRQ(AXP806, PWROK_RISE, 1, 6),
+ INIT_REGMAP_IRQ(AXP806, POK_FALL, 1, 5),
+ INIT_REGMAP_IRQ(AXP806, POK_RISE, 1, 6),
};
static const struct regmap_irq axp809_regmap_irqs[] = {
@@ -648,7 +578,7 @@ static const struct regmap_irq_chip axp809_regmap_irq_chip = {
.num_regs = 5,
};
-static struct mfd_cell axp20x_cells[] = {
+static const struct mfd_cell axp20x_cells[] = {
{
.name = "axp20x-gpio",
.of_compatible = "x-powers,axp209-gpio",
@@ -660,6 +590,7 @@ static struct mfd_cell axp20x_cells[] = {
.name = "axp20x-regulator",
}, {
.name = "axp20x-adc",
+ .of_compatible = "x-powers,axp209-adc",
}, {
.name = "axp20x-battery-power-supply",
.of_compatible = "x-powers,axp209-battery-power-supply",
@@ -676,7 +607,7 @@ static struct mfd_cell axp20x_cells[] = {
},
};
-static struct mfd_cell axp221_cells[] = {
+static const struct mfd_cell axp221_cells[] = {
{
.name = "axp221-pek",
.num_resources = ARRAY_SIZE(axp22x_pek_resources),
@@ -684,7 +615,8 @@ static struct mfd_cell axp221_cells[] = {
}, {
.name = "axp20x-regulator",
}, {
- .name = "axp22x-adc"
+ .name = "axp22x-adc",
+ .of_compatible = "x-powers,axp221-adc",
}, {
.name = "axp20x-ac-power-supply",
.of_compatible = "x-powers,axp221-ac-power-supply",
@@ -701,13 +633,14 @@ static struct mfd_cell axp221_cells[] = {
},
};
-static struct mfd_cell axp223_cells[] = {
+static const struct mfd_cell axp223_cells[] = {
{
.name = "axp221-pek",
.num_resources = ARRAY_SIZE(axp22x_pek_resources),
.resources = axp22x_pek_resources,
}, {
.name = "axp22x-adc",
+ .of_compatible = "x-powers,axp221-adc",
}, {
.name = "axp20x-battery-power-supply",
.of_compatible = "x-powers,axp221-battery-power-supply",
@@ -726,7 +659,7 @@ static struct mfd_cell axp223_cells[] = {
},
};
-static struct mfd_cell axp152_cells[] = {
+static const struct mfd_cell axp152_cells[] = {
{
.name = "axp20x-pek",
.num_resources = ARRAY_SIZE(axp152_pek_resources),
@@ -734,87 +667,30 @@ static struct mfd_cell axp152_cells[] = {
},
};
-static struct resource axp288_adc_resources[] = {
- {
- .name = "GPADC",
- .start = AXP288_IRQ_GPADC,
- .end = AXP288_IRQ_GPADC,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp288_adc_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"),
};
-static struct resource axp288_extcon_resources[] = {
- {
- .start = AXP288_IRQ_VBUS_FALL,
- .end = AXP288_IRQ_VBUS_FALL,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_VBUS_RISE,
- .end = AXP288_IRQ_VBUS_RISE,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_MV_CHNG,
- .end = AXP288_IRQ_MV_CHNG,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_BC_USB_CHNG,
- .end = AXP288_IRQ_BC_USB_CHNG,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp288_extcon_resources[] = {
+ DEFINE_RES_IRQ(AXP288_IRQ_VBUS_FALL),
+ DEFINE_RES_IRQ(AXP288_IRQ_VBUS_RISE),
+ DEFINE_RES_IRQ(AXP288_IRQ_MV_CHNG),
+ DEFINE_RES_IRQ(AXP288_IRQ_BC_USB_CHNG),
};
-static struct resource axp288_charger_resources[] = {
- {
- .start = AXP288_IRQ_OV,
- .end = AXP288_IRQ_OV,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_DONE,
- .end = AXP288_IRQ_DONE,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_CHARGING,
- .end = AXP288_IRQ_CHARGING,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_SAFE_QUIT,
- .end = AXP288_IRQ_SAFE_QUIT,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_SAFE_ENTER,
- .end = AXP288_IRQ_SAFE_ENTER,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_QCBTU,
- .end = AXP288_IRQ_QCBTU,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_CBTU,
- .end = AXP288_IRQ_CBTU,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_QCBTO,
- .end = AXP288_IRQ_QCBTO,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_CBTO,
- .end = AXP288_IRQ_CBTO,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp288_charger_resources[] = {
+ DEFINE_RES_IRQ(AXP288_IRQ_OV),
+ DEFINE_RES_IRQ(AXP288_IRQ_DONE),
+ DEFINE_RES_IRQ(AXP288_IRQ_CHARGING),
+ DEFINE_RES_IRQ(AXP288_IRQ_SAFE_QUIT),
+ DEFINE_RES_IRQ(AXP288_IRQ_SAFE_ENTER),
+ DEFINE_RES_IRQ(AXP288_IRQ_QCBTU),
+ DEFINE_RES_IRQ(AXP288_IRQ_CBTU),
+ DEFINE_RES_IRQ(AXP288_IRQ_QCBTO),
+ DEFINE_RES_IRQ(AXP288_IRQ_CBTO),
};
-static struct mfd_cell axp288_cells[] = {
+static const struct mfd_cell axp288_cells[] = {
{
.name = "axp288_adc",
.num_resources = ARRAY_SIZE(axp288_adc_resources),
@@ -845,7 +721,7 @@ static struct mfd_cell axp288_cells[] = {
},
};
-static struct mfd_cell axp803_cells[] = {
+static const struct mfd_cell axp803_cells[] = {
{
.name = "axp221-pek",
.num_resources = ARRAY_SIZE(axp803_pek_resources),
@@ -854,14 +730,14 @@ static struct mfd_cell axp803_cells[] = {
{ .name = "axp20x-regulator" },
};
-static struct mfd_cell axp806_cells[] = {
+static const struct mfd_cell axp806_cells[] = {
{
.id = 2,
.name = "axp20x-regulator",
},
};
-static struct mfd_cell axp809_cells[] = {
+static const struct mfd_cell axp809_cells[] = {
{
.name = "axp221-pek",
.num_resources = ARRAY_SIZE(axp809_pek_resources),
@@ -872,7 +748,7 @@ static struct mfd_cell axp809_cells[] = {
},
};
-static struct mfd_cell axp813_cells[] = {
+static const struct mfd_cell axp813_cells[] = {
{
.name = "axp221-pek",
.num_resources = ARRAY_SIZE(axp803_pek_resources),
@@ -882,7 +758,13 @@ static struct mfd_cell axp813_cells[] = {
}, {
.name = "axp20x-gpio",
.of_compatible = "x-powers,axp813-gpio",
- }
+ }, {
+ .name = "axp813-adc",
+ .of_compatible = "x-powers,axp813-adc",
+ }, {
+ .name = "axp20x-battery-power-supply",
+ .of_compatible = "x-powers,axp813-battery-power-supply",
+ },
};
static struct axp20x_dev *axp20x_pm_power_off;
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index 36156a41499c..65a9757a6d21 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -112,12 +112,16 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
mutex_init(&ec_dev->lock);
- cros_ec_query_all(ec_dev);
+ err = cros_ec_query_all(ec_dev);
+ if (err) {
+ dev_err(dev, "Cannot identify the EC: error %d\n", err);
+ return err;
+ }
if (ec_dev->irq) {
- err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- "chromeos-ec", ec_dev);
+ err = devm_request_threaded_irq(dev, ec_dev->irq, NULL,
+ ec_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "chromeos-ec", ec_dev);
if (err) {
dev_err(dev, "Failed to request IRQ %d: %d",
ec_dev->irq, err);
@@ -131,7 +135,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
dev_err(dev,
"Failed to register Embedded Controller subdevice %d\n",
err);
- goto fail_mfd;
+ return err;
}
if (ec_dev->max_passthru) {
@@ -149,7 +153,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
dev_err(dev,
"Failed to register Power Delivery subdevice %d\n",
err);
- goto fail_mfd;
+ return err;
}
}
@@ -158,7 +162,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
if (err) {
mfd_remove_devices(dev);
dev_err(dev, "Failed to register sub-devices\n");
- goto fail_mfd;
+ return err;
}
}
@@ -173,14 +177,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
dev_info(dev, "Chrome EC device registered\n");
- cros_ec_acpi_install_gpe_handler(dev);
-
return 0;
-
-fail_mfd:
- if (ec_dev->irq)
- free_irq(ec_dev->irq, ec_dev);
- return err;
}
EXPORT_SYMBOL(cros_ec_register);
@@ -188,11 +185,6 @@ int cros_ec_remove(struct cros_ec_device *ec_dev)
{
mfd_remove_devices(ec_dev->dev);
- cros_ec_acpi_remove_gpe_handler();
-
- if (ec_dev->irq)
- free_irq(ec_dev->irq, ec_dev);
-
return 0;
}
EXPORT_SYMBOL(cros_ec_remove);
@@ -204,14 +196,9 @@ int cros_ec_suspend(struct cros_ec_device *ec_dev)
int ret;
u8 sleep_event;
- if (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) {
- sleep_event = HOST_SLEEP_EVENT_S3_SUSPEND;
- } else {
- sleep_event = HOST_SLEEP_EVENT_S0IX_SUSPEND;
-
- /* Clearing the GPE status for any pending event */
- cros_ec_acpi_clear_gpe();
- }
+ sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ?
+ HOST_SLEEP_EVENT_S3_SUSPEND :
+ HOST_SLEEP_EVENT_S0IX_SUSPEND;
ret = cros_ec_sleep_event(ec_dev, sleep_event);
if (ret < 0)
diff --git a/drivers/mfd/cros_ec_acpi_gpe.c b/drivers/mfd/cros_ec_acpi_gpe.c
deleted file mode 100644
index 56d305dab2d4..000000000000
--- a/drivers/mfd/cros_ec_acpi_gpe.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * ChromeOS EC multi-function device
- *
- * Copyright (C) 2017 Google, Inc
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that 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.
- *
- * The ChromeOS EC multi function device is used to mux all the requests
- * to the EC device for its multiple features: keyboard controller,
- * battery charging and regulator control, firmware update.
- */
-#include <linux/acpi.h>
-
-#define ACPI_LID_DEVICE "LID0"
-
-static int ec_wake_gpe = -EINVAL;
-
-/*
- * This handler indicates to ACPI core that this GPE should stay enabled for
- * lid to work in suspend to idle path.
- */
-static u32 cros_ec_gpe_handler(acpi_handle gpe_device, u32 gpe_number,
- void *data)
-{
- return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
-}
-
-/*
- * Get ACPI GPE for LID0 device.
- */
-static int cros_ec_get_ec_wake_gpe(struct device *dev)
-{
- struct acpi_device *cros_acpi_dev;
- struct acpi_device *adev;
- acpi_handle handle;
- acpi_status status;
- int ret;
-
- cros_acpi_dev = ACPI_COMPANION(dev);
-
- if (!cros_acpi_dev || !cros_acpi_dev->parent ||
- !cros_acpi_dev->parent->handle)
- return -EINVAL;
-
- status = acpi_get_handle(cros_acpi_dev->parent->handle, ACPI_LID_DEVICE,
- &handle);
- if (ACPI_FAILURE(status))
- return -EINVAL;
-
- ret = acpi_bus_get_device(handle, &adev);
- if (ret)
- return ret;
-
- return adev->wakeup.gpe_number;
-}
-
-int cros_ec_acpi_install_gpe_handler(struct device *dev)
-{
- acpi_status status;
-
- ec_wake_gpe = cros_ec_get_ec_wake_gpe(dev);
-
- if (ec_wake_gpe < 0)
- return ec_wake_gpe;
-
- status = acpi_install_gpe_handler(NULL, ec_wake_gpe,
- ACPI_GPE_EDGE_TRIGGERED,
- &cros_ec_gpe_handler, NULL);
- if (ACPI_FAILURE(status))
- return -ENODEV;
-
- dev_info(dev, "Initialized, GPE = 0x%x\n", ec_wake_gpe);
-
- return 0;
-}
-
-void cros_ec_acpi_remove_gpe_handler(void)
-{
- acpi_status status;
-
- if (ec_wake_gpe < 0)
- return;
-
- status = acpi_remove_gpe_handler(NULL, ec_wake_gpe,
- &cros_ec_gpe_handler);
- if (ACPI_FAILURE(status))
- pr_err("failed to remove gpe handler\n");
-}
-
-void cros_ec_acpi_clear_gpe(void)
-{
- if (ec_wake_gpe < 0)
- return;
-
- acpi_clear_gpe(NULL, ec_wake_gpe);
-}
diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
index eafd06f62a3a..4199cdd4ff89 100644
--- a/drivers/mfd/cros_ec_dev.c
+++ b/drivers/mfd/cros_ec_dev.c
@@ -113,10 +113,10 @@ static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
ret, msg->result);
memset(ec->features, 0, sizeof(ec->features));
+ } else {
+ memcpy(ec->features, msg->data, sizeof(ec->features));
}
- memcpy(ec->features, msg->data, sizeof(ec->features));
-
dev_dbg(ec->dev, "EC features %08x %08x\n",
ec->features[0], ec->features[1]);
@@ -262,13 +262,6 @@ static const struct file_operations fops = {
#endif
};
-static void __remove(struct device *dev)
-{
- struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
- class_dev);
- kfree(ec);
-}
-
static void cros_ec_sensors_register(struct cros_ec_dev *ec)
{
/*
@@ -383,12 +376,16 @@ error:
kfree(msg);
}
+static const struct mfd_cell cros_ec_rtc_cells[] = {
+ { .name = "cros-ec-rtc" }
+};
+
static int ec_device_probe(struct platform_device *pdev)
{
int retval = -ENOMEM;
struct device *dev = &pdev->dev;
struct cros_ec_platform *ec_platform = dev_get_platdata(dev);
- struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);
+ struct cros_ec_dev *ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL);
if (!ec)
return retval;
@@ -410,7 +407,6 @@ static int ec_device_probe(struct platform_device *pdev)
ec->class_dev.devt = MKDEV(ec_major, pdev->id);
ec->class_dev.class = &cros_class;
ec->class_dev.parent = dev;
- ec->class_dev.release = __remove;
retval = dev_set_name(&ec->class_dev, "%s", ec_platform->ec_name);
if (retval) {
@@ -422,6 +418,18 @@ static int ec_device_probe(struct platform_device *pdev)
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
cros_ec_sensors_register(ec);
+ /* Check whether this EC instance has RTC host command support */
+ if (cros_ec_check_features(ec, EC_FEATURE_RTC)) {
+ retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
+ cros_ec_rtc_cells,
+ ARRAY_SIZE(cros_ec_rtc_cells),
+ NULL, 0, NULL);
+ if (retval)
+ dev_err(ec->dev,
+ "failed to add cros-ec-rtc device: %d\n",
+ retval);
+ }
+
/* Take control of the lightbar from the EC. */
lb_manual_suspend_ctrl(ec, 1);
@@ -456,9 +464,17 @@ static int ec_device_remove(struct platform_device *pdev)
return 0;
}
+static void ec_device_shutdown(struct platform_device *pdev)
+{
+ struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
+
+ /* Be sure to clear up debugfs delayed works */
+ cros_ec_debugfs_remove(ec);
+}
+
static const struct platform_device_id cros_ec_id[] = {
{ DRV_NAME, 0 },
- { /* sentinel */ },
+ { /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, cros_ec_id);
@@ -466,6 +482,8 @@ static __maybe_unused int ec_device_suspend(struct device *dev)
{
struct cros_ec_dev *ec = dev_get_drvdata(dev);
+ cros_ec_debugfs_suspend(ec);
+
lb_suspend(ec);
return 0;
@@ -475,6 +493,8 @@ static __maybe_unused int ec_device_resume(struct device *dev)
{
struct cros_ec_dev *ec = dev_get_drvdata(dev);
+ cros_ec_debugfs_resume(ec);
+
lb_resume(ec);
return 0;
@@ -494,6 +514,7 @@ static struct platform_driver cros_ec_dev_driver = {
},
.probe = ec_device_probe,
.remove = ec_device_remove,
+ .shutdown = ec_device_shutdown,
};
static int __init cros_ec_dev_init(void)
diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 9f70de1e4c70..ef9b4763356f 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -13,6 +13,7 @@
* GNU General Public License for more details.
*/
+#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -341,14 +342,17 @@ static int cros_ec_i2c_resume(struct device *dev)
}
#endif
-static SIMPLE_DEV_PM_OPS(cros_ec_i2c_pm_ops, cros_ec_i2c_suspend,
- cros_ec_i2c_resume);
+static const struct dev_pm_ops cros_ec_i2c_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_i2c_suspend, cros_ec_i2c_resume)
+};
+#ifdef CONFIG_OF
static const struct of_device_id cros_ec_i2c_of_match[] = {
{ .compatible = "google,cros-ec-i2c", },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, cros_ec_i2c_of_match);
+#endif
static const struct i2c_device_id cros_ec_i2c_id[] = {
{ "cros-ec-i2c", 0 },
@@ -356,9 +360,18 @@ static const struct i2c_device_id cros_ec_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, cros_ec_i2c_id);
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id cros_ec_i2c_acpi_id[] = {
+ { "GOOG0008", 0 },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(acpi, cros_ec_i2c_acpi_id);
+#endif
+
static struct i2c_driver cros_ec_driver = {
.driver = {
.name = "cros-ec-i2c",
+ .acpi_match_table = ACPI_PTR(cros_ec_i2c_acpi_id),
.of_match_table = of_match_ptr(cros_ec_i2c_of_match),
.pm = &cros_ec_i2c_pm_ops,
},
diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c
index fe1811523e4a..9f6105906c09 100644
--- a/drivers/mfd/da9062-core.c
+++ b/drivers/mfd/da9062-core.c
@@ -365,186 +365,69 @@ static int da9062_get_device_type(struct da9062 *chip)
}
static const struct regmap_range da9061_aa_readable_ranges[] = {
- {
- .range_min = DA9062AA_PAGE_CON,
- .range_max = DA9062AA_STATUS_B,
- }, {
- .range_min = DA9062AA_STATUS_D,
- .range_max = DA9062AA_EVENT_C,
- }, {
- .range_min = DA9062AA_IRQ_MASK_A,
- .range_max = DA9062AA_IRQ_MASK_C,
- }, {
- .range_min = DA9062AA_CONTROL_A,
- .range_max = DA9062AA_GPIO_4,
- }, {
- .range_min = DA9062AA_GPIO_WKUP_MODE,
- .range_max = DA9062AA_GPIO_OUT3_4,
- }, {
- .range_min = DA9062AA_BUCK1_CONT,
- .range_max = DA9062AA_BUCK4_CONT,
- }, {
- .range_min = DA9062AA_BUCK3_CONT,
- .range_max = DA9062AA_BUCK3_CONT,
- }, {
- .range_min = DA9062AA_LDO1_CONT,
- .range_max = DA9062AA_LDO4_CONT,
- }, {
- .range_min = DA9062AA_DVC_1,
- .range_max = DA9062AA_DVC_1,
- }, {
- .range_min = DA9062AA_SEQ,
- .range_max = DA9062AA_ID_4_3,
- }, {
- .range_min = DA9062AA_ID_12_11,
- .range_max = DA9062AA_ID_16_15,
- }, {
- .range_min = DA9062AA_ID_22_21,
- .range_max = DA9062AA_ID_32_31,
- }, {
- .range_min = DA9062AA_SEQ_A,
- .range_max = DA9062AA_WAIT,
- }, {
- .range_min = DA9062AA_RESET,
- .range_max = DA9062AA_BUCK_ILIM_C,
- }, {
- .range_min = DA9062AA_BUCK1_CFG,
- .range_max = DA9062AA_BUCK3_CFG,
- }, {
- .range_min = DA9062AA_VBUCK1_A,
- .range_max = DA9062AA_VBUCK4_A,
- }, {
- .range_min = DA9062AA_VBUCK3_A,
- .range_max = DA9062AA_VBUCK3_A,
- }, {
- .range_min = DA9062AA_VLDO1_A,
- .range_max = DA9062AA_VLDO4_A,
- }, {
- .range_min = DA9062AA_VBUCK1_B,
- .range_max = DA9062AA_VBUCK4_B,
- }, {
- .range_min = DA9062AA_VBUCK3_B,
- .range_max = DA9062AA_VBUCK3_B,
- }, {
- .range_min = DA9062AA_VLDO1_B,
- .range_max = DA9062AA_VLDO4_B,
- }, {
- .range_min = DA9062AA_INTERFACE,
- .range_max = DA9062AA_CONFIG_E,
- }, {
- .range_min = DA9062AA_CONFIG_G,
- .range_max = DA9062AA_CONFIG_K,
- }, {
- .range_min = DA9062AA_CONFIG_M,
- .range_max = DA9062AA_CONFIG_M,
- }, {
- .range_min = DA9062AA_GP_ID_0,
- .range_max = DA9062AA_GP_ID_19,
- }, {
- .range_min = DA9062AA_DEVICE_ID,
- .range_max = DA9062AA_CONFIG_ID,
- },
+ regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
+ regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
+ regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
+ regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
+ regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4),
+ regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),
+ regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
+ regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
+ regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
+ regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
+ regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
+ regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
+ regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT),
+ regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C),
+ regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG),
+ regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A),
+ regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
+ regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
+ regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B),
+ regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
+ regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
+ regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E),
+ regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K),
+ regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M),
+ regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
+ regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID),
};
static const struct regmap_range da9061_aa_writeable_ranges[] = {
- {
- .range_min = DA9062AA_PAGE_CON,
- .range_max = DA9062AA_PAGE_CON,
- }, {
- .range_min = DA9062AA_FAULT_LOG,
- .range_max = DA9062AA_EVENT_C,
- }, {
- .range_min = DA9062AA_IRQ_MASK_A,
- .range_max = DA9062AA_IRQ_MASK_C,
- }, {
- .range_min = DA9062AA_CONTROL_A,
- .range_max = DA9062AA_GPIO_4,
- }, {
- .range_min = DA9062AA_GPIO_WKUP_MODE,
- .range_max = DA9062AA_GPIO_OUT3_4,
- }, {
- .range_min = DA9062AA_BUCK1_CONT,
- .range_max = DA9062AA_BUCK4_CONT,
- }, {
- .range_min = DA9062AA_BUCK3_CONT,
- .range_max = DA9062AA_BUCK3_CONT,
- }, {
- .range_min = DA9062AA_LDO1_CONT,
- .range_max = DA9062AA_LDO4_CONT,
- }, {
- .range_min = DA9062AA_DVC_1,
- .range_max = DA9062AA_DVC_1,
- }, {
- .range_min = DA9062AA_SEQ,
- .range_max = DA9062AA_ID_4_3,
- }, {
- .range_min = DA9062AA_ID_12_11,
- .range_max = DA9062AA_ID_16_15,
- }, {
- .range_min = DA9062AA_ID_22_21,
- .range_max = DA9062AA_ID_32_31,
- }, {
- .range_min = DA9062AA_SEQ_A,
- .range_max = DA9062AA_WAIT,
- }, {
- .range_min = DA9062AA_RESET,
- .range_max = DA9062AA_BUCK_ILIM_C,
- }, {
- .range_min = DA9062AA_BUCK1_CFG,
- .range_max = DA9062AA_BUCK3_CFG,
- }, {
- .range_min = DA9062AA_VBUCK1_A,
- .range_max = DA9062AA_VBUCK4_A,
- }, {
- .range_min = DA9062AA_VBUCK3_A,
- .range_max = DA9062AA_VBUCK3_A,
- }, {
- .range_min = DA9062AA_VLDO1_A,
- .range_max = DA9062AA_VLDO4_A,
- }, {
- .range_min = DA9062AA_VBUCK1_B,
- .range_max = DA9062AA_VBUCK4_B,
- }, {
- .range_min = DA9062AA_VBUCK3_B,
- .range_max = DA9062AA_VBUCK3_B,
- }, {
- .range_min = DA9062AA_VLDO1_B,
- .range_max = DA9062AA_VLDO4_B,
- }, {
- .range_min = DA9062AA_GP_ID_0,
- .range_max = DA9062AA_GP_ID_19,
- },
+ regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON),
+ regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C),
+ regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
+ regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
+ regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4),
+ regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),
+ regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
+ regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
+ regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
+ regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
+ regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
+ regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
+ regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT),
+ regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C),
+ regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG),
+ regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A),
+ regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
+ regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
+ regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B),
+ regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
+ regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
+ regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
};
static const struct regmap_range da9061_aa_volatile_ranges[] = {
- {
- .range_min = DA9062AA_PAGE_CON,
- .range_max = DA9062AA_STATUS_B,
- }, {
- .range_min = DA9062AA_STATUS_D,
- .range_max = DA9062AA_EVENT_C,
- }, {
- .range_min = DA9062AA_CONTROL_A,
- .range_max = DA9062AA_CONTROL_B,
- }, {
- .range_min = DA9062AA_CONTROL_E,
- .range_max = DA9062AA_CONTROL_F,
- }, {
- .range_min = DA9062AA_BUCK1_CONT,
- .range_max = DA9062AA_BUCK4_CONT,
- }, {
- .range_min = DA9062AA_BUCK3_CONT,
- .range_max = DA9062AA_BUCK3_CONT,
- }, {
- .range_min = DA9062AA_LDO1_CONT,
- .range_max = DA9062AA_LDO4_CONT,
- }, {
- .range_min = DA9062AA_DVC_1,
- .range_max = DA9062AA_DVC_1,
- }, {
- .range_min = DA9062AA_SEQ,
- .range_max = DA9062AA_SEQ,
- },
+ regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
+ regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
+ regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B),
+ regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F),
+ regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),
+ regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
+ regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
+ regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
+ regmap_reg_range(DA9062AA_SEQ, DA9062AA_SEQ),
};
static const struct regmap_access_table da9061_aa_readable_table = {
@@ -587,186 +470,69 @@ static struct regmap_config da9061_regmap_config = {
};
static const struct regmap_range da9062_aa_readable_ranges[] = {
- {
- .range_min = DA9062AA_PAGE_CON,
- .range_max = DA9062AA_STATUS_B,
- }, {
- .range_min = DA9062AA_STATUS_D,
- .range_max = DA9062AA_EVENT_C,
- }, {
- .range_min = DA9062AA_IRQ_MASK_A,
- .range_max = DA9062AA_IRQ_MASK_C,
- }, {
- .range_min = DA9062AA_CONTROL_A,
- .range_max = DA9062AA_GPIO_4,
- }, {
- .range_min = DA9062AA_GPIO_WKUP_MODE,
- .range_max = DA9062AA_BUCK4_CONT,
- }, {
- .range_min = DA9062AA_BUCK3_CONT,
- .range_max = DA9062AA_BUCK3_CONT,
- }, {
- .range_min = DA9062AA_LDO1_CONT,
- .range_max = DA9062AA_LDO4_CONT,
- }, {
- .range_min = DA9062AA_DVC_1,
- .range_max = DA9062AA_DVC_1,
- }, {
- .range_min = DA9062AA_COUNT_S,
- .range_max = DA9062AA_SECOND_D,
- }, {
- .range_min = DA9062AA_SEQ,
- .range_max = DA9062AA_ID_4_3,
- }, {
- .range_min = DA9062AA_ID_12_11,
- .range_max = DA9062AA_ID_16_15,
- }, {
- .range_min = DA9062AA_ID_22_21,
- .range_max = DA9062AA_ID_32_31,
- }, {
- .range_min = DA9062AA_SEQ_A,
- .range_max = DA9062AA_BUCK3_CFG,
- }, {
- .range_min = DA9062AA_VBUCK2_A,
- .range_max = DA9062AA_VBUCK4_A,
- }, {
- .range_min = DA9062AA_VBUCK3_A,
- .range_max = DA9062AA_VBUCK3_A,
- }, {
- .range_min = DA9062AA_VLDO1_A,
- .range_max = DA9062AA_VLDO4_A,
- }, {
- .range_min = DA9062AA_VBUCK2_B,
- .range_max = DA9062AA_VBUCK4_B,
- }, {
- .range_min = DA9062AA_VBUCK3_B,
- .range_max = DA9062AA_VBUCK3_B,
- }, {
- .range_min = DA9062AA_VLDO1_B,
- .range_max = DA9062AA_VLDO4_B,
- }, {
- .range_min = DA9062AA_BBAT_CONT,
- .range_max = DA9062AA_BBAT_CONT,
- }, {
- .range_min = DA9062AA_INTERFACE,
- .range_max = DA9062AA_CONFIG_E,
- }, {
- .range_min = DA9062AA_CONFIG_G,
- .range_max = DA9062AA_CONFIG_K,
- }, {
- .range_min = DA9062AA_CONFIG_M,
- .range_max = DA9062AA_CONFIG_M,
- }, {
- .range_min = DA9062AA_TRIM_CLDR,
- .range_max = DA9062AA_GP_ID_19,
- }, {
- .range_min = DA9062AA_DEVICE_ID,
- .range_max = DA9062AA_CONFIG_ID,
- },
+ regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
+ regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
+ regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
+ regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
+ regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT),
+ regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
+ regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
+ regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
+ regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_SECOND_D),
+ regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
+ regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
+ regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
+ regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG),
+ regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A),
+ regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
+ regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
+ regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B),
+ regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
+ regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
+ regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT),
+ regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E),
+ regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K),
+ regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M),
+ regmap_reg_range(DA9062AA_TRIM_CLDR, DA9062AA_GP_ID_19),
+ regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID),
};
static const struct regmap_range da9062_aa_writeable_ranges[] = {
- {
- .range_min = DA9062AA_PAGE_CON,
- .range_max = DA9062AA_PAGE_CON,
- }, {
- .range_min = DA9062AA_FAULT_LOG,
- .range_max = DA9062AA_EVENT_C,
- }, {
- .range_min = DA9062AA_IRQ_MASK_A,
- .range_max = DA9062AA_IRQ_MASK_C,
- }, {
- .range_min = DA9062AA_CONTROL_A,
- .range_max = DA9062AA_GPIO_4,
- }, {
- .range_min = DA9062AA_GPIO_WKUP_MODE,
- .range_max = DA9062AA_BUCK4_CONT,
- }, {
- .range_min = DA9062AA_BUCK3_CONT,
- .range_max = DA9062AA_BUCK3_CONT,
- }, {
- .range_min = DA9062AA_LDO1_CONT,
- .range_max = DA9062AA_LDO4_CONT,
- }, {
- .range_min = DA9062AA_DVC_1,
- .range_max = DA9062AA_DVC_1,
- }, {
- .range_min = DA9062AA_COUNT_S,
- .range_max = DA9062AA_ALARM_Y,
- }, {
- .range_min = DA9062AA_SEQ,
- .range_max = DA9062AA_ID_4_3,
- }, {
- .range_min = DA9062AA_ID_12_11,
- .range_max = DA9062AA_ID_16_15,
- }, {
- .range_min = DA9062AA_ID_22_21,
- .range_max = DA9062AA_ID_32_31,
- }, {
- .range_min = DA9062AA_SEQ_A,
- .range_max = DA9062AA_BUCK3_CFG,
- }, {
- .range_min = DA9062AA_VBUCK2_A,
- .range_max = DA9062AA_VBUCK4_A,
- }, {
- .range_min = DA9062AA_VBUCK3_A,
- .range_max = DA9062AA_VBUCK3_A,
- }, {
- .range_min = DA9062AA_VLDO1_A,
- .range_max = DA9062AA_VLDO4_A,
- }, {
- .range_min = DA9062AA_VBUCK2_B,
- .range_max = DA9062AA_VBUCK4_B,
- }, {
- .range_min = DA9062AA_VBUCK3_B,
- .range_max = DA9062AA_VBUCK3_B,
- }, {
- .range_min = DA9062AA_VLDO1_B,
- .range_max = DA9062AA_VLDO4_B,
- }, {
- .range_min = DA9062AA_BBAT_CONT,
- .range_max = DA9062AA_BBAT_CONT,
- }, {
- .range_min = DA9062AA_GP_ID_0,
- .range_max = DA9062AA_GP_ID_19,
- },
+ regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON),
+ regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C),
+ regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
+ regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
+ regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT),
+ regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
+ regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
+ regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
+ regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_ALARM_Y),
+ regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
+ regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
+ regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
+ regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG),
+ regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A),
+ regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
+ regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
+ regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B),
+ regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
+ regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
+ regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT),
+ regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
};
static const struct regmap_range da9062_aa_volatile_ranges[] = {
- {
- .range_min = DA9062AA_PAGE_CON,
- .range_max = DA9062AA_STATUS_B,
- }, {
- .range_min = DA9062AA_STATUS_D,
- .range_max = DA9062AA_EVENT_C,
- }, {
- .range_min = DA9062AA_CONTROL_A,
- .range_max = DA9062AA_CONTROL_B,
- }, {
- .range_min = DA9062AA_CONTROL_E,
- .range_max = DA9062AA_CONTROL_F,
- }, {
- .range_min = DA9062AA_BUCK2_CONT,
- .range_max = DA9062AA_BUCK4_CONT,
- }, {
- .range_min = DA9062AA_BUCK3_CONT,
- .range_max = DA9062AA_BUCK3_CONT,
- }, {
- .range_min = DA9062AA_LDO1_CONT,
- .range_max = DA9062AA_LDO4_CONT,
- }, {
- .range_min = DA9062AA_DVC_1,
- .range_max = DA9062AA_DVC_1,
- }, {
- .range_min = DA9062AA_COUNT_S,
- .range_max = DA9062AA_SECOND_D,
- }, {
- .range_min = DA9062AA_SEQ,
- .range_max = DA9062AA_SEQ,
- }, {
- .range_min = DA9062AA_EN_32K,
- .range_max = DA9062AA_EN_32K,
- },
+ regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
+ regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
+ regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B),
+ regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F),
+ regmap_reg_range(DA9062AA_BUCK2_CONT, DA9062AA_BUCK4_CONT),
+ regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
+ regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
+ regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
+ regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_SECOND_D),
+ regmap_reg_range(DA9062AA_SEQ, DA9062AA_SEQ),
+ regmap_reg_range(DA9062AA_EN_32K, DA9062AA_EN_32K),
};
static const struct regmap_access_table da9062_aa_readable_table = {
diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c
index 3f9eee5f8fb9..4bf8b7781c77 100644
--- a/drivers/mfd/htc-i2cpld.c
+++ b/drivers/mfd/htc-i2cpld.c
@@ -479,10 +479,8 @@ static int htcpld_setup_chips(struct platform_device *pdev)
htcpld->nchips = pdata->num_chip;
htcpld->chip = devm_kzalloc(dev, sizeof(struct htcpld_chip) * htcpld->nchips,
GFP_KERNEL);
- if (!htcpld->chip) {
- dev_warn(dev, "Unable to allocate memory for chips\n");
+ if (!htcpld->chip)
return -ENOMEM;
- }
/* Add the chips as best we can */
for (i = 0; i < htcpld->nchips; i++) {
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c
index d1c46de89eb4..d9ae983095c5 100644
--- a/drivers/mfd/intel-lpss-pci.c
+++ b/drivers/mfd/intel-lpss-pci.c
@@ -124,6 +124,11 @@ static const struct intel_lpss_platform_info apl_i2c_info = {
.properties = apl_i2c_properties,
};
+static const struct intel_lpss_platform_info cnl_i2c_info = {
+ .clk_rate = 216000000,
+ .properties = spt_i2c_properties,
+};
+
static const struct pci_device_id intel_lpss_pci_ids[] = {
/* BXT A-Step */
{ PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info },
@@ -207,13 +212,13 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x9daa), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0x9dab), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0x9dfb), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0x9dc5), (kernel_ulong_t)&spt_i2c_info },
- { PCI_VDEVICE(INTEL, 0x9dc6), (kernel_ulong_t)&spt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9dc5), (kernel_ulong_t)&cnl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9dc6), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9dc7), (kernel_ulong_t)&spt_uart_info },
- { PCI_VDEVICE(INTEL, 0x9de8), (kernel_ulong_t)&spt_i2c_info },
- { PCI_VDEVICE(INTEL, 0x9de9), (kernel_ulong_t)&spt_i2c_info },
- { PCI_VDEVICE(INTEL, 0x9dea), (kernel_ulong_t)&spt_i2c_info },
- { PCI_VDEVICE(INTEL, 0x9deb), (kernel_ulong_t)&spt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9de8), (kernel_ulong_t)&cnl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9de9), (kernel_ulong_t)&cnl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9dea), (kernel_ulong_t)&cnl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9deb), (kernel_ulong_t)&cnl_i2c_info },
/* SPT-H */
{ PCI_VDEVICE(INTEL, 0xa127), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa128), (kernel_ulong_t)&spt_uart_info },
@@ -240,10 +245,10 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0xa32b), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0xa37b), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0xa347), (kernel_ulong_t)&spt_uart_info },
- { PCI_VDEVICE(INTEL, 0xa368), (kernel_ulong_t)&spt_i2c_info },
- { PCI_VDEVICE(INTEL, 0xa369), (kernel_ulong_t)&spt_i2c_info },
- { PCI_VDEVICE(INTEL, 0xa36a), (kernel_ulong_t)&spt_i2c_info },
- { PCI_VDEVICE(INTEL, 0xa36b), (kernel_ulong_t)&spt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0xa368), (kernel_ulong_t)&cnl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0xa369), (kernel_ulong_t)&cnl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0xa36a), (kernel_ulong_t)&cnl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0xa36b), (kernel_ulong_t)&cnl_i2c_info },
{ }
};
MODULE_DEVICE_TABLE(pci, intel_lpss_pci_ids);
diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c
index 9e545eb6e8b4..50bffc3382d7 100644
--- a/drivers/mfd/intel-lpss.c
+++ b/drivers/mfd/intel-lpss.c
@@ -40,8 +40,8 @@
/* Offsets from lpss->priv */
#define LPSS_PRIV_RESETS 0x04
-#define LPSS_PRIV_RESETS_FUNC BIT(2)
-#define LPSS_PRIV_RESETS_IDMA 0x3
+#define LPSS_PRIV_RESETS_IDMA BIT(2)
+#define LPSS_PRIV_RESETS_FUNC 0x3
#define LPSS_PRIV_ACTIVELTR 0x10
#define LPSS_PRIV_IDLELTR 0x14
@@ -275,11 +275,11 @@ static void intel_lpss_init_dev(const struct intel_lpss *lpss)
intel_lpss_deassert_reset(lpss);
+ intel_lpss_set_remap_addr(lpss);
+
if (!intel_lpss_has_idma(lpss))
return;
- intel_lpss_set_remap_addr(lpss);
-
/* Make sure that SPI multiblock DMA transfers are re-enabled */
if (lpss->type == LPSS_DEV_SPI)
writel(value, lpss->priv + LPSS_PRIV_SSP_REG);
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c
index ec1f46a6be3a..317a47ad5bb7 100644
--- a/drivers/mfd/janz-cmodio.c
+++ b/drivers/mfd/janz-cmodio.c
@@ -183,10 +183,8 @@ static int cmodio_pci_probe(struct pci_dev *dev,
int ret;
priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- dev_err(&dev->dev, "unable to allocate private data\n");
+ if (!priv)
return -ENOMEM;
- }
pci_set_drvdata(dev, priv);
priv->pdev = dev;
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c
index 798e44306382..f4cd14294b61 100644
--- a/drivers/mfd/jz4740-adc.c
+++ b/drivers/mfd/jz4740-adc.c
@@ -212,10 +212,8 @@ static int jz4740_adc_probe(struct platform_device *pdev)
int irq_base;
adc = devm_kzalloc(&pdev->dev, sizeof(*adc), GFP_KERNEL);
- if (!adc) {
- dev_err(&pdev->dev, "Failed to allocate driver structure\n");
+ if (!adc)
return -ENOMEM;
- }
adc->irq = platform_get_irq(pdev, 0);
if (adc->irq < 0) {
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index 2d6e2c392786..3f554c447521 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -148,10 +148,8 @@ static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
struct max8997_platform_data *pd;
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
- if (!pd) {
- dev_err(dev, "could not allocate memory for pdata\n");
+ if (!pd)
return ERR_PTR(-ENOMEM);
- }
pd->ono = irq_of_parse_and_map(dev->of_node, 1);
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 04a601f6aebe..77b64bd64df3 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -43,6 +43,16 @@ static const struct resource mt6397_rtc_resources[] = {
},
};
+static const struct resource mt6323_keys_resources[] = {
+ DEFINE_RES_IRQ(MT6323_IRQ_STATUS_PWRKEY),
+ DEFINE_RES_IRQ(MT6323_IRQ_STATUS_FCHRKEY),
+};
+
+static const struct resource mt6397_keys_resources[] = {
+ DEFINE_RES_IRQ(MT6397_IRQ_PWRKEY),
+ DEFINE_RES_IRQ(MT6397_IRQ_HOMEKEY),
+};
+
static const struct mfd_cell mt6323_devs[] = {
{
.name = "mt6323-regulator",
@@ -50,6 +60,11 @@ static const struct mfd_cell mt6323_devs[] = {
}, {
.name = "mt6323-led",
.of_compatible = "mediatek,mt6323-led"
+ }, {
+ .name = "mtk-pmic-keys",
+ .num_resources = ARRAY_SIZE(mt6323_keys_resources),
+ .resources = mt6323_keys_resources,
+ .of_compatible = "mediatek,mt6323-keys"
},
};
@@ -71,7 +86,12 @@ static const struct mfd_cell mt6397_devs[] = {
}, {
.name = "mt6397-pinctrl",
.of_compatible = "mediatek,mt6397-pinctrl",
- },
+ }, {
+ .name = "mtk-pmic-keys",
+ .num_resources = ARRAY_SIZE(mt6397_keys_resources),
+ .resources = mt6397_keys_resources,
+ .of_compatible = "mediatek,mt6397-keys"
+ }
};
static void mt6397_irq_lock(struct irq_data *data)
@@ -289,7 +309,7 @@ static int mt6397_probe(struct platform_device *pdev)
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs,
ARRAY_SIZE(mt6323_devs), NULL,
- 0, NULL);
+ 0, pmic->irq_domain);
break;
case MT6397_CID_CODE:
@@ -304,7 +324,7 @@ static int mt6397_probe(struct platform_device *pdev)
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs,
ARRAY_SIZE(mt6397_devs), NULL,
- 0, NULL);
+ 0, pmic->irq_domain);
break;
default:
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 7aab376ecb84..e11ab12fbdf2 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -153,27 +153,6 @@ static const char * const port_modes[] = {
[OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM] = "ohci-tll-2pin-dpdm",
};
-/**
- * omap_usbhs_get_dt_port_mode - Get the 'enum usbhs_omap_port_mode'
- * from the port mode string.
- * @mode: The port mode string, usually obtained from device tree.
- *
- * The function returns the 'enum usbhs_omap_port_mode' that matches the
- * provided port mode string as per the port_modes table.
- * If no match is found it returns -ENODEV
- */
-static int omap_usbhs_get_dt_port_mode(const char *mode)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(port_modes); i++) {
- if (!strcmp(mode, port_modes[i]))
- return i;
- }
-
- return -ENODEV;
-}
-
static struct platform_device *omap_usbhs_alloc_child(const char *name,
struct resource *res, int num_resources, void *pdata,
size_t pdata_size, struct device *dev)
@@ -529,7 +508,8 @@ static int usbhs_omap_get_dt_pdata(struct device *dev,
if (ret < 0)
continue;
- ret = omap_usbhs_get_dt_port_mode(mode);
+ /* get 'enum usbhs_omap_port_mode' from port mode string */
+ ret = match_string(port_modes, ARRAY_SIZE(port_modes), mode);
if (ret < 0) {
dev_warn(dev, "Invalid port%d-mode \"%s\" in device tree\n",
i, mode);
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index 44a5d66314c6..446713dbee27 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -108,9 +108,9 @@
(x) != OMAP_EHCI_PORT_MODE_PHY)
struct usbtll_omap {
- int nch; /* num. of channels */
- struct clk **ch_clk;
- void __iomem *base;
+ void __iomem *base;
+ int nch; /* num. of channels */
+ struct clk *ch_clk[0]; /* must be the last member */
};
/*-------------------------------------------------------------------------*/
@@ -216,53 +216,49 @@ static int usbtll_omap_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct resource *res;
struct usbtll_omap *tll;
- int ret = 0;
- int i, ver;
+ void __iomem *base;
+ int i, nch, ver;
dev_dbg(dev, "starting TI HSUSB TLL Controller\n");
- tll = devm_kzalloc(dev, sizeof(struct usbtll_omap), GFP_KERNEL);
- if (!tll) {
- dev_err(dev, "Memory allocation failed\n");
- return -ENOMEM;
- }
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- tll->base = devm_ioremap_resource(dev, res);
- if (IS_ERR(tll->base))
- return PTR_ERR(tll->base);
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
- platform_set_drvdata(pdev, tll);
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
- ver = usbtll_read(tll->base, OMAP_USBTLL_REVISION);
+ ver = usbtll_read(base, OMAP_USBTLL_REVISION);
switch (ver) {
case OMAP_USBTLL_REV1:
case OMAP_USBTLL_REV4:
- tll->nch = OMAP_TLL_CHANNEL_COUNT;
+ nch = OMAP_TLL_CHANNEL_COUNT;
break;
case OMAP_USBTLL_REV2:
case OMAP_USBTLL_REV3:
- tll->nch = OMAP_REV2_TLL_CHANNEL_COUNT;
+ nch = OMAP_REV2_TLL_CHANNEL_COUNT;
break;
default:
- tll->nch = OMAP_TLL_CHANNEL_COUNT;
- dev_dbg(dev,
- "USB TLL Rev : 0x%x not recognized, assuming %d channels\n",
- ver, tll->nch);
+ nch = OMAP_TLL_CHANNEL_COUNT;
+ dev_dbg(dev, "rev 0x%x not recognized, assuming %d channels\n",
+ ver, nch);
break;
}
- tll->ch_clk = devm_kzalloc(dev, sizeof(struct clk *) * tll->nch,
- GFP_KERNEL);
- if (!tll->ch_clk) {
- ret = -ENOMEM;
- dev_err(dev, "Couldn't allocate memory for channel clocks\n");
- goto err_clk_alloc;
+ tll = devm_kzalloc(dev, sizeof(*tll) + sizeof(tll->ch_clk[nch]),
+ GFP_KERNEL);
+ if (!tll) {
+ pm_runtime_put_sync(dev);
+ pm_runtime_disable(dev);
+ return -ENOMEM;
}
- for (i = 0; i < tll->nch; i++) {
+ tll->base = base;
+ tll->nch = nch;
+ platform_set_drvdata(pdev, tll);
+
+ for (i = 0; i < nch; i++) {
char clkname[] = "usb_tll_hs_usb_chx_clk";
snprintf(clkname, sizeof(clkname),
@@ -282,12 +278,6 @@ static int usbtll_omap_probe(struct platform_device *pdev)
spin_unlock(&tll_lock);
return 0;
-
-err_clk_alloc:
- pm_runtime_put_sync(dev);
- pm_runtime_disable(dev);
-
- return ret;
}
/**
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index f952dff6765f..0d2a88d53eed 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -242,8 +242,10 @@ static int pcf50633_probe(struct i2c_client *client,
for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
pdev = platform_device_alloc("pcf50633-regulator", i);
- if (!pdev)
- return -ENOMEM;
+ if (!pdev) {
+ ret = -ENOMEM;
+ goto err2;
+ }
pdev->dev.parent = pcf->dev;
ret = platform_device_add_data(pdev, &pdata->reg_init_data[i],
@@ -269,6 +271,7 @@ static int pcf50633_probe(struct i2c_client *client,
err:
platform_device_put(pdev);
+err2:
for (j = 0; j < i; j++)
platform_device_put(pcf->regulator_pdev[j]);
diff --git a/drivers/mfd/qcom-spmi-pmic.c b/drivers/mfd/qcom-spmi-pmic.c
index 2022bdfa7ab4..e2e95de649a4 100644
--- a/drivers/mfd/qcom-spmi-pmic.c
+++ b/drivers/mfd/qcom-spmi-pmic.c
@@ -39,6 +39,9 @@
#define PM8916_SUBTYPE 0x0b
#define PM8004_SUBTYPE 0x0c
#define PM8909_SUBTYPE 0x0d
+#define PM8998_SUBTYPE 0x14
+#define PMI8998_SUBTYPE 0x15
+#define PM8005_SUBTYPE 0x18
static const struct of_device_id pmic_spmi_id_table[] = {
{ .compatible = "qcom,spmi-pmic", .data = (void *)COMMON_SUBTYPE },
@@ -55,6 +58,9 @@ static const struct of_device_id pmic_spmi_id_table[] = {
{ .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE },
{ .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE },
{ .compatible = "qcom,pm8909", .data = (void *)PM8909_SUBTYPE },
+ { .compatible = "qcom,pm8998", .data = (void *)PM8998_SUBTYPE },
+ { .compatible = "qcom,pmi8998", .data = (void *)PMI8998_SUBTYPE },
+ { .compatible = "qcom,pm8005", .data = (void *)PM8005_SUBTYPE },
{ }
};
diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c
index 5c858e784a89..36dcd98977d6 100644
--- a/drivers/mfd/rave-sp.c
+++ b/drivers/mfd/rave-sp.c
@@ -45,7 +45,9 @@
#define RAVE_SP_DLE 0x10
#define RAVE_SP_MAX_DATA_SIZE 64
-#define RAVE_SP_CHECKSUM_SIZE 2 /* Worst case scenario on RDU2 */
+#define RAVE_SP_CHECKSUM_8B2C 1
+#define RAVE_SP_CHECKSUM_CCITT 2
+#define RAVE_SP_CHECKSUM_SIZE RAVE_SP_CHECKSUM_CCITT
/*
* We don't store STX, ETX and unescaped bytes, so Rx is only
* DATA + CSUM
@@ -160,6 +162,8 @@ struct rave_sp_variant {
* @variant: Device variant specific information
* @event_notifier_list: Input event notification chain
*
+ * @part_number_firmware: Firmware version
+ * @part_number_bootloader: Bootloader version
*/
struct rave_sp {
struct serdev_device *serdev;
@@ -171,8 +175,40 @@ struct rave_sp {
const struct rave_sp_variant *variant;
struct blocking_notifier_head event_notifier_list;
+
+ const char *part_number_firmware;
+ const char *part_number_bootloader;
};
+struct rave_sp_version {
+ u8 hardware;
+ __le16 major;
+ u8 minor;
+ u8 letter[2];
+} __packed;
+
+struct rave_sp_status {
+ struct rave_sp_version bootloader_version;
+ struct rave_sp_version firmware_version;
+ u16 rdu_eeprom_flag;
+ u16 dds_eeprom_flag;
+ u8 pic_flag;
+ u8 orientation;
+ u32 etc;
+ s16 temp[2];
+ u8 backlight_current[3];
+ u8 dip_switch;
+ u8 host_interrupt;
+ u16 voltage_28;
+ u8 i2c_device_status;
+ u8 power_status;
+ u8 general_status;
+ u8 deprecated1;
+ u8 power_led_status;
+ u8 deprecated2;
+ u8 periph_power_shutoff;
+} __packed;
+
static bool rave_sp_id_is_event(u8 code)
{
return (code & 0xF0) == RAVE_SP_EVNT_BASE;
@@ -275,8 +311,8 @@ static int rave_sp_write(struct rave_sp *sp, const u8 *data, u8 data_size)
length = dest - frame;
- print_hex_dump(KERN_DEBUG, "rave-sp tx: ", DUMP_PREFIX_NONE,
- 16, 1, frame, length, false);
+ print_hex_dump_debug("rave-sp tx: ", DUMP_PREFIX_NONE,
+ 16, 1, frame, length, false);
return serdev_device_write(sp->serdev, frame, length, HZ);
}
@@ -415,10 +451,15 @@ static void rave_sp_receive_frame(struct rave_sp *sp,
const size_t payload_length = length - checksum_length;
const u8 *crc_reported = &data[payload_length];
struct device *dev = &sp->serdev->dev;
- u8 crc_calculated[checksum_length];
+ u8 crc_calculated[RAVE_SP_CHECKSUM_SIZE];
+
+ if (unlikely(checksum_length > sizeof(crc_calculated))) {
+ dev_warn(dev, "Checksum too long, dropping\n");
+ return;
+ }
- print_hex_dump(KERN_DEBUG, "rave-sp rx: ", DUMP_PREFIX_NONE,
- 16, 1, data, length, false);
+ print_hex_dump_debug("rave-sp rx: ", DUMP_PREFIX_NONE,
+ 16, 1, data, length, false);
if (unlikely(length <= checksum_length)) {
dev_warn(dev, "Dropping short frame\n");
@@ -512,8 +553,6 @@ static int rave_sp_receive_buf(struct serdev_device *serdev,
/* FALLTHROUGH */
case RAVE_SP_EXPECT_ESCAPED_DATA:
- deframer->data[deframer->length++] = byte;
-
if (deframer->length == sizeof(deframer->data)) {
dev_warn(dev, "Bad frame: Too long\n");
/*
@@ -528,6 +567,8 @@ static int rave_sp_receive_buf(struct serdev_device *serdev,
goto reset_framer;
}
+ deframer->data[deframer->length++] = byte;
+
/*
* We've extracted out special byte, now we
* can go back to regular data collecting
@@ -609,6 +650,52 @@ static int rave_sp_default_cmd_translate(enum rave_sp_command command)
}
}
+static const char *devm_rave_sp_version(struct device *dev,
+ struct rave_sp_version *version)
+{
+ /*
+ * NOTE: The format string below uses %02d to display u16
+ * intentionally for the sake of backwards compatibility with
+ * legacy software.
+ */
+ return devm_kasprintf(dev, GFP_KERNEL, "%02d%02d%02d.%c%c\n",
+ version->hardware,
+ le16_to_cpu(version->major),
+ version->minor,
+ version->letter[0],
+ version->letter[1]);
+}
+
+static int rave_sp_get_status(struct rave_sp *sp)
+{
+ struct device *dev = &sp->serdev->dev;
+ u8 cmd[] = {
+ [0] = RAVE_SP_CMD_STATUS,
+ [1] = 0
+ };
+ struct rave_sp_status status;
+ const char *version;
+ int ret;
+
+ ret = rave_sp_exec(sp, cmd, sizeof(cmd), &status, sizeof(status));
+ if (ret)
+ return ret;
+
+ version = devm_rave_sp_version(dev, &status.firmware_version);
+ if (!version)
+ return -ENOMEM;
+
+ sp->part_number_firmware = version;
+
+ version = devm_rave_sp_version(dev, &status.bootloader_version);
+ if (!version)
+ return -ENOMEM;
+
+ sp->part_number_bootloader = version;
+
+ return 0;
+}
+
static const struct rave_sp_checksum rave_sp_checksum_8b2c = {
.length = 1,
.subroutine = csum_8b2c,
@@ -657,6 +744,7 @@ static const struct serdev_device_ops rave_sp_serdev_device_ops = {
static int rave_sp_probe(struct serdev_device *serdev)
{
struct device *dev = &serdev->dev;
+ const char *unknown = "unknown\n";
struct rave_sp *sp;
u32 baud;
int ret;
@@ -689,6 +777,20 @@ static int rave_sp_probe(struct serdev_device *serdev)
serdev_device_set_baudrate(serdev, baud);
+ ret = rave_sp_get_status(sp);
+ if (ret) {
+ dev_warn(dev, "Failed to get firmware status: %d\n", ret);
+ sp->part_number_firmware = unknown;
+ sp->part_number_bootloader = unknown;
+ }
+
+ /*
+ * Those strings already have a \n embedded, so there's no
+ * need to have one in format string.
+ */
+ dev_info(dev, "Firmware version: %s", sp->part_number_firmware);
+ dev_info(dev, "Bootloader version: %s", sp->part_number_bootloader);
+
return devm_of_platform_populate(dev);
}
diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c
index d12243d5ecb8..fd46de02b715 100644
--- a/drivers/mfd/rc5t583.c
+++ b/drivers/mfd/rc5t583.c
@@ -258,11 +258,9 @@ static int rc5t583_i2c_probe(struct i2c_client *i2c,
return -EINVAL;
}
- rc5t583 = devm_kzalloc(&i2c->dev, sizeof(struct rc5t583), GFP_KERNEL);
- if (!rc5t583) {
- dev_err(&i2c->dev, "Memory allocation failed\n");
+ rc5t583 = devm_kzalloc(&i2c->dev, sizeof(*rc5t583), GFP_KERNEL);
+ if (!rc5t583)
return -ENOMEM;
- }
rc5t583->dev = &i2c->dev;
i2c_set_clientdata(i2c, rc5t583);
diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c
index e6a3d999a376..2c5ec93333c3 100644
--- a/drivers/mfd/si476x-i2c.c
+++ b/drivers/mfd/si476x-i2c.c
@@ -697,11 +697,9 @@ static int si476x_core_probe(struct i2c_client *client,
int cell_num;
core = devm_kzalloc(&client->dev, sizeof(*core), GFP_KERNEL);
- if (!core) {
- dev_err(&client->dev,
- "failed to allocate 'struct si476x_core'\n");
+ if (!core)
return -ENOMEM;
- }
+
core->client = client;
core->regmap = devm_regmap_init_si476x(core);
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index ad774161a22d..55d19fd0994e 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1050,13 +1050,13 @@ static int sm501_register_gpio(struct sm501_devdata *sm)
spin_lock_init(&gpio->lock);
gpio->regs_res = request_mem_region(iobase, 0x20, "sm501-gpio");
- if (gpio->regs_res == NULL) {
+ if (!gpio->regs_res) {
dev_err(sm->dev, "gpio: failed to request region\n");
return -ENXIO;
}
gpio->regs = ioremap(iobase, 0x20);
- if (gpio->regs == NULL) {
+ if (!gpio->regs) {
dev_err(sm->dev, "gpio: failed to remap registers\n");
ret = -ENXIO;
goto err_claimed;
@@ -1358,7 +1358,7 @@ static int sm501_init_dev(struct sm501_devdata *sm)
sm501_register_gpio(sm);
}
- if (pdata && pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
+ if (pdata && pdata->gpio_i2c && pdata->gpio_i2c_nr > 0) {
if (!sm501_gpio_isregistered(sm))
dev_err(sm->dev, "no gpio available for i2c gpio.\n");
else
@@ -1383,9 +1383,8 @@ static int sm501_plat_probe(struct platform_device *dev)
struct sm501_devdata *sm;
int ret;
- sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL);
- if (sm == NULL) {
- dev_err(&dev->dev, "no memory for device data\n");
+ sm = kzalloc(sizeof(*sm), GFP_KERNEL);
+ if (!sm) {
ret = -ENOMEM;
goto err1;
}
@@ -1403,8 +1402,7 @@ static int sm501_plat_probe(struct platform_device *dev)
sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-
- if (sm->io_res == NULL || sm->mem_res == NULL) {
+ if (!sm->io_res || !sm->mem_res) {
dev_err(&dev->dev, "failed to get IO resource\n");
ret = -ENOENT;
goto err_res;
@@ -1412,8 +1410,7 @@ static int sm501_plat_probe(struct platform_device *dev)
sm->regs_claim = request_mem_region(sm->io_res->start,
0x100, "sm501");
-
- if (sm->regs_claim == NULL) {
+ if (!sm->regs_claim) {
dev_err(&dev->dev, "cannot claim registers\n");
ret = -EBUSY;
goto err_res;
@@ -1422,8 +1419,7 @@ static int sm501_plat_probe(struct platform_device *dev)
platform_set_drvdata(dev, sm);
sm->regs = ioremap(sm->io_res->start, resource_size(sm->io_res));
-
- if (sm->regs == NULL) {
+ if (!sm->regs) {
dev_err(&dev->dev, "cannot remap registers\n");
ret = -EIO;
goto err_claim;
@@ -1449,7 +1445,7 @@ static void sm501_set_power(struct sm501_devdata *sm, int on)
{
struct sm501_platdata *pd = sm->platdata;
- if (pd == NULL)
+ if (!pd)
return;
if (pd->get_power) {
@@ -1573,9 +1569,8 @@ static int sm501_pci_probe(struct pci_dev *dev,
struct sm501_devdata *sm;
int err;
- sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL);
- if (sm == NULL) {
- dev_err(&dev->dev, "no memory for device data\n");
+ sm = kzalloc(sizeof(*sm), GFP_KERNEL);
+ if (!sm) {
err = -ENOMEM;
goto err1;
}
@@ -1626,15 +1621,14 @@ static int sm501_pci_probe(struct pci_dev *dev,
sm->regs_claim = request_mem_region(sm->io_res->start,
0x100, "sm501");
- if (sm->regs_claim == NULL) {
+ if (!sm->regs_claim) {
dev_err(&dev->dev, "cannot claim registers\n");
err= -EBUSY;
goto err3;
}
sm->regs = pci_ioremap_bar(dev, 1);
-
- if (sm->regs == NULL) {
+ if (!sm->regs) {
dev_err(&dev->dev, "cannot remap registers\n");
err = -EIO;
goto err4;
diff --git a/drivers/mfd/smsc-ece1099.c b/drivers/mfd/smsc-ece1099.c
index 93a8297de52a..57b792eb58fd 100644
--- a/drivers/mfd/smsc-ece1099.c
+++ b/drivers/mfd/smsc-ece1099.c
@@ -37,12 +37,9 @@ static int smsc_i2c_probe(struct i2c_client *i2c,
int devid, rev, venid_l, venid_h;
int ret;
- smsc = devm_kzalloc(&i2c->dev, sizeof(struct smsc),
- GFP_KERNEL);
- if (!smsc) {
- dev_err(&i2c->dev, "smsc mfd driver memory allocation failed\n");
+ smsc = devm_kzalloc(&i2c->dev, sizeof(*smsc), GFP_KERNEL);
+ if (!smsc)
return -ENOMEM;
- }
smsc->regmap = devm_regmap_init_i2c(i2c, &smsc_regmap_config);
if (IS_ERR(smsc->regmap))
diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c
index 56a4782f0569..3460ef07623c 100644
--- a/drivers/mfd/sprd-sc27xx-spi.c
+++ b/drivers/mfd/sprd-sc27xx-spi.c
@@ -111,6 +111,9 @@ static const struct mfd_cell sprd_pmic_devs[] = {
}, {
.name = "sc27xx-poweroff",
.of_compatible = "sprd,sc27xx-poweroff",
+ }, {
+ .name = "sc27xx-syscon",
+ .of_compatible = "sprd,sc27xx-syscon",
},
};
diff --git a/drivers/mfd/stm32-timers.c b/drivers/mfd/stm32-timers.c
index 1d347e5dfa79..efcd4b980c94 100644
--- a/drivers/mfd/stm32-timers.c
+++ b/drivers/mfd/stm32-timers.c
@@ -4,16 +4,156 @@
* Author: Benjamin Gaignard <benjamin.gaignard@st.com>
*/
+#include <linux/bitfield.h>
#include <linux/mfd/stm32-timers.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/reset.h>
+#define STM32_TIMERS_MAX_REGISTERS 0x3fc
+
+/* DIER register DMA enable bits */
+static const u32 stm32_timers_dier_dmaen[STM32_TIMERS_MAX_DMAS] = {
+ TIM_DIER_CC1DE,
+ TIM_DIER_CC2DE,
+ TIM_DIER_CC3DE,
+ TIM_DIER_CC4DE,
+ TIM_DIER_UIE,
+ TIM_DIER_TDE,
+ TIM_DIER_COMDE
+};
+
+static void stm32_timers_dma_done(void *p)
+{
+ struct stm32_timers_dma *dma = p;
+ struct dma_tx_state state;
+ enum dma_status status;
+
+ status = dmaengine_tx_status(dma->chan, dma->chan->cookie, &state);
+ if (status == DMA_COMPLETE)
+ complete(&dma->completion);
+}
+
+/**
+ * stm32_timers_dma_burst_read - Read from timers registers using DMA.
+ *
+ * Read from STM32 timers registers using DMA on a single event.
+ * @dev: reference to stm32_timers MFD device
+ * @buf: DMA'able destination buffer
+ * @id: stm32_timers_dmas event identifier (ch[1..4], up, trig or com)
+ * @reg: registers start offset for DMA to read from (like CCRx for capture)
+ * @num_reg: number of registers to read upon each DMA request, starting @reg.
+ * @bursts: number of bursts to read (e.g. like two for pwm period capture)
+ * @tmo_ms: timeout (milliseconds)
+ */
+int stm32_timers_dma_burst_read(struct device *dev, u32 *buf,
+ enum stm32_timers_dmas id, u32 reg,
+ unsigned int num_reg, unsigned int bursts,
+ unsigned long tmo_ms)
+{
+ struct stm32_timers *ddata = dev_get_drvdata(dev);
+ unsigned long timeout = msecs_to_jiffies(tmo_ms);
+ struct regmap *regmap = ddata->regmap;
+ struct stm32_timers_dma *dma = &ddata->dma;
+ size_t len = num_reg * bursts * sizeof(u32);
+ struct dma_async_tx_descriptor *desc;
+ struct dma_slave_config config;
+ dma_cookie_t cookie;
+ dma_addr_t dma_buf;
+ u32 dbl, dba;
+ long err;
+ int ret;
+
+ /* Sanity check */
+ if (id < STM32_TIMERS_DMA_CH1 || id >= STM32_TIMERS_MAX_DMAS)
+ return -EINVAL;
+
+ if (!num_reg || !bursts || reg > STM32_TIMERS_MAX_REGISTERS ||
+ (reg + num_reg * sizeof(u32)) > STM32_TIMERS_MAX_REGISTERS)
+ return -EINVAL;
+
+ if (!dma->chans[id])
+ return -ENODEV;
+ mutex_lock(&dma->lock);
+
+ /* Select DMA channel in use */
+ dma->chan = dma->chans[id];
+ dma_buf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, dma_buf)) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
+
+ /* Prepare DMA read from timer registers, using DMA burst mode */
+ memset(&config, 0, sizeof(config));
+ config.src_addr = (dma_addr_t)dma->phys_base + TIM_DMAR;
+ config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ ret = dmaengine_slave_config(dma->chan, &config);
+ if (ret)
+ goto unmap;
+
+ desc = dmaengine_prep_slave_single(dma->chan, dma_buf, len,
+ DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
+ if (!desc) {
+ ret = -EBUSY;
+ goto unmap;
+ }
+
+ desc->callback = stm32_timers_dma_done;
+ desc->callback_param = dma;
+ cookie = dmaengine_submit(desc);
+ ret = dma_submit_error(cookie);
+ if (ret)
+ goto dma_term;
+
+ reinit_completion(&dma->completion);
+ dma_async_issue_pending(dma->chan);
+
+ /* Setup and enable timer DMA burst mode */
+ dbl = FIELD_PREP(TIM_DCR_DBL, bursts - 1);
+ dba = FIELD_PREP(TIM_DCR_DBA, reg >> 2);
+ ret = regmap_write(regmap, TIM_DCR, dbl | dba);
+ if (ret)
+ goto dma_term;
+
+ /* Clear pending flags before enabling DMA request */
+ ret = regmap_write(regmap, TIM_SR, 0);
+ if (ret)
+ goto dcr_clr;
+
+ ret = regmap_update_bits(regmap, TIM_DIER, stm32_timers_dier_dmaen[id],
+ stm32_timers_dier_dmaen[id]);
+ if (ret)
+ goto dcr_clr;
+
+ err = wait_for_completion_interruptible_timeout(&dma->completion,
+ timeout);
+ if (err == 0)
+ ret = -ETIMEDOUT;
+ else if (err < 0)
+ ret = err;
+
+ regmap_update_bits(regmap, TIM_DIER, stm32_timers_dier_dmaen[id], 0);
+ regmap_write(regmap, TIM_SR, 0);
+dcr_clr:
+ regmap_write(regmap, TIM_DCR, 0);
+dma_term:
+ dmaengine_terminate_all(dma->chan);
+unmap:
+ dma_unmap_single(dev, dma_buf, len, DMA_FROM_DEVICE);
+unlock:
+ dma->chan = NULL;
+ mutex_unlock(&dma->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(stm32_timers_dma_burst_read);
+
static const struct regmap_config stm32_timers_regmap_cfg = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = sizeof(u32),
- .max_register = 0x3fc,
+ .max_register = STM32_TIMERS_MAX_REGISTERS,
};
static void stm32_timers_get_arr_size(struct stm32_timers *ddata)
@@ -27,12 +167,45 @@ static void stm32_timers_get_arr_size(struct stm32_timers *ddata)
regmap_write(ddata->regmap, TIM_ARR, 0x0);
}
+static void stm32_timers_dma_probe(struct device *dev,
+ struct stm32_timers *ddata)
+{
+ int i;
+ char name[4];
+
+ init_completion(&ddata->dma.completion);
+ mutex_init(&ddata->dma.lock);
+
+ /* Optional DMA support: get valid DMA channel(s) or NULL */
+ for (i = STM32_TIMERS_DMA_CH1; i <= STM32_TIMERS_DMA_CH4; i++) {
+ snprintf(name, ARRAY_SIZE(name), "ch%1d", i + 1);
+ ddata->dma.chans[i] = dma_request_slave_channel(dev, name);
+ }
+ ddata->dma.chans[STM32_TIMERS_DMA_UP] =
+ dma_request_slave_channel(dev, "up");
+ ddata->dma.chans[STM32_TIMERS_DMA_TRIG] =
+ dma_request_slave_channel(dev, "trig");
+ ddata->dma.chans[STM32_TIMERS_DMA_COM] =
+ dma_request_slave_channel(dev, "com");
+}
+
+static void stm32_timers_dma_remove(struct device *dev,
+ struct stm32_timers *ddata)
+{
+ int i;
+
+ for (i = STM32_TIMERS_DMA_CH1; i < STM32_TIMERS_MAX_DMAS; i++)
+ if (ddata->dma.chans[i])
+ dma_release_channel(ddata->dma.chans[i]);
+}
+
static int stm32_timers_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct stm32_timers *ddata;
struct resource *res;
void __iomem *mmio;
+ int ret;
ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
if (!ddata)
@@ -43,6 +216,9 @@ static int stm32_timers_probe(struct platform_device *pdev)
if (IS_ERR(mmio))
return PTR_ERR(mmio);
+ /* Timer physical addr for DMA */
+ ddata->dma.phys_base = res->start;
+
ddata->regmap = devm_regmap_init_mmio_clk(dev, "int", mmio,
&stm32_timers_regmap_cfg);
if (IS_ERR(ddata->regmap))
@@ -54,9 +230,29 @@ static int stm32_timers_probe(struct platform_device *pdev)
stm32_timers_get_arr_size(ddata);
+ stm32_timers_dma_probe(dev, ddata);
+
platform_set_drvdata(pdev, ddata);
- return devm_of_platform_populate(&pdev->dev);
+ ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+ if (ret)
+ stm32_timers_dma_remove(dev, ddata);
+
+ return ret;
+}
+
+static int stm32_timers_remove(struct platform_device *pdev)
+{
+ struct stm32_timers *ddata = platform_get_drvdata(pdev);
+
+ /*
+ * Don't use devm_ here: enfore of_platform_depopulate() happens before
+ * DMA are released, to avoid race on DMA.
+ */
+ of_platform_depopulate(&pdev->dev);
+ stm32_timers_dma_remove(&pdev->dev, ddata);
+
+ return 0;
}
static const struct of_device_id stm32_timers_of_match[] = {
@@ -67,6 +263,7 @@ MODULE_DEVICE_TABLE(of, stm32_timers_of_match);
static struct platform_driver stm32_timers_driver = {
.probe = stm32_timers_probe,
+ .remove = stm32_timers_remove,
.driver = {
.name = "stm32-timers",
.of_match_table = stm32_timers_of_match,
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 7eaa40bc703f..b6d05cd934e6 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -106,9 +106,11 @@ static struct syscon *of_syscon_register(struct device_node *np)
}
}
+ syscon_config.name = of_node_full_name(np);
syscon_config.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size(&res) - reg_io_width;
+ syscon_config.name = of_node_full_name(np);
regmap = regmap_init_mmio(NULL, base, &syscon_config);
if (IS_ERR(regmap)) {
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index 3cd958a31f36..47012c0899cd 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -169,10 +169,9 @@ static int ti_tscadc_probe(struct platform_device *pdev)
/* Allocate memory for device */
tscadc = devm_kzalloc(&pdev->dev, sizeof(*tscadc), GFP_KERNEL);
- if (!tscadc) {
- dev_err(&pdev->dev, "failed to allocate memory.\n");
+ if (!tscadc)
return -ENOMEM;
- }
+
tscadc->dev = &pdev->dev;
err = platform_get_irq(pdev, 0);
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
index cd4a6d7d6750..7c13d2e7061c 100644
--- a/drivers/mfd/timberdale.c
+++ b/drivers/mfd/timberdale.c
@@ -777,7 +777,7 @@ static int timb_probe(struct pci_dev *dev,
&dev->resource[0], msix_entries[0].vector, NULL);
break;
default:
- dev_err(&dev->dev, "Uknown IP setup: %d.%d.%d\n",
+ dev_err(&dev->dev, "Unknown IP setup: %d.%d.%d\n",
priv->fw.major, priv->fw.minor, ip_setup);
err = -ENODEV;
goto err_mfd;
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
index d7ec318c40c3..f13e4cd06e89 100644
--- a/drivers/mfd/tps65090.c
+++ b/drivers/mfd/tps65090.c
@@ -192,10 +192,8 @@ static int tps65090_i2c_probe(struct i2c_client *client,
irq_base = pdata->irq_base;
tps65090 = devm_kzalloc(&client->dev, sizeof(*tps65090), GFP_KERNEL);
- if (!tps65090) {
- dev_err(&client->dev, "mem alloc for tps65090 failed\n");
+ if (!tps65090)
return -ENOMEM;
- }
tps65090->dev = &client->dev;
i2c_set_clientdata(client, tps65090);
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 5628a6b5b19b..b89379782741 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -423,10 +423,8 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien
struct tps6586x_platform_data *pdata;
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata) {
- dev_err(&client->dev, "Memory allocation failed\n");
+ if (!pdata)
return NULL;
- }
pdata->num_subdevs = 0;
pdata->subdevs = NULL;
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index 8263605f6d2f..bf16cbe6fd88 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -229,7 +229,7 @@ static struct regmap_irq_chip tps65910_irq_chip = {
static int tps65910_irq_init(struct tps65910 *tps65910, int irq,
struct tps65910_platform_data *pdata)
{
- int ret = 0;
+ int ret;
static struct regmap_irq_chip *tps6591x_irqs_chip;
if (!irq) {
@@ -312,14 +312,14 @@ static int tps65910_ck32k_init(struct tps65910 *tps65910,
static int tps65910_sleepinit(struct tps65910 *tps65910,
struct tps65910_board *pmic_pdata)
{
- struct device *dev = NULL;
- int ret = 0;
-
- dev = tps65910->dev;
+ struct device *dev;
+ int ret;
if (!pmic_pdata->en_dev_slp)
return 0;
+ dev = tps65910->dev;
+
/* enabling SLEEP device state */
ret = tps65910_reg_set_bits(tps65910, TPS65910_DEVCTRL,
DEVCTRL_DEV_SLP_MASK);
@@ -383,7 +383,7 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
struct tps65910_board *board_info;
unsigned int prop;
const struct of_device_id *match;
- int ret = 0;
+ int ret;
match = of_match_device(tps65910_of_match, &client->dev);
if (!match) {
@@ -395,10 +395,8 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
board_info = devm_kzalloc(&client->dev, sizeof(*board_info),
GFP_KERNEL);
- if (!board_info) {
- dev_err(&client->dev, "Failed to allocate pdata\n");
+ if (!board_info)
return NULL;
- }
ret = of_property_read_u32(np, "ti,vmbch-threshold", &prop);
if (!ret)
@@ -462,7 +460,7 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
struct tps65910_board *of_pmic_plat_data = NULL;
struct tps65910_platform_data *init_data;
unsigned long chip_id = id->driver_data;
- int ret = 0;
+ int ret;
pmic_plat_data = dev_get_platdata(&i2c->dev);
diff --git a/drivers/mfd/tps65911-comparator.c b/drivers/mfd/tps65911-comparator.c
index c0789f81a1c5..33591767fb9b 100644
--- a/drivers/mfd/tps65911-comparator.c
+++ b/drivers/mfd/tps65911-comparator.c
@@ -22,9 +22,8 @@
#include <linux/gpio.h>
#include <linux/mfd/tps65910.h>
-#define COMP 0
-#define COMP1 1
-#define COMP2 2
+#define COMP1 0
+#define COMP2 1
/* Comparator 1 voltage selection table in millivolts */
static const u16 COMP_VSEL_TABLE[] = {
@@ -63,9 +62,6 @@ static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage)
int ret;
u8 index = 0, val;
- if (id == COMP)
- return 0;
-
while (curr_voltage < tps_comp.uV_max) {
curr_voltage = tps_comp.vsel_table[index];
if (curr_voltage >= voltage)
@@ -78,7 +74,7 @@ static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage)
return -EINVAL;
val = index << 1;
- ret = tps65910->write(tps65910, tps_comp.reg, 1, &val);
+ ret = tps65910_reg_write(tps65910, tps_comp.reg, val);
return ret;
}
@@ -86,13 +82,10 @@ static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage)
static int comp_threshold_get(struct tps65910 *tps65910, int id)
{
struct comparator tps_comp = tps_comparators[id];
+ unsigned int val;
int ret;
- u8 val;
-
- if (id == COMP)
- return 0;
- ret = tps65910->read(tps65910, tps_comp.reg, 1, &val);
+ ret = tps65910_reg_read(tps65910, tps_comp.reg, &val);
if (ret < 0)
return ret;
diff --git a/drivers/mfd/tps68470.c b/drivers/mfd/tps68470.c
index 189efaea054c..a5981a79b29a 100644
--- a/drivers/mfd/tps68470.c
+++ b/drivers/mfd/tps68470.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* TPS68470 chip Parent driver
*
@@ -8,15 +9,6 @@
* Tianshu Qiu <tian.shu.qiu@intel.com>
* Jian Xu Zheng <jian.xu.zheng@intel.com>
* Yuning Pu <yuning.pu@intel.com>
- *
- * 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 the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/acpi.h>
diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c
index 0812df3b0d47..608c7f77830e 100644
--- a/drivers/mfd/tps80031.c
+++ b/drivers/mfd/tps80031.c
@@ -431,10 +431,8 @@ static int tps80031_probe(struct i2c_client *client,
}
tps80031 = devm_kzalloc(&client->dev, sizeof(*tps80031), GFP_KERNEL);
- if (!tps80031) {
- dev_err(&client->dev, "Malloc failed for tps80031\n");
+ if (!tps80031)
return -ENOMEM;
- }
for (i = 0; i < TPS80031_NUM_SLAVES; i++) {
if (tps80031_slave_address[i] == client->addr)
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index d3133a371e27..c649344fd7f2 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -1177,7 +1177,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
twl_priv->ready = true;
/* setup clock framework */
- clocks_init(&pdev->dev, pdata ? pdata->clock : NULL);
+ clocks_init(&client->dev, pdata ? pdata->clock : NULL);
/* read TWL IDCODE Register */
if (twl_class_is_4030()) {
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index e3ec8dfa9f1e..e939431ed10c 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -392,10 +392,8 @@ int twl6030_init_irq(struct device *dev, int irq_num)
nr_irqs = TWL6030_NR_IRQS;
twl6030_irq = devm_kzalloc(dev, sizeof(*twl6030_irq), GFP_KERNEL);
- if (!twl6030_irq) {
- dev_err(dev, "twl6030_irq: Memory allocation failed\n");
+ if (!twl6030_irq)
return -ENOMEM;
- }
mask[0] = 0xFF;
mask[1] = 0xFF;
diff --git a/drivers/mfd/viperboard.c b/drivers/mfd/viperboard.c
index e6b3c70aeb22..e9f61262d583 100644
--- a/drivers/mfd/viperboard.c
+++ b/drivers/mfd/viperboard.c
@@ -59,10 +59,8 @@ static int vprbrd_probe(struct usb_interface *interface,
/* allocate memory for our device state and initialize it */
vb = kzalloc(sizeof(*vb), GFP_KERNEL);
- if (vb == NULL) {
- dev_err(&interface->dev, "Out of memory\n");
+ if (!vb)
return -ENOMEM;
- }
mutex_init(&vb->lock);
diff --git a/drivers/mfd/wm97xx-core.c b/drivers/mfd/wm97xx-core.c
index 4141ee52a70b..f5a8347f837f 100644
--- a/drivers/mfd/wm97xx-core.c
+++ b/drivers/mfd/wm97xx-core.c
@@ -278,7 +278,7 @@ static int wm97xx_ac97_probe(struct ac97_codec_device *adev)
codec_pdata = &wm97xx->codec_pdata;
codec_pdata->ac97 = wm97xx->ac97;
- codec_pdata->batt_pdata = pdata->batt_pdata;
+ codec_pdata->batt_pdata = pdata ? pdata->batt_pdata : NULL;
switch (adev->vendor_id) {
case WM9705_VENDOR_ID:
diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c
index cc265ed8deb7..c62ee8e610a0 100644
--- a/drivers/platform/chrome/cros_ec_debugfs.c
+++ b/drivers/platform/chrome/cros_ec_debugfs.c
@@ -470,3 +470,23 @@ void cros_ec_debugfs_remove(struct cros_ec_dev *ec)
cros_ec_cleanup_console_log(ec->debug_info);
}
EXPORT_SYMBOL(cros_ec_debugfs_remove);
+
+void cros_ec_debugfs_suspend(struct cros_ec_dev *ec)
+{
+ /*
+ * cros_ec_debugfs_init() failures are non-fatal; it's also possible
+ * that we initted things but decided that console log wasn't supported.
+ * We'll use the same set of checks that cros_ec_debugfs_remove() +
+ * cros_ec_cleanup_console_log() end up using to handle those cases.
+ */
+ if (ec->debug_info && ec->debug_info->log_buffer.buf)
+ cancel_delayed_work_sync(&ec->debug_info->log_poll_work);
+}
+EXPORT_SYMBOL(cros_ec_debugfs_suspend);
+
+void cros_ec_debugfs_resume(struct cros_ec_dev *ec)
+{
+ if (ec->debug_info && ec->debug_info->log_buffer.buf)
+ schedule_delayed_work(&ec->debug_info->log_poll_work, 0);
+}
+EXPORT_SYMBOL(cros_ec_debugfs_resume);
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index 2708212933f7..09383c6720fb 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -8,6 +8,7 @@
* pwm-atmel.c from Bo Shen
*/
+#include <linux/bitfield.h>
#include <linux/mfd/stm32-timers.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -25,6 +26,7 @@ struct stm32_pwm {
struct regmap *regmap;
u32 max_arr;
bool have_complementary_output;
+ u32 capture[4] ____cacheline_aligned; /* DMA'able buffer */
};
struct stm32_breakinput {
@@ -62,6 +64,258 @@ static int write_ccrx(struct stm32_pwm *dev, int ch, u32 value)
return -EINVAL;
}
+#define TIM_CCER_CC12P (TIM_CCER_CC1P | TIM_CCER_CC2P)
+#define TIM_CCER_CC12E (TIM_CCER_CC1E | TIM_CCER_CC2E)
+#define TIM_CCER_CC34P (TIM_CCER_CC3P | TIM_CCER_CC4P)
+#define TIM_CCER_CC34E (TIM_CCER_CC3E | TIM_CCER_CC4E)
+
+/*
+ * Capture using PWM input mode:
+ * ___ ___
+ * TI[1, 2, 3 or 4]: ........._| |________|
+ * ^0 ^1 ^2
+ * . . .
+ * . . XXXXX
+ * . . XXXXX |
+ * . XXXXX . |
+ * XXXXX . . |
+ * COUNTER: ______XXXXX . . . |_XXX
+ * start^ . . . ^stop
+ * . . . .
+ * v v . v
+ * v
+ * CCR1/CCR3: tx..........t0...........t2
+ * CCR2/CCR4: tx..............t1.........
+ *
+ * DMA burst transfer: | |
+ * v v
+ * DMA buffer: { t0, tx } { t2, t1 }
+ * DMA done: ^
+ *
+ * 0: IC1/3 snapchot on rising edge: counter value -> CCR1/CCR3
+ * + DMA transfer CCR[1/3] & CCR[2/4] values (t0, tx: doesn't care)
+ * 1: IC2/4 snapchot on falling edge: counter value -> CCR2/CCR4
+ * 2: IC1/3 snapchot on rising edge: counter value -> CCR1/CCR3
+ * + DMA transfer CCR[1/3] & CCR[2/4] values (t2, t1)
+ *
+ * DMA done, compute:
+ * - Period = t2 - t0
+ * - Duty cycle = t1 - t0
+ */
+static int stm32_pwm_raw_capture(struct stm32_pwm *priv, struct pwm_device *pwm,
+ unsigned long tmo_ms, u32 *raw_prd,
+ u32 *raw_dty)
+{
+ struct device *parent = priv->chip.dev->parent;
+ enum stm32_timers_dmas dma_id;
+ u32 ccen, ccr;
+ int ret;
+
+ /* Ensure registers have been updated, enable counter and capture */
+ regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG);
+ regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, TIM_CR1_CEN);
+
+ /* Use cc1 or cc3 DMA resp for PWM input channels 1 & 2 or 3 & 4 */
+ dma_id = pwm->hwpwm < 2 ? STM32_TIMERS_DMA_CH1 : STM32_TIMERS_DMA_CH3;
+ ccen = pwm->hwpwm < 2 ? TIM_CCER_CC12E : TIM_CCER_CC34E;
+ ccr = pwm->hwpwm < 2 ? TIM_CCR1 : TIM_CCR3;
+ regmap_update_bits(priv->regmap, TIM_CCER, ccen, ccen);
+
+ /*
+ * Timer DMA burst mode. Request 2 registers, 2 bursts, to get both
+ * CCR1 & CCR2 (or CCR3 & CCR4) on each capture event.
+ * We'll get two capture snapchots: { CCR1, CCR2 }, { CCR1, CCR2 }
+ * or { CCR3, CCR4 }, { CCR3, CCR4 }
+ */
+ ret = stm32_timers_dma_burst_read(parent, priv->capture, dma_id, ccr, 2,
+ 2, tmo_ms);
+ if (ret)
+ goto stop;
+
+ /* Period: t2 - t0 (take care of counter overflow) */
+ if (priv->capture[0] <= priv->capture[2])
+ *raw_prd = priv->capture[2] - priv->capture[0];
+ else
+ *raw_prd = priv->max_arr - priv->capture[0] + priv->capture[2];
+
+ /* Duty cycle capture requires at least two capture units */
+ if (pwm->chip->npwm < 2)
+ *raw_dty = 0;
+ else if (priv->capture[0] <= priv->capture[3])
+ *raw_dty = priv->capture[3] - priv->capture[0];
+ else
+ *raw_dty = priv->max_arr - priv->capture[0] + priv->capture[3];
+
+ if (*raw_dty > *raw_prd) {
+ /*
+ * Race beetween PWM input and DMA: it may happen
+ * falling edge triggers new capture on TI2/4 before DMA
+ * had a chance to read CCR2/4. It means capture[1]
+ * contains period + duty_cycle. So, subtract period.
+ */
+ *raw_dty -= *raw_prd;
+ }
+
+stop:
+ regmap_update_bits(priv->regmap, TIM_CCER, ccen, 0);
+ regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
+
+ return ret;
+}
+
+static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_capture *result, unsigned long tmo_ms)
+{
+ struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
+ unsigned long long prd, div, dty;
+ unsigned long rate;
+ unsigned int psc = 0, icpsc, scale;
+ u32 raw_prd = 0, raw_dty = 0;
+ int ret = 0;
+
+ mutex_lock(&priv->lock);
+
+ if (active_channels(priv)) {
+ ret = -EBUSY;
+ goto unlock;
+ }
+
+ ret = clk_enable(priv->clk);
+ if (ret) {
+ dev_err(priv->chip.dev, "failed to enable counter clock\n");
+ goto unlock;
+ }
+
+ rate = clk_get_rate(priv->clk);
+ if (!rate) {
+ ret = -EINVAL;
+ goto clk_dis;
+ }
+
+ /* prescaler: fit timeout window provided by upper layer */
+ div = (unsigned long long)rate * (unsigned long long)tmo_ms;
+ do_div(div, MSEC_PER_SEC);
+ prd = div;
+ while ((div > priv->max_arr) && (psc < MAX_TIM_PSC)) {
+ psc++;
+ div = prd;
+ do_div(div, psc + 1);
+ }
+ regmap_write(priv->regmap, TIM_ARR, priv->max_arr);
+ regmap_write(priv->regmap, TIM_PSC, psc);
+
+ /* Map TI1 or TI2 PWM input to IC1 & IC2 (or TI3/4 to IC3 & IC4) */
+ regmap_update_bits(priv->regmap,
+ pwm->hwpwm < 2 ? TIM_CCMR1 : TIM_CCMR2,
+ TIM_CCMR_CC1S | TIM_CCMR_CC2S, pwm->hwpwm & 0x1 ?
+ TIM_CCMR_CC1S_TI2 | TIM_CCMR_CC2S_TI2 :
+ TIM_CCMR_CC1S_TI1 | TIM_CCMR_CC2S_TI1);
+
+ /* Capture period on IC1/3 rising edge, duty cycle on IC2/4 falling. */
+ regmap_update_bits(priv->regmap, TIM_CCER, pwm->hwpwm < 2 ?
+ TIM_CCER_CC12P : TIM_CCER_CC34P, pwm->hwpwm < 2 ?
+ TIM_CCER_CC2P : TIM_CCER_CC4P);
+
+ ret = stm32_pwm_raw_capture(priv, pwm, tmo_ms, &raw_prd, &raw_dty);
+ if (ret)
+ goto stop;
+
+ /*
+ * Got a capture. Try to improve accuracy at high rates:
+ * - decrease counter clock prescaler, scale up to max rate.
+ * - use input prescaler, capture once every /2 /4 or /8 edges.
+ */
+ if (raw_prd) {
+ u32 max_arr = priv->max_arr - 0x1000; /* arbitrary margin */
+
+ scale = max_arr / min(max_arr, raw_prd);
+ } else {
+ scale = priv->max_arr; /* bellow resolution, use max scale */
+ }
+
+ if (psc && scale > 1) {
+ /* 2nd measure with new scale */
+ psc /= scale;
+ regmap_write(priv->regmap, TIM_PSC, psc);
+ ret = stm32_pwm_raw_capture(priv, pwm, tmo_ms, &raw_prd,
+ &raw_dty);
+ if (ret)
+ goto stop;
+ }
+
+ /* Compute intermediate period not to exceed timeout at low rates */
+ prd = (unsigned long long)raw_prd * (psc + 1) * NSEC_PER_SEC;
+ do_div(prd, rate);
+
+ for (icpsc = 0; icpsc < MAX_TIM_ICPSC ; icpsc++) {
+ /* input prescaler: also keep arbitrary margin */
+ if (raw_prd >= (priv->max_arr - 0x1000) >> (icpsc + 1))
+ break;
+ if (prd >= (tmo_ms * NSEC_PER_MSEC) >> (icpsc + 2))
+ break;
+ }
+
+ if (!icpsc)
+ goto done;
+
+ /* Last chance to improve period accuracy, using input prescaler */
+ regmap_update_bits(priv->regmap,
+ pwm->hwpwm < 2 ? TIM_CCMR1 : TIM_CCMR2,
+ TIM_CCMR_IC1PSC | TIM_CCMR_IC2PSC,
+ FIELD_PREP(TIM_CCMR_IC1PSC, icpsc) |
+ FIELD_PREP(TIM_CCMR_IC2PSC, icpsc));
+
+ ret = stm32_pwm_raw_capture(priv, pwm, tmo_ms, &raw_prd, &raw_dty);
+ if (ret)
+ goto stop;
+
+ if (raw_dty >= (raw_prd >> icpsc)) {
+ /*
+ * We may fall here using input prescaler, when input
+ * capture starts on high side (before falling edge).
+ * Example with icpsc to capture on each 4 events:
+ *
+ * start 1st capture 2nd capture
+ * v v v
+ * ___ _____ _____ _____ _____ ____
+ * TI1..4 |__| |__| |__| |__| |__|
+ * v v . . . . . v v
+ * icpsc1/3: . 0 . 1 . 2 . 3 . 0
+ * icpsc2/4: 0 1 2 3 0
+ * v v v v
+ * CCR1/3 ......t0..............................t2
+ * CCR2/4 ..t1..............................t1'...
+ * . . .
+ * Capture0: .<----------------------------->.
+ * Capture1: .<-------------------------->. .
+ * . . .
+ * Period: .<------> . .
+ * Low side: .<>.
+ *
+ * Result:
+ * - Period = Capture0 / icpsc
+ * - Duty = Period - Low side = Period - (Capture0 - Capture1)
+ */
+ raw_dty = (raw_prd >> icpsc) - (raw_prd - raw_dty);
+ }
+
+done:
+ prd = (unsigned long long)raw_prd * (psc + 1) * NSEC_PER_SEC;
+ result->period = DIV_ROUND_UP_ULL(prd, rate << icpsc);
+ dty = (unsigned long long)raw_dty * (psc + 1) * NSEC_PER_SEC;
+ result->duty_cycle = DIV_ROUND_UP_ULL(dty, rate);
+stop:
+ regmap_write(priv->regmap, TIM_CCER, 0);
+ regmap_write(priv->regmap, pwm->hwpwm < 2 ? TIM_CCMR1 : TIM_CCMR2, 0);
+ regmap_write(priv->regmap, TIM_PSC, 0);
+clk_dis:
+ clk_disable(priv->clk);
+unlock:
+ mutex_unlock(&priv->lock);
+
+ return ret;
+}
+
static int stm32_pwm_config(struct stm32_pwm *priv, int ch,
int duty_ns, int period_ns)
{
@@ -230,6 +484,9 @@ static int stm32_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *pwm,
static const struct pwm_ops stm32pwm_ops = {
.owner = THIS_MODULE,
.apply = stm32_pwm_apply_locked,
+#if IS_ENABLED(CONFIG_DMA_ENGINE)
+ .capture = stm32_pwm_capture,
+#endif
};
static int stm32_pwm_set_breakinput(struct stm32_pwm *priv,
diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c
index 1a61fa56f3ad..385f8303bb41 100644
--- a/drivers/rtc/rtc-mt6397.c
+++ b/drivers/rtc/rtc-mt6397.c
@@ -322,10 +322,9 @@ static int mtk_rtc_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rtc->addr_base = res->start;
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- rtc->irq = irq_create_mapping(mt6397_chip->irq_domain, res->start);
- if (rtc->irq <= 0)
- return -EINVAL;
+ rtc->irq = platform_get_irq(pdev, 0);
+ if (rtc->irq < 0)
+ return rtc->irq;
rtc->regmap = mt6397_chip->regmap;
rtc->dev = &pdev->dev;