diff options
64 files changed, 1574 insertions, 994 deletions
diff --git a/Documentation/devicetree/bindings/input/mtk-pmic-keys.txt b/Documentation/devicetree/bindings/input/mtk-pmic-keys.txt new file mode 100644 index 000000000000..2888d07c2ef0 --- /dev/null +++ b/Documentation/devicetree/bindings/input/mtk-pmic-keys.txt @@ -0,0 +1,43 @@ +MediaTek MT6397/MT6323 PMIC Keys Device Driver + +There are two key functions provided by MT6397/MT6323 PMIC, pwrkey +and homekey. The key functions are defined as the subnode of the function +node provided by MT6397/MT6323 PMIC that is being defined as one kind +of Muti-Function Device (MFD) + +For MT6397/MT6323 MFD bindings see: +Documentation/devicetree/bindings/mfd/mt6397.txt + +Required properties: +- compatible: "mediatek,mt6397-keys" or "mediatek,mt6323-keys" +- linux,keycodes: See Documentation/devicetree/bindings/input/keys.txt + +Optional Properties: +- wakeup-source: See Documentation/devicetree/bindings/power/wakeup-source.txt +- mediatek,long-press-mode: Long press key shutdown setting, 1 for + pwrkey only, 2 for pwrkey/homekey together, others for disabled. +- power-off-time-sec: See Documentation/devicetree/bindings/input/keys.txt + +Example: + + pmic: mt6397 { + compatible = "mediatek,mt6397"; + + ... + + mt6397keys: mt6397keys { + compatible = "mediatek,mt6397-keys"; + mediatek,long-press-mode = <1>; + power-off-time-sec = <0>; + + power { + linux,keycodes = <116>; + wakeup-source; + }; + + home { + linux,keycodes = <114>; + }; + }; + + }; diff --git a/Documentation/devicetree/bindings/mfd/arizona.txt b/Documentation/devicetree/bindings/mfd/arizona.txt index bdd017686ea5..a014afb07902 100644 --- a/Documentation/devicetree/bindings/mfd/arizona.txt +++ b/Documentation/devicetree/bindings/mfd/arizona.txt @@ -50,7 +50,7 @@ Required properties: Optional properties: - - wlf,reset : GPIO specifier for the GPIO controlling /RESET + - reset-gpios : GPIO specifier for the GPIO controlling /RESET - clocks: Should reference the clocks supplied on MCLK1 and MCLK2 - clock-names: Should contains two strings: @@ -70,6 +70,10 @@ Optional properties: Documentation/devicetree/bindings/regulator/regulator.txt (wm5102, wm5110, wm8280, wm8997, wm8998, wm1814) +Deprecated properties: + + - wlf,reset : GPIO specifier for the GPIO controlling /RESET + Also see child specific device properties: Regulator - ../regulator/arizona-regulator.txt Extcon - ../extcon/extcon-arizona.txt diff --git a/Documentation/devicetree/bindings/mfd/da9063.txt b/Documentation/devicetree/bindings/mfd/da9063.txt index 05b21bcb8543..443e68286957 100644 --- a/Documentation/devicetree/bindings/mfd/da9063.txt +++ b/Documentation/devicetree/bindings/mfd/da9063.txt @@ -1,4 +1,4 @@ -* Dialog DA9063 Power Management Integrated Circuit (PMIC) +* Dialog DA9063/DA9063L Power Management Integrated Circuit (PMIC) DA9093 consists of a large and varied group of sub-devices (I2C Only): @@ -6,14 +6,14 @@ Device Supply Names Description ------ ------------ ----------- da9063-regulator : : LDOs & BUCKs da9063-onkey : : On Key -da9063-rtc : : Real-Time Clock +da9063-rtc : : Real-Time Clock (DA9063 only) da9063-watchdog : : Watchdog ====== Required properties: -- compatible : Should be "dlg,da9063" +- compatible : Should be "dlg,da9063" or "dlg,da9063l" - reg : Specifies the I2C slave address (this defaults to 0x58 but it can be modified to match the chip's OTP settings). - interrupt-parent : Specifies the reference to the interrupt controller for @@ -23,8 +23,8 @@ Required properties: Sub-nodes: -- regulators : This node defines the settings for the LDOs and BUCKs. The - DA9063 regulators are bound using their names listed below: +- regulators : This node defines the settings for the LDOs and BUCKs. + The DA9063(L) regulators are bound using their names listed below: bcore1 : BUCK CORE1 bcore2 : BUCK CORE2 @@ -32,16 +32,16 @@ Sub-nodes: bmem : BUCK MEM bio : BUCK IO bperi : BUCK PERI - ldo1 : LDO_1 - ldo2 : LDO_2 + ldo1 : LDO_1 (DA9063 only) + ldo2 : LDO_2 (DA9063 only) ldo3 : LDO_3 - ldo4 : LDO_4 - ldo5 : LDO_5 - ldo6 : LDO_6 + ldo4 : LDO_4 (DA9063 only) + ldo5 : LDO_5 (DA9063 only) + ldo6 : LDO_6 (DA9063 only) ldo7 : LDO_7 ldo8 : LDO_8 ldo9 : LDO_9 - ldo10 : LDO_10 + ldo10 : LDO_10 (DA9063 only) ldo11 : LDO_11 The component follows the standard regulator framework and the bindings @@ -49,8 +49,9 @@ Sub-nodes: Documentation/devicetree/bindings/regulator/regulator.txt - rtc : This node defines settings for the Real-Time Clock associated with - the DA9063. There are currently no entries in this binding, however - compatible = "dlg,da9063-rtc" should be added if a node is created. + the DA9063 only. The RTC is not present in DA9063L. There are currently + no entries in this binding, however compatible = "dlg,da9063-rtc" should + be added if a node is created. - onkey : This node defines the OnKey settings for controlling the key functionality of the device. The node should contain the compatible property @@ -65,8 +66,9 @@ Sub-nodes: and KEY_SLEEP. - watchdog : This node defines settings for the Watchdog timer associated - with the DA9063. There are currently no entries in this binding, however - compatible = "dlg,da9063-watchdog" should be added if a node is created. + with the DA9063 and DA9063L. There are currently no entries in this + binding, however compatible = "dlg,da9063-watchdog" should be added + if a node is created. Example: diff --git a/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt b/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt index 15bc885f9df4..c639705a98ef 100644 --- a/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt +++ b/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt @@ -12,6 +12,30 @@ Required properties: - spi-max-frequency : Typically set to 3000000 - spi-cs-high : SPI chip select direction +Optional subnodes: + +The sub-functions of CPCAP get their own node with their own compatible values, +which are described in the following files: + +- ../power/supply/cpcap-battery.txt +- ../power/supply/cpcap-charger.txt +- ../regulator/cpcap-regulator.txt +- ../phy/phy-cpcap-usb.txt +- ../input/cpcap-pwrbutton.txt +- ../rtc/cpcap-rtc.txt +- ../leds/leds-cpcap.txt +- ../iio/adc/cpcap-adc.txt + +The only exception is the audio codec. Instead of a compatible value its +node must be named "audio-codec". + +Required properties for the audio-codec subnode: + +- #sound-dai-cells = <1>; + +The audio-codec provides two DAIs. The first one is connected to the +Stereo HiFi DAC and the second one is connected to the Voice DAC. + Example: &mcspi1 { @@ -26,6 +50,24 @@ Example: #size-cells = <0>; spi-max-frequency = <3000000>; spi-cs-high; + + audio-codec { + #sound-dai-cells = <1>; + + /* HiFi */ + port@0 { + endpoint { + remote-endpoint = <&cpu_dai1>; + }; + }; + + /* Voice */ + port@1 { + endpoint { + remote-endpoint = <&cpu_dai2>; + }; + }; + }; }; }; diff --git a/Documentation/devicetree/bindings/mfd/mt6397.txt b/Documentation/devicetree/bindings/mfd/mt6397.txt index 522a3bbf1bac..d1df77f4d655 100644 --- a/Documentation/devicetree/bindings/mfd/mt6397.txt +++ b/Documentation/devicetree/bindings/mfd/mt6397.txt @@ -7,6 +7,7 @@ MT6397/MT6323 is a multifunction device with the following sub modules: - GPIO - Clock - LED +- Keys It is interfaced to host controller using SPI interface by a proprietary hardware called PMIC wrapper or pwrap. MT6397/MT6323 MFD is a child device of pwrap. @@ -40,6 +41,11 @@ Optional subnodes: - compatible: "mediatek,mt6323-led" see Documentation/devicetree/bindings/leds/leds-mt6323.txt +- keys + Required properties: + - compatible: "mediatek,mt6397-keys" or "mediatek,mt6323-keys" + see Documentation/devicetree/bindings/input/mtk-pmic-keys.txt + Example: pwrap: pwrap@1000f000 { compatible = "mediatek,mt8135-pwrap"; diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.txt b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.txt index 6ac06c1b9aec..143706222a51 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.txt +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.txt @@ -29,6 +29,9 @@ Required properties: "qcom,pm8916", "qcom,pm8004", "qcom,pm8909", + "qcom,pm8998", + "qcom,pmi8998", + "qcom,pm8005", or generalized "qcom,spmi-pmic". - reg: Specifies the SPMI USID slave address for this device. For more information see: diff --git a/MAINTAINERS b/MAINTAINERS index 2c7069037a15..8fcfc9a4a71d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13562,6 +13562,16 @@ T: git git://linuxtv.org/media_tree.git S: Maintained F: drivers/media/usb/stk1160/ +STM32 TIMER/LPTIMER DRIVERS +M: Fabrice Gasnier <fabrice.gasnier@st.com> +S: Maintained +F: drivers/*/stm32-*timer* +F: drivers/pwm/pwm-stm32* +F: include/linux/*/stm32-*tim* +F: Documentation/ABI/testing/*timer-stm32 +F: Documentation/devicetree/bindings/*/stm32-*timer +F: Documentation/devicetree/bindings/pwm/pwm-stm32* + STMMAC ETHERNET DRIVER M: Giuseppe Cavallaro <peppe.cavallaro@st.com> M: Alexandre Torgue <alexandre.torgue@st.com> 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; diff --git a/include/linux/mfd/arizona/pdata.h b/include/linux/mfd/arizona/pdata.h index f72dc53848d7..0013075d4cda 100644 --- a/include/linux/mfd/arizona/pdata.h +++ b/include/linux/mfd/arizona/pdata.h @@ -56,6 +56,7 @@ #define ARIZONA_MAX_PDM_SPK 2 struct regulator_init_data; +struct gpio_desc; struct arizona_micbias { int mV; /** Regulated voltage */ @@ -77,7 +78,7 @@ struct arizona_micd_range { }; struct arizona_pdata { - int reset; /** GPIO controlling /RESET, if any */ + struct gpio_desc *reset; /** GPIO controlling /RESET, if any */ /** Regulator configuration for MICVDD */ struct arizona_micsupp_pdata micvdd; diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h index 82bf7747b312..517e60eecbcb 100644 --- a/include/linux/mfd/axp20x.h +++ b/include/linux/mfd/axp20x.h @@ -592,11 +592,11 @@ enum axp806_irqs { AXP806_IRQ_DCDCC_V_LOW, AXP806_IRQ_DCDCD_V_LOW, AXP806_IRQ_DCDCE_V_LOW, - AXP806_IRQ_PWROK_LONG, - AXP806_IRQ_PWROK_SHORT, + AXP806_IRQ_POK_LONG, + AXP806_IRQ_POK_SHORT, AXP806_IRQ_WAKEUP, - AXP806_IRQ_PWROK_FALL, - AXP806_IRQ_PWROK_RISE, + AXP806_IRQ_POK_FALL, + AXP806_IRQ_POK_RISE, }; enum axp809_irqs { @@ -642,7 +642,7 @@ struct axp20x_dev { struct regmap_irq_chip_data *regmap_irqc; long variant; int nr_cells; - struct mfd_cell *cells; + const struct mfd_cell *cells; const struct regmap_config *regmap_cfg; const struct regmap_irq_chip *regmap_irq_chip; }; diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h index f09e9cf2e4ab..32421dfeb996 100644 --- a/include/linux/mfd/cros_ec.h +++ b/include/linux/mfd/cros_ec.h @@ -329,23 +329,7 @@ extern struct attribute_group cros_ec_vbc_attr_group; /* debugfs stuff */ int cros_ec_debugfs_init(struct cros_ec_dev *ec); void cros_ec_debugfs_remove(struct cros_ec_dev *ec); - -/* ACPI GPE handler */ -#ifdef CONFIG_ACPI - -int cros_ec_acpi_install_gpe_handler(struct device *dev); -void cros_ec_acpi_remove_gpe_handler(void); -void cros_ec_acpi_clear_gpe(void); - -#else /* CONFIG_ACPI */ - -static inline int cros_ec_acpi_install_gpe_handler(struct device *dev) -{ - return -ENODEV; -} -static inline void cros_ec_acpi_remove_gpe_handler(void) {} -static inline void cros_ec_acpi_clear_gpe(void) {} - -#endif /* CONFIG_ACPI */ +void cros_ec_debugfs_suspend(struct cros_ec_dev *ec); +void cros_ec_debugfs_resume(struct cros_ec_dev *ec); #endif /* __LINUX_MFD_CROS_EC_H */ diff --git a/include/linux/mfd/stm32-timers.h b/include/linux/mfd/stm32-timers.h index 2aadab6f34a1..067d14655c28 100644 --- a/include/linux/mfd/stm32-timers.h +++ b/include/linux/mfd/stm32-timers.h @@ -8,6 +8,8 @@ #define _LINUX_STM32_GPTIMER_H_ #include <linux/clk.h> +#include <linux/dmaengine.h> +#include <linux/dma-mapping.h> #include <linux/regmap.h> #define TIM_CR1 0x00 /* Control Register 1 */ @@ -27,6 +29,8 @@ #define TIM_CCR3 0x3C /* Capt/Comp Register 3 */ #define TIM_CCR4 0x40 /* Capt/Comp Register 4 */ #define TIM_BDTR 0x44 /* Break and Dead-Time Reg */ +#define TIM_DCR 0x48 /* DMA control register */ +#define TIM_DMAR 0x4C /* DMA register for transfer */ #define TIM_CR1_CEN BIT(0) /* Counter Enable */ #define TIM_CR1_DIR BIT(4) /* Counter Direction */ @@ -36,17 +40,35 @@ #define TIM_SMCR_SMS (BIT(0) | BIT(1) | BIT(2)) /* Slave mode selection */ #define TIM_SMCR_TS (BIT(4) | BIT(5) | BIT(6)) /* Trigger selection */ #define TIM_DIER_UIE BIT(0) /* Update interrupt */ +#define TIM_DIER_UDE BIT(8) /* Update DMA request Enable */ +#define TIM_DIER_CC1DE BIT(9) /* CC1 DMA request Enable */ +#define TIM_DIER_CC2DE BIT(10) /* CC2 DMA request Enable */ +#define TIM_DIER_CC3DE BIT(11) /* CC3 DMA request Enable */ +#define TIM_DIER_CC4DE BIT(12) /* CC4 DMA request Enable */ +#define TIM_DIER_COMDE BIT(13) /* COM DMA request Enable */ +#define TIM_DIER_TDE BIT(14) /* Trigger DMA request Enable */ #define TIM_SR_UIF BIT(0) /* Update interrupt flag */ #define TIM_EGR_UG BIT(0) /* Update Generation */ #define TIM_CCMR_PE BIT(3) /* Channel Preload Enable */ #define TIM_CCMR_M1 (BIT(6) | BIT(5)) /* Channel PWM Mode 1 */ +#define TIM_CCMR_CC1S (BIT(0) | BIT(1)) /* Capture/compare 1 sel */ +#define TIM_CCMR_IC1PSC GENMASK(3, 2) /* Input capture 1 prescaler */ +#define TIM_CCMR_CC2S (BIT(8) | BIT(9)) /* Capture/compare 2 sel */ +#define TIM_CCMR_IC2PSC GENMASK(11, 10) /* Input capture 2 prescaler */ +#define TIM_CCMR_CC1S_TI1 BIT(0) /* IC1/IC3 selects TI1/TI3 */ +#define TIM_CCMR_CC1S_TI2 BIT(1) /* IC1/IC3 selects TI2/TI4 */ +#define TIM_CCMR_CC2S_TI2 BIT(8) /* IC2/IC4 selects TI2/TI4 */ +#define TIM_CCMR_CC2S_TI1 BIT(9) /* IC2/IC4 selects TI1/TI3 */ #define TIM_CCER_CC1E BIT(0) /* Capt/Comp 1 out Ena */ #define TIM_CCER_CC1P BIT(1) /* Capt/Comp 1 Polarity */ #define TIM_CCER_CC1NE BIT(2) /* Capt/Comp 1N out Ena */ #define TIM_CCER_CC1NP BIT(3) /* Capt/Comp 1N Polarity */ #define TIM_CCER_CC2E BIT(4) /* Capt/Comp 2 out Ena */ +#define TIM_CCER_CC2P BIT(5) /* Capt/Comp 2 Polarity */ #define TIM_CCER_CC3E BIT(8) /* Capt/Comp 3 out Ena */ +#define TIM_CCER_CC3P BIT(9) /* Capt/Comp 3 Polarity */ #define TIM_CCER_CC4E BIT(12) /* Capt/Comp 4 out Ena */ +#define TIM_CCER_CC4P BIT(13) /* Capt/Comp 4 Polarity */ #define TIM_CCER_CCXE (BIT(0) | BIT(4) | BIT(8) | BIT(12)) #define TIM_BDTR_BKE BIT(12) /* Break input enable */ #define TIM_BDTR_BKP BIT(13) /* Break input polarity */ @@ -56,8 +78,11 @@ #define TIM_BDTR_BK2F (BIT(20) | BIT(21) | BIT(22) | BIT(23)) #define TIM_BDTR_BK2E BIT(24) /* Break 2 input enable */ #define TIM_BDTR_BK2P BIT(25) /* Break 2 input polarity */ +#define TIM_DCR_DBA GENMASK(4, 0) /* DMA base addr */ +#define TIM_DCR_DBL GENMASK(12, 8) /* DMA burst len */ #define MAX_TIM_PSC 0xFFFF +#define MAX_TIM_ICPSC 0x3 #define TIM_CR2_MMS_SHIFT 4 #define TIM_CR2_MMS2_SHIFT 20 #define TIM_SMCR_TS_SHIFT 4 @@ -65,9 +90,54 @@ #define TIM_BDTR_BKF_SHIFT 16 #define TIM_BDTR_BK2F_SHIFT 20 +enum stm32_timers_dmas { + STM32_TIMERS_DMA_CH1, + STM32_TIMERS_DMA_CH2, + STM32_TIMERS_DMA_CH3, + STM32_TIMERS_DMA_CH4, + STM32_TIMERS_DMA_UP, + STM32_TIMERS_DMA_TRIG, + STM32_TIMERS_DMA_COM, + STM32_TIMERS_MAX_DMAS, +}; + +/** + * struct stm32_timers_dma - STM32 timer DMA handling. + * @completion: end of DMA transfer completion + * @phys_base: control registers physical base address + * @lock: protect DMA access + * @chan: DMA channel in use + * @chans: DMA channels available for this timer instance + */ +struct stm32_timers_dma { + struct completion completion; + phys_addr_t phys_base; + struct mutex lock; + struct dma_chan *chan; + struct dma_chan *chans[STM32_TIMERS_MAX_DMAS]; +}; + struct stm32_timers { struct clk *clk; struct regmap *regmap; u32 max_arr; + struct stm32_timers_dma dma; /* Only to be used by the parent */ }; + +#if IS_REACHABLE(CONFIG_MFD_STM32_TIMERS) +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); +#else +static inline 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) +{ + return -ENODEV; +} +#endif #endif diff --git a/include/linux/mfd/syscon/exynos4-pmu.h b/include/linux/mfd/syscon/exynos4-pmu.h deleted file mode 100644 index 278b1b1549e9..000000000000 --- a/include/linux/mfd/syscon/exynos4-pmu.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2015 Samsung Electronics Co., Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _LINUX_MFD_SYSCON_PMU_EXYNOS4_H_ -#define _LINUX_MFD_SYSCON_PMU_EXYNOS4_H_ - -/* Exynos4 PMU register definitions */ - -/* MIPI_PHYn_CONTROL register offset: n = 0..1 */ -#define EXYNOS4_MIPI_PHY_CONTROL(n) (0x710 + (n) * 4) -#define EXYNOS4_MIPI_PHY_ENABLE (1 << 0) -#define EXYNOS4_MIPI_PHY_SRESETN (1 << 1) -#define EXYNOS4_MIPI_PHY_MRESETN (1 << 2) -#define EXYNOS4_MIPI_PHY_RESET_MASK (3 << 1) - -#endif /* _LINUX_MFD_SYSCON_PMU_EXYNOS4_H_ */ diff --git a/include/linux/mfd/syscon/exynos5-pmu.h b/include/linux/mfd/syscon/exynos5-pmu.h deleted file mode 100644 index b4942a32b81d..000000000000 --- a/include/linux/mfd/syscon/exynos5-pmu.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Exynos5 SoC series Power Management Unit (PMU) register offsets - * and bit definitions. - * - * Copyright (C) 2014 Samsung Electronics Co., Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _LINUX_MFD_SYSCON_PMU_EXYNOS5_H_ -#define _LINUX_MFD_SYSCON_PMU_EXYNOS5_H_ - -#define EXYNOS5_PHY_ENABLE BIT(0) -#define EXYNOS5_MIPI_PHY_S_RESETN BIT(1) -#define EXYNOS5_MIPI_PHY_M_RESETN BIT(2) - -#endif /* _LINUX_MFD_SYSCON_PMU_EXYNOS5_H_ */ diff --git a/include/linux/mfd/tps65218.h b/include/linux/mfd/tps65218.h index f069c518c0ed..c204d9a79436 100644 --- a/include/linux/mfd/tps65218.h +++ b/include/linux/mfd/tps65218.h @@ -205,10 +205,10 @@ enum tps65218_regulator_id { TPS65218_DCDC_4, TPS65218_DCDC_5, TPS65218_DCDC_6, - /* LS's */ - TPS65218_LS_3, /* LDOs */ TPS65218_LDO_1, + /* LS's */ + TPS65218_LS_3, }; #define TPS65218_MAX_REG_ID TPS65218_LDO_1 diff --git a/include/linux/mfd/tps68470.h b/include/linux/mfd/tps68470.h index 44f9d9f647ed..ffe81127d91c 100644 --- a/include/linux/mfd/tps68470.h +++ b/include/linux/mfd/tps68470.h @@ -1,17 +1,6 @@ -/* - * Copyright (c) 2017 Intel Corporation - * - * Functions to access TPS68470 power management chip. - * - * 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. - */ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2017 Intel Corporation */ +/* Functions to access TPS68470 power management chip. */ #ifndef __LINUX_MFD_TPS68470_H #define __LINUX_MFD_TPS68470_H |