Commit 883cad5b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mfd-next-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd

Pull MFD updates from Lee Jones:
 "New Device Support:
   - Add support for AXP813 ADC to AXP20x
   - Add support for PM8005, PM8998 and PMI8998

  New Functionality:
   - Add support for Battery Power Supply to AXP813
   - Add support for SYSCON to SPARD SC27XX SPI
   - Add support for RTC to ChromeOS Embedded-Controller

  Fix-ups:
   - Remove unused code; exynos{4,5}-pmu, cros_ec, cros_ec_acpi_gpe
   - Remove duplicate error messages (-ENOMEM, etc); htc-i2cpld,
        janz-cmodio, max8997, rc5t583, sm501, smsc-ece1099, abx500-core,
        si476x-i2c, ti_am335x_tscadc, tps65090, tps6586x, tps65910,
        tps80031, twl6030-irq, viperboard
   - Succinctly use ptr to struct in sizeof(); rc5t583, abx500-core,
        sm501, smsc-ece1099
   - Simplify syntax for NULL ptr checking; abx500-core, sm501
   - No not unnecessarily initialise variables; tps65910, tps65910
   - Reorganise and simplify driver data; omap-usb-tll
   - Move to SPDX license statement; tps68470
   - Probe ADCs via DT; axp20x
   - Use new GPIOD API; arizona-core
   - Constify things; axp20x
   - Reduce code-size (use MACROS, etc); axp20x, omap-usb-host
   - Add DT support/docs; motorola-cpcap
   - Remove VLAs; rave-sp
   - Use devm_* managed resources; cros_ec
   - Interrogate HW for firmware version; rave-sp
   - Provide ACPI support for ChromeOS Embedded-Controller

  Bug Fixes:
   - Reorder ordered (enum) device list; tps65218
   - Only accept valid data from the offset; rave-sp
   - Refrain from copying junk from failed SPI read; cros_ec_dev
   - Fix potential memory leaks; pcf50633-core
   - Fix clock initialisation; twl-core
   - Fix build-issue; tps65911
   - Fix off-by-one error; tps65911
   - Fix code ordering issues; intel-lpss
   - Fix COMPILE_TEST related issues; pwm-stm32
   - Fix broken MMC card detection; asic3
   - Fix clocking related issues; intel-lpss-pci"

* tag 'mfd-next-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (84 commits)
  mfd: cros_ec: Remove unused __remove function
  mfd: wm97xx-core: Platform data can be NULL
  mfd: cros_ec_dev: Don't advertise junk features on failure
  mfd: cros_ec: Use devm_kzalloc for private data
  mfd: intel-lpss: Fix Intel Cannon Lake LPSS I2C input clock
  mfd: asic3: Fix broken MMC card detection
  mfd: timberdale: Fix spelling mistake "Uknown" -> "Unknown"
  mfd: omap-usb-host: Use match_string() helper
  mfd: stm32-timers: Fix pwm-stm32 linker issue with COMPILE_TEST
  pwm: stm32: Initialize raw local variables
  mfd: arizona: Update DT doc to support more standard Reset binding
  dt-bindings: mfd: Add bindings for DA9063L
  mfd: intel-lpss: Correct names of RESETS register bits
  mfd: qcom-spmi-pmic: Add support for pm8005, pm8998 and pmi8998
  mfd: intel-lpss: Program REMAP register in PIO mode
  mfd: cros_ec_i2c: Moving the system sleep pm ops to late
  mfd: cros_ec_i2c: Add ACPI module device table
  mfd: cros_ec_dev: Register shutdown function for debugfs
  mfd: cros_ec_dev: Register cros-ec-rtc driver as a subdevice
  mfd: cros_ec: Don't try to grab log when suspended
  ...
parents 8d08c055 556c2420
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>;
};
};
};
...@@ -50,7 +50,7 @@ Required properties: ...@@ -50,7 +50,7 @@ Required properties:
Optional 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 - clocks: Should reference the clocks supplied on MCLK1 and MCLK2
- clock-names: Should contains two strings: - clock-names: Should contains two strings:
...@@ -70,6 +70,10 @@ Optional properties: ...@@ -70,6 +70,10 @@ Optional properties:
Documentation/devicetree/bindings/regulator/regulator.txt Documentation/devicetree/bindings/regulator/regulator.txt
(wm5102, wm5110, wm8280, wm8997, wm8998, wm1814) (wm5102, wm5110, wm8280, wm8997, wm8998, wm1814)
Deprecated properties:
- wlf,reset : GPIO specifier for the GPIO controlling /RESET
Also see child specific device properties: Also see child specific device properties:
Regulator - ../regulator/arizona-regulator.txt Regulator - ../regulator/arizona-regulator.txt
Extcon - ../extcon/extcon-arizona.txt Extcon - ../extcon/extcon-arizona.txt
......
* 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): DA9093 consists of a large and varied group of sub-devices (I2C Only):
...@@ -6,14 +6,14 @@ Device Supply Names Description ...@@ -6,14 +6,14 @@ Device Supply Names Description
------ ------------ ----------- ------ ------------ -----------
da9063-regulator : : LDOs & BUCKs da9063-regulator : : LDOs & BUCKs
da9063-onkey : : On Key da9063-onkey : : On Key
da9063-rtc : : Real-Time Clock da9063-rtc : : Real-Time Clock (DA9063 only)
da9063-watchdog : : Watchdog da9063-watchdog : : Watchdog
====== ======
Required properties: 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 - reg : Specifies the I2C slave address (this defaults to 0x58 but it can be
modified to match the chip's OTP settings). modified to match the chip's OTP settings).
- interrupt-parent : Specifies the reference to the interrupt controller for - interrupt-parent : Specifies the reference to the interrupt controller for
...@@ -23,8 +23,8 @@ Required properties: ...@@ -23,8 +23,8 @@ Required properties:
Sub-nodes: Sub-nodes:
- regulators : This node defines the settings for the LDOs and BUCKs. The - regulators : This node defines the settings for the LDOs and BUCKs.
DA9063 regulators are bound using their names listed below: The DA9063(L) regulators are bound using their names listed below:
bcore1 : BUCK CORE1 bcore1 : BUCK CORE1
bcore2 : BUCK CORE2 bcore2 : BUCK CORE2
...@@ -32,16 +32,16 @@ Sub-nodes: ...@@ -32,16 +32,16 @@ Sub-nodes:
bmem : BUCK MEM bmem : BUCK MEM
bio : BUCK IO bio : BUCK IO
bperi : BUCK PERI bperi : BUCK PERI
ldo1 : LDO_1 ldo1 : LDO_1 (DA9063 only)
ldo2 : LDO_2 ldo2 : LDO_2 (DA9063 only)
ldo3 : LDO_3 ldo3 : LDO_3
ldo4 : LDO_4 ldo4 : LDO_4 (DA9063 only)
ldo5 : LDO_5 ldo5 : LDO_5 (DA9063 only)
ldo6 : LDO_6 ldo6 : LDO_6 (DA9063 only)
ldo7 : LDO_7 ldo7 : LDO_7
ldo8 : LDO_8 ldo8 : LDO_8
ldo9 : LDO_9 ldo9 : LDO_9
ldo10 : LDO_10 ldo10 : LDO_10 (DA9063 only)
ldo11 : LDO_11 ldo11 : LDO_11
The component follows the standard regulator framework and the bindings The component follows the standard regulator framework and the bindings
...@@ -49,8 +49,9 @@ Sub-nodes: ...@@ -49,8 +49,9 @@ Sub-nodes:
Documentation/devicetree/bindings/regulator/regulator.txt Documentation/devicetree/bindings/regulator/regulator.txt
- rtc : This node defines settings for the Real-Time Clock associated with - rtc : This node defines settings for the Real-Time Clock associated with
the DA9063. There are currently no entries in this binding, however the DA9063 only. The RTC is not present in DA9063L. There are currently
compatible = "dlg,da9063-rtc" should be added if a node is created. 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 - onkey : This node defines the OnKey settings for controlling the key
functionality of the device. The node should contain the compatible property functionality of the device. The node should contain the compatible property
...@@ -65,8 +66,9 @@ Sub-nodes: ...@@ -65,8 +66,9 @@ Sub-nodes:
and KEY_SLEEP. and KEY_SLEEP.
- watchdog : This node defines settings for the Watchdog timer associated - watchdog : This node defines settings for the Watchdog timer associated
with the DA9063. There are currently no entries in this binding, however with the DA9063 and DA9063L. There are currently no entries in this
compatible = "dlg,da9063-watchdog" should be added if a node is created. binding, however compatible = "dlg,da9063-watchdog" should be added
if a node is created.
Example: Example:
......
...@@ -12,6 +12,30 @@ Required properties: ...@@ -12,6 +12,30 @@ Required properties:
- spi-max-frequency : Typically set to 3000000 - spi-max-frequency : Typically set to 3000000
- spi-cs-high : SPI chip select direction - 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: Example:
&mcspi1 { &mcspi1 {
...@@ -26,6 +50,24 @@ Example: ...@@ -26,6 +50,24 @@ Example:
#size-cells = <0>; #size-cells = <0>;
spi-max-frequency = <3000000>; spi-max-frequency = <3000000>;
spi-cs-high; 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>;
};
};
};
}; };
}; };
...@@ -7,6 +7,7 @@ MT6397/MT6323 is a multifunction device with the following sub modules: ...@@ -7,6 +7,7 @@ MT6397/MT6323 is a multifunction device with the following sub modules:
- GPIO - GPIO
- Clock - Clock
- LED - LED
- Keys
It is interfaced to host controller using SPI interface by a proprietary hardware 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. called PMIC wrapper or pwrap. MT6397/MT6323 MFD is a child device of pwrap.
...@@ -40,6 +41,11 @@ Optional subnodes: ...@@ -40,6 +41,11 @@ Optional subnodes:
- compatible: "mediatek,mt6323-led" - compatible: "mediatek,mt6323-led"
see Documentation/devicetree/bindings/leds/leds-mt6323.txt 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: Example:
pwrap: pwrap@1000f000 { pwrap: pwrap@1000f000 {
compatible = "mediatek,mt8135-pwrap"; compatible = "mediatek,mt8135-pwrap";
......
...@@ -29,6 +29,9 @@ Required properties: ...@@ -29,6 +29,9 @@ Required properties:
"qcom,pm8916", "qcom,pm8916",
"qcom,pm8004", "qcom,pm8004",
"qcom,pm8909", "qcom,pm8909",
"qcom,pm8998",
"qcom,pmi8998",
"qcom,pm8005",
or generalized "qcom,spmi-pmic". or generalized "qcom,spmi-pmic".
- reg: Specifies the SPMI USID slave address for this device. - reg: Specifies the SPMI USID slave address for this device.
For more information see: For more information see:
......
...@@ -13562,6 +13562,16 @@ T: git git://linuxtv.org/media_tree.git ...@@ -13562,6 +13562,16 @@ T: git git://linuxtv.org/media_tree.git
S: Maintained S: Maintained
F: drivers/media/usb/stk1160/ 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 STMMAC ETHERNET DRIVER
M: Giuseppe Cavallaro <peppe.cavallaro@st.com> M: Giuseppe Cavallaro <peppe.cavallaro@st.com>
M: Alexandre Torgue <alexandre.torgue@st.com> M: Alexandre Torgue <alexandre.torgue@st.com>
......
...@@ -747,4 +747,13 @@ config KEYBOARD_BCM ...@@ -747,4 +747,13 @@ config KEYBOARD_BCM
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called bcm-keypad. 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 endif
...@@ -40,6 +40,7 @@ obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o ...@@ -40,6 +40,7 @@ obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o
obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o
obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o
obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_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_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o
obj-$(CONFIG_KEYBOARD_NSPIRE) += nspire-keypad.o obj-$(CONFIG_KEYBOARD_NSPIRE) += nspire-keypad.o
......
/*
* 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");
...@@ -13,7 +13,6 @@ obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o ...@@ -13,7 +13,6 @@ obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
cros_ec_core-objs := cros_ec.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) += cros_ec_core.o
obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
......
...@@ -2519,11 +2519,10 @@ static ssize_t ab8500_subscribe_write(struct file *file, ...@@ -2519,11 +2519,10 @@ static ssize_t ab8500_subscribe_write(struct file *file,
if (!dev_attr[irq_index]) if (!dev_attr[irq_index])
return -ENOMEM; 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]) if (!event_name[irq_index])
return -ENOMEM; return -ENOMEM;
sprintf(event_name[irq_index], "%lu", user_val);
dev_attr[irq_index]->show = show_irq; dev_attr[irq_index]->show = show_irq;
dev_attr[irq_index]->store = NULL; dev_attr[irq_index]->store = NULL;
dev_attr[irq_index]->attr.name = event_name[irq_index]; dev_attr[irq_index]->attr.name = event_name[irq_index];
......
...@@ -37,15 +37,12 @@ int abx500_register_ops(struct device *dev, struct abx500_ops *ops) ...@@ -37,15 +37,12 @@ int abx500_register_ops(struct device *dev, struct abx500_ops *ops)
{ {
struct abx500_device_entry *dev_entry; struct abx500_device_entry *dev_entry;
dev_entry = devm_kzalloc(dev, dev_entry = devm_kzalloc(dev, sizeof(*dev_entry), GFP_KERNEL);
sizeof(struct abx500_device_entry), if (!dev_entry)
GFP_KERNEL);
if (!dev_entry) {
dev_err(dev, "register_ops kzalloc failed");
return -ENOMEM; return -ENOMEM;
}
dev_entry->dev = dev; 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); list_add_tail(&dev_entry->list, &abx500_list);
return 0; return 0;
...@@ -68,7 +65,7 @@ int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg, ...@@ -68,7 +65,7 @@ int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
struct abx500_ops *ops; struct abx500_ops *ops;
lookup_ops(dev->parent, &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); return ops->set_register(dev, bank, reg, value);
else else
return -ENOTSUPP; return -ENOTSUPP;
...@@ -81,7 +78,7 @@ int abx500_get_register_interruptible(struct device *dev, u8 bank, u8 reg, ...@@ -81,7 +78,7 @@ int abx500_get_register_interruptible(struct device *dev, u8 bank, u8 reg,
struct abx500_ops *ops; struct abx500_ops *ops;
lookup_ops(dev->parent, &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); return ops->get_register(dev, bank, reg, value);
else else
return -ENOTSUPP; return -ENOTSUPP;
...@@ -94,7 +91,7 @@ int abx500_get_register_page_interruptible(struct device *dev, u8 bank, ...@@ -94,7 +91,7 @@ int abx500_get_register_page_interruptible(struct device *dev, u8 bank,
struct abx500_ops *ops; struct abx500_ops *ops;
lookup_ops(dev->parent, &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, return ops->get_register_page(dev, bank,
first_reg, regvals, numregs); first_reg, regvals, numregs);
else else
...@@ -108,7 +105,7 @@ int abx500_mask_and_set_register_interruptible(struct device *dev, u8 bank, ...@@ -108,7 +105,7 @@ int abx500_mask_and_set_register_interruptible(struct device *dev, u8 bank,
struct abx500_ops *ops; struct abx500_ops *ops;
lookup_ops(dev->parent, &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, return ops->mask_and_set_register(dev, bank,
reg, bitmask, bitvalues); reg, bitmask, bitvalues);
else else
...@@ -121,7 +118,7 @@ int abx500_get_chip_id(struct device *dev) ...@@ -121,7 +118,7 @@ int abx500_get_chip_id(struct device *dev)
struct abx500_ops *ops; struct abx500_ops *ops;
lookup_ops(dev->parent, &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); return ops->get_chip_id(dev);
else else
return -ENOTSUPP; return -ENOTSUPP;
...@@ -133,7 +130,7 @@ int abx500_event_registers_startup_state_get(struct device *dev, u8 *event) ...@@ -133,7 +130,7 @@ int abx500_event_registers_startup_state_get(struct device *dev, u8 *event)
struct abx500_ops *ops; struct abx500_ops *ops;
lookup_ops(dev->parent, &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); return ops->event_registers_startup_state_get(dev, event);
else else
return -ENOTSUPP; return -ENOTSUPP;
...@@ -145,7 +142,7 @@ int abx500_startup_irq_enabled(struct device *dev, unsigned int irq) ...@@ -145,7 +142,7 @@ int abx500_startup_irq_enabled(struct device *dev, unsigned int irq)
struct abx500_ops *ops; struct abx500_ops *ops;
lookup_ops(dev->parent, &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); return ops->startup_irq_enabled(dev, irq);
else else
return -ENOTSUPP; return -ENOTSUPP;
......
...@@ -13,13 +13,12 @@ ...@@ -13,13 +13,12 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
...@@ -279,7 +278,7 @@ static int arizona_wait_for_boot(struct arizona *arizona) ...@@ -279,7 +278,7 @@ static int arizona_wait_for_boot(struct arizona *arizona)
static inline void arizona_enable_reset(struct arizona *arizona) static inline void arizona_enable_reset(struct arizona *arizona)
{ {
if (arizona->pdata.reset) 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) static void arizona_disable_reset(struct arizona *arizona)
...@@ -295,7 +294,7 @@ static void arizona_disable_reset(struct arizona *arizona) ...@@ -295,7 +294,7 @@ static void arizona_disable_reset(struct arizona *arizona)
break; break;
} }
gpio_set_value_cansleep(arizona->pdata.reset, 1); gpiod_set_raw_value_cansleep(arizona->pdata.reset, 1);
usleep_range(1000, 5000); usleep_range(1000, 5000);
} }
} }
...@@ -799,14 +798,27 @@ static int arizona_of_get_core_pdata(struct arizona *arizona) ...@@ -799,14 +798,27 @@ static int arizona_of_get_core_pdata(struct arizona *arizona)
struct arizona_pdata *pdata = &arizona->pdata; struct arizona_pdata *pdata = &arizona->pdata;
int ret, i; int ret, i;
pdata->reset = of_get_named_gpio(arizona->dev->of_node, "wlf,reset", 0); /* Handle old non-standard DT binding */
if (pdata->reset == -EPROBE_DEFER) { pdata->reset = devm_gpiod_get_from_of_node(arizona->dev,
return pdata->reset; arizona->dev->of_node,
} else if (pdata->reset < 0) { "wlf,reset", 0,
dev_err(arizona->dev, "Reset GPIO missing/malformed: %d\n", GPIOD_OUT_LOW,
pdata->reset); "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, ret = of_property_read_u32_array(arizona->dev->of_node,
...@@ -1050,14 +1062,19 @@ int arizona_dev_init(struct arizona *arizona) ...@@ -1050,14 +1062,19 @@ int arizona_dev_init(struct arizona *arizona)
goto err_early; goto err_early;
} }
if (arizona->pdata.reset) { if (!arizona->pdata.reset) {
/* Start out with /RESET low to put the chip into reset */ /* Start out with /RESET low to put the chip into reset */
ret = devm_gpio_request_one(arizona->dev, arizona->pdata.reset, arizona->pdata.reset = devm_gpiod_get(arizona->dev, "reset",
GPIOF_DIR_OUT | GPIOF_INIT_LOW, GPIOD_OUT_LOW);
"arizona /RESET"); if (IS_ERR(arizona->pdata.reset)) {
if (ret != 0) { ret = PTR_ERR(arizona->pdata.reset);
dev_err(dev, "Failed to request /RESET: %d\n", ret); if (ret == -EPROBE_DEFER)
goto err_dcvdd; goto err_dcvdd;
dev_err(arizona->dev,
"Reset GPIO missing/malformed: %d\n", ret);
arizona->pdata.reset = NULL;
} }
} }
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include <linux/mfd/ds1wm.h> #include <linux/mfd/ds1wm.h>
#include <linux/mfd/tmio.h> #include <linux/mfd/tmio.h>
#include <linux/mmc/host.h>
enum { enum {
ASIC3_CLOCK_SPI, ASIC3_CLOCK_SPI,
ASIC3_CLOCK_OWM, ASIC3_CLOCK_OWM,
...@@ -719,6 +721,7 @@ static void asic3_mmc_clk_div(struct platform_device *pdev, int state) ...@@ -719,6 +721,7 @@ static void asic3_mmc_clk_div(struct platform_device *pdev, int state)
static struct tmio_mmc_data asic3_mmc_data = { static struct tmio_mmc_data asic3_mmc_data = {
.hclk = 24576000, .hclk = 24576000,
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
.set_pwr = asic3_mmc_pwr, .set_pwr = asic3_mmc_pwr,
.set_clk_div = asic3_mmc_clk_div, .set_clk_div = asic3_mmc_clk_div,
}; };
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
*/ */
#include <linux/mfd/syscon/atmel-smc.h> #include <linux/mfd/syscon/atmel-smc.h>
#include <linux/string.h>
/** /**
* atmel_smc_cs_conf_init - initialize a SMC CS conf * atmel_smc_cs_conf_init - initialize a SMC CS conf
......
This diff is collapsed.
...@@ -112,11 +112,15 @@ int cros_ec_register(struct cros_ec_device *ec_dev) ...@@ -112,11 +112,15 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
mutex_init(&ec_dev->lock); 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) { if (ec_dev->irq) {
err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread, err = devm_request_threaded_irq(dev, ec_dev->irq, NULL,
IRQF_TRIGGER_LOW | IRQF_ONESHOT, ec_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"chromeos-ec", ec_dev); "chromeos-ec", ec_dev);
if (err) { if (err) {
dev_err(dev, "Failed to request IRQ %d: %d", dev_err(dev, "Failed to request IRQ %d: %d",
...@@ -131,7 +135,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev) ...@@ -131,7 +135,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
dev_err(dev, dev_err(dev,
"Failed to register Embedded Controller subdevice %d\n", "Failed to register Embedded Controller subdevice %d\n",
err); err);
goto fail_mfd; return err;
} }
if (ec_dev->max_passthru) { if (ec_dev->max_passthru) {
...@@ -149,7 +153,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev) ...@@ -149,7 +153,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
dev_err(dev, dev_err(dev,
"Failed to register Power Delivery subdevice %d\n", "Failed to register Power Delivery subdevice %d\n",
err); err);
goto fail_mfd; return err;
} }
} }
...@@ -158,7 +162,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev) ...@@ -158,7 +162,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
if (err) { if (err) {
mfd_remove_devices(dev); mfd_remove_devices(dev);
dev_err(dev, "Failed to register sub-devices\n"); 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) ...@@ -173,14 +177,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
dev_info(dev, "Chrome EC device registered\n"); dev_info(dev, "Chrome EC device registered\n");
cros_ec_acpi_install_gpe_handler(dev);
return 0; return 0;
fail_mfd:
if (ec_dev->irq)
free_irq(ec_dev->irq, ec_dev);
return err;
} }
EXPORT_SYMBOL(cros_ec_register); EXPORT_SYMBOL(cros_ec_register);
...@@ -188,11 +185,6 @@ int cros_ec_remove(struct cros_ec_device *ec_dev) ...@@ -188,11 +185,6 @@ int cros_ec_remove(struct cros_ec_device *ec_dev)
{ {
mfd_remove_devices(ec_dev->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; return 0;
} }
EXPORT_SYMBOL(cros_ec_remove); EXPORT_SYMBOL(cros_ec_remove);
...@@ -204,14 +196,9 @@ int cros_ec_suspend(struct cros_ec_device *ec_dev) ...@@ -204,14 +196,9 @@ int cros_ec_suspend(struct cros_ec_device *ec_dev)
int ret; int ret;
u8 sleep_event; u8 sleep_event;
if (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) { sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ?
sleep_event = HOST_SLEEP_EVENT_S3_SUSPEND; HOST_SLEEP_EVENT_S3_SUSPEND :
} else { HOST_SLEEP_EVENT_S0IX_SUSPEND;
sleep_event = HOST_SLEEP_EVENT_S0IX_SUSPEND;
/* Clearing the GPE status for any pending event */
cros_ec_acpi_clear_gpe();
}
ret = cros_ec_sleep_event(ec_dev, sleep_event); ret = cros_ec_sleep_event(ec_dev, sleep_event);
if (ret < 0) if (ret < 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);
}
...@@ -113,9 +113,9 @@ static int cros_ec_check_features(struct cros_ec_dev *ec, int feature) ...@@ -113,9 +113,9 @@ static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
dev_warn(ec->dev, "cannot get EC features: %d/%d\n", dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
ret, msg->result); ret, msg->result);
memset(ec->features, 0, sizeof(ec->features)); 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", dev_dbg(ec->dev, "EC features %08x %08x\n",
ec->features[0], ec->features[1]); ec->features[0], ec->features[1]);
...@@ -262,13 +262,6 @@ static const struct file_operations fops = { ...@@ -262,13 +262,6 @@ static const struct file_operations fops = {
#endif #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) static void cros_ec_sensors_register(struct cros_ec_dev *ec)
{ {
/* /*
...@@ -383,12 +376,16 @@ static void cros_ec_sensors_register(struct cros_ec_dev *ec) ...@@ -383,12 +376,16 @@ static void cros_ec_sensors_register(struct cros_ec_dev *ec)
kfree(msg); kfree(msg);
} }
static const struct mfd_cell cros_ec_rtc_cells[] = {
{ .name = "cros-ec-rtc" }
};
static int ec_device_probe(struct platform_device *pdev) static int ec_device_probe(struct platform_device *pdev)
{ {
int retval = -ENOMEM; int retval = -ENOMEM;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct cros_ec_platform *ec_platform = dev_get_platdata(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) if (!ec)
return retval; return retval;
...@@ -410,7 +407,6 @@ static int ec_device_probe(struct platform_device *pdev) ...@@ -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.devt = MKDEV(ec_major, pdev->id);
ec->class_dev.class = &cros_class; ec->class_dev.class = &cros_class;
ec->class_dev.parent = dev; ec->class_dev.parent = dev;
ec->class_dev.release = __remove;
retval = dev_set_name(&ec->class_dev, "%s", ec_platform->ec_name); retval = dev_set_name(&ec->class_dev, "%s", ec_platform->ec_name);
if (retval) { if (retval) {
...@@ -422,6 +418,18 @@ static int ec_device_probe(struct platform_device *pdev) ...@@ -422,6 +418,18 @@ static int ec_device_probe(struct platform_device *pdev)
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE)) if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
cros_ec_sensors_register(ec); 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. */ /* Take control of the lightbar from the EC. */
lb_manual_suspend_ctrl(ec, 1); lb_manual_suspend_ctrl(ec, 1);
...@@ -456,9 +464,17 @@ static int ec_device_remove(struct platform_device *pdev) ...@@ -456,9 +464,17 @@ static int ec_device_remove(struct platform_device *pdev)
return 0; 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[] = { static const struct platform_device_id cros_ec_id[] = {
{ DRV_NAME, 0 }, { DRV_NAME, 0 },
{ /* sentinel */ }, { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(platform, cros_ec_id); MODULE_DEVICE_TABLE(platform, cros_ec_id);
...@@ -466,6 +482,8 @@ static __maybe_unused int ec_device_suspend(struct device *dev) ...@@ -466,6 +482,8 @@ static __maybe_unused int ec_device_suspend(struct device *dev)
{ {
struct cros_ec_dev *ec = dev_get_drvdata(dev); struct cros_ec_dev *ec = dev_get_drvdata(dev);
cros_ec_debugfs_suspend(ec);
lb_suspend(ec); lb_suspend(ec);
return 0; return 0;
...@@ -475,6 +493,8 @@ static __maybe_unused int ec_device_resume(struct device *dev) ...@@ -475,6 +493,8 @@ static __maybe_unused int ec_device_resume(struct device *dev)
{ {
struct cros_ec_dev *ec = dev_get_drvdata(dev); struct cros_ec_dev *ec = dev_get_drvdata(dev);
cros_ec_debugfs_resume(ec);
lb_resume(ec); lb_resume(ec);
return 0; return 0;
...@@ -494,6 +514,7 @@ static struct platform_driver cros_ec_dev_driver = { ...@@ -494,6 +514,7 @@ static struct platform_driver cros_ec_dev_driver = {
}, },
.probe = ec_device_probe, .probe = ec_device_probe,
.remove = ec_device_remove, .remove = ec_device_remove,
.shutdown = ec_device_shutdown,
}; };
static int __init cros_ec_dev_init(void) static int __init cros_ec_dev_init(void)
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include <linux/acpi.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -341,14 +342,17 @@ static int cros_ec_i2c_resume(struct device *dev) ...@@ -341,14 +342,17 @@ static int cros_ec_i2c_resume(struct device *dev)
} }
#endif #endif
static SIMPLE_DEV_PM_OPS(cros_ec_i2c_pm_ops, cros_ec_i2c_suspend, static const struct dev_pm_ops cros_ec_i2c_pm_ops = {
cros_ec_i2c_resume); 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[] = { static const struct of_device_id cros_ec_i2c_of_match[] = {
{ .compatible = "google,cros-ec-i2c", }, { .compatible = "google,cros-ec-i2c", },
{ /* sentinel */ }, { /* sentinel */ },
}; };
MODULE_DEVICE_TABLE(of, cros_ec_i2c_of_match); MODULE_DEVICE_TABLE(of, cros_ec_i2c_of_match);
#endif
static const struct i2c_device_id cros_ec_i2c_id[] = { static const struct i2c_device_id cros_ec_i2c_id[] = {
{ "cros-ec-i2c", 0 }, { "cros-ec-i2c", 0 },
...@@ -356,9 +360,18 @@ static const struct i2c_device_id cros_ec_i2c_id[] = { ...@@ -356,9 +360,18 @@ static const struct i2c_device_id cros_ec_i2c_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, 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 = { static struct i2c_driver cros_ec_driver = {
.driver = { .driver = {
.name = "cros-ec-i2c", .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), .of_match_table = of_match_ptr(cros_ec_i2c_of_match),
.pm = &cros_ec_i2c_pm_ops, .pm = &cros_ec_i2c_pm_ops,
}, },
......
This diff is collapsed.
...@@ -479,10 +479,8 @@ static int htcpld_setup_chips(struct platform_device *pdev) ...@@ -479,10 +479,8 @@ static int htcpld_setup_chips(struct platform_device *pdev)
htcpld->nchips = pdata->num_chip; htcpld->nchips = pdata->num_chip;
htcpld->chip = devm_kzalloc(dev, sizeof(struct htcpld_chip) * htcpld->nchips, htcpld->chip = devm_kzalloc(dev, sizeof(struct htcpld_chip) * htcpld->nchips,
GFP_KERNEL); GFP_KERNEL);
if (!htcpld->chip) { if (!htcpld->chip)
dev_warn(dev, "Unable to allocate memory for chips\n");
return -ENOMEM; return -ENOMEM;
}
/* Add the chips as best we can */ /* Add the chips as best we can */
for (i = 0; i < htcpld->nchips; i++) { for (i = 0; i < htcpld->nchips; i++) {
......
...@@ -124,6 +124,11 @@ static const struct intel_lpss_platform_info apl_i2c_info = { ...@@ -124,6 +124,11 @@ static const struct intel_lpss_platform_info apl_i2c_info = {
.properties = apl_i2c_properties, .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[] = { static const struct pci_device_id intel_lpss_pci_ids[] = {
/* BXT A-Step */ /* BXT A-Step */
{ PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info },
...@@ -207,13 +212,13 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { ...@@ -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, 0x9daa), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0x9dab), (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, 0x9dfb), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0x9dc5), (kernel_ulong_t)&spt_i2c_info }, { PCI_VDEVICE(INTEL, 0x9dc5), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9dc6), (kernel_ulong_t)&spt_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, 0x9dc7), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x9de8), (kernel_ulong_t)&spt_i2c_info }, { PCI_VDEVICE(INTEL, 0x9de8), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9de9), (kernel_ulong_t)&spt_i2c_info }, { PCI_VDEVICE(INTEL, 0x9de9), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9dea), (kernel_ulong_t)&spt_i2c_info }, { PCI_VDEVICE(INTEL, 0x9dea), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9deb), (kernel_ulong_t)&spt_i2c_info }, { PCI_VDEVICE(INTEL, 0x9deb), (kernel_ulong_t)&cnl_i2c_info },
/* SPT-H */ /* SPT-H */
{ PCI_VDEVICE(INTEL, 0xa127), (kernel_ulong_t)&spt_uart_info }, { PCI_VDEVICE(INTEL, 0xa127), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa128), (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[] = { ...@@ -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, 0xa32b), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0xa37b), (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, 0xa347), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa368), (kernel_ulong_t)&spt_i2c_info }, { PCI_VDEVICE(INTEL, 0xa368), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa369), (kernel_ulong_t)&spt_i2c_info }, { PCI_VDEVICE(INTEL, 0xa369), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa36a), (kernel_ulong_t)&spt_i2c_info }, { PCI_VDEVICE(INTEL, 0xa36a), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa36b), (kernel_ulong_t)&spt_i2c_info }, { PCI_VDEVICE(INTEL, 0xa36b), (kernel_ulong_t)&cnl_i2c_info },
{ } { }
}; };
MODULE_DEVICE_TABLE(pci, intel_lpss_pci_ids); MODULE_DEVICE_TABLE(pci, intel_lpss_pci_ids);
......
...@@ -40,8 +40,8 @@ ...@@ -40,8 +40,8 @@
/* Offsets from lpss->priv */ /* Offsets from lpss->priv */
#define LPSS_PRIV_RESETS 0x04 #define LPSS_PRIV_RESETS 0x04
#define LPSS_PRIV_RESETS_FUNC BIT(2) #define LPSS_PRIV_RESETS_IDMA BIT(2)
#define LPSS_PRIV_RESETS_IDMA 0x3 #define LPSS_PRIV_RESETS_FUNC 0x3
#define LPSS_PRIV_ACTIVELTR 0x10 #define LPSS_PRIV_ACTIVELTR 0x10
#define LPSS_PRIV_IDLELTR 0x14 #define LPSS_PRIV_IDLELTR 0x14
...@@ -275,11 +275,11 @@ static void intel_lpss_init_dev(const struct intel_lpss *lpss) ...@@ -275,11 +275,11 @@ static void intel_lpss_init_dev(const struct intel_lpss *lpss)
intel_lpss_deassert_reset(lpss); intel_lpss_deassert_reset(lpss);
intel_lpss_set_remap_addr(lpss);
if (!intel_lpss_has_idma(lpss)) if (!intel_lpss_has_idma(lpss))
return; return;
intel_lpss_set_remap_addr(lpss);
/* Make sure that SPI multiblock DMA transfers are re-enabled */ /* Make sure that SPI multiblock DMA transfers are re-enabled */
if (lpss->type == LPSS_DEV_SPI) if (lpss->type == LPSS_DEV_SPI)
writel(value, lpss->priv + LPSS_PRIV_SSP_REG); writel(value, lpss->priv + LPSS_PRIV_SSP_REG);
......
...@@ -183,10 +183,8 @@ static int cmodio_pci_probe(struct pci_dev *dev, ...@@ -183,10 +183,8 @@ static int cmodio_pci_probe(struct pci_dev *dev,
int ret; int ret;
priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL); priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) { if (!priv)
dev_err(&dev->dev, "unable to allocate private data\n");
return -ENOMEM; return -ENOMEM;
}
pci_set_drvdata(dev, priv); pci_set_drvdata(dev, priv);
priv->pdev = dev; priv->pdev = dev;
......
...@@ -212,10 +212,8 @@ static int jz4740_adc_probe(struct platform_device *pdev) ...@@ -212,10 +212,8 @@ static int jz4740_adc_probe(struct platform_device *pdev)
int irq_base; int irq_base;
adc = devm_kzalloc(&pdev->dev, sizeof(*adc), GFP_KERNEL); adc = devm_kzalloc(&pdev->dev, sizeof(*adc), GFP_KERNEL);
if (!adc) { if (!adc)
dev_err(&pdev->dev, "Failed to allocate driver structure\n");
return -ENOMEM; return -ENOMEM;
}
adc->irq = platform_get_irq(pdev, 0); adc->irq = platform_get_irq(pdev, 0);
if (adc->irq < 0) { if (adc->irq < 0) {
......
...@@ -148,10 +148,8 @@ static struct max8997_platform_data *max8997_i2c_parse_dt_pdata( ...@@ -148,10 +148,8 @@ static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
struct max8997_platform_data *pd; struct max8997_platform_data *pd;
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
if (!pd) { if (!pd)
dev_err(dev, "could not allocate memory for pdata\n");
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
pd->ono = irq_of_parse_and_map(dev->of_node, 1); pd->ono = irq_of_parse_and_map(dev->of_node, 1);
......
...@@ -43,6 +43,16 @@ static const struct resource mt6397_rtc_resources[] = { ...@@ -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[] = { static const struct mfd_cell mt6323_devs[] = {
{ {
.name = "mt6323-regulator", .name = "mt6323-regulator",
...@@ -50,6 +60,11 @@ static const struct mfd_cell mt6323_devs[] = { ...@@ -50,6 +60,11 @@ static const struct mfd_cell mt6323_devs[] = {
}, { }, {
.name = "mt6323-led", .name = "mt6323-led",
.of_compatible = "mediatek,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[] = { ...@@ -71,7 +86,12 @@ static const struct mfd_cell mt6397_devs[] = {
}, { }, {
.name = "mt6397-pinctrl", .name = "mt6397-pinctrl",
.of_compatible = "mediatek,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) static void mt6397_irq_lock(struct irq_data *data)
...@@ -289,7 +309,7 @@ static int mt6397_probe(struct platform_device *pdev) ...@@ -289,7 +309,7 @@ static int mt6397_probe(struct platform_device *pdev)
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs, ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs,
ARRAY_SIZE(mt6323_devs), NULL, ARRAY_SIZE(mt6323_devs), NULL,
0, NULL); 0, pmic->irq_domain);
break; break;
case MT6397_CID_CODE: case MT6397_CID_CODE:
...@@ -304,7 +324,7 @@ static int mt6397_probe(struct platform_device *pdev) ...@@ -304,7 +324,7 @@ static int mt6397_probe(struct platform_device *pdev)
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs, ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs,
ARRAY_SIZE(mt6397_devs), NULL, ARRAY_SIZE(mt6397_devs), NULL,
0, NULL); 0, pmic->irq_domain);
break; break;
default: default:
......
...@@ -153,27 +153,6 @@ static const char * const port_modes[] = { ...@@ -153,27 +153,6 @@ static const char * const port_modes[] = {
[OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM] = "ohci-tll-2pin-dpdm", [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, static struct platform_device *omap_usbhs_alloc_child(const char *name,
struct resource *res, int num_resources, void *pdata, struct resource *res, int num_resources, void *pdata,
size_t pdata_size, struct device *dev) size_t pdata_size, struct device *dev)
...@@ -529,7 +508,8 @@ static int usbhs_omap_get_dt_pdata(struct device *dev, ...@@ -529,7 +508,8 @@ static int usbhs_omap_get_dt_pdata(struct device *dev,
if (ret < 0) if (ret < 0)
continue; 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) { if (ret < 0) {
dev_warn(dev, "Invalid port%d-mode \"%s\" in device tree\n", dev_warn(dev, "Invalid port%d-mode \"%s\" in device tree\n",
i, mode); i, mode);
......
...@@ -108,9 +108,9 @@ ...@@ -108,9 +108,9 @@
(x) != OMAP_EHCI_PORT_MODE_PHY) (x) != OMAP_EHCI_PORT_MODE_PHY)
struct usbtll_omap { 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) ...@@ -216,53 +216,49 @@ static int usbtll_omap_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct resource *res; struct resource *res;
struct usbtll_omap *tll; struct usbtll_omap *tll;
int ret = 0; void __iomem *base;
int i, ver; int i, nch, ver;
dev_dbg(dev, "starting TI HSUSB TLL Controller\n"); 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); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
tll->base = devm_ioremap_resource(dev, res); base = devm_ioremap_resource(dev, res);
if (IS_ERR(tll->base)) if (IS_ERR(base))
return PTR_ERR(tll->base); return PTR_ERR(base);
platform_set_drvdata(pdev, tll);
pm_runtime_enable(dev); pm_runtime_enable(dev);
pm_runtime_get_sync(dev); pm_runtime_get_sync(dev);
ver = usbtll_read(tll->base, OMAP_USBTLL_REVISION); ver = usbtll_read(base, OMAP_USBTLL_REVISION);
switch (ver) { switch (ver) {
case OMAP_USBTLL_REV1: case OMAP_USBTLL_REV1:
case OMAP_USBTLL_REV4: case OMAP_USBTLL_REV4:
tll->nch = OMAP_TLL_CHANNEL_COUNT; nch = OMAP_TLL_CHANNEL_COUNT;
break; break;
case OMAP_USBTLL_REV2: case OMAP_USBTLL_REV2:
case OMAP_USBTLL_REV3: case OMAP_USBTLL_REV3:
tll->nch = OMAP_REV2_TLL_CHANNEL_COUNT; nch = OMAP_REV2_TLL_CHANNEL_COUNT;
break; break;
default: default:
tll->nch = OMAP_TLL_CHANNEL_COUNT; nch = OMAP_TLL_CHANNEL_COUNT;
dev_dbg(dev, dev_dbg(dev, "rev 0x%x not recognized, assuming %d channels\n",
"USB TLL Rev : 0x%x not recognized, assuming %d channels\n", ver, nch);
ver, tll->nch);
break; break;
} }
tll->ch_clk = devm_kzalloc(dev, sizeof(struct clk *) * tll->nch, tll = devm_kzalloc(dev, sizeof(*tll) + sizeof(tll->ch_clk[nch]),
GFP_KERNEL); GFP_KERNEL);
if (!tll->ch_clk) { if (!tll) {
ret = -ENOMEM; pm_runtime_put_sync(dev);
dev_err(dev, "Couldn't allocate memory for channel clocks\n"); pm_runtime_disable(dev);
goto err_clk_alloc; 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"; char clkname[] = "usb_tll_hs_usb_chx_clk";
snprintf(clkname, sizeof(clkname), snprintf(clkname, sizeof(clkname),
...@@ -282,12 +278,6 @@ static int usbtll_omap_probe(struct platform_device *pdev) ...@@ -282,12 +278,6 @@ static int usbtll_omap_probe(struct platform_device *pdev)
spin_unlock(&tll_lock); spin_unlock(&tll_lock);
return 0; return 0;
err_clk_alloc:
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
return ret;
} }
/** /**
......
...@@ -242,8 +242,10 @@ static int pcf50633_probe(struct i2c_client *client, ...@@ -242,8 +242,10 @@ static int pcf50633_probe(struct i2c_client *client,
for (i = 0; i < PCF50633_NUM_REGULATORS; i++) { for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
pdev = platform_device_alloc("pcf50633-regulator", i); pdev = platform_device_alloc("pcf50633-regulator", i);
if (!pdev) if (!pdev) {
return -ENOMEM; ret = -ENOMEM;
goto err2;
}
pdev->dev.parent = pcf->dev; pdev->dev.parent = pcf->dev;
ret = platform_device_add_data(pdev, &pdata->reg_init_data[i], ret = platform_device_add_data(pdev, &pdata->reg_init_data[i],
...@@ -269,6 +271,7 @@ static int pcf50633_probe(struct i2c_client *client, ...@@ -269,6 +271,7 @@ static int pcf50633_probe(struct i2c_client *client,
err: err:
platform_device_put(pdev); platform_device_put(pdev);
err2:
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
platform_device_put(pcf->regulator_pdev[j]); platform_device_put(pcf->regulator_pdev[j]);
......
...@@ -39,6 +39,9 @@ ...@@ -39,6 +39,9 @@
#define PM8916_SUBTYPE 0x0b #define PM8916_SUBTYPE 0x0b
#define PM8004_SUBTYPE 0x0c #define PM8004_SUBTYPE 0x0c
#define PM8909_SUBTYPE 0x0d #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[] = { static const struct of_device_id pmic_spmi_id_table[] = {
{ .compatible = "qcom,spmi-pmic", .data = (void *)COMMON_SUBTYPE }, { .compatible = "qcom,spmi-pmic", .data = (void *)COMMON_SUBTYPE },
...@@ -55,6 +58,9 @@ static const struct of_device_id pmic_spmi_id_table[] = { ...@@ -55,6 +58,9 @@ static const struct of_device_id pmic_spmi_id_table[] = {
{ .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE }, { .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE },
{ .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE }, { .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE },
{ .compatible = "qcom,pm8909", .data = (void *)PM8909_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 },
{ } { }
}; };
......
...@@ -45,7 +45,9 @@ ...@@ -45,7 +45,9 @@
#define RAVE_SP_DLE 0x10 #define RAVE_SP_DLE 0x10
#define RAVE_SP_MAX_DATA_SIZE 64 #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 * We don't store STX, ETX and unescaped bytes, so Rx is only
* DATA + CSUM * DATA + CSUM
...@@ -160,6 +162,8 @@ struct rave_sp_variant { ...@@ -160,6 +162,8 @@ struct rave_sp_variant {
* @variant: Device variant specific information * @variant: Device variant specific information
* @event_notifier_list: Input event notification chain * @event_notifier_list: Input event notification chain
* *
* @part_number_firmware: Firmware version
* @part_number_bootloader: Bootloader version
*/ */
struct rave_sp { struct rave_sp {
struct serdev_device *serdev; struct serdev_device *serdev;
...@@ -171,8 +175,40 @@ struct rave_sp { ...@@ -171,8 +175,40 @@ struct rave_sp {
const struct rave_sp_variant *variant; const struct rave_sp_variant *variant;
struct blocking_notifier_head event_notifier_list; 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) static bool rave_sp_id_is_event(u8 code)
{ {
return (code & 0xF0) == RAVE_SP_EVNT_BASE; return (code & 0xF0) == RAVE_SP_EVNT_BASE;
...@@ -275,7 +311,7 @@ static int rave_sp_write(struct rave_sp *sp, const u8 *data, u8 data_size) ...@@ -275,7 +311,7 @@ static int rave_sp_write(struct rave_sp *sp, const u8 *data, u8 data_size)
length = dest - frame; length = dest - frame;
print_hex_dump(KERN_DEBUG, "rave-sp tx: ", DUMP_PREFIX_NONE, print_hex_dump_debug("rave-sp tx: ", DUMP_PREFIX_NONE,
16, 1, frame, length, false); 16, 1, frame, length, false);
return serdev_device_write(sp->serdev, frame, length, HZ); return serdev_device_write(sp->serdev, frame, length, HZ);
...@@ -415,9 +451,14 @@ static void rave_sp_receive_frame(struct rave_sp *sp, ...@@ -415,9 +451,14 @@ static void rave_sp_receive_frame(struct rave_sp *sp,
const size_t payload_length = length - checksum_length; const size_t payload_length = length - checksum_length;
const u8 *crc_reported = &data[payload_length]; const u8 *crc_reported = &data[payload_length];
struct device *dev = &sp->serdev->dev; 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, print_hex_dump_debug("rave-sp rx: ", DUMP_PREFIX_NONE,
16, 1, data, length, false); 16, 1, data, length, false);
if (unlikely(length <= checksum_length)) { if (unlikely(length <= checksum_length)) {
...@@ -512,8 +553,6 @@ static int rave_sp_receive_buf(struct serdev_device *serdev, ...@@ -512,8 +553,6 @@ static int rave_sp_receive_buf(struct serdev_device *serdev,
/* FALLTHROUGH */ /* FALLTHROUGH */
case RAVE_SP_EXPECT_ESCAPED_DATA: case RAVE_SP_EXPECT_ESCAPED_DATA:
deframer->data[deframer->length++] = byte;
if (deframer->length == sizeof(deframer->data)) { if (deframer->length == sizeof(deframer->data)) {
dev_warn(dev, "Bad frame: Too long\n"); dev_warn(dev, "Bad frame: Too long\n");
/* /*
...@@ -528,6 +567,8 @@ static int rave_sp_receive_buf(struct serdev_device *serdev, ...@@ -528,6 +567,8 @@ static int rave_sp_receive_buf(struct serdev_device *serdev,
goto reset_framer; goto reset_framer;
} }
deframer->data[deframer->length++] = byte;
/* /*
* We've extracted out special byte, now we * We've extracted out special byte, now we
* can go back to regular data collecting * can go back to regular data collecting
...@@ -609,6 +650,52 @@ static int rave_sp_default_cmd_translate(enum rave_sp_command command) ...@@ -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 = { static const struct rave_sp_checksum rave_sp_checksum_8b2c = {
.length = 1, .length = 1,
.subroutine = csum_8b2c, .subroutine = csum_8b2c,
...@@ -657,6 +744,7 @@ static const struct serdev_device_ops rave_sp_serdev_device_ops = { ...@@ -657,6 +744,7 @@ static const struct serdev_device_ops rave_sp_serdev_device_ops = {
static int rave_sp_probe(struct serdev_device *serdev) static int rave_sp_probe(struct serdev_device *serdev)
{ {
struct device *dev = &serdev->dev; struct device *dev = &serdev->dev;
const char *unknown = "unknown\n";
struct rave_sp *sp; struct rave_sp *sp;
u32 baud; u32 baud;
int ret; int ret;
...@@ -689,6 +777,20 @@ static int rave_sp_probe(struct serdev_device *serdev) ...@@ -689,6 +777,20 @@ static int rave_sp_probe(struct serdev_device *serdev)
serdev_device_set_baudrate(serdev, baud); 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); return devm_of_platform_populate(dev);
} }
......
...@@ -258,11 +258,9 @@ static int rc5t583_i2c_probe(struct i2c_client *i2c, ...@@ -258,11 +258,9 @@ static int rc5t583_i2c_probe(struct i2c_client *i2c,
return -EINVAL; return -EINVAL;
} }
rc5t583 = devm_kzalloc(&i2c->dev, sizeof(struct rc5t583), GFP_KERNEL); rc5t583 = devm_kzalloc(&i2c->dev, sizeof(*rc5t583), GFP_KERNEL);
if (!rc5t583) { if (!rc5t583)
dev_err(&i2c->dev, "Memory allocation failed\n");
return -ENOMEM; return -ENOMEM;
}
rc5t583->dev = &i2c->dev; rc5t583->dev = &i2c->dev;
i2c_set_clientdata(i2c, rc5t583); i2c_set_clientdata(i2c, rc5t583);
......
...@@ -697,11 +697,9 @@ static int si476x_core_probe(struct i2c_client *client, ...@@ -697,11 +697,9 @@ static int si476x_core_probe(struct i2c_client *client,
int cell_num; int cell_num;
core = devm_kzalloc(&client->dev, sizeof(*core), GFP_KERNEL); core = devm_kzalloc(&client->dev, sizeof(*core), GFP_KERNEL);
if (!core) { if (!core)
dev_err(&client->dev,
"failed to allocate 'struct si476x_core'\n");
return -ENOMEM; return -ENOMEM;
}
core->client = client; core->client = client;
core->regmap = devm_regmap_init_si476x(core); core->regmap = devm_regmap_init_si476x(core);
......
...@@ -1050,13 +1050,13 @@ static int sm501_register_gpio(struct sm501_devdata *sm) ...@@ -1050,13 +1050,13 @@ static int sm501_register_gpio(struct sm501_devdata *sm)
spin_lock_init(&gpio->lock); spin_lock_init(&gpio->lock);
gpio->regs_res = request_mem_region(iobase, 0x20, "sm501-gpio"); 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"); dev_err(sm->dev, "gpio: failed to request region\n");
return -ENXIO; return -ENXIO;
} }
gpio->regs = ioremap(iobase, 0x20); gpio->regs = ioremap(iobase, 0x20);
if (gpio->regs == NULL) { if (!gpio->regs) {
dev_err(sm->dev, "gpio: failed to remap registers\n"); dev_err(sm->dev, "gpio: failed to remap registers\n");
ret = -ENXIO; ret = -ENXIO;
goto err_claimed; goto err_claimed;
...@@ -1358,7 +1358,7 @@ static int sm501_init_dev(struct sm501_devdata *sm) ...@@ -1358,7 +1358,7 @@ static int sm501_init_dev(struct sm501_devdata *sm)
sm501_register_gpio(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)) if (!sm501_gpio_isregistered(sm))
dev_err(sm->dev, "no gpio available for i2c gpio.\n"); dev_err(sm->dev, "no gpio available for i2c gpio.\n");
else else
...@@ -1383,9 +1383,8 @@ static int sm501_plat_probe(struct platform_device *dev) ...@@ -1383,9 +1383,8 @@ static int sm501_plat_probe(struct platform_device *dev)
struct sm501_devdata *sm; struct sm501_devdata *sm;
int ret; int ret;
sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL); sm = kzalloc(sizeof(*sm), GFP_KERNEL);
if (sm == NULL) { if (!sm) {
dev_err(&dev->dev, "no memory for device data\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err1; goto err1;
} }
...@@ -1403,8 +1402,7 @@ static int sm501_plat_probe(struct platform_device *dev) ...@@ -1403,8 +1402,7 @@ static int sm501_plat_probe(struct platform_device *dev)
sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1); sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0); sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!sm->io_res || !sm->mem_res) {
if (sm->io_res == NULL || sm->mem_res == NULL) {
dev_err(&dev->dev, "failed to get IO resource\n"); dev_err(&dev->dev, "failed to get IO resource\n");
ret = -ENOENT; ret = -ENOENT;
goto err_res; goto err_res;
...@@ -1412,8 +1410,7 @@ static int sm501_plat_probe(struct platform_device *dev) ...@@ -1412,8 +1410,7 @@ static int sm501_plat_probe(struct platform_device *dev)
sm->regs_claim = request_mem_region(sm->io_res->start, sm->regs_claim = request_mem_region(sm->io_res->start,
0x100, "sm501"); 0x100, "sm501");
if (!sm->regs_claim) {
if (sm->regs_claim == NULL) {
dev_err(&dev->dev, "cannot claim registers\n"); dev_err(&dev->dev, "cannot claim registers\n");
ret = -EBUSY; ret = -EBUSY;
goto err_res; goto err_res;
...@@ -1422,8 +1419,7 @@ static int sm501_plat_probe(struct platform_device *dev) ...@@ -1422,8 +1419,7 @@ static int sm501_plat_probe(struct platform_device *dev)
platform_set_drvdata(dev, sm); platform_set_drvdata(dev, sm);
sm->regs = ioremap(sm->io_res->start, resource_size(sm->io_res)); sm->regs = ioremap(sm->io_res->start, resource_size(sm->io_res));
if (!sm->regs) {
if (sm->regs == NULL) {
dev_err(&dev->dev, "cannot remap registers\n"); dev_err(&dev->dev, "cannot remap registers\n");
ret = -EIO; ret = -EIO;
goto err_claim; goto err_claim;
...@@ -1449,7 +1445,7 @@ static void sm501_set_power(struct sm501_devdata *sm, int on) ...@@ -1449,7 +1445,7 @@ static void sm501_set_power(struct sm501_devdata *sm, int on)
{ {
struct sm501_platdata *pd = sm->platdata; struct sm501_platdata *pd = sm->platdata;
if (pd == NULL) if (!pd)
return; return;
if (pd->get_power) { if (pd->get_power) {
...@@ -1573,9 +1569,8 @@ static int sm501_pci_probe(struct pci_dev *dev, ...@@ -1573,9 +1569,8 @@ static int sm501_pci_probe(struct pci_dev *dev,
struct sm501_devdata *sm; struct sm501_devdata *sm;
int err; int err;
sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL); sm = kzalloc(sizeof(*sm), GFP_KERNEL);
if (sm == NULL) { if (!sm) {
dev_err(&dev->dev, "no memory for device data\n");
err = -ENOMEM; err = -ENOMEM;
goto err1; goto err1;
} }
...@@ -1626,15 +1621,14 @@ static int sm501_pci_probe(struct pci_dev *dev, ...@@ -1626,15 +1621,14 @@ static int sm501_pci_probe(struct pci_dev *dev,
sm->regs_claim = request_mem_region(sm->io_res->start, sm->regs_claim = request_mem_region(sm->io_res->start,
0x100, "sm501"); 0x100, "sm501");
if (sm->regs_claim == NULL) { if (!sm->regs_claim) {
dev_err(&dev->dev, "cannot claim registers\n"); dev_err(&dev->dev, "cannot claim registers\n");
err= -EBUSY; err= -EBUSY;
goto err3; goto err3;
} }
sm->regs = pci_ioremap_bar(dev, 1); sm->regs = pci_ioremap_bar(dev, 1);
if (!sm->regs) {
if (sm->regs == NULL) {
dev_err(&dev->dev, "cannot remap registers\n"); dev_err(&dev->dev, "cannot remap registers\n");
err = -EIO; err = -EIO;
goto err4; goto err4;
......
...@@ -37,12 +37,9 @@ static int smsc_i2c_probe(struct i2c_client *i2c, ...@@ -37,12 +37,9 @@ static int smsc_i2c_probe(struct i2c_client *i2c,
int devid, rev, venid_l, venid_h; int devid, rev, venid_l, venid_h;
int ret; int ret;
smsc = devm_kzalloc(&i2c->dev, sizeof(struct smsc), smsc = devm_kzalloc(&i2c->dev, sizeof(*smsc), GFP_KERNEL);
GFP_KERNEL); if (!smsc)
if (!smsc) {
dev_err(&i2c->dev, "smsc mfd driver memory allocation failed\n");
return -ENOMEM; return -ENOMEM;
}
smsc->regmap = devm_regmap_init_i2c(i2c, &smsc_regmap_config); smsc->regmap = devm_regmap_init_i2c(i2c, &smsc_regmap_config);
if (IS_ERR(smsc->regmap)) if (IS_ERR(smsc->regmap))
......
...@@ -111,6 +111,9 @@ static const struct mfd_cell sprd_pmic_devs[] = { ...@@ -111,6 +111,9 @@ static const struct mfd_cell sprd_pmic_devs[] = {
}, { }, {
.name = "sc27xx-poweroff", .name = "sc27xx-poweroff",
.of_compatible = "sprd,sc27xx-poweroff", .of_compatible = "sprd,sc27xx-poweroff",
}, {
.name = "sc27xx-syscon",
.of_compatible = "sprd,sc27xx-syscon",
}, },
}; };
......
...@@ -4,16 +4,156 @@ ...@@ -4,16 +4,156 @@
* Author: Benjamin Gaignard <benjamin.gaignard@st.com> * Author: Benjamin Gaignard <benjamin.gaignard@st.com>
*/ */
#include <linux/bitfield.h>
#include <linux/mfd/stm32-timers.h> #include <linux/mfd/stm32-timers.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/reset.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 = { static const struct regmap_config stm32_timers_regmap_cfg = {
.reg_bits = 32, .reg_bits = 32,
.val_bits = 32, .val_bits = 32,
.reg_stride = sizeof(u32), .reg_stride = sizeof(u32),
.max_register = 0x3fc, .max_register = STM32_TIMERS_MAX_REGISTERS,
}; };
static void stm32_timers_get_arr_size(struct stm32_timers *ddata) 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) ...@@ -27,12 +167,45 @@ static void stm32_timers_get_arr_size(struct stm32_timers *ddata)
regmap_write(ddata->regmap, TIM_ARR, 0x0); 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) static int stm32_timers_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct stm32_timers *ddata; struct stm32_timers *ddata;
struct resource *res; struct resource *res;
void __iomem *mmio; void __iomem *mmio;
int ret;
ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
if (!ddata) if (!ddata)
...@@ -43,6 +216,9 @@ static int stm32_timers_probe(struct platform_device *pdev) ...@@ -43,6 +216,9 @@ static int stm32_timers_probe(struct platform_device *pdev)
if (IS_ERR(mmio)) if (IS_ERR(mmio))
return PTR_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, ddata->regmap = devm_regmap_init_mmio_clk(dev, "int", mmio,
&stm32_timers_regmap_cfg); &stm32_timers_regmap_cfg);
if (IS_ERR(ddata->regmap)) if (IS_ERR(ddata->regmap))
...@@ -54,9 +230,29 @@ static int stm32_timers_probe(struct platform_device *pdev) ...@@ -54,9 +230,29 @@ static int stm32_timers_probe(struct platform_device *pdev)
stm32_timers_get_arr_size(ddata); stm32_timers_get_arr_size(ddata);
stm32_timers_dma_probe(dev, ddata);
platform_set_drvdata(pdev, 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[] = { static const struct of_device_id stm32_timers_of_match[] = {
...@@ -67,6 +263,7 @@ MODULE_DEVICE_TABLE(of, stm32_timers_of_match); ...@@ -67,6 +263,7 @@ MODULE_DEVICE_TABLE(of, stm32_timers_of_match);
static struct platform_driver stm32_timers_driver = { static struct platform_driver stm32_timers_driver = {
.probe = stm32_timers_probe, .probe = stm32_timers_probe,
.remove = stm32_timers_remove,
.driver = { .driver = {
.name = "stm32-timers", .name = "stm32-timers",
.of_match_table = stm32_timers_of_match, .of_match_table = stm32_timers_of_match,
......
...@@ -106,9 +106,11 @@ static struct syscon *of_syscon_register(struct device_node *np) ...@@ -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.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8; syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size(&res) - reg_io_width; 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); regmap = regmap_init_mmio(NULL, base, &syscon_config);
if (IS_ERR(regmap)) { if (IS_ERR(regmap)) {
......
...@@ -169,10 +169,9 @@ static int ti_tscadc_probe(struct platform_device *pdev) ...@@ -169,10 +169,9 @@ static int ti_tscadc_probe(struct platform_device *pdev)
/* Allocate memory for device */ /* Allocate memory for device */
tscadc = devm_kzalloc(&pdev->dev, sizeof(*tscadc), GFP_KERNEL); tscadc = devm_kzalloc(&pdev->dev, sizeof(*tscadc), GFP_KERNEL);
if (!tscadc) { if (!tscadc)
dev_err(&pdev->dev, "failed to allocate memory.\n");
return -ENOMEM; return -ENOMEM;
}
tscadc->dev = &pdev->dev; tscadc->dev = &pdev->dev;
err = platform_get_irq(pdev, 0); err = platform_get_irq(pdev, 0);
......
...@@ -777,7 +777,7 @@ static int timb_probe(struct pci_dev *dev, ...@@ -777,7 +777,7 @@ static int timb_probe(struct pci_dev *dev,
&dev->resource[0], msix_entries[0].vector, NULL); &dev->resource[0], msix_entries[0].vector, NULL);
break; break;
default: 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); priv->fw.major, priv->fw.minor, ip_setup);
err = -ENODEV; err = -ENODEV;
goto err_mfd; goto err_mfd;
......
...@@ -192,10 +192,8 @@ static int tps65090_i2c_probe(struct i2c_client *client, ...@@ -192,10 +192,8 @@ static int tps65090_i2c_probe(struct i2c_client *client,
irq_base = pdata->irq_base; irq_base = pdata->irq_base;
tps65090 = devm_kzalloc(&client->dev, sizeof(*tps65090), GFP_KERNEL); tps65090 = devm_kzalloc(&client->dev, sizeof(*tps65090), GFP_KERNEL);
if (!tps65090) { if (!tps65090)
dev_err(&client->dev, "mem alloc for tps65090 failed\n");
return -ENOMEM; return -ENOMEM;
}
tps65090->dev = &client->dev; tps65090->dev = &client->dev;
i2c_set_clientdata(client, tps65090); i2c_set_clientdata(client, tps65090);
......
...@@ -423,10 +423,8 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien ...@@ -423,10 +423,8 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien
struct tps6586x_platform_data *pdata; struct tps6586x_platform_data *pdata;
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) { if (!pdata)
dev_err(&client->dev, "Memory allocation failed\n");
return NULL; return NULL;
}
pdata->num_subdevs = 0; pdata->num_subdevs = 0;
pdata->subdevs = NULL; pdata->subdevs = NULL;
......
...@@ -229,7 +229,7 @@ static struct regmap_irq_chip tps65910_irq_chip = { ...@@ -229,7 +229,7 @@ static struct regmap_irq_chip tps65910_irq_chip = {
static int tps65910_irq_init(struct tps65910 *tps65910, int irq, static int tps65910_irq_init(struct tps65910 *tps65910, int irq,
struct tps65910_platform_data *pdata) struct tps65910_platform_data *pdata)
{ {
int ret = 0; int ret;
static struct regmap_irq_chip *tps6591x_irqs_chip; static struct regmap_irq_chip *tps6591x_irqs_chip;
if (!irq) { if (!irq) {
...@@ -312,14 +312,14 @@ static int tps65910_ck32k_init(struct tps65910 *tps65910, ...@@ -312,14 +312,14 @@ static int tps65910_ck32k_init(struct tps65910 *tps65910,
static int tps65910_sleepinit(struct tps65910 *tps65910, static int tps65910_sleepinit(struct tps65910 *tps65910,
struct tps65910_board *pmic_pdata) struct tps65910_board *pmic_pdata)
{ {
struct device *dev = NULL; struct device *dev;
int ret = 0; int ret;
dev = tps65910->dev;
if (!pmic_pdata->en_dev_slp) if (!pmic_pdata->en_dev_slp)
return 0; return 0;
dev = tps65910->dev;
/* enabling SLEEP device state */ /* enabling SLEEP device state */
ret = tps65910_reg_set_bits(tps65910, TPS65910_DEVCTRL, ret = tps65910_reg_set_bits(tps65910, TPS65910_DEVCTRL,
DEVCTRL_DEV_SLP_MASK); DEVCTRL_DEV_SLP_MASK);
...@@ -383,7 +383,7 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client, ...@@ -383,7 +383,7 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
struct tps65910_board *board_info; struct tps65910_board *board_info;
unsigned int prop; unsigned int prop;
const struct of_device_id *match; const struct of_device_id *match;
int ret = 0; int ret;
match = of_match_device(tps65910_of_match, &client->dev); match = of_match_device(tps65910_of_match, &client->dev);
if (!match) { if (!match) {
...@@ -395,10 +395,8 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client, ...@@ -395,10 +395,8 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
board_info = devm_kzalloc(&client->dev, sizeof(*board_info), board_info = devm_kzalloc(&client->dev, sizeof(*board_info),
GFP_KERNEL); GFP_KERNEL);
if (!board_info) { if (!board_info)
dev_err(&client->dev, "Failed to allocate pdata\n");
return NULL; return NULL;
}
ret = of_property_read_u32(np, "ti,vmbch-threshold", &prop); ret = of_property_read_u32(np, "ti,vmbch-threshold", &prop);
if (!ret) if (!ret)
...@@ -462,7 +460,7 @@ static int tps65910_i2c_probe(struct i2c_client *i2c, ...@@ -462,7 +460,7 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
struct tps65910_board *of_pmic_plat_data = NULL; struct tps65910_board *of_pmic_plat_data = NULL;
struct tps65910_platform_data *init_data; struct tps65910_platform_data *init_data;
unsigned long chip_id = id->driver_data; unsigned long chip_id = id->driver_data;
int ret = 0; int ret;
pmic_plat_data = dev_get_platdata(&i2c->dev); pmic_plat_data = dev_get_platdata(&i2c->dev);
......
...@@ -22,9 +22,8 @@ ...@@ -22,9 +22,8 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/mfd/tps65910.h> #include <linux/mfd/tps65910.h>
#define COMP 0 #define COMP1 0
#define COMP1 1 #define COMP2 1
#define COMP2 2
/* Comparator 1 voltage selection table in millivolts */ /* Comparator 1 voltage selection table in millivolts */
static const u16 COMP_VSEL_TABLE[] = { static const u16 COMP_VSEL_TABLE[] = {
...@@ -63,9 +62,6 @@ static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage) ...@@ -63,9 +62,6 @@ static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage)
int ret; int ret;
u8 index = 0, val; u8 index = 0, val;
if (id == COMP)
return 0;
while (curr_voltage < tps_comp.uV_max) { while (curr_voltage < tps_comp.uV_max) {
curr_voltage = tps_comp.vsel_table[index]; curr_voltage = tps_comp.vsel_table[index];
if (curr_voltage >= voltage) if (curr_voltage >= voltage)
...@@ -78,7 +74,7 @@ static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage) ...@@ -78,7 +74,7 @@ static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage)
return -EINVAL; return -EINVAL;
val = index << 1; val = index << 1;
ret = tps65910->write(tps65910, tps_comp.reg, 1, &val); ret = tps65910_reg_write(tps65910, tps_comp.reg, val);
return ret; return ret;
} }
...@@ -86,13 +82,10 @@ static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage) ...@@ -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) static int comp_threshold_get(struct tps65910 *tps65910, int id)
{ {
struct comparator tps_comp = tps_comparators[id]; struct comparator tps_comp = tps_comparators[id];
unsigned int val;
int ret; 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) if (ret < 0)
return ret; return ret;
......
// SPDX-License-Identifier: GPL-2.0
/* /*
* TPS68470 chip Parent driver * TPS68470 chip Parent driver
* *
...@@ -8,15 +9,6 @@ ...@@ -8,15 +9,6 @@
* Tianshu Qiu <tian.shu.qiu@intel.com> * Tianshu Qiu <tian.shu.qiu@intel.com>
* Jian Xu Zheng <jian.xu.zheng@intel.com> * Jian Xu Zheng <jian.xu.zheng@intel.com>
* Yuning Pu <yuning.pu@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> #include <linux/acpi.h>
......
...@@ -431,10 +431,8 @@ static int tps80031_probe(struct i2c_client *client, ...@@ -431,10 +431,8 @@ static int tps80031_probe(struct i2c_client *client,
} }
tps80031 = devm_kzalloc(&client->dev, sizeof(*tps80031), GFP_KERNEL); tps80031 = devm_kzalloc(&client->dev, sizeof(*tps80031), GFP_KERNEL);
if (!tps80031) { if (!tps80031)
dev_err(&client->dev, "Malloc failed for tps80031\n");
return -ENOMEM; return -ENOMEM;
}
for (i = 0; i < TPS80031_NUM_SLAVES; i++) { for (i = 0; i < TPS80031_NUM_SLAVES; i++) {
if (tps80031_slave_address[i] == client->addr) if (tps80031_slave_address[i] == client->addr)
......
...@@ -1177,7 +1177,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -1177,7 +1177,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
twl_priv->ready = true; twl_priv->ready = true;
/* setup clock framework */ /* setup clock framework */
clocks_init(&pdev->dev, pdata ? pdata->clock : NULL); clocks_init(&client->dev, pdata ? pdata->clock : NULL);
/* read TWL IDCODE Register */ /* read TWL IDCODE Register */
if (twl_class_is_4030()) { if (twl_class_is_4030()) {
......
...@@ -392,10 +392,8 @@ int twl6030_init_irq(struct device *dev, int irq_num) ...@@ -392,10 +392,8 @@ int twl6030_init_irq(struct device *dev, int irq_num)
nr_irqs = TWL6030_NR_IRQS; nr_irqs = TWL6030_NR_IRQS;
twl6030_irq = devm_kzalloc(dev, sizeof(*twl6030_irq), GFP_KERNEL); twl6030_irq = devm_kzalloc(dev, sizeof(*twl6030_irq), GFP_KERNEL);
if (!twl6030_irq) { if (!twl6030_irq)
dev_err(dev, "twl6030_irq: Memory allocation failed\n");
return -ENOMEM; return -ENOMEM;
}
mask[0] = 0xFF; mask[0] = 0xFF;
mask[1] = 0xFF; mask[1] = 0xFF;
......
...@@ -59,10 +59,8 @@ static int vprbrd_probe(struct usb_interface *interface, ...@@ -59,10 +59,8 @@ static int vprbrd_probe(struct usb_interface *interface,
/* allocate memory for our device state and initialize it */ /* allocate memory for our device state and initialize it */
vb = kzalloc(sizeof(*vb), GFP_KERNEL); vb = kzalloc(sizeof(*vb), GFP_KERNEL);
if (vb == NULL) { if (!vb)
dev_err(&interface->dev, "Out of memory\n");
return -ENOMEM; return -ENOMEM;
}
mutex_init(&vb->lock); mutex_init(&vb->lock);
......
...@@ -278,7 +278,7 @@ static int wm97xx_ac97_probe(struct ac97_codec_device *adev) ...@@ -278,7 +278,7 @@ static int wm97xx_ac97_probe(struct ac97_codec_device *adev)
codec_pdata = &wm97xx->codec_pdata; codec_pdata = &wm97xx->codec_pdata;
codec_pdata->ac97 = wm97xx->ac97; 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) { switch (adev->vendor_id) {
case WM9705_VENDOR_ID: case WM9705_VENDOR_ID:
......
...@@ -470,3 +470,23 @@ void cros_ec_debugfs_remove(struct cros_ec_dev *ec) ...@@ -470,3 +470,23 @@ void cros_ec_debugfs_remove(struct cros_ec_dev *ec)
cros_ec_cleanup_console_log(ec->debug_info); cros_ec_cleanup_console_log(ec->debug_info);
} }
EXPORT_SYMBOL(cros_ec_debugfs_remove); 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);
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* pwm-atmel.c from Bo Shen * pwm-atmel.c from Bo Shen
*/ */
#include <linux/bitfield.h>
#include <linux/mfd/stm32-timers.h> #include <linux/mfd/stm32-timers.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
...@@ -25,6 +26,7 @@ struct stm32_pwm { ...@@ -25,6 +26,7 @@ struct stm32_pwm {
struct regmap *regmap; struct regmap *regmap;
u32 max_arr; u32 max_arr;
bool have_complementary_output; bool have_complementary_output;
u32 capture[4] ____cacheline_aligned; /* DMA'able buffer */
}; };
struct stm32_breakinput { struct stm32_breakinput {
...@@ -62,6 +64,258 @@ static int write_ccrx(struct stm32_pwm *dev, int ch, u32 value) ...@@ -62,6 +64,258 @@ static int write_ccrx(struct stm32_pwm *dev, int ch, u32 value)
return -EINVAL; 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, static int stm32_pwm_config(struct stm32_pwm *priv, int ch,
int duty_ns, int period_ns) int duty_ns, int period_ns)
{ {
...@@ -230,6 +484,9 @@ static int stm32_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -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 = { static const struct pwm_ops stm32pwm_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.apply = stm32_pwm_apply_locked, .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, static int stm32_pwm_set_breakinput(struct stm32_pwm *priv,
......
...@@ -322,10 +322,9 @@ static int mtk_rtc_probe(struct platform_device *pdev) ...@@ -322,10 +322,9 @@ static int mtk_rtc_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rtc->addr_base = res->start; rtc->addr_base = res->start;
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); rtc->irq = platform_get_irq(pdev, 0);
rtc->irq = irq_create_mapping(mt6397_chip->irq_domain, res->start); if (rtc->irq < 0)
if (rtc->irq <= 0) return rtc->irq;
return -EINVAL;
rtc->regmap = mt6397_chip->regmap; rtc->regmap = mt6397_chip->regmap;
rtc->dev = &pdev->dev; rtc->dev = &pdev->dev;
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#define ARIZONA_MAX_PDM_SPK 2 #define ARIZONA_MAX_PDM_SPK 2
struct regulator_init_data; struct regulator_init_data;
struct gpio_desc;
struct arizona_micbias { struct arizona_micbias {
int mV; /** Regulated voltage */ int mV; /** Regulated voltage */
...@@ -77,7 +78,7 @@ struct arizona_micd_range { ...@@ -77,7 +78,7 @@ struct arizona_micd_range {
}; };
struct arizona_pdata { struct arizona_pdata {
int reset; /** GPIO controlling /RESET, if any */ struct gpio_desc *reset; /** GPIO controlling /RESET, if any */
/** Regulator configuration for MICVDD */ /** Regulator configuration for MICVDD */
struct arizona_micsupp_pdata micvdd; struct arizona_micsupp_pdata micvdd;
......
...@@ -592,11 +592,11 @@ enum axp806_irqs { ...@@ -592,11 +592,11 @@ enum axp806_irqs {
AXP806_IRQ_DCDCC_V_LOW, AXP806_IRQ_DCDCC_V_LOW,
AXP806_IRQ_DCDCD_V_LOW, AXP806_IRQ_DCDCD_V_LOW,
AXP806_IRQ_DCDCE_V_LOW, AXP806_IRQ_DCDCE_V_LOW,
AXP806_IRQ_PWROK_LONG, AXP806_IRQ_POK_LONG,
AXP806_IRQ_PWROK_SHORT, AXP806_IRQ_POK_SHORT,
AXP806_IRQ_WAKEUP, AXP806_IRQ_WAKEUP,
AXP806_IRQ_PWROK_FALL, AXP806_IRQ_POK_FALL,
AXP806_IRQ_PWROK_RISE, AXP806_IRQ_POK_RISE,
}; };
enum axp809_irqs { enum axp809_irqs {
...@@ -642,7 +642,7 @@ struct axp20x_dev { ...@@ -642,7 +642,7 @@ struct axp20x_dev {
struct regmap_irq_chip_data *regmap_irqc; struct regmap_irq_chip_data *regmap_irqc;
long variant; long variant;
int nr_cells; int nr_cells;
struct mfd_cell *cells; const struct mfd_cell *cells;
const struct regmap_config *regmap_cfg; const struct regmap_config *regmap_cfg;
const struct regmap_irq_chip *regmap_irq_chip; const struct regmap_irq_chip *regmap_irq_chip;
}; };
......
...@@ -329,23 +329,7 @@ extern struct attribute_group cros_ec_vbc_attr_group; ...@@ -329,23 +329,7 @@ extern struct attribute_group cros_ec_vbc_attr_group;
/* debugfs stuff */ /* debugfs stuff */
int cros_ec_debugfs_init(struct cros_ec_dev *ec); int cros_ec_debugfs_init(struct cros_ec_dev *ec);
void cros_ec_debugfs_remove(struct cros_ec_dev *ec); void cros_ec_debugfs_remove(struct cros_ec_dev *ec);
void cros_ec_debugfs_suspend(struct cros_ec_dev *ec);
/* ACPI GPE handler */ void cros_ec_debugfs_resume(struct cros_ec_dev *ec);
#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 */
#endif /* __LINUX_MFD_CROS_EC_H */ #endif /* __LINUX_MFD_CROS_EC_H */
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#define _LINUX_STM32_GPTIMER_H_ #define _LINUX_STM32_GPTIMER_H_
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#define TIM_CR1 0x00 /* Control Register 1 */ #define TIM_CR1 0x00 /* Control Register 1 */
...@@ -27,6 +29,8 @@ ...@@ -27,6 +29,8 @@
#define TIM_CCR3 0x3C /* Capt/Comp Register 3 */ #define TIM_CCR3 0x3C /* Capt/Comp Register 3 */
#define TIM_CCR4 0x40 /* Capt/Comp Register 4 */ #define TIM_CCR4 0x40 /* Capt/Comp Register 4 */
#define TIM_BDTR 0x44 /* Break and Dead-Time Reg */ #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_CEN BIT(0) /* Counter Enable */
#define TIM_CR1_DIR BIT(4) /* Counter Direction */ #define TIM_CR1_DIR BIT(4) /* Counter Direction */
...@@ -36,17 +40,35 @@ ...@@ -36,17 +40,35 @@
#define TIM_SMCR_SMS (BIT(0) | BIT(1) | BIT(2)) /* Slave mode selection */ #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_SMCR_TS (BIT(4) | BIT(5) | BIT(6)) /* Trigger selection */
#define TIM_DIER_UIE BIT(0) /* Update interrupt */ #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_SR_UIF BIT(0) /* Update interrupt flag */
#define TIM_EGR_UG BIT(0) /* Update Generation */ #define TIM_EGR_UG BIT(0) /* Update Generation */
#define TIM_CCMR_PE BIT(3) /* Channel Preload Enable */ #define TIM_CCMR_PE BIT(3) /* Channel Preload Enable */
#define TIM_CCMR_M1 (BIT(6) | BIT(5)) /* Channel PWM Mode 1 */ #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_CC1E BIT(0) /* Capt/Comp 1 out Ena */
#define TIM_CCER_CC1P BIT(1) /* Capt/Comp 1 Polarity */ #define TIM_CCER_CC1P BIT(1) /* Capt/Comp 1 Polarity */
#define TIM_CCER_CC1NE BIT(2) /* Capt/Comp 1N out Ena */ #define TIM_CCER_CC1NE BIT(2) /* Capt/Comp 1N out Ena */
#define TIM_CCER_CC1NP BIT(3) /* Capt/Comp 1N Polarity */ #define TIM_CCER_CC1NP BIT(3) /* Capt/Comp 1N Polarity */
#define TIM_CCER_CC2E BIT(4) /* Capt/Comp 2 out Ena */ #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_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_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_CCER_CCXE (BIT(0) | BIT(4) | BIT(8) | BIT(12))
#define TIM_BDTR_BKE BIT(12) /* Break input enable */ #define TIM_BDTR_BKE BIT(12) /* Break input enable */
#define TIM_BDTR_BKP BIT(13) /* Break input polarity */ #define TIM_BDTR_BKP BIT(13) /* Break input polarity */
...@@ -56,8 +78,11 @@ ...@@ -56,8 +78,11 @@
#define TIM_BDTR_BK2F (BIT(20) | BIT(21) | BIT(22) | BIT(23)) #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_BK2E BIT(24) /* Break 2 input enable */
#define TIM_BDTR_BK2P BIT(25) /* Break 2 input polarity */ #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_PSC 0xFFFF
#define MAX_TIM_ICPSC 0x3
#define TIM_CR2_MMS_SHIFT 4 #define TIM_CR2_MMS_SHIFT 4
#define TIM_CR2_MMS2_SHIFT 20 #define TIM_CR2_MMS2_SHIFT 20
#define TIM_SMCR_TS_SHIFT 4 #define TIM_SMCR_TS_SHIFT 4
...@@ -65,9 +90,54 @@ ...@@ -65,9 +90,54 @@
#define TIM_BDTR_BKF_SHIFT 16 #define TIM_BDTR_BKF_SHIFT 16
#define TIM_BDTR_BK2F_SHIFT 20 #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 stm32_timers {
struct clk *clk; struct clk *clk;
struct regmap *regmap; struct regmap *regmap;
u32 max_arr; 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 #endif
/*
* 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_ */
/*
* 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_ */
...@@ -205,10 +205,10 @@ enum tps65218_regulator_id { ...@@ -205,10 +205,10 @@ enum tps65218_regulator_id {
TPS65218_DCDC_4, TPS65218_DCDC_4,
TPS65218_DCDC_5, TPS65218_DCDC_5,
TPS65218_DCDC_6, TPS65218_DCDC_6,
/* LS's */
TPS65218_LS_3,
/* LDOs */ /* LDOs */
TPS65218_LDO_1, TPS65218_LDO_1,
/* LS's */
TPS65218_LS_3,
}; };
#define TPS65218_MAX_REG_ID TPS65218_LDO_1 #define TPS65218_MAX_REG_ID TPS65218_LDO_1
......
/* /* SPDX-License-Identifier: GPL-2.0 */
* Copyright (c) 2017 Intel Corporation /* Copyright (C) 2017 Intel Corporation */
* /* Functions to access TPS68470 power management chip. */
* 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.
*/
#ifndef __LINUX_MFD_TPS68470_H #ifndef __LINUX_MFD_TPS68470_H
#define __LINUX_MFD_TPS68470_H #define __LINUX_MFD_TPS68470_H
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment