mirror of
https://github.com/a52xq-dev/kernel.git
synced 2026-10-18 21:58:11 +07:00
- 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
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEdrbJNaO+IJqU8IdIUa+KL4f8d2EFAlsea+sACgkQUa+KL4f8
d2Fc+A//aaFlfHfJh337tvmJ6wC8w13jjXn0f2M2NrCvRS1CoMF/WqSmJbFGguET
gwv4v8Yf5mWe9crJfSLR4b6hlNWfvzK9Rxwy1WJ8sfnN7a71SIS6LlapxQwZ0S5o
3tQ8n2YKdIyy6feATKnxzRi6IvTjTsIe6BRYev2+m23cEqxoI7b6xo0H1CApVXez
vEnPaT08421qZ2vuPx3UW3JgwWMTYe4iazq1BRkveZZBdyQC+GLpdpoJIO5/OziF
Wgn01Hluu11YuAPidxtmLCAI23RcqLNcPB0zu6//CG5+ut71qnQRs6ua4R352nME
G6aMRVCTR1b0XY48MK+IOLb7mPCCUByHdvdaonzBd48dIrX6k//kVzYxNKY1vlmk
//l/cYhnHBZxGvJAvCmtyi+4AjGz0aLcabY6S7qHMvpNMQ7oNU9FDomJXxynjXg9
ulDkA4EJy6jlWDS6h0u99xycyLuQ4wKo997/Sl5SU+9FBFrdOor2q7R4KfIXQsG9
VGZXi2kWBO9V9oFbbo1oyZ52hDiCy2TKz6fk0rdRltOpVMd4PYluETc4nmnWDo5W
hvjP3rIJSSSIcpggOoQMp5L03cONPGP4MdiuCXOREc6q476CFtpEgJMWApgaEUjw
e1SE8HMKounqw0JYLVz3Lf0RbcHPuR1PN5HDbrchDb8LaAAyCcA=
=NF/E
-----END PGP SIGNATURE-----
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
...
This commit is contained in:
commit
883cad5ba8
64 changed files with 1574 additions and 994 deletions
43
Documentation/devicetree/bindings/input/mtk-pmic-keys.txt
Normal file
43
Documentation/devicetree/bindings/input/mtk-pmic-keys.txt
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
MediaTek MT6397/MT6323 PMIC Keys Device Driver
|
||||
|
||||
There are two key functions provided by MT6397/MT6323 PMIC, pwrkey
|
||||
and homekey. The key functions are defined as the subnode of the function
|
||||
node provided by MT6397/MT6323 PMIC that is being defined as one kind
|
||||
of Muti-Function Device (MFD)
|
||||
|
||||
For MT6397/MT6323 MFD bindings see:
|
||||
Documentation/devicetree/bindings/mfd/mt6397.txt
|
||||
|
||||
Required properties:
|
||||
- compatible: "mediatek,mt6397-keys" or "mediatek,mt6323-keys"
|
||||
- linux,keycodes: See Documentation/devicetree/bindings/input/keys.txt
|
||||
|
||||
Optional Properties:
|
||||
- wakeup-source: See Documentation/devicetree/bindings/power/wakeup-source.txt
|
||||
- mediatek,long-press-mode: Long press key shutdown setting, 1 for
|
||||
pwrkey only, 2 for pwrkey/homekey together, others for disabled.
|
||||
- power-off-time-sec: See Documentation/devicetree/bindings/input/keys.txt
|
||||
|
||||
Example:
|
||||
|
||||
pmic: mt6397 {
|
||||
compatible = "mediatek,mt6397";
|
||||
|
||||
...
|
||||
|
||||
mt6397keys: mt6397keys {
|
||||
compatible = "mediatek,mt6397-keys";
|
||||
mediatek,long-press-mode = <1>;
|
||||
power-off-time-sec = <0>;
|
||||
|
||||
power {
|
||||
linux,keycodes = <116>;
|
||||
wakeup-source;
|
||||
};
|
||||
|
||||
home {
|
||||
linux,keycodes = <114>;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -50,7 +50,7 @@ Required properties:
|
|||
|
||||
Optional properties:
|
||||
|
||||
- wlf,reset : GPIO specifier for the GPIO controlling /RESET
|
||||
- reset-gpios : GPIO specifier for the GPIO controlling /RESET
|
||||
|
||||
- clocks: Should reference the clocks supplied on MCLK1 and MCLK2
|
||||
- clock-names: Should contains two strings:
|
||||
|
|
@ -70,6 +70,10 @@ Optional properties:
|
|||
Documentation/devicetree/bindings/regulator/regulator.txt
|
||||
(wm5102, wm5110, wm8280, wm8997, wm8998, wm1814)
|
||||
|
||||
Deprecated properties:
|
||||
|
||||
- wlf,reset : GPIO specifier for the GPIO controlling /RESET
|
||||
|
||||
Also see child specific device properties:
|
||||
Regulator - ../regulator/arizona-regulator.txt
|
||||
Extcon - ../extcon/extcon-arizona.txt
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
* Dialog DA9063 Power Management Integrated Circuit (PMIC)
|
||||
* Dialog DA9063/DA9063L Power Management Integrated Circuit (PMIC)
|
||||
|
||||
DA9093 consists of a large and varied group of sub-devices (I2C Only):
|
||||
|
||||
|
|
@ -6,14 +6,14 @@ Device Supply Names Description
|
|||
------ ------------ -----------
|
||||
da9063-regulator : : LDOs & BUCKs
|
||||
da9063-onkey : : On Key
|
||||
da9063-rtc : : Real-Time Clock
|
||||
da9063-rtc : : Real-Time Clock (DA9063 only)
|
||||
da9063-watchdog : : Watchdog
|
||||
|
||||
======
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : Should be "dlg,da9063"
|
||||
- compatible : Should be "dlg,da9063" or "dlg,da9063l"
|
||||
- reg : Specifies the I2C slave address (this defaults to 0x58 but it can be
|
||||
modified to match the chip's OTP settings).
|
||||
- interrupt-parent : Specifies the reference to the interrupt controller for
|
||||
|
|
@ -23,8 +23,8 @@ Required properties:
|
|||
|
||||
Sub-nodes:
|
||||
|
||||
- regulators : This node defines the settings for the LDOs and BUCKs. The
|
||||
DA9063 regulators are bound using their names listed below:
|
||||
- regulators : This node defines the settings for the LDOs and BUCKs.
|
||||
The DA9063(L) regulators are bound using their names listed below:
|
||||
|
||||
bcore1 : BUCK CORE1
|
||||
bcore2 : BUCK CORE2
|
||||
|
|
@ -32,16 +32,16 @@ Sub-nodes:
|
|||
bmem : BUCK MEM
|
||||
bio : BUCK IO
|
||||
bperi : BUCK PERI
|
||||
ldo1 : LDO_1
|
||||
ldo2 : LDO_2
|
||||
ldo1 : LDO_1 (DA9063 only)
|
||||
ldo2 : LDO_2 (DA9063 only)
|
||||
ldo3 : LDO_3
|
||||
ldo4 : LDO_4
|
||||
ldo5 : LDO_5
|
||||
ldo6 : LDO_6
|
||||
ldo4 : LDO_4 (DA9063 only)
|
||||
ldo5 : LDO_5 (DA9063 only)
|
||||
ldo6 : LDO_6 (DA9063 only)
|
||||
ldo7 : LDO_7
|
||||
ldo8 : LDO_8
|
||||
ldo9 : LDO_9
|
||||
ldo10 : LDO_10
|
||||
ldo10 : LDO_10 (DA9063 only)
|
||||
ldo11 : LDO_11
|
||||
|
||||
The component follows the standard regulator framework and the bindings
|
||||
|
|
@ -49,8 +49,9 @@ Sub-nodes:
|
|||
Documentation/devicetree/bindings/regulator/regulator.txt
|
||||
|
||||
- rtc : This node defines settings for the Real-Time Clock associated with
|
||||
the DA9063. There are currently no entries in this binding, however
|
||||
compatible = "dlg,da9063-rtc" should be added if a node is created.
|
||||
the DA9063 only. The RTC is not present in DA9063L. There are currently
|
||||
no entries in this binding, however compatible = "dlg,da9063-rtc" should
|
||||
be added if a node is created.
|
||||
|
||||
- onkey : This node defines the OnKey settings for controlling the key
|
||||
functionality of the device. The node should contain the compatible property
|
||||
|
|
@ -65,8 +66,9 @@ Sub-nodes:
|
|||
and KEY_SLEEP.
|
||||
|
||||
- watchdog : This node defines settings for the Watchdog timer associated
|
||||
with the DA9063. There are currently no entries in this binding, however
|
||||
compatible = "dlg,da9063-watchdog" should be added if a node is created.
|
||||
with the DA9063 and DA9063L. There are currently no entries in this
|
||||
binding, however compatible = "dlg,da9063-watchdog" should be added
|
||||
if a node is created.
|
||||
|
||||
|
||||
Example:
|
||||
|
|
|
|||
|
|
@ -12,6 +12,30 @@ Required properties:
|
|||
- spi-max-frequency : Typically set to 3000000
|
||||
- spi-cs-high : SPI chip select direction
|
||||
|
||||
Optional subnodes:
|
||||
|
||||
The sub-functions of CPCAP get their own node with their own compatible values,
|
||||
which are described in the following files:
|
||||
|
||||
- ../power/supply/cpcap-battery.txt
|
||||
- ../power/supply/cpcap-charger.txt
|
||||
- ../regulator/cpcap-regulator.txt
|
||||
- ../phy/phy-cpcap-usb.txt
|
||||
- ../input/cpcap-pwrbutton.txt
|
||||
- ../rtc/cpcap-rtc.txt
|
||||
- ../leds/leds-cpcap.txt
|
||||
- ../iio/adc/cpcap-adc.txt
|
||||
|
||||
The only exception is the audio codec. Instead of a compatible value its
|
||||
node must be named "audio-codec".
|
||||
|
||||
Required properties for the audio-codec subnode:
|
||||
|
||||
- #sound-dai-cells = <1>;
|
||||
|
||||
The audio-codec provides two DAIs. The first one is connected to the
|
||||
Stereo HiFi DAC and the second one is connected to the Voice DAC.
|
||||
|
||||
Example:
|
||||
|
||||
&mcspi1 {
|
||||
|
|
@ -26,6 +50,24 @@ Example:
|
|||
#size-cells = <0>;
|
||||
spi-max-frequency = <3000000>;
|
||||
spi-cs-high;
|
||||
|
||||
audio-codec {
|
||||
#sound-dai-cells = <1>;
|
||||
|
||||
/* HiFi */
|
||||
port@0 {
|
||||
endpoint {
|
||||
remote-endpoint = <&cpu_dai1>;
|
||||
};
|
||||
};
|
||||
|
||||
/* Voice */
|
||||
port@1 {
|
||||
endpoint {
|
||||
remote-endpoint = <&cpu_dai2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ MT6397/MT6323 is a multifunction device with the following sub modules:
|
|||
- GPIO
|
||||
- Clock
|
||||
- LED
|
||||
- Keys
|
||||
|
||||
It is interfaced to host controller using SPI interface by a proprietary hardware
|
||||
called PMIC wrapper or pwrap. MT6397/MT6323 MFD is a child device of pwrap.
|
||||
|
|
@ -40,6 +41,11 @@ Optional subnodes:
|
|||
- compatible: "mediatek,mt6323-led"
|
||||
see Documentation/devicetree/bindings/leds/leds-mt6323.txt
|
||||
|
||||
- keys
|
||||
Required properties:
|
||||
- compatible: "mediatek,mt6397-keys" or "mediatek,mt6323-keys"
|
||||
see Documentation/devicetree/bindings/input/mtk-pmic-keys.txt
|
||||
|
||||
Example:
|
||||
pwrap: pwrap@1000f000 {
|
||||
compatible = "mediatek,mt8135-pwrap";
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ Required properties:
|
|||
"qcom,pm8916",
|
||||
"qcom,pm8004",
|
||||
"qcom,pm8909",
|
||||
"qcom,pm8998",
|
||||
"qcom,pmi8998",
|
||||
"qcom,pm8005",
|
||||
or generalized "qcom,spmi-pmic".
|
||||
- reg: Specifies the SPMI USID slave address for this device.
|
||||
For more information see:
|
||||
|
|
|
|||
10
MAINTAINERS
10
MAINTAINERS
|
|
@ -13562,6 +13562,16 @@ T: git git://linuxtv.org/media_tree.git
|
|||
S: Maintained
|
||||
F: drivers/media/usb/stk1160/
|
||||
|
||||
STM32 TIMER/LPTIMER DRIVERS
|
||||
M: Fabrice Gasnier <fabrice.gasnier@st.com>
|
||||
S: Maintained
|
||||
F: drivers/*/stm32-*timer*
|
||||
F: drivers/pwm/pwm-stm32*
|
||||
F: include/linux/*/stm32-*tim*
|
||||
F: Documentation/ABI/testing/*timer-stm32
|
||||
F: Documentation/devicetree/bindings/*/stm32-*timer
|
||||
F: Documentation/devicetree/bindings/pwm/pwm-stm32*
|
||||
|
||||
STMMAC ETHERNET DRIVER
|
||||
M: Giuseppe Cavallaro <peppe.cavallaro@st.com>
|
||||
M: Alexandre Torgue <alexandre.torgue@st.com>
|
||||
|
|
|
|||
|
|
@ -747,4 +747,13 @@ config KEYBOARD_BCM
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called bcm-keypad.
|
||||
|
||||
config KEYBOARD_MTK_PMIC
|
||||
tristate "MediaTek PMIC keys support"
|
||||
depends on MFD_MT6397
|
||||
help
|
||||
Say Y here if you want to use the pmic keys (powerkey/homekey).
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called pmic-keys.
|
||||
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o
|
|||
obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o
|
||||
obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o
|
||||
obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_touchkey.o
|
||||
obj-$(CONFIG_KEYBOARD_MTK_PMIC) += mtk-pmic-keys.o
|
||||
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
|
||||
obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o
|
||||
obj-$(CONFIG_KEYBOARD_NSPIRE) += nspire-keypad.o
|
||||
|
|
|
|||
339
drivers/input/keyboard/mtk-pmic-keys.c
Normal file
339
drivers/input/keyboard/mtk-pmic-keys.c
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
/*
|
||||
* Copyright (C) 2017 MediaTek, Inc.
|
||||
*
|
||||
* Author: Chen Zhong <chen.zhong@mediatek.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/mt6323/registers.h>
|
||||
#include <linux/mfd/mt6397/registers.h>
|
||||
#include <linux/mfd/mt6397/core.h>
|
||||
|
||||
#define MTK_PMIC_PWRKEY_RST_EN_MASK 0x1
|
||||
#define MTK_PMIC_PWRKEY_RST_EN_SHIFT 6
|
||||
#define MTK_PMIC_HOMEKEY_RST_EN_MASK 0x1
|
||||
#define MTK_PMIC_HOMEKEY_RST_EN_SHIFT 5
|
||||
#define MTK_PMIC_RST_DU_MASK 0x3
|
||||
#define MTK_PMIC_RST_DU_SHIFT 8
|
||||
|
||||
#define MTK_PMIC_PWRKEY_RST \
|
||||
(MTK_PMIC_PWRKEY_RST_EN_MASK << MTK_PMIC_PWRKEY_RST_EN_SHIFT)
|
||||
#define MTK_PMIC_HOMEKEY_RST \
|
||||
(MTK_PMIC_HOMEKEY_RST_EN_MASK << MTK_PMIC_HOMEKEY_RST_EN_SHIFT)
|
||||
|
||||
#define MTK_PMIC_PWRKEY_INDEX 0
|
||||
#define MTK_PMIC_HOMEKEY_INDEX 1
|
||||
#define MTK_PMIC_MAX_KEY_COUNT 2
|
||||
|
||||
struct mtk_pmic_keys_regs {
|
||||
u32 deb_reg;
|
||||
u32 deb_mask;
|
||||
u32 intsel_reg;
|
||||
u32 intsel_mask;
|
||||
};
|
||||
|
||||
#define MTK_PMIC_KEYS_REGS(_deb_reg, _deb_mask, \
|
||||
_intsel_reg, _intsel_mask) \
|
||||
{ \
|
||||
.deb_reg = _deb_reg, \
|
||||
.deb_mask = _deb_mask, \
|
||||
.intsel_reg = _intsel_reg, \
|
||||
.intsel_mask = _intsel_mask, \
|
||||
}
|
||||
|
||||
struct mtk_pmic_regs {
|
||||
const struct mtk_pmic_keys_regs keys_regs[MTK_PMIC_MAX_KEY_COUNT];
|
||||
u32 pmic_rst_reg;
|
||||
};
|
||||
|
||||
static const struct mtk_pmic_regs mt6397_regs = {
|
||||
.keys_regs[MTK_PMIC_PWRKEY_INDEX] =
|
||||
MTK_PMIC_KEYS_REGS(MT6397_CHRSTATUS,
|
||||
0x8, MT6397_INT_RSV, 0x10),
|
||||
.keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
|
||||
MTK_PMIC_KEYS_REGS(MT6397_OCSTATUS2,
|
||||
0x10, MT6397_INT_RSV, 0x8),
|
||||
.pmic_rst_reg = MT6397_TOP_RST_MISC,
|
||||
};
|
||||
|
||||
static const struct mtk_pmic_regs mt6323_regs = {
|
||||
.keys_regs[MTK_PMIC_PWRKEY_INDEX] =
|
||||
MTK_PMIC_KEYS_REGS(MT6323_CHRSTATUS,
|
||||
0x2, MT6323_INT_MISC_CON, 0x10),
|
||||
.keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
|
||||
MTK_PMIC_KEYS_REGS(MT6323_CHRSTATUS,
|
||||
0x4, MT6323_INT_MISC_CON, 0x8),
|
||||
.pmic_rst_reg = MT6323_TOP_RST_MISC,
|
||||
};
|
||||
|
||||
struct mtk_pmic_keys_info {
|
||||
struct mtk_pmic_keys *keys;
|
||||
const struct mtk_pmic_keys_regs *regs;
|
||||
unsigned int keycode;
|
||||
int irq;
|
||||
bool wakeup:1;
|
||||
};
|
||||
|
||||
struct mtk_pmic_keys {
|
||||
struct input_dev *input_dev;
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct mtk_pmic_keys_info keys[MTK_PMIC_MAX_KEY_COUNT];
|
||||
};
|
||||
|
||||
enum mtk_pmic_keys_lp_mode {
|
||||
LP_DISABLE,
|
||||
LP_ONEKEY,
|
||||
LP_TWOKEY,
|
||||
};
|
||||
|
||||
static void mtk_pmic_keys_lp_reset_setup(struct mtk_pmic_keys *keys,
|
||||
u32 pmic_rst_reg)
|
||||
{
|
||||
int ret;
|
||||
u32 long_press_mode, long_press_debounce;
|
||||
|
||||
ret = of_property_read_u32(keys->dev->of_node,
|
||||
"power-off-time-sec", &long_press_debounce);
|
||||
if (ret)
|
||||
long_press_debounce = 0;
|
||||
|
||||
regmap_update_bits(keys->regmap, pmic_rst_reg,
|
||||
MTK_PMIC_RST_DU_MASK << MTK_PMIC_RST_DU_SHIFT,
|
||||
long_press_debounce << MTK_PMIC_RST_DU_SHIFT);
|
||||
|
||||
ret = of_property_read_u32(keys->dev->of_node,
|
||||
"mediatek,long-press-mode", &long_press_mode);
|
||||
if (ret)
|
||||
long_press_mode = LP_DISABLE;
|
||||
|
||||
switch (long_press_mode) {
|
||||
case LP_ONEKEY:
|
||||
regmap_update_bits(keys->regmap, pmic_rst_reg,
|
||||
MTK_PMIC_PWRKEY_RST,
|
||||
MTK_PMIC_PWRKEY_RST);
|
||||
regmap_update_bits(keys->regmap, pmic_rst_reg,
|
||||
MTK_PMIC_HOMEKEY_RST,
|
||||
0);
|
||||
break;
|
||||
case LP_TWOKEY:
|
||||
regmap_update_bits(keys->regmap, pmic_rst_reg,
|
||||
MTK_PMIC_PWRKEY_RST,
|
||||
MTK_PMIC_PWRKEY_RST);
|
||||
regmap_update_bits(keys->regmap, pmic_rst_reg,
|
||||
MTK_PMIC_HOMEKEY_RST,
|
||||
MTK_PMIC_HOMEKEY_RST);
|
||||
break;
|
||||
case LP_DISABLE:
|
||||
regmap_update_bits(keys->regmap, pmic_rst_reg,
|
||||
MTK_PMIC_PWRKEY_RST,
|
||||
0);
|
||||
regmap_update_bits(keys->regmap, pmic_rst_reg,
|
||||
MTK_PMIC_HOMEKEY_RST,
|
||||
0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t mtk_pmic_keys_irq_handler_thread(int irq, void *data)
|
||||
{
|
||||
struct mtk_pmic_keys_info *info = data;
|
||||
u32 key_deb, pressed;
|
||||
|
||||
regmap_read(info->keys->regmap, info->regs->deb_reg, &key_deb);
|
||||
|
||||
key_deb &= info->regs->deb_mask;
|
||||
|
||||
pressed = !key_deb;
|
||||
|
||||
input_report_key(info->keys->input_dev, info->keycode, pressed);
|
||||
input_sync(info->keys->input_dev);
|
||||
|
||||
dev_dbg(info->keys->dev, "(%s) key =%d using PMIC\n",
|
||||
pressed ? "pressed" : "released", info->keycode);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int mtk_pmic_key_setup(struct mtk_pmic_keys *keys,
|
||||
struct mtk_pmic_keys_info *info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
info->keys = keys;
|
||||
|
||||
ret = regmap_update_bits(keys->regmap, info->regs->intsel_reg,
|
||||
info->regs->intsel_mask,
|
||||
info->regs->intsel_mask);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = devm_request_threaded_irq(keys->dev, info->irq, NULL,
|
||||
mtk_pmic_keys_irq_handler_thread,
|
||||
IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
|
||||
"mtk-pmic-keys", info);
|
||||
if (ret) {
|
||||
dev_err(keys->dev, "Failed to request IRQ: %d: %d\n",
|
||||
info->irq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
input_set_capability(keys->input_dev, EV_KEY, info->keycode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused mtk_pmic_keys_suspend(struct device *dev)
|
||||
{
|
||||
struct mtk_pmic_keys *keys = dev_get_drvdata(dev);
|
||||
int index;
|
||||
|
||||
for (index = 0; index < MTK_PMIC_MAX_KEY_COUNT; index++) {
|
||||
if (keys->keys[index].wakeup)
|
||||
enable_irq_wake(keys->keys[index].irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused mtk_pmic_keys_resume(struct device *dev)
|
||||
{
|
||||
struct mtk_pmic_keys *keys = dev_get_drvdata(dev);
|
||||
int index;
|
||||
|
||||
for (index = 0; index < MTK_PMIC_MAX_KEY_COUNT; index++) {
|
||||
if (keys->keys[index].wakeup)
|
||||
disable_irq_wake(keys->keys[index].irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(mtk_pmic_keys_pm_ops, mtk_pmic_keys_suspend,
|
||||
mtk_pmic_keys_resume);
|
||||
|
||||
static const struct of_device_id of_mtk_pmic_keys_match_tbl[] = {
|
||||
{
|
||||
.compatible = "mediatek,mt6397-keys",
|
||||
.data = &mt6397_regs,
|
||||
}, {
|
||||
.compatible = "mediatek,mt6323-keys",
|
||||
.data = &mt6323_regs,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_mtk_pmic_keys_match_tbl);
|
||||
|
||||
static int mtk_pmic_keys_probe(struct platform_device *pdev)
|
||||
{
|
||||
int error, index = 0;
|
||||
unsigned int keycount;
|
||||
struct mt6397_chip *pmic_chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct device_node *node = pdev->dev.of_node, *child;
|
||||
struct mtk_pmic_keys *keys;
|
||||
const struct mtk_pmic_regs *mtk_pmic_regs;
|
||||
struct input_dev *input_dev;
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(of_mtk_pmic_keys_match_tbl, &pdev->dev);
|
||||
|
||||
keys = devm_kzalloc(&pdev->dev, sizeof(*keys), GFP_KERNEL);
|
||||
if (!keys)
|
||||
return -ENOMEM;
|
||||
|
||||
keys->dev = &pdev->dev;
|
||||
keys->regmap = pmic_chip->regmap;
|
||||
mtk_pmic_regs = of_id->data;
|
||||
|
||||
keys->input_dev = input_dev = devm_input_allocate_device(keys->dev);
|
||||
if (!input_dev) {
|
||||
dev_err(keys->dev, "input allocate device fail.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
input_dev->name = "mtk-pmic-keys";
|
||||
input_dev->id.bustype = BUS_HOST;
|
||||
input_dev->id.vendor = 0x0001;
|
||||
input_dev->id.product = 0x0001;
|
||||
input_dev->id.version = 0x0001;
|
||||
|
||||
keycount = of_get_available_child_count(node);
|
||||
if (keycount > MTK_PMIC_MAX_KEY_COUNT) {
|
||||
dev_err(keys->dev, "too many keys defined (%d)\n", keycount);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for_each_child_of_node(node, child) {
|
||||
keys->keys[index].regs = &mtk_pmic_regs->keys_regs[index];
|
||||
|
||||
keys->keys[index].irq = platform_get_irq(pdev, index);
|
||||
if (keys->keys[index].irq < 0)
|
||||
return keys->keys[index].irq;
|
||||
|
||||
error = of_property_read_u32(child,
|
||||
"linux,keycodes", &keys->keys[index].keycode);
|
||||
if (error) {
|
||||
dev_err(keys->dev,
|
||||
"failed to read key:%d linux,keycode property: %d\n",
|
||||
index, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (of_property_read_bool(child, "wakeup-source"))
|
||||
keys->keys[index].wakeup = true;
|
||||
|
||||
error = mtk_pmic_key_setup(keys, &keys->keys[index]);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
error = input_register_device(input_dev);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev,
|
||||
"register input device failed (%d)\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
mtk_pmic_keys_lp_reset_setup(keys, mtk_pmic_regs->pmic_rst_reg);
|
||||
|
||||
platform_set_drvdata(pdev, keys);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver pmic_keys_pdrv = {
|
||||
.probe = mtk_pmic_keys_probe,
|
||||
.driver = {
|
||||
.name = "mtk-pmic-keys",
|
||||
.of_match_table = of_mtk_pmic_keys_match_tbl,
|
||||
.pm = &mtk_pmic_keys_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(pmic_keys_pdrv);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Chen Zhong <chen.zhong@mediatek.com>");
|
||||
MODULE_DESCRIPTION("MTK pmic-keys driver v0.1");
|
||||
|
|
@ -13,7 +13,6 @@ obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
|
|||
obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
|
||||
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
|
||||
cros_ec_core-objs := cros_ec.o
|
||||
cros_ec_core-$(CONFIG_ACPI) += cros_ec_acpi_gpe.o
|
||||
obj-$(CONFIG_MFD_CROS_EC) += cros_ec_core.o
|
||||
obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
|
||||
obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
|
||||
|
|
|
|||
|
|
@ -2519,11 +2519,10 @@ static ssize_t ab8500_subscribe_write(struct file *file,
|
|||
if (!dev_attr[irq_index])
|
||||
return -ENOMEM;
|
||||
|
||||
event_name[irq_index] = kmalloc(count, GFP_KERNEL);
|
||||
event_name[irq_index] = kasprintf(GFP_KERNEL, "%lu", user_val);
|
||||
if (!event_name[irq_index])
|
||||
return -ENOMEM;
|
||||
|
||||
sprintf(event_name[irq_index], "%lu", user_val);
|
||||
dev_attr[irq_index]->show = show_irq;
|
||||
dev_attr[irq_index]->store = NULL;
|
||||
dev_attr[irq_index]->attr.name = event_name[irq_index];
|
||||
|
|
|
|||
|
|
@ -37,15 +37,12 @@ int abx500_register_ops(struct device *dev, struct abx500_ops *ops)
|
|||
{
|
||||
struct abx500_device_entry *dev_entry;
|
||||
|
||||
dev_entry = devm_kzalloc(dev,
|
||||
sizeof(struct abx500_device_entry),
|
||||
GFP_KERNEL);
|
||||
if (!dev_entry) {
|
||||
dev_err(dev, "register_ops kzalloc failed");
|
||||
dev_entry = devm_kzalloc(dev, sizeof(*dev_entry), GFP_KERNEL);
|
||||
if (!dev_entry)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev_entry->dev = dev;
|
||||
memcpy(&dev_entry->ops, ops, sizeof(struct abx500_ops));
|
||||
memcpy(&dev_entry->ops, ops, sizeof(*ops));
|
||||
|
||||
list_add_tail(&dev_entry->list, &abx500_list);
|
||||
return 0;
|
||||
|
|
@ -68,7 +65,7 @@ int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
|
|||
struct abx500_ops *ops;
|
||||
|
||||
lookup_ops(dev->parent, &ops);
|
||||
if ((ops != NULL) && (ops->set_register != NULL))
|
||||
if (ops && ops->set_register)
|
||||
return ops->set_register(dev, bank, reg, value);
|
||||
else
|
||||
return -ENOTSUPP;
|
||||
|
|
@ -81,7 +78,7 @@ int abx500_get_register_interruptible(struct device *dev, u8 bank, u8 reg,
|
|||
struct abx500_ops *ops;
|
||||
|
||||
lookup_ops(dev->parent, &ops);
|
||||
if ((ops != NULL) && (ops->get_register != NULL))
|
||||
if (ops && ops->get_register)
|
||||
return ops->get_register(dev, bank, reg, value);
|
||||
else
|
||||
return -ENOTSUPP;
|
||||
|
|
@ -94,7 +91,7 @@ int abx500_get_register_page_interruptible(struct device *dev, u8 bank,
|
|||
struct abx500_ops *ops;
|
||||
|
||||
lookup_ops(dev->parent, &ops);
|
||||
if ((ops != NULL) && (ops->get_register_page != NULL))
|
||||
if (ops && ops->get_register_page)
|
||||
return ops->get_register_page(dev, bank,
|
||||
first_reg, regvals, numregs);
|
||||
else
|
||||
|
|
@ -108,7 +105,7 @@ int abx500_mask_and_set_register_interruptible(struct device *dev, u8 bank,
|
|||
struct abx500_ops *ops;
|
||||
|
||||
lookup_ops(dev->parent, &ops);
|
||||
if ((ops != NULL) && (ops->mask_and_set_register != NULL))
|
||||
if (ops && ops->mask_and_set_register)
|
||||
return ops->mask_and_set_register(dev, bank,
|
||||
reg, bitmask, bitvalues);
|
||||
else
|
||||
|
|
@ -121,7 +118,7 @@ int abx500_get_chip_id(struct device *dev)
|
|||
struct abx500_ops *ops;
|
||||
|
||||
lookup_ops(dev->parent, &ops);
|
||||
if ((ops != NULL) && (ops->get_chip_id != NULL))
|
||||
if (ops && ops->get_chip_id)
|
||||
return ops->get_chip_id(dev);
|
||||
else
|
||||
return -ENOTSUPP;
|
||||
|
|
@ -133,7 +130,7 @@ int abx500_event_registers_startup_state_get(struct device *dev, u8 *event)
|
|||
struct abx500_ops *ops;
|
||||
|
||||
lookup_ops(dev->parent, &ops);
|
||||
if ((ops != NULL) && (ops->event_registers_startup_state_get != NULL))
|
||||
if (ops && ops->event_registers_startup_state_get)
|
||||
return ops->event_registers_startup_state_get(dev, event);
|
||||
else
|
||||
return -ENOTSUPP;
|
||||
|
|
@ -145,7 +142,7 @@ int abx500_startup_irq_enabled(struct device *dev, unsigned int irq)
|
|||
struct abx500_ops *ops;
|
||||
|
||||
lookup_ops(dev->parent, &ops);
|
||||
if ((ops != NULL) && (ops->startup_irq_enabled != NULL))
|
||||
if (ops && ops->startup_irq_enabled)
|
||||
return ops->startup_irq_enabled(dev, irq);
|
||||
else
|
||||
return -ENOTSUPP;
|
||||
|
|
|
|||
|
|
@ -13,13 +13,12 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
|
@ -279,7 +278,7 @@ static int arizona_wait_for_boot(struct arizona *arizona)
|
|||
static inline void arizona_enable_reset(struct arizona *arizona)
|
||||
{
|
||||
if (arizona->pdata.reset)
|
||||
gpio_set_value_cansleep(arizona->pdata.reset, 0);
|
||||
gpiod_set_raw_value_cansleep(arizona->pdata.reset, 0);
|
||||
}
|
||||
|
||||
static void arizona_disable_reset(struct arizona *arizona)
|
||||
|
|
@ -295,7 +294,7 @@ static void arizona_disable_reset(struct arizona *arizona)
|
|||
break;
|
||||
}
|
||||
|
||||
gpio_set_value_cansleep(arizona->pdata.reset, 1);
|
||||
gpiod_set_raw_value_cansleep(arizona->pdata.reset, 1);
|
||||
usleep_range(1000, 5000);
|
||||
}
|
||||
}
|
||||
|
|
@ -799,14 +798,27 @@ static int arizona_of_get_core_pdata(struct arizona *arizona)
|
|||
struct arizona_pdata *pdata = &arizona->pdata;
|
||||
int ret, i;
|
||||
|
||||
pdata->reset = of_get_named_gpio(arizona->dev->of_node, "wlf,reset", 0);
|
||||
if (pdata->reset == -EPROBE_DEFER) {
|
||||
return pdata->reset;
|
||||
} else if (pdata->reset < 0) {
|
||||
dev_err(arizona->dev, "Reset GPIO missing/malformed: %d\n",
|
||||
pdata->reset);
|
||||
/* Handle old non-standard DT binding */
|
||||
pdata->reset = devm_gpiod_get_from_of_node(arizona->dev,
|
||||
arizona->dev->of_node,
|
||||
"wlf,reset", 0,
|
||||
GPIOD_OUT_LOW,
|
||||
"arizona /RESET");
|
||||
if (IS_ERR(pdata->reset)) {
|
||||
ret = PTR_ERR(pdata->reset);
|
||||
|
||||
pdata->reset = 0;
|
||||
/*
|
||||
* Reset missing will be caught when other binding is read
|
||||
* but all other errors imply this binding is in use but has
|
||||
* encountered a problem so should be handled.
|
||||
*/
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
else if (ret != -ENOENT && ret != -ENOSYS)
|
||||
dev_err(arizona->dev, "Reset GPIO malformed: %d\n",
|
||||
ret);
|
||||
|
||||
pdata->reset = NULL;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32_array(arizona->dev->of_node,
|
||||
|
|
@ -1050,14 +1062,19 @@ int arizona_dev_init(struct arizona *arizona)
|
|||
goto err_early;
|
||||
}
|
||||
|
||||
if (arizona->pdata.reset) {
|
||||
if (!arizona->pdata.reset) {
|
||||
/* Start out with /RESET low to put the chip into reset */
|
||||
ret = devm_gpio_request_one(arizona->dev, arizona->pdata.reset,
|
||||
GPIOF_DIR_OUT | GPIOF_INIT_LOW,
|
||||
"arizona /RESET");
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "Failed to request /RESET: %d\n", ret);
|
||||
goto err_dcvdd;
|
||||
arizona->pdata.reset = devm_gpiod_get(arizona->dev, "reset",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(arizona->pdata.reset)) {
|
||||
ret = PTR_ERR(arizona->pdata.reset);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
goto err_dcvdd;
|
||||
|
||||
dev_err(arizona->dev,
|
||||
"Reset GPIO missing/malformed: %d\n", ret);
|
||||
|
||||
arizona->pdata.reset = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
#include <linux/mfd/ds1wm.h>
|
||||
#include <linux/mfd/tmio.h>
|
||||
|
||||
#include <linux/mmc/host.h>
|
||||
|
||||
enum {
|
||||
ASIC3_CLOCK_SPI,
|
||||
ASIC3_CLOCK_OWM,
|
||||
|
|
@ -719,6 +721,7 @@ static void asic3_mmc_clk_div(struct platform_device *pdev, int state)
|
|||
|
||||
static struct tmio_mmc_data asic3_mmc_data = {
|
||||
.hclk = 24576000,
|
||||
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||
.set_pwr = asic3_mmc_pwr,
|
||||
.set_clk_div = asic3_mmc_clk_div,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/mfd/syscon/atmel-smc.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
/**
|
||||
* atmel_smc_cs_conf_init - initialize a SMC CS conf
|
||||
|
|
|
|||
|
|
@ -169,131 +169,61 @@ static const struct regmap_access_table axp806_volatile_table = {
|
|||
.n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges),
|
||||
};
|
||||
|
||||
static struct resource axp152_pek_resources[] = {
|
||||
static const struct resource axp152_pek_resources[] = {
|
||||
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
|
||||
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
|
||||
};
|
||||
|
||||
static struct resource axp20x_ac_power_supply_resources[] = {
|
||||
static const struct resource axp20x_ac_power_supply_resources[] = {
|
||||
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"),
|
||||
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"),
|
||||
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_OVER_V, "ACIN_OVER_V"),
|
||||
};
|
||||
|
||||
static struct resource axp20x_pek_resources[] = {
|
||||
{
|
||||
.name = "PEK_DBR",
|
||||
.start = AXP20X_IRQ_PEK_RIS_EDGE,
|
||||
.end = AXP20X_IRQ_PEK_RIS_EDGE,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}, {
|
||||
.name = "PEK_DBF",
|
||||
.start = AXP20X_IRQ_PEK_FAL_EDGE,
|
||||
.end = AXP20X_IRQ_PEK_FAL_EDGE,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
static const struct resource axp20x_pek_resources[] = {
|
||||
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
|
||||
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
|
||||
};
|
||||
|
||||
static struct resource axp20x_usb_power_supply_resources[] = {
|
||||
static const struct resource axp20x_usb_power_supply_resources[] = {
|
||||
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
|
||||
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
|
||||
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_VALID, "VBUS_VALID"),
|
||||
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"),
|
||||
};
|
||||
|
||||
static struct resource axp22x_usb_power_supply_resources[] = {
|
||||
static const struct resource axp22x_usb_power_supply_resources[] = {
|
||||
DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
|
||||
DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
|
||||
};
|
||||
|
||||
static struct resource axp22x_pek_resources[] = {
|
||||
{
|
||||
.name = "PEK_DBR",
|
||||
.start = AXP22X_IRQ_PEK_RIS_EDGE,
|
||||
.end = AXP22X_IRQ_PEK_RIS_EDGE,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}, {
|
||||
.name = "PEK_DBF",
|
||||
.start = AXP22X_IRQ_PEK_FAL_EDGE,
|
||||
.end = AXP22X_IRQ_PEK_FAL_EDGE,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
static const struct resource axp22x_pek_resources[] = {
|
||||
DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
|
||||
DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
|
||||
};
|
||||
|
||||
static struct resource axp288_power_button_resources[] = {
|
||||
{
|
||||
.name = "PEK_DBR",
|
||||
.start = AXP288_IRQ_POKP,
|
||||
.end = AXP288_IRQ_POKP,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.name = "PEK_DBF",
|
||||
.start = AXP288_IRQ_POKN,
|
||||
.end = AXP288_IRQ_POKN,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
static const struct resource axp288_power_button_resources[] = {
|
||||
DEFINE_RES_IRQ_NAMED(AXP288_IRQ_POKP, "PEK_DBR"),
|
||||
DEFINE_RES_IRQ_NAMED(AXP288_IRQ_POKN, "PEK_DBF"),
|
||||
};
|
||||
|
||||
static struct resource axp288_fuel_gauge_resources[] = {
|
||||
{
|
||||
.start = AXP288_IRQ_QWBTU,
|
||||
.end = AXP288_IRQ_QWBTU,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_WBTU,
|
||||
.end = AXP288_IRQ_WBTU,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_QWBTO,
|
||||
.end = AXP288_IRQ_QWBTO,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_WBTO,
|
||||
.end = AXP288_IRQ_WBTO,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_WL2,
|
||||
.end = AXP288_IRQ_WL2,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_WL1,
|
||||
.end = AXP288_IRQ_WL1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
static const struct resource axp288_fuel_gauge_resources[] = {
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_QWBTU),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_WBTU),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_QWBTO),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_WBTO),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_WL2),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_WL1),
|
||||
};
|
||||
|
||||
static struct resource axp803_pek_resources[] = {
|
||||
{
|
||||
.name = "PEK_DBR",
|
||||
.start = AXP803_IRQ_PEK_RIS_EDGE,
|
||||
.end = AXP803_IRQ_PEK_RIS_EDGE,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}, {
|
||||
.name = "PEK_DBF",
|
||||
.start = AXP803_IRQ_PEK_FAL_EDGE,
|
||||
.end = AXP803_IRQ_PEK_FAL_EDGE,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
static const struct resource axp803_pek_resources[] = {
|
||||
DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
|
||||
DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
|
||||
};
|
||||
|
||||
static struct resource axp809_pek_resources[] = {
|
||||
{
|
||||
.name = "PEK_DBR",
|
||||
.start = AXP809_IRQ_PEK_RIS_EDGE,
|
||||
.end = AXP809_IRQ_PEK_RIS_EDGE,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}, {
|
||||
.name = "PEK_DBF",
|
||||
.start = AXP809_IRQ_PEK_FAL_EDGE,
|
||||
.end = AXP809_IRQ_PEK_FAL_EDGE,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
static const struct resource axp809_pek_resources[] = {
|
||||
DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
|
||||
DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
|
||||
};
|
||||
|
||||
static const struct regmap_config axp152_regmap_config = {
|
||||
|
|
@ -520,11 +450,11 @@ static const struct regmap_irq axp806_regmap_irqs[] = {
|
|||
INIT_REGMAP_IRQ(AXP806, DCDCC_V_LOW, 0, 5),
|
||||
INIT_REGMAP_IRQ(AXP806, DCDCD_V_LOW, 0, 6),
|
||||
INIT_REGMAP_IRQ(AXP806, DCDCE_V_LOW, 0, 7),
|
||||
INIT_REGMAP_IRQ(AXP806, PWROK_LONG, 1, 0),
|
||||
INIT_REGMAP_IRQ(AXP806, PWROK_SHORT, 1, 1),
|
||||
INIT_REGMAP_IRQ(AXP806, POK_LONG, 1, 0),
|
||||
INIT_REGMAP_IRQ(AXP806, POK_SHORT, 1, 1),
|
||||
INIT_REGMAP_IRQ(AXP806, WAKEUP, 1, 4),
|
||||
INIT_REGMAP_IRQ(AXP806, PWROK_FALL, 1, 5),
|
||||
INIT_REGMAP_IRQ(AXP806, PWROK_RISE, 1, 6),
|
||||
INIT_REGMAP_IRQ(AXP806, POK_FALL, 1, 5),
|
||||
INIT_REGMAP_IRQ(AXP806, POK_RISE, 1, 6),
|
||||
};
|
||||
|
||||
static const struct regmap_irq axp809_regmap_irqs[] = {
|
||||
|
|
@ -648,7 +578,7 @@ static const struct regmap_irq_chip axp809_regmap_irq_chip = {
|
|||
.num_regs = 5,
|
||||
};
|
||||
|
||||
static struct mfd_cell axp20x_cells[] = {
|
||||
static const struct mfd_cell axp20x_cells[] = {
|
||||
{
|
||||
.name = "axp20x-gpio",
|
||||
.of_compatible = "x-powers,axp209-gpio",
|
||||
|
|
@ -660,6 +590,7 @@ static struct mfd_cell axp20x_cells[] = {
|
|||
.name = "axp20x-regulator",
|
||||
}, {
|
||||
.name = "axp20x-adc",
|
||||
.of_compatible = "x-powers,axp209-adc",
|
||||
}, {
|
||||
.name = "axp20x-battery-power-supply",
|
||||
.of_compatible = "x-powers,axp209-battery-power-supply",
|
||||
|
|
@ -676,7 +607,7 @@ static struct mfd_cell axp20x_cells[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell axp221_cells[] = {
|
||||
static const struct mfd_cell axp221_cells[] = {
|
||||
{
|
||||
.name = "axp221-pek",
|
||||
.num_resources = ARRAY_SIZE(axp22x_pek_resources),
|
||||
|
|
@ -684,7 +615,8 @@ static struct mfd_cell axp221_cells[] = {
|
|||
}, {
|
||||
.name = "axp20x-regulator",
|
||||
}, {
|
||||
.name = "axp22x-adc"
|
||||
.name = "axp22x-adc",
|
||||
.of_compatible = "x-powers,axp221-adc",
|
||||
}, {
|
||||
.name = "axp20x-ac-power-supply",
|
||||
.of_compatible = "x-powers,axp221-ac-power-supply",
|
||||
|
|
@ -701,13 +633,14 @@ static struct mfd_cell axp221_cells[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell axp223_cells[] = {
|
||||
static const struct mfd_cell axp223_cells[] = {
|
||||
{
|
||||
.name = "axp221-pek",
|
||||
.num_resources = ARRAY_SIZE(axp22x_pek_resources),
|
||||
.resources = axp22x_pek_resources,
|
||||
}, {
|
||||
.name = "axp22x-adc",
|
||||
.of_compatible = "x-powers,axp221-adc",
|
||||
}, {
|
||||
.name = "axp20x-battery-power-supply",
|
||||
.of_compatible = "x-powers,axp221-battery-power-supply",
|
||||
|
|
@ -726,7 +659,7 @@ static struct mfd_cell axp223_cells[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell axp152_cells[] = {
|
||||
static const struct mfd_cell axp152_cells[] = {
|
||||
{
|
||||
.name = "axp20x-pek",
|
||||
.num_resources = ARRAY_SIZE(axp152_pek_resources),
|
||||
|
|
@ -734,87 +667,30 @@ static struct mfd_cell axp152_cells[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct resource axp288_adc_resources[] = {
|
||||
{
|
||||
.name = "GPADC",
|
||||
.start = AXP288_IRQ_GPADC,
|
||||
.end = AXP288_IRQ_GPADC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
static const struct resource axp288_adc_resources[] = {
|
||||
DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"),
|
||||
};
|
||||
|
||||
static struct resource axp288_extcon_resources[] = {
|
||||
{
|
||||
.start = AXP288_IRQ_VBUS_FALL,
|
||||
.end = AXP288_IRQ_VBUS_FALL,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_VBUS_RISE,
|
||||
.end = AXP288_IRQ_VBUS_RISE,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_MV_CHNG,
|
||||
.end = AXP288_IRQ_MV_CHNG,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_BC_USB_CHNG,
|
||||
.end = AXP288_IRQ_BC_USB_CHNG,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
static const struct resource axp288_extcon_resources[] = {
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_VBUS_FALL),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_VBUS_RISE),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_MV_CHNG),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_BC_USB_CHNG),
|
||||
};
|
||||
|
||||
static struct resource axp288_charger_resources[] = {
|
||||
{
|
||||
.start = AXP288_IRQ_OV,
|
||||
.end = AXP288_IRQ_OV,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_DONE,
|
||||
.end = AXP288_IRQ_DONE,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_CHARGING,
|
||||
.end = AXP288_IRQ_CHARGING,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_SAFE_QUIT,
|
||||
.end = AXP288_IRQ_SAFE_QUIT,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_SAFE_ENTER,
|
||||
.end = AXP288_IRQ_SAFE_ENTER,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_QCBTU,
|
||||
.end = AXP288_IRQ_QCBTU,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_CBTU,
|
||||
.end = AXP288_IRQ_CBTU,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_QCBTO,
|
||||
.end = AXP288_IRQ_QCBTO,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AXP288_IRQ_CBTO,
|
||||
.end = AXP288_IRQ_CBTO,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
static const struct resource axp288_charger_resources[] = {
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_OV),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_DONE),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_CHARGING),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_SAFE_QUIT),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_SAFE_ENTER),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_QCBTU),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_CBTU),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_QCBTO),
|
||||
DEFINE_RES_IRQ(AXP288_IRQ_CBTO),
|
||||
};
|
||||
|
||||
static struct mfd_cell axp288_cells[] = {
|
||||
static const struct mfd_cell axp288_cells[] = {
|
||||
{
|
||||
.name = "axp288_adc",
|
||||
.num_resources = ARRAY_SIZE(axp288_adc_resources),
|
||||
|
|
@ -845,7 +721,7 @@ static struct mfd_cell axp288_cells[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell axp803_cells[] = {
|
||||
static const struct mfd_cell axp803_cells[] = {
|
||||
{
|
||||
.name = "axp221-pek",
|
||||
.num_resources = ARRAY_SIZE(axp803_pek_resources),
|
||||
|
|
@ -854,14 +730,14 @@ static struct mfd_cell axp803_cells[] = {
|
|||
{ .name = "axp20x-regulator" },
|
||||
};
|
||||
|
||||
static struct mfd_cell axp806_cells[] = {
|
||||
static const struct mfd_cell axp806_cells[] = {
|
||||
{
|
||||
.id = 2,
|
||||
.name = "axp20x-regulator",
|
||||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell axp809_cells[] = {
|
||||
static const struct mfd_cell axp809_cells[] = {
|
||||
{
|
||||
.name = "axp221-pek",
|
||||
.num_resources = ARRAY_SIZE(axp809_pek_resources),
|
||||
|
|
@ -872,7 +748,7 @@ static struct mfd_cell axp809_cells[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell axp813_cells[] = {
|
||||
static const struct mfd_cell axp813_cells[] = {
|
||||
{
|
||||
.name = "axp221-pek",
|
||||
.num_resources = ARRAY_SIZE(axp803_pek_resources),
|
||||
|
|
@ -882,7 +758,13 @@ static struct mfd_cell axp813_cells[] = {
|
|||
}, {
|
||||
.name = "axp20x-gpio",
|
||||
.of_compatible = "x-powers,axp813-gpio",
|
||||
}
|
||||
}, {
|
||||
.name = "axp813-adc",
|
||||
.of_compatible = "x-powers,axp813-adc",
|
||||
}, {
|
||||
.name = "axp20x-battery-power-supply",
|
||||
.of_compatible = "x-powers,axp813-battery-power-supply",
|
||||
},
|
||||
};
|
||||
|
||||
static struct axp20x_dev *axp20x_pm_power_off;
|
||||
|
|
|
|||
|
|
@ -112,12 +112,16 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
|
|||
|
||||
mutex_init(&ec_dev->lock);
|
||||
|
||||
cros_ec_query_all(ec_dev);
|
||||
err = cros_ec_query_all(ec_dev);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot identify the EC: error %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (ec_dev->irq) {
|
||||
err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
"chromeos-ec", ec_dev);
|
||||
err = devm_request_threaded_irq(dev, ec_dev->irq, NULL,
|
||||
ec_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
"chromeos-ec", ec_dev);
|
||||
if (err) {
|
||||
dev_err(dev, "Failed to request IRQ %d: %d",
|
||||
ec_dev->irq, err);
|
||||
|
|
@ -131,7 +135,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
|
|||
dev_err(dev,
|
||||
"Failed to register Embedded Controller subdevice %d\n",
|
||||
err);
|
||||
goto fail_mfd;
|
||||
return err;
|
||||
}
|
||||
|
||||
if (ec_dev->max_passthru) {
|
||||
|
|
@ -149,7 +153,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
|
|||
dev_err(dev,
|
||||
"Failed to register Power Delivery subdevice %d\n",
|
||||
err);
|
||||
goto fail_mfd;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -158,7 +162,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
|
|||
if (err) {
|
||||
mfd_remove_devices(dev);
|
||||
dev_err(dev, "Failed to register sub-devices\n");
|
||||
goto fail_mfd;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -173,14 +177,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
|
|||
|
||||
dev_info(dev, "Chrome EC device registered\n");
|
||||
|
||||
cros_ec_acpi_install_gpe_handler(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
fail_mfd:
|
||||
if (ec_dev->irq)
|
||||
free_irq(ec_dev->irq, ec_dev);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(cros_ec_register);
|
||||
|
||||
|
|
@ -188,11 +185,6 @@ int cros_ec_remove(struct cros_ec_device *ec_dev)
|
|||
{
|
||||
mfd_remove_devices(ec_dev->dev);
|
||||
|
||||
cros_ec_acpi_remove_gpe_handler();
|
||||
|
||||
if (ec_dev->irq)
|
||||
free_irq(ec_dev->irq, ec_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cros_ec_remove);
|
||||
|
|
@ -204,14 +196,9 @@ int cros_ec_suspend(struct cros_ec_device *ec_dev)
|
|||
int ret;
|
||||
u8 sleep_event;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) {
|
||||
sleep_event = HOST_SLEEP_EVENT_S3_SUSPEND;
|
||||
} else {
|
||||
sleep_event = HOST_SLEEP_EVENT_S0IX_SUSPEND;
|
||||
|
||||
/* Clearing the GPE status for any pending event */
|
||||
cros_ec_acpi_clear_gpe();
|
||||
}
|
||||
sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ?
|
||||
HOST_SLEEP_EVENT_S3_SUSPEND :
|
||||
HOST_SLEEP_EVENT_S0IX_SUSPEND;
|
||||
|
||||
ret = cros_ec_sleep_event(ec_dev, sleep_event);
|
||||
if (ret < 0)
|
||||
|
|
|
|||
|
|
@ -1,103 +0,0 @@
|
|||
/*
|
||||
* ChromeOS EC multi-function device
|
||||
*
|
||||
* Copyright (C) 2017 Google, Inc
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* The ChromeOS EC multi function device is used to mux all the requests
|
||||
* to the EC device for its multiple features: keyboard controller,
|
||||
* battery charging and regulator control, firmware update.
|
||||
*/
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#define ACPI_LID_DEVICE "LID0"
|
||||
|
||||
static int ec_wake_gpe = -EINVAL;
|
||||
|
||||
/*
|
||||
* This handler indicates to ACPI core that this GPE should stay enabled for
|
||||
* lid to work in suspend to idle path.
|
||||
*/
|
||||
static u32 cros_ec_gpe_handler(acpi_handle gpe_device, u32 gpe_number,
|
||||
void *data)
|
||||
{
|
||||
return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get ACPI GPE for LID0 device.
|
||||
*/
|
||||
static int cros_ec_get_ec_wake_gpe(struct device *dev)
|
||||
{
|
||||
struct acpi_device *cros_acpi_dev;
|
||||
struct acpi_device *adev;
|
||||
acpi_handle handle;
|
||||
acpi_status status;
|
||||
int ret;
|
||||
|
||||
cros_acpi_dev = ACPI_COMPANION(dev);
|
||||
|
||||
if (!cros_acpi_dev || !cros_acpi_dev->parent ||
|
||||
!cros_acpi_dev->parent->handle)
|
||||
return -EINVAL;
|
||||
|
||||
status = acpi_get_handle(cros_acpi_dev->parent->handle, ACPI_LID_DEVICE,
|
||||
&handle);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EINVAL;
|
||||
|
||||
ret = acpi_bus_get_device(handle, &adev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return adev->wakeup.gpe_number;
|
||||
}
|
||||
|
||||
int cros_ec_acpi_install_gpe_handler(struct device *dev)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
ec_wake_gpe = cros_ec_get_ec_wake_gpe(dev);
|
||||
|
||||
if (ec_wake_gpe < 0)
|
||||
return ec_wake_gpe;
|
||||
|
||||
status = acpi_install_gpe_handler(NULL, ec_wake_gpe,
|
||||
ACPI_GPE_EDGE_TRIGGERED,
|
||||
&cros_ec_gpe_handler, NULL);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
dev_info(dev, "Initialized, GPE = 0x%x\n", ec_wake_gpe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cros_ec_acpi_remove_gpe_handler(void)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
if (ec_wake_gpe < 0)
|
||||
return;
|
||||
|
||||
status = acpi_remove_gpe_handler(NULL, ec_wake_gpe,
|
||||
&cros_ec_gpe_handler);
|
||||
if (ACPI_FAILURE(status))
|
||||
pr_err("failed to remove gpe handler\n");
|
||||
}
|
||||
|
||||
void cros_ec_acpi_clear_gpe(void)
|
||||
{
|
||||
if (ec_wake_gpe < 0)
|
||||
return;
|
||||
|
||||
acpi_clear_gpe(NULL, ec_wake_gpe);
|
||||
}
|
||||
|
|
@ -113,10 +113,10 @@ static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
|
|||
dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
|
||||
ret, msg->result);
|
||||
memset(ec->features, 0, sizeof(ec->features));
|
||||
} else {
|
||||
memcpy(ec->features, msg->data, sizeof(ec->features));
|
||||
}
|
||||
|
||||
memcpy(ec->features, msg->data, sizeof(ec->features));
|
||||
|
||||
dev_dbg(ec->dev, "EC features %08x %08x\n",
|
||||
ec->features[0], ec->features[1]);
|
||||
|
||||
|
|
@ -262,13 +262,6 @@ static const struct file_operations fops = {
|
|||
#endif
|
||||
};
|
||||
|
||||
static void __remove(struct device *dev)
|
||||
{
|
||||
struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
|
||||
class_dev);
|
||||
kfree(ec);
|
||||
}
|
||||
|
||||
static void cros_ec_sensors_register(struct cros_ec_dev *ec)
|
||||
{
|
||||
/*
|
||||
|
|
@ -383,12 +376,16 @@ error:
|
|||
kfree(msg);
|
||||
}
|
||||
|
||||
static const struct mfd_cell cros_ec_rtc_cells[] = {
|
||||
{ .name = "cros-ec-rtc" }
|
||||
};
|
||||
|
||||
static int ec_device_probe(struct platform_device *pdev)
|
||||
{
|
||||
int retval = -ENOMEM;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct cros_ec_platform *ec_platform = dev_get_platdata(dev);
|
||||
struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);
|
||||
struct cros_ec_dev *ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL);
|
||||
|
||||
if (!ec)
|
||||
return retval;
|
||||
|
|
@ -410,7 +407,6 @@ static int ec_device_probe(struct platform_device *pdev)
|
|||
ec->class_dev.devt = MKDEV(ec_major, pdev->id);
|
||||
ec->class_dev.class = &cros_class;
|
||||
ec->class_dev.parent = dev;
|
||||
ec->class_dev.release = __remove;
|
||||
|
||||
retval = dev_set_name(&ec->class_dev, "%s", ec_platform->ec_name);
|
||||
if (retval) {
|
||||
|
|
@ -422,6 +418,18 @@ static int ec_device_probe(struct platform_device *pdev)
|
|||
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
|
||||
cros_ec_sensors_register(ec);
|
||||
|
||||
/* Check whether this EC instance has RTC host command support */
|
||||
if (cros_ec_check_features(ec, EC_FEATURE_RTC)) {
|
||||
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
|
||||
cros_ec_rtc_cells,
|
||||
ARRAY_SIZE(cros_ec_rtc_cells),
|
||||
NULL, 0, NULL);
|
||||
if (retval)
|
||||
dev_err(ec->dev,
|
||||
"failed to add cros-ec-rtc device: %d\n",
|
||||
retval);
|
||||
}
|
||||
|
||||
/* Take control of the lightbar from the EC. */
|
||||
lb_manual_suspend_ctrl(ec, 1);
|
||||
|
||||
|
|
@ -456,9 +464,17 @@ static int ec_device_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ec_device_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
/* Be sure to clear up debugfs delayed works */
|
||||
cros_ec_debugfs_remove(ec);
|
||||
}
|
||||
|
||||
static const struct platform_device_id cros_ec_id[] = {
|
||||
{ DRV_NAME, 0 },
|
||||
{ /* sentinel */ },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, cros_ec_id);
|
||||
|
||||
|
|
@ -466,6 +482,8 @@ static __maybe_unused int ec_device_suspend(struct device *dev)
|
|||
{
|
||||
struct cros_ec_dev *ec = dev_get_drvdata(dev);
|
||||
|
||||
cros_ec_debugfs_suspend(ec);
|
||||
|
||||
lb_suspend(ec);
|
||||
|
||||
return 0;
|
||||
|
|
@ -475,6 +493,8 @@ static __maybe_unused int ec_device_resume(struct device *dev)
|
|||
{
|
||||
struct cros_ec_dev *ec = dev_get_drvdata(dev);
|
||||
|
||||
cros_ec_debugfs_resume(ec);
|
||||
|
||||
lb_resume(ec);
|
||||
|
||||
return 0;
|
||||
|
|
@ -494,6 +514,7 @@ static struct platform_driver cros_ec_dev_driver = {
|
|||
},
|
||||
.probe = ec_device_probe,
|
||||
.remove = ec_device_remove,
|
||||
.shutdown = ec_device_shutdown,
|
||||
};
|
||||
|
||||
static int __init cros_ec_dev_init(void)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue