diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-14 13:39:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-14 13:39:08 -0400 |
commit | ebcf5bb28241fe3ddc9e786e3816848a10f688b8 (patch) | |
tree | 28c8ce0f20c690b0ac2492e034fab34ad89aa9d1 | |
parent | 414147d99b928c574ed76e9374a5d2cb77866a29 (diff) | |
parent | ed835136ee679dc528333c454ca4d1543c5aab76 (diff) |
Merge tag 'mfd-next-5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones:
"Core Framework:
- Document (kerneldoc) core mfd_add_devices() API
New Drivers:
- Altera SOCFPGA System Manager
- Maxim MAX77650/77651 PMIC
- Maxim MAX77663 PMIC
- ST Multi-Function eXpander (STMFX)
New Device Support:
- LEDs support in Intel Cherry Trail Whiskey Cove PMIC
- RTC support in SAMSUNG Electronics S2MPA01 PMIC
- SAM9X60 support in Atmel HLCDC (High-end LCD Controller)
- USB X-Powers AXP 8xx PMICs
- Integrated Sensor Hub (ISH) in ChromeOS EC
- USB PD Logger in ChromeOS EC
- AXP223 in X-Powers AXP series PMICs
- Power Supply in X-Powers AXP 803 PMICs
- Comet Lake in Intel Low Power Subsystem
- Fingerprint MCU in ChromeOS EC
- Touchpad MCU in ChromeOS EC
- Move TI LM3532 support to LED
New Functionality:
- max77650, max77620: Add/extend DT support
- max77620 power-off
- syscon clocking
- croc_ec host sleep event
Fix-ups:
- Trivial; Formatting, spelling, etc; Kconfig, sec-core, ab8500-debugfs
- Remove unused functionality; rk808, da9063-*
- SPDX conversion; da9063-*, atmel-*,
- Adapt/add new register definitions; cs47l35-tables, cs47l90-tables, imx6q-iomuxc-gpr
- Fix-up DT bindings; ti-lmu, cirrus,lochnagar
- Simply obtaining driver data; ssbi, t7l66xb, tc6387xb, tc6393xb
Bug Fixes:
- Fix incorrect defined values; max77620, da9063
- Fix device initialisation; twl6040
- Reset device on init; intel-lpss
- Fix build warnings when !OF; sun6i-prcm
- Register OF match tables; tps65912-spi
- Fix DMI matching; intel_quark_i2c_gpio"
* tag 'mfd-next-5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (65 commits)
mfd: Use dev_get_drvdata() directly
mfd: cros_ec: Instantiate properly CrOS Touchpad MCU device
mfd: cros_ec: Instantiate properly CrOS FP MCU device
mfd: cros_ec: Update the EC feature codes
mfd: intel-lpss: Add Intel Comet Lake PCI IDs
mfd: lochnagar: Add links to binding docs for sound and hwmon
mfd: ab8500-debugfs: Fix a typo ("deubgfs")
mfd: imx6sx: Add MQS register definition for iomuxc gpr
dt-bindings: mfd: LMU: Fix lm3632 dt binding example
mfd: intel_quark_i2c_gpio: Adjust IOT2000 matching
mfd: da9063: Fix OTP control register names to match datasheets for DA9063/63L
mfd: tps65912-spi: Add missing of table registration
mfd: axp20x: Add USB power supply mfd cell to AXP803
mfd: sun6i-prcm: Fix build warning for non-OF configurations
mfd: intel-lpss: Set the device in reset state when init
platform/chrome: Add support for v1 of host sleep event
mfd: cros_ec: Add host_sleep_event_v1 command
mfd: cros_ec: Instantiate the CrOS USB PD logger driver
mfd: cs47l90: Make DAC_AEC_CONTROL_2 readable
mfd: cs47l35: Make DAC_AEC_CONTROL_2 readable
...
79 files changed, 3745 insertions, 219 deletions
diff --git a/Documentation/devicetree/bindings/arm/altera/socfpga-system.txt b/Documentation/devicetree/bindings/arm/altera/socfpga-system.txt index f4d04a067282..82edbaaa3f85 100644 --- a/Documentation/devicetree/bindings/arm/altera/socfpga-system.txt +++ b/Documentation/devicetree/bindings/arm/altera/socfpga-system.txt | |||
@@ -11,3 +11,15 @@ Example: | |||
11 | reg = <0xffd08000 0x1000>; | 11 | reg = <0xffd08000 0x1000>; |
12 | cpu1-start-addr = <0xffd080c4>; | 12 | cpu1-start-addr = <0xffd080c4>; |
13 | }; | 13 | }; |
14 | |||
15 | ARM64 - Stratix10 | ||
16 | Required properties: | ||
17 | - compatible : "altr,sys-mgr-s10" | ||
18 | - reg : Should contain 1 register range(address and length) | ||
19 | for system manager register. | ||
20 | |||
21 | Example: | ||
22 | sysmgr@ffd12000 { | ||
23 | compatible = "altr,sys-mgr-s10"; | ||
24 | reg = <0xffd12000 0x228>; | ||
25 | }; | ||
diff --git a/Documentation/devicetree/bindings/arm/stm32/stm32-syscon.txt b/Documentation/devicetree/bindings/arm/stm32/stm32-syscon.txt index 99980aee26e5..c92d411fd023 100644 --- a/Documentation/devicetree/bindings/arm/stm32/stm32-syscon.txt +++ b/Documentation/devicetree/bindings/arm/stm32/stm32-syscon.txt | |||
@@ -5,10 +5,12 @@ Properties: | |||
5 | - " st,stm32mp157-syscfg " - for stm32mp157 based SoCs, | 5 | - " st,stm32mp157-syscfg " - for stm32mp157 based SoCs, |
6 | second value must be always "syscon". | 6 | second value must be always "syscon". |
7 | - reg : offset and length of the register set. | 7 | - reg : offset and length of the register set. |
8 | - clocks: phandle to the syscfg clock | ||
8 | 9 | ||
9 | Example: | 10 | Example: |
10 | syscfg: syscon@50020000 { | 11 | syscfg: syscon@50020000 { |
11 | compatible = "st,stm32mp157-syscfg", "syscon"; | 12 | compatible = "st,stm32mp157-syscfg", "syscon"; |
12 | reg = <0x50020000 0x400>; | 13 | reg = <0x50020000 0x400>; |
14 | clocks = <&rcc SYSCFG>; | ||
13 | }; | 15 | }; |
14 | 16 | ||
diff --git a/Documentation/devicetree/bindings/input/max77650-onkey.txt b/Documentation/devicetree/bindings/input/max77650-onkey.txt new file mode 100644 index 000000000000..477dc74f452a --- /dev/null +++ b/Documentation/devicetree/bindings/input/max77650-onkey.txt | |||
@@ -0,0 +1,26 @@ | |||
1 | Onkey driver for MAX77650 PMIC from Maxim Integrated. | ||
2 | |||
3 | This module is part of the MAX77650 MFD device. For more details | ||
4 | see Documentation/devicetree/bindings/mfd/max77650.txt. | ||
5 | |||
6 | The onkey controller is represented as a sub-node of the PMIC node on | ||
7 | the device tree. | ||
8 | |||
9 | Required properties: | ||
10 | -------------------- | ||
11 | - compatible: Must be "maxim,max77650-onkey". | ||
12 | |||
13 | Optional properties: | ||
14 | - linux,code: The key-code to be reported when the key is pressed. | ||
15 | Defaults to KEY_POWER. | ||
16 | - maxim,onkey-slide: The system's button is a slide switch, not the default | ||
17 | push button. | ||
18 | |||
19 | Example: | ||
20 | -------- | ||
21 | |||
22 | onkey { | ||
23 | compatible = "maxim,max77650-onkey"; | ||
24 | linux,code = <KEY_END>; | ||
25 | maxim,onkey-slide; | ||
26 | }; | ||
diff --git a/Documentation/devicetree/bindings/leds/leds-max77650.txt b/Documentation/devicetree/bindings/leds/leds-max77650.txt new file mode 100644 index 000000000000..3a67115cc1da --- /dev/null +++ b/Documentation/devicetree/bindings/leds/leds-max77650.txt | |||
@@ -0,0 +1,57 @@ | |||
1 | LED driver for MAX77650 PMIC from Maxim Integrated. | ||
2 | |||
3 | This module is part of the MAX77650 MFD device. For more details | ||
4 | see Documentation/devicetree/bindings/mfd/max77650.txt. | ||
5 | |||
6 | The LED controller is represented as a sub-node of the PMIC node on | ||
7 | the device tree. | ||
8 | |||
9 | This device has three current sinks. | ||
10 | |||
11 | Required properties: | ||
12 | -------------------- | ||
13 | - compatible: Must be "maxim,max77650-led" | ||
14 | - #address-cells: Must be <1>. | ||
15 | - #size-cells: Must be <0>. | ||
16 | |||
17 | Each LED is represented as a sub-node of the LED-controller node. Up to | ||
18 | three sub-nodes can be defined. | ||
19 | |||
20 | Required properties of the sub-node: | ||
21 | ------------------------------------ | ||
22 | |||
23 | - reg: Must be <0>, <1> or <2>. | ||
24 | |||
25 | Optional properties of the sub-node: | ||
26 | ------------------------------------ | ||
27 | |||
28 | - label: See Documentation/devicetree/bindings/leds/common.txt | ||
29 | - linux,default-trigger: See Documentation/devicetree/bindings/leds/common.txt | ||
30 | |||
31 | For more details, please refer to the generic GPIO DT binding document | ||
32 | <devicetree/bindings/gpio/gpio.txt>. | ||
33 | |||
34 | Example: | ||
35 | -------- | ||
36 | |||
37 | leds { | ||
38 | compatible = "maxim,max77650-led"; | ||
39 | #address-cells = <1>; | ||
40 | #size-cells = <0>; | ||
41 | |||
42 | led@0 { | ||
43 | reg = <0>; | ||
44 | label = "blue:usr0"; | ||
45 | }; | ||
46 | |||
47 | led@1 { | ||
48 | reg = <1>; | ||
49 | label = "red:usr1"; | ||
50 | linux,default-trigger = "heartbeat"; | ||
51 | }; | ||
52 | |||
53 | led@2 { | ||
54 | reg = <2>; | ||
55 | label = "green:usr2"; | ||
56 | }; | ||
57 | }; | ||
diff --git a/Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt b/Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt index 3f643ef121ff..5f8880cc757e 100644 --- a/Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt | |||
@@ -7,6 +7,7 @@ Required properties: | |||
7 | "atmel,sama5d2-hlcdc" | 7 | "atmel,sama5d2-hlcdc" |
8 | "atmel,sama5d3-hlcdc" | 8 | "atmel,sama5d3-hlcdc" |
9 | "atmel,sama5d4-hlcdc" | 9 | "atmel,sama5d4-hlcdc" |
10 | "microchip,sam9x60-hlcdc" | ||
10 | - reg: base address and size of the HLCDC device registers. | 11 | - reg: base address and size of the HLCDC device registers. |
11 | - clock-names: the name of the 3 clocks requested by the HLCDC device. | 12 | - clock-names: the name of the 3 clocks requested by the HLCDC device. |
12 | Should contain "periph_clk", "sys_clk" and "slow_clk". | 13 | Should contain "periph_clk", "sys_clk" and "slow_clk". |
diff --git a/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.txt b/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.txt index 004b0158cf4d..3bf92ad37fa1 100644 --- a/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.txt +++ b/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.txt | |||
@@ -19,6 +19,8 @@ And these documents for the required sub-node binding details: | |||
19 | [4] Clock: ../clock/cirrus,lochnagar.txt | 19 | [4] Clock: ../clock/cirrus,lochnagar.txt |
20 | [5] Pinctrl: ../pinctrl/cirrus,lochnagar.txt | 20 | [5] Pinctrl: ../pinctrl/cirrus,lochnagar.txt |
21 | [6] Regulator: ../regulator/cirrus,lochnagar.txt | 21 | [6] Regulator: ../regulator/cirrus,lochnagar.txt |
22 | [7] Sound: ../sound/cirrus,lochnagar.txt | ||
23 | [8] Hardware Monitor: ../hwmon/cirrus,lochnagar.txt | ||
22 | 24 | ||
23 | Required properties: | 25 | Required properties: |
24 | 26 | ||
@@ -41,6 +43,11 @@ Optional sub-nodes: | |||
41 | - Bindings for the regulator components, see [6]. Only available on | 43 | - Bindings for the regulator components, see [6]. Only available on |
42 | Lochnagar 2. | 44 | Lochnagar 2. |
43 | 45 | ||
46 | - lochnagar-sc : Binding for the sound card components, see [7]. | ||
47 | Only available on Lochnagar 2. | ||
48 | - lochnagar-hwmon : Binding for the hardware monitor components, see [8]. | ||
49 | Only available on Lochnagar 2. | ||
50 | |||
44 | Optional properties: | 51 | Optional properties: |
45 | 52 | ||
46 | - present-gpios : Host present line, indicating the presence of a | 53 | - present-gpios : Host present line, indicating the presence of a |
@@ -65,4 +72,14 @@ lochnagar: lochnagar@22 { | |||
65 | compatible = "cirrus,lochnagar-pinctrl"; | 72 | compatible = "cirrus,lochnagar-pinctrl"; |
66 | ... | 73 | ... |
67 | }; | 74 | }; |
75 | |||
76 | lochnagar-sc { | ||
77 | compatible = "cirrus,lochnagar2-soundcard"; | ||
78 | ... | ||
79 | }; | ||
80 | |||
81 | lochnagar-hwmon { | ||
82 | compatible = "cirrus,lochnagar2-hwmon"; | ||
83 | ... | ||
84 | }; | ||
68 | }; | 85 | }; |
diff --git a/Documentation/devicetree/bindings/mfd/max77620.txt b/Documentation/devicetree/bindings/mfd/max77620.txt index 9c16d51cc15b..5a642a51d58e 100644 --- a/Documentation/devicetree/bindings/mfd/max77620.txt +++ b/Documentation/devicetree/bindings/mfd/max77620.txt | |||
@@ -4,7 +4,8 @@ Required properties: | |||
4 | ------------------- | 4 | ------------------- |
5 | - compatible: Must be one of | 5 | - compatible: Must be one of |
6 | "maxim,max77620" | 6 | "maxim,max77620" |
7 | "maxim,max20024". | 7 | "maxim,max20024" |
8 | "maxim,max77663" | ||
8 | - reg: I2C device address. | 9 | - reg: I2C device address. |
9 | 10 | ||
10 | Optional properties: | 11 | Optional properties: |
@@ -17,6 +18,11 @@ Optional properties: | |||
17 | IRQ numbers for different interrupt source of MAX77620 | 18 | IRQ numbers for different interrupt source of MAX77620 |
18 | are defined at dt-bindings/mfd/max77620.h. | 19 | are defined at dt-bindings/mfd/max77620.h. |
19 | 20 | ||
21 | - system-power-controller: Indicates that this PMIC is controlling the | ||
22 | system power, see [1] for more details. | ||
23 | |||
24 | [1] Documentation/devicetree/bindings/power/power-controller.txt | ||
25 | |||
20 | Optional subnodes and their properties: | 26 | Optional subnodes and their properties: |
21 | ======================================= | 27 | ======================================= |
22 | 28 | ||
@@ -105,6 +111,7 @@ Optional properties: | |||
105 | Here supported time periods by device in microseconds are as follows: | 111 | Here supported time periods by device in microseconds are as follows: |
106 | MAX77620 supports 40, 80, 160, 320, 640, 1280, 2560 and 5120 microseconds. | 112 | MAX77620 supports 40, 80, 160, 320, 640, 1280, 2560 and 5120 microseconds. |
107 | MAX20024 supports 20, 40, 80, 160, 320, 640, 1280 and 2540 microseconds. | 113 | MAX20024 supports 20, 40, 80, 160, 320, 640, 1280 and 2540 microseconds. |
114 | MAX77663 supports 20, 40, 80, 160, 320, 640, 1280 and 2540 microseconds. | ||
108 | 115 | ||
109 | -maxim,power-ok-control: configure map power ok bit | 116 | -maxim,power-ok-control: configure map power ok bit |
110 | 1: Enables POK(Power OK) to control nRST_IO and GPIO1 | 117 | 1: Enables POK(Power OK) to control nRST_IO and GPIO1 |
diff --git a/Documentation/devicetree/bindings/mfd/max77650.txt b/Documentation/devicetree/bindings/mfd/max77650.txt new file mode 100644 index 000000000000..b529d8d19335 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/max77650.txt | |||
@@ -0,0 +1,46 @@ | |||
1 | MAX77650 ultra low-power PMIC from Maxim Integrated. | ||
2 | |||
3 | Required properties: | ||
4 | ------------------- | ||
5 | - compatible: Must be "maxim,max77650" | ||
6 | - reg: I2C device address. | ||
7 | - interrupts: The interrupt on the parent the controller is | ||
8 | connected to. | ||
9 | - interrupt-controller: Marks the device node as an interrupt controller. | ||
10 | - #interrupt-cells: Must be <2>. | ||
11 | |||
12 | - gpio-controller: Marks the device node as a gpio controller. | ||
13 | - #gpio-cells: Must be <2>. The first cell is the pin number and | ||
14 | the second cell is used to specify the gpio active | ||
15 | state. | ||
16 | |||
17 | Optional properties: | ||
18 | -------------------- | ||
19 | gpio-line-names: Single string containing the name of the GPIO line. | ||
20 | |||
21 | The GPIO-controller module is represented as part of the top-level PMIC | ||
22 | node. The device exposes a single GPIO line. | ||
23 | |||
24 | For device-tree bindings of other sub-modules (regulator, power supply, | ||
25 | LEDs and onkey) refer to the binding documents under the respective | ||
26 | sub-system directories. | ||
27 | |||
28 | For more details on GPIO bindings, please refer to the generic GPIO DT | ||
29 | binding document <devicetree/bindings/gpio/gpio.txt>. | ||
30 | |||
31 | Example: | ||
32 | -------- | ||
33 | |||
34 | pmic@48 { | ||
35 | compatible = "maxim,max77650"; | ||
36 | reg = <0x48>; | ||
37 | |||
38 | interrupt-controller; | ||
39 | interrupt-parent = <&gpio2>; | ||
40 | #interrupt-cells = <2>; | ||
41 | interrupts = <3 IRQ_TYPE_LEVEL_LOW>; | ||
42 | |||
43 | gpio-controller; | ||
44 | #gpio-cells = <2>; | ||
45 | gpio-line-names = "max77650-charger"; | ||
46 | }; | ||
diff --git a/Documentation/devicetree/bindings/mfd/stmfx.txt b/Documentation/devicetree/bindings/mfd/stmfx.txt new file mode 100644 index 000000000000..f0c2f7fcf5c7 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/stmfx.txt | |||
@@ -0,0 +1,28 @@ | |||
1 | STMicroelectonics Multi-Function eXpander (STMFX) Core bindings | ||
2 | |||
3 | ST Multi-Function eXpander (STMFX) is a slave controller using I2C for | ||
4 | communication with the main MCU. Its main features are GPIO expansion, main | ||
5 | MCU IDD measurement (IDD is the amount of current that flows through VDD) and | ||
6 | resistive touchscreen controller. | ||
7 | |||
8 | Required properties: | ||
9 | - compatible: should be "st,stmfx-0300". | ||
10 | - reg: I2C slave address of the device. | ||
11 | - interrupts: interrupt specifier triggered by MFX_IRQ_OUT signal. | ||
12 | Please refer to ../interrupt-controller/interrupt.txt | ||
13 | |||
14 | Optional properties: | ||
15 | - drive-open-drain: configure MFX_IRQ_OUT as open drain. | ||
16 | - vdd-supply: phandle of the regulator supplying STMFX. | ||
17 | |||
18 | Example: | ||
19 | |||
20 | stmfx: stmfx@42 { | ||
21 | compatible = "st,stmfx-0300"; | ||
22 | reg = <0x42>; | ||
23 | interrupts = <8 IRQ_TYPE_EDGE_RISING>; | ||
24 | interrupt-parent = <&gpioi>; | ||
25 | vdd-supply = <&v3v3>; | ||
26 | }; | ||
27 | |||
28 | Please refer to ../pinctrl/pinctrl-stmfx.txt for STMFX GPIO expander function bindings. | ||
diff --git a/Documentation/devicetree/bindings/mfd/ti-lmu.txt b/Documentation/devicetree/bindings/mfd/ti-lmu.txt index 980394d701a7..86ca786d54fc 100644 --- a/Documentation/devicetree/bindings/mfd/ti-lmu.txt +++ b/Documentation/devicetree/bindings/mfd/ti-lmu.txt | |||
@@ -104,8 +104,8 @@ lm3632@11 { | |||
104 | regulators { | 104 | regulators { |
105 | compatible = "ti,lm363x-regulator"; | 105 | compatible = "ti,lm363x-regulator"; |
106 | 106 | ||
107 | ti,lcm-en1-gpio = <&pioC 0 GPIO_ACTIVE_HIGH>; /* PC0 */ | 107 | enable-gpios = <&pioC 0 GPIO_ACTIVE_HIGH>, |
108 | ti,lcm-en2-gpio = <&pioC 1 GPIO_ACTIVE_HIGH>; /* PC1 */ | 108 | <&pioC 1 GPIO_ACTIVE_HIGH>; |
109 | 109 | ||
110 | vboost { | 110 | vboost { |
111 | regulator-name = "lcd_boost"; | 111 | regulator-name = "lcd_boost"; |
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-stmfx.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-stmfx.txt new file mode 100644 index 000000000000..c1b4c1819b84 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-stmfx.txt | |||
@@ -0,0 +1,116 @@ | |||
1 | STMicroelectronics Multi-Function eXpander (STMFX) GPIO expander bindings | ||
2 | |||
3 | ST Multi-Function eXpander (STMFX) offers up to 24 GPIOs expansion. | ||
4 | Please refer to ../mfd/stmfx.txt for STMFX Core bindings. | ||
5 | |||
6 | Required properties: | ||
7 | - compatible: should be "st,stmfx-0300-pinctrl". | ||
8 | - #gpio-cells: should be <2>, the first cell is the GPIO number and the second | ||
9 | cell is the gpio flags in accordance with <dt-bindings/gpio/gpio.h>. | ||
10 | - gpio-controller: marks the device as a GPIO controller. | ||
11 | - #interrupt-cells: should be <2>, the first cell is the GPIO number and the | ||
12 | second cell is the interrupt flags in accordance with | ||
13 | <dt-bindings/interrupt-controller/irq.h>. | ||
14 | - interrupt-controller: marks the device as an interrupt controller. | ||
15 | - gpio-ranges: specifies the mapping between gpio controller and pin | ||
16 | controller pins. Check "Concerning gpio-ranges property" below. | ||
17 | Please refer to ../gpio/gpio.txt. | ||
18 | |||
19 | Please refer to pinctrl-bindings.txt for pin configuration. | ||
20 | |||
21 | Required properties for pin configuration sub-nodes: | ||
22 | - pins: list of pins to which the configuration applies. | ||
23 | |||
24 | Optional properties for pin configuration sub-nodes (pinconf-generic ones): | ||
25 | - bias-disable: disable any bias on the pin. | ||
26 | - bias-pull-up: the pin will be pulled up. | ||
27 | - bias-pull-pin-default: use the pin-default pull state. | ||
28 | - bias-pull-down: the pin will be pulled down. | ||
29 | - drive-open-drain: the pin will be driven with open drain. | ||
30 | - drive-push-pull: the pin will be driven actively high and low. | ||
31 | - output-high: the pin will be configured as an output driving high level. | ||
32 | - output-low: the pin will be configured as an output driving low level. | ||
33 | |||
34 | Note that STMFX pins[15:0] are called "gpio[15:0]", and STMFX pins[23:16] are | ||
35 | called "agpio[7:0]". Example, to refer to pin 18 of STMFX, use "agpio2". | ||
36 | |||
37 | Concerning gpio-ranges property: | ||
38 | - if all STMFX pins[24:0] are available (no other STMFX function in use), you | ||
39 | should use gpio-ranges = <&stmfx_pinctrl 0 0 24>; | ||
40 | - if agpio[3:0] are not available (STMFX Touchscreen function in use), you | ||
41 | should use gpio-ranges = <&stmfx_pinctrl 0 0 16>, <&stmfx_pinctrl 20 20 4>; | ||
42 | - if agpio[7:4] are not available (STMFX IDD function in use), you | ||
43 | should use gpio-ranges = <&stmfx_pinctrl 0 0 20>; | ||
44 | |||
45 | |||
46 | Example: | ||
47 | |||
48 | stmfx: stmfx@42 { | ||
49 | ... | ||
50 | |||
51 | stmfx_pinctrl: stmfx-pin-controller { | ||
52 | compatible = "st,stmfx-0300-pinctrl"; | ||
53 | #gpio-cells = <2>; | ||
54 | #interrupt-cells = <2>; | ||
55 | gpio-controller; | ||
56 | interrupt-controller; | ||
57 | gpio-ranges = <&stmfx_pinctrl 0 0 24>; | ||
58 | |||
59 | joystick_pins: joystick { | ||
60 | pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4"; | ||
61 | drive-push-pull; | ||
62 | bias-pull-up; | ||
63 | }; | ||
64 | }; | ||
65 | }; | ||
66 | |||
67 | Example of STMFX GPIO consumers: | ||
68 | |||
69 | joystick { | ||
70 | compatible = "gpio-keys"; | ||
71 | #address-cells = <1>; | ||
72 | #size-cells = <0>; | ||
73 | pinctrl-0 = <&joystick_pins>; | ||
74 | pinctrl-names = "default"; | ||
75 | button-0 { | ||
76 | label = "JoySel"; | ||
77 | linux,code = <KEY_ENTER>; | ||
78 | interrupt-parent = <&stmfx_pinctrl>; | ||
79 | interrupts = <0 IRQ_TYPE_EDGE_RISING>; | ||
80 | }; | ||
81 | button-1 { | ||
82 | label = "JoyDown"; | ||
83 | linux,code = <KEY_DOWN>; | ||
84 | interrupt-parent = <&stmfx_pinctrl>; | ||
85 | interrupts = <1 IRQ_TYPE_EDGE_RISING>; | ||
86 | }; | ||
87 | button-2 { | ||
88 | label = "JoyLeft"; | ||
89 | linux,code = <KEY_LEFT>; | ||
90 | interrupt-parent = <&stmfx_pinctrl>; | ||
91 | interrupts = <2 IRQ_TYPE_EDGE_RISING>; | ||
92 | }; | ||
93 | button-3 { | ||
94 | label = "JoyRight"; | ||
95 | linux,code = <KEY_RIGHT>; | ||
96 | interrupt-parent = <&stmfx_pinctrl>; | ||
97 | interrupts = <3 IRQ_TYPE_EDGE_RISING>; | ||
98 | }; | ||
99 | button-4 { | ||
100 | label = "JoyUp"; | ||
101 | linux,code = <KEY_UP>; | ||
102 | interrupt-parent = <&stmfx_pinctrl>; | ||
103 | interrupts = <4 IRQ_TYPE_EDGE_RISING>; | ||
104 | }; | ||
105 | }; | ||
106 | |||
107 | leds { | ||
108 | compatible = "gpio-leds"; | ||
109 | orange { | ||
110 | gpios = <&stmfx_pinctrl 17 1>; | ||
111 | }; | ||
112 | |||
113 | blue { | ||
114 | gpios = <&stmfx_pinctrl 19 1>; | ||
115 | }; | ||
116 | } | ||
diff --git a/Documentation/devicetree/bindings/power/supply/max77650-charger.txt b/Documentation/devicetree/bindings/power/supply/max77650-charger.txt new file mode 100644 index 000000000000..e6d0fb6ff94e --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/max77650-charger.txt | |||
@@ -0,0 +1,28 @@ | |||
1 | Battery charger driver for MAX77650 PMIC from Maxim Integrated. | ||
2 | |||
3 | This module is part of the MAX77650 MFD device. For more details | ||
4 | see Documentation/devicetree/bindings/mfd/max77650.txt. | ||
5 | |||
6 | The charger is represented as a sub-node of the PMIC node on the device tree. | ||
7 | |||
8 | Required properties: | ||
9 | -------------------- | ||
10 | - compatible: Must be "maxim,max77650-charger" | ||
11 | |||
12 | Optional properties: | ||
13 | -------------------- | ||
14 | - input-voltage-min-microvolt: Minimum CHGIN regulation voltage. Must be one | ||
15 | of: 4000000, 4100000, 4200000, 4300000, | ||
16 | 4400000, 4500000, 4600000, 4700000. | ||
17 | - input-current-limit-microamp: CHGIN input current limit (in microamps). Must | ||
18 | be one of: 95000, 190000, 285000, 380000, | ||
19 | 475000. | ||
20 | |||
21 | Example: | ||
22 | -------- | ||
23 | |||
24 | charger { | ||
25 | compatible = "maxim,max77650-charger"; | ||
26 | input-voltage-min-microvolt = <4200000>; | ||
27 | input-current-limit-microamp = <285000>; | ||
28 | }; | ||
diff --git a/MAINTAINERS b/MAINTAINERS index a8b3eefc37a2..ce573aaa04df 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -710,6 +710,12 @@ L: linux-gpio@vger.kernel.org | |||
710 | S: Maintained | 710 | S: Maintained |
711 | F: drivers/gpio/gpio-altera.c | 711 | F: drivers/gpio/gpio-altera.c |
712 | 712 | ||
713 | ALTERA SYSTEM MANAGER DRIVER | ||
714 | M: Thor Thayer <thor.thayer@linux.intel.com> | ||
715 | S: Maintained | ||
716 | F: drivers/mfd/altera-sysmgr.c | ||
717 | F: include/linux/mfd/altera-sysgmr.h | ||
718 | |||
713 | ALTERA SYSTEM RESOURCE DRIVER FOR ARRIA10 DEVKIT | 719 | ALTERA SYSTEM RESOURCE DRIVER FOR ARRIA10 DEVKIT |
714 | M: Thor Thayer <thor.thayer@linux.intel.com> | 720 | M: Thor Thayer <thor.thayer@linux.intel.com> |
715 | S: Maintained | 721 | S: Maintained |
@@ -9517,6 +9523,20 @@ S: Maintained | |||
9517 | F: Documentation/devicetree/bindings/iio/proximity/maxbotix,mb1232.txt | 9523 | F: Documentation/devicetree/bindings/iio/proximity/maxbotix,mb1232.txt |
9518 | F: drivers/iio/proximity/mb1232.c | 9524 | F: drivers/iio/proximity/mb1232.c |
9519 | 9525 | ||
9526 | MAXIM MAX77650 PMIC MFD DRIVER | ||
9527 | M: Bartosz Golaszewski <bgolaszewski@baylibre.com> | ||
9528 | L: linux-kernel@vger.kernel.org | ||
9529 | S: Maintained | ||
9530 | F: Documentation/devicetree/bindings/*/*max77650.txt | ||
9531 | F: Documentation/devicetree/bindings/*/max77650*.txt | ||
9532 | F: include/linux/mfd/max77650.h | ||
9533 | F: drivers/mfd/max77650.c | ||
9534 | F: drivers/regulator/max77650-regulator.c | ||
9535 | F: drivers/power/supply/max77650-charger.c | ||
9536 | F: drivers/input/misc/max77650-onkey.c | ||
9537 | F: drivers/leds/leds-max77650.c | ||
9538 | F: drivers/gpio/gpio-max77650.c | ||
9539 | |||
9520 | MAXIM MAX77802 PMIC REGULATOR DEVICE DRIVER | 9540 | MAXIM MAX77802 PMIC REGULATOR DEVICE DRIVER |
9521 | M: Javier Martinez Canillas <javier@dowhile0.org> | 9541 | M: Javier Martinez Canillas <javier@dowhile0.org> |
9522 | L: linux-kernel@vger.kernel.org | 9542 | L: linux-kernel@vger.kernel.org |
diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig index 3b42e0d597bd..9d42cfe85f5b 100644 --- a/arch/arm/configs/socfpga_defconfig +++ b/arch/arm/configs/socfpga_defconfig | |||
@@ -106,6 +106,7 @@ CONFIG_SENSORS_LTC2978_REGULATOR=y | |||
106 | CONFIG_WATCHDOG=y | 106 | CONFIG_WATCHDOG=y |
107 | CONFIG_DW_WATCHDOG=y | 107 | CONFIG_DW_WATCHDOG=y |
108 | CONFIG_MFD_ALTERA_A10SR=y | 108 | CONFIG_MFD_ALTERA_A10SR=y |
109 | CONFIG_MFD_ALTERA_SYSMGR=y | ||
109 | CONFIG_MFD_STMPE=y | 110 | CONFIG_MFD_STMPE=y |
110 | CONFIG_REGULATOR=y | 111 | CONFIG_REGULATOR=y |
111 | CONFIG_REGULATOR_FIXED_VOLTAGE=y | 112 | CONFIG_REGULATOR_FIXED_VOLTAGE=y |
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi index a2cec6218211..fe107ce115ef 100644 --- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi +++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi | |||
@@ -393,7 +393,7 @@ | |||
393 | }; | 393 | }; |
394 | 394 | ||
395 | sysmgr: sysmgr@ffd12000 { | 395 | sysmgr: sysmgr@ffd12000 { |
396 | compatible = "altr,sys-mgr", "syscon"; | 396 | compatible = "altr,sys-mgr-s10","altr,sys-mgr"; |
397 | reg = <0xffd12000 0x228>; | 397 | reg = <0xffd12000 0x228>; |
398 | }; | 398 | }; |
399 | 399 | ||
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 9a8718bbf6ba..74f0a199166d 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig | |||
@@ -432,6 +432,7 @@ CONFIG_MESON_WATCHDOG=m | |||
432 | CONFIG_RENESAS_WDT=y | 432 | CONFIG_RENESAS_WDT=y |
433 | CONFIG_UNIPHIER_WATCHDOG=y | 433 | CONFIG_UNIPHIER_WATCHDOG=y |
434 | CONFIG_BCM2835_WDT=y | 434 | CONFIG_BCM2835_WDT=y |
435 | CONFIG_MFD_ALTERA_SYSMGR=y | ||
435 | CONFIG_MFD_BD9571MWV=y | 436 | CONFIG_MFD_BD9571MWV=y |
436 | CONFIG_MFD_AXP20X_I2C=y | 437 | CONFIG_MFD_AXP20X_I2C=y |
437 | CONFIG_MFD_AXP20X_RSB=y | 438 | CONFIG_MFD_AXP20X_RSB=y |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 9370276fe7fe..41f08362dad3 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -1097,6 +1097,13 @@ config GPIO_MAX77620 | |||
1097 | driver also provides interrupt support for each of the gpios. | 1097 | driver also provides interrupt support for each of the gpios. |
1098 | Say yes here to enable the max77620 to be used as gpio controller. | 1098 | Say yes here to enable the max77620 to be used as gpio controller. |
1099 | 1099 | ||
1100 | config GPIO_MAX77650 | ||
1101 | tristate "Maxim MAX77650/77651 GPIO support" | ||
1102 | depends on MFD_MAX77650 | ||
1103 | help | ||
1104 | GPIO driver for MAX77650/77651 PMIC from Maxim Semiconductor. | ||
1105 | These chips have a single pin that can be configured as GPIO. | ||
1106 | |||
1100 | config GPIO_MSIC | 1107 | config GPIO_MSIC |
1101 | bool "Intel MSIC mixed signal gpio support" | 1108 | bool "Intel MSIC mixed signal gpio support" |
1102 | depends on (X86 || COMPILE_TEST) && MFD_INTEL_MSIC | 1109 | depends on (X86 || COMPILE_TEST) && MFD_INTEL_MSIC |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index db8d854f9aea..e19be766f6a6 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -80,6 +80,7 @@ obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o | |||
80 | obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o | 80 | obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o |
81 | obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o | 81 | obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o |
82 | obj-$(CONFIG_GPIO_MAX77620) += gpio-max77620.o | 82 | obj-$(CONFIG_GPIO_MAX77620) += gpio-max77620.o |
83 | obj-$(CONFIG_GPIO_MAX77650) += gpio-max77650.o | ||
83 | obj-$(CONFIG_GPIO_MB86S7X) += gpio-mb86s7x.o | 84 | obj-$(CONFIG_GPIO_MB86S7X) += gpio-mb86s7x.o |
84 | obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o | 85 | obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o |
85 | obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o | 86 | obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o |
diff --git a/drivers/gpio/gpio-max77650.c b/drivers/gpio/gpio-max77650.c new file mode 100644 index 000000000000..3f03f4e8956c --- /dev/null +++ b/drivers/gpio/gpio-max77650.c | |||
@@ -0,0 +1,190 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // | ||
3 | // Copyright (C) 2018 BayLibre SAS | ||
4 | // Author: Bartosz Golaszewski <bgolaszewski@baylibre.com> | ||
5 | // | ||
6 | // GPIO driver for MAXIM 77650/77651 charger/power-supply. | ||
7 | |||
8 | #include <linux/gpio/driver.h> | ||
9 | #include <linux/i2c.h> | ||
10 | #include <linux/mfd/max77650.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/regmap.h> | ||
14 | |||
15 | #define MAX77650_GPIO_DIR_MASK BIT(0) | ||
16 | #define MAX77650_GPIO_INVAL_MASK BIT(1) | ||
17 | #define MAX77650_GPIO_DRV_MASK BIT(2) | ||
18 | #define MAX77650_GPIO_OUTVAL_MASK BIT(3) | ||
19 | #define MAX77650_GPIO_DEBOUNCE_MASK BIT(4) | ||
20 | |||
21 | #define MAX77650_GPIO_DIR_OUT 0x00 | ||
22 | #define MAX77650_GPIO_DIR_IN BIT(0) | ||
23 | #define MAX77650_GPIO_OUT_LOW 0x00 | ||
24 | #define MAX77650_GPIO_OUT_HIGH BIT(3) | ||
25 | #define MAX77650_GPIO_DRV_OPEN_DRAIN 0x00 | ||
26 | #define MAX77650_GPIO_DRV_PUSH_PULL BIT(2) | ||
27 | #define MAX77650_GPIO_DEBOUNCE BIT(4) | ||
28 | |||
29 | #define MAX77650_GPIO_DIR_BITS(_reg) \ | ||
30 | ((_reg) & MAX77650_GPIO_DIR_MASK) | ||
31 | #define MAX77650_GPIO_INVAL_BITS(_reg) \ | ||
32 | (((_reg) & MAX77650_GPIO_INVAL_MASK) >> 1) | ||
33 | |||
34 | struct max77650_gpio_chip { | ||
35 | struct regmap *map; | ||
36 | struct gpio_chip gc; | ||
37 | int irq; | ||
38 | }; | ||
39 | |||
40 | static int max77650_gpio_direction_input(struct gpio_chip *gc, | ||
41 | unsigned int offset) | ||
42 | { | ||
43 | struct max77650_gpio_chip *chip = gpiochip_get_data(gc); | ||
44 | |||
45 | return regmap_update_bits(chip->map, | ||
46 | MAX77650_REG_CNFG_GPIO, | ||
47 | MAX77650_GPIO_DIR_MASK, | ||
48 | MAX77650_GPIO_DIR_IN); | ||
49 | } | ||
50 | |||
51 | static int max77650_gpio_direction_output(struct gpio_chip *gc, | ||
52 | unsigned int offset, int value) | ||
53 | { | ||
54 | struct max77650_gpio_chip *chip = gpiochip_get_data(gc); | ||
55 | int mask, regval; | ||
56 | |||
57 | mask = MAX77650_GPIO_DIR_MASK | MAX77650_GPIO_OUTVAL_MASK; | ||
58 | regval = value ? MAX77650_GPIO_OUT_HIGH : MAX77650_GPIO_OUT_LOW; | ||
59 | regval |= MAX77650_GPIO_DIR_OUT; | ||
60 | |||
61 | return regmap_update_bits(chip->map, | ||
62 | MAX77650_REG_CNFG_GPIO, mask, regval); | ||
63 | } | ||
64 | |||
65 | static void max77650_gpio_set_value(struct gpio_chip *gc, | ||
66 | unsigned int offset, int value) | ||
67 | { | ||
68 | struct max77650_gpio_chip *chip = gpiochip_get_data(gc); | ||
69 | int rv, regval; | ||
70 | |||
71 | regval = value ? MAX77650_GPIO_OUT_HIGH : MAX77650_GPIO_OUT_LOW; | ||
72 | |||
73 | rv = regmap_update_bits(chip->map, MAX77650_REG_CNFG_GPIO, | ||
74 | MAX77650_GPIO_OUTVAL_MASK, regval); | ||
75 | if (rv) | ||
76 | dev_err(gc->parent, "cannot set GPIO value: %d\n", rv); | ||
77 | } | ||
78 | |||
79 | static int max77650_gpio_get_value(struct gpio_chip *gc, | ||
80 | unsigned int offset) | ||
81 | { | ||
82 | struct max77650_gpio_chip *chip = gpiochip_get_data(gc); | ||
83 | unsigned int val; | ||
84 | int rv; | ||
85 | |||
86 | rv = regmap_read(chip->map, MAX77650_REG_CNFG_GPIO, &val); | ||
87 | if (rv) | ||
88 | return rv; | ||
89 | |||
90 | return MAX77650_GPIO_INVAL_BITS(val); | ||
91 | } | ||
92 | |||
93 | static int max77650_gpio_get_direction(struct gpio_chip *gc, | ||
94 | unsigned int offset) | ||
95 | { | ||
96 | struct max77650_gpio_chip *chip = gpiochip_get_data(gc); | ||
97 | unsigned int val; | ||
98 | int rv; | ||
99 | |||
100 | rv = regmap_read(chip->map, MAX77650_REG_CNFG_GPIO, &val); | ||
101 | if (rv) | ||
102 | return rv; | ||
103 | |||
104 | return MAX77650_GPIO_DIR_BITS(val); | ||
105 | } | ||
106 | |||
107 | static int max77650_gpio_set_config(struct gpio_chip *gc, | ||
108 | unsigned int offset, unsigned long cfg) | ||
109 | { | ||
110 | struct max77650_gpio_chip *chip = gpiochip_get_data(gc); | ||
111 | |||
112 | switch (pinconf_to_config_param(cfg)) { | ||
113 | case PIN_CONFIG_DRIVE_OPEN_DRAIN: | ||
114 | return regmap_update_bits(chip->map, | ||
115 | MAX77650_REG_CNFG_GPIO, | ||
116 | MAX77650_GPIO_DRV_MASK, | ||
117 | MAX77650_GPIO_DRV_OPEN_DRAIN); | ||
118 | case PIN_CONFIG_DRIVE_PUSH_PULL: | ||
119 | return regmap_update_bits(chip->map, | ||
120 | MAX77650_REG_CNFG_GPIO, | ||
121 | MAX77650_GPIO_DRV_MASK, | ||
122 | MAX77650_GPIO_DRV_PUSH_PULL); | ||
123 | case PIN_CONFIG_INPUT_DEBOUNCE: | ||
124 | return regmap_update_bits(chip->map, | ||
125 | MAX77650_REG_CNFG_GPIO, | ||
126 | MAX77650_GPIO_DEBOUNCE_MASK, | ||
127 | MAX77650_GPIO_DEBOUNCE); | ||
128 | default: | ||
129 | return -ENOTSUPP; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | static int max77650_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) | ||
134 | { | ||
135 | struct max77650_gpio_chip *chip = gpiochip_get_data(gc); | ||
136 | |||
137 | return chip->irq; | ||
138 | } | ||
139 | |||
140 | static int max77650_gpio_probe(struct platform_device *pdev) | ||
141 | { | ||
142 | struct max77650_gpio_chip *chip; | ||
143 | struct device *dev, *parent; | ||
144 | struct i2c_client *i2c; | ||
145 | |||
146 | dev = &pdev->dev; | ||
147 | parent = dev->parent; | ||
148 | i2c = to_i2c_client(parent); | ||
149 | |||
150 | chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); | ||
151 | if (!chip) | ||
152 | return -ENOMEM; | ||
153 | |||
154 | chip->map = dev_get_regmap(parent, NULL); | ||
155 | if (!chip->map) | ||
156 | return -ENODEV; | ||
157 | |||
158 | chip->irq = platform_get_irq_byname(pdev, "GPI"); | ||
159 | if (chip->irq < 0) | ||
160 | return chip->irq; | ||
161 | |||
162 | chip->gc.base = -1; | ||
163 | chip->gc.ngpio = 1; | ||
164 | chip->gc.label = i2c->name; | ||
165 | chip->gc.parent = dev; | ||
166 | chip->gc.owner = THIS_MODULE; | ||
167 | chip->gc.can_sleep = true; | ||
168 | |||
169 | chip->gc.direction_input = max77650_gpio_direction_input; | ||
170 | chip->gc.direction_output = max77650_gpio_direction_output; | ||
171 | chip->gc.set = max77650_gpio_set_value; | ||
172 | chip->gc.get = max77650_gpio_get_value; | ||
173 | chip->gc.get_direction = max77650_gpio_get_direction; | ||
174 | chip->gc.set_config = max77650_gpio_set_config; | ||
175 | chip->gc.to_irq = max77650_gpio_to_irq; | ||
176 | |||
177 | return devm_gpiochip_add_data(dev, &chip->gc, chip); | ||
178 | } | ||
179 | |||
180 | static struct platform_driver max77650_gpio_driver = { | ||
181 | .driver = { | ||
182 | .name = "max77650-gpio", | ||
183 | }, | ||
184 | .probe = max77650_gpio_probe, | ||
185 | }; | ||
186 | module_platform_driver(max77650_gpio_driver); | ||
187 | |||
188 | MODULE_DESCRIPTION("MAXIM 77650/77651 GPIO driver"); | ||
189 | MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); | ||
190 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 6dfe9e2fe5b1..54d36f98b426 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -190,6 +190,15 @@ config INPUT_M68K_BEEP | |||
190 | tristate "M68k Beeper support" | 190 | tristate "M68k Beeper support" |
191 | depends on M68K | 191 | depends on M68K |
192 | 192 | ||
193 | config INPUT_MAX77650_ONKEY | ||
194 | tristate "Maxim MAX77650 ONKEY support" | ||
195 | depends on MFD_MAX77650 | ||
196 | help | ||
197 | Support the ONKEY of the MAX77650 PMIC as an input device. | ||
198 | |||
199 | To compile this driver as a module, choose M here: the module | ||
200 | will be called max77650-onkey. | ||
201 | |||
193 | config INPUT_MAX77693_HAPTIC | 202 | config INPUT_MAX77693_HAPTIC |
194 | tristate "MAXIM MAX77693/MAX77843 haptic controller support" | 203 | tristate "MAXIM MAX77693/MAX77843 haptic controller support" |
195 | depends on (MFD_MAX77693 || MFD_MAX77843) && PWM | 204 | depends on (MFD_MAX77693 || MFD_MAX77843) && PWM |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index f38ebbdb05e2..8fd187f314bd 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -44,6 +44,7 @@ obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o | |||
44 | obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o | 44 | obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o |
45 | obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o | 45 | obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o |
46 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o | 46 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o |
47 | obj-$(CONFIG_INPUT_MAX77650_ONKEY) += max77650-onkey.o | ||
47 | obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o | 48 | obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o |
48 | obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o | 49 | obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o |
49 | obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o | 50 | obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o |
diff --git a/drivers/input/misc/max77650-onkey.c b/drivers/input/misc/max77650-onkey.c new file mode 100644 index 000000000000..fbf6caab7217 --- /dev/null +++ b/drivers/input/misc/max77650-onkey.c | |||
@@ -0,0 +1,121 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // | ||
3 | // Copyright (C) 2018 BayLibre SAS | ||
4 | // Author: Bartosz Golaszewski <bgolaszewski@baylibre.com> | ||
5 | // | ||
6 | // ONKEY driver for MAXIM 77650/77651 charger/power-supply. | ||
7 | |||
8 | #include <linux/i2c.h> | ||
9 | #include <linux/input.h> | ||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/mfd/max77650.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/regmap.h> | ||
15 | |||
16 | #define MAX77650_ONKEY_MODE_MASK BIT(3) | ||
17 | #define MAX77650_ONKEY_MODE_PUSH 0x00 | ||
18 | #define MAX77650_ONKEY_MODE_SLIDE BIT(3) | ||
19 | |||
20 | struct max77650_onkey { | ||
21 | struct input_dev *input; | ||
22 | unsigned int code; | ||
23 | }; | ||
24 | |||
25 | static irqreturn_t max77650_onkey_falling(int irq, void *data) | ||
26 | { | ||
27 | struct max77650_onkey *onkey = data; | ||
28 | |||
29 | input_report_key(onkey->input, onkey->code, 0); | ||
30 | input_sync(onkey->input); | ||
31 | |||
32 | return IRQ_HANDLED; | ||
33 | } | ||
34 | |||
35 | static irqreturn_t max77650_onkey_rising(int irq, void *data) | ||
36 | { | ||
37 | struct max77650_onkey *onkey = data; | ||
38 | |||
39 | input_report_key(onkey->input, onkey->code, 1); | ||
40 | input_sync(onkey->input); | ||
41 | |||
42 | return IRQ_HANDLED; | ||
43 | } | ||
44 | |||
45 | static int max77650_onkey_probe(struct platform_device *pdev) | ||
46 | { | ||
47 | int irq_r, irq_f, error, mode; | ||
48 | struct max77650_onkey *onkey; | ||
49 | struct device *dev, *parent; | ||
50 | struct regmap *map; | ||
51 | unsigned int type; | ||
52 | |||
53 | dev = &pdev->dev; | ||
54 | parent = dev->parent; | ||
55 | |||
56 | map = dev_get_regmap(parent, NULL); | ||
57 | if (!map) | ||
58 | return -ENODEV; | ||
59 | |||
60 | onkey = devm_kzalloc(dev, sizeof(*onkey), GFP_KERNEL); | ||
61 | if (!onkey) | ||
62 | return -ENOMEM; | ||
63 | |||
64 | error = device_property_read_u32(dev, "linux,code", &onkey->code); | ||
65 | if (error) | ||
66 | onkey->code = KEY_POWER; | ||
67 | |||
68 | if (device_property_read_bool(dev, "maxim,onkey-slide")) { | ||
69 | mode = MAX77650_ONKEY_MODE_SLIDE; | ||
70 | type = EV_SW; | ||
71 | } else { | ||
72 | mode = MAX77650_ONKEY_MODE_PUSH; | ||
73 | type = EV_KEY; | ||
74 | } | ||
75 | |||
76 | error = regmap_update_bits(map, MAX77650_REG_CNFG_GLBL, | ||
77 | MAX77650_ONKEY_MODE_MASK, mode); | ||
78 | if (error) | ||
79 | return error; | ||
80 | |||
81 | irq_f = platform_get_irq_byname(pdev, "nEN_F"); | ||
82 | if (irq_f < 0) | ||
83 | return irq_f; | ||
84 | |||
85 | irq_r = platform_get_irq_byname(pdev, "nEN_R"); | ||
86 | if (irq_r < 0) | ||
87 | return irq_r; | ||
88 | |||
89 | onkey->input = devm_input_allocate_device(dev); | ||
90 | if (!onkey->input) | ||
91 | return -ENOMEM; | ||
92 | |||
93 | onkey->input->name = "max77650_onkey"; | ||
94 | onkey->input->phys = "max77650_onkey/input0"; | ||
95 | onkey->input->id.bustype = BUS_I2C; | ||
96 | input_set_capability(onkey->input, type, onkey->code); | ||
97 | |||
98 | error = devm_request_any_context_irq(dev, irq_f, max77650_onkey_falling, | ||
99 | IRQF_ONESHOT, "onkey-down", onkey); | ||
100 | if (error < 0) | ||
101 | return error; | ||
102 | |||
103 | error = devm_request_any_context_irq(dev, irq_r, max77650_onkey_rising, | ||
104 | IRQF_ONESHOT, "onkey-up", onkey); | ||
105 | if (error < 0) | ||
106 | return error; | ||
107 | |||
108 | return input_register_device(onkey->input); | ||
109 | } | ||
110 | |||
111 | static struct platform_driver max77650_onkey_driver = { | ||
112 | .driver = { | ||
113 | .name = "max77650-onkey", | ||
114 | }, | ||
115 | .probe = max77650_onkey_probe, | ||
116 | }; | ||
117 | module_platform_driver(max77650_onkey_driver); | ||
118 | |||
119 | MODULE_DESCRIPTION("MAXIM 77650/77651 ONKEY driver"); | ||
120 | MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); | ||
121 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index f3000ccb8d35..71be87bdb926 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -619,6 +619,12 @@ config LEDS_TLC591XX | |||
619 | This option enables support for Texas Instruments TLC59108 | 619 | This option enables support for Texas Instruments TLC59108 |
620 | and TLC59116 LED controllers. | 620 | and TLC59116 LED controllers. |
621 | 621 | ||
622 | config LEDS_MAX77650 | ||
623 | tristate "LED support for Maxim MAX77650 PMIC" | ||
624 | depends on LEDS_CLASS && MFD_MAX77650 | ||
625 | help | ||
626 | LEDs driver for MAX77650 family of PMICs from Maxim Integrated. | ||
627 | |||
622 | config LEDS_MAX77693 | 628 | config LEDS_MAX77693 |
623 | tristate "LED support for MAX77693 Flash" | 629 | tristate "LED support for MAX77693 Flash" |
624 | depends on LEDS_CLASS_FLASH | 630 | depends on LEDS_CLASS_FLASH |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 7a8b1f55d459..1e9702ebffee 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
@@ -62,6 +62,7 @@ obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o | |||
62 | obj-$(CONFIG_LEDS_NS2) += leds-ns2.o | 62 | obj-$(CONFIG_LEDS_NS2) += leds-ns2.o |
63 | obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o | 63 | obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o |
64 | obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o | 64 | obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o |
65 | obj-$(CONFIG_LEDS_MAX77650) += leds-max77650.o | ||
65 | obj-$(CONFIG_LEDS_MAX77693) += leds-max77693.o | 66 | obj-$(CONFIG_LEDS_MAX77693) += leds-max77693.o |
66 | obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o | 67 | obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o |
67 | obj-$(CONFIG_LEDS_LM355x) += leds-lm355x.o | 68 | obj-$(CONFIG_LEDS_LM355x) += leds-lm355x.o |
diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c new file mode 100644 index 000000000000..6b74ce9cac12 --- /dev/null +++ b/drivers/leds/leds-max77650.c | |||
@@ -0,0 +1,147 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // | ||
3 | // Copyright (C) 2018 BayLibre SAS | ||
4 | // Author: Bartosz Golaszewski <bgolaszewski@baylibre.com> | ||
5 | // | ||
6 | // LED driver for MAXIM 77650/77651 charger/power-supply. | ||
7 | |||
8 | #include <linux/i2c.h> | ||
9 | #include <linux/leds.h> | ||
10 | #include <linux/mfd/max77650.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/regmap.h> | ||
14 | |||
15 | #define MAX77650_LED_NUM_LEDS 3 | ||
16 | |||
17 | #define MAX77650_LED_A_BASE 0x40 | ||
18 | #define MAX77650_LED_B_BASE 0x43 | ||
19 | |||
20 | #define MAX77650_LED_BR_MASK GENMASK(4, 0) | ||
21 | #define MAX77650_LED_EN_MASK GENMASK(7, 6) | ||
22 | |||
23 | #define MAX77650_LED_MAX_BRIGHTNESS MAX77650_LED_BR_MASK | ||
24 | |||
25 | /* Enable EN_LED_MSTR. */ | ||
26 | #define MAX77650_LED_TOP_DEFAULT BIT(0) | ||
27 | |||
28 | #define MAX77650_LED_ENABLE GENMASK(7, 6) | ||
29 | #define MAX77650_LED_DISABLE 0x00 | ||
30 | |||
31 | #define MAX77650_LED_A_DEFAULT MAX77650_LED_DISABLE | ||
32 | /* 100% on duty */ | ||
33 | #define MAX77650_LED_B_DEFAULT GENMASK(3, 0) | ||
34 | |||
35 | struct max77650_led { | ||
36 | struct led_classdev cdev; | ||
37 | struct regmap *map; | ||
38 | unsigned int regA; | ||
39 | unsigned int regB; | ||
40 | }; | ||
41 | |||
42 | static struct max77650_led *max77650_to_led(struct led_classdev *cdev) | ||
43 | { | ||
44 | return container_of(cdev, struct max77650_led, cdev); | ||
45 | } | ||
46 | |||
47 | static int max77650_led_brightness_set(struct led_classdev *cdev, | ||
48 | enum led_brightness brightness) | ||
49 | { | ||
50 | struct max77650_led *led = max77650_to_led(cdev); | ||
51 | int val, mask; | ||
52 | |||
53 | mask = MAX77650_LED_BR_MASK | MAX77650_LED_EN_MASK; | ||
54 | |||
55 | if (brightness == LED_OFF) | ||
56 | val = MAX77650_LED_DISABLE; | ||
57 | else | ||
58 | val = MAX77650_LED_ENABLE | brightness; | ||
59 | |||
60 | return regmap_update_bits(led->map, led->regA, mask, val); | ||
61 | } | ||
62 | |||
63 | static int max77650_led_probe(struct platform_device *pdev) | ||
64 | { | ||
65 | struct device_node *of_node, *child; | ||
66 | struct max77650_led *leds, *led; | ||
67 | struct device *parent; | ||
68 | struct device *dev; | ||
69 | struct regmap *map; | ||
70 | const char *label; | ||
71 | int rv, num_leds; | ||
72 | u32 reg; | ||
73 | |||
74 | dev = &pdev->dev; | ||
75 | parent = dev->parent; | ||
76 | of_node = dev->of_node; | ||
77 | |||
78 | if (!of_node) | ||
79 | return -ENODEV; | ||
80 | |||
81 | leds = devm_kcalloc(dev, sizeof(*leds), | ||
82 | MAX77650_LED_NUM_LEDS, GFP_KERNEL); | ||
83 | if (!leds) | ||
84 | return -ENOMEM; | ||
85 | |||
86 | map = dev_get_regmap(dev->parent, NULL); | ||
87 | if (!map) | ||
88 | return -ENODEV; | ||
89 | |||
90 | num_leds = of_get_child_count(of_node); | ||
91 | if (!num_leds || num_leds > MAX77650_LED_NUM_LEDS) | ||
92 | return -ENODEV; | ||
93 | |||
94 | for_each_child_of_node(of_node, child) { | ||
95 | rv = of_property_read_u32(child, "reg", ®); | ||
96 | if (rv || reg >= MAX77650_LED_NUM_LEDS) | ||
97 | return -EINVAL; | ||
98 | |||
99 | led = &leds[reg]; | ||
100 | led->map = map; | ||
101 | led->regA = MAX77650_LED_A_BASE + reg; | ||
102 | led->regB = MAX77650_LED_B_BASE + reg; | ||
103 | led->cdev.brightness_set_blocking = max77650_led_brightness_set; | ||
104 | led->cdev.max_brightness = MAX77650_LED_MAX_BRIGHTNESS; | ||
105 | |||
106 | label = of_get_property(child, "label", NULL); | ||
107 | if (!label) { | ||
108 | led->cdev.name = "max77650::"; | ||
109 | } else { | ||
110 | led->cdev.name = devm_kasprintf(dev, GFP_KERNEL, | ||
111 | "max77650:%s", label); | ||
112 | if (!led->cdev.name) | ||
113 | return -ENOMEM; | ||
114 | } | ||
115 | |||
116 | of_property_read_string(child, "linux,default-trigger", | ||
117 | &led->cdev.default_trigger); | ||
118 | |||
119 | rv = devm_of_led_classdev_register(dev, child, &led->cdev); | ||
120 | if (rv) | ||
121 | return rv; | ||
122 | |||
123 | rv = regmap_write(map, led->regA, MAX77650_LED_A_DEFAULT); | ||
124 | if (rv) | ||
125 | return rv; | ||
126 | |||
127 | rv = regmap_write(map, led->regB, MAX77650_LED_B_DEFAULT); | ||
128 | if (rv) | ||
129 | return rv; | ||
130 | } | ||
131 | |||
132 | return regmap_write(map, | ||
133 | MAX77650_REG_CNFG_LED_TOP, | ||
134 | MAX77650_LED_TOP_DEFAULT); | ||
135 | } | ||
136 | |||
137 | static struct platform_driver max77650_led_driver = { | ||
138 | .driver = { | ||
139 | .name = "max77650-led", | ||
140 | }, | ||
141 | .probe = max77650_led_probe, | ||
142 | }; | ||
143 | module_platform_driver(max77650_led_driver); | ||
144 | |||
145 | MODULE_DESCRIPTION("MAXIM 77650/77651 LED driver"); | ||
146 | MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); | ||
147 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 26ad6468d13a..294d9567cc71 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -16,7 +16,7 @@ config MFD_CS5535 | |||
16 | depends on PCI && (X86_32 || (X86 && COMPILE_TEST)) | 16 | depends on PCI && (X86_32 || (X86 && COMPILE_TEST)) |
17 | ---help--- | 17 | ---help--- |
18 | This is the core driver for CS5535/CS5536 MFD functions. This is | 18 | This is the core driver for CS5535/CS5536 MFD functions. This is |
19 | necessary for using the board's GPIO and MFGPT functionality. | 19 | necessary for using the board's GPIO and MFGPT functionality. |
20 | 20 | ||
21 | config MFD_ALTERA_A10SR | 21 | config MFD_ALTERA_A10SR |
22 | bool "Altera Arria10 DevKit System Resource chip" | 22 | bool "Altera Arria10 DevKit System Resource chip" |
@@ -29,6 +29,16 @@ config MFD_ALTERA_A10SR | |||
29 | accessing the external gpio extender (LEDs & buttons) and | 29 | accessing the external gpio extender (LEDs & buttons) and |
30 | power supply alarms (hwmon). | 30 | power supply alarms (hwmon). |
31 | 31 | ||
32 | config MFD_ALTERA_SYSMGR | ||
33 | bool "Altera SOCFPGA System Manager" | ||
34 | depends on (ARCH_SOCFPGA || ARCH_STRATIX10) && OF | ||
35 | select MFD_SYSCON | ||
36 | help | ||
37 | Select this to get System Manager support for all Altera branded | ||
38 | SOCFPGAs. The SOCFPGA System Manager handles all SOCFPGAs by | ||
39 | using regmap_mmio accesses for ARM32 parts and SMC calls to | ||
40 | EL3 for ARM64 parts. | ||
41 | |||
32 | config MFD_ACT8945A | 42 | config MFD_ACT8945A |
33 | tristate "Active-semi ACT8945A" | 43 | tristate "Active-semi ACT8945A" |
34 | select MFD_CORE | 44 | select MFD_CORE |
@@ -213,13 +223,13 @@ config MFD_CROS_EC | |||
213 | protocol for talking to the EC is defined by the bus driver. | 223 | protocol for talking to the EC is defined by the bus driver. |
214 | 224 | ||
215 | config MFD_CROS_EC_CHARDEV | 225 | config MFD_CROS_EC_CHARDEV |
216 | tristate "Chrome OS Embedded Controller userspace device interface" | 226 | tristate "Chrome OS Embedded Controller userspace device interface" |
217 | depends on MFD_CROS_EC | 227 | depends on MFD_CROS_EC |
218 | ---help--- | 228 | ---help--- |
219 | This driver adds support to talk with the ChromeOS EC from userspace. | 229 | This driver adds support to talk with the ChromeOS EC from userspace. |
220 | 230 | ||
221 | If you have a supported Chromebook, choose Y or M here. | 231 | If you have a supported Chromebook, choose Y or M here. |
222 | The module will be called cros_ec_dev. | 232 | The module will be called cros_ec_dev. |
223 | 233 | ||
224 | config MFD_MADERA | 234 | config MFD_MADERA |
225 | tristate "Cirrus Logic Madera codecs" | 235 | tristate "Cirrus Logic Madera codecs" |
@@ -733,6 +743,20 @@ config MFD_MAX77620 | |||
733 | provides common support for accessing the device; additional drivers | 743 | provides common support for accessing the device; additional drivers |
734 | must be enabled in order to use the functionality of the device. | 744 | must be enabled in order to use the functionality of the device. |
735 | 745 | ||
746 | config MFD_MAX77650 | ||
747 | tristate "Maxim MAX77650/77651 PMIC Support" | ||
748 | depends on I2C | ||
749 | depends on OF || COMPILE_TEST | ||
750 | select MFD_CORE | ||
751 | select REGMAP_I2C | ||
752 | help | ||
753 | Say Y here to add support for Maxim Semiconductor MAX77650 and | ||
754 | MAX77651 Power Management ICs. This is the core multifunction | ||
755 | driver for interacting with the device. The module name is | ||
756 | 'max77650'. Additional drivers can be enabled in order to use | ||
757 | the following functionalities of the device: GPIO, regulator, | ||
758 | charger, LED, onkey. | ||
759 | |||
736 | config MFD_MAX77686 | 760 | config MFD_MAX77686 |
737 | tristate "Maxim Semiconductor MAX77686/802 PMIC Support" | 761 | tristate "Maxim Semiconductor MAX77686/802 PMIC Support" |
738 | depends on I2C | 762 | depends on I2C |
@@ -867,7 +891,7 @@ config MFD_CPCAP | |||
867 | At least Motorola Droid 4 is known to use CPCAP. | 891 | At least Motorola Droid 4 is known to use CPCAP. |
868 | 892 | ||
869 | config MFD_VIPERBOARD | 893 | config MFD_VIPERBOARD |
870 | tristate "Nano River Technologies Viperboard" | 894 | tristate "Nano River Technologies Viperboard" |
871 | select MFD_CORE | 895 | select MFD_CORE |
872 | depends on USB | 896 | depends on USB |
873 | default n | 897 | default n |
@@ -903,15 +927,15 @@ config PCF50633_ADC | |||
903 | tristate "NXP PCF50633 ADC" | 927 | tristate "NXP PCF50633 ADC" |
904 | depends on MFD_PCF50633 | 928 | depends on MFD_PCF50633 |
905 | help | 929 | help |
906 | Say yes here if you want to include support for ADC in the | 930 | Say yes here if you want to include support for ADC in the |
907 | NXP PCF50633 chip. | 931 | NXP PCF50633 chip. |
908 | 932 | ||
909 | config PCF50633_GPIO | 933 | config PCF50633_GPIO |
910 | tristate "NXP PCF50633 GPIO" | 934 | tristate "NXP PCF50633 GPIO" |
911 | depends on MFD_PCF50633 | 935 | depends on MFD_PCF50633 |
912 | help | 936 | help |
913 | Say yes here if you want to include support GPIO for pins on | 937 | Say yes here if you want to include support GPIO for pins on |
914 | the PCF50633 chip. | 938 | the PCF50633 chip. |
915 | 939 | ||
916 | config UCB1400_CORE | 940 | config UCB1400_CORE |
917 | tristate "Philips UCB1400 Core driver" | 941 | tristate "Philips UCB1400 Core driver" |
@@ -1026,7 +1050,7 @@ config MFD_RN5T618 | |||
1026 | select REGMAP_I2C | 1050 | select REGMAP_I2C |
1027 | help | 1051 | help |
1028 | Say yes here to add support for the Ricoh RN5T567, | 1052 | Say yes here to add support for the Ricoh RN5T567, |
1029 | RN5T618, RC5T619 PMIC. | 1053 | RN5T618, RC5T619 PMIC. |
1030 | This driver provides common support for accessing the device, | 1054 | This driver provides common support for accessing the device, |
1031 | additional drivers must be enabled in order to use the | 1055 | additional drivers must be enabled in order to use the |
1032 | functionality of the device. | 1056 | functionality of the device. |
@@ -1079,9 +1103,9 @@ config MFD_SM501_GPIO | |||
1079 | bool "Export GPIO via GPIO layer" | 1103 | bool "Export GPIO via GPIO layer" |
1080 | depends on MFD_SM501 && GPIOLIB | 1104 | depends on MFD_SM501 && GPIOLIB |
1081 | ---help--- | 1105 | ---help--- |
1082 | This option uses the gpio library layer to export the 64 GPIO | 1106 | This option uses the gpio library layer to export the 64 GPIO |
1083 | lines on the SM501. The platform data is used to supply the | 1107 | lines on the SM501. The platform data is used to supply the |
1084 | base number for the first GPIO line to register. | 1108 | base number for the first GPIO line to register. |
1085 | 1109 | ||
1086 | config MFD_SKY81452 | 1110 | config MFD_SKY81452 |
1087 | tristate "Skyworks Solutions SKY81452" | 1111 | tristate "Skyworks Solutions SKY81452" |
@@ -1096,16 +1120,16 @@ config MFD_SKY81452 | |||
1096 | will be called sky81452. | 1120 | will be called sky81452. |
1097 | 1121 | ||
1098 | config MFD_SMSC | 1122 | config MFD_SMSC |
1099 | bool "SMSC ECE1099 series chips" | 1123 | bool "SMSC ECE1099 series chips" |
1100 | depends on I2C=y | 1124 | depends on I2C=y |
1101 | select MFD_CORE | 1125 | select MFD_CORE |
1102 | select REGMAP_I2C | 1126 | select REGMAP_I2C |
1103 | help | 1127 | help |
1104 | If you say yes here you get support for the | 1128 | If you say yes here you get support for the |
1105 | ece1099 chips from SMSC. | 1129 | ece1099 chips from SMSC. |
1106 | 1130 | ||
1107 | To compile this driver as a module, choose M here: the | 1131 | To compile this driver as a module, choose M here: the |
1108 | module will be called smsc. | 1132 | module will be called smsc. |
1109 | 1133 | ||
1110 | config MFD_SC27XX_PMIC | 1134 | config MFD_SC27XX_PMIC |
1111 | tristate "Spreadtrum SC27xx PMICs" | 1135 | tristate "Spreadtrum SC27xx PMICs" |
@@ -1171,12 +1195,12 @@ config AB8500_CORE | |||
1171 | This chip embeds various other multimedia funtionalities as well. | 1195 | This chip embeds various other multimedia funtionalities as well. |
1172 | 1196 | ||
1173 | config AB8500_DEBUG | 1197 | config AB8500_DEBUG |
1174 | bool "Enable debug info via debugfs" | 1198 | bool "Enable debug info via debugfs" |
1175 | depends on AB8500_GPADC && DEBUG_FS | 1199 | depends on AB8500_GPADC && DEBUG_FS |
1176 | default y if DEBUG_FS | 1200 | default y if DEBUG_FS |
1177 | help | 1201 | help |
1178 | Select this option if you want debug information using the debug | 1202 | Select this option if you want debug information using the debug |
1179 | filesystem, debugfs. | 1203 | filesystem, debugfs. |
1180 | 1204 | ||
1181 | config AB8500_GPADC | 1205 | config AB8500_GPADC |
1182 | bool "ST-Ericsson AB8500 GPADC driver" | 1206 | bool "ST-Ericsson AB8500 GPADC driver" |
@@ -1907,6 +1931,19 @@ config MFD_STPMIC1 | |||
1907 | To compile this driver as a module, choose M here: the | 1931 | To compile this driver as a module, choose M here: the |
1908 | module will be called stpmic1. | 1932 | module will be called stpmic1. |
1909 | 1933 | ||
1934 | config MFD_STMFX | ||
1935 | tristate "Support for STMicroelectronics Multi-Function eXpander (STMFX)" | ||
1936 | depends on I2C | ||
1937 | depends on OF || COMPILE_TEST | ||
1938 | select MFD_CORE | ||
1939 | select REGMAP_I2C | ||
1940 | help | ||
1941 | Support for the STMicroelectronics Multi-Function eXpander. | ||
1942 | |||
1943 | This driver provides common support for accessing the device, | ||
1944 | additional drivers must be enabled in order to use the functionality | ||
1945 | of the device. | ||
1946 | |||
1910 | menu "Multimedia Capabilities Port drivers" | 1947 | menu "Multimedia Capabilities Port drivers" |
1911 | depends on ARCH_SA1100 | 1948 | depends on ARCH_SA1100 |
1912 | 1949 | ||
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index b4569ed7f3f3..52b1a90ff515 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -155,6 +155,7 @@ obj-$(CONFIG_MFD_DA9150) += da9150-core.o | |||
155 | 155 | ||
156 | obj-$(CONFIG_MFD_MAX14577) += max14577.o | 156 | obj-$(CONFIG_MFD_MAX14577) += max14577.o |
157 | obj-$(CONFIG_MFD_MAX77620) += max77620.o | 157 | obj-$(CONFIG_MFD_MAX77620) += max77620.o |
158 | obj-$(CONFIG_MFD_MAX77650) += max77650.o | ||
158 | obj-$(CONFIG_MFD_MAX77686) += max77686.o | 159 | obj-$(CONFIG_MFD_MAX77686) += max77686.o |
159 | obj-$(CONFIG_MFD_MAX77693) += max77693.o | 160 | obj-$(CONFIG_MFD_MAX77693) += max77693.o |
160 | obj-$(CONFIG_MFD_MAX77843) += max77843.o | 161 | obj-$(CONFIG_MFD_MAX77843) += max77843.o |
@@ -237,6 +238,7 @@ obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI) += intel_soc_pmic_chtdc_ti.o | |||
237 | obj-$(CONFIG_MFD_MT6397) += mt6397-core.o | 238 | obj-$(CONFIG_MFD_MT6397) += mt6397-core.o |
238 | 239 | ||
239 | obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o | 240 | obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o |
241 | obj-$(CONFIG_MFD_ALTERA_SYSMGR) += altera-sysmgr.o | ||
240 | obj-$(CONFIG_MFD_STPMIC1) += stpmic1.o | 242 | obj-$(CONFIG_MFD_STPMIC1) += stpmic1.o |
241 | obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o | 243 | obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o |
242 | 244 | ||
@@ -246,4 +248,4 @@ obj-$(CONFIG_MFD_MXS_LRADC) += mxs-lradc.o | |||
246 | obj-$(CONFIG_MFD_SC27XX_PMIC) += sprd-sc27xx-spi.o | 248 | obj-$(CONFIG_MFD_SC27XX_PMIC) += sprd-sc27xx-spi.o |
247 | obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o | 249 | obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o |
248 | obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o | 250 | obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o |
249 | 251 | obj-$(CONFIG_MFD_STMFX) += stmfx.o | |
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 8d652b2f9d14..f70d3f6a959b 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c | |||
@@ -2587,7 +2587,7 @@ static ssize_t ab8500_unsubscribe_write(struct file *file, | |||
2587 | } | 2587 | } |
2588 | 2588 | ||
2589 | /* | 2589 | /* |
2590 | * - several deubgfs nodes fops | 2590 | * - several debugfs nodes fops |
2591 | */ | 2591 | */ |
2592 | 2592 | ||
2593 | static const struct file_operations ab8500_bank_fops = { | 2593 | static const struct file_operations ab8500_bank_fops = { |
diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c new file mode 100644 index 000000000000..8976f82785bb --- /dev/null +++ b/drivers/mfd/altera-sysmgr.c | |||
@@ -0,0 +1,211 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Copyright (C) 2018-2019, Intel Corporation. | ||
4 | * Copyright (C) 2012 Freescale Semiconductor, Inc. | ||
5 | * Copyright (C) 2012 Linaro Ltd. | ||
6 | * | ||
7 | * Based on syscon driver. | ||
8 | */ | ||
9 | |||
10 | #include <linux/arm-smccc.h> | ||
11 | #include <linux/err.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/mfd/altera-sysmgr.h> | ||
14 | #include <linux/mfd/syscon.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/of.h> | ||
17 | #include <linux/of_address.h> | ||
18 | #include <linux/of_platform.h> | ||
19 | #include <linux/regmap.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | /** | ||
23 | * struct altr_sysmgr - Altera SOCFPGA System Manager | ||
24 | * @regmap: the regmap used for System Manager accesses. | ||
25 | * @base : the base address for the System Manager | ||
26 | */ | ||
27 | struct altr_sysmgr { | ||
28 | struct regmap *regmap; | ||
29 | resource_size_t *base; | ||
30 | }; | ||
31 | |||
32 | static struct platform_driver altr_sysmgr_driver; | ||
33 | |||
34 | /** | ||
35 | * s10_protected_reg_write | ||
36 | * Write to a protected SMC register. | ||
37 | * @base: Base address of System Manager | ||
38 | * @reg: Address offset of register | ||
39 | * @val: Value to write | ||
40 | * Return: INTEL_SIP_SMC_STATUS_OK (0) on success | ||
41 | * INTEL_SIP_SMC_REG_ERROR on error | ||
42 | * INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION if not supported | ||
43 | */ | ||
44 | static int s10_protected_reg_write(void *base, | ||
45 | unsigned int reg, unsigned int val) | ||
46 | { | ||
47 | struct arm_smccc_res result; | ||
48 | unsigned long sysmgr_base = (unsigned long)base; | ||
49 | |||
50 | arm_smccc_smc(INTEL_SIP_SMC_REG_WRITE, sysmgr_base + reg, | ||
51 | val, 0, 0, 0, 0, 0, &result); | ||
52 | |||
53 | return (int)result.a0; | ||
54 | } | ||
55 | |||
56 | /** | ||
57 | * s10_protected_reg_read | ||
58 | * Read the status of a protected SMC register | ||
59 | * @base: Base address of System Manager. | ||
60 | * @reg: Address of register | ||
61 | * @val: Value read. | ||
62 | * Return: INTEL_SIP_SMC_STATUS_OK (0) on success | ||
63 | * INTEL_SIP_SMC_REG_ERROR on error | ||
64 | * INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION if not supported | ||
65 | */ | ||
66 | static int s10_protected_reg_read(void *base, | ||
67 | unsigned int reg, unsigned int *val) | ||
68 | { | ||
69 | struct arm_smccc_res result; | ||
70 | unsigned long sysmgr_base = (unsigned long)base; | ||
71 | |||
72 | arm_smccc_smc(INTEL_SIP_SMC_REG_READ, sysmgr_base + reg, | ||
73 | 0, 0, 0, 0, 0, 0, &result); | ||
74 | |||
75 | *val = (unsigned int)result.a1; | ||
76 | |||
77 | return (int)result.a0; | ||
78 | } | ||
79 | |||
80 | static struct regmap_config altr_sysmgr_regmap_cfg = { | ||
81 | .name = "altr_sysmgr", | ||
82 | .reg_bits = 32, | ||
83 | .reg_stride = 4, | ||
84 | .val_bits = 32, | ||
85 | .fast_io = true, | ||
86 | .use_single_read = true, | ||
87 | .use_single_write = true, | ||
88 | }; | ||
89 | |||
90 | /** | ||
91 | * sysmgr_match_phandle | ||
92 | * Matching function used by driver_find_device(). | ||
93 | * Return: True if match is found, otherwise false. | ||
94 | */ | ||
95 | static int sysmgr_match_phandle(struct device *dev, void *data) | ||
96 | { | ||
97 | return dev->of_node == (struct device_node *)data; | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * altr_sysmgr_regmap_lookup_by_phandle | ||
102 | * Find the sysmgr previous configured in probe() and return regmap property. | ||
103 | * Return: regmap if found or error if not found. | ||
104 | */ | ||
105 | struct regmap *altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np, | ||
106 | const char *property) | ||
107 | { | ||
108 | struct device *dev; | ||
109 | struct altr_sysmgr *sysmgr; | ||
110 | struct device_node *sysmgr_np; | ||
111 | |||
112 | if (property) | ||
113 | sysmgr_np = of_parse_phandle(np, property, 0); | ||
114 | else | ||
115 | sysmgr_np = np; | ||
116 | |||
117 | if (!sysmgr_np) | ||
118 | return ERR_PTR(-ENODEV); | ||
119 | |||
120 | dev = driver_find_device(&altr_sysmgr_driver.driver, NULL, | ||
121 | (void *)sysmgr_np, sysmgr_match_phandle); | ||
122 | of_node_put(sysmgr_np); | ||
123 | if (!dev) | ||
124 | return ERR_PTR(-EPROBE_DEFER); | ||
125 | |||
126 | sysmgr = dev_get_drvdata(dev); | ||
127 | |||
128 | return sysmgr->regmap; | ||
129 | } | ||
130 | EXPORT_SYMBOL_GPL(altr_sysmgr_regmap_lookup_by_phandle); | ||
131 | |||
132 | static int sysmgr_probe(struct platform_device *pdev) | ||
133 | { | ||
134 | struct altr_sysmgr *sysmgr; | ||
135 | struct regmap *regmap; | ||
136 | struct resource *res; | ||
137 | struct regmap_config sysmgr_config = altr_sysmgr_regmap_cfg; | ||
138 | struct device *dev = &pdev->dev; | ||
139 | struct device_node *np = dev->of_node; | ||
140 | |||
141 | sysmgr = devm_kzalloc(dev, sizeof(*sysmgr), GFP_KERNEL); | ||
142 | if (!sysmgr) | ||
143 | return -ENOMEM; | ||
144 | |||
145 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
146 | if (!res) | ||
147 | return -ENOENT; | ||
148 | |||
149 | sysmgr_config.max_register = resource_size(res) - | ||
150 | sysmgr_config.reg_stride; | ||
151 | if (of_device_is_compatible(np, "altr,sys-mgr-s10")) { | ||
152 | /* Need physical address for SMCC call */ | ||
153 | sysmgr->base = (resource_size_t *)res->start; | ||
154 | sysmgr_config.reg_read = s10_protected_reg_read; | ||
155 | sysmgr_config.reg_write = s10_protected_reg_write; | ||
156 | |||
157 | regmap = devm_regmap_init(dev, NULL, sysmgr->base, | ||
158 | &sysmgr_config); | ||
159 | } else { | ||
160 | sysmgr->base = devm_ioremap(dev, res->start, | ||
161 | resource_size(res)); | ||
162 | if (!sysmgr->base) | ||
163 | return -ENOMEM; | ||
164 | |||
165 | sysmgr_config.max_register = res->end - res->start - 3; | ||
166 | regmap = devm_regmap_init_mmio(dev, sysmgr->base, | ||
167 | &sysmgr_config); | ||
168 | } | ||
169 | |||
170 | if (IS_ERR(regmap)) { | ||
171 | pr_err("regmap init failed\n"); | ||
172 | return PTR_ERR(regmap); | ||
173 | } | ||
174 | |||
175 | sysmgr->regmap = regmap; | ||
176 | |||
177 | platform_set_drvdata(pdev, sysmgr); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static const struct of_device_id altr_sysmgr_of_match[] = { | ||
183 | { .compatible = "altr,sys-mgr" }, | ||
184 | { .compatible = "altr,sys-mgr-s10" }, | ||
185 | {}, | ||
186 | }; | ||
187 | MODULE_DEVICE_TABLE(of, altr_sysmgr_of_match); | ||
188 | |||
189 | static struct platform_driver altr_sysmgr_driver = { | ||
190 | .probe = sysmgr_probe, | ||
191 | .driver = { | ||
192 | .name = "altr,system_manager", | ||
193 | .of_match_table = altr_sysmgr_of_match, | ||
194 | }, | ||
195 | }; | ||
196 | |||
197 | static int __init altr_sysmgr_init(void) | ||
198 | { | ||
199 | return platform_driver_register(&altr_sysmgr_driver); | ||
200 | } | ||
201 | core_initcall(altr_sysmgr_init); | ||
202 | |||
203 | static void __exit altr_sysmgr_exit(void) | ||
204 | { | ||
205 | platform_driver_unregister(&altr_sysmgr_driver); | ||
206 | } | ||
207 | module_exit(altr_sysmgr_exit); | ||
208 | |||
209 | MODULE_AUTHOR("Thor Thayer <>"); | ||
210 | MODULE_DESCRIPTION("SOCFPGA System Manager driver"); | ||
211 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/atmel-hlcdc.c b/drivers/mfd/atmel-hlcdc.c index e82543bcfdc8..35a9e16f9902 100644 --- a/drivers/mfd/atmel-hlcdc.c +++ b/drivers/mfd/atmel-hlcdc.c | |||
@@ -141,6 +141,7 @@ static const struct of_device_id atmel_hlcdc_match[] = { | |||
141 | { .compatible = "atmel,sama5d2-hlcdc" }, | 141 | { .compatible = "atmel,sama5d2-hlcdc" }, |
142 | { .compatible = "atmel,sama5d3-hlcdc" }, | 142 | { .compatible = "atmel,sama5d3-hlcdc" }, |
143 | { .compatible = "atmel,sama5d4-hlcdc" }, | 143 | { .compatible = "atmel,sama5d4-hlcdc" }, |
144 | { .compatible = "microchip,sam9x60-hlcdc" }, | ||
144 | { /* sentinel */ }, | 145 | { /* sentinel */ }, |
145 | }; | 146 | }; |
146 | MODULE_DEVICE_TABLE(of, atmel_hlcdc_match); | 147 | MODULE_DEVICE_TABLE(of, atmel_hlcdc_match); |
diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c index a7b7c5423ea5..c2e8a0dee7f8 100644 --- a/drivers/mfd/axp20x-i2c.c +++ b/drivers/mfd/axp20x-i2c.c | |||
@@ -65,6 +65,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = { | |||
65 | { .compatible = "x-powers,axp202", .data = (void *)AXP202_ID }, | 65 | { .compatible = "x-powers,axp202", .data = (void *)AXP202_ID }, |
66 | { .compatible = "x-powers,axp209", .data = (void *)AXP209_ID }, | 66 | { .compatible = "x-powers,axp209", .data = (void *)AXP209_ID }, |
67 | { .compatible = "x-powers,axp221", .data = (void *)AXP221_ID }, | 67 | { .compatible = "x-powers,axp221", .data = (void *)AXP221_ID }, |
68 | { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, | ||
68 | { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID }, | 69 | { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID }, |
69 | { }, | 70 | { }, |
70 | }; | 71 | }; |
@@ -75,6 +76,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = { | |||
75 | { "axp202", 0 }, | 76 | { "axp202", 0 }, |
76 | { "axp209", 0 }, | 77 | { "axp209", 0 }, |
77 | { "axp221", 0 }, | 78 | { "axp221", 0 }, |
79 | { "axp223", 0 }, | ||
78 | { "axp806", 0 }, | 80 | { "axp806", 0 }, |
79 | { }, | 81 | { }, |
80 | }; | 82 | }; |
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 3c97f2c0fdfe..2215660dfa05 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c | |||
@@ -198,6 +198,12 @@ static const struct resource axp22x_usb_power_supply_resources[] = { | |||
198 | DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"), | 198 | DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"), |
199 | }; | 199 | }; |
200 | 200 | ||
201 | /* AXP803 and AXP813/AXP818 share the same interrupts */ | ||
202 | static const struct resource axp803_usb_power_supply_resources[] = { | ||
203 | DEFINE_RES_IRQ_NAMED(AXP803_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"), | ||
204 | DEFINE_RES_IRQ_NAMED(AXP803_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"), | ||
205 | }; | ||
206 | |||
201 | static const struct resource axp22x_pek_resources[] = { | 207 | static const struct resource axp22x_pek_resources[] = { |
202 | DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_PEK_RIS_EDGE, "PEK_DBR"), | 208 | DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_PEK_RIS_EDGE, "PEK_DBR"), |
203 | DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_PEK_FAL_EDGE, "PEK_DBF"), | 209 | DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_PEK_FAL_EDGE, "PEK_DBF"), |
@@ -741,6 +747,11 @@ static const struct mfd_cell axp803_cells[] = { | |||
741 | .of_compatible = "x-powers,axp813-ac-power-supply", | 747 | .of_compatible = "x-powers,axp813-ac-power-supply", |
742 | .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources), | 748 | .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources), |
743 | .resources = axp20x_ac_power_supply_resources, | 749 | .resources = axp20x_ac_power_supply_resources, |
750 | }, { | ||
751 | .name = "axp20x-usb-power-supply", | ||
752 | .num_resources = ARRAY_SIZE(axp803_usb_power_supply_resources), | ||
753 | .resources = axp803_usb_power_supply_resources, | ||
754 | .of_compatible = "x-powers,axp813-usb-power-supply", | ||
744 | }, | 755 | }, |
745 | { .name = "axp20x-regulator" }, | 756 | { .name = "axp20x-regulator" }, |
746 | }; | 757 | }; |
@@ -793,6 +804,11 @@ static const struct mfd_cell axp813_cells[] = { | |||
793 | .of_compatible = "x-powers,axp813-ac-power-supply", | 804 | .of_compatible = "x-powers,axp813-ac-power-supply", |
794 | .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources), | 805 | .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources), |
795 | .resources = axp20x_ac_power_supply_resources, | 806 | .resources = axp20x_ac_power_supply_resources, |
807 | }, { | ||
808 | .name = "axp20x-usb-power-supply", | ||
809 | .num_resources = ARRAY_SIZE(axp803_usb_power_supply_resources), | ||
810 | .resources = axp803_usb_power_supply_resources, | ||
811 | .of_compatible = "x-powers,axp813-usb-power-supply", | ||
796 | }, | 812 | }, |
797 | }; | 813 | }; |
798 | 814 | ||
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c index 6acfe036d522..bd2bcdd4718b 100644 --- a/drivers/mfd/cros_ec.c +++ b/drivers/mfd/cros_ec.c | |||
@@ -75,20 +75,49 @@ static irqreturn_t ec_irq_thread(int irq, void *data) | |||
75 | 75 | ||
76 | static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event) | 76 | static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event) |
77 | { | 77 | { |
78 | int ret; | ||
78 | struct { | 79 | struct { |
79 | struct cros_ec_command msg; | 80 | struct cros_ec_command msg; |
80 | struct ec_params_host_sleep_event req; | 81 | union { |
82 | struct ec_params_host_sleep_event req0; | ||
83 | struct ec_params_host_sleep_event_v1 req1; | ||
84 | struct ec_response_host_sleep_event_v1 resp1; | ||
85 | } u; | ||
81 | } __packed buf; | 86 | } __packed buf; |
82 | 87 | ||
83 | memset(&buf, 0, sizeof(buf)); | 88 | memset(&buf, 0, sizeof(buf)); |
84 | 89 | ||
85 | buf.req.sleep_event = sleep_event; | 90 | if (ec_dev->host_sleep_v1) { |
91 | buf.u.req1.sleep_event = sleep_event; | ||
92 | buf.u.req1.suspend_params.sleep_timeout_ms = | ||
93 | EC_HOST_SLEEP_TIMEOUT_DEFAULT; | ||
94 | |||
95 | buf.msg.outsize = sizeof(buf.u.req1); | ||
96 | if ((sleep_event == HOST_SLEEP_EVENT_S3_RESUME) || | ||
97 | (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME)) | ||
98 | buf.msg.insize = sizeof(buf.u.resp1); | ||
99 | |||
100 | buf.msg.version = 1; | ||
101 | |||
102 | } else { | ||
103 | buf.u.req0.sleep_event = sleep_event; | ||
104 | buf.msg.outsize = sizeof(buf.u.req0); | ||
105 | } | ||
86 | 106 | ||
87 | buf.msg.command = EC_CMD_HOST_SLEEP_EVENT; | 107 | buf.msg.command = EC_CMD_HOST_SLEEP_EVENT; |
88 | buf.msg.version = 0; | ||
89 | buf.msg.outsize = sizeof(buf.req); | ||
90 | 108 | ||
91 | return cros_ec_cmd_xfer(ec_dev, &buf.msg); | 109 | ret = cros_ec_cmd_xfer(ec_dev, &buf.msg); |
110 | |||
111 | /* For now, report failure to transition to S0ix with a warning. */ | ||
112 | if (ret >= 0 && ec_dev->host_sleep_v1 && | ||
113 | (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME)) | ||
114 | WARN_ONCE(buf.u.resp1.resume_response.sleep_transitions & | ||
115 | EC_HOST_RESUME_SLEEP_TIMEOUT, | ||
116 | "EC detected sleep transition timeout. Total slp_s0 transitions: %d", | ||
117 | buf.u.resp1.resume_response.sleep_transitions & | ||
118 | EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK); | ||
119 | |||
120 | return ret; | ||
92 | } | 121 | } |
93 | 122 | ||
94 | int cros_ec_register(struct cros_ec_device *ec_dev) | 123 | int cros_ec_register(struct cros_ec_device *ec_dev) |
diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index d275deaecb12..54a58df571b6 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c | |||
@@ -385,7 +385,8 @@ static const struct mfd_cell cros_ec_rtc_cells[] = { | |||
385 | }; | 385 | }; |
386 | 386 | ||
387 | static const struct mfd_cell cros_usbpd_charger_cells[] = { | 387 | static const struct mfd_cell cros_usbpd_charger_cells[] = { |
388 | { .name = "cros-usbpd-charger" } | 388 | { .name = "cros-usbpd-charger" }, |
389 | { .name = "cros-usbpd-logger" }, | ||
389 | }; | 390 | }; |
390 | 391 | ||
391 | static const struct mfd_cell cros_ec_platform_cells[] = { | 392 | static const struct mfd_cell cros_ec_platform_cells[] = { |
@@ -418,6 +419,39 @@ static int ec_device_probe(struct platform_device *pdev) | |||
418 | device_initialize(&ec->class_dev); | 419 | device_initialize(&ec->class_dev); |
419 | cdev_init(&ec->cdev, &fops); | 420 | cdev_init(&ec->cdev, &fops); |
420 | 421 | ||
422 | /* Check whether this is actually a Fingerprint MCU rather than an EC */ | ||
423 | if (cros_ec_check_features(ec, EC_FEATURE_FINGERPRINT)) { | ||
424 | dev_info(dev, "CrOS Fingerprint MCU detected.\n"); | ||
425 | /* | ||
426 | * Help userspace differentiating ECs from FP MCU, | ||
427 | * regardless of the probing order. | ||
428 | */ | ||
429 | ec_platform->ec_name = CROS_EC_DEV_FP_NAME; | ||
430 | } | ||
431 | |||
432 | /* | ||
433 | * Check whether this is actually an Integrated Sensor Hub (ISH) | ||
434 | * rather than an EC. | ||
435 | */ | ||
436 | if (cros_ec_check_features(ec, EC_FEATURE_ISH)) { | ||
437 | dev_info(dev, "CrOS ISH MCU detected.\n"); | ||
438 | /* | ||
439 | * Help userspace differentiating ECs from ISH MCU, | ||
440 | * regardless of the probing order. | ||
441 | */ | ||
442 | ec_platform->ec_name = CROS_EC_DEV_ISH_NAME; | ||
443 | } | ||
444 | |||
445 | /* Check whether this is actually a Touchpad MCU rather than an EC */ | ||
446 | if (cros_ec_check_features(ec, EC_FEATURE_TOUCHPAD)) { | ||
447 | dev_info(dev, "CrOS Touchpad MCU detected.\n"); | ||
448 | /* | ||
449 | * Help userspace differentiating ECs from TP MCU, | ||
450 | * regardless of the probing order. | ||
451 | */ | ||
452 | ec_platform->ec_name = CROS_EC_DEV_TP_NAME; | ||
453 | } | ||
454 | |||
421 | /* | 455 | /* |
422 | * Add the class device | 456 | * Add the class device |
423 | * Link to the character device for creating the /dev entry | 457 | * Link to the character device for creating the /dev entry |
diff --git a/drivers/mfd/cs47l35-tables.c b/drivers/mfd/cs47l35-tables.c index 604c9dd14df5..338b825127f1 100644 --- a/drivers/mfd/cs47l35-tables.c +++ b/drivers/mfd/cs47l35-tables.c | |||
@@ -178,6 +178,7 @@ static const struct reg_default cs47l35_reg_default[] = { | |||
178 | { 0x00000448, 0x0a83 }, /* R1096 (0x448) - eDRE Enable */ | 178 | { 0x00000448, 0x0a83 }, /* R1096 (0x448) - eDRE Enable */ |
179 | { 0x0000044a, 0x0000 }, /* R1098 (0x44a) - eDRE Manual */ | 179 | { 0x0000044a, 0x0000 }, /* R1098 (0x44a) - eDRE Manual */ |
180 | { 0x00000450, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 1 */ | 180 | { 0x00000450, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 1 */ |
181 | { 0x00000451, 0x0000 }, /* R1105 (0x451) - DAC AEC Control 2 */ | ||
181 | { 0x00000458, 0x0000 }, /* R1112 (0x458) - Noise Gate Control */ | 182 | { 0x00000458, 0x0000 }, /* R1112 (0x458) - Noise Gate Control */ |
182 | { 0x00000490, 0x0069 }, /* R1168 (0x490) - PDM SPK1 CTRL 1 */ | 183 | { 0x00000490, 0x0069 }, /* R1168 (0x490) - PDM SPK1 CTRL 1 */ |
183 | { 0x00000491, 0x0000 }, /* R1169 (0x491) - PDM SPK1 CTRL 2 */ | 184 | { 0x00000491, 0x0000 }, /* R1169 (0x491) - PDM SPK1 CTRL 2 */ |
@@ -970,6 +971,7 @@ static bool cs47l35_16bit_readable_register(struct device *dev, | |||
970 | case MADERA_EDRE_ENABLE: | 971 | case MADERA_EDRE_ENABLE: |
971 | case MADERA_EDRE_MANUAL: | 972 | case MADERA_EDRE_MANUAL: |
972 | case MADERA_DAC_AEC_CONTROL_1: | 973 | case MADERA_DAC_AEC_CONTROL_1: |
974 | case MADERA_DAC_AEC_CONTROL_2: | ||
973 | case MADERA_NOISE_GATE_CONTROL: | 975 | case MADERA_NOISE_GATE_CONTROL: |
974 | case MADERA_PDM_SPK1_CTRL_1: | 976 | case MADERA_PDM_SPK1_CTRL_1: |
975 | case MADERA_PDM_SPK1_CTRL_2: | 977 | case MADERA_PDM_SPK1_CTRL_2: |
diff --git a/drivers/mfd/cs47l90-tables.c b/drivers/mfd/cs47l90-tables.c index 77207d98f0cc..c040d3d7232a 100644 --- a/drivers/mfd/cs47l90-tables.c +++ b/drivers/mfd/cs47l90-tables.c | |||
@@ -263,6 +263,7 @@ static const struct reg_default cs47l90_reg_default[] = { | |||
263 | { 0x00000440, 0x003f }, /* R1088 (0x440) - DRE Enable */ | 263 | { 0x00000440, 0x003f }, /* R1088 (0x440) - DRE Enable */ |
264 | { 0x00000448, 0x003f }, /* R1096 (0x448) - eDRE Enable */ | 264 | { 0x00000448, 0x003f }, /* R1096 (0x448) - eDRE Enable */ |
265 | { 0x00000450, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 1 */ | 265 | { 0x00000450, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 1 */ |
266 | { 0x00000451, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 2 */ | ||
266 | { 0x00000458, 0x0000 }, /* R1112 (0x458) - Noise Gate Control */ | 267 | { 0x00000458, 0x0000 }, /* R1112 (0x458) - Noise Gate Control */ |
267 | { 0x00000490, 0x0069 }, /* R1168 (0x490) - PDM SPK1 CTRL 1 */ | 268 | { 0x00000490, 0x0069 }, /* R1168 (0x490) - PDM SPK1 CTRL 1 */ |
268 | { 0x00000491, 0x0000 }, /* R1169 (0x491) - PDM SPK1 CTRL 2 */ | 269 | { 0x00000491, 0x0000 }, /* R1169 (0x491) - PDM SPK1 CTRL 2 */ |
@@ -1692,6 +1693,7 @@ static bool cs47l90_16bit_readable_register(struct device *dev, | |||
1692 | case MADERA_DRE_ENABLE: | 1693 | case MADERA_DRE_ENABLE: |
1693 | case MADERA_EDRE_ENABLE: | 1694 | case MADERA_EDRE_ENABLE: |
1694 | case MADERA_DAC_AEC_CONTROL_1: | 1695 | case MADERA_DAC_AEC_CONTROL_1: |
1696 | case MADERA_DAC_AEC_CONTROL_2: | ||
1695 | case MADERA_NOISE_GATE_CONTROL: | 1697 | case MADERA_NOISE_GATE_CONTROL: |
1696 | case MADERA_PDM_SPK1_CTRL_1: | 1698 | case MADERA_PDM_SPK1_CTRL_1: |
1697 | case MADERA_PDM_SPK1_CTRL_2: | 1699 | case MADERA_PDM_SPK1_CTRL_2: |
diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c index 6e4ce49b4405..b125f90dd375 100644 --- a/drivers/mfd/da9063-core.c +++ b/drivers/mfd/da9063-core.c | |||
@@ -1,5 +1,6 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
1 | /* | 2 | /* |
2 | * da9063-core.c: Device access for Dialog DA9063 modules | 3 | * Device access for Dialog DA9063 modules |
3 | * | 4 | * |
4 | * Copyright 2012 Dialog Semiconductors Ltd. | 5 | * Copyright 2012 Dialog Semiconductors Ltd. |
5 | * Copyright 2013 Philipp Zabel, Pengutronix | 6 | * Copyright 2013 Philipp Zabel, Pengutronix |
@@ -7,11 +8,6 @@ | |||
7 | * Author: Krystian Garbaciak, Dialog Semiconductor | 8 | * Author: Krystian Garbaciak, Dialog Semiconductor |
8 | * Author: Michal Hajduk, Dialog Semiconductor | 9 | * Author: Michal Hajduk, Dialog Semiconductor |
9 | * | 10 | * |
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | 11 | */ |
16 | 12 | ||
17 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
@@ -26,7 +22,6 @@ | |||
26 | #include <linux/regmap.h> | 22 | #include <linux/regmap.h> |
27 | 23 | ||
28 | #include <linux/mfd/da9063/core.h> | 24 | #include <linux/mfd/da9063/core.h> |
29 | #include <linux/mfd/da9063/pdata.h> | ||
30 | #include <linux/mfd/da9063/registers.h> | 25 | #include <linux/mfd/da9063/registers.h> |
31 | 26 | ||
32 | #include <linux/proc_fs.h> | 27 | #include <linux/proc_fs.h> |
@@ -165,7 +160,6 @@ static int da9063_clear_fault_log(struct da9063 *da9063) | |||
165 | 160 | ||
166 | int da9063_device_init(struct da9063 *da9063, unsigned int irq) | 161 | int da9063_device_init(struct da9063 *da9063, unsigned int irq) |
167 | { | 162 | { |
168 | struct da9063_pdata *pdata = da9063->dev->platform_data; | ||
169 | int model, variant_id, variant_code; | 163 | int model, variant_id, variant_code; |
170 | int ret; | 164 | int ret; |
171 | 165 | ||
@@ -173,24 +167,10 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq) | |||
173 | if (ret < 0) | 167 | if (ret < 0) |
174 | dev_err(da9063->dev, "Cannot clear fault log\n"); | 168 | dev_err(da9063->dev, "Cannot clear fault log\n"); |
175 | 169 | ||
176 | if (pdata) { | 170 | da9063->flags = 0; |
177 | da9063->flags = pdata->flags; | 171 | da9063->irq_base = -1; |
178 | da9063->irq_base = pdata->irq_base; | ||
179 | } else { | ||
180 | da9063->flags = 0; | ||
181 | da9063->irq_base = -1; | ||
182 | } | ||
183 | da9063->chip_irq = irq; | 172 | da9063->chip_irq = irq; |
184 | 173 | ||
185 | if (pdata && pdata->init != NULL) { | ||
186 | ret = pdata->init(da9063); | ||
187 | if (ret != 0) { | ||
188 | dev_err(da9063->dev, | ||
189 | "Platform initialization failed.\n"); | ||
190 | return ret; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_ID, &model); | 174 | ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_ID, &model); |
195 | if (ret < 0) { | 175 | if (ret < 0) { |
196 | dev_err(da9063->dev, "Cannot read chip model id.\n"); | 176 | dev_err(da9063->dev, "Cannot read chip model id.\n"); |
diff --git a/drivers/mfd/da9063-i2c.c b/drivers/mfd/da9063-i2c.c index 50a24b1921d0..455de74c0dd2 100644 --- a/drivers/mfd/da9063-i2c.c +++ b/drivers/mfd/da9063-i2c.c | |||
@@ -1,15 +1,10 @@ | |||
1 | /* da9063-i2c.c: Interrupt support for Dialog DA9063 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* I2C support for Dialog DA9063 | ||
2 | * | 3 | * |
3 | * Copyright 2012 Dialog Semiconductor Ltd. | 4 | * Copyright 2012 Dialog Semiconductor Ltd. |
4 | * Copyright 2013 Philipp Zabel, Pengutronix | 5 | * Copyright 2013 Philipp Zabel, Pengutronix |
5 | * | 6 | * |
6 | * Author: Krystian Garbaciak, Dialog Semiconductor | 7 | * Author: Krystian Garbaciak, Dialog Semiconductor |
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | 8 | */ |
14 | 9 | ||
15 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
@@ -22,7 +17,6 @@ | |||
22 | 17 | ||
23 | #include <linux/mfd/core.h> | 18 | #include <linux/mfd/core.h> |
24 | #include <linux/mfd/da9063/core.h> | 19 | #include <linux/mfd/da9063/core.h> |
25 | #include <linux/mfd/da9063/pdata.h> | ||
26 | #include <linux/mfd/da9063/registers.h> | 20 | #include <linux/mfd/da9063/registers.h> |
27 | 21 | ||
28 | #include <linux/of.h> | 22 | #include <linux/of.h> |
diff --git a/drivers/mfd/da9063-irq.c b/drivers/mfd/da9063-irq.c index ecc0c8ce6c58..e2bbedf58e68 100644 --- a/drivers/mfd/da9063-irq.c +++ b/drivers/mfd/da9063-irq.c | |||
@@ -1,15 +1,10 @@ | |||
1 | /* da9063-irq.c: Interrupts support for Dialog DA9063 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* Interrupt support for Dialog DA9063 | ||
2 | * | 3 | * |
3 | * Copyright 2012 Dialog Semiconductor Ltd. | 4 | * Copyright 2012 Dialog Semiconductor Ltd. |
4 | * Copyright 2013 Philipp Zabel, Pengutronix | 5 | * Copyright 2013 Philipp Zabel, Pengutronix |
5 | * | 6 | * |
6 | * Author: Michal Hajduk, Dialog Semiconductor | 7 | * Author: Michal Hajduk, Dialog Semiconductor |
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | 8 | */ |
14 | 9 | ||
15 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
@@ -19,7 +14,6 @@ | |||
19 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
20 | #include <linux/regmap.h> | 15 | #include <linux/regmap.h> |
21 | #include <linux/mfd/da9063/core.h> | 16 | #include <linux/mfd/da9063/core.h> |
22 | #include <linux/mfd/da9063/pdata.h> | ||
23 | 17 | ||
24 | #define DA9063_REG_EVENT_A_OFFSET 0 | 18 | #define DA9063_REG_EVENT_A_OFFSET 0 |
25 | #define DA9063_REG_EVENT_B_OFFSET 1 | 19 | #define DA9063_REG_EVENT_B_OFFSET 1 |
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index cba2eb166650..6b111be944d9 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c | |||
@@ -129,6 +129,19 @@ static const struct intel_lpss_platform_info cnl_i2c_info = { | |||
129 | }; | 129 | }; |
130 | 130 | ||
131 | static const struct pci_device_id intel_lpss_pci_ids[] = { | 131 | static const struct pci_device_id intel_lpss_pci_ids[] = { |
132 | /* CML */ | ||
133 | { PCI_VDEVICE(INTEL, 0x02a8), (kernel_ulong_t)&spt_uart_info }, | ||
134 | { PCI_VDEVICE(INTEL, 0x02a9), (kernel_ulong_t)&spt_uart_info }, | ||
135 | { PCI_VDEVICE(INTEL, 0x02aa), (kernel_ulong_t)&spt_info }, | ||
136 | { PCI_VDEVICE(INTEL, 0x02ab), (kernel_ulong_t)&spt_info }, | ||
137 | { PCI_VDEVICE(INTEL, 0x02c5), (kernel_ulong_t)&cnl_i2c_info }, | ||
138 | { PCI_VDEVICE(INTEL, 0x02c6), (kernel_ulong_t)&cnl_i2c_info }, | ||
139 | { PCI_VDEVICE(INTEL, 0x02c7), (kernel_ulong_t)&spt_uart_info }, | ||
140 | { PCI_VDEVICE(INTEL, 0x02e8), (kernel_ulong_t)&cnl_i2c_info }, | ||
141 | { PCI_VDEVICE(INTEL, 0x02e9), (kernel_ulong_t)&cnl_i2c_info }, | ||
142 | { PCI_VDEVICE(INTEL, 0x02ea), (kernel_ulong_t)&cnl_i2c_info }, | ||
143 | { PCI_VDEVICE(INTEL, 0x02eb), (kernel_ulong_t)&cnl_i2c_info }, | ||
144 | { PCI_VDEVICE(INTEL, 0x02fb), (kernel_ulong_t)&spt_info }, | ||
132 | /* BXT A-Step */ | 145 | /* BXT A-Step */ |
133 | { PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info }, | 146 | { PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info }, |
134 | { PCI_VDEVICE(INTEL, 0x0aae), (kernel_ulong_t)&bxt_i2c_info }, | 147 | { PCI_VDEVICE(INTEL, 0x0aae), (kernel_ulong_t)&bxt_i2c_info }, |
diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c index 45221e092ecf..7e425ff53491 100644 --- a/drivers/mfd/intel-lpss.c +++ b/drivers/mfd/intel-lpss.c | |||
@@ -273,6 +273,9 @@ static void intel_lpss_init_dev(const struct intel_lpss *lpss) | |||
273 | { | 273 | { |
274 | u32 value = LPSS_PRIV_SSP_REG_DIS_DMA_FIN; | 274 | u32 value = LPSS_PRIV_SSP_REG_DIS_DMA_FIN; |
275 | 275 | ||
276 | /* Set the device in reset state */ | ||
277 | writel(0, lpss->priv + LPSS_PRIV_RESETS); | ||
278 | |||
276 | intel_lpss_deassert_reset(lpss); | 279 | intel_lpss_deassert_reset(lpss); |
277 | 280 | ||
278 | intel_lpss_set_remap_addr(lpss); | 281 | intel_lpss_set_remap_addr(lpss); |
diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index 5bddb84cfc1f..11adbf77960d 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c | |||
@@ -74,16 +74,6 @@ static const struct dmi_system_id dmi_platform_info[] = { | |||
74 | { | 74 | { |
75 | .matches = { | 75 | .matches = { |
76 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"), | 76 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"), |
77 | DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG, | ||
78 | "6ES7647-0AA00-0YA2"), | ||
79 | }, | ||
80 | .driver_data = (void *)400000, | ||
81 | }, | ||
82 | { | ||
83 | .matches = { | ||
84 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"), | ||
85 | DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG, | ||
86 | "6ES7647-0AA00-1YA2"), | ||
87 | }, | 77 | }, |
88 | .driver_data = (void *)400000, | 78 | .driver_data = (void *)400000, |
89 | }, | 79 | }, |
diff --git a/drivers/mfd/intel_soc_pmic_chtwc.c b/drivers/mfd/intel_soc_pmic_chtwc.c index 64a3aece9c5e..be84bb2aa837 100644 --- a/drivers/mfd/intel_soc_pmic_chtwc.c +++ b/drivers/mfd/intel_soc_pmic_chtwc.c | |||
@@ -60,6 +60,7 @@ static struct mfd_cell cht_wc_dev[] = { | |||
60 | .resources = cht_wc_ext_charger_resources, | 60 | .resources = cht_wc_ext_charger_resources, |
61 | }, | 61 | }, |
62 | { .name = "cht_wcove_region", }, | 62 | { .name = "cht_wcove_region", }, |
63 | { .name = "cht_wcove_leds", }, | ||
63 | }; | 64 | }; |
64 | 65 | ||
65 | /* | 66 | /* |
diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c index d8ddd1a6f304..436361ce3737 100644 --- a/drivers/mfd/max77620.c +++ b/drivers/mfd/max77620.c | |||
@@ -37,6 +37,8 @@ | |||
37 | #include <linux/regmap.h> | 37 | #include <linux/regmap.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | 39 | ||
40 | static struct max77620_chip *max77620_scratch; | ||
41 | |||
40 | static const struct resource gpio_resources[] = { | 42 | static const struct resource gpio_resources[] = { |
41 | DEFINE_RES_IRQ(MAX77620_IRQ_TOP_GPIO), | 43 | DEFINE_RES_IRQ(MAX77620_IRQ_TOP_GPIO), |
42 | }; | 44 | }; |
@@ -111,6 +113,26 @@ static const struct mfd_cell max20024_children[] = { | |||
111 | }, | 113 | }, |
112 | }; | 114 | }; |
113 | 115 | ||
116 | static const struct mfd_cell max77663_children[] = { | ||
117 | { .name = "max77620-pinctrl", }, | ||
118 | { .name = "max77620-clock", }, | ||
119 | { .name = "max77663-pmic", }, | ||
120 | { .name = "max77620-watchdog", }, | ||
121 | { | ||
122 | .name = "max77620-gpio", | ||
123 | .resources = gpio_resources, | ||
124 | .num_resources = ARRAY_SIZE(gpio_resources), | ||
125 | }, { | ||
126 | .name = "max77620-rtc", | ||
127 | .resources = rtc_resources, | ||
128 | .num_resources = ARRAY_SIZE(rtc_resources), | ||
129 | }, { | ||
130 | .name = "max77663-power", | ||
131 | .resources = power_resources, | ||
132 | .num_resources = ARRAY_SIZE(power_resources), | ||
133 | }, | ||
134 | }; | ||
135 | |||
114 | static const struct regmap_range max77620_readable_ranges[] = { | 136 | static const struct regmap_range max77620_readable_ranges[] = { |
115 | regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4), | 137 | regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4), |
116 | }; | 138 | }; |
@@ -171,6 +193,35 @@ static const struct regmap_config max20024_regmap_config = { | |||
171 | .volatile_table = &max77620_volatile_table, | 193 | .volatile_table = &max77620_volatile_table, |
172 | }; | 194 | }; |
173 | 195 | ||
196 | static const struct regmap_range max77663_readable_ranges[] = { | ||
197 | regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_CID5), | ||
198 | }; | ||
199 | |||
200 | static const struct regmap_access_table max77663_readable_table = { | ||
201 | .yes_ranges = max77663_readable_ranges, | ||
202 | .n_yes_ranges = ARRAY_SIZE(max77663_readable_ranges), | ||
203 | }; | ||
204 | |||
205 | static const struct regmap_range max77663_writable_ranges[] = { | ||
206 | regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_CID5), | ||
207 | }; | ||
208 | |||
209 | static const struct regmap_access_table max77663_writable_table = { | ||
210 | .yes_ranges = max77663_writable_ranges, | ||
211 | .n_yes_ranges = ARRAY_SIZE(max77663_writable_ranges), | ||
212 | }; | ||
213 | |||
214 | static const struct regmap_config max77663_regmap_config = { | ||
215 | .name = "power-slave", | ||
216 | .reg_bits = 8, | ||
217 | .val_bits = 8, | ||
218 | .max_register = MAX77620_REG_CID5 + 1, | ||
219 | .cache_type = REGCACHE_RBTREE, | ||
220 | .rd_table = &max77663_readable_table, | ||
221 | .wr_table = &max77663_writable_table, | ||
222 | .volatile_table = &max77620_volatile_table, | ||
223 | }; | ||
224 | |||
174 | /* | 225 | /* |
175 | * MAX77620 and MAX20024 has the following steps of the interrupt handling | 226 | * MAX77620 and MAX20024 has the following steps of the interrupt handling |
176 | * for TOP interrupts: | 227 | * for TOP interrupts: |
@@ -240,6 +291,9 @@ static int max77620_get_fps_period_reg_value(struct max77620_chip *chip, | |||
240 | case MAX77620: | 291 | case MAX77620: |
241 | fps_min_period = MAX77620_FPS_PERIOD_MIN_US; | 292 | fps_min_period = MAX77620_FPS_PERIOD_MIN_US; |
242 | break; | 293 | break; |
294 | case MAX77663: | ||
295 | fps_min_period = MAX20024_FPS_PERIOD_MIN_US; | ||
296 | break; | ||
243 | default: | 297 | default: |
244 | return -EINVAL; | 298 | return -EINVAL; |
245 | } | 299 | } |
@@ -274,6 +328,9 @@ static int max77620_config_fps(struct max77620_chip *chip, | |||
274 | case MAX77620: | 328 | case MAX77620: |
275 | fps_max_period = MAX77620_FPS_PERIOD_MAX_US; | 329 | fps_max_period = MAX77620_FPS_PERIOD_MAX_US; |
276 | break; | 330 | break; |
331 | case MAX77663: | ||
332 | fps_max_period = MAX20024_FPS_PERIOD_MAX_US; | ||
333 | break; | ||
277 | default: | 334 | default: |
278 | return -EINVAL; | 335 | return -EINVAL; |
279 | } | 336 | } |
@@ -375,6 +432,9 @@ static int max77620_initialise_fps(struct max77620_chip *chip) | |||
375 | } | 432 | } |
376 | 433 | ||
377 | skip_fps: | 434 | skip_fps: |
435 | if (chip->chip_id == MAX77663) | ||
436 | return 0; | ||
437 | |||
378 | /* Enable wake on EN0 pin */ | 438 | /* Enable wake on EN0 pin */ |
379 | ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2, | 439 | ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2, |
380 | MAX77620_ONOFFCNFG2_WK_EN0, | 440 | MAX77620_ONOFFCNFG2_WK_EN0, |
@@ -423,6 +483,15 @@ static int max77620_read_es_version(struct max77620_chip *chip) | |||
423 | return ret; | 483 | return ret; |
424 | } | 484 | } |
425 | 485 | ||
486 | static void max77620_pm_power_off(void) | ||
487 | { | ||
488 | struct max77620_chip *chip = max77620_scratch; | ||
489 | |||
490 | regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG1, | ||
491 | MAX77620_ONOFFCNFG1_SFT_RST, | ||
492 | MAX77620_ONOFFCNFG1_SFT_RST); | ||
493 | } | ||
494 | |||
426 | static int max77620_probe(struct i2c_client *client, | 495 | static int max77620_probe(struct i2c_client *client, |
427 | const struct i2c_device_id *id) | 496 | const struct i2c_device_id *id) |
428 | { | 497 | { |
@@ -430,6 +499,7 @@ static int max77620_probe(struct i2c_client *client, | |||
430 | struct max77620_chip *chip; | 499 | struct max77620_chip *chip; |
431 | const struct mfd_cell *mfd_cells; | 500 | const struct mfd_cell *mfd_cells; |
432 | int n_mfd_cells; | 501 | int n_mfd_cells; |
502 | bool pm_off; | ||
433 | int ret; | 503 | int ret; |
434 | 504 | ||
435 | chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); | 505 | chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); |
@@ -453,6 +523,11 @@ static int max77620_probe(struct i2c_client *client, | |||
453 | n_mfd_cells = ARRAY_SIZE(max20024_children); | 523 | n_mfd_cells = ARRAY_SIZE(max20024_children); |
454 | rmap_config = &max20024_regmap_config; | 524 | rmap_config = &max20024_regmap_config; |
455 | break; | 525 | break; |
526 | case MAX77663: | ||
527 | mfd_cells = max77663_children; | ||
528 | n_mfd_cells = ARRAY_SIZE(max77663_children); | ||
529 | rmap_config = &max77663_regmap_config; | ||
530 | break; | ||
456 | default: | 531 | default: |
457 | dev_err(chip->dev, "ChipID is invalid %d\n", chip->chip_id); | 532 | dev_err(chip->dev, "ChipID is invalid %d\n", chip->chip_id); |
458 | return -EINVAL; | 533 | return -EINVAL; |
@@ -491,6 +566,12 @@ static int max77620_probe(struct i2c_client *client, | |||
491 | return ret; | 566 | return ret; |
492 | } | 567 | } |
493 | 568 | ||
569 | pm_off = of_device_is_system_power_controller(client->dev.of_node); | ||
570 | if (pm_off && !pm_power_off) { | ||
571 | max77620_scratch = chip; | ||
572 | pm_power_off = max77620_pm_power_off; | ||
573 | } | ||
574 | |||
494 | return 0; | 575 | return 0; |
495 | } | 576 | } |
496 | 577 | ||
@@ -546,6 +627,9 @@ static int max77620_i2c_suspend(struct device *dev) | |||
546 | return ret; | 627 | return ret; |
547 | } | 628 | } |
548 | 629 | ||
630 | if (chip->chip_id == MAX77663) | ||
631 | goto out; | ||
632 | |||
549 | /* Disable WK_EN0 */ | 633 | /* Disable WK_EN0 */ |
550 | ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2, | 634 | ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2, |
551 | MAX77620_ONOFFCNFG2_WK_EN0, 0); | 635 | MAX77620_ONOFFCNFG2_WK_EN0, 0); |
@@ -581,7 +665,7 @@ static int max77620_i2c_resume(struct device *dev) | |||
581 | * For MAX20024: No need to configure WKEN0 on resume as | 665 | * For MAX20024: No need to configure WKEN0 on resume as |
582 | * it is configured on Init. | 666 | * it is configured on Init. |
583 | */ | 667 | */ |
584 | if (chip->chip_id == MAX20024) | 668 | if (chip->chip_id == MAX20024 || chip->chip_id == MAX77663) |
585 | goto out; | 669 | goto out; |
586 | 670 | ||
587 | /* Enable WK_EN0 */ | 671 | /* Enable WK_EN0 */ |
@@ -603,6 +687,7 @@ out: | |||
603 | static const struct i2c_device_id max77620_id[] = { | 687 | static const struct i2c_device_id max77620_id[] = { |
604 | {"max77620", MAX77620}, | 688 | {"max77620", MAX77620}, |
605 | {"max20024", MAX20024}, | 689 | {"max20024", MAX20024}, |
690 | {"max77663", MAX77663}, | ||
606 | {}, | 691 | {}, |
607 | }; | 692 | }; |
608 | 693 | ||
diff --git a/drivers/mfd/max77650.c b/drivers/mfd/max77650.c new file mode 100644 index 000000000000..60e07aca6ae5 --- /dev/null +++ b/drivers/mfd/max77650.c | |||
@@ -0,0 +1,232 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // | ||
3 | // Copyright (C) 2018 BayLibre SAS | ||
4 | // Author: Bartosz Golaszewski <bgolaszewski@baylibre.com> | ||
5 | // | ||
6 | // Core MFD driver for MAXIM 77650/77651 charger/power-supply. | ||
7 | // Programming manual: https://pdfserv.maximintegrated.com/en/an/AN6428.pdf | ||
8 | |||
9 | #include <linux/i2c.h> | ||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/irq.h> | ||
12 | #include <linux/mfd/core.h> | ||
13 | #include <linux/mfd/max77650.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/of.h> | ||
16 | #include <linux/regmap.h> | ||
17 | |||
18 | #define MAX77650_INT_GPI_F_MSK BIT(0) | ||
19 | #define MAX77650_INT_GPI_R_MSK BIT(1) | ||
20 | #define MAX77650_INT_GPI_MSK \ | ||
21 | (MAX77650_INT_GPI_F_MSK | MAX77650_INT_GPI_R_MSK) | ||
22 | #define MAX77650_INT_nEN_F_MSK BIT(2) | ||
23 | #define MAX77650_INT_nEN_R_MSK BIT(3) | ||
24 | #define MAX77650_INT_TJAL1_R_MSK BIT(4) | ||
25 | #define MAX77650_INT_TJAL2_R_MSK BIT(5) | ||
26 | #define MAX77650_INT_DOD_R_MSK BIT(6) | ||
27 | |||
28 | #define MAX77650_INT_THM_MSK BIT(0) | ||
29 | #define MAX77650_INT_CHG_MSK BIT(1) | ||
30 | #define MAX77650_INT_CHGIN_MSK BIT(2) | ||
31 | #define MAX77650_INT_TJ_REG_MSK BIT(3) | ||
32 | #define MAX77650_INT_CHGIN_CTRL_MSK BIT(4) | ||
33 | #define MAX77650_INT_SYS_CTRL_MSK BIT(5) | ||
34 | #define MAX77650_INT_SYS_CNFG_MSK BIT(6) | ||
35 | |||
36 | #define MAX77650_INT_GLBL_OFFSET 0 | ||
37 | #define MAX77650_INT_CHG_OFFSET 1 | ||
38 | |||
39 | #define MAX77650_SBIA_LPM_MASK BIT(5) | ||
40 | #define MAX77650_SBIA_LPM_DISABLED 0x00 | ||
41 | |||
42 | enum { | ||
43 | MAX77650_INT_GPI, | ||
44 | MAX77650_INT_nEN_F, | ||
45 | MAX77650_INT_nEN_R, | ||
46 | MAX77650_INT_TJAL1_R, | ||
47 | MAX77650_INT_TJAL2_R, | ||
48 | MAX77650_INT_DOD_R, | ||
49 | MAX77650_INT_THM, | ||
50 | MAX77650_INT_CHG, | ||
51 | MAX77650_INT_CHGIN, | ||
52 | MAX77650_INT_TJ_REG, | ||
53 | MAX77650_INT_CHGIN_CTRL, | ||
54 | MAX77650_INT_SYS_CTRL, | ||
55 | MAX77650_INT_SYS_CNFG, | ||
56 | }; | ||
57 | |||
58 | static const struct resource max77650_charger_resources[] = { | ||
59 | DEFINE_RES_IRQ_NAMED(MAX77650_INT_CHG, "CHG"), | ||
60 | DEFINE_RES_IRQ_NAMED(MAX77650_INT_CHGIN, "CHGIN"), | ||
61 | }; | ||
62 | |||
63 | static const struct resource max77650_gpio_resources[] = { | ||
64 | DEFINE_RES_IRQ_NAMED(MAX77650_INT_GPI, "GPI"), | ||
65 | }; | ||
66 | |||
67 | static const struct resource max77650_onkey_resources[] = { | ||
68 | DEFINE_RES_IRQ_NAMED(MAX77650_INT_nEN_F, "nEN_F"), | ||
69 | DEFINE_RES_IRQ_NAMED(MAX77650_INT_nEN_R, "nEN_R"), | ||
70 | }; | ||
71 | |||
72 | static const struct mfd_cell max77650_cells[] = { | ||
73 | { | ||
74 | .name = "max77650-regulator", | ||
75 | .of_compatible = "maxim,max77650-regulator", | ||
76 | }, { | ||
77 | .name = "max77650-charger", | ||
78 | .of_compatible = "maxim,max77650-charger", | ||
79 | .resources = max77650_charger_resources, | ||
80 | .num_resources = ARRAY_SIZE(max77650_charger_resources), | ||
81 | }, { | ||
82 | .name = "max77650-gpio", | ||
83 | .of_compatible = "maxim,max77650-gpio", | ||
84 | .resources = max77650_gpio_resources, | ||
85 | .num_resources = ARRAY_SIZE(max77650_gpio_resources), | ||
86 | }, { | ||
87 | .name = "max77650-led", | ||
88 | .of_compatible = "maxim,max77650-led", | ||
89 | }, { | ||
90 | .name = "max77650-onkey", | ||
91 | .of_compatible = "maxim,max77650-onkey", | ||
92 | .resources = max77650_onkey_resources, | ||
93 | .num_resources = ARRAY_SIZE(max77650_onkey_resources), | ||
94 | }, | ||
95 | }; | ||
96 | |||
97 | static const struct regmap_irq max77650_irqs[] = { | ||
98 | [MAX77650_INT_GPI] = { | ||
99 | .reg_offset = MAX77650_INT_GLBL_OFFSET, | ||
100 | .mask = MAX77650_INT_GPI_MSK, | ||
101 | .type = { | ||
102 | .type_falling_val = MAX77650_INT_GPI_F_MSK, | ||
103 | .type_rising_val = MAX77650_INT_GPI_R_MSK, | ||
104 | .types_supported = IRQ_TYPE_EDGE_BOTH, | ||
105 | }, | ||
106 | }, | ||
107 | REGMAP_IRQ_REG(MAX77650_INT_nEN_F, | ||
108 | MAX77650_INT_GLBL_OFFSET, MAX77650_INT_nEN_F_MSK), | ||
109 | REGMAP_IRQ_REG(MAX77650_INT_nEN_R, | ||
110 | MAX77650_INT_GLBL_OFFSET, MAX77650_INT_nEN_R_MSK), | ||
111 | REGMAP_IRQ_REG(MAX77650_INT_TJAL1_R, | ||
112 | MAX77650_INT_GLBL_OFFSET, MAX77650_INT_TJAL1_R_MSK), | ||
113 | REGMAP_IRQ_REG(MAX77650_INT_TJAL2_R, | ||
114 | MAX77650_INT_GLBL_OFFSET, MAX77650_INT_TJAL2_R_MSK), | ||
115 | REGMAP_IRQ_REG(MAX77650_INT_DOD_R, | ||
116 | MAX77650_INT_GLBL_OFFSET, MAX77650_INT_DOD_R_MSK), | ||
117 | REGMAP_IRQ_REG(MAX77650_INT_THM, | ||
118 | MAX77650_INT_CHG_OFFSET, MAX77650_INT_THM_MSK), | ||
119 | REGMAP_IRQ_REG(MAX77650_INT_CHG, | ||
120 | MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHG_MSK), | ||
121 | REGMAP_IRQ_REG(MAX77650_INT_CHGIN, | ||
122 | MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHGIN_MSK), | ||
123 | REGMAP_IRQ_REG(MAX77650_INT_TJ_REG, | ||
124 | MAX77650_INT_CHG_OFFSET, MAX77650_INT_TJ_REG_MSK), | ||
125 | REGMAP_IRQ_REG(MAX77650_INT_CHGIN_CTRL, | ||
126 | MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHGIN_CTRL_MSK), | ||
127 | REGMAP_IRQ_REG(MAX77650_INT_SYS_CTRL, | ||
128 | MAX77650_INT_CHG_OFFSET, MAX77650_INT_SYS_CTRL_MSK), | ||
129 | REGMAP_IRQ_REG(MAX77650_INT_SYS_CNFG, | ||
130 | MAX77650_INT_CHG_OFFSET, MAX77650_INT_SYS_CNFG_MSK), | ||
131 | }; | ||
132 | |||
133 | static const struct regmap_irq_chip max77650_irq_chip = { | ||
134 | .name = "max77650-irq", | ||
135 | .irqs = max77650_irqs, | ||
136 | .num_irqs = ARRAY_SIZE(max77650_irqs), | ||
137 | .num_regs = 2, | ||
138 | .status_base = MAX77650_REG_INT_GLBL, | ||
139 | .mask_base = MAX77650_REG_INTM_GLBL, | ||
140 | .type_in_mask = true, | ||
141 | .type_invert = true, | ||
142 | .init_ack_masked = true, | ||
143 | .clear_on_unmask = true, | ||
144 | }; | ||
145 | |||
146 | static const struct regmap_config max77650_regmap_config = { | ||
147 | .name = "max77650", | ||
148 | .reg_bits = 8, | ||
149 | .val_bits = 8, | ||
150 | }; | ||
151 | |||
152 | static int max77650_i2c_probe(struct i2c_client *i2c) | ||
153 | { | ||
154 | struct regmap_irq_chip_data *irq_data; | ||
155 | struct device *dev = &i2c->dev; | ||
156 | struct irq_domain *domain; | ||
157 | struct regmap *map; | ||
158 | unsigned int val; | ||
159 | int rv, id; | ||
160 | |||
161 | map = devm_regmap_init_i2c(i2c, &max77650_regmap_config); | ||
162 | if (IS_ERR(map)) { | ||
163 | dev_err(dev, "Unable to initialise I2C Regmap\n"); | ||
164 | return PTR_ERR(map); | ||
165 | } | ||
166 | |||
167 | rv = regmap_read(map, MAX77650_REG_CID, &val); | ||
168 | if (rv) { | ||
169 | dev_err(dev, "Unable to read Chip ID\n"); | ||
170 | return rv; | ||
171 | } | ||
172 | |||
173 | id = MAX77650_CID_BITS(val); | ||
174 | switch (id) { | ||
175 | case MAX77650_CID_77650A: | ||
176 | case MAX77650_CID_77650C: | ||
177 | case MAX77650_CID_77651A: | ||
178 | case MAX77650_CID_77651B: | ||
179 | break; | ||
180 | default: | ||
181 | dev_err(dev, "Chip not supported - ID: 0x%02x\n", id); | ||
182 | return -ENODEV; | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * This IC has a low-power mode which reduces the quiescent current | ||
187 | * consumption to ~5.6uA but is only suitable for systems consuming | ||
188 | * less than ~2mA. Since this is not likely the case even on | ||
189 | * linux-based wearables - keep the chip in normal power mode. | ||
190 | */ | ||
191 | rv = regmap_update_bits(map, | ||
192 | MAX77650_REG_CNFG_GLBL, | ||
193 | MAX77650_SBIA_LPM_MASK, | ||
194 | MAX77650_SBIA_LPM_DISABLED); | ||
195 | if (rv) { | ||
196 | dev_err(dev, "Unable to change the power mode\n"); | ||
197 | return rv; | ||
198 | } | ||
199 | |||
200 | rv = devm_regmap_add_irq_chip(dev, map, i2c->irq, | ||
201 | IRQF_ONESHOT | IRQF_SHARED, 0, | ||
202 | &max77650_irq_chip, &irq_data); | ||
203 | if (rv) { | ||
204 | dev_err(dev, "Unable to add Regmap IRQ chip\n"); | ||
205 | return rv; | ||
206 | } | ||
207 | |||
208 | domain = regmap_irq_get_domain(irq_data); | ||
209 | |||
210 | return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, | ||
211 | max77650_cells, ARRAY_SIZE(max77650_cells), | ||
212 | NULL, 0, domain); | ||
213 | } | ||
214 | |||
215 | static const struct of_device_id max77650_of_match[] = { | ||
216 | { .compatible = "maxim,max77650" }, | ||
217 | { } | ||
218 | }; | ||
219 | MODULE_DEVICE_TABLE(of, max77650_of_match); | ||
220 | |||
221 | static struct i2c_driver max77650_i2c_driver = { | ||
222 | .driver = { | ||
223 | .name = "max77650", | ||
224 | .of_match_table = of_match_ptr(max77650_of_match), | ||
225 | }, | ||
226 | .probe_new = max77650_i2c_probe, | ||
227 | }; | ||
228 | module_i2c_driver(max77650_i2c_driver); | ||
229 | |||
230 | MODULE_DESCRIPTION("MAXIM 77650/77651 multi-function core driver"); | ||
231 | MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); | ||
232 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 94e3f32ce935..1ade4c8cc91f 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c | |||
@@ -269,6 +269,19 @@ fail_alloc: | |||
269 | return ret; | 269 | return ret; |
270 | } | 270 | } |
271 | 271 | ||
272 | /** | ||
273 | * mfd_add_devices - register child devices | ||
274 | * | ||
275 | * @parent: Pointer to parent device. | ||
276 | * @id: Can be PLATFORM_DEVID_AUTO to let the Platform API take care | ||
277 | * of device numbering, or will be added to a device's cell_id. | ||
278 | * @cells: Array of (struct mfd_cell)s describing child devices. | ||
279 | * @n_devs: Number of child devices to register. | ||
280 | * @mem_base: Parent register range resource for child devices. | ||
281 | * @irq_base: Base of the range of virtual interrupt numbers allocated for | ||
282 | * this MFD device. Unused if @domain is specified. | ||
283 | * @domain: Interrupt domain to create mappings for hardware interrupts. | ||
284 | */ | ||
272 | int mfd_add_devices(struct device *parent, int id, | 285 | int mfd_add_devices(struct device *parent, int id, |
273 | const struct mfd_cell *cells, int n_devs, | 286 | const struct mfd_cell *cells, int n_devs, |
274 | struct resource *mem_base, | 287 | struct resource *mem_base, |
diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 216fbf6adec9..94377782d208 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c | |||
@@ -568,14 +568,6 @@ static int rk808_remove(struct i2c_client *client) | |||
568 | return 0; | 568 | return 0; |
569 | } | 569 | } |
570 | 570 | ||
571 | static const struct i2c_device_id rk808_ids[] = { | ||
572 | { "rk805" }, | ||
573 | { "rk808" }, | ||
574 | { "rk818" }, | ||
575 | { }, | ||
576 | }; | ||
577 | MODULE_DEVICE_TABLE(i2c, rk808_ids); | ||
578 | |||
579 | static struct i2c_driver rk808_i2c_driver = { | 571 | static struct i2c_driver rk808_i2c_driver = { |
580 | .driver = { | 572 | .driver = { |
581 | .name = "rk808", | 573 | .name = "rk808", |
@@ -583,7 +575,6 @@ static struct i2c_driver rk808_i2c_driver = { | |||
583 | }, | 575 | }, |
584 | .probe = rk808_probe, | 576 | .probe = rk808_probe, |
585 | .remove = rk808_remove, | 577 | .remove = rk808_remove, |
586 | .id_table = rk808_ids, | ||
587 | }; | 578 | }; |
588 | 579 | ||
589 | module_i2c_driver(rk808_i2c_driver); | 580 | module_i2c_driver(rk808_i2c_driver); |
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 521319086c81..95473ff9bb4b 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c | |||
@@ -28,45 +28,33 @@ | |||
28 | #include <linux/regmap.h> | 28 | #include <linux/regmap.h> |
29 | 29 | ||
30 | static const struct mfd_cell s5m8751_devs[] = { | 30 | static const struct mfd_cell s5m8751_devs[] = { |
31 | { | 31 | { .name = "s5m8751-pmic", }, |
32 | .name = "s5m8751-pmic", | 32 | { .name = "s5m-charger", }, |
33 | }, { | 33 | { .name = "s5m8751-codec", }, |
34 | .name = "s5m-charger", | ||
35 | }, { | ||
36 | .name = "s5m8751-codec", | ||
37 | }, | ||
38 | }; | 34 | }; |
39 | 35 | ||
40 | static const struct mfd_cell s5m8763_devs[] = { | 36 | static const struct mfd_cell s5m8763_devs[] = { |
41 | { | 37 | { .name = "s5m8763-pmic", }, |
42 | .name = "s5m8763-pmic", | 38 | { .name = "s5m-rtc", }, |
43 | }, { | 39 | { .name = "s5m-charger", }, |
44 | .name = "s5m-rtc", | ||
45 | }, { | ||
46 | .name = "s5m-charger", | ||
47 | }, | ||
48 | }; | 40 | }; |
49 | 41 | ||
50 | static const struct mfd_cell s5m8767_devs[] = { | 42 | static const struct mfd_cell s5m8767_devs[] = { |
43 | { .name = "s5m8767-pmic", }, | ||
44 | { .name = "s5m-rtc", }, | ||
51 | { | 45 | { |
52 | .name = "s5m8767-pmic", | ||
53 | }, { | ||
54 | .name = "s5m-rtc", | ||
55 | }, { | ||
56 | .name = "s5m8767-clk", | 46 | .name = "s5m8767-clk", |
57 | .of_compatible = "samsung,s5m8767-clk", | 47 | .of_compatible = "samsung,s5m8767-clk", |
58 | } | 48 | }, |
59 | }; | 49 | }; |
60 | 50 | ||
61 | static const struct mfd_cell s2mps11_devs[] = { | 51 | static const struct mfd_cell s2mps11_devs[] = { |
52 | { .name = "s2mps11-regulator", }, | ||
53 | { .name = "s2mps14-rtc", }, | ||
62 | { | 54 | { |
63 | .name = "s2mps11-regulator", | ||
64 | }, { | ||
65 | .name = "s2mps14-rtc", | ||
66 | }, { | ||
67 | .name = "s2mps11-clk", | 55 | .name = "s2mps11-clk", |
68 | .of_compatible = "samsung,s2mps11-clk", | 56 | .of_compatible = "samsung,s2mps11-clk", |
69 | } | 57 | }, |
70 | }; | 58 | }; |
71 | 59 | ||
72 | static const struct mfd_cell s2mps13_devs[] = { | 60 | static const struct mfd_cell s2mps13_devs[] = { |
@@ -79,37 +67,30 @@ static const struct mfd_cell s2mps13_devs[] = { | |||
79 | }; | 67 | }; |
80 | 68 | ||
81 | static const struct mfd_cell s2mps14_devs[] = { | 69 | static const struct mfd_cell s2mps14_devs[] = { |
70 | { .name = "s2mps14-regulator", }, | ||
71 | { .name = "s2mps14-rtc", }, | ||
82 | { | 72 | { |
83 | .name = "s2mps14-regulator", | ||
84 | }, { | ||
85 | .name = "s2mps14-rtc", | ||
86 | }, { | ||
87 | .name = "s2mps14-clk", | 73 | .name = "s2mps14-clk", |
88 | .of_compatible = "samsung,s2mps14-clk", | 74 | .of_compatible = "samsung,s2mps14-clk", |
89 | } | 75 | }, |
90 | }; | 76 | }; |
91 | 77 | ||
92 | static const struct mfd_cell s2mps15_devs[] = { | 78 | static const struct mfd_cell s2mps15_devs[] = { |
79 | { .name = "s2mps15-regulator", }, | ||
80 | { .name = "s2mps15-rtc", }, | ||
93 | { | 81 | { |
94 | .name = "s2mps15-regulator", | ||
95 | }, { | ||
96 | .name = "s2mps15-rtc", | ||
97 | }, { | ||
98 | .name = "s2mps13-clk", | 82 | .name = "s2mps13-clk", |
99 | .of_compatible = "samsung,s2mps13-clk", | 83 | .of_compatible = "samsung,s2mps13-clk", |
100 | }, | 84 | }, |
101 | }; | 85 | }; |
102 | 86 | ||
103 | static const struct mfd_cell s2mpa01_devs[] = { | 87 | static const struct mfd_cell s2mpa01_devs[] = { |
104 | { | 88 | { .name = "s2mpa01-pmic", }, |
105 | .name = "s2mpa01-pmic", | 89 | { .name = "s2mps14-rtc", }, |
106 | }, | ||
107 | }; | 90 | }; |
108 | 91 | ||
109 | static const struct mfd_cell s2mpu02_devs[] = { | 92 | static const struct mfd_cell s2mpu02_devs[] = { |
110 | { | 93 | { .name = "s2mpu02-regulator", }, |
111 | .name = "s2mpu02-regulator", | ||
112 | }, | ||
113 | }; | 94 | }; |
114 | 95 | ||
115 | #ifdef CONFIG_OF | 96 | #ifdef CONFIG_OF |
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index ad0099077e7e..a98c5d165039 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c | |||
@@ -455,6 +455,9 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) | |||
455 | case S5M8767X: | 455 | case S5M8767X: |
456 | sec_irq_chip = &s5m8767_irq_chip; | 456 | sec_irq_chip = &s5m8767_irq_chip; |
457 | break; | 457 | break; |
458 | case S2MPA01: | ||
459 | sec_irq_chip = &s2mps14_irq_chip; | ||
460 | break; | ||
458 | case S2MPS11X: | 461 | case S2MPS11X: |
459 | sec_irq_chip = &s2mps11_irq_chip; | 462 | sec_irq_chip = &s2mps11_irq_chip; |
460 | break; | 463 | break; |
diff --git a/drivers/mfd/ssbi.c b/drivers/mfd/ssbi.c index 36b96fee4ce6..0ae27cd30268 100644 --- a/drivers/mfd/ssbi.c +++ b/drivers/mfd/ssbi.c | |||
@@ -80,8 +80,6 @@ struct ssbi { | |||
80 | int (*write)(struct ssbi *, u16 addr, const u8 *buf, int len); | 80 | int (*write)(struct ssbi *, u16 addr, const u8 *buf, int len); |
81 | }; | 81 | }; |
82 | 82 | ||
83 | #define to_ssbi(dev) platform_get_drvdata(to_platform_device(dev)) | ||
84 | |||
85 | static inline u32 ssbi_readl(struct ssbi *ssbi, u32 reg) | 83 | static inline u32 ssbi_readl(struct ssbi *ssbi, u32 reg) |
86 | { | 84 | { |
87 | return readl(ssbi->base + reg); | 85 | return readl(ssbi->base + reg); |
@@ -243,7 +241,7 @@ err: | |||
243 | 241 | ||
244 | int ssbi_read(struct device *dev, u16 addr, u8 *buf, int len) | 242 | int ssbi_read(struct device *dev, u16 addr, u8 *buf, int len) |
245 | { | 243 | { |
246 | struct ssbi *ssbi = to_ssbi(dev); | 244 | struct ssbi *ssbi = dev_get_drvdata(dev); |
247 | unsigned long flags; | 245 | unsigned long flags; |
248 | int ret; | 246 | int ret; |
249 | 247 | ||
@@ -257,7 +255,7 @@ EXPORT_SYMBOL_GPL(ssbi_read); | |||
257 | 255 | ||
258 | int ssbi_write(struct device *dev, u16 addr, const u8 *buf, int len) | 256 | int ssbi_write(struct device *dev, u16 addr, const u8 *buf, int len) |
259 | { | 257 | { |
260 | struct ssbi *ssbi = to_ssbi(dev); | 258 | struct ssbi *ssbi = dev_get_drvdata(dev); |
261 | unsigned long flags; | 259 | unsigned long flags; |
262 | int ret; | 260 | int ret; |
263 | 261 | ||
diff --git a/drivers/mfd/stmfx.c b/drivers/mfd/stmfx.c new file mode 100644 index 000000000000..fe8efba2d45f --- /dev/null +++ b/drivers/mfd/stmfx.c | |||
@@ -0,0 +1,545 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Driver for STMicroelectronics Multi-Function eXpander (STMFX) core | ||
4 | * | ||
5 | * Copyright (C) 2019 STMicroelectronics | ||
6 | * Author(s): Amelie Delaunay <amelie.delaunay@st.com>. | ||
7 | */ | ||
8 | #include <linux/bitfield.h> | ||
9 | #include <linux/i2c.h> | ||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/irq.h> | ||
12 | #include <linux/mfd/core.h> | ||
13 | #include <linux/mfd/stmfx.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/regulator/consumer.h> | ||
16 | |||
17 | static bool stmfx_reg_volatile(struct device *dev, unsigned int reg) | ||
18 | { | ||
19 | switch (reg) { | ||
20 | case STMFX_REG_SYS_CTRL: | ||
21 | case STMFX_REG_IRQ_SRC_EN: | ||
22 | case STMFX_REG_IRQ_PENDING: | ||
23 | case STMFX_REG_IRQ_GPI_PENDING1: | ||
24 | case STMFX_REG_IRQ_GPI_PENDING2: | ||
25 | case STMFX_REG_IRQ_GPI_PENDING3: | ||
26 | case STMFX_REG_GPIO_STATE1: | ||
27 | case STMFX_REG_GPIO_STATE2: | ||
28 | case STMFX_REG_GPIO_STATE3: | ||
29 | case STMFX_REG_IRQ_GPI_SRC1: | ||
30 | case STMFX_REG_IRQ_GPI_SRC2: | ||
31 | case STMFX_REG_IRQ_GPI_SRC3: | ||
32 | case STMFX_REG_GPO_SET1: | ||
33 | case STMFX_REG_GPO_SET2: | ||
34 | case STMFX_REG_GPO_SET3: | ||
35 | case STMFX_REG_GPO_CLR1: | ||
36 | case STMFX_REG_GPO_CLR2: | ||
37 | case STMFX_REG_GPO_CLR3: | ||
38 | return true; | ||
39 | default: | ||
40 | return false; | ||
41 | } | ||
42 | } | ||
43 | |||
44 | static bool stmfx_reg_writeable(struct device *dev, unsigned int reg) | ||
45 | { | ||
46 | return (reg >= STMFX_REG_SYS_CTRL); | ||
47 | } | ||
48 | |||
49 | static const struct regmap_config stmfx_regmap_config = { | ||
50 | .reg_bits = 8, | ||
51 | .reg_stride = 1, | ||
52 | .val_bits = 8, | ||
53 | .max_register = STMFX_REG_MAX, | ||
54 | .volatile_reg = stmfx_reg_volatile, | ||
55 | .writeable_reg = stmfx_reg_writeable, | ||
56 | .cache_type = REGCACHE_RBTREE, | ||
57 | }; | ||
58 | |||
59 | static const struct resource stmfx_pinctrl_resources[] = { | ||
60 | DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_GPIO), | ||
61 | }; | ||
62 | |||
63 | static const struct resource stmfx_idd_resources[] = { | ||
64 | DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_IDD), | ||
65 | DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_ERROR), | ||
66 | }; | ||
67 | |||
68 | static const struct resource stmfx_ts_resources[] = { | ||
69 | DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_TS_DET), | ||
70 | DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_TS_NE), | ||
71 | DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_TS_TH), | ||
72 | DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_TS_FULL), | ||
73 | DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_TS_OVF), | ||
74 | }; | ||
75 | |||
76 | static struct mfd_cell stmfx_cells[] = { | ||
77 | { | ||
78 | .of_compatible = "st,stmfx-0300-pinctrl", | ||
79 | .name = "stmfx-pinctrl", | ||
80 | .resources = stmfx_pinctrl_resources, | ||
81 | .num_resources = ARRAY_SIZE(stmfx_pinctrl_resources), | ||
82 | }, | ||
83 | { | ||
84 | .of_compatible = "st,stmfx-0300-idd", | ||
85 | .name = "stmfx-idd", | ||
86 | .resources = stmfx_idd_resources, | ||
87 | .num_resources = ARRAY_SIZE(stmfx_idd_resources), | ||
88 | }, | ||
89 | { | ||
90 | .of_compatible = "st,stmfx-0300-ts", | ||
91 | .name = "stmfx-ts", | ||
92 | .resources = stmfx_ts_resources, | ||
93 | .num_resources = ARRAY_SIZE(stmfx_ts_resources), | ||
94 | }, | ||
95 | }; | ||
96 | |||
97 | static u8 stmfx_func_to_mask(u32 func) | ||
98 | { | ||
99 | u8 mask = 0; | ||
100 | |||
101 | if (func & STMFX_FUNC_GPIO) | ||
102 | mask |= STMFX_REG_SYS_CTRL_GPIO_EN; | ||
103 | |||
104 | if ((func & STMFX_FUNC_ALTGPIO_LOW) || (func & STMFX_FUNC_ALTGPIO_HIGH)) | ||
105 | mask |= STMFX_REG_SYS_CTRL_ALTGPIO_EN; | ||
106 | |||
107 | if (func & STMFX_FUNC_TS) | ||
108 | mask |= STMFX_REG_SYS_CTRL_TS_EN; | ||
109 | |||
110 | if (func & STMFX_FUNC_IDD) | ||
111 | mask |= STMFX_REG_SYS_CTRL_IDD_EN; | ||
112 | |||
113 | return mask; | ||
114 | } | ||
115 | |||
116 | int stmfx_function_enable(struct stmfx *stmfx, u32 func) | ||
117 | { | ||
118 | u32 sys_ctrl; | ||
119 | u8 mask; | ||
120 | int ret; | ||
121 | |||
122 | ret = regmap_read(stmfx->map, STMFX_REG_SYS_CTRL, &sys_ctrl); | ||
123 | if (ret) | ||
124 | return ret; | ||
125 | |||
126 | /* | ||
127 | * IDD and TS have priority in STMFX FW, so if IDD and TS are enabled, | ||
128 | * ALTGPIO function is disabled by STMFX FW. If IDD or TS is enabled, | ||
129 | * the number of aGPIO available decreases. To avoid GPIO management | ||
130 | * disturbance, abort IDD or TS function enable in this case. | ||
131 | */ | ||
132 | if (((func & STMFX_FUNC_IDD) || (func & STMFX_FUNC_TS)) && | ||
133 | (sys_ctrl & STMFX_REG_SYS_CTRL_ALTGPIO_EN)) { | ||
134 | dev_err(stmfx->dev, "ALTGPIO function already enabled\n"); | ||
135 | return -EBUSY; | ||
136 | } | ||
137 | |||
138 | /* If TS is enabled, aGPIO[3:0] cannot be used */ | ||
139 | if ((func & STMFX_FUNC_ALTGPIO_LOW) && | ||
140 | (sys_ctrl & STMFX_REG_SYS_CTRL_TS_EN)) { | ||
141 | dev_err(stmfx->dev, "TS in use, aGPIO[3:0] unavailable\n"); | ||
142 | return -EBUSY; | ||
143 | } | ||
144 | |||
145 | /* If IDD is enabled, aGPIO[7:4] cannot be used */ | ||
146 | if ((func & STMFX_FUNC_ALTGPIO_HIGH) && | ||
147 | (sys_ctrl & STMFX_REG_SYS_CTRL_IDD_EN)) { | ||
148 | dev_err(stmfx->dev, "IDD in use, aGPIO[7:4] unavailable\n"); | ||
149 | return -EBUSY; | ||
150 | } | ||
151 | |||
152 | mask = stmfx_func_to_mask(func); | ||
153 | |||
154 | return regmap_update_bits(stmfx->map, STMFX_REG_SYS_CTRL, mask, mask); | ||
155 | } | ||
156 | EXPORT_SYMBOL_GPL(stmfx_function_enable); | ||
157 | |||
158 | int stmfx_function_disable(struct stmfx *stmfx, u32 func) | ||
159 | { | ||
160 | u8 mask = stmfx_func_to_mask(func); | ||
161 | |||
162 | return regmap_update_bits(stmfx->map, STMFX_REG_SYS_CTRL, mask, 0); | ||
163 | } | ||
164 | EXPORT_SYMBOL_GPL(stmfx_function_disable); | ||
165 | |||
166 | static void stmfx_irq_bus_lock(struct irq_data *data) | ||
167 | { | ||
168 | struct stmfx *stmfx = irq_data_get_irq_chip_data(data); | ||
169 | |||
170 | mutex_lock(&stmfx->lock); | ||
171 | } | ||
172 | |||
173 | static void stmfx_irq_bus_sync_unlock(struct irq_data *data) | ||
174 | { | ||
175 | struct stmfx *stmfx = irq_data_get_irq_chip_data(data); | ||
176 | |||
177 | regmap_write(stmfx->map, STMFX_REG_IRQ_SRC_EN, stmfx->irq_src); | ||
178 | |||
179 | mutex_unlock(&stmfx->lock); | ||
180 | } | ||
181 | |||
182 | static void stmfx_irq_mask(struct irq_data *data) | ||
183 | { | ||
184 | struct stmfx *stmfx = irq_data_get_irq_chip_data(data); | ||
185 | |||
186 | stmfx->irq_src &= ~BIT(data->hwirq % 8); | ||
187 | } | ||
188 | |||
189 | static void stmfx_irq_unmask(struct irq_data *data) | ||
190 | { | ||
191 | struct stmfx *stmfx = irq_data_get_irq_chip_data(data); | ||
192 | |||
193 | stmfx->irq_src |= BIT(data->hwirq % 8); | ||
194 | } | ||
195 | |||
196 | static struct irq_chip stmfx_irq_chip = { | ||
197 | .name = "stmfx-core", | ||
198 | .irq_bus_lock = stmfx_irq_bus_lock, | ||
199 | .irq_bus_sync_unlock = stmfx_irq_bus_sync_unlock, | ||
200 | .irq_mask = stmfx_irq_mask, | ||
201 | .irq_unmask = stmfx_irq_unmask, | ||
202 | }; | ||
203 | |||
204 | static irqreturn_t stmfx_irq_handler(int irq, void *data) | ||
205 | { | ||
206 | struct stmfx *stmfx = data; | ||
207 | unsigned long n, pending; | ||
208 | u32 ack; | ||
209 | int ret; | ||
210 | |||
211 | ret = regmap_read(stmfx->map, STMFX_REG_IRQ_PENDING, | ||
212 | (u32 *)&pending); | ||
213 | if (ret) | ||
214 | return IRQ_NONE; | ||
215 | |||
216 | /* | ||
217 | * There is no ACK for GPIO, MFX_REG_IRQ_PENDING_GPIO is a logical OR | ||
218 | * of MFX_REG_IRQ_GPI _PENDING1/_PENDING2/_PENDING3 | ||
219 | */ | ||
220 | ack = pending & ~BIT(STMFX_REG_IRQ_SRC_EN_GPIO); | ||
221 | if (ack) { | ||
222 | ret = regmap_write(stmfx->map, STMFX_REG_IRQ_ACK, ack); | ||
223 | if (ret) | ||
224 | return IRQ_NONE; | ||
225 | } | ||
226 | |||
227 | for_each_set_bit(n, &pending, STMFX_REG_IRQ_SRC_MAX) | ||
228 | handle_nested_irq(irq_find_mapping(stmfx->irq_domain, n)); | ||
229 | |||
230 | return IRQ_HANDLED; | ||
231 | } | ||
232 | |||
233 | static int stmfx_irq_map(struct irq_domain *d, unsigned int virq, | ||
234 | irq_hw_number_t hwirq) | ||
235 | { | ||
236 | irq_set_chip_data(virq, d->host_data); | ||
237 | irq_set_chip_and_handler(virq, &stmfx_irq_chip, handle_simple_irq); | ||
238 | irq_set_nested_thread(virq, 1); | ||
239 | irq_set_noprobe(virq); | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static void stmfx_irq_unmap(struct irq_domain *d, unsigned int virq) | ||
245 | { | ||
246 | irq_set_chip_and_handler(virq, NULL, NULL); | ||
247 | irq_set_chip_data(virq, NULL); | ||
248 | } | ||
249 | |||
250 | static const struct irq_domain_ops stmfx_irq_ops = { | ||
251 | .map = stmfx_irq_map, | ||
252 | .unmap = stmfx_irq_unmap, | ||
253 | }; | ||
254 | |||
255 | static void stmfx_irq_exit(struct i2c_client *client) | ||
256 | { | ||
257 | struct stmfx *stmfx = i2c_get_clientdata(client); | ||
258 | int hwirq; | ||
259 | |||
260 | for (hwirq = 0; hwirq < STMFX_REG_IRQ_SRC_MAX; hwirq++) | ||
261 | irq_dispose_mapping(irq_find_mapping(stmfx->irq_domain, hwirq)); | ||
262 | |||
263 | irq_domain_remove(stmfx->irq_domain); | ||
264 | } | ||
265 | |||
266 | static int stmfx_irq_init(struct i2c_client *client) | ||
267 | { | ||
268 | struct stmfx *stmfx = i2c_get_clientdata(client); | ||
269 | u32 irqoutpin = 0, irqtrigger; | ||
270 | int ret; | ||
271 | |||
272 | stmfx->irq_domain = irq_domain_add_simple(stmfx->dev->of_node, | ||
273 | STMFX_REG_IRQ_SRC_MAX, 0, | ||
274 | &stmfx_irq_ops, stmfx); | ||
275 | if (!stmfx->irq_domain) { | ||
276 | dev_err(stmfx->dev, "Failed to create IRQ domain\n"); | ||
277 | return -EINVAL; | ||
278 | } | ||
279 | |||
280 | if (!of_property_read_bool(stmfx->dev->of_node, "drive-open-drain")) | ||
281 | irqoutpin |= STMFX_REG_IRQ_OUT_PIN_TYPE; | ||
282 | |||
283 | irqtrigger = irq_get_trigger_type(client->irq); | ||
284 | if ((irqtrigger & IRQ_TYPE_EDGE_RISING) || | ||
285 | (irqtrigger & IRQ_TYPE_LEVEL_HIGH)) | ||
286 | irqoutpin |= STMFX_REG_IRQ_OUT_PIN_POL; | ||
287 | |||
288 | ret = regmap_write(stmfx->map, STMFX_REG_IRQ_OUT_PIN, irqoutpin); | ||
289 | if (ret) | ||
290 | return ret; | ||
291 | |||
292 | ret = devm_request_threaded_irq(stmfx->dev, client->irq, | ||
293 | NULL, stmfx_irq_handler, | ||
294 | irqtrigger | IRQF_ONESHOT, | ||
295 | "stmfx", stmfx); | ||
296 | if (ret) | ||
297 | stmfx_irq_exit(client); | ||
298 | |||
299 | return ret; | ||
300 | } | ||
301 | |||
302 | static int stmfx_chip_reset(struct stmfx *stmfx) | ||
303 | { | ||
304 | int ret; | ||
305 | |||
306 | ret = regmap_write(stmfx->map, STMFX_REG_SYS_CTRL, | ||
307 | STMFX_REG_SYS_CTRL_SWRST); | ||
308 | if (ret) | ||
309 | return ret; | ||
310 | |||
311 | msleep(STMFX_BOOT_TIME_MS); | ||
312 | |||
313 | return ret; | ||
314 | } | ||
315 | |||
316 | static int stmfx_chip_init(struct i2c_client *client) | ||
317 | { | ||
318 | struct stmfx *stmfx = i2c_get_clientdata(client); | ||
319 | u32 id; | ||
320 | u8 version[2]; | ||
321 | int ret; | ||
322 | |||
323 | stmfx->vdd = devm_regulator_get_optional(&client->dev, "vdd"); | ||
324 | ret = PTR_ERR_OR_ZERO(stmfx->vdd); | ||
325 | if (ret == -ENODEV) { | ||
326 | stmfx->vdd = NULL; | ||
327 | } else if (ret == -EPROBE_DEFER) { | ||
328 | return ret; | ||
329 | } else if (ret) { | ||
330 | dev_err(&client->dev, "Failed to get VDD regulator: %d\n", ret); | ||
331 | return ret; | ||
332 | } | ||
333 | |||
334 | if (stmfx->vdd) { | ||
335 | ret = regulator_enable(stmfx->vdd); | ||
336 | if (ret) { | ||
337 | dev_err(&client->dev, "VDD enable failed: %d\n", ret); | ||
338 | return ret; | ||
339 | } | ||
340 | } | ||
341 | |||
342 | ret = regmap_read(stmfx->map, STMFX_REG_CHIP_ID, &id); | ||
343 | if (ret) { | ||
344 | dev_err(&client->dev, "Error reading chip ID: %d\n", ret); | ||
345 | goto err; | ||
346 | } | ||
347 | |||
348 | /* | ||
349 | * Check that ID is the complement of the I2C address: | ||
350 | * STMFX I2C address follows the 7-bit format (MSB), that's why | ||
351 | * client->addr is shifted. | ||
352 | * | ||
353 | * STMFX_I2C_ADDR| STMFX | Linux | ||
354 | * input pin | I2C device address | I2C device address | ||
355 | *--------------------------------------------------------- | ||
356 | * 0 | b: 1000 010x h:0x84 | 0x42 | ||
357 | * 1 | b: 1000 011x h:0x86 | 0x43 | ||
358 | */ | ||
359 | if (FIELD_GET(STMFX_REG_CHIP_ID_MASK, ~id) != (client->addr << 1)) { | ||
360 | dev_err(&client->dev, "Unknown chip ID: %#x\n", id); | ||
361 | ret = -EINVAL; | ||
362 | goto err; | ||
363 | } | ||
364 | |||
365 | ret = regmap_bulk_read(stmfx->map, STMFX_REG_FW_VERSION_MSB, | ||
366 | version, ARRAY_SIZE(version)); | ||
367 | if (ret) { | ||
368 | dev_err(&client->dev, "Error reading FW version: %d\n", ret); | ||
369 | goto err; | ||
370 | } | ||
371 | |||
372 | dev_info(&client->dev, "STMFX id: %#x, fw version: %x.%02x\n", | ||
373 | id, version[0], version[1]); | ||
374 | |||
375 | ret = stmfx_chip_reset(stmfx); | ||
376 | if (ret) { | ||
377 | dev_err(&client->dev, "Failed to reset chip: %d\n", ret); | ||
378 | goto err; | ||
379 | } | ||
380 | |||
381 | return 0; | ||
382 | |||
383 | err: | ||
384 | if (stmfx->vdd) | ||
385 | return regulator_disable(stmfx->vdd); | ||
386 | |||
387 | return ret; | ||
388 | } | ||
389 | |||
390 | static int stmfx_chip_exit(struct i2c_client *client) | ||
391 | { | ||
392 | struct stmfx *stmfx = i2c_get_clientdata(client); | ||
393 | |||
394 | regmap_write(stmfx->map, STMFX_REG_IRQ_SRC_EN, 0); | ||
395 | regmap_write(stmfx->map, STMFX_REG_SYS_CTRL, 0); | ||
396 | |||
397 | if (stmfx->vdd) | ||
398 | return regulator_disable(stmfx->vdd); | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static int stmfx_probe(struct i2c_client *client, | ||
404 | const struct i2c_device_id *id) | ||
405 | { | ||
406 | struct device *dev = &client->dev; | ||
407 | struct stmfx *stmfx; | ||
408 | int ret; | ||
409 | |||
410 | stmfx = devm_kzalloc(dev, sizeof(*stmfx), GFP_KERNEL); | ||
411 | if (!stmfx) | ||
412 | return -ENOMEM; | ||
413 | |||
414 | i2c_set_clientdata(client, stmfx); | ||
415 | |||
416 | stmfx->dev = dev; | ||
417 | |||
418 | stmfx->map = devm_regmap_init_i2c(client, &stmfx_regmap_config); | ||
419 | if (IS_ERR(stmfx->map)) { | ||
420 | ret = PTR_ERR(stmfx->map); | ||
421 | dev_err(dev, "Failed to allocate register map: %d\n", ret); | ||
422 | return ret; | ||
423 | } | ||
424 | |||
425 | mutex_init(&stmfx->lock); | ||
426 | |||
427 | ret = stmfx_chip_init(client); | ||
428 | if (ret) { | ||
429 | if (ret == -ETIMEDOUT) | ||
430 | return -EPROBE_DEFER; | ||
431 | return ret; | ||
432 | } | ||
433 | |||
434 | if (client->irq < 0) { | ||
435 | dev_err(dev, "Failed to get IRQ: %d\n", client->irq); | ||
436 | ret = client->irq; | ||
437 | goto err_chip_exit; | ||
438 | } | ||
439 | |||
440 | ret = stmfx_irq_init(client); | ||
441 | if (ret) | ||
442 | goto err_chip_exit; | ||
443 | |||
444 | ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, | ||
445 | stmfx_cells, ARRAY_SIZE(stmfx_cells), NULL, | ||
446 | 0, stmfx->irq_domain); | ||
447 | if (ret) | ||
448 | goto err_irq_exit; | ||
449 | |||
450 | return 0; | ||
451 | |||
452 | err_irq_exit: | ||
453 | stmfx_irq_exit(client); | ||
454 | err_chip_exit: | ||
455 | stmfx_chip_exit(client); | ||
456 | |||
457 | return ret; | ||
458 | } | ||
459 | |||
460 | static int stmfx_remove(struct i2c_client *client) | ||
461 | { | ||
462 | stmfx_irq_exit(client); | ||
463 | |||
464 | return stmfx_chip_exit(client); | ||
465 | } | ||
466 | |||
467 | #ifdef CONFIG_PM_SLEEP | ||
468 | static int stmfx_suspend(struct device *dev) | ||
469 | { | ||
470 | struct stmfx *stmfx = dev_get_drvdata(dev); | ||
471 | int ret; | ||
472 | |||
473 | ret = regmap_raw_read(stmfx->map, STMFX_REG_SYS_CTRL, | ||
474 | &stmfx->bkp_sysctrl, sizeof(stmfx->bkp_sysctrl)); | ||
475 | if (ret) | ||
476 | return ret; | ||
477 | |||
478 | ret = regmap_raw_read(stmfx->map, STMFX_REG_IRQ_OUT_PIN, | ||
479 | &stmfx->bkp_irqoutpin, | ||
480 | sizeof(stmfx->bkp_irqoutpin)); | ||
481 | if (ret) | ||
482 | return ret; | ||
483 | |||
484 | if (stmfx->vdd) | ||
485 | return regulator_disable(stmfx->vdd); | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static int stmfx_resume(struct device *dev) | ||
491 | { | ||
492 | struct stmfx *stmfx = dev_get_drvdata(dev); | ||
493 | int ret; | ||
494 | |||
495 | if (stmfx->vdd) { | ||
496 | ret = regulator_enable(stmfx->vdd); | ||
497 | if (ret) { | ||
498 | dev_err(stmfx->dev, | ||
499 | "VDD enable failed: %d\n", ret); | ||
500 | return ret; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | ret = regmap_raw_write(stmfx->map, STMFX_REG_SYS_CTRL, | ||
505 | &stmfx->bkp_sysctrl, sizeof(stmfx->bkp_sysctrl)); | ||
506 | if (ret) | ||
507 | return ret; | ||
508 | |||
509 | ret = regmap_raw_write(stmfx->map, STMFX_REG_IRQ_OUT_PIN, | ||
510 | &stmfx->bkp_irqoutpin, | ||
511 | sizeof(stmfx->bkp_irqoutpin)); | ||
512 | if (ret) | ||
513 | return ret; | ||
514 | |||
515 | ret = regmap_raw_write(stmfx->map, STMFX_REG_IRQ_SRC_EN, | ||
516 | &stmfx->irq_src, sizeof(stmfx->irq_src)); | ||
517 | if (ret) | ||
518 | return ret; | ||
519 | |||
520 | return 0; | ||
521 | } | ||
522 | #endif | ||
523 | |||
524 | static SIMPLE_DEV_PM_OPS(stmfx_dev_pm_ops, stmfx_suspend, stmfx_resume); | ||
525 | |||
526 | static const struct of_device_id stmfx_of_match[] = { | ||
527 | { .compatible = "st,stmfx-0300", }, | ||
528 | {}, | ||
529 | }; | ||
530 | MODULE_DEVICE_TABLE(of, stmfx_of_match); | ||
531 | |||
532 | static struct i2c_driver stmfx_driver = { | ||
533 | .driver = { | ||
534 | .name = "stmfx-core", | ||
535 | .of_match_table = of_match_ptr(stmfx_of_match), | ||
536 | .pm = &stmfx_dev_pm_ops, | ||
537 | }, | ||
538 | .probe = stmfx_probe, | ||
539 | .remove = stmfx_remove, | ||
540 | }; | ||
541 | module_i2c_driver(stmfx_driver); | ||
542 | |||
543 | MODULE_DESCRIPTION("STMFX core driver"); | ||
544 | MODULE_AUTHOR("Amelie Delaunay <amelie.delaunay@st.com>"); | ||
545 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/sun6i-prcm.c b/drivers/mfd/sun6i-prcm.c index 2b658bed47db..2f12a415b807 100644 --- a/drivers/mfd/sun6i-prcm.c +++ b/drivers/mfd/sun6i-prcm.c | |||
@@ -148,13 +148,12 @@ static const struct of_device_id sun6i_prcm_dt_ids[] = { | |||
148 | 148 | ||
149 | static int sun6i_prcm_probe(struct platform_device *pdev) | 149 | static int sun6i_prcm_probe(struct platform_device *pdev) |
150 | { | 150 | { |
151 | struct device_node *np = pdev->dev.of_node; | ||
152 | const struct of_device_id *match; | 151 | const struct of_device_id *match; |
153 | const struct prcm_data *data; | 152 | const struct prcm_data *data; |
154 | struct resource *res; | 153 | struct resource *res; |
155 | int ret; | 154 | int ret; |
156 | 155 | ||
157 | match = of_match_node(sun6i_prcm_dt_ids, np); | 156 | match = of_match_node(sun6i_prcm_dt_ids, pdev->dev.of_node); |
158 | if (!match) | 157 | if (!match) |
159 | return -EINVAL; | 158 | return -EINVAL; |
160 | 159 | ||
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c index 0ecdffb3d967..f6922a0f8058 100644 --- a/drivers/mfd/syscon.c +++ b/drivers/mfd/syscon.c | |||
@@ -12,6 +12,7 @@ | |||
12 | * (at your option) any later version. | 12 | * (at your option) any later version. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/clk.h> | ||
15 | #include <linux/err.h> | 16 | #include <linux/err.h> |
16 | #include <linux/hwspinlock.h> | 17 | #include <linux/hwspinlock.h> |
17 | #include <linux/io.h> | 18 | #include <linux/io.h> |
@@ -45,6 +46,7 @@ static const struct regmap_config syscon_regmap_config = { | |||
45 | 46 | ||
46 | static struct syscon *of_syscon_register(struct device_node *np) | 47 | static struct syscon *of_syscon_register(struct device_node *np) |
47 | { | 48 | { |
49 | struct clk *clk; | ||
48 | struct syscon *syscon; | 50 | struct syscon *syscon; |
49 | struct regmap *regmap; | 51 | struct regmap *regmap; |
50 | void __iomem *base; | 52 | void __iomem *base; |
@@ -119,6 +121,18 @@ static struct syscon *of_syscon_register(struct device_node *np) | |||
119 | goto err_regmap; | 121 | goto err_regmap; |
120 | } | 122 | } |
121 | 123 | ||
124 | clk = of_clk_get(np, 0); | ||
125 | if (IS_ERR(clk)) { | ||
126 | ret = PTR_ERR(clk); | ||
127 | /* clock is optional */ | ||
128 | if (ret != -ENOENT) | ||
129 | goto err_clk; | ||
130 | } else { | ||
131 | ret = regmap_mmio_attach_clk(regmap, clk); | ||
132 | if (ret) | ||
133 | goto err_attach; | ||
134 | } | ||
135 | |||
122 | syscon->regmap = regmap; | 136 | syscon->regmap = regmap; |
123 | syscon->np = np; | 137 | syscon->np = np; |
124 | 138 | ||
@@ -128,6 +142,11 @@ static struct syscon *of_syscon_register(struct device_node *np) | |||
128 | 142 | ||
129 | return syscon; | 143 | return syscon; |
130 | 144 | ||
145 | err_attach: | ||
146 | if (!IS_ERR(clk)) | ||
147 | clk_put(clk); | ||
148 | err_clk: | ||
149 | regmap_exit(regmap); | ||
131 | err_regmap: | 150 | err_regmap: |
132 | iounmap(base); | 151 | iounmap(base); |
133 | err_map: | 152 | err_map: |
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 43d8683266de..e9cfb147345e 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c | |||
@@ -82,8 +82,7 @@ struct t7l66xb { | |||
82 | 82 | ||
83 | static int t7l66xb_mmc_enable(struct platform_device *mmc) | 83 | static int t7l66xb_mmc_enable(struct platform_device *mmc) |
84 | { | 84 | { |
85 | struct platform_device *dev = to_platform_device(mmc->dev.parent); | 85 | struct t7l66xb *t7l66xb = dev_get_drvdata(mmc->dev.parent); |
86 | struct t7l66xb *t7l66xb = platform_get_drvdata(dev); | ||
87 | unsigned long flags; | 86 | unsigned long flags; |
88 | u8 dev_ctl; | 87 | u8 dev_ctl; |
89 | int ret; | 88 | int ret; |
@@ -108,8 +107,7 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc) | |||
108 | 107 | ||
109 | static int t7l66xb_mmc_disable(struct platform_device *mmc) | 108 | static int t7l66xb_mmc_disable(struct platform_device *mmc) |
110 | { | 109 | { |
111 | struct platform_device *dev = to_platform_device(mmc->dev.parent); | 110 | struct t7l66xb *t7l66xb = dev_get_drvdata(mmc->dev.parent); |
112 | struct t7l66xb *t7l66xb = platform_get_drvdata(dev); | ||
113 | unsigned long flags; | 111 | unsigned long flags; |
114 | u8 dev_ctl; | 112 | u8 dev_ctl; |
115 | 113 | ||
@@ -128,16 +126,14 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc) | |||
128 | 126 | ||
129 | static void t7l66xb_mmc_pwr(struct platform_device *mmc, int state) | 127 | static void t7l66xb_mmc_pwr(struct platform_device *mmc, int state) |
130 | { | 128 | { |
131 | struct platform_device *dev = to_platform_device(mmc->dev.parent); | 129 | struct t7l66xb *t7l66xb = dev_get_drvdata(mmc->dev.parent); |
132 | struct t7l66xb *t7l66xb = platform_get_drvdata(dev); | ||
133 | 130 | ||
134 | tmio_core_mmc_pwr(t7l66xb->scr + 0x200, 0, state); | 131 | tmio_core_mmc_pwr(t7l66xb->scr + 0x200, 0, state); |
135 | } | 132 | } |
136 | 133 | ||
137 | static void t7l66xb_mmc_clk_div(struct platform_device *mmc, int state) | 134 | static void t7l66xb_mmc_clk_div(struct platform_device *mmc, int state) |
138 | { | 135 | { |
139 | struct platform_device *dev = to_platform_device(mmc->dev.parent); | 136 | struct t7l66xb *t7l66xb = dev_get_drvdata(mmc->dev.parent); |
140 | struct t7l66xb *t7l66xb = platform_get_drvdata(dev); | ||
141 | 137 | ||
142 | tmio_core_mmc_clk_div(t7l66xb->scr + 0x200, 0, state); | 138 | tmio_core_mmc_clk_div(t7l66xb->scr + 0x200, 0, state); |
143 | } | 139 | } |
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index 85fab3729102..f417c6fecfe2 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c | |||
@@ -80,16 +80,14 @@ static int tc6387xb_resume(struct platform_device *dev) | |||
80 | 80 | ||
81 | static void tc6387xb_mmc_pwr(struct platform_device *mmc, int state) | 81 | static void tc6387xb_mmc_pwr(struct platform_device *mmc, int state) |
82 | { | 82 | { |
83 | struct platform_device *dev = to_platform_device(mmc->dev.parent); | 83 | struct tc6387xb *tc6387xb = dev_get_drvdata(mmc->dev.parent); |
84 | struct tc6387xb *tc6387xb = platform_get_drvdata(dev); | ||
85 | 84 | ||
86 | tmio_core_mmc_pwr(tc6387xb->scr + 0x200, 0, state); | 85 | tmio_core_mmc_pwr(tc6387xb->scr + 0x200, 0, state); |
87 | } | 86 | } |
88 | 87 | ||
89 | static void tc6387xb_mmc_clk_div(struct platform_device *mmc, int state) | 88 | static void tc6387xb_mmc_clk_div(struct platform_device *mmc, int state) |
90 | { | 89 | { |
91 | struct platform_device *dev = to_platform_device(mmc->dev.parent); | 90 | struct tc6387xb *tc6387xb = dev_get_drvdata(mmc->dev.parent); |
92 | struct tc6387xb *tc6387xb = platform_get_drvdata(dev); | ||
93 | 91 | ||
94 | tmio_core_mmc_clk_div(tc6387xb->scr + 0x200, 0, state); | 92 | tmio_core_mmc_clk_div(tc6387xb->scr + 0x200, 0, state); |
95 | } | 93 | } |
@@ -97,8 +95,7 @@ static void tc6387xb_mmc_clk_div(struct platform_device *mmc, int state) | |||
97 | 95 | ||
98 | static int tc6387xb_mmc_enable(struct platform_device *mmc) | 96 | static int tc6387xb_mmc_enable(struct platform_device *mmc) |
99 | { | 97 | { |
100 | struct platform_device *dev = to_platform_device(mmc->dev.parent); | 98 | struct tc6387xb *tc6387xb = dev_get_drvdata(mmc->dev.parent); |
101 | struct tc6387xb *tc6387xb = platform_get_drvdata(dev); | ||
102 | 99 | ||
103 | clk_prepare_enable(tc6387xb->clk32k); | 100 | clk_prepare_enable(tc6387xb->clk32k); |
104 | 101 | ||
@@ -110,8 +107,7 @@ static int tc6387xb_mmc_enable(struct platform_device *mmc) | |||
110 | 107 | ||
111 | static int tc6387xb_mmc_disable(struct platform_device *mmc) | 108 | static int tc6387xb_mmc_disable(struct platform_device *mmc) |
112 | { | 109 | { |
113 | struct platform_device *dev = to_platform_device(mmc->dev.parent); | 110 | struct tc6387xb *tc6387xb = dev_get_drvdata(mmc->dev.parent); |
114 | struct tc6387xb *tc6387xb = platform_get_drvdata(dev); | ||
115 | 111 | ||
116 | clk_disable_unprepare(tc6387xb->clk32k); | 112 | clk_disable_unprepare(tc6387xb->clk32k); |
117 | 113 | ||
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 0c9f0390e891..6943048a64c2 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c | |||
@@ -122,14 +122,13 @@ enum { | |||
122 | 122 | ||
123 | static int tc6393xb_nand_enable(struct platform_device *nand) | 123 | static int tc6393xb_nand_enable(struct platform_device *nand) |
124 | { | 124 | { |
125 | struct platform_device *dev = to_platform_device(nand->dev.parent); | 125 | struct tc6393xb *tc6393xb = dev_get_drvdata(nand->dev.parent); |
126 | struct tc6393xb *tc6393xb = platform_get_drvdata(dev); | ||
127 | unsigned long flags; | 126 | unsigned long flags; |
128 | 127 | ||
129 | raw_spin_lock_irqsave(&tc6393xb->lock, flags); | 128 | raw_spin_lock_irqsave(&tc6393xb->lock, flags); |
130 | 129 | ||
131 | /* SMD buffer on */ | 130 | /* SMD buffer on */ |
132 | dev_dbg(&dev->dev, "SMD buffer on\n"); | 131 | dev_dbg(nand->dev.parent, "SMD buffer on\n"); |
133 | tmio_iowrite8(0xff, tc6393xb->scr + SCR_GPI_BCR(1)); | 132 | tmio_iowrite8(0xff, tc6393xb->scr + SCR_GPI_BCR(1)); |
134 | 133 | ||
135 | raw_spin_unlock_irqrestore(&tc6393xb->lock, flags); | 134 | raw_spin_unlock_irqrestore(&tc6393xb->lock, flags); |
@@ -312,8 +311,7 @@ static int tc6393xb_fb_disable(struct platform_device *dev) | |||
312 | 311 | ||
313 | int tc6393xb_lcd_set_power(struct platform_device *fb, bool on) | 312 | int tc6393xb_lcd_set_power(struct platform_device *fb, bool on) |
314 | { | 313 | { |
315 | struct platform_device *dev = to_platform_device(fb->dev.parent); | 314 | struct tc6393xb *tc6393xb = dev_get_drvdata(fb->dev.parent); |
316 | struct tc6393xb *tc6393xb = platform_get_drvdata(dev); | ||
317 | u8 fer; | 315 | u8 fer; |
318 | unsigned long flags; | 316 | unsigned long flags; |
319 | 317 | ||
@@ -334,8 +332,7 @@ EXPORT_SYMBOL(tc6393xb_lcd_set_power); | |||
334 | 332 | ||
335 | int tc6393xb_lcd_mode(struct platform_device *fb, | 333 | int tc6393xb_lcd_mode(struct platform_device *fb, |
336 | const struct fb_videomode *mode) { | 334 | const struct fb_videomode *mode) { |
337 | struct platform_device *dev = to_platform_device(fb->dev.parent); | 335 | struct tc6393xb *tc6393xb = dev_get_drvdata(fb->dev.parent); |
338 | struct tc6393xb *tc6393xb = platform_get_drvdata(dev); | ||
339 | unsigned long flags; | 336 | unsigned long flags; |
340 | 337 | ||
341 | raw_spin_lock_irqsave(&tc6393xb->lock, flags); | 338 | raw_spin_lock_irqsave(&tc6393xb->lock, flags); |
@@ -351,8 +348,7 @@ EXPORT_SYMBOL(tc6393xb_lcd_mode); | |||
351 | 348 | ||
352 | static int tc6393xb_mmc_enable(struct platform_device *mmc) | 349 | static int tc6393xb_mmc_enable(struct platform_device *mmc) |
353 | { | 350 | { |
354 | struct platform_device *dev = to_platform_device(mmc->dev.parent); | 351 | struct tc6393xb *tc6393xb = dev_get_drvdata(mmc->dev.parent); |
355 | struct tc6393xb *tc6393xb = platform_get_drvdata(dev); | ||
356 | 352 | ||
357 | tmio_core_mmc_enable(tc6393xb->scr + 0x200, 0, | 353 | tmio_core_mmc_enable(tc6393xb->scr + 0x200, 0, |
358 | tc6393xb_mmc_resources[0].start & 0xfffe); | 354 | tc6393xb_mmc_resources[0].start & 0xfffe); |
@@ -362,8 +358,7 @@ static int tc6393xb_mmc_enable(struct platform_device *mmc) | |||
362 | 358 | ||
363 | static int tc6393xb_mmc_resume(struct platform_device *mmc) | 359 | static int tc6393xb_mmc_resume(struct platform_device *mmc) |
364 | { | 360 | { |
365 | struct platform_device *dev = to_platform_device(mmc->dev.parent); | 361 | struct tc6393xb *tc6393xb = dev_get_drvdata(mmc->dev.parent); |
366 | struct tc6393xb *tc6393xb = platform_get_drvdata(dev); | ||
367 | 362 | ||
368 | tmio_core_mmc_resume(tc6393xb->scr + 0x200, 0, | 363 | tmio_core_mmc_resume(tc6393xb->scr + 0x200, 0, |
369 | tc6393xb_mmc_resources[0].start & 0xfffe); | 364 | tc6393xb_mmc_resources[0].start & 0xfffe); |
@@ -373,16 +368,14 @@ static int tc6393xb_mmc_resume(struct platform_device *mmc) | |||
373 | 368 | ||
374 | static void tc6393xb_mmc_pwr(struct platform_device *mmc, int state) | 369 | static void tc6393xb_mmc_pwr(struct platform_device *mmc, int state) |
375 | { | 370 | { |
376 | struct platform_device *dev = to_platform_device(mmc->dev.parent); | 371 | struct tc6393xb *tc6393xb = dev_get_drvdata(mmc->dev.parent); |
377 | struct tc6393xb *tc6393xb = platform_get_drvdata(dev); | ||
378 | 372 | ||
379 | tmio_core_mmc_pwr(tc6393xb->scr + 0x200, 0, state); | 373 | tmio_core_mmc_pwr(tc6393xb->scr + 0x200, 0, state); |
380 | } | 374 | } |
381 | 375 | ||
382 | static void tc6393xb_mmc_clk_div(struct platform_device *mmc, int state) | 376 | static void tc6393xb_mmc_clk_div(struct platform_device *mmc, int state) |
383 | { | 377 | { |
384 | struct platform_device *dev = to_platform_device(mmc->dev.parent); | 378 | struct tc6393xb *tc6393xb = dev_get_drvdata(mmc->dev.parent); |
385 | struct tc6393xb *tc6393xb = platform_get_drvdata(dev); | ||
386 | 379 | ||
387 | tmio_core_mmc_clk_div(tc6393xb->scr + 0x200, 0, state); | 380 | tmio_core_mmc_clk_div(tc6393xb->scr + 0x200, 0, state); |
388 | } | 381 | } |
diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c index 3bd75061f777..f78be039e463 100644 --- a/drivers/mfd/tps65912-spi.c +++ b/drivers/mfd/tps65912-spi.c | |||
@@ -27,6 +27,7 @@ static const struct of_device_id tps65912_spi_of_match_table[] = { | |||
27 | { .compatible = "ti,tps65912", }, | 27 | { .compatible = "ti,tps65912", }, |
28 | { /* sentinel */ } | 28 | { /* sentinel */ } |
29 | }; | 29 | }; |
30 | MODULE_DEVICE_TABLE(of, tps65912_spi_of_match_table); | ||
30 | 31 | ||
31 | static int tps65912_spi_probe(struct spi_device *spi) | 32 | static int tps65912_spi_probe(struct spi_device *spi) |
32 | { | 33 | { |
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index 7c3c5fd5fcd0..86052c5c6069 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c | |||
@@ -322,8 +322,19 @@ int twl6040_power(struct twl6040 *twl6040, int on) | |||
322 | } | 322 | } |
323 | } | 323 | } |
324 | 324 | ||
325 | /* | ||
326 | * Register access can produce errors after power-up unless we | ||
327 | * wait at least 8ms based on measurements on duovero. | ||
328 | */ | ||
329 | usleep_range(10000, 12000); | ||
330 | |||
325 | /* Sync with the HW */ | 331 | /* Sync with the HW */ |
326 | regcache_sync(twl6040->regmap); | 332 | ret = regcache_sync(twl6040->regmap); |
333 | if (ret) { | ||
334 | dev_err(twl6040->dev, "Failed to sync with the HW: %i\n", | ||
335 | ret); | ||
336 | goto out; | ||
337 | } | ||
327 | 338 | ||
328 | /* Default PLL configuration after power up */ | 339 | /* Default PLL configuration after power up */ |
329 | twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; | 340 | twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index 5b3b06a0a3bf..d466e33635b0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c | |||
@@ -15,7 +15,7 @@ | |||
15 | * Adopted from dwmac-sti.c | 15 | * Adopted from dwmac-sti.c |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/mfd/syscon.h> | 18 | #include <linux/mfd/altera-sysmgr.h> |
19 | #include <linux/of.h> | 19 | #include <linux/of.h> |
20 | #include <linux/of_address.h> | 20 | #include <linux/of_address.h> |
21 | #include <linux/of_net.h> | 21 | #include <linux/of_net.h> |
@@ -114,7 +114,8 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device * | |||
114 | 114 | ||
115 | dwmac->interface = of_get_phy_mode(np); | 115 | dwmac->interface = of_get_phy_mode(np); |
116 | 116 | ||
117 | sys_mgr_base_addr = syscon_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon"); | 117 | sys_mgr_base_addr = |
118 | altr_sysmgr_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon"); | ||
118 | if (IS_ERR(sys_mgr_base_addr)) { | 119 | if (IS_ERR(sys_mgr_base_addr)) { |
119 | dev_info(dev, "No sysmgr-syscon node found\n"); | 120 | dev_info(dev, "No sysmgr-syscon node found\n"); |
120 | return PTR_ERR(sys_mgr_base_addr); | 121 | return PTR_ERR(sys_mgr_base_addr); |
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 19d8af9a36a2..ea798548b012 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig | |||
@@ -273,6 +273,20 @@ config PINCTRL_ST | |||
273 | select PINCONF | 273 | select PINCONF |
274 | select GPIOLIB_IRQCHIP | 274 | select GPIOLIB_IRQCHIP |
275 | 275 | ||
276 | config PINCTRL_STMFX | ||
277 | tristate "STMicroelectronics STMFX GPIO expander pinctrl driver" | ||
278 | depends on I2C | ||
279 | depends on OF || COMPILE_TEST | ||
280 | select GENERIC_PINCONF | ||
281 | select GPIOLIB_IRQCHIP | ||
282 | select MFD_STMFX | ||
283 | help | ||
284 | Driver for STMicroelectronics Multi-Function eXpander (STMFX) | ||
285 | GPIO expander. | ||
286 | This provides a GPIO interface supporting inputs and outputs, | ||
287 | and configuring push-pull, open-drain, and can also be used as | ||
288 | interrupt-controller. | ||
289 | |||
276 | config PINCTRL_U300 | 290 | config PINCTRL_U300 |
277 | bool "U300 pin controller driver" | 291 | bool "U300 pin controller driver" |
278 | depends on ARCH_U300 | 292 | depends on ARCH_U300 |
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 62df40647e02..ac537fdbc998 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile | |||
@@ -41,6 +41,7 @@ obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o | |||
41 | obj-$(CONFIG_PINCTRL_LPC18XX) += pinctrl-lpc18xx.o | 41 | obj-$(CONFIG_PINCTRL_LPC18XX) += pinctrl-lpc18xx.o |
42 | obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o | 42 | obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o |
43 | obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o | 43 | obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o |
44 | obj-$(CONFIG_PINCTRL_STMFX) += pinctrl-stmfx.o | ||
44 | obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o | 45 | obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o |
45 | obj-$(CONFIG_PINCTRL_INGENIC) += pinctrl-ingenic.o | 46 | obj-$(CONFIG_PINCTRL_INGENIC) += pinctrl-ingenic.o |
46 | obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o | 47 | obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o |
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c new file mode 100644 index 000000000000..eba872ce4a7c --- /dev/null +++ b/drivers/pinctrl/pinctrl-stmfx.c | |||
@@ -0,0 +1,819 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Driver for STMicroelectronics Multi-Function eXpander (STMFX) GPIO expander | ||
4 | * | ||
5 | * Copyright (C) 2019 STMicroelectronics | ||
6 | * Author(s): Amelie Delaunay <amelie.delaunay@st.com>. | ||
7 | */ | ||
8 | #include <linux/gpio/driver.h> | ||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/mfd/stmfx.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/pinctrl/pinconf.h> | ||
14 | #include <linux/pinctrl/pinmux.h> | ||
15 | |||
16 | #include "core.h" | ||
17 | #include "pinctrl-utils.h" | ||
18 | |||
19 | /* GPIOs expander */ | ||
20 | /* GPIO_STATE1 0x10, GPIO_STATE2 0x11, GPIO_STATE3 0x12 */ | ||
21 | #define STMFX_REG_GPIO_STATE STMFX_REG_GPIO_STATE1 /* R */ | ||
22 | /* GPIO_DIR1 0x60, GPIO_DIR2 0x61, GPIO_DIR3 0x63 */ | ||
23 | #define STMFX_REG_GPIO_DIR STMFX_REG_GPIO_DIR1 /* RW */ | ||
24 | /* GPIO_TYPE1 0x64, GPIO_TYPE2 0x65, GPIO_TYPE3 0x66 */ | ||
25 | #define STMFX_REG_GPIO_TYPE STMFX_REG_GPIO_TYPE1 /* RW */ | ||
26 | /* GPIO_PUPD1 0x68, GPIO_PUPD2 0x69, GPIO_PUPD3 0x6A */ | ||
27 | #define STMFX_REG_GPIO_PUPD STMFX_REG_GPIO_PUPD1 /* RW */ | ||
28 | /* GPO_SET1 0x6C, GPO_SET2 0x6D, GPO_SET3 0x6E */ | ||
29 | #define STMFX_REG_GPO_SET STMFX_REG_GPO_SET1 /* RW */ | ||
30 | /* GPO_CLR1 0x70, GPO_CLR2 0x71, GPO_CLR3 0x72 */ | ||
31 | #define STMFX_REG_GPO_CLR STMFX_REG_GPO_CLR1 /* RW */ | ||
32 | /* IRQ_GPI_SRC1 0x48, IRQ_GPI_SRC2 0x49, IRQ_GPI_SRC3 0x4A */ | ||
33 | #define STMFX_REG_IRQ_GPI_SRC STMFX_REG_IRQ_GPI_SRC1 /* RW */ | ||
34 | /* IRQ_GPI_EVT1 0x4C, IRQ_GPI_EVT2 0x4D, IRQ_GPI_EVT3 0x4E */ | ||
35 | #define STMFX_REG_IRQ_GPI_EVT STMFX_REG_IRQ_GPI_EVT1 /* RW */ | ||
36 | /* IRQ_GPI_TYPE1 0x50, IRQ_GPI_TYPE2 0x51, IRQ_GPI_TYPE3 0x52 */ | ||
37 | #define STMFX_REG_IRQ_GPI_TYPE STMFX_REG_IRQ_GPI_TYPE1 /* RW */ | ||
38 | /* IRQ_GPI_PENDING1 0x0C, IRQ_GPI_PENDING2 0x0D, IRQ_GPI_PENDING3 0x0E*/ | ||
39 | #define STMFX_REG_IRQ_GPI_PENDING STMFX_REG_IRQ_GPI_PENDING1 /* R */ | ||
40 | /* IRQ_GPI_ACK1 0x54, IRQ_GPI_ACK2 0x55, IRQ_GPI_ACK3 0x56 */ | ||
41 | #define STMFX_REG_IRQ_GPI_ACK STMFX_REG_IRQ_GPI_ACK1 /* RW */ | ||
42 | |||
43 | #define NR_GPIO_REGS 3 | ||
44 | #define NR_GPIOS_PER_REG 8 | ||
45 | #define get_reg(offset) ((offset) / NR_GPIOS_PER_REG) | ||
46 | #define get_shift(offset) ((offset) % NR_GPIOS_PER_REG) | ||
47 | #define get_mask(offset) (BIT(get_shift(offset))) | ||
48 | |||
49 | /* | ||
50 | * STMFX pinctrl can have up to 24 pins if STMFX other functions are not used. | ||
51 | * Pins availability is managed thanks to gpio-ranges property. | ||
52 | */ | ||
53 | static const struct pinctrl_pin_desc stmfx_pins[] = { | ||
54 | PINCTRL_PIN(0, "gpio0"), | ||
55 | PINCTRL_PIN(1, "gpio1"), | ||
56 | PINCTRL_PIN(2, "gpio2"), | ||
57 | PINCTRL_PIN(3, "gpio3"), | ||
58 | PINCTRL_PIN(4, "gpio4"), | ||
59 | PINCTRL_PIN(5, "gpio5"), | ||
60 | PINCTRL_PIN(6, "gpio6"), | ||
61 | PINCTRL_PIN(7, "gpio7"), | ||
62 | PINCTRL_PIN(8, "gpio8"), | ||
63 | PINCTRL_PIN(9, "gpio9"), | ||
64 | PINCTRL_PIN(10, "gpio10"), | ||
65 | PINCTRL_PIN(11, "gpio11"), | ||
66 | PINCTRL_PIN(12, "gpio12"), | ||
67 | PINCTRL_PIN(13, "gpio13"), | ||
68 | PINCTRL_PIN(14, "gpio14"), | ||
69 | PINCTRL_PIN(15, "gpio15"), | ||
70 | PINCTRL_PIN(16, "agpio0"), | ||
71 | PINCTRL_PIN(17, "agpio1"), | ||
72 | PINCTRL_PIN(18, "agpio2"), | ||
73 | PINCTRL_PIN(19, "agpio3"), | ||
74 | PINCTRL_PIN(20, "agpio4"), | ||
75 | PINCTRL_PIN(21, "agpio5"), | ||
76 | PINCTRL_PIN(22, "agpio6"), | ||
77 | PINCTRL_PIN(23, "agpio7"), | ||
78 | }; | ||
79 | |||
80 | struct stmfx_pinctrl { | ||
81 | struct device *dev; | ||
82 | struct stmfx *stmfx; | ||
83 | struct pinctrl_dev *pctl_dev; | ||
84 | struct pinctrl_desc pctl_desc; | ||
85 | struct gpio_chip gpio_chip; | ||
86 | struct irq_chip irq_chip; | ||
87 | struct mutex lock; /* IRQ bus lock */ | ||
88 | unsigned long gpio_valid_mask; | ||
89 | /* Cache of IRQ_GPI_* registers for bus_lock */ | ||
90 | u8 irq_gpi_src[NR_GPIO_REGS]; | ||
91 | u8 irq_gpi_type[NR_GPIO_REGS]; | ||
92 | u8 irq_gpi_evt[NR_GPIO_REGS]; | ||
93 | u8 irq_toggle_edge[NR_GPIO_REGS]; | ||
94 | #ifdef CONFIG_PM | ||
95 | /* Backup of GPIO_* registers for suspend/resume */ | ||
96 | u8 bkp_gpio_state[NR_GPIO_REGS]; | ||
97 | u8 bkp_gpio_dir[NR_GPIO_REGS]; | ||
98 | u8 bkp_gpio_type[NR_GPIO_REGS]; | ||
99 | u8 bkp_gpio_pupd[NR_GPIO_REGS]; | ||
100 | #endif | ||
101 | }; | ||
102 | |||
103 | static int stmfx_gpio_get(struct gpio_chip *gc, unsigned int offset) | ||
104 | { | ||
105 | struct stmfx_pinctrl *pctl = gpiochip_get_data(gc); | ||
106 | u32 reg = STMFX_REG_GPIO_STATE + get_reg(offset); | ||
107 | u32 mask = get_mask(offset); | ||
108 | u32 value; | ||
109 | int ret; | ||
110 | |||
111 | ret = regmap_read(pctl->stmfx->map, reg, &value); | ||
112 | |||
113 | return ret ? ret : !!(value & mask); | ||
114 | } | ||
115 | |||
116 | static void stmfx_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) | ||
117 | { | ||
118 | struct stmfx_pinctrl *pctl = gpiochip_get_data(gc); | ||
119 | u32 reg = value ? STMFX_REG_GPO_SET : STMFX_REG_GPO_CLR; | ||
120 | u32 mask = get_mask(offset); | ||
121 | |||
122 | regmap_write_bits(pctl->stmfx->map, reg + get_reg(offset), | ||
123 | mask, mask); | ||
124 | } | ||
125 | |||
126 | static int stmfx_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) | ||
127 | { | ||
128 | struct stmfx_pinctrl *pctl = gpiochip_get_data(gc); | ||
129 | u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset); | ||
130 | u32 mask = get_mask(offset); | ||
131 | u32 val; | ||
132 | int ret; | ||
133 | |||
134 | ret = regmap_read(pctl->stmfx->map, reg, &val); | ||
135 | /* | ||
136 | * On stmfx, gpio pins direction is (0)input, (1)output. | ||
137 | * .get_direction returns 0=out, 1=in | ||
138 | */ | ||
139 | |||
140 | return ret ? ret : !(val & mask); | ||
141 | } | ||
142 | |||
143 | static int stmfx_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) | ||
144 | { | ||
145 | struct stmfx_pinctrl *pctl = gpiochip_get_data(gc); | ||
146 | u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset); | ||
147 | u32 mask = get_mask(offset); | ||
148 | |||
149 | return regmap_write_bits(pctl->stmfx->map, reg, mask, 0); | ||
150 | } | ||
151 | |||
152 | static int stmfx_gpio_direction_output(struct gpio_chip *gc, | ||
153 | unsigned int offset, int value) | ||
154 | { | ||
155 | struct stmfx_pinctrl *pctl = gpiochip_get_data(gc); | ||
156 | u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset); | ||
157 | u32 mask = get_mask(offset); | ||
158 | |||
159 | stmfx_gpio_set(gc, offset, value); | ||
160 | |||
161 | return regmap_write_bits(pctl->stmfx->map, reg, mask, mask); | ||
162 | } | ||
163 | |||
164 | static int stmfx_pinconf_get_pupd(struct stmfx_pinctrl *pctl, | ||
165 | unsigned int offset) | ||
166 | { | ||
167 | u32 reg = STMFX_REG_GPIO_PUPD + get_reg(offset); | ||
168 | u32 pupd, mask = get_mask(offset); | ||
169 | int ret; | ||
170 | |||
171 | ret = regmap_read(pctl->stmfx->map, reg, &pupd); | ||
172 | if (ret) | ||
173 | return ret; | ||
174 | |||
175 | return !!(pupd & mask); | ||
176 | } | ||
177 | |||
178 | static int stmfx_pinconf_set_pupd(struct stmfx_pinctrl *pctl, | ||
179 | unsigned int offset, u32 pupd) | ||
180 | { | ||
181 | u32 reg = STMFX_REG_GPIO_PUPD + get_reg(offset); | ||
182 | u32 mask = get_mask(offset); | ||
183 | |||
184 | return regmap_write_bits(pctl->stmfx->map, reg, mask, pupd ? mask : 0); | ||
185 | } | ||
186 | |||
187 | static int stmfx_pinconf_get_type(struct stmfx_pinctrl *pctl, | ||
188 | unsigned int offset) | ||
189 | { | ||
190 | u32 reg = STMFX_REG_GPIO_TYPE + get_reg(offset); | ||
191 | u32 type, mask = get_mask(offset); | ||
192 | int ret; | ||
193 | |||
194 | ret = regmap_read(pctl->stmfx->map, reg, &type); | ||
195 | if (ret) | ||
196 | return ret; | ||
197 | |||
198 | return !!(type & mask); | ||
199 | } | ||
200 | |||
201 | static int stmfx_pinconf_set_type(struct stmfx_pinctrl *pctl, | ||
202 | unsigned int offset, u32 type) | ||
203 | { | ||
204 | u32 reg = STMFX_REG_GPIO_TYPE + get_reg(offset); | ||
205 | u32 mask = get_mask(offset); | ||
206 | |||
207 | return regmap_write_bits(pctl->stmfx->map, reg, mask, type ? mask : 0); | ||
208 | } | ||
209 | |||
210 | static int stmfx_pinconf_get(struct pinctrl_dev *pctldev, | ||
211 | unsigned int pin, unsigned long *config) | ||
212 | { | ||
213 | struct stmfx_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
214 | u32 param = pinconf_to_config_param(*config); | ||
215 | struct pinctrl_gpio_range *range; | ||
216 | u32 arg = 0; | ||
217 | int ret, dir, type, pupd; | ||
218 | |||
219 | range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin); | ||
220 | if (!range) | ||
221 | return -EINVAL; | ||
222 | |||
223 | dir = stmfx_gpio_get_direction(&pctl->gpio_chip, pin); | ||
224 | if (dir < 0) | ||
225 | return dir; | ||
226 | type = stmfx_pinconf_get_type(pctl, pin); | ||
227 | if (type < 0) | ||
228 | return type; | ||
229 | pupd = stmfx_pinconf_get_pupd(pctl, pin); | ||
230 | if (pupd < 0) | ||
231 | return pupd; | ||
232 | |||
233 | switch (param) { | ||
234 | case PIN_CONFIG_BIAS_DISABLE: | ||
235 | if ((!dir && (!type || !pupd)) || (dir && !type)) | ||
236 | arg = 1; | ||
237 | break; | ||
238 | case PIN_CONFIG_BIAS_PULL_DOWN: | ||
239 | if (dir && type && !pupd) | ||
240 | arg = 1; | ||
241 | break; | ||
242 | case PIN_CONFIG_BIAS_PULL_UP: | ||
243 | if (type && pupd) | ||
244 | arg = 1; | ||
245 | break; | ||
246 | case PIN_CONFIG_DRIVE_OPEN_DRAIN: | ||
247 | if ((!dir && type) || (dir && !type)) | ||
248 | arg = 1; | ||
249 | break; | ||
250 | case PIN_CONFIG_DRIVE_PUSH_PULL: | ||
251 | if ((!dir && !type) || (dir && type)) | ||
252 | arg = 1; | ||
253 | break; | ||
254 | case PIN_CONFIG_OUTPUT: | ||
255 | if (dir) | ||
256 | return -EINVAL; | ||
257 | |||
258 | ret = stmfx_gpio_get(&pctl->gpio_chip, pin); | ||
259 | if (ret < 0) | ||
260 | return ret; | ||
261 | |||
262 | arg = ret; | ||
263 | break; | ||
264 | default: | ||
265 | return -ENOTSUPP; | ||
266 | } | ||
267 | |||
268 | *config = pinconf_to_config_packed(param, arg); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int stmfx_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, | ||
274 | unsigned long *configs, unsigned int num_configs) | ||
275 | { | ||
276 | struct stmfx_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
277 | struct pinctrl_gpio_range *range; | ||
278 | enum pin_config_param param; | ||
279 | u32 arg; | ||
280 | int dir, i, ret; | ||
281 | |||
282 | range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin); | ||
283 | if (!range) { | ||
284 | dev_err(pctldev->dev, "pin %d is not available\n", pin); | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | |||
288 | dir = stmfx_gpio_get_direction(&pctl->gpio_chip, pin); | ||
289 | if (dir < 0) | ||
290 | return dir; | ||
291 | |||
292 | for (i = 0; i < num_configs; i++) { | ||
293 | param = pinconf_to_config_param(configs[i]); | ||
294 | arg = pinconf_to_config_argument(configs[i]); | ||
295 | |||
296 | switch (param) { | ||
297 | case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: | ||
298 | case PIN_CONFIG_BIAS_DISABLE: | ||
299 | case PIN_CONFIG_BIAS_PULL_DOWN: | ||
300 | ret = stmfx_pinconf_set_pupd(pctl, pin, 0); | ||
301 | if (ret) | ||
302 | return ret; | ||
303 | break; | ||
304 | case PIN_CONFIG_BIAS_PULL_UP: | ||
305 | ret = stmfx_pinconf_set_pupd(pctl, pin, 1); | ||
306 | if (ret) | ||
307 | return ret; | ||
308 | break; | ||
309 | case PIN_CONFIG_DRIVE_OPEN_DRAIN: | ||
310 | if (!dir) | ||
311 | ret = stmfx_pinconf_set_type(pctl, pin, 1); | ||
312 | else | ||
313 | ret = stmfx_pinconf_set_type(pctl, pin, 0); | ||
314 | if (ret) | ||
315 | return ret; | ||
316 | break; | ||
317 | case PIN_CONFIG_DRIVE_PUSH_PULL: | ||
318 | if (!dir) | ||
319 | ret = stmfx_pinconf_set_type(pctl, pin, 0); | ||
320 | else | ||
321 | ret = stmfx_pinconf_set_type(pctl, pin, 1); | ||
322 | if (ret) | ||
323 | return ret; | ||
324 | break; | ||
325 | case PIN_CONFIG_OUTPUT: | ||
326 | ret = stmfx_gpio_direction_output(&pctl->gpio_chip, | ||
327 | pin, arg); | ||
328 | if (ret) | ||
329 | return ret; | ||
330 | break; | ||
331 | default: | ||
332 | return -ENOTSUPP; | ||
333 | } | ||
334 | } | ||
335 | |||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | static void stmfx_pinconf_dbg_show(struct pinctrl_dev *pctldev, | ||
340 | struct seq_file *s, unsigned int offset) | ||
341 | { | ||
342 | struct stmfx_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
343 | struct pinctrl_gpio_range *range; | ||
344 | int dir, type, pupd, val; | ||
345 | |||
346 | range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, offset); | ||
347 | if (!range) | ||
348 | return; | ||
349 | |||
350 | dir = stmfx_gpio_get_direction(&pctl->gpio_chip, offset); | ||
351 | if (dir < 0) | ||
352 | return; | ||
353 | type = stmfx_pinconf_get_type(pctl, offset); | ||
354 | if (type < 0) | ||
355 | return; | ||
356 | pupd = stmfx_pinconf_get_pupd(pctl, offset); | ||
357 | if (pupd < 0) | ||
358 | return; | ||
359 | val = stmfx_gpio_get(&pctl->gpio_chip, offset); | ||
360 | if (val < 0) | ||
361 | return; | ||
362 | |||
363 | if (!dir) { | ||
364 | seq_printf(s, "output %s ", val ? "high" : "low"); | ||
365 | if (type) | ||
366 | seq_printf(s, "open drain %s internal pull-up ", | ||
367 | pupd ? "with" : "without"); | ||
368 | else | ||
369 | seq_puts(s, "push pull no pull "); | ||
370 | } else { | ||
371 | seq_printf(s, "input %s ", val ? "high" : "low"); | ||
372 | if (type) | ||
373 | seq_printf(s, "with internal pull-%s ", | ||
374 | pupd ? "up" : "down"); | ||
375 | else | ||
376 | seq_printf(s, "%s ", pupd ? "floating" : "analog"); | ||
377 | } | ||
378 | } | ||
379 | |||
380 | static const struct pinconf_ops stmfx_pinconf_ops = { | ||
381 | .pin_config_get = stmfx_pinconf_get, | ||
382 | .pin_config_set = stmfx_pinconf_set, | ||
383 | .pin_config_dbg_show = stmfx_pinconf_dbg_show, | ||
384 | }; | ||
385 | |||
386 | static int stmfx_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) | ||
387 | { | ||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | static const char *stmfx_pinctrl_get_group_name(struct pinctrl_dev *pctldev, | ||
392 | unsigned int selector) | ||
393 | { | ||
394 | return NULL; | ||
395 | } | ||
396 | |||
397 | static int stmfx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, | ||
398 | unsigned int selector, | ||
399 | const unsigned int **pins, | ||
400 | unsigned int *num_pins) | ||
401 | { | ||
402 | return -ENOTSUPP; | ||
403 | } | ||
404 | |||
405 | static const struct pinctrl_ops stmfx_pinctrl_ops = { | ||
406 | .get_groups_count = stmfx_pinctrl_get_groups_count, | ||
407 | .get_group_name = stmfx_pinctrl_get_group_name, | ||
408 | .get_group_pins = stmfx_pinctrl_get_group_pins, | ||
409 | .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, | ||
410 | .dt_free_map = pinctrl_utils_free_map, | ||
411 | }; | ||
412 | |||
413 | static void stmfx_pinctrl_irq_mask(struct irq_data *data) | ||
414 | { | ||
415 | struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(data); | ||
416 | struct stmfx_pinctrl *pctl = gpiochip_get_data(gpio_chip); | ||
417 | u32 reg = get_reg(data->hwirq); | ||
418 | u32 mask = get_mask(data->hwirq); | ||
419 | |||
420 | pctl->irq_gpi_src[reg] &= ~mask; | ||
421 | } | ||
422 | |||
423 | static void stmfx_pinctrl_irq_unmask(struct irq_data *data) | ||
424 | { | ||
425 | struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(data); | ||
426 | struct stmfx_pinctrl *pctl = gpiochip_get_data(gpio_chip); | ||
427 | u32 reg = get_reg(data->hwirq); | ||
428 | u32 mask = get_mask(data->hwirq); | ||
429 | |||
430 | pctl->irq_gpi_src[reg] |= mask; | ||
431 | } | ||
432 | |||
433 | static int stmfx_pinctrl_irq_set_type(struct irq_data *data, unsigned int type) | ||
434 | { | ||
435 | struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(data); | ||
436 | struct stmfx_pinctrl *pctl = gpiochip_get_data(gpio_chip); | ||
437 | u32 reg = get_reg(data->hwirq); | ||
438 | u32 mask = get_mask(data->hwirq); | ||
439 | |||
440 | if (type == IRQ_TYPE_NONE) | ||
441 | return -EINVAL; | ||
442 | |||
443 | if (type & IRQ_TYPE_EDGE_BOTH) { | ||
444 | pctl->irq_gpi_evt[reg] |= mask; | ||
445 | irq_set_handler_locked(data, handle_edge_irq); | ||
446 | } else { | ||
447 | pctl->irq_gpi_evt[reg] &= ~mask; | ||
448 | irq_set_handler_locked(data, handle_level_irq); | ||
449 | } | ||
450 | |||
451 | if ((type & IRQ_TYPE_EDGE_RISING) || (type & IRQ_TYPE_LEVEL_HIGH)) | ||
452 | pctl->irq_gpi_type[reg] |= mask; | ||
453 | else | ||
454 | pctl->irq_gpi_type[reg] &= ~mask; | ||
455 | |||
456 | /* | ||
457 | * In case of (type & IRQ_TYPE_EDGE_BOTH), we need to know current | ||
458 | * GPIO value to set the right edge trigger. But in atomic context | ||
459 | * here we can't access registers over I2C. That's why (type & | ||
460 | * IRQ_TYPE_EDGE_BOTH) will be managed in .irq_sync_unlock. | ||
461 | */ | ||
462 | |||
463 | if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) | ||
464 | pctl->irq_toggle_edge[reg] |= mask; | ||
465 | else | ||
466 | pctl->irq_toggle_edge[reg] &= mask; | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static void stmfx_pinctrl_irq_bus_lock(struct irq_data *data) | ||
472 | { | ||
473 | struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(data); | ||
474 | struct stmfx_pinctrl *pctl = gpiochip_get_data(gpio_chip); | ||
475 | |||
476 | mutex_lock(&pctl->lock); | ||
477 | } | ||
478 | |||
479 | static void stmfx_pinctrl_irq_bus_sync_unlock(struct irq_data *data) | ||
480 | { | ||
481 | struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(data); | ||
482 | struct stmfx_pinctrl *pctl = gpiochip_get_data(gpio_chip); | ||
483 | u32 reg = get_reg(data->hwirq); | ||
484 | u32 mask = get_mask(data->hwirq); | ||
485 | |||
486 | /* | ||
487 | * In case of IRQ_TYPE_EDGE_BOTH), read the current GPIO value | ||
488 | * (this couldn't be done in .irq_set_type because of atomic context) | ||
489 | * to set the right irq trigger type. | ||
490 | */ | ||
491 | if (pctl->irq_toggle_edge[reg] & mask) { | ||
492 | if (stmfx_gpio_get(gpio_chip, data->hwirq)) | ||
493 | pctl->irq_gpi_type[reg] &= ~mask; | ||
494 | else | ||
495 | pctl->irq_gpi_type[reg] |= mask; | ||
496 | } | ||
497 | |||
498 | regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_EVT, | ||
499 | pctl->irq_gpi_evt, NR_GPIO_REGS); | ||
500 | regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_TYPE, | ||
501 | pctl->irq_gpi_type, NR_GPIO_REGS); | ||
502 | regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC, | ||
503 | pctl->irq_gpi_src, NR_GPIO_REGS); | ||
504 | |||
505 | mutex_unlock(&pctl->lock); | ||
506 | } | ||
507 | |||
508 | static void stmfx_pinctrl_irq_toggle_trigger(struct stmfx_pinctrl *pctl, | ||
509 | unsigned int offset) | ||
510 | { | ||
511 | u32 reg = get_reg(offset); | ||
512 | u32 mask = get_mask(offset); | ||
513 | int val; | ||
514 | |||
515 | if (!(pctl->irq_toggle_edge[reg] & mask)) | ||
516 | return; | ||
517 | |||
518 | val = stmfx_gpio_get(&pctl->gpio_chip, offset); | ||
519 | if (val < 0) | ||
520 | return; | ||
521 | |||
522 | if (val) { | ||
523 | pctl->irq_gpi_type[reg] &= mask; | ||
524 | regmap_write_bits(pctl->stmfx->map, | ||
525 | STMFX_REG_IRQ_GPI_TYPE + reg, | ||
526 | mask, 0); | ||
527 | |||
528 | } else { | ||
529 | pctl->irq_gpi_type[reg] |= mask; | ||
530 | regmap_write_bits(pctl->stmfx->map, | ||
531 | STMFX_REG_IRQ_GPI_TYPE + reg, | ||
532 | mask, mask); | ||
533 | } | ||
534 | } | ||
535 | |||
536 | static irqreturn_t stmfx_pinctrl_irq_thread_fn(int irq, void *dev_id) | ||
537 | { | ||
538 | struct stmfx_pinctrl *pctl = (struct stmfx_pinctrl *)dev_id; | ||
539 | struct gpio_chip *gc = &pctl->gpio_chip; | ||
540 | u8 pending[NR_GPIO_REGS]; | ||
541 | u8 src[NR_GPIO_REGS] = {0, 0, 0}; | ||
542 | unsigned long n, status; | ||
543 | int ret; | ||
544 | |||
545 | ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_IRQ_GPI_PENDING, | ||
546 | &pending, NR_GPIO_REGS); | ||
547 | if (ret) | ||
548 | return IRQ_NONE; | ||
549 | |||
550 | regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC, | ||
551 | src, NR_GPIO_REGS); | ||
552 | |||
553 | status = *(unsigned long *)pending; | ||
554 | for_each_set_bit(n, &status, gc->ngpio) { | ||
555 | handle_nested_irq(irq_find_mapping(gc->irq.domain, n)); | ||
556 | stmfx_pinctrl_irq_toggle_trigger(pctl, n); | ||
557 | } | ||
558 | |||
559 | regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC, | ||
560 | pctl->irq_gpi_src, NR_GPIO_REGS); | ||
561 | |||
562 | return IRQ_HANDLED; | ||
563 | } | ||
564 | |||
565 | static int stmfx_pinctrl_gpio_function_enable(struct stmfx_pinctrl *pctl) | ||
566 | { | ||
567 | struct pinctrl_gpio_range *gpio_range; | ||
568 | struct pinctrl_dev *pctl_dev = pctl->pctl_dev; | ||
569 | u32 func = STMFX_FUNC_GPIO; | ||
570 | |||
571 | pctl->gpio_valid_mask = GENMASK(15, 0); | ||
572 | |||
573 | gpio_range = pinctrl_find_gpio_range_from_pin(pctl_dev, 16); | ||
574 | if (gpio_range) { | ||
575 | func |= STMFX_FUNC_ALTGPIO_LOW; | ||
576 | pctl->gpio_valid_mask |= GENMASK(19, 16); | ||
577 | } | ||
578 | |||
579 | gpio_range = pinctrl_find_gpio_range_from_pin(pctl_dev, 20); | ||
580 | if (gpio_range) { | ||
581 | func |= STMFX_FUNC_ALTGPIO_HIGH; | ||
582 | pctl->gpio_valid_mask |= GENMASK(23, 20); | ||
583 | } | ||
584 | |||
585 | return stmfx_function_enable(pctl->stmfx, func); | ||
586 | } | ||
587 | |||
588 | static int stmfx_pinctrl_probe(struct platform_device *pdev) | ||
589 | { | ||
590 | struct stmfx *stmfx = dev_get_drvdata(pdev->dev.parent); | ||
591 | struct device_node *np = pdev->dev.of_node; | ||
592 | struct stmfx_pinctrl *pctl; | ||
593 | u32 n; | ||
594 | int irq, ret; | ||
595 | |||
596 | pctl = devm_kzalloc(stmfx->dev, sizeof(*pctl), GFP_KERNEL); | ||
597 | if (!pctl) | ||
598 | return -ENOMEM; | ||
599 | |||
600 | platform_set_drvdata(pdev, pctl); | ||
601 | |||
602 | pctl->dev = &pdev->dev; | ||
603 | pctl->stmfx = stmfx; | ||
604 | |||
605 | if (!of_find_property(np, "gpio-ranges", NULL)) { | ||
606 | dev_err(pctl->dev, "missing required gpio-ranges property\n"); | ||
607 | return -EINVAL; | ||
608 | } | ||
609 | |||
610 | irq = platform_get_irq(pdev, 0); | ||
611 | if (irq <= 0) { | ||
612 | dev_err(pctl->dev, "failed to get irq\n"); | ||
613 | return -ENXIO; | ||
614 | } | ||
615 | |||
616 | mutex_init(&pctl->lock); | ||
617 | |||
618 | /* Register pin controller */ | ||
619 | pctl->pctl_desc.name = "stmfx-pinctrl"; | ||
620 | pctl->pctl_desc.pctlops = &stmfx_pinctrl_ops; | ||
621 | pctl->pctl_desc.confops = &stmfx_pinconf_ops; | ||
622 | pctl->pctl_desc.pins = stmfx_pins; | ||
623 | pctl->pctl_desc.npins = ARRAY_SIZE(stmfx_pins); | ||
624 | pctl->pctl_desc.owner = THIS_MODULE; | ||
625 | |||
626 | ret = devm_pinctrl_register_and_init(pctl->dev, &pctl->pctl_desc, | ||
627 | pctl, &pctl->pctl_dev); | ||
628 | if (ret) { | ||
629 | dev_err(pctl->dev, "pinctrl registration failed\n"); | ||
630 | return ret; | ||
631 | } | ||
632 | |||
633 | ret = pinctrl_enable(pctl->pctl_dev); | ||
634 | if (ret) { | ||
635 | dev_err(pctl->dev, "pinctrl enable failed\n"); | ||
636 | return ret; | ||
637 | } | ||
638 | |||
639 | /* Register gpio controller */ | ||
640 | pctl->gpio_chip.label = "stmfx-gpio"; | ||
641 | pctl->gpio_chip.parent = pctl->dev; | ||
642 | pctl->gpio_chip.get_direction = stmfx_gpio_get_direction; | ||
643 | pctl->gpio_chip.direction_input = stmfx_gpio_direction_input; | ||
644 | pctl->gpio_chip.direction_output = stmfx_gpio_direction_output; | ||
645 | pctl->gpio_chip.get = stmfx_gpio_get; | ||
646 | pctl->gpio_chip.set = stmfx_gpio_set; | ||
647 | pctl->gpio_chip.set_config = gpiochip_generic_config; | ||
648 | pctl->gpio_chip.base = -1; | ||
649 | pctl->gpio_chip.ngpio = pctl->pctl_desc.npins; | ||
650 | pctl->gpio_chip.can_sleep = true; | ||
651 | pctl->gpio_chip.of_node = np; | ||
652 | pctl->gpio_chip.need_valid_mask = true; | ||
653 | |||
654 | ret = devm_gpiochip_add_data(pctl->dev, &pctl->gpio_chip, pctl); | ||
655 | if (ret) { | ||
656 | dev_err(pctl->dev, "gpio_chip registration failed\n"); | ||
657 | return ret; | ||
658 | } | ||
659 | |||
660 | ret = stmfx_pinctrl_gpio_function_enable(pctl); | ||
661 | if (ret) | ||
662 | return ret; | ||
663 | |||
664 | pctl->irq_chip.name = dev_name(pctl->dev); | ||
665 | pctl->irq_chip.irq_mask = stmfx_pinctrl_irq_mask; | ||
666 | pctl->irq_chip.irq_unmask = stmfx_pinctrl_irq_unmask; | ||
667 | pctl->irq_chip.irq_set_type = stmfx_pinctrl_irq_set_type; | ||
668 | pctl->irq_chip.irq_bus_lock = stmfx_pinctrl_irq_bus_lock; | ||
669 | pctl->irq_chip.irq_bus_sync_unlock = stmfx_pinctrl_irq_bus_sync_unlock; | ||
670 | for_each_clear_bit(n, &pctl->gpio_valid_mask, pctl->gpio_chip.ngpio) | ||
671 | clear_bit(n, pctl->gpio_chip.valid_mask); | ||
672 | |||
673 | ret = gpiochip_irqchip_add_nested(&pctl->gpio_chip, &pctl->irq_chip, | ||
674 | 0, handle_bad_irq, IRQ_TYPE_NONE); | ||
675 | if (ret) { | ||
676 | dev_err(pctl->dev, "cannot add irqchip to gpiochip\n"); | ||
677 | return ret; | ||
678 | } | ||
679 | |||
680 | ret = devm_request_threaded_irq(pctl->dev, irq, NULL, | ||
681 | stmfx_pinctrl_irq_thread_fn, | ||
682 | IRQF_ONESHOT, | ||
683 | pctl->irq_chip.name, pctl); | ||
684 | if (ret) { | ||
685 | dev_err(pctl->dev, "cannot request irq%d\n", irq); | ||
686 | return ret; | ||
687 | } | ||
688 | |||
689 | gpiochip_set_nested_irqchip(&pctl->gpio_chip, &pctl->irq_chip, irq); | ||
690 | |||
691 | dev_info(pctl->dev, | ||
692 | "%ld GPIOs available\n", hweight_long(pctl->gpio_valid_mask)); | ||
693 | |||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | static int stmfx_pinctrl_remove(struct platform_device *pdev) | ||
698 | { | ||
699 | struct stmfx *stmfx = dev_get_platdata(&pdev->dev); | ||
700 | |||
701 | return stmfx_function_disable(stmfx, | ||
702 | STMFX_FUNC_GPIO | | ||
703 | STMFX_FUNC_ALTGPIO_LOW | | ||
704 | STMFX_FUNC_ALTGPIO_HIGH); | ||
705 | } | ||
706 | |||
707 | #ifdef CONFIG_PM_SLEEP | ||
708 | static int stmfx_pinctrl_backup_regs(struct stmfx_pinctrl *pctl) | ||
709 | { | ||
710 | int ret; | ||
711 | |||
712 | ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_GPIO_STATE, | ||
713 | &pctl->bkp_gpio_state, NR_GPIO_REGS); | ||
714 | if (ret) | ||
715 | return ret; | ||
716 | ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_GPIO_DIR, | ||
717 | &pctl->bkp_gpio_dir, NR_GPIO_REGS); | ||
718 | if (ret) | ||
719 | return ret; | ||
720 | ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_GPIO_TYPE, | ||
721 | &pctl->bkp_gpio_type, NR_GPIO_REGS); | ||
722 | if (ret) | ||
723 | return ret; | ||
724 | ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_GPIO_PUPD, | ||
725 | &pctl->bkp_gpio_pupd, NR_GPIO_REGS); | ||
726 | if (ret) | ||
727 | return ret; | ||
728 | |||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | static int stmfx_pinctrl_restore_regs(struct stmfx_pinctrl *pctl) | ||
733 | { | ||
734 | int ret; | ||
735 | |||
736 | ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_GPIO_DIR, | ||
737 | pctl->bkp_gpio_dir, NR_GPIO_REGS); | ||
738 | if (ret) | ||
739 | return ret; | ||
740 | ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_GPIO_TYPE, | ||
741 | pctl->bkp_gpio_type, NR_GPIO_REGS); | ||
742 | if (ret) | ||
743 | return ret; | ||
744 | ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_GPIO_PUPD, | ||
745 | pctl->bkp_gpio_pupd, NR_GPIO_REGS); | ||
746 | if (ret) | ||
747 | return ret; | ||
748 | ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_GPO_SET, | ||
749 | pctl->bkp_gpio_state, NR_GPIO_REGS); | ||
750 | if (ret) | ||
751 | return ret; | ||
752 | ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_EVT, | ||
753 | pctl->irq_gpi_evt, NR_GPIO_REGS); | ||
754 | if (ret) | ||
755 | return ret; | ||
756 | ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_TYPE, | ||
757 | pctl->irq_gpi_type, NR_GPIO_REGS); | ||
758 | if (ret) | ||
759 | return ret; | ||
760 | ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC, | ||
761 | pctl->irq_gpi_src, NR_GPIO_REGS); | ||
762 | if (ret) | ||
763 | return ret; | ||
764 | |||
765 | return 0; | ||
766 | } | ||
767 | |||
768 | static int stmfx_pinctrl_suspend(struct device *dev) | ||
769 | { | ||
770 | struct stmfx_pinctrl *pctl = dev_get_drvdata(dev); | ||
771 | int ret; | ||
772 | |||
773 | ret = stmfx_pinctrl_backup_regs(pctl); | ||
774 | if (ret) { | ||
775 | dev_err(pctl->dev, "registers backup failure\n"); | ||
776 | return ret; | ||
777 | } | ||
778 | |||
779 | return 0; | ||
780 | } | ||
781 | |||
782 | static int stmfx_pinctrl_resume(struct device *dev) | ||
783 | { | ||
784 | struct stmfx_pinctrl *pctl = dev_get_drvdata(dev); | ||
785 | int ret; | ||
786 | |||
787 | ret = stmfx_pinctrl_restore_regs(pctl); | ||
788 | if (ret) { | ||
789 | dev_err(pctl->dev, "registers restoration failure\n"); | ||
790 | return ret; | ||
791 | } | ||
792 | |||
793 | return 0; | ||
794 | } | ||
795 | #endif | ||
796 | |||
797 | static SIMPLE_DEV_PM_OPS(stmfx_pinctrl_dev_pm_ops, | ||
798 | stmfx_pinctrl_suspend, stmfx_pinctrl_resume); | ||
799 | |||
800 | static const struct of_device_id stmfx_pinctrl_of_match[] = { | ||
801 | { .compatible = "st,stmfx-0300-pinctrl", }, | ||
802 | {}, | ||
803 | }; | ||
804 | MODULE_DEVICE_TABLE(of, stmfx_pinctrl_of_match); | ||
805 | |||
806 | static struct platform_driver stmfx_pinctrl_driver = { | ||
807 | .driver = { | ||
808 | .name = "stmfx-pinctrl", | ||
809 | .of_match_table = stmfx_pinctrl_of_match, | ||
810 | .pm = &stmfx_pinctrl_dev_pm_ops, | ||
811 | }, | ||
812 | .probe = stmfx_pinctrl_probe, | ||
813 | .remove = stmfx_pinctrl_remove, | ||
814 | }; | ||
815 | module_platform_driver(stmfx_pinctrl_driver); | ||
816 | |||
817 | MODULE_DESCRIPTION("STMFX pinctrl/GPIO driver"); | ||
818 | MODULE_AUTHOR("Amelie Delaunay <amelie.delaunay@st.com>"); | ||
819 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index 171475862ede..3d2325197a68 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c | |||
@@ -429,6 +429,12 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev) | |||
429 | else | 429 | else |
430 | ec_dev->mkbp_event_supported = 1; | 430 | ec_dev->mkbp_event_supported = 1; |
431 | 431 | ||
432 | /* Probe if host sleep v1 is supported for S0ix failure detection. */ | ||
433 | ret = cros_ec_get_host_command_version_mask(ec_dev, | ||
434 | EC_CMD_HOST_SLEEP_EVENT, | ||
435 | &ver_mask); | ||
436 | ec_dev->host_sleep_v1 = (ret >= 0 && (ver_mask & EC_VER_MASK(1))); | ||
437 | |||
432 | /* | 438 | /* |
433 | * Get host event wake mask, assume all events are wake events | 439 | * Get host event wake mask, assume all events are wake events |
434 | * if unavailable. | 440 | * if unavailable. |
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index e901b9879e7e..0230c96fa94d 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig | |||
@@ -499,6 +499,13 @@ config CHARGER_DETECTOR_MAX14656 | |||
499 | Revision 1.2 and can be found e.g. in Kindle 4/5th generation | 499 | Revision 1.2 and can be found e.g. in Kindle 4/5th generation |
500 | readers and certain LG devices. | 500 | readers and certain LG devices. |
501 | 501 | ||
502 | config CHARGER_MAX77650 | ||
503 | tristate "Maxim MAX77650 battery charger driver" | ||
504 | depends on MFD_MAX77650 | ||
505 | help | ||
506 | Say Y to enable support for the battery charger control of MAX77650 | ||
507 | PMICs. | ||
508 | |||
502 | config CHARGER_MAX77693 | 509 | config CHARGER_MAX77693 |
503 | tristate "Maxim MAX77693 battery charger driver" | 510 | tristate "Maxim MAX77693 battery charger driver" |
504 | depends on MFD_MAX77693 | 511 | depends on MFD_MAX77693 |
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index b731c2a9b695..b73eb8c5c1a9 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile | |||
@@ -70,6 +70,7 @@ obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o | |||
70 | obj-$(CONFIG_CHARGER_LTC3651) += ltc3651-charger.o | 70 | obj-$(CONFIG_CHARGER_LTC3651) += ltc3651-charger.o |
71 | obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o | 71 | obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o |
72 | obj-$(CONFIG_CHARGER_DETECTOR_MAX14656) += max14656_charger_detector.o | 72 | obj-$(CONFIG_CHARGER_DETECTOR_MAX14656) += max14656_charger_detector.o |
73 | obj-$(CONFIG_CHARGER_MAX77650) += max77650-charger.o | ||
73 | obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o | 74 | obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o |
74 | obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o | 75 | obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o |
75 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o | 76 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o |
diff --git a/drivers/power/supply/max77650-charger.c b/drivers/power/supply/max77650-charger.c new file mode 100644 index 000000000000..e34714cb05ec --- /dev/null +++ b/drivers/power/supply/max77650-charger.c | |||
@@ -0,0 +1,368 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // | ||
3 | // Copyright (C) 2018 BayLibre SAS | ||
4 | // Author: Bartosz Golaszewski <bgolaszewski@baylibre.com> | ||
5 | // | ||
6 | // Battery charger driver for MAXIM 77650/77651 charger/power-supply. | ||
7 | |||
8 | #include <linux/i2c.h> | ||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/mfd/max77650.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/power_supply.h> | ||
14 | #include <linux/regmap.h> | ||
15 | |||
16 | #define MAX77650_CHARGER_ENABLED BIT(0) | ||
17 | #define MAX77650_CHARGER_DISABLED 0x00 | ||
18 | #define MAX77650_CHARGER_CHG_EN_MASK BIT(0) | ||
19 | |||
20 | #define MAX77650_CHG_DETAILS_MASK GENMASK(7, 4) | ||
21 | #define MAX77650_CHG_DETAILS_BITS(_reg) \ | ||
22 | (((_reg) & MAX77650_CHG_DETAILS_MASK) >> 4) | ||
23 | |||
24 | /* Charger is OFF. */ | ||
25 | #define MAX77650_CHG_OFF 0x00 | ||
26 | /* Charger is in prequalification mode. */ | ||
27 | #define MAX77650_CHG_PREQ 0x01 | ||
28 | /* Charger is in fast-charge constant current mode. */ | ||
29 | #define MAX77650_CHG_ON_CURR 0x02 | ||
30 | /* Charger is in JEITA modified fast-charge constant-current mode. */ | ||
31 | #define MAX77650_CHG_ON_CURR_JEITA 0x03 | ||
32 | /* Charger is in fast-charge constant-voltage mode. */ | ||
33 | #define MAX77650_CHG_ON_VOLT 0x04 | ||
34 | /* Charger is in JEITA modified fast-charge constant-voltage mode. */ | ||
35 | #define MAX77650_CHG_ON_VOLT_JEITA 0x05 | ||
36 | /* Charger is in top-off mode. */ | ||
37 | #define MAX77650_CHG_ON_TOPOFF 0x06 | ||
38 | /* Charger is in JEITA modified top-off mode. */ | ||
39 | #define MAX77650_CHG_ON_TOPOFF_JEITA 0x07 | ||
40 | /* Charger is done. */ | ||
41 | #define MAX77650_CHG_DONE 0x08 | ||
42 | /* Charger is JEITA modified done. */ | ||
43 | #define MAX77650_CHG_DONE_JEITA 0x09 | ||
44 | /* Charger is suspended due to a prequalification timer fault. */ | ||
45 | #define MAX77650_CHG_SUSP_PREQ_TIM_FAULT 0x0a | ||
46 | /* Charger is suspended due to a fast-charge timer fault. */ | ||
47 | #define MAX77650_CHG_SUSP_FAST_CHG_TIM_FAULT 0x0b | ||
48 | /* Charger is suspended due to a battery temperature fault. */ | ||
49 | #define MAX77650_CHG_SUSP_BATT_TEMP_FAULT 0x0c | ||
50 | |||
51 | #define MAX77650_CHGIN_DETAILS_MASK GENMASK(3, 2) | ||
52 | #define MAX77650_CHGIN_DETAILS_BITS(_reg) \ | ||
53 | (((_reg) & MAX77650_CHGIN_DETAILS_MASK) >> 2) | ||
54 | |||
55 | #define MAX77650_CHGIN_UNDERVOLTAGE_LOCKOUT 0x00 | ||
56 | #define MAX77650_CHGIN_OVERVOLTAGE_LOCKOUT 0x01 | ||
57 | #define MAX77650_CHGIN_OKAY 0x11 | ||
58 | |||
59 | #define MAX77650_CHARGER_CHG_MASK BIT(1) | ||
60 | #define MAX77650_CHARGER_CHG_CHARGING(_reg) \ | ||
61 | (((_reg) & MAX77650_CHARGER_CHG_MASK) > 1) | ||
62 | |||
63 | #define MAX77650_CHARGER_VCHGIN_MIN_MASK 0xc0 | ||
64 | #define MAX77650_CHARGER_VCHGIN_MIN_SHIFT(_val) ((_val) << 5) | ||
65 | |||
66 | #define MAX77650_CHARGER_ICHGIN_LIM_MASK 0x1c | ||
67 | #define MAX77650_CHARGER_ICHGIN_LIM_SHIFT(_val) ((_val) << 2) | ||
68 | |||
69 | struct max77650_charger_data { | ||
70 | struct regmap *map; | ||
71 | struct device *dev; | ||
72 | }; | ||
73 | |||
74 | static enum power_supply_property max77650_charger_properties[] = { | ||
75 | POWER_SUPPLY_PROP_STATUS, | ||
76 | POWER_SUPPLY_PROP_ONLINE, | ||
77 | POWER_SUPPLY_PROP_CHARGE_TYPE | ||
78 | }; | ||
79 | |||
80 | static const unsigned int max77650_charger_vchgin_min_table[] = { | ||
81 | 4000000, 4100000, 4200000, 4300000, 4400000, 4500000, 4600000, 4700000 | ||
82 | }; | ||
83 | |||
84 | static const unsigned int max77650_charger_ichgin_lim_table[] = { | ||
85 | 95000, 190000, 285000, 380000, 475000 | ||
86 | }; | ||
87 | |||
88 | static int max77650_charger_set_vchgin_min(struct max77650_charger_data *chg, | ||
89 | unsigned int val) | ||
90 | { | ||
91 | int i, rv; | ||
92 | |||
93 | for (i = 0; i < ARRAY_SIZE(max77650_charger_vchgin_min_table); i++) { | ||
94 | if (val == max77650_charger_vchgin_min_table[i]) { | ||
95 | rv = regmap_update_bits(chg->map, | ||
96 | MAX77650_REG_CNFG_CHG_B, | ||
97 | MAX77650_CHARGER_VCHGIN_MIN_MASK, | ||
98 | MAX77650_CHARGER_VCHGIN_MIN_SHIFT(i)); | ||
99 | if (rv) | ||
100 | return rv; | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | return -EINVAL; | ||
107 | } | ||
108 | |||
109 | static int max77650_charger_set_ichgin_lim(struct max77650_charger_data *chg, | ||
110 | unsigned int val) | ||
111 | { | ||
112 | int i, rv; | ||
113 | |||
114 | for (i = 0; i < ARRAY_SIZE(max77650_charger_ichgin_lim_table); i++) { | ||
115 | if (val == max77650_charger_ichgin_lim_table[i]) { | ||
116 | rv = regmap_update_bits(chg->map, | ||
117 | MAX77650_REG_CNFG_CHG_B, | ||
118 | MAX77650_CHARGER_ICHGIN_LIM_MASK, | ||
119 | MAX77650_CHARGER_ICHGIN_LIM_SHIFT(i)); | ||
120 | if (rv) | ||
121 | return rv; | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | return -EINVAL; | ||
128 | } | ||
129 | |||
130 | static int max77650_charger_enable(struct max77650_charger_data *chg) | ||
131 | { | ||
132 | int rv; | ||
133 | |||
134 | rv = regmap_update_bits(chg->map, | ||
135 | MAX77650_REG_CNFG_CHG_B, | ||
136 | MAX77650_CHARGER_CHG_EN_MASK, | ||
137 | MAX77650_CHARGER_ENABLED); | ||
138 | if (rv) | ||
139 | dev_err(chg->dev, "unable to enable the charger: %d\n", rv); | ||
140 | |||
141 | return rv; | ||
142 | } | ||
143 | |||
144 | static int max77650_charger_disable(struct max77650_charger_data *chg) | ||
145 | { | ||
146 | int rv; | ||
147 | |||
148 | rv = regmap_update_bits(chg->map, | ||
149 | MAX77650_REG_CNFG_CHG_B, | ||
150 | MAX77650_CHARGER_CHG_EN_MASK, | ||
151 | MAX77650_CHARGER_DISABLED); | ||
152 | if (rv) | ||
153 | dev_err(chg->dev, "unable to disable the charger: %d\n", rv); | ||
154 | |||
155 | return rv; | ||
156 | } | ||
157 | |||
158 | static irqreturn_t max77650_charger_check_status(int irq, void *data) | ||
159 | { | ||
160 | struct max77650_charger_data *chg = data; | ||
161 | int rv, reg; | ||
162 | |||
163 | rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, ®); | ||
164 | if (rv) { | ||
165 | dev_err(chg->dev, | ||
166 | "unable to read the charger status: %d\n", rv); | ||
167 | return IRQ_HANDLED; | ||
168 | } | ||
169 | |||
170 | switch (MAX77650_CHGIN_DETAILS_BITS(reg)) { | ||
171 | case MAX77650_CHGIN_UNDERVOLTAGE_LOCKOUT: | ||
172 | dev_err(chg->dev, "undervoltage lockout detected, disabling charger\n"); | ||
173 | max77650_charger_disable(chg); | ||
174 | break; | ||
175 | case MAX77650_CHGIN_OVERVOLTAGE_LOCKOUT: | ||
176 | dev_err(chg->dev, "overvoltage lockout detected, disabling charger\n"); | ||
177 | max77650_charger_disable(chg); | ||
178 | break; | ||
179 | case MAX77650_CHGIN_OKAY: | ||
180 | max77650_charger_enable(chg); | ||
181 | break; | ||
182 | default: | ||
183 | /* May be 0x10 - debouncing */ | ||
184 | break; | ||
185 | } | ||
186 | |||
187 | return IRQ_HANDLED; | ||
188 | } | ||
189 | |||
190 | static int max77650_charger_get_property(struct power_supply *psy, | ||
191 | enum power_supply_property psp, | ||
192 | union power_supply_propval *val) | ||
193 | { | ||
194 | struct max77650_charger_data *chg = power_supply_get_drvdata(psy); | ||
195 | int rv, reg; | ||
196 | |||
197 | switch (psp) { | ||
198 | case POWER_SUPPLY_PROP_STATUS: | ||
199 | rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, ®); | ||
200 | if (rv) | ||
201 | return rv; | ||
202 | |||
203 | if (MAX77650_CHARGER_CHG_CHARGING(reg)) { | ||
204 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
205 | break; | ||
206 | } | ||
207 | |||
208 | switch (MAX77650_CHG_DETAILS_BITS(reg)) { | ||
209 | case MAX77650_CHG_OFF: | ||
210 | case MAX77650_CHG_SUSP_PREQ_TIM_FAULT: | ||
211 | case MAX77650_CHG_SUSP_FAST_CHG_TIM_FAULT: | ||
212 | case MAX77650_CHG_SUSP_BATT_TEMP_FAULT: | ||
213 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
214 | break; | ||
215 | case MAX77650_CHG_PREQ: | ||
216 | case MAX77650_CHG_ON_CURR: | ||
217 | case MAX77650_CHG_ON_CURR_JEITA: | ||
218 | case MAX77650_CHG_ON_VOLT: | ||
219 | case MAX77650_CHG_ON_VOLT_JEITA: | ||
220 | case MAX77650_CHG_ON_TOPOFF: | ||
221 | case MAX77650_CHG_ON_TOPOFF_JEITA: | ||
222 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
223 | break; | ||
224 | case MAX77650_CHG_DONE: | ||
225 | val->intval = POWER_SUPPLY_STATUS_FULL; | ||
226 | break; | ||
227 | default: | ||
228 | val->intval = POWER_SUPPLY_STATUS_UNKNOWN; | ||
229 | } | ||
230 | break; | ||
231 | case POWER_SUPPLY_PROP_ONLINE: | ||
232 | rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, ®); | ||
233 | if (rv) | ||
234 | return rv; | ||
235 | |||
236 | val->intval = MAX77650_CHARGER_CHG_CHARGING(reg); | ||
237 | break; | ||
238 | case POWER_SUPPLY_PROP_CHARGE_TYPE: | ||
239 | rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, ®); | ||
240 | if (rv) | ||
241 | return rv; | ||
242 | |||
243 | if (!MAX77650_CHARGER_CHG_CHARGING(reg)) { | ||
244 | val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; | ||
245 | break; | ||
246 | } | ||
247 | |||
248 | switch (MAX77650_CHG_DETAILS_BITS(reg)) { | ||
249 | case MAX77650_CHG_PREQ: | ||
250 | case MAX77650_CHG_ON_CURR: | ||
251 | case MAX77650_CHG_ON_CURR_JEITA: | ||
252 | case MAX77650_CHG_ON_VOLT: | ||
253 | case MAX77650_CHG_ON_VOLT_JEITA: | ||
254 | val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; | ||
255 | break; | ||
256 | case MAX77650_CHG_ON_TOPOFF: | ||
257 | case MAX77650_CHG_ON_TOPOFF_JEITA: | ||
258 | val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; | ||
259 | break; | ||
260 | default: | ||
261 | val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN; | ||
262 | } | ||
263 | break; | ||
264 | default: | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | |||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static const struct power_supply_desc max77650_battery_desc = { | ||
272 | .name = "max77650", | ||
273 | .type = POWER_SUPPLY_TYPE_USB, | ||
274 | .get_property = max77650_charger_get_property, | ||
275 | .properties = max77650_charger_properties, | ||
276 | .num_properties = ARRAY_SIZE(max77650_charger_properties), | ||
277 | }; | ||
278 | |||
279 | static int max77650_charger_probe(struct platform_device *pdev) | ||
280 | { | ||
281 | struct power_supply_config pscfg = {}; | ||
282 | struct max77650_charger_data *chg; | ||
283 | struct power_supply *battery; | ||
284 | struct device *dev, *parent; | ||
285 | int rv, chg_irq, chgin_irq; | ||
286 | unsigned int prop; | ||
287 | |||
288 | dev = &pdev->dev; | ||
289 | parent = dev->parent; | ||
290 | |||
291 | chg = devm_kzalloc(dev, sizeof(*chg), GFP_KERNEL); | ||
292 | if (!chg) | ||
293 | return -ENOMEM; | ||
294 | |||
295 | platform_set_drvdata(pdev, chg); | ||
296 | |||
297 | chg->map = dev_get_regmap(parent, NULL); | ||
298 | if (!chg->map) | ||
299 | return -ENODEV; | ||
300 | |||
301 | chg->dev = dev; | ||
302 | |||
303 | pscfg.of_node = dev->of_node; | ||
304 | pscfg.drv_data = chg; | ||
305 | |||
306 | chg_irq = platform_get_irq_byname(pdev, "CHG"); | ||
307 | if (chg_irq < 0) | ||
308 | return chg_irq; | ||
309 | |||
310 | chgin_irq = platform_get_irq_byname(pdev, "CHGIN"); | ||
311 | if (chgin_irq < 0) | ||
312 | return chgin_irq; | ||
313 | |||
314 | rv = devm_request_any_context_irq(dev, chg_irq, | ||
315 | max77650_charger_check_status, | ||
316 | IRQF_ONESHOT, "chg", chg); | ||
317 | if (rv < 0) | ||
318 | return rv; | ||
319 | |||
320 | rv = devm_request_any_context_irq(dev, chgin_irq, | ||
321 | max77650_charger_check_status, | ||
322 | IRQF_ONESHOT, "chgin", chg); | ||
323 | if (rv < 0) | ||
324 | return rv; | ||
325 | |||
326 | battery = devm_power_supply_register(dev, | ||
327 | &max77650_battery_desc, &pscfg); | ||
328 | if (IS_ERR(battery)) | ||
329 | return PTR_ERR(battery); | ||
330 | |||
331 | rv = of_property_read_u32(dev->of_node, | ||
332 | "input-voltage-min-microvolt", &prop); | ||
333 | if (rv == 0) { | ||
334 | rv = max77650_charger_set_vchgin_min(chg, prop); | ||
335 | if (rv) | ||
336 | return rv; | ||
337 | } | ||
338 | |||
339 | rv = of_property_read_u32(dev->of_node, | ||
340 | "input-current-limit-microamp", &prop); | ||
341 | if (rv == 0) { | ||
342 | rv = max77650_charger_set_ichgin_lim(chg, prop); | ||
343 | if (rv) | ||
344 | return rv; | ||
345 | } | ||
346 | |||
347 | return max77650_charger_enable(chg); | ||
348 | } | ||
349 | |||
350 | static int max77650_charger_remove(struct platform_device *pdev) | ||
351 | { | ||
352 | struct max77650_charger_data *chg = platform_get_drvdata(pdev); | ||
353 | |||
354 | return max77650_charger_disable(chg); | ||
355 | } | ||
356 | |||
357 | static struct platform_driver max77650_charger_driver = { | ||
358 | .driver = { | ||
359 | .name = "max77650-charger", | ||
360 | }, | ||
361 | .probe = max77650_charger_probe, | ||
362 | .remove = max77650_charger_remove, | ||
363 | }; | ||
364 | module_platform_driver(max77650_charger_driver); | ||
365 | |||
366 | MODULE_DESCRIPTION("MAXIM 77650/77651 charger driver"); | ||
367 | MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); | ||
368 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/include/linux/mfd/altera-sysmgr.h b/include/linux/mfd/altera-sysmgr.h new file mode 100644 index 000000000000..b1ef11a83872 --- /dev/null +++ b/include/linux/mfd/altera-sysmgr.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * Copyright (C) 2018-2019 Intel Corporation | ||
4 | * Copyright (C) 2012 Freescale Semiconductor, Inc. | ||
5 | * Copyright (C) 2012 Linaro Ltd. | ||
6 | */ | ||
7 | |||
8 | #ifndef __LINUX_MFD_ALTERA_SYSMGR_H__ | ||
9 | #define __LINUX_MFD_ALTERA_SYSMGR_H__ | ||
10 | |||
11 | #include <linux/err.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/firmware/intel/stratix10-smc.h> | ||
14 | |||
15 | struct device_node; | ||
16 | |||
17 | #ifdef CONFIG_MFD_ALTERA_SYSMGR | ||
18 | struct regmap *altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np, | ||
19 | const char *property); | ||
20 | #else | ||
21 | static inline struct regmap * | ||
22 | altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np, | ||
23 | const char *property) | ||
24 | { | ||
25 | return ERR_PTR(-ENOTSUPP); | ||
26 | } | ||
27 | #endif | ||
28 | |||
29 | #endif /* __LINUX_MFD_ALTERA_SYSMGR_H__ */ | ||
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h index 8f2a8918bfa3..cfa78bb4990f 100644 --- a/include/linux/mfd/cros_ec.h +++ b/include/linux/mfd/cros_ec.h | |||
@@ -23,7 +23,10 @@ | |||
23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
24 | 24 | ||
25 | #define CROS_EC_DEV_NAME "cros_ec" | 25 | #define CROS_EC_DEV_NAME "cros_ec" |
26 | #define CROS_EC_DEV_FP_NAME "cros_fp" | ||
26 | #define CROS_EC_DEV_PD_NAME "cros_pd" | 27 | #define CROS_EC_DEV_PD_NAME "cros_pd" |
28 | #define CROS_EC_DEV_TP_NAME "cros_tp" | ||
29 | #define CROS_EC_DEV_ISH_NAME "cros_ish" | ||
27 | 30 | ||
28 | /* | 31 | /* |
29 | * The EC is unresponsive for a time after a reboot command. Add a | 32 | * The EC is unresponsive for a time after a reboot command. Add a |
@@ -120,6 +123,7 @@ struct cros_ec_command { | |||
120 | * @pkt_xfer: Send packet to EC and get response. | 123 | * @pkt_xfer: Send packet to EC and get response. |
121 | * @lock: One transaction at a time. | 124 | * @lock: One transaction at a time. |
122 | * @mkbp_event_supported: True if this EC supports the MKBP event protocol. | 125 | * @mkbp_event_supported: True if this EC supports the MKBP event protocol. |
126 | * @host_sleep_v1: True if this EC supports the sleep v1 command. | ||
123 | * @event_notifier: Interrupt event notifier for transport devices. | 127 | * @event_notifier: Interrupt event notifier for transport devices. |
124 | * @event_data: Raw payload transferred with the MKBP event. | 128 | * @event_data: Raw payload transferred with the MKBP event. |
125 | * @event_size: Size in bytes of the event data. | 129 | * @event_size: Size in bytes of the event data. |
@@ -153,6 +157,7 @@ struct cros_ec_device { | |||
153 | struct cros_ec_command *msg); | 157 | struct cros_ec_command *msg); |
154 | struct mutex lock; | 158 | struct mutex lock; |
155 | bool mkbp_event_supported; | 159 | bool mkbp_event_supported; |
160 | bool host_sleep_v1; | ||
156 | struct blocking_notifier_head event_notifier; | 161 | struct blocking_notifier_head event_notifier; |
157 | 162 | ||
158 | struct ec_response_get_next_event_v1 event_data; | 163 | struct ec_response_get_next_event_v1 event_data; |
diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h index fc91082d4c35..dcec96f01879 100644 --- a/include/linux/mfd/cros_ec_commands.h +++ b/include/linux/mfd/cros_ec_commands.h | |||
@@ -840,7 +840,7 @@ enum ec_feature_code { | |||
840 | * (Common Smart Battery System Interface Specification) | 840 | * (Common Smart Battery System Interface Specification) |
841 | */ | 841 | */ |
842 | EC_FEATURE_SMART_BATTERY = 18, | 842 | EC_FEATURE_SMART_BATTERY = 18, |
843 | /* EC can dectect when the host hangs. */ | 843 | /* EC can detect when the host hangs. */ |
844 | EC_FEATURE_HANG_DETECT = 19, | 844 | EC_FEATURE_HANG_DETECT = 19, |
845 | /* Report power information, for pit only */ | 845 | /* Report power information, for pit only */ |
846 | EC_FEATURE_PMU = 20, | 846 | EC_FEATURE_PMU = 20, |
@@ -852,10 +852,42 @@ enum ec_feature_code { | |||
852 | EC_FEATURE_USB_MUX = 23, | 852 | EC_FEATURE_USB_MUX = 23, |
853 | /* Motion Sensor code has an internal software FIFO */ | 853 | /* Motion Sensor code has an internal software FIFO */ |
854 | EC_FEATURE_MOTION_SENSE_FIFO = 24, | 854 | EC_FEATURE_MOTION_SENSE_FIFO = 24, |
855 | /* Support temporary secure vstore */ | ||
856 | EC_FEATURE_VSTORE = 25, | ||
857 | /* EC decides on USB-C SS mux state, muxes configured by host */ | ||
858 | EC_FEATURE_USBC_SS_MUX_VIRTUAL = 26, | ||
855 | /* EC has RTC feature that can be controlled by host commands */ | 859 | /* EC has RTC feature that can be controlled by host commands */ |
856 | EC_FEATURE_RTC = 27, | 860 | EC_FEATURE_RTC = 27, |
861 | /* The MCU exposes a Fingerprint sensor */ | ||
862 | EC_FEATURE_FINGERPRINT = 28, | ||
863 | /* The MCU exposes a Touchpad */ | ||
864 | EC_FEATURE_TOUCHPAD = 29, | ||
865 | /* The MCU has RWSIG task enabled */ | ||
866 | EC_FEATURE_RWSIG = 30, | ||
867 | /* EC has device events support */ | ||
868 | EC_FEATURE_DEVICE_EVENT = 31, | ||
869 | /* EC supports the unified wake masks for LPC/eSPI systems */ | ||
870 | EC_FEATURE_UNIFIED_WAKE_MASKS = 32, | ||
871 | /* EC supports 64-bit host events */ | ||
872 | EC_FEATURE_HOST_EVENT64 = 33, | ||
873 | /* EC runs code in RAM (not in place, a.k.a. XIP) */ | ||
874 | EC_FEATURE_EXEC_IN_RAM = 34, | ||
857 | /* EC supports CEC commands */ | 875 | /* EC supports CEC commands */ |
858 | EC_FEATURE_CEC = 35, | 876 | EC_FEATURE_CEC = 35, |
877 | /* EC supports tight sensor timestamping. */ | ||
878 | EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS = 36, | ||
879 | /* | ||
880 | * EC supports tablet mode detection aligned to Chrome and allows | ||
881 | * setting of threshold by host command using | ||
882 | * MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE. | ||
883 | */ | ||
884 | EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS = 37, | ||
885 | /* EC supports audio codec. */ | ||
886 | EC_FEATURE_AUDIO_CODEC = 38, | ||
887 | /* EC Supports SCP. */ | ||
888 | EC_FEATURE_SCP = 39, | ||
889 | /* The MCU is an Integrated Sensor Hub */ | ||
890 | EC_FEATURE_ISH = 40, | ||
859 | }; | 891 | }; |
860 | 892 | ||
861 | #define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32)) | 893 | #define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32)) |
@@ -2729,6 +2761,63 @@ struct ec_params_host_sleep_event { | |||
2729 | uint8_t sleep_event; | 2761 | uint8_t sleep_event; |
2730 | } __packed; | 2762 | } __packed; |
2731 | 2763 | ||
2764 | /* | ||
2765 | * Use a default timeout value (CONFIG_SLEEP_TIMEOUT_MS) for detecting sleep | ||
2766 | * transition failures | ||
2767 | */ | ||
2768 | #define EC_HOST_SLEEP_TIMEOUT_DEFAULT 0 | ||
2769 | |||
2770 | /* Disable timeout detection for this sleep transition */ | ||
2771 | #define EC_HOST_SLEEP_TIMEOUT_INFINITE 0xFFFF | ||
2772 | |||
2773 | struct ec_params_host_sleep_event_v1 { | ||
2774 | /* The type of sleep being entered or exited. */ | ||
2775 | uint8_t sleep_event; | ||
2776 | |||
2777 | /* Padding */ | ||
2778 | uint8_t reserved; | ||
2779 | union { | ||
2780 | /* Parameters that apply for suspend messages. */ | ||
2781 | struct { | ||
2782 | /* | ||
2783 | * The timeout in milliseconds between when this message | ||
2784 | * is received and when the EC will declare sleep | ||
2785 | * transition failure if the sleep signal is not | ||
2786 | * asserted. | ||
2787 | */ | ||
2788 | uint16_t sleep_timeout_ms; | ||
2789 | } suspend_params; | ||
2790 | |||
2791 | /* No parameters for non-suspend messages. */ | ||
2792 | }; | ||
2793 | } __packed; | ||
2794 | |||
2795 | /* A timeout occurred when this bit is set */ | ||
2796 | #define EC_HOST_RESUME_SLEEP_TIMEOUT 0x80000000 | ||
2797 | |||
2798 | /* | ||
2799 | * The mask defining which bits correspond to the number of sleep transitions, | ||
2800 | * as well as the maximum number of suspend line transitions that will be | ||
2801 | * reported back to the host. | ||
2802 | */ | ||
2803 | #define EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK 0x7FFFFFFF | ||
2804 | |||
2805 | struct ec_response_host_sleep_event_v1 { | ||
2806 | union { | ||
2807 | /* Response fields that apply for resume messages. */ | ||
2808 | struct { | ||
2809 | /* | ||
2810 | * The number of sleep power signal transitions that | ||
2811 | * occurred since the suspend message. The high bit | ||
2812 | * indicates a timeout occurred. | ||
2813 | */ | ||
2814 | uint32_t sleep_transitions; | ||
2815 | } resume_response; | ||
2816 | |||
2817 | /* No response fields for non-resume messages. */ | ||
2818 | }; | ||
2819 | } __packed; | ||
2820 | |||
2732 | /*****************************************************************************/ | 2821 | /*****************************************************************************/ |
2733 | /* Smart battery pass-through */ | 2822 | /* Smart battery pass-through */ |
2734 | 2823 | ||
diff --git a/include/linux/mfd/da9063/core.h b/include/linux/mfd/da9063/core.h index 71b09154e2db..5cd06ab26352 100644 --- a/include/linux/mfd/da9063/core.h +++ b/include/linux/mfd/da9063/core.h | |||
@@ -1,3 +1,4 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
1 | /* | 2 | /* |
2 | * Definitions for DA9063 MFD driver | 3 | * Definitions for DA9063 MFD driver |
3 | * | 4 | * |
@@ -5,12 +6,6 @@ | |||
5 | * | 6 | * |
6 | * Author: Michal Hajduk, Dialog Semiconductor | 7 | * Author: Michal Hajduk, Dialog Semiconductor |
7 | * Author: Krystian Garbaciak, Dialog Semiconductor | 8 | * Author: Krystian Garbaciak, Dialog Semiconductor |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | */ | 9 | */ |
15 | 10 | ||
16 | #ifndef __MFD_DA9063_CORE_H__ | 11 | #ifndef __MFD_DA9063_CORE_H__ |
diff --git a/include/linux/mfd/da9063/registers.h b/include/linux/mfd/da9063/registers.h index 5d42859cb441..ba706b0e28c2 100644 --- a/include/linux/mfd/da9063/registers.h +++ b/include/linux/mfd/da9063/registers.h | |||
@@ -1,3 +1,4 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
1 | /* | 2 | /* |
2 | * Registers definition for DA9063 modules | 3 | * Registers definition for DA9063 modules |
3 | * | 4 | * |
@@ -5,12 +6,6 @@ | |||
5 | * | 6 | * |
6 | * Author: Michal Hajduk, Dialog Semiconductor | 7 | * Author: Michal Hajduk, Dialog Semiconductor |
7 | * Author: Krystian Garbaciak, Dialog Semiconductor | 8 | * Author: Krystian Garbaciak, Dialog Semiconductor |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | */ | 9 | */ |
15 | 10 | ||
16 | #ifndef _DA9063_REG_H | 11 | #ifndef _DA9063_REG_H |
@@ -215,9 +210,9 @@ | |||
215 | 210 | ||
216 | /* DA9063 Configuration registers */ | 211 | /* DA9063 Configuration registers */ |
217 | /* OTP */ | 212 | /* OTP */ |
218 | #define DA9063_REG_OPT_COUNT 0x101 | 213 | #define DA9063_REG_OTP_CONT 0x101 |
219 | #define DA9063_REG_OPT_ADDR 0x102 | 214 | #define DA9063_REG_OTP_ADDR 0x102 |
220 | #define DA9063_REG_OPT_DATA 0x103 | 215 | #define DA9063_REG_OTP_DATA 0x103 |
221 | 216 | ||
222 | /* Customer Trim and Configuration */ | 217 | /* Customer Trim and Configuration */ |
223 | #define DA9063_REG_T_OFFSET 0x104 | 218 | #define DA9063_REG_T_OFFSET 0x104 |
diff --git a/include/linux/mfd/max77620.h b/include/linux/mfd/max77620.h index ad2a9a852aea..82407fe85ca2 100644 --- a/include/linux/mfd/max77620.h +++ b/include/linux/mfd/max77620.h | |||
@@ -136,8 +136,8 @@ | |||
136 | #define MAX77620_FPS_PERIOD_MIN_US 40 | 136 | #define MAX77620_FPS_PERIOD_MIN_US 40 |
137 | #define MAX20024_FPS_PERIOD_MIN_US 20 | 137 | #define MAX20024_FPS_PERIOD_MIN_US 20 |
138 | 138 | ||
139 | #define MAX77620_FPS_PERIOD_MAX_US 2560 | 139 | #define MAX20024_FPS_PERIOD_MAX_US 2560 |
140 | #define MAX20024_FPS_PERIOD_MAX_US 5120 | 140 | #define MAX77620_FPS_PERIOD_MAX_US 5120 |
141 | 141 | ||
142 | #define MAX77620_REG_FPS_GPIO1 0x54 | 142 | #define MAX77620_REG_FPS_GPIO1 0x54 |
143 | #define MAX77620_REG_FPS_GPIO2 0x55 | 143 | #define MAX77620_REG_FPS_GPIO2 0x55 |
@@ -324,6 +324,7 @@ enum max77620_fps_src { | |||
324 | enum max77620_chip_id { | 324 | enum max77620_chip_id { |
325 | MAX77620, | 325 | MAX77620, |
326 | MAX20024, | 326 | MAX20024, |
327 | MAX77663, | ||
327 | }; | 328 | }; |
328 | 329 | ||
329 | struct max77620_chip { | 330 | struct max77620_chip { |
diff --git a/include/linux/mfd/max77650.h b/include/linux/mfd/max77650.h new file mode 100644 index 000000000000..c809e211a8cd --- /dev/null +++ b/include/linux/mfd/max77650.h | |||
@@ -0,0 +1,59 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * Copyright (C) 2018 BayLibre SAS | ||
4 | * Author: Bartosz Golaszewski <bgolaszewski@baylibre.com> | ||
5 | * | ||
6 | * Common definitions for MAXIM 77650/77651 charger/power-supply. | ||
7 | */ | ||
8 | |||
9 | #ifndef MAX77650_H | ||
10 | #define MAX77650_H | ||
11 | |||
12 | #include <linux/bits.h> | ||
13 | |||
14 | #define MAX77650_REG_INT_GLBL 0x00 | ||
15 | #define MAX77650_REG_INT_CHG 0x01 | ||
16 | #define MAX77650_REG_STAT_CHG_A 0x02 | ||
17 | #define MAX77650_REG_STAT_CHG_B 0x03 | ||
18 | #define MAX77650_REG_ERCFLAG 0x04 | ||
19 | #define MAX77650_REG_STAT_GLBL 0x05 | ||
20 | #define MAX77650_REG_INTM_GLBL 0x06 | ||
21 | #define MAX77650_REG_INTM_CHG 0x07 | ||
22 | #define MAX77650_REG_CNFG_GLBL 0x10 | ||
23 | #define MAX77650_REG_CID 0x11 | ||
24 | #define MAX77650_REG_CNFG_GPIO 0x12 | ||
25 | #define MAX77650_REG_CNFG_CHG_A 0x18 | ||
26 | #define MAX77650_REG_CNFG_CHG_B 0x19 | ||
27 | #define MAX77650_REG_CNFG_CHG_C 0x1a | ||
28 | #define MAX77650_REG_CNFG_CHG_D 0x1b | ||
29 | #define MAX77650_REG_CNFG_CHG_E 0x1c | ||
30 | #define MAX77650_REG_CNFG_CHG_F 0x1d | ||
31 | #define MAX77650_REG_CNFG_CHG_G 0x1e | ||
32 | #define MAX77650_REG_CNFG_CHG_H 0x1f | ||
33 | #define MAX77650_REG_CNFG_CHG_I 0x20 | ||
34 | #define MAX77650_REG_CNFG_SBB_TOP 0x28 | ||
35 | #define MAX77650_REG_CNFG_SBB0_A 0x29 | ||
36 | #define MAX77650_REG_CNFG_SBB0_B 0x2a | ||
37 | #define MAX77650_REG_CNFG_SBB1_A 0x2b | ||
38 | #define MAX77650_REG_CNFG_SBB1_B 0x2c | ||
39 | #define MAX77650_REG_CNFG_SBB2_A 0x2d | ||
40 | #define MAX77650_REG_CNFG_SBB2_B 0x2e | ||
41 | #define MAX77650_REG_CNFG_LDO_A 0x38 | ||
42 | #define MAX77650_REG_CNFG_LDO_B 0x39 | ||
43 | #define MAX77650_REG_CNFG_LED0_A 0x40 | ||
44 | #define MAX77650_REG_CNFG_LED1_A 0x41 | ||
45 | #define MAX77650_REG_CNFG_LED2_A 0x42 | ||
46 | #define MAX77650_REG_CNFG_LED0_B 0x43 | ||
47 | #define MAX77650_REG_CNFG_LED1_B 0x44 | ||
48 | #define MAX77650_REG_CNFG_LED2_B 0x45 | ||
49 | #define MAX77650_REG_CNFG_LED_TOP 0x46 | ||
50 | |||
51 | #define MAX77650_CID_MASK GENMASK(3, 0) | ||
52 | #define MAX77650_CID_BITS(_reg) (_reg & MAX77650_CID_MASK) | ||
53 | |||
54 | #define MAX77650_CID_77650A 0x03 | ||
55 | #define MAX77650_CID_77650C 0x0a | ||
56 | #define MAX77650_CID_77651A 0x06 | ||
57 | #define MAX77650_CID_77651B 0x08 | ||
58 | |||
59 | #endif /* MAX77650_H */ | ||
diff --git a/include/linux/mfd/stmfx.h b/include/linux/mfd/stmfx.h new file mode 100644 index 000000000000..d890595b89b6 --- /dev/null +++ b/include/linux/mfd/stmfx.h | |||
@@ -0,0 +1,123 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * Copyright (C) 2019 STMicroelectronics | ||
4 | * Author(s): Amelie Delaunay <amelie.delaunay@st.com>. | ||
5 | */ | ||
6 | |||
7 | #ifndef MFD_STMFX_H | ||
8 | #define MFX_STMFX_H | ||
9 | |||
10 | #include <linux/regmap.h> | ||
11 | |||
12 | /* General */ | ||
13 | #define STMFX_REG_CHIP_ID 0x00 /* R */ | ||
14 | #define STMFX_REG_FW_VERSION_MSB 0x01 /* R */ | ||
15 | #define STMFX_REG_FW_VERSION_LSB 0x02 /* R */ | ||
16 | #define STMFX_REG_SYS_CTRL 0x40 /* RW */ | ||
17 | /* IRQ output management */ | ||
18 | #define STMFX_REG_IRQ_OUT_PIN 0x41 /* RW */ | ||
19 | #define STMFX_REG_IRQ_SRC_EN 0x42 /* RW */ | ||
20 | #define STMFX_REG_IRQ_PENDING 0x08 /* R */ | ||
21 | #define STMFX_REG_IRQ_ACK 0x44 /* RW */ | ||
22 | /* GPIO management */ | ||
23 | #define STMFX_REG_IRQ_GPI_PENDING1 0x0C /* R */ | ||
24 | #define STMFX_REG_IRQ_GPI_PENDING2 0x0D /* R */ | ||
25 | #define STMFX_REG_IRQ_GPI_PENDING3 0x0E /* R */ | ||
26 | #define STMFX_REG_GPIO_STATE1 0x10 /* R */ | ||
27 | #define STMFX_REG_GPIO_STATE2 0x11 /* R */ | ||
28 | #define STMFX_REG_GPIO_STATE3 0x12 /* R */ | ||
29 | #define STMFX_REG_IRQ_GPI_SRC1 0x48 /* RW */ | ||
30 | #define STMFX_REG_IRQ_GPI_SRC2 0x49 /* RW */ | ||
31 | #define STMFX_REG_IRQ_GPI_SRC3 0x4A /* RW */ | ||
32 | #define STMFX_REG_IRQ_GPI_EVT1 0x4C /* RW */ | ||
33 | #define STMFX_REG_IRQ_GPI_EVT2 0x4D /* RW */ | ||
34 | #define STMFX_REG_IRQ_GPI_EVT3 0x4E /* RW */ | ||
35 | #define STMFX_REG_IRQ_GPI_TYPE1 0x50 /* RW */ | ||
36 | #define STMFX_REG_IRQ_GPI_TYPE2 0x51 /* RW */ | ||
37 | #define STMFX_REG_IRQ_GPI_TYPE3 0x52 /* RW */ | ||
38 | #define STMFX_REG_IRQ_GPI_ACK1 0x54 /* RW */ | ||
39 | #define STMFX_REG_IRQ_GPI_ACK2 0x55 /* RW */ | ||
40 | #define STMFX_REG_IRQ_GPI_ACK3 0x56 /* RW */ | ||
41 | #define STMFX_REG_GPIO_DIR1 0x60 /* RW */ | ||
42 | #define STMFX_REG_GPIO_DIR2 0x61 /* RW */ | ||
43 | #define STMFX_REG_GPIO_DIR3 0x62 /* RW */ | ||
44 | #define STMFX_REG_GPIO_TYPE1 0x64 /* RW */ | ||
45 | #define STMFX_REG_GPIO_TYPE2 0x65 /* RW */ | ||
46 | #define STMFX_REG_GPIO_TYPE3 0x66 /* RW */ | ||
47 | #define STMFX_REG_GPIO_PUPD1 0x68 /* RW */ | ||
48 | #define STMFX_REG_GPIO_PUPD2 0x69 /* RW */ | ||
49 | #define STMFX_REG_GPIO_PUPD3 0x6A /* RW */ | ||
50 | #define STMFX_REG_GPO_SET1 0x6C /* RW */ | ||
51 | #define STMFX_REG_GPO_SET2 0x6D /* RW */ | ||
52 | #define STMFX_REG_GPO_SET3 0x6E /* RW */ | ||
53 | #define STMFX_REG_GPO_CLR1 0x70 /* RW */ | ||
54 | #define STMFX_REG_GPO_CLR2 0x71 /* RW */ | ||
55 | #define STMFX_REG_GPO_CLR3 0x72 /* RW */ | ||
56 | |||
57 | #define STMFX_REG_MAX 0xB0 | ||
58 | |||
59 | /* MFX boot time is around 10ms, so after reset, we have to wait this delay */ | ||
60 | #define STMFX_BOOT_TIME_MS 10 | ||
61 | |||
62 | /* STMFX_REG_CHIP_ID bitfields */ | ||
63 | #define STMFX_REG_CHIP_ID_MASK GENMASK(7, 0) | ||
64 | |||
65 | /* STMFX_REG_SYS_CTRL bitfields */ | ||
66 | #define STMFX_REG_SYS_CTRL_GPIO_EN BIT(0) | ||
67 | #define STMFX_REG_SYS_CTRL_TS_EN BIT(1) | ||
68 | #define STMFX_REG_SYS_CTRL_IDD_EN BIT(2) | ||
69 | #define STMFX_REG_SYS_CTRL_ALTGPIO_EN BIT(3) | ||
70 | #define STMFX_REG_SYS_CTRL_SWRST BIT(7) | ||
71 | |||
72 | /* STMFX_REG_IRQ_OUT_PIN bitfields */ | ||
73 | #define STMFX_REG_IRQ_OUT_PIN_TYPE BIT(0) /* 0-OD 1-PP */ | ||
74 | #define STMFX_REG_IRQ_OUT_PIN_POL BIT(1) /* 0-active LOW 1-active HIGH */ | ||
75 | |||
76 | /* STMFX_REG_IRQ_(SRC_EN/PENDING/ACK) bit shift */ | ||
77 | enum stmfx_irqs { | ||
78 | STMFX_REG_IRQ_SRC_EN_GPIO = 0, | ||
79 | STMFX_REG_IRQ_SRC_EN_IDD, | ||
80 | STMFX_REG_IRQ_SRC_EN_ERROR, | ||
81 | STMFX_REG_IRQ_SRC_EN_TS_DET, | ||
82 | STMFX_REG_IRQ_SRC_EN_TS_NE, | ||
83 | STMFX_REG_IRQ_SRC_EN_TS_TH, | ||
84 | STMFX_REG_IRQ_SRC_EN_TS_FULL, | ||
85 | STMFX_REG_IRQ_SRC_EN_TS_OVF, | ||
86 | STMFX_REG_IRQ_SRC_MAX, | ||
87 | }; | ||
88 | |||
89 | enum stmfx_functions { | ||
90 | STMFX_FUNC_GPIO = BIT(0), /* GPIO[15:0] */ | ||
91 | STMFX_FUNC_ALTGPIO_LOW = BIT(1), /* aGPIO[3:0] */ | ||
92 | STMFX_FUNC_ALTGPIO_HIGH = BIT(2), /* aGPIO[7:4] */ | ||
93 | STMFX_FUNC_TS = BIT(3), | ||
94 | STMFX_FUNC_IDD = BIT(4), | ||
95 | }; | ||
96 | |||
97 | /** | ||
98 | * struct stmfx_ddata - STMFX MFD structure | ||
99 | * @device: device reference used for logs | ||
100 | * @map: register map | ||
101 | * @vdd: STMFX power supply | ||
102 | * @irq_domain: IRQ domain | ||
103 | * @lock: IRQ bus lock | ||
104 | * @irq_src: cache of IRQ_SRC_EN register for bus_lock | ||
105 | * @bkp_sysctrl: backup of SYS_CTRL register for suspend/resume | ||
106 | * @bkp_irqoutpin: backup of IRQ_OUT_PIN register for suspend/resume | ||
107 | */ | ||
108 | struct stmfx { | ||
109 | struct device *dev; | ||
110 | struct regmap *map; | ||
111 | struct regulator *vdd; | ||
112 | struct irq_domain *irq_domain; | ||
113 | struct mutex lock; /* IRQ bus lock */ | ||
114 | u8 irq_src; | ||
115 | #ifdef CONFIG_PM | ||
116 | u8 bkp_sysctrl; | ||
117 | u8 bkp_irqoutpin; | ||
118 | #endif | ||
119 | }; | ||
120 | |||
121 | int stmfx_function_enable(struct stmfx *stmfx, u32 func); | ||
122 | int stmfx_function_disable(struct stmfx *stmfx, u32 func); | ||
123 | #endif | ||
diff --git a/include/linux/mfd/syscon/atmel-matrix.h b/include/linux/mfd/syscon/atmel-matrix.h index 8293c3e2a82a..f61cd127a852 100644 --- a/include/linux/mfd/syscon/atmel-matrix.h +++ b/include/linux/mfd/syscon/atmel-matrix.h | |||
@@ -1,12 +1,8 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) 2014 Atmel Corporation. | 3 | * Copyright (C) 2014 Atmel Corporation. |
3 | * | 4 | * |
4 | * Memory Controllers (MATRIX, EBI) - System peripherals registers. | 5 | * Memory Controllers (MATRIX, EBI) - System peripherals registers. |
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | 6 | */ |
11 | 7 | ||
12 | #ifndef _LINUX_MFD_SYSCON_ATMEL_MATRIX_H | 8 | #ifndef _LINUX_MFD_SYSCON_ATMEL_MATRIX_H |
diff --git a/include/linux/mfd/syscon/atmel-mc.h b/include/linux/mfd/syscon/atmel-mc.h index afd9b8f1e363..99c56205c410 100644 --- a/include/linux/mfd/syscon/atmel-mc.h +++ b/include/linux/mfd/syscon/atmel-mc.h | |||
@@ -1,3 +1,4 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) 2005 Ivan Kokshaysky | 3 | * Copyright (C) 2005 Ivan Kokshaysky |
3 | * Copyright (C) SAN People | 4 | * Copyright (C) SAN People |
@@ -5,11 +6,6 @@ | |||
5 | * Memory Controllers (MC, EBI, SMC, SDRAMC, BFC) - System peripherals | 6 | * Memory Controllers (MC, EBI, SMC, SDRAMC, BFC) - System peripherals |
6 | * registers. | 7 | * registers. |
7 | * Based on AT91RM9200 datasheet revision E. | 8 | * Based on AT91RM9200 datasheet revision E. |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | */ | 9 | */ |
14 | 10 | ||
15 | #ifndef _LINUX_MFD_SYSCON_ATMEL_MC_H_ | 11 | #ifndef _LINUX_MFD_SYSCON_ATMEL_MC_H_ |
diff --git a/include/linux/mfd/syscon/atmel-smc.h b/include/linux/mfd/syscon/atmel-smc.h index 7a367f34b66a..e9e24f4c4578 100644 --- a/include/linux/mfd/syscon/atmel-smc.h +++ b/include/linux/mfd/syscon/atmel-smc.h | |||
@@ -1,3 +1,4 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Atmel SMC (Static Memory Controller) register offsets and bit definitions. | 3 | * Atmel SMC (Static Memory Controller) register offsets and bit definitions. |
3 | * | 4 | * |
@@ -5,10 +6,6 @@ | |||
5 | * Copyright (C) 2014 Free Electrons | 6 | * Copyright (C) 2014 Free Electrons |
6 | * | 7 | * |
7 | * Author: Boris Brezillon <boris.brezillon@free-electrons.com> | 8 | * Author: Boris Brezillon <boris.brezillon@free-electrons.com> |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | 9 | */ |
13 | 10 | ||
14 | #ifndef _LINUX_MFD_SYSCON_ATMEL_SMC_H_ | 11 | #ifndef _LINUX_MFD_SYSCON_ATMEL_SMC_H_ |
diff --git a/include/linux/mfd/syscon/atmel-st.h b/include/linux/mfd/syscon/atmel-st.h index 8acf1ec1fa32..5b6013d0c440 100644 --- a/include/linux/mfd/syscon/atmel-st.h +++ b/include/linux/mfd/syscon/atmel-st.h | |||
@@ -1,14 +1,10 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) 2005 Ivan Kokshaysky | 3 | * Copyright (C) 2005 Ivan Kokshaysky |
3 | * Copyright (C) SAN People | 4 | * Copyright (C) SAN People |
4 | * | 5 | * |
5 | * System Timer (ST) - System peripherals registers. | 6 | * System Timer (ST) - System peripherals registers. |
6 | * Based on AT91RM9200 datasheet revision E. | 7 | * Based on AT91RM9200 datasheet revision E. |
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | 8 | */ |
13 | 9 | ||
14 | #ifndef _LINUX_MFD_SYSCON_ATMEL_ST_H | 10 | #ifndef _LINUX_MFD_SYSCON_ATMEL_ST_H |
diff --git a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h index c1b25f5e386d..f232c8130d00 100644 --- a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h +++ b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h | |||
@@ -410,6 +410,15 @@ | |||
410 | #define IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK (0x3 << 17) | 410 | #define IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK (0x3 << 17) |
411 | #define IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_EXT (0x3 << 13) | 411 | #define IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_EXT (0x3 << 13) |
412 | 412 | ||
413 | #define IMX6SX_GPR2_MQS_OVERSAMPLE_MASK (0x1 << 26) | ||
414 | #define IMX6SX_GPR2_MQS_OVERSAMPLE_SHIFT (26) | ||
415 | #define IMX6SX_GPR2_MQS_EN_MASK (0x1 << 25) | ||
416 | #define IMX6SX_GPR2_MQS_EN_SHIFT (25) | ||
417 | #define IMX6SX_GPR2_MQS_SW_RST_MASK (0x1 << 24) | ||
418 | #define IMX6SX_GPR2_MQS_SW_RST_SHIFT (24) | ||
419 | #define IMX6SX_GPR2_MQS_CLK_DIV_MASK (0xFF << 16) | ||
420 | #define IMX6SX_GPR2_MQS_CLK_DIV_SHIFT (16) | ||
421 | |||
413 | #define IMX6SX_GPR4_FEC_ENET1_STOP_REQ (0x1 << 3) | 422 | #define IMX6SX_GPR4_FEC_ENET1_STOP_REQ (0x1 << 3) |
414 | #define IMX6SX_GPR4_FEC_ENET2_STOP_REQ (0x1 << 4) | 423 | #define IMX6SX_GPR4_FEC_ENET2_STOP_REQ (0x1 << 4) |
415 | 424 | ||