Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

Pull MFD updates from Lee Jones:
"New Drivers:
- Add support for initialising shared (between children) Regmaps
- Add support for Kontron SL28CPLD
- Add support for ENE KB3930 Embedded Controller
- Add support for Intel FPGA PAC MAX 10 BMC

New Device Support:
- Add support for Power to Ricoh RN5T618
- Add support for UART to Intel Lakefield
- Add support for LP87524_Q1 to Texas Instruments LP87565

New Functionality:
- Device Tree; ene-kb3930, sl28cpld, syscon, lp87565, lp87524-q1
- Use new helper dev_err_probe(); madera-core, stmfx, wcd934x
- Use new GPIOD API; dm355evm_msp
- Add wake-up capability; sprd-sc27xx-spi
- Add ACPI support; kempld-core

Fix-ups:
- Trivial (spelling/whitespace); Kconfig, ab8500
- Fix for unused variables; khadas-mcu, kempld-core
- Remove unused header file(s); mt6360-core
- Use correct IRQ flags in docs; act8945a, gateworks-gsc, rohm,bd70528-pmic
- Add COMPILE_TEST support; asic3, tmio_core
- Add dependency on I2C; SL28CPLD

Bug Fixes:
- Fix memory leak(s); sm501
- Do not free regmap_config's 'name' until exit; syscon"

* tag 'mfd-next-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (34 commits)
mfd: kempld-core: Fix unused variable 'kempld_acpi_table' when !ACPI
mfd: sl28cpld: Depend on I2C
mfd: asic3: Build if COMPILE_TEST=y
dt-bindings: mfd: Correct interrupt flags in examples
mfd: Add ACPI support to Kontron PLD driver
mfd: intel-m10-bmc: Add Intel MAX 10 BMC chip support for Intel FPGA PAC
mfd: lp87565: Add LP87524-Q1 variant
dt-bindings: mfd: Add LP87524-Q1
dt-bindings: mfd: lp87565: Convert to yaml
mfd: mt6360: Remove unused include <linux/version.h>
mfd: sm501: Fix leaks in probe()
mfd: syscon: Don't free allocated name for regmap_config
dt-bindings: mfd: syscon: Document Exynos3 and Exynos5433 compatibles
dt-bindings: mfd: syscon: Merge Samsung Exynos Sysreg bindings
dt-bindings: mfd: ab8500: Remove weird Unicode characters
mfd: sprd: Add wakeup capability for PMIC IRQ
mfd: intel-lpss: Add device IDs for UART ports for Lakefield
mfd: dm355evm_msp: Convert LEDs to GPIO descriptor table
mfd: wcd934x: Simplify with dev_err_probe()
mfd: stmfx: Simplify with dev_err_probe()
...

+2493 -186
+15
Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
··· 1 + What: /sys/bus/spi/devices/.../bmc_version 2 + Date: June 2020 3 + KernelVersion: 5.10 4 + Contact: Xu Yilun <yilun.xu@intel.com> 5 + Description: Read only. Returns the hardware build version of Intel 6 + MAX10 BMC chip. 7 + Format: "0x%x". 8 + 9 + What: /sys/bus/spi/devices/.../bmcfw_version 10 + Date: June 2020 11 + KernelVersion: 5.10 12 + Contact: Xu Yilun <yilun.xu@intel.com> 13 + Description: Read only. Returns the firmware version of Intel MAX10 14 + BMC chip. 15 + Format: "0x%x".
-45
Documentation/devicetree/bindings/arm/samsung/sysreg.yaml
··· 1 - # SPDX-License-Identifier: GPL-2.0 2 - %YAML 1.2 3 - --- 4 - $id: http://devicetree.org/schemas/arm/samsung/sysreg.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: Samsung S5P/Exynos SoC series System Registers (SYSREG) 8 - 9 - maintainers: 10 - - Krzysztof Kozlowski <krzk@kernel.org> 11 - 12 - # Custom select to avoid matching all nodes with 'syscon' 13 - select: 14 - properties: 15 - compatible: 16 - contains: 17 - enum: 18 - - samsung,exynos4-sysreg 19 - - samsung,exynos5-sysreg 20 - required: 21 - - compatible 22 - 23 - properties: 24 - compatible: 25 - allOf: 26 - - items: 27 - - enum: 28 - - samsung,exynos4-sysreg 29 - - samsung,exynos5-sysreg 30 - - const: syscon 31 - 32 - reg: 33 - maxItems: 1 34 - 35 - examples: 36 - - | 37 - syscon@10010000 { 38 - compatible = "samsung,exynos4-sysreg", "syscon"; 39 - reg = <0x10010000 0x400>; 40 - }; 41 - 42 - syscon@10050000 { 43 - compatible = "samsung,exynos5-sysreg", "syscon"; 44 - reg = <0x10050000 0x5000>; 45 - };
+54
Documentation/devicetree/bindings/gpio/kontron,sl28cpld-gpio.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/gpio/kontron,sl28cpld-gpio.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: GPIO driver for the sl28cpld board management controller 8 + 9 + maintainers: 10 + - Michael Walle <michael@walle.cc> 11 + 12 + description: | 13 + This module is part of the sl28cpld multi-function device. For more 14 + details see ../mfd/kontron,sl28cpld.yaml. 15 + 16 + There are three flavors of the GPIO controller, one full featured 17 + input/output with interrupt support (kontron,sl28cpld-gpio), one 18 + output-only (kontron,sl28-gpo) and one input-only (kontron,sl28-gpi). 19 + 20 + Each controller supports 8 GPIO lines. 21 + 22 + properties: 23 + compatible: 24 + enum: 25 + - kontron,sl28cpld-gpio 26 + - kontron,sl28cpld-gpi 27 + - kontron,sl28cpld-gpo 28 + 29 + reg: 30 + maxItems: 1 31 + 32 + interrupts: 33 + maxItems: 1 34 + 35 + "#interrupt-cells": 36 + const: 2 37 + 38 + interrupt-controller: true 39 + 40 + "#gpio-cells": 41 + const: 2 42 + 43 + gpio-controller: true 44 + 45 + gpio-line-names: 46 + minItems: 1 47 + maxItems: 8 48 + 49 + required: 50 + - compatible 51 + - "#gpio-cells" 52 + - gpio-controller 53 + 54 + additionalProperties: false
+27
Documentation/devicetree/bindings/hwmon/kontron,sl28cpld-hwmon.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/hwmon/kontron,sl28cpld-hwmon.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Hardware monitoring driver for the sl28cpld board management controller 8 + 9 + maintainers: 10 + - Michael Walle <michael@walle.cc> 11 + 12 + description: | 13 + This module is part of the sl28cpld multi-function device. For more 14 + details see ../mfd/kontron,sl28cpld.yaml. 15 + 16 + properties: 17 + compatible: 18 + enum: 19 + - kontron,sl28cpld-fan 20 + 21 + reg: 22 + maxItems: 1 23 + 24 + required: 25 + - compatible 26 + 27 + additionalProperties: false
+54
Documentation/devicetree/bindings/interrupt-controller/kontron,sl28cpld-intc.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/interrupt-controller/kontron,sl28cpld-intc.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Interrupt controller driver for the sl28cpld board management controller 8 + 9 + maintainers: 10 + - Michael Walle <michael@walle.cc> 11 + 12 + description: | 13 + This module is part of the sl28cpld multi-function device. For more 14 + details see ../mfd/kontron,sl28cpld.yaml. 15 + 16 + The following interrupts are available. All types and levels are fixed 17 + and handled by the board management controller. 18 + 19 + ==== ============= ================================== 20 + IRQ line/device description 21 + ==== ============= ================================== 22 + 0 RTC_INT# Interrupt line from on-board RTC 23 + 1 SMB_ALERT# Event on SMB_ALERT# line (P1) 24 + 2 ESPI_ALERT0# Event on ESPI_ALERT0# line (S43) 25 + 3 ESPI_ALERT1# Event on ESPI_ALERT1# line (S44) 26 + 4 PWR_BTN# Event on PWR_BTN# line (P128) 27 + 5 SLEEP# Event on SLEEP# line (S149) 28 + 6 watchdog Interrupt of the internal watchdog 29 + 7 n/a not used 30 + ==== ============= ================================== 31 + 32 + properties: 33 + compatible: 34 + enum: 35 + - kontron,sl28cpld-intc 36 + 37 + reg: 38 + maxItems: 1 39 + 40 + interrupts: 41 + maxItems: 1 42 + 43 + "#interrupt-cells": 44 + const: 2 45 + 46 + interrupt-controller: true 47 + 48 + required: 49 + - compatible 50 + - interrupts 51 + - "#interrupt-cells" 52 + - interrupt-controller 53 + 54 + additionalProperties: false
+2 -2
Documentation/devicetree/bindings/mfd/ab8500.txt
··· 31 31 : BAT_CTRL_INDB : : Battery Removal Indicator 32 32 : BTEMP_LOW : : Btemp < BtempLow, if battery temperature is lower than -10°C 33 33 : BTEMP_LOW_MEDIUM : : BtempLow < Btemp < BtempMedium,if battery temperature is between -10 and 0°C 34 - : BTEMP_MEDIUM_HIGH : : BtempMedium < Btemp < BtempHigh,if battery temperature is between 0°C and“MaxTemp 35 - : BTEMP_HIGH : : Btemp > BtempHigh, if battery temperature is higher than “MaxTemp 34 + : BTEMP_MEDIUM_HIGH : : BtempMedium < Btemp < BtempHigh,if battery temperature is between 0°C and MaxTemp 35 + : BTEMP_HIGH : : Btemp > BtempHigh, if battery temperature is higher than MaxTemp 36 36 ab8500-charger : : vddadc : Charger interface 37 37 : MAIN_CH_UNPLUG_DET : : main charger unplug detection management (not in 8505) 38 38 : MAIN_CHARGE_PLUG_DET : : main charger plug detection management (not in 8505)
+1 -1
Documentation/devicetree/bindings/mfd/act8945a.txt
··· 71 71 pinctrl-names = "default"; 72 72 pinctrl-0 = <&pinctrl_charger_chglev &pinctrl_charger_lbo &pinctrl_charger_irq>; 73 73 interrupt-parent = <&pioA>; 74 - interrupts = <45 GPIO_ACTIVE_LOW>; 74 + interrupts = <45 IRQ_TYPE_LEVEL_LOW>; 75 75 76 76 active-semi,chglev-gpios = <&pioA 12 GPIO_ACTIVE_HIGH>; 77 77 active-semi,lbo-gpios = <&pioA 72 GPIO_ACTIVE_LOW>;
+55
Documentation/devicetree/bindings/mfd/ene-kb3930.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/mfd/ene-kb3930.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: ENE KB3930 Embedded Controller bindings 8 + 9 + description: | 10 + This binding describes the ENE KB3930 Embedded Controller attached to an 11 + I2C bus. 12 + 13 + maintainers: 14 + - Lubomir Rintel <lkundrak@v3.sk> 15 + 16 + properties: 17 + compatible: 18 + items: 19 + - enum: 20 + - dell,wyse-ariel-ec # Dell Wyse Ariel board (3020) 21 + - const: ene,kb3930 22 + reg: 23 + maxItems: 1 24 + 25 + off-gpios: 26 + description: GPIO used with the shutdown protocol on Ariel 27 + maxItems: 2 28 + 29 + system-power-controller: true 30 + 31 + required: 32 + - compatible 33 + - reg 34 + 35 + additionalProperties: false 36 + 37 + examples: 38 + - | 39 + #include <dt-bindings/gpio/gpio.h> 40 + 41 + i2c { 42 + #address-cells = <1>; 43 + #size-cells = <0>; 44 + 45 + embedded-controller@58 { 46 + compatible = "dell,wyse-ariel-ec", "ene,kb3930"; 47 + reg = <0x58>; 48 + system-power-controller; 49 + 50 + off-gpios = <&gpio 126 GPIO_ACTIVE_HIGH>, 51 + <&gpio 127 GPIO_ACTIVE_HIGH>; 52 + }; 53 + }; 54 + 55 + ...
+2 -1
Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml
··· 149 149 examples: 150 150 - | 151 151 #include <dt-bindings/gpio/gpio.h> 152 + #include <dt-bindings/interrupt-controller/irq.h> 152 153 i2c { 153 154 #address-cells = <1>; 154 155 #size-cells = <0>; ··· 158 157 compatible = "gw,gsc"; 159 158 reg = <0x20>; 160 159 interrupt-parent = <&gpio1>; 161 - interrupts = <4 GPIO_ACTIVE_LOW>; 160 + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; 162 161 interrupt-controller; 163 162 #interrupt-cells = <1>; 164 163 #address-cells = <1>;
+153
Documentation/devicetree/bindings/mfd/kontron,sl28cpld.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/mfd/kontron,sl28cpld.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Kontron's sl28cpld board management controller 8 + 9 + maintainers: 10 + - Michael Walle <michael@walle.cc> 11 + 12 + description: | 13 + The board management controller may contain different IP blocks like 14 + watchdog, fan monitoring, PWM controller, interrupt controller and a 15 + GPIO controller. 16 + 17 + properties: 18 + compatible: 19 + const: kontron,sl28cpld 20 + 21 + reg: 22 + description: 23 + I2C device address. 24 + maxItems: 1 25 + 26 + "#address-cells": 27 + const: 1 28 + 29 + "#size-cells": 30 + const: 0 31 + 32 + "#interrupt-cells": 33 + const: 2 34 + 35 + interrupts: 36 + maxItems: 1 37 + 38 + interrupt-controller: true 39 + 40 + patternProperties: 41 + "^gpio(@[0-9a-f]+)?$": 42 + $ref: ../gpio/kontron,sl28cpld-gpio.yaml 43 + 44 + "^hwmon(@[0-9a-f]+)?$": 45 + $ref: ../hwmon/kontron,sl28cpld-hwmon.yaml 46 + 47 + "^interrupt-controller(@[0-9a-f]+)?$": 48 + $ref: ../interrupt-controller/kontron,sl28cpld-intc.yaml 49 + 50 + "^pwm(@[0-9a-f]+)?$": 51 + $ref: ../pwm/kontron,sl28cpld-pwm.yaml 52 + 53 + "^watchdog(@[0-9a-f]+)?$": 54 + $ref: ../watchdog/kontron,sl28cpld-wdt.yaml 55 + 56 + required: 57 + - "#address-cells" 58 + - "#size-cells" 59 + - compatible 60 + - reg 61 + 62 + additionalProperties: false 63 + 64 + examples: 65 + - | 66 + #include <dt-bindings/interrupt-controller/irq.h> 67 + i2c { 68 + #address-cells = <1>; 69 + #size-cells = <0>; 70 + 71 + sl28cpld@4a { 72 + compatible = "kontron,sl28cpld"; 73 + reg = <0x4a>; 74 + #address-cells = <1>; 75 + #size-cells = <0>; 76 + 77 + watchdog@4 { 78 + compatible = "kontron,sl28cpld-wdt"; 79 + reg = <0x4>; 80 + kontron,assert-wdt-timeout-pin; 81 + }; 82 + 83 + hwmon@b { 84 + compatible = "kontron,sl28cpld-fan"; 85 + reg = <0xb>; 86 + }; 87 + 88 + pwm@c { 89 + compatible = "kontron,sl28cpld-pwm"; 90 + reg = <0xc>; 91 + #pwm-cells = <2>; 92 + }; 93 + 94 + pwm@e { 95 + compatible = "kontron,sl28cpld-pwm"; 96 + reg = <0xe>; 97 + #pwm-cells = <2>; 98 + }; 99 + 100 + gpio@10 { 101 + compatible = "kontron,sl28cpld-gpio"; 102 + reg = <0x10>; 103 + interrupts-extended = <&gpio2 6 104 + IRQ_TYPE_EDGE_FALLING>; 105 + 106 + gpio-controller; 107 + #gpio-cells = <2>; 108 + gpio-line-names = "a", "b", "c"; 109 + 110 + interrupt-controller; 111 + #interrupt-cells = <2>; 112 + }; 113 + 114 + gpio@15 { 115 + compatible = "kontron,sl28cpld-gpio"; 116 + reg = <0x15>; 117 + interrupts-extended = <&gpio2 6 118 + IRQ_TYPE_EDGE_FALLING>; 119 + 120 + gpio-controller; 121 + #gpio-cells = <2>; 122 + 123 + interrupt-controller; 124 + #interrupt-cells = <2>; 125 + }; 126 + 127 + gpio@1a { 128 + compatible = "kontron,sl28cpld-gpo"; 129 + reg = <0x1a>; 130 + 131 + gpio-controller; 132 + #gpio-cells = <2>; 133 + }; 134 + 135 + gpio@1b { 136 + compatible = "kontron,sl28cpld-gpi"; 137 + reg = <0x1b>; 138 + 139 + gpio-controller; 140 + #gpio-cells = <2>; 141 + }; 142 + 143 + interrupt-controller@1c { 144 + compatible = "kontron,sl28cpld-intc"; 145 + reg = <0x1c>; 146 + interrupts-extended = <&gpio2 6 147 + IRQ_TYPE_EDGE_FALLING>; 148 + 149 + interrupt-controller; 150 + #interrupt-cells = <2>; 151 + }; 152 + }; 153 + };
-79
Documentation/devicetree/bindings/mfd/lp87565.txt
··· 1 - TI LP87565 PMIC MFD driver 2 - 3 - Required properties: 4 - - compatible: "ti,lp87565", "ti,lp87565-q1" 5 - - reg: I2C slave address. 6 - - gpio-controller: Marks the device node as a GPIO Controller. 7 - - #gpio-cells: Should be two. The first cell is the pin number and 8 - the second cell is used to specify flags. 9 - See ../gpio/gpio.txt for more information. 10 - - xxx-in-supply: Phandle to parent supply node of each regulator 11 - populated under regulators node. xxx should match 12 - the supply_name populated in driver. 13 - Example: 14 - 15 - lp87565_pmic: pmic@60 { 16 - compatible = "ti,lp87565-q1"; 17 - reg = <0x60>; 18 - gpio-controller; 19 - #gpio-cells = <2>; 20 - 21 - buck10-in-supply = <&vsys_3v3>; 22 - buck23-in-supply = <&vsys_3v3>; 23 - 24 - regulators: regulators { 25 - buck10_reg: buck10 { 26 - /* VDD_MPU */ 27 - regulator-name = "buck10"; 28 - regulator-min-microvolt = <850000>; 29 - regulator-max-microvolt = <1250000>; 30 - regulator-always-on; 31 - regulator-boot-on; 32 - }; 33 - 34 - buck23_reg: buck23 { 35 - /* VDD_GPU */ 36 - regulator-name = "buck23"; 37 - regulator-min-microvolt = <850000>; 38 - regulator-max-microvolt = <1250000>; 39 - regulator-boot-on; 40 - regulator-always-on; 41 - }; 42 - }; 43 - }; 44 - 45 - TI LP87561 PMIC: 46 - 47 - This is a single output 4-phase regulator configuration 48 - 49 - Required properties: 50 - - compatible: "ti,lp87561-q1" 51 - - reg: I2C slave address. 52 - - gpio-controller: Marks the device node as a GPIO Controller. 53 - - #gpio-cells: Should be two. The first cell is the pin number and 54 - the second cell is used to specify flags. 55 - See ../gpio/gpio.txt for more information. 56 - - xxx-in-supply: Phandle to parent supply node of each regulator 57 - populated under regulators node. xxx should match 58 - the supply_name populated in driver. 59 - Example: 60 - 61 - lp87561_pmic: pmic@62 { 62 - compatible = "ti,lp87561-q1"; 63 - reg = <0x62>; 64 - gpio-controller; 65 - #gpio-cells = <2>; 66 - 67 - buck3210-in-supply = <&vsys_3v3>; 68 - 69 - regulators: regulators { 70 - buck3210_reg: buck3210 { 71 - /* VDD_CORE */ 72 - regulator-name = "buck3210"; 73 - regulator-min-microvolt = <800000>; 74 - regulator-max-microvolt = <800000>; 75 - regulator-always-on; 76 - regulator-boot-on; 77 - }; 78 - }; 79 - };
+1 -1
Documentation/devicetree/bindings/mfd/rohm,bd70528-pmic.txt
··· 39 39 compatible = "rohm,bd70528"; 40 40 reg = <0x4b>; 41 41 interrupt-parent = <&gpio1>; 42 - interrupts = <29 GPIO_ACTIVE_LOW>; 42 + interrupts = <29 IRQ_TYPE_LEVEL_LOW>; 43 43 clocks = <&osc 0>; 44 44 #clock-cells = <0>; 45 45 clock-output-names = "bd70528-32k-out";
+4
Documentation/devicetree/bindings/mfd/syscon.yaml
··· 44 44 - hisilicon,peri-subctrl 45 45 - microchip,sparx5-cpu-syscon 46 46 - mstar,msc313-pmsleep 47 + - samsung,exynos3-sysreg 48 + - samsung,exynos4-sysreg 49 + - samsung,exynos5-sysreg 50 + - samsung,exynos5433-sysreg 47 51 48 52 - const: syscon 49 53
+112
Documentation/devicetree/bindings/mfd/ti,lp87524-q1.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/mfd/ti,lp87524-q1.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: TI LP87524-Q1 four 1-phase output buck converter 8 + 9 + maintainers: 10 + - Keerthy <j-keerthy@ti.com> 11 + 12 + properties: 13 + compatible: 14 + const: ti,lp87524-q1 15 + 16 + reg: 17 + description: I2C slave address 18 + const: 0x60 19 + 20 + gpio-controller: true 21 + 22 + '#gpio-cells': 23 + description: 24 + The first cell is the pin number. 25 + The second cell is is used to specify flags. 26 + See ../gpio/gpio.txt for more information. 27 + const: 2 28 + 29 + regulators: 30 + type: object 31 + 32 + patternProperties: 33 + "^buck[0123]$": 34 + type: object 35 + $ref: /schemas/regulator/regulator.yaml# 36 + 37 + required: 38 + - buck0 39 + - buck1 40 + - buck2 41 + - buck3 42 + 43 + additionalProperties: false 44 + 45 + patternProperties: 46 + "^buck[0123]-in-supply$": 47 + description: Voltage regulator supply for each BUCK converter 48 + 49 + required: 50 + - compatible 51 + - reg 52 + - gpio-controller 53 + - '#gpio-cells' 54 + - buck0-in-supply 55 + - buck1-in-supply 56 + - buck2-in-supply 57 + - buck3-in-supply 58 + - regulators 59 + 60 + additionalProperties: false 61 + 62 + examples: 63 + - | 64 + i2c@0 { 65 + reg = <0x0 0x100>; 66 + #address-cells = <1>; 67 + #size-cells = <0>; 68 + 69 + pmic@60 { 70 + compatible = "ti,lp87524-q1"; 71 + reg = <0x60>; 72 + gpio-controller; 73 + #gpio-cells = <2>; 74 + 75 + buck0-in-supply = <&vdd_5v0>; 76 + buck1-in-supply = <&vdd_5v0>; 77 + buck2-in-supply = <&vdd_5v0>; 78 + buck3-in-supply = <&vdd_5v0>; 79 + 80 + regulators { 81 + buck0_reg: buck0 { 82 + regulator-name = "buck0"; 83 + regulator-min-microvolt = <3300000>; 84 + regulator-max-microvolt = <3300000>; 85 + regulator-always-on; 86 + }; 87 + 88 + buck1_reg: buck1 { 89 + regulator-name = "buck1"; 90 + regulator-min-microvolt = <1350000>; 91 + regulator-max-microvolt = <1350000>; 92 + regulator-always-on; 93 + }; 94 + 95 + buck2_reg: buck2 { 96 + regulator-name = "buck2"; 97 + regulator-min-microvolt = <950000>; 98 + regulator-max-microvolt = <950000>; 99 + regulator-always-on; 100 + }; 101 + 102 + buck3_reg: buck3 { 103 + regulator-name = "buck3"; 104 + regulator-min-microvolt = <1800000>; 105 + regulator-max-microvolt = <1800000>; 106 + regulator-always-on; 107 + }; 108 + }; 109 + }; 110 + }; 111 + 112 + ...
+83
Documentation/devicetree/bindings/mfd/ti,lp87561-q1.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/mfd/ti,lp87561-q1.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: TI LP87561-Q1 single 4-phase output buck converter 8 + 9 + maintainers: 10 + - Keerthy <j-keerthy@ti.com> 11 + 12 + properties: 13 + compatible: 14 + const: ti,lp87561-q1 15 + 16 + reg: 17 + description: I2C slave address 18 + const: 0x60 19 + 20 + gpio-controller: true 21 + 22 + '#gpio-cells': 23 + description: 24 + The first cell is the pin number. 25 + The second cell is is used to specify flags. 26 + See ../gpio/gpio.txt for more information. 27 + const: 2 28 + 29 + buck3210-in-supply: 30 + description: 31 + Voltage regulator supply for all the four BUCK converters. 32 + 33 + regulators: 34 + type: object 35 + 36 + properties: 37 + buck3210: 38 + type: object 39 + $ref: /schemas/regulator/regulator.yaml# 40 + 41 + required: 42 + - buck3210 43 + 44 + additionalProperties: false 45 + 46 + required: 47 + - compatible 48 + - reg 49 + - gpio-controller 50 + - '#gpio-cells' 51 + - buck3210-in-supply 52 + 53 + additionalProperties: false 54 + 55 + examples: 56 + - | 57 + i2c@0 { 58 + reg = <0x0 0x100>; 59 + #address-cells = <1>; 60 + #size-cells = <0>; 61 + 62 + pmic@60 { 63 + compatible = "ti,lp87561-q1"; 64 + reg = <0x60>; 65 + gpio-controller; 66 + #gpio-cells = <2>; 67 + 68 + buck3210-in-supply = <&vsys_3v3>; 69 + 70 + regulators { 71 + buck3210_reg: buck3210 { 72 + /* VDD_CORE */ 73 + regulator-name = "buck3210"; 74 + regulator-min-microvolt = <800000>; 75 + regulator-max-microvolt = <800000>; 76 + regulator-always-on; 77 + regulator-boot-on; 78 + }; 79 + }; 80 + }; 81 + }; 82 + 83 + ...
+101
Documentation/devicetree/bindings/mfd/ti,lp87565-q1.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/mfd/ti,lp87565-q1.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: TI LP87565-Q1 / LP87565 dual 2-phase output buck converter 8 + 9 + maintainers: 10 + - Keerthy <j-keerthy@ti.com> 11 + 12 + properties: 13 + compatible: 14 + oneOf: 15 + - const: ti,lp87565 16 + - const: ti,lp87565-q1 17 + 18 + reg: 19 + description: I2C slave address 20 + const: 0x60 21 + 22 + gpio-controller: true 23 + 24 + '#gpio-cells': 25 + description: 26 + The first cell is the pin number. 27 + The second cell is is used to specify flags. 28 + See ../gpio/gpio.txt for more information. 29 + const: 2 30 + 31 + buck10-in-supply: 32 + description: 33 + Voltage regulator supply for BUCK0 and BUCK1 converters. 34 + 35 + buck23-in-supply: 36 + description: 37 + Voltage regulator supply for BUCK2 and BUCK3 converters. 38 + 39 + regulators: 40 + type: object 41 + 42 + patternProperties: 43 + "^buck(10|23)$": 44 + type: object 45 + $ref: /schemas/regulator/regulator.yaml# 46 + 47 + required: 48 + - buck10 49 + - buck23 50 + 51 + additionalProperties: false 52 + 53 + required: 54 + - compatible 55 + - reg 56 + - gpio-controller 57 + - '#gpio-cells' 58 + - buck10-in-supply 59 + - buck23-in-supply 60 + 61 + additionalProperties: false 62 + 63 + examples: 64 + - | 65 + i2c@0 { 66 + reg = <0x0 0x100>; 67 + #address-cells = <1>; 68 + #size-cells = <0>; 69 + 70 + pmic@60 { 71 + compatible = "ti,lp87565-q1"; 72 + reg = <0x60>; 73 + gpio-controller; 74 + #gpio-cells = <2>; 75 + 76 + buck10-in-supply = <&vsys_3v3>; 77 + buck23-in-supply = <&vsys_3v3>; 78 + 79 + regulators { 80 + buck10_reg: buck10 { 81 + /* VDD_MPU */ 82 + regulator-name = "buck10"; 83 + regulator-min-microvolt = <850000>; 84 + regulator-max-microvolt = <1250000>; 85 + regulator-always-on; 86 + regulator-boot-on; 87 + }; 88 + 89 + buck23_reg: buck23 { 90 + /* VDD_GPU */ 91 + regulator-name = "buck23"; 92 + regulator-min-microvolt = <850000>; 93 + regulator-max-microvolt = <1250000>; 94 + regulator-boot-on; 95 + regulator-always-on; 96 + }; 97 + }; 98 + }; 99 + }; 100 + 101 + ...
+35
Documentation/devicetree/bindings/pwm/kontron,sl28cpld-pwm.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/pwm/kontron,sl28cpld-pwm.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: PWM driver for the sl28cpld board management controller 8 + 9 + maintainers: 10 + - Michael Walle <michael@walle.cc> 11 + 12 + description: | 13 + This module is part of the sl28cpld multi-function device. For more 14 + details see ../mfd/kontron,sl28cpld.yaml. 15 + 16 + The controller supports one PWM channel and supports only four distinct 17 + frequencies (250Hz, 500Hz, 1kHz, 2kHz). 18 + 19 + allOf: 20 + - $ref: pwm.yaml# 21 + 22 + properties: 23 + compatible: 24 + const: kontron,sl28cpld-pwm 25 + 26 + reg: 27 + maxItems: 1 28 + 29 + "#pwm-cells": 30 + const: 2 31 + 32 + required: 33 + - compatible 34 + 35 + additionalProperties: false
+35
Documentation/devicetree/bindings/watchdog/kontron,sl28cpld-wdt.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/watchdog/kontron,sl28cpld-wdt.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Watchdog driver for the sl28cpld board management controller 8 + 9 + maintainers: 10 + - Michael Walle <michael@walle.cc> 11 + 12 + description: | 13 + This module is part of the sl28cpld multi-function device. For more 14 + details see ../mfd/kontron,sl28cpld.yaml. 15 + 16 + allOf: 17 + - $ref: watchdog.yaml# 18 + 19 + properties: 20 + compatible: 21 + const: kontron,sl28cpld-wdt 22 + 23 + reg: 24 + maxItems: 1 25 + 26 + kontron,assert-wdt-timeout-pin: 27 + description: The SMARC standard defines a WDT_TIME_OUT# pin. If this 28 + property is set, this output will be pulsed when the watchdog bites 29 + and the system resets. 30 + type: boolean 31 + 32 + required: 33 + - compatible 34 + 35 + additionalProperties: false
+1
Documentation/hwmon/index.rst
··· 156 156 sht3x 157 157 shtc1 158 158 sis5595 159 + sl28cpld 159 160 smm665 160 161 smsc47b397 161 162 smsc47m192
+36
Documentation/hwmon/sl28cpld.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0-only 2 + 3 + Kernel driver sl28cpld 4 + ====================== 5 + 6 + Supported chips: 7 + 8 + * Kontron sl28cpld 9 + 10 + Prefix: 'sl28cpld' 11 + 12 + Datasheet: not available 13 + 14 + Authors: Michael Walle <michael@walle.cc> 15 + 16 + Description 17 + ----------- 18 + 19 + The sl28cpld is a board management controller which also exposes a hardware 20 + monitoring controller. At the moment this controller supports a single fan 21 + supervisor. In the future there might be other flavours and additional 22 + hardware monitoring might be supported. 23 + 24 + The fan supervisor has a 7 bit counter register and a counter period of 1 25 + second. If the 7 bit counter overflows, the supervisor will automatically 26 + switch to x8 mode to support a wider input range at the loss of 27 + granularity. 28 + 29 + Sysfs entries 30 + ------------- 31 + 32 + The following attributes are supported. 33 + 34 + ======================= ======================================================== 35 + fan1_input Fan RPM. Assuming 2 pulses per revolution. 36 + ======================= ========================================================
+12
drivers/gpio/Kconfig
··· 1248 1248 This driver provides the support for driving/reading the gpio pins 1249 1249 of RC5T583 device through standard gpio library. 1250 1250 1251 + config GPIO_SL28CPLD 1252 + tristate "Kontron sl28cpld GPIO support" 1253 + depends on MFD_SL28CPLD || COMPILE_TEST 1254 + select GPIO_REGMAP 1255 + select GPIOLIB_IRQCHIP 1256 + select REGMAP_IRQ 1257 + help 1258 + This enables support for the GPIOs found on the Kontron sl28 CPLD. 1259 + 1260 + This driver can also be built as a module. If so, the module will be 1261 + called gpio-sl28cpld. 1262 + 1251 1263 config GPIO_STMPE 1252 1264 bool "STMPE GPIOs" 1253 1265 depends on MFD_STMPE
+1
drivers/gpio/Makefile
··· 131 131 obj-$(CONFIG_GPIO_SCH) += gpio-sch.o 132 132 obj-$(CONFIG_GPIO_SIFIVE) += gpio-sifive.o 133 133 obj-$(CONFIG_GPIO_SIOX) += gpio-siox.o 134 + obj-$(CONFIG_GPIO_SL28CPLD) += gpio-sl28cpld.o 134 135 obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o 135 136 obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o 136 137 obj-$(CONFIG_GPIO_SPRD) += gpio-sprd.o
+161
drivers/gpio/gpio-sl28cpld.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * sl28cpld GPIO driver 4 + * 5 + * Copyright 2020 Michael Walle <michael@walle.cc> 6 + */ 7 + 8 + #include <linux/device.h> 9 + #include <linux/gpio/driver.h> 10 + #include <linux/gpio/regmap.h> 11 + #include <linux/interrupt.h> 12 + #include <linux/kernel.h> 13 + #include <linux/mod_devicetable.h> 14 + #include <linux/module.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/regmap.h> 17 + 18 + /* GPIO flavor */ 19 + #define GPIO_REG_DIR 0x00 20 + #define GPIO_REG_OUT 0x01 21 + #define GPIO_REG_IN 0x02 22 + #define GPIO_REG_IE 0x03 23 + #define GPIO_REG_IP 0x04 24 + 25 + /* input-only flavor */ 26 + #define GPI_REG_IN 0x00 27 + 28 + /* output-only flavor */ 29 + #define GPO_REG_OUT 0x00 30 + 31 + enum sl28cpld_gpio_type { 32 + SL28CPLD_GPIO = 1, 33 + SL28CPLD_GPI, 34 + SL28CPLD_GPO, 35 + }; 36 + 37 + static const struct regmap_irq sl28cpld_gpio_irqs[] = { 38 + REGMAP_IRQ_REG_LINE(0, 8), 39 + REGMAP_IRQ_REG_LINE(1, 8), 40 + REGMAP_IRQ_REG_LINE(2, 8), 41 + REGMAP_IRQ_REG_LINE(3, 8), 42 + REGMAP_IRQ_REG_LINE(4, 8), 43 + REGMAP_IRQ_REG_LINE(5, 8), 44 + REGMAP_IRQ_REG_LINE(6, 8), 45 + REGMAP_IRQ_REG_LINE(7, 8), 46 + }; 47 + 48 + static int sl28cpld_gpio_irq_init(struct platform_device *pdev, 49 + unsigned int base, 50 + struct gpio_regmap_config *config) 51 + { 52 + struct regmap_irq_chip_data *irq_data; 53 + struct regmap_irq_chip *irq_chip; 54 + struct device *dev = &pdev->dev; 55 + int irq, ret; 56 + 57 + if (!device_property_read_bool(dev, "interrupt-controller")) 58 + return 0; 59 + 60 + irq = platform_get_irq(pdev, 0); 61 + if (irq < 0) 62 + return irq; 63 + 64 + irq_chip = devm_kzalloc(dev, sizeof(*irq_chip), GFP_KERNEL); 65 + if (!irq_chip) 66 + return -ENOMEM; 67 + 68 + irq_chip->name = "sl28cpld-gpio-irq", 69 + irq_chip->irqs = sl28cpld_gpio_irqs; 70 + irq_chip->num_irqs = ARRAY_SIZE(sl28cpld_gpio_irqs); 71 + irq_chip->num_regs = 1; 72 + irq_chip->status_base = base + GPIO_REG_IP; 73 + irq_chip->mask_base = base + GPIO_REG_IE; 74 + irq_chip->mask_invert = true, 75 + irq_chip->ack_base = base + GPIO_REG_IP; 76 + 77 + ret = devm_regmap_add_irq_chip_fwnode(dev, dev_fwnode(dev), 78 + config->regmap, irq, 79 + IRQF_SHARED | IRQF_ONESHOT, 80 + 0, irq_chip, &irq_data); 81 + if (ret) 82 + return ret; 83 + 84 + config->irq_domain = regmap_irq_get_domain(irq_data); 85 + 86 + return 0; 87 + } 88 + 89 + static int sl28cpld_gpio_probe(struct platform_device *pdev) 90 + { 91 + struct gpio_regmap_config config = {0}; 92 + enum sl28cpld_gpio_type type; 93 + struct regmap *regmap; 94 + u32 base; 95 + int ret; 96 + 97 + if (!pdev->dev.parent) 98 + return -ENODEV; 99 + 100 + type = (uintptr_t)device_get_match_data(&pdev->dev); 101 + if (!type) 102 + return -ENODEV; 103 + 104 + ret = device_property_read_u32(&pdev->dev, "reg", &base); 105 + if (ret) 106 + return -EINVAL; 107 + 108 + regmap = dev_get_regmap(pdev->dev.parent, NULL); 109 + if (!regmap) 110 + return -ENODEV; 111 + 112 + config.regmap = regmap; 113 + config.parent = &pdev->dev; 114 + config.ngpio = 8; 115 + 116 + switch (type) { 117 + case SL28CPLD_GPIO: 118 + config.reg_dat_base = base + GPIO_REG_IN; 119 + config.reg_set_base = base + GPIO_REG_OUT; 120 + /* reg_dir_out_base might be zero */ 121 + config.reg_dir_out_base = GPIO_REGMAP_ADDR(base + GPIO_REG_DIR); 122 + 123 + /* This type supports interrupts */ 124 + ret = sl28cpld_gpio_irq_init(pdev, base, &config); 125 + if (ret) 126 + return ret; 127 + break; 128 + case SL28CPLD_GPO: 129 + config.reg_set_base = base + GPO_REG_OUT; 130 + break; 131 + case SL28CPLD_GPI: 132 + config.reg_dat_base = base + GPI_REG_IN; 133 + break; 134 + default: 135 + dev_err(&pdev->dev, "unknown type %d\n", type); 136 + return -ENODEV; 137 + } 138 + 139 + return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(&pdev->dev, &config)); 140 + } 141 + 142 + static const struct of_device_id sl28cpld_gpio_of_match[] = { 143 + { .compatible = "kontron,sl28cpld-gpio", .data = (void *)SL28CPLD_GPIO }, 144 + { .compatible = "kontron,sl28cpld-gpi", .data = (void *)SL28CPLD_GPI }, 145 + { .compatible = "kontron,sl28cpld-gpo", .data = (void *)SL28CPLD_GPO }, 146 + {} 147 + }; 148 + MODULE_DEVICE_TABLE(of, sl28cpld_gpio_of_match); 149 + 150 + static struct platform_driver sl28cpld_gpio_driver = { 151 + .probe = sl28cpld_gpio_probe, 152 + .driver = { 153 + .name = "sl28cpld-gpio", 154 + .of_match_table = sl28cpld_gpio_of_match, 155 + }, 156 + }; 157 + module_platform_driver(sl28cpld_gpio_driver); 158 + 159 + MODULE_DESCRIPTION("sl28cpld GPIO Driver"); 160 + MODULE_AUTHOR("Michael Walle <michael@walle.cc>"); 161 + MODULE_LICENSE("GPL");
+10
drivers/hwmon/Kconfig
··· 1489 1489 This driver can also be built as a module. If so, the module 1490 1490 will be called raspberrypi-hwmon. 1491 1491 1492 + config SENSORS_SL28CPLD 1493 + tristate "Kontron sl28cpld hardware monitoring driver" 1494 + depends on MFD_SL28CPLD || COMPILE_TEST 1495 + help 1496 + If you say yes here you get support for the fan supervisor of the 1497 + sl28cpld board management controller. 1498 + 1499 + This driver can also be built as a module. If so, the module 1500 + will be called sl28cpld-hwmon. 1501 + 1492 1502 config SENSORS_SHT15 1493 1503 tristate "Sensiron humidity and temperature sensors. SHT15 and compat." 1494 1504 depends on GPIOLIB || COMPILE_TEST
+1
drivers/hwmon/Makefile
··· 161 161 obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o 162 162 obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o 163 163 obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o 164 + obj-$(CONFIG_SENSORS_SL28CPLD) += sl28cpld-hwmon.o 164 165 obj-$(CONFIG_SENSORS_SHT15) += sht15.o 165 166 obj-$(CONFIG_SENSORS_SHT21) += sht21.o 166 167 obj-$(CONFIG_SENSORS_SHT3x) += sht3x.o
+142
drivers/hwmon/sl28cpld-hwmon.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * sl28cpld hardware monitoring driver 4 + * 5 + * Copyright 2020 Kontron Europe GmbH 6 + */ 7 + 8 + #include <linux/bitfield.h> 9 + #include <linux/hwmon.h> 10 + #include <linux/kernel.h> 11 + #include <linux/mod_devicetable.h> 12 + #include <linux/module.h> 13 + #include <linux/platform_device.h> 14 + #include <linux/property.h> 15 + #include <linux/regmap.h> 16 + 17 + #define FAN_INPUT 0x00 18 + #define FAN_SCALE_X8 BIT(7) 19 + #define FAN_VALUE_MASK GENMASK(6, 0) 20 + 21 + struct sl28cpld_hwmon { 22 + struct regmap *regmap; 23 + u32 offset; 24 + }; 25 + 26 + static umode_t sl28cpld_hwmon_is_visible(const void *data, 27 + enum hwmon_sensor_types type, 28 + u32 attr, int channel) 29 + { 30 + return 0444; 31 + } 32 + 33 + static int sl28cpld_hwmon_read(struct device *dev, 34 + enum hwmon_sensor_types type, u32 attr, 35 + int channel, long *input) 36 + { 37 + struct sl28cpld_hwmon *hwmon = dev_get_drvdata(dev); 38 + unsigned int value; 39 + int ret; 40 + 41 + switch (attr) { 42 + case hwmon_fan_input: 43 + ret = regmap_read(hwmon->regmap, hwmon->offset + FAN_INPUT, 44 + &value); 45 + if (ret) 46 + return ret; 47 + /* 48 + * The register has a 7 bit value and 1 bit which indicates the 49 + * scale. If the MSB is set, then the lower 7 bit has to be 50 + * multiplied by 8, to get the correct reading. 51 + */ 52 + if (value & FAN_SCALE_X8) 53 + value = FIELD_GET(FAN_VALUE_MASK, value) << 3; 54 + 55 + /* 56 + * The counter period is 1000ms and the sysfs specification 57 + * says we should asssume 2 pulses per revolution. 58 + */ 59 + value *= 60 / 2; 60 + 61 + break; 62 + default: 63 + return -EOPNOTSUPP; 64 + } 65 + 66 + *input = value; 67 + return 0; 68 + } 69 + 70 + static const u32 sl28cpld_hwmon_fan_config[] = { 71 + HWMON_F_INPUT, 72 + 0 73 + }; 74 + 75 + static const struct hwmon_channel_info sl28cpld_hwmon_fan = { 76 + .type = hwmon_fan, 77 + .config = sl28cpld_hwmon_fan_config, 78 + }; 79 + 80 + static const struct hwmon_channel_info *sl28cpld_hwmon_info[] = { 81 + &sl28cpld_hwmon_fan, 82 + NULL 83 + }; 84 + 85 + static const struct hwmon_ops sl28cpld_hwmon_ops = { 86 + .is_visible = sl28cpld_hwmon_is_visible, 87 + .read = sl28cpld_hwmon_read, 88 + }; 89 + 90 + static const struct hwmon_chip_info sl28cpld_hwmon_chip_info = { 91 + .ops = &sl28cpld_hwmon_ops, 92 + .info = sl28cpld_hwmon_info, 93 + }; 94 + 95 + static int sl28cpld_hwmon_probe(struct platform_device *pdev) 96 + { 97 + struct sl28cpld_hwmon *hwmon; 98 + struct device *hwmon_dev; 99 + int ret; 100 + 101 + if (!pdev->dev.parent) 102 + return -ENODEV; 103 + 104 + hwmon = devm_kzalloc(&pdev->dev, sizeof(*hwmon), GFP_KERNEL); 105 + if (!hwmon) 106 + return -ENOMEM; 107 + 108 + hwmon->regmap = dev_get_regmap(pdev->dev.parent, NULL); 109 + if (!hwmon->regmap) 110 + return -ENODEV; 111 + 112 + ret = device_property_read_u32(&pdev->dev, "reg", &hwmon->offset); 113 + if (ret) 114 + return -EINVAL; 115 + 116 + hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, 117 + "sl28cpld_hwmon", hwmon, 118 + &sl28cpld_hwmon_chip_info, NULL); 119 + if (IS_ERR(hwmon_dev)) 120 + dev_err(&pdev->dev, "failed to register as hwmon device"); 121 + 122 + return PTR_ERR_OR_ZERO(hwmon_dev); 123 + } 124 + 125 + static const struct of_device_id sl28cpld_hwmon_of_match[] = { 126 + { .compatible = "kontron,sl28cpld-fan" }, 127 + {} 128 + }; 129 + MODULE_DEVICE_TABLE(of, sl28cpld_hwmon_of_match); 130 + 131 + static struct platform_driver sl28cpld_hwmon_driver = { 132 + .probe = sl28cpld_hwmon_probe, 133 + .driver = { 134 + .name = "sl28cpld-fan", 135 + .of_match_table = sl28cpld_hwmon_of_match, 136 + }, 137 + }; 138 + module_platform_driver(sl28cpld_hwmon_driver); 139 + 140 + MODULE_DESCRIPTION("sl28cpld Hardware Monitoring Driver"); 141 + MODULE_AUTHOR("Michael Walle <michael@walle.cc>"); 142 + MODULE_LICENSE("GPL");
+8
drivers/irqchip/Kconfig
··· 246 246 Enable support for the Renesas RZ/A1 Interrupt Controller, to use up 247 247 to 8 external interrupts with configurable sense select. 248 248 249 + config SL28CPLD_INTC 250 + bool "Kontron sl28cpld IRQ controller" 251 + depends on MFD_SL28CPLD=y || COMPILE_TEST 252 + select REGMAP_IRQ 253 + help 254 + Interrupt controller driver for the board management controller 255 + found on the Kontron sl28 CPLD. 256 + 249 257 config ST_IRQCHIP 250 258 bool 251 259 select REGMAP
+1
drivers/irqchip/Makefile
··· 114 114 obj-$(CONFIG_LOONGSON_PCH_PIC) += irq-loongson-pch-pic.o 115 115 obj-$(CONFIG_LOONGSON_PCH_MSI) += irq-loongson-pch-msi.o 116 116 obj-$(CONFIG_MST_IRQ) += irq-mst-intc.o 117 + obj-$(CONFIG_SL28CPLD_INTC) += irq-sl28cpld.o
+96
drivers/irqchip/irq-sl28cpld.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * sl28cpld interrupt controller driver 4 + * 5 + * Copyright 2020 Kontron Europe GmbH 6 + */ 7 + 8 + #include <linux/interrupt.h> 9 + #include <linux/kernel.h> 10 + #include <linux/mod_devicetable.h> 11 + #include <linux/module.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/property.h> 14 + #include <linux/regmap.h> 15 + 16 + #define INTC_IE 0x00 17 + #define INTC_IP 0x01 18 + 19 + static const struct regmap_irq sl28cpld_irqs[] = { 20 + REGMAP_IRQ_REG_LINE(0, 8), 21 + REGMAP_IRQ_REG_LINE(1, 8), 22 + REGMAP_IRQ_REG_LINE(2, 8), 23 + REGMAP_IRQ_REG_LINE(3, 8), 24 + REGMAP_IRQ_REG_LINE(4, 8), 25 + REGMAP_IRQ_REG_LINE(5, 8), 26 + REGMAP_IRQ_REG_LINE(6, 8), 27 + REGMAP_IRQ_REG_LINE(7, 8), 28 + }; 29 + 30 + struct sl28cpld_intc { 31 + struct regmap *regmap; 32 + struct regmap_irq_chip chip; 33 + struct regmap_irq_chip_data *irq_data; 34 + }; 35 + 36 + static int sl28cpld_intc_probe(struct platform_device *pdev) 37 + { 38 + struct device *dev = &pdev->dev; 39 + struct sl28cpld_intc *irqchip; 40 + int irq; 41 + u32 base; 42 + int ret; 43 + 44 + if (!dev->parent) 45 + return -ENODEV; 46 + 47 + irqchip = devm_kzalloc(dev, sizeof(*irqchip), GFP_KERNEL); 48 + if (!irqchip) 49 + return -ENOMEM; 50 + 51 + irqchip->regmap = dev_get_regmap(dev->parent, NULL); 52 + if (!irqchip->regmap) 53 + return -ENODEV; 54 + 55 + irq = platform_get_irq(pdev, 0); 56 + if (irq < 0) 57 + return irq; 58 + 59 + ret = device_property_read_u32(&pdev->dev, "reg", &base); 60 + if (ret) 61 + return -EINVAL; 62 + 63 + irqchip->chip.name = "sl28cpld-intc"; 64 + irqchip->chip.irqs = sl28cpld_irqs; 65 + irqchip->chip.num_irqs = ARRAY_SIZE(sl28cpld_irqs); 66 + irqchip->chip.num_regs = 1; 67 + irqchip->chip.status_base = base + INTC_IP; 68 + irqchip->chip.mask_base = base + INTC_IE; 69 + irqchip->chip.mask_invert = true, 70 + irqchip->chip.ack_base = base + INTC_IP; 71 + 72 + return devm_regmap_add_irq_chip_fwnode(dev, dev_fwnode(dev), 73 + irqchip->regmap, irq, 74 + IRQF_SHARED | IRQF_ONESHOT, 0, 75 + &irqchip->chip, 76 + &irqchip->irq_data); 77 + } 78 + 79 + static const struct of_device_id sl28cpld_intc_of_match[] = { 80 + { .compatible = "kontron,sl28cpld-intc" }, 81 + {} 82 + }; 83 + MODULE_DEVICE_TABLE(of, sl28cpld_intc_of_match); 84 + 85 + static struct platform_driver sl28cpld_intc_driver = { 86 + .probe = sl28cpld_intc_probe, 87 + .driver = { 88 + .name = "sl28cpld-intc", 89 + .of_match_table = sl28cpld_intc_of_match, 90 + } 91 + }; 92 + module_platform_driver(sl28cpld_intc_driver); 93 + 94 + MODULE_DESCRIPTION("sl28cpld Interrupt Controller Driver"); 95 + MODULE_AUTHOR("Michael Walle <michael@walle.cc>"); 96 + MODULE_LICENSE("GPL");
+50 -2
drivers/mfd/Kconfig
··· 290 290 291 291 config MFD_ASIC3 292 292 bool "Compaq ASIC3" 293 - depends on GPIOLIB && ARM 293 + depends on GPIOLIB 294 + depends on ARM || COMPILE_TEST 294 295 select MFD_CORE 295 296 help 296 297 This driver supports the ASIC3 multifunction chip found on many ··· 399 398 etc. must be enabled in order to use the functionality of 400 399 the device. 401 400 401 + config MFD_ENE_KB3930 402 + tristate "ENE KB3930 Embedded Controller support" 403 + depends on I2C 404 + depends on MACH_MMP3_DT || COMPILE_TEST 405 + select MFD_CORE 406 + help 407 + This adds support for the power-off functionality and access to 408 + the registers that control LEDS and USB port power on ENE KB3930 409 + Embedded Controller. To use the LED functionality LEDS_ARIEL must 410 + be enabled. 411 + 402 412 config MFD_EXYNOS_LPASS 403 413 tristate "Samsung Exynos SoC Low Power Audio Subsystem" 404 414 depends on ARCH_EXYNOS || COMPILE_TEST ··· 505 493 Add support for HiSilicon Hi6421 PMIC. Hi6421 includes multi- 506 494 functions, such as regulators, RTC, codec, Coulomb counter, etc. 507 495 This driver includes core APIs _only_. You have to select 508 - individul components like voltage regulators under corresponding 496 + individual components like voltage regulators under corresponding 509 497 menus in order to enable them. 510 498 We communicate with the Hi6421 via memory-mapped I/O. 511 499 ··· 1173 1161 1174 1162 To compile this driver as a module, choose M here: the 1175 1163 module will be called si476x-core. 1164 + 1165 + config MFD_SIMPLE_MFD_I2C 1166 + tristate 1167 + depends on I2C 1168 + select REGMAP_I2C 1169 + help 1170 + This driver creates a single register map with the intention for it 1171 + to be shared by all sub-devices. 1172 + 1173 + Once the register map has been successfully initialised, any 1174 + sub-devices represented by child nodes in Device Tree will be 1175 + subsequently registered. 1176 + 1177 + config MFD_SL28CPLD 1178 + tristate "Kontron sl28cpld Board Management Controller" 1179 + depends on I2C 1180 + select MFD_SIMPLE_MFD_I2C 1181 + help 1182 + Say yes here to enable support for the Kontron sl28cpld board 1183 + management controller. 1184 + 1185 + It can be found on the following boards: 1186 + * SMARC-sAL28 1176 1187 1177 1188 config MFD_SM501 1178 1189 tristate "Silicon Motion SM501" ··· 2152 2117 2153 2118 If you have an SGI Origin, Octane, or a PCI IOC3 card, 2154 2119 then say Y. Otherwise say N. 2120 + 2121 + config MFD_INTEL_M10_BMC 2122 + tristate "Intel MAX 10 Board Management Controller" 2123 + depends on SPI_MASTER 2124 + select REGMAP_SPI_AVMM 2125 + select MFD_CORE 2126 + help 2127 + Support for the Intel MAX 10 board management controller using the 2128 + SPI interface. 2129 + 2130 + This driver provides common support for accessing the device, 2131 + additional drivers must be enabled in order to use the functionality 2132 + of the device. 2155 2133 2156 2134 endmenu 2157 2135 endif
+3
drivers/mfd/Makefile
··· 14 14 obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o 15 15 obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o 16 16 obj-$(CONFIG_MFD_CROS_EC_DEV) += cros_ec_dev.o 17 + obj-$(CONFIG_MFD_ENE_KB3930) += ene-kb3930.o 17 18 obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o 18 19 obj-$(CONFIG_MFD_GATEWORKS_GSC) += gateworks-gsc.o 19 20 ··· 265 264 obj-$(CONFIG_MFD_KHADAS_MCU) += khadas-mcu.o 266 265 267 266 obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o 267 + obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o 268 + obj-$(CONFIG_MFD_INTEL_M10_BMC) += intel-m10-bmc.o
+50 -26
drivers/mfd/dm355evm_msp.c
··· 12 12 #include <linux/module.h> 13 13 #include <linux/err.h> 14 14 #include <linux/gpio.h> 15 + #include <linux/gpio/machine.h> 15 16 #include <linux/leds.h> 16 17 #include <linux/i2c.h> 17 18 #include <linux/mfd/dm355evm_msp.h> ··· 115 114 */ 116 115 MSP_GPIO(2, SDMMC), MSP_GPIO(1, SDMMC), /* mmc0 WP, nCD */ 117 116 MSP_GPIO(4, SDMMC), MSP_GPIO(3, SDMMC), /* mmc1 WP, nCD */ 117 + }; 118 + 119 + static struct gpio_led evm_leds[] = { 120 + { .name = "dm355evm::ds14", 121 + .default_trigger = "heartbeat", }, 122 + { .name = "dm355evm::ds15", 123 + .default_trigger = "mmc0", }, 124 + { .name = "dm355evm::ds16", 125 + /* could also be a CE-ATA drive */ 126 + .default_trigger = "mmc1", }, 127 + { .name = "dm355evm::ds17", 128 + .default_trigger = "nand-disk", }, 129 + { .name = "dm355evm::ds18", }, 130 + { .name = "dm355evm::ds19", }, 131 + { .name = "dm355evm::ds20", }, 132 + { .name = "dm355evm::ds21", }, 133 + }; 134 + 135 + static struct gpio_led_platform_data evm_led_data = { 136 + .num_leds = ARRAY_SIZE(evm_leds), 137 + .leds = evm_leds, 138 + }; 139 + 140 + static struct gpiod_lookup_table evm_leds_gpio_table = { 141 + .dev_id = "leds-gpio", 142 + .table = { 143 + /* 144 + * These GPIOs are on the dm355evm_msp 145 + * GPIO chip at index 0..7 146 + */ 147 + GPIO_LOOKUP_IDX("dm355evm_msp", 0, NULL, 148 + 0, GPIO_ACTIVE_LOW), 149 + GPIO_LOOKUP_IDX("dm355evm_msp", 1, NULL, 150 + 1, GPIO_ACTIVE_LOW), 151 + GPIO_LOOKUP_IDX("dm355evm_msp", 2, NULL, 152 + 2, GPIO_ACTIVE_LOW), 153 + GPIO_LOOKUP_IDX("dm355evm_msp", 3, NULL, 154 + 3, GPIO_ACTIVE_LOW), 155 + GPIO_LOOKUP_IDX("dm355evm_msp", 4, NULL, 156 + 4, GPIO_ACTIVE_LOW), 157 + GPIO_LOOKUP_IDX("dm355evm_msp", 5, NULL, 158 + 5, GPIO_ACTIVE_LOW), 159 + GPIO_LOOKUP_IDX("dm355evm_msp", 6, NULL, 160 + 6, GPIO_ACTIVE_LOW), 161 + GPIO_LOOKUP_IDX("dm355evm_msp", 7, NULL, 162 + 7, GPIO_ACTIVE_LOW), 163 + { }, 164 + }, 118 165 }; 119 166 120 167 #define MSP_GPIO_REG(offset) (msp_gpios[(offset)] >> 3) ··· 309 260 310 261 /* LED output */ 311 262 if (msp_has_leds()) { 312 - #define GPIO_LED(l) .name = l, .active_low = true 313 - static struct gpio_led evm_leds[] = { 314 - { GPIO_LED("dm355evm::ds14"), 315 - .default_trigger = "heartbeat", }, 316 - { GPIO_LED("dm355evm::ds15"), 317 - .default_trigger = "mmc0", }, 318 - { GPIO_LED("dm355evm::ds16"), 319 - /* could also be a CE-ATA drive */ 320 - .default_trigger = "mmc1", }, 321 - { GPIO_LED("dm355evm::ds17"), 322 - .default_trigger = "nand-disk", }, 323 - { GPIO_LED("dm355evm::ds18"), }, 324 - { GPIO_LED("dm355evm::ds19"), }, 325 - { GPIO_LED("dm355evm::ds20"), }, 326 - { GPIO_LED("dm355evm::ds21"), }, 327 - }; 328 - #undef GPIO_LED 329 - 330 - struct gpio_led_platform_data evm_led_data = { 331 - .num_leds = ARRAY_SIZE(evm_leds), 332 - .leds = evm_leds, 333 - }; 334 - 335 - for (i = 0; i < ARRAY_SIZE(evm_leds); i++) 336 - evm_leds[i].gpio = i + dm355evm_msp_gpio.base; 337 - 263 + gpiod_add_lookup_table(&evm_leds_gpio_table); 338 264 /* NOTE: these are the only fully programmable LEDs 339 265 * on the board, since GPIO-61/ds22 (and many signals 340 266 * going to DC7) must be used for AEMIF address lines
+212
drivers/mfd/ene-kb3930.c
··· 1 + // SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0-or-later 2 + /* 3 + * ENE KB3930 Embedded Controller Driver 4 + * 5 + * Copyright (C) 2020 Lubomir Rintel 6 + */ 7 + 8 + #include <linux/delay.h> 9 + #include <linux/gpio/consumer.h> 10 + #include <linux/i2c.h> 11 + #include <linux/mfd/core.h> 12 + #include <linux/module.h> 13 + #include <linux/reboot.h> 14 + #include <linux/regmap.h> 15 + 16 + /* I2C registers that are multiplexing access to the EC RAM. */ 17 + enum { 18 + EC_DATA_IN = 0x00, 19 + EC_RAM_OUT = 0x80, 20 + EC_RAM_IN = 0x81, 21 + }; 22 + 23 + /* EC RAM registers. */ 24 + enum { 25 + EC_MODEL = 0x30, 26 + EC_VERSION_MAJ = 0x31, 27 + EC_VERSION_MIN = 0x32, 28 + }; 29 + 30 + struct kb3930 { 31 + struct i2c_client *client; 32 + struct regmap *ram_regmap; 33 + struct gpio_descs *off_gpios; 34 + }; 35 + 36 + struct kb3930 *kb3930_power_off; 37 + 38 + #define EC_GPIO_WAVE 0 39 + #define EC_GPIO_OFF_MODE 1 40 + 41 + #define EC_OFF_MODE_REBOOT 0 42 + #define EC_OFF_MODE_POWER 1 43 + 44 + static void kb3930_off(struct kb3930 *ddata, int off_mode) 45 + { 46 + gpiod_direction_output(ddata->off_gpios->desc[EC_GPIO_OFF_MODE], 47 + off_mode); 48 + 49 + /* 50 + * This creates a 10 Hz wave on EC_GPIO_WAVE that signals a 51 + * shutdown request to the EC. Once the EC detects it, it will 52 + * proceed to turn the power off or reset the board depending on 53 + * the value of EC_GPIO_OFF_MODE. 54 + */ 55 + while (1) { 56 + mdelay(50); 57 + gpiod_direction_output(ddata->off_gpios->desc[EC_GPIO_WAVE], 0); 58 + mdelay(50); 59 + gpiod_direction_output(ddata->off_gpios->desc[EC_GPIO_WAVE], 1); 60 + } 61 + } 62 + 63 + static int kb3930_restart(struct notifier_block *this, 64 + unsigned long mode, void *cmd) 65 + { 66 + kb3930_off(kb3930_power_off, EC_OFF_MODE_REBOOT); 67 + return NOTIFY_DONE; 68 + } 69 + 70 + static void kb3930_pm_power_off(void) 71 + { 72 + kb3930_off(kb3930_power_off, EC_OFF_MODE_POWER); 73 + } 74 + 75 + static struct notifier_block kb3930_restart_nb = { 76 + .notifier_call = kb3930_restart, 77 + }; 78 + 79 + static const struct mfd_cell ariel_ec_cells[] = { 80 + { .name = "dell-wyse-ariel-led", }, 81 + { .name = "dell-wyse-ariel-power", }, 82 + }; 83 + 84 + static int kb3930_ec_ram_reg_write(void *context, unsigned int reg, 85 + unsigned int val) 86 + { 87 + struct kb3930 *ddata = context; 88 + 89 + return i2c_smbus_write_word_data(ddata->client, EC_RAM_OUT, 90 + (val << 8) | reg); 91 + } 92 + 93 + static int kb3930_ec_ram_reg_read(void *context, unsigned int reg, 94 + unsigned int *val) 95 + { 96 + struct kb3930 *ddata = context; 97 + int ret; 98 + 99 + ret = i2c_smbus_write_word_data(ddata->client, EC_RAM_IN, reg); 100 + if (ret < 0) 101 + return ret; 102 + 103 + ret = i2c_smbus_read_word_data(ddata->client, EC_DATA_IN); 104 + if (ret < 0) 105 + return ret; 106 + 107 + *val = ret >> 8; 108 + return 0; 109 + } 110 + 111 + static const struct regmap_config kb3930_ram_regmap_config = { 112 + .name = "ec_ram", 113 + .reg_bits = 8, 114 + .val_bits = 8, 115 + .reg_stride = 1, 116 + .max_register = 0xff, 117 + .reg_write = kb3930_ec_ram_reg_write, 118 + .reg_read = kb3930_ec_ram_reg_read, 119 + .fast_io = false, 120 + }; 121 + 122 + static int kb3930_probe(struct i2c_client *client) 123 + { 124 + struct device *dev = &client->dev; 125 + struct device_node *np = dev->of_node; 126 + struct kb3930 *ddata; 127 + unsigned int model; 128 + int ret; 129 + 130 + ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); 131 + if (!ddata) 132 + return -ENOMEM; 133 + 134 + kb3930_power_off = ddata; 135 + ddata->client = client; 136 + i2c_set_clientdata(client, ddata); 137 + 138 + ddata->ram_regmap = devm_regmap_init(dev, NULL, ddata, 139 + &kb3930_ram_regmap_config); 140 + if (IS_ERR(ddata->ram_regmap)) 141 + return PTR_ERR(ddata->ram_regmap); 142 + 143 + ret = regmap_read(ddata->ram_regmap, EC_MODEL, &model); 144 + if (ret < 0) 145 + return ret; 146 + 147 + /* Currently we only support the cells present on Dell Ariel model. */ 148 + if (model != 'J') { 149 + dev_err(dev, "unknown board model: %02x\n", model); 150 + return -ENODEV; 151 + } 152 + 153 + ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, 154 + ariel_ec_cells, 155 + ARRAY_SIZE(ariel_ec_cells), 156 + NULL, 0, NULL); 157 + if (ret) 158 + return ret; 159 + 160 + if (of_property_read_bool(np, "system-power-controller")) { 161 + ddata->off_gpios = 162 + devm_gpiod_get_array_optional(dev, "off", GPIOD_IN); 163 + if (IS_ERR(ddata->off_gpios)) 164 + return PTR_ERR(ddata->off_gpios); 165 + if (ddata->off_gpios->ndescs < 2) { 166 + dev_err(dev, "invalid off-gpios property\n"); 167 + return -EINVAL; 168 + } 169 + } 170 + 171 + if (ddata->off_gpios) { 172 + register_restart_handler(&kb3930_restart_nb); 173 + if (!pm_power_off) 174 + pm_power_off = kb3930_pm_power_off; 175 + } 176 + 177 + return 0; 178 + } 179 + 180 + static int kb3930_remove(struct i2c_client *client) 181 + { 182 + struct kb3930 *ddata = i2c_get_clientdata(client); 183 + 184 + if (ddata->off_gpios) { 185 + if (pm_power_off == kb3930_pm_power_off) 186 + pm_power_off = NULL; 187 + unregister_restart_handler(&kb3930_restart_nb); 188 + } 189 + kb3930_power_off = NULL; 190 + 191 + return 0; 192 + } 193 + 194 + static const struct of_device_id kb3930_dt_ids[] = { 195 + { .compatible = "ene,kb3930" }, 196 + { } 197 + }; 198 + MODULE_DEVICE_TABLE(of, kb3930_dt_ids); 199 + 200 + static struct i2c_driver kb3930_driver = { 201 + .probe_new = kb3930_probe, 202 + .remove = kb3930_remove, 203 + .driver = { 204 + .name = "ene-kb3930", 205 + .of_match_table = of_match_ptr(kb3930_dt_ids), 206 + }, 207 + }; 208 + module_i2c_driver(kb3930_driver); 209 + 210 + MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>"); 211 + MODULE_DESCRIPTION("ENE KB3930 Embedded Controller Driver"); 212 + MODULE_LICENSE("Dual BSD/GPL");
+4
drivers/mfd/intel-lpss-pci.c
··· 293 293 { PCI_VDEVICE(INTEL, 0x5ac4), (kernel_ulong_t)&bxt_info }, 294 294 { PCI_VDEVICE(INTEL, 0x5ac6), (kernel_ulong_t)&bxt_info }, 295 295 { PCI_VDEVICE(INTEL, 0x5aee), (kernel_ulong_t)&bxt_uart_info }, 296 + /* LKF */ 297 + { PCI_VDEVICE(INTEL, 0x98a8), (kernel_ulong_t)&bxt_uart_info }, 298 + { PCI_VDEVICE(INTEL, 0x98a9), (kernel_ulong_t)&bxt_uart_info }, 299 + { PCI_VDEVICE(INTEL, 0x98c7), (kernel_ulong_t)&bxt_uart_info }, 296 300 /* SPT-LP */ 297 301 { PCI_VDEVICE(INTEL, 0x9d27), (kernel_ulong_t)&spt_uart_info }, 298 302 { PCI_VDEVICE(INTEL, 0x9d28), (kernel_ulong_t)&spt_uart_info },
+164
drivers/mfd/intel-m10-bmc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Intel MAX 10 Board Management Controller chip 4 + * 5 + * Copyright (C) 2018-2020 Intel Corporation. All rights reserved. 6 + */ 7 + #include <linux/bitfield.h> 8 + #include <linux/init.h> 9 + #include <linux/mfd/core.h> 10 + #include <linux/mfd/intel-m10-bmc.h> 11 + #include <linux/module.h> 12 + #include <linux/mutex.h> 13 + #include <linux/regmap.h> 14 + #include <linux/spi/spi.h> 15 + 16 + enum m10bmc_type { 17 + M10_N3000, 18 + }; 19 + 20 + static struct mfd_cell m10bmc_pacn3000_subdevs[] = { 21 + { .name = "n3000bmc-hwmon" }, 22 + { .name = "n3000bmc-retimer" }, 23 + { .name = "n3000bmc-secure" }, 24 + }; 25 + 26 + static struct regmap_config intel_m10bmc_regmap_config = { 27 + .reg_bits = 32, 28 + .val_bits = 32, 29 + .reg_stride = 4, 30 + .max_register = M10BMC_MEM_END, 31 + }; 32 + 33 + static ssize_t bmc_version_show(struct device *dev, 34 + struct device_attribute *attr, char *buf) 35 + { 36 + struct intel_m10bmc *ddata = dev_get_drvdata(dev); 37 + unsigned int val; 38 + int ret; 39 + 40 + ret = m10bmc_sys_read(ddata, M10BMC_BUILD_VER, &val); 41 + if (ret) 42 + return ret; 43 + 44 + return sprintf(buf, "0x%x\n", val); 45 + } 46 + static DEVICE_ATTR_RO(bmc_version); 47 + 48 + static ssize_t bmcfw_version_show(struct device *dev, 49 + struct device_attribute *attr, char *buf) 50 + { 51 + struct intel_m10bmc *ddata = dev_get_drvdata(dev); 52 + unsigned int val; 53 + int ret; 54 + 55 + ret = m10bmc_sys_read(ddata, NIOS2_FW_VERSION, &val); 56 + if (ret) 57 + return ret; 58 + 59 + return sprintf(buf, "0x%x\n", val); 60 + } 61 + static DEVICE_ATTR_RO(bmcfw_version); 62 + 63 + static struct attribute *m10bmc_attrs[] = { 64 + &dev_attr_bmc_version.attr, 65 + &dev_attr_bmcfw_version.attr, 66 + NULL, 67 + }; 68 + ATTRIBUTE_GROUPS(m10bmc); 69 + 70 + static int check_m10bmc_version(struct intel_m10bmc *ddata) 71 + { 72 + unsigned int v; 73 + int ret; 74 + 75 + /* 76 + * This check is to filter out the very old legacy BMC versions, 77 + * M10BMC_LEGACY_SYS_BASE is the offset to this old block of mmio 78 + * registers. In the old BMC chips, the BMC version info is stored 79 + * in this old version register (M10BMC_LEGACY_SYS_BASE + 80 + * M10BMC_BUILD_VER), so its read out value would have not been 81 + * LEGACY_INVALID (0xffffffff). But in new BMC chips that the 82 + * driver supports, the value of this register should be 83 + * LEGACY_INVALID. 84 + */ 85 + ret = m10bmc_raw_read(ddata, 86 + M10BMC_LEGACY_SYS_BASE + M10BMC_BUILD_VER, &v); 87 + if (ret) 88 + return -ENODEV; 89 + 90 + if (v != M10BMC_VER_LEGACY_INVALID) { 91 + dev_err(ddata->dev, "bad version M10BMC detected\n"); 92 + return -ENODEV; 93 + } 94 + 95 + return 0; 96 + } 97 + 98 + static int intel_m10_bmc_spi_probe(struct spi_device *spi) 99 + { 100 + const struct spi_device_id *id = spi_get_device_id(spi); 101 + struct device *dev = &spi->dev; 102 + struct mfd_cell *cells; 103 + struct intel_m10bmc *ddata; 104 + int ret, n_cell; 105 + 106 + ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); 107 + if (!ddata) 108 + return -ENOMEM; 109 + 110 + ddata->dev = dev; 111 + 112 + ddata->regmap = 113 + devm_regmap_init_spi_avmm(spi, &intel_m10bmc_regmap_config); 114 + if (IS_ERR(ddata->regmap)) { 115 + ret = PTR_ERR(ddata->regmap); 116 + dev_err(dev, "Failed to allocate regmap: %d\n", ret); 117 + return ret; 118 + } 119 + 120 + spi_set_drvdata(spi, ddata); 121 + 122 + ret = check_m10bmc_version(ddata); 123 + if (ret) { 124 + dev_err(dev, "Failed to identify m10bmc hardware\n"); 125 + return ret; 126 + } 127 + 128 + switch (id->driver_data) { 129 + case M10_N3000: 130 + cells = m10bmc_pacn3000_subdevs; 131 + n_cell = ARRAY_SIZE(m10bmc_pacn3000_subdevs); 132 + break; 133 + default: 134 + return -ENODEV; 135 + } 136 + 137 + ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, cells, n_cell, 138 + NULL, 0, NULL); 139 + if (ret) 140 + dev_err(dev, "Failed to register sub-devices: %d\n", ret); 141 + 142 + return ret; 143 + } 144 + 145 + static const struct spi_device_id m10bmc_spi_id[] = { 146 + { "m10-n3000", M10_N3000 }, 147 + { } 148 + }; 149 + MODULE_DEVICE_TABLE(spi, m10bmc_spi_id); 150 + 151 + static struct spi_driver intel_m10bmc_spi_driver = { 152 + .driver = { 153 + .name = "intel-m10-bmc", 154 + .dev_groups = m10bmc_groups, 155 + }, 156 + .probe = intel_m10_bmc_spi_probe, 157 + .id_table = m10bmc_spi_id, 158 + }; 159 + module_spi_driver(intel_m10bmc_spi_driver); 160 + 161 + MODULE_DESCRIPTION("Intel MAX 10 BMC Device Driver"); 162 + MODULE_AUTHOR("Intel Corporation"); 163 + MODULE_LICENSE("GPL v2"); 164 + MODULE_ALIAS("spi:intel-m10-bmc");
+111 -6
drivers/mfd/kempld-core.c
··· 13 13 #include <linux/dmi.h> 14 14 #include <linux/io.h> 15 15 #include <linux/delay.h> 16 + #include <linux/acpi.h> 16 17 17 18 #define MAX_ID_LEN 4 18 19 static char force_device_id[MAX_ID_LEN + 1] = ""; ··· 125 124 }; 126 125 127 126 static struct platform_device *kempld_pdev; 127 + static bool kempld_acpi_mode; 128 128 129 129 static int kempld_create_platform_device(const struct dmi_system_id *id) 130 130 { ··· 428 426 return ret; 429 427 } 430 428 429 + #ifdef CONFIG_ACPI 430 + static int kempld_get_acpi_data(struct platform_device *pdev) 431 + { 432 + struct list_head resource_list; 433 + struct resource *resources; 434 + struct resource_entry *rentry; 435 + struct device *dev = &pdev->dev; 436 + struct acpi_device *acpi_dev = ACPI_COMPANION(dev); 437 + const struct kempld_platform_data *pdata; 438 + int ret; 439 + int count; 440 + 441 + pdata = acpi_device_get_match_data(dev); 442 + ret = platform_device_add_data(pdev, pdata, 443 + sizeof(struct kempld_platform_data)); 444 + if (ret) 445 + return ret; 446 + 447 + INIT_LIST_HEAD(&resource_list); 448 + ret = acpi_dev_get_resources(acpi_dev, &resource_list, NULL, NULL); 449 + if (ret < 0) 450 + goto out; 451 + 452 + count = ret; 453 + 454 + if (count == 0) { 455 + ret = platform_device_add_resources(pdev, pdata->ioresource, 1); 456 + goto out; 457 + } 458 + 459 + resources = devm_kcalloc(&acpi_dev->dev, count, sizeof(*resources), 460 + GFP_KERNEL); 461 + if (!resources) { 462 + ret = -ENOMEM; 463 + goto out; 464 + } 465 + 466 + count = 0; 467 + list_for_each_entry(rentry, &resource_list, node) { 468 + memcpy(&resources[count], rentry->res, 469 + sizeof(*resources)); 470 + count++; 471 + } 472 + ret = platform_device_add_resources(pdev, resources, count); 473 + 474 + out: 475 + acpi_dev_free_resource_list(&resource_list); 476 + 477 + return ret; 478 + } 479 + #else 480 + static int kempld_get_acpi_data(struct platform_device *pdev) 481 + { 482 + return -ENODEV; 483 + } 484 + #endif /* CONFIG_ACPI */ 485 + 431 486 static int kempld_probe(struct platform_device *pdev) 432 487 { 433 - const struct kempld_platform_data *pdata = 434 - dev_get_platdata(&pdev->dev); 488 + const struct kempld_platform_data *pdata; 435 489 struct device *dev = &pdev->dev; 436 490 struct kempld_device_data *pld; 437 491 struct resource *ioport; 492 + int ret; 493 + 494 + if (kempld_pdev == NULL) { 495 + /* 496 + * No kempld_pdev device has been registered in kempld_init, 497 + * so we seem to be probing an ACPI platform device. 498 + */ 499 + ret = kempld_get_acpi_data(pdev); 500 + if (ret) 501 + return ret; 502 + 503 + kempld_acpi_mode = true; 504 + } else if (kempld_pdev != pdev) { 505 + /* 506 + * The platform device we are probing is not the one we 507 + * registered in kempld_init using the DMI table, so this one 508 + * comes from ACPI. 509 + * As we can only probe one - abort here and use the DMI 510 + * based one instead. 511 + */ 512 + dev_notice(dev, "platform device exists - not using ACPI\n"); 513 + return -ENODEV; 514 + } 515 + pdata = dev_get_platdata(dev); 438 516 439 517 pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL); 440 518 if (!pld) ··· 553 471 return 0; 554 472 } 555 473 474 + #ifdef CONFIG_ACPI 475 + static const struct acpi_device_id kempld_acpi_table[] = { 476 + { "KEM0001", (kernel_ulong_t)&kempld_platform_data_generic }, 477 + {} 478 + }; 479 + MODULE_DEVICE_TABLE(acpi, kempld_acpi_table); 480 + #endif 481 + 556 482 static struct platform_driver kempld_driver = { 557 483 .driver = { 558 484 .name = "kempld", 485 + .acpi_match_table = ACPI_PTR(kempld_acpi_table), 486 + .probe_type = PROBE_FORCE_SYNCHRONOUS, 559 487 }, 560 488 .probe = kempld_probe, 561 489 .remove = kempld_remove, ··· 884 792 static int __init kempld_init(void) 885 793 { 886 794 const struct dmi_system_id *id; 795 + int ret; 887 796 888 797 if (force_device_id[0]) { 889 798 for (id = kempld_dmi_table; ··· 894 801 break; 895 802 if (id->matches[0].slot == DMI_NONE) 896 803 return -ENODEV; 897 - } else { 898 - if (!dmi_check_system(kempld_dmi_table)) 899 - return -ENODEV; 900 804 } 901 805 902 - return platform_driver_register(&kempld_driver); 806 + ret = platform_driver_register(&kempld_driver); 807 + if (ret) 808 + return ret; 809 + 810 + /* 811 + * With synchronous probing the device should already be probed now. 812 + * If no device id is forced and also no ACPI definition for the 813 + * device was found, scan DMI table as fallback. 814 + * 815 + * If drivers_autoprobing is disabled and the device is found here, 816 + * only that device can be bound manually later. 817 + */ 818 + if (!kempld_pdev && !kempld_acpi_mode) 819 + dmi_check_system(kempld_dmi_table); 820 + 821 + return 0; 903 822 } 904 823 905 824 static void __exit kempld_exit(void)
+2
drivers/mfd/khadas-mcu.c
··· 122 122 return 0; 123 123 } 124 124 125 + #ifdef CONFIG_OF 125 126 static const struct of_device_id khadas_mcu_of_match[] = { 126 127 { .compatible = "khadas,mcu", }, 127 128 {}, 128 129 }; 129 130 MODULE_DEVICE_TABLE(of, khadas_mcu_of_match); 131 + #endif 130 132 131 133 static struct i2c_driver khadas_mcu_driver = { 132 134 .driver = {
+4
drivers/mfd/lp87565.c
··· 27 27 static const struct of_device_id of_lp87565_match_table[] = { 28 28 { .compatible = "ti,lp87565", }, 29 29 { 30 + .compatible = "ti,lp87524-q1", 31 + .data = (void *)LP87565_DEVICE_TYPE_LP87524_Q1, 32 + }, 33 + { 30 34 .compatible = "ti,lp87565-q1", 31 35 .data = (void *)LP87565_DEVICE_TYPE_LP87565_Q1, 32 36 },
+3 -8
drivers/mfd/madera-core.c
··· 369 369 static int madera_get_reset_gpio(struct madera *madera) 370 370 { 371 371 struct gpio_desc *reset; 372 - int ret; 373 372 374 373 if (madera->pdata.reset) 375 374 return 0; 376 375 377 376 reset = devm_gpiod_get_optional(madera->dev, "reset", GPIOD_OUT_LOW); 378 - if (IS_ERR(reset)) { 379 - ret = PTR_ERR(reset); 380 - if (ret != -EPROBE_DEFER) 381 - dev_err(madera->dev, "Failed to request /RESET: %d\n", 382 - ret); 383 - return ret; 384 - } 377 + if (IS_ERR(reset)) 378 + return dev_err_probe(madera->dev, PTR_ERR(reset), 379 + "Failed to request /RESET"); 385 380 386 381 /* 387 382 * A hard reset is needed for full reset of the chip. We allow running
-1
drivers/mfd/mt6360-core.c
··· 13 13 #include <linux/module.h> 14 14 #include <linux/of_irq.h> 15 15 #include <linux/of_platform.h> 16 - #include <linux/version.h> 17 16 18 17 #include <linux/mfd/mt6360.h> 19 18
+1
drivers/mfd/rn5t618.c
··· 25 25 26 26 static const struct mfd_cell rc5t619_cells[] = { 27 27 { .name = "rn5t618-adc" }, 28 + { .name = "rn5t618-power" }, 28 29 { .name = "rn5t618-regulator" }, 29 30 { .name = "rc5t619-rtc" }, 30 31 { .name = "rn5t618-wdt" },
+57
drivers/mfd/simple-mfd-i2c.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Simple MFD - I2C 4 + * 5 + * This driver creates a single register map with the intention for it to be 6 + * shared by all sub-devices. Children can use their parent's device structure 7 + * (dev.parent) in order to reference it. 8 + * 9 + * Once the register map has been successfully initialised, any sub-devices 10 + * represented by child nodes in Device Tree will be subsequently registered. 11 + */ 12 + 13 + #include <linux/i2c.h> 14 + #include <linux/kernel.h> 15 + #include <linux/module.h> 16 + #include <linux/of_platform.h> 17 + #include <linux/regmap.h> 18 + 19 + static const struct regmap_config simple_regmap_config = { 20 + .reg_bits = 8, 21 + .val_bits = 8, 22 + }; 23 + 24 + static int simple_mfd_i2c_probe(struct i2c_client *i2c) 25 + { 26 + const struct regmap_config *config; 27 + struct regmap *regmap; 28 + 29 + config = device_get_match_data(&i2c->dev); 30 + if (!config) 31 + config = &simple_regmap_config; 32 + 33 + regmap = devm_regmap_init_i2c(i2c, config); 34 + if (IS_ERR(regmap)) 35 + return PTR_ERR(regmap); 36 + 37 + return devm_of_platform_populate(&i2c->dev); 38 + } 39 + 40 + static const struct of_device_id simple_mfd_i2c_of_match[] = { 41 + { .compatible = "kontron,sl28cpld" }, 42 + {} 43 + }; 44 + MODULE_DEVICE_TABLE(of, simple_mfd_i2c_of_match); 45 + 46 + static struct i2c_driver simple_mfd_i2c_driver = { 47 + .probe_new = simple_mfd_i2c_probe, 48 + .driver = { 49 + .name = "simple-mfd-i2c", 50 + .of_match_table = simple_mfd_i2c_of_match, 51 + }, 52 + }; 53 + module_i2c_driver(simple_mfd_i2c_driver); 54 + 55 + MODULE_AUTHOR("Michael Walle <michael@walle.cc>"); 56 + MODULE_DESCRIPTION("Simple MFD - I2C driver"); 57 + MODULE_LICENSE("GPL v2");
+7 -1
drivers/mfd/sm501.c
··· 1415 1415 goto err_claim; 1416 1416 } 1417 1417 1418 - return sm501_init_dev(sm); 1418 + ret = sm501_init_dev(sm); 1419 + if (ret) 1420 + goto err_unmap; 1419 1421 1422 + return 0; 1423 + 1424 + err_unmap: 1425 + iounmap(sm->regs); 1420 1426 err_claim: 1421 1427 release_mem_region(sm->io_res->start, 0x100); 1422 1428 err_res:
+27 -1
drivers/mfd/sprd-sc27xx-spi.c
··· 189 189 ddata->irqs[i].mask = BIT(i); 190 190 191 191 ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq, 192 - IRQF_ONESHOT | IRQF_NO_SUSPEND, 0, 192 + IRQF_ONESHOT, 0, 193 193 &ddata->irq_chip, &ddata->irq_data); 194 194 if (ret) { 195 195 dev_err(&spi->dev, "Failed to add PMIC irq chip %d\n", ret); ··· 202 202 return ret; 203 203 } 204 204 205 + device_init_wakeup(&spi->dev, true); 205 206 return 0; 206 207 } 208 + 209 + #ifdef CONFIG_PM_SLEEP 210 + static int sprd_pmic_suspend(struct device *dev) 211 + { 212 + struct sprd_pmic *ddata = dev_get_drvdata(dev); 213 + 214 + if (device_may_wakeup(dev)) 215 + enable_irq_wake(ddata->irq); 216 + 217 + return 0; 218 + } 219 + 220 + static int sprd_pmic_resume(struct device *dev) 221 + { 222 + struct sprd_pmic *ddata = dev_get_drvdata(dev); 223 + 224 + if (device_may_wakeup(dev)) 225 + disable_irq_wake(ddata->irq); 226 + 227 + return 0; 228 + } 229 + #endif 230 + 231 + static SIMPLE_DEV_PM_OPS(sprd_pmic_pm_ops, sprd_pmic_suspend, sprd_pmic_resume); 207 232 208 233 static const struct of_device_id sprd_pmic_match[] = { 209 234 { .compatible = "sprd,sc2731", .data = &sc2731_data }, ··· 240 215 .driver = { 241 216 .name = "sc27xx-pmic", 242 217 .of_match_table = sprd_pmic_match, 218 + .pm = &sprd_pmic_pm_ops, 243 219 }, 244 220 .probe = sprd_pmic_probe, 245 221 };
+3 -5
drivers/mfd/stmfx.c
··· 331 331 ret = PTR_ERR_OR_ZERO(stmfx->vdd); 332 332 if (ret == -ENODEV) { 333 333 stmfx->vdd = NULL; 334 - } else if (ret == -EPROBE_DEFER) { 335 - return ret; 336 - } else if (ret) { 337 - dev_err(&client->dev, "Failed to get VDD regulator: %d\n", ret); 338 - return ret; 334 + } else { 335 + return dev_err_probe(&client->dev, ret, 336 + "Failed to get VDD regulator\n"); 339 337 } 340 338 341 339 if (stmfx->vdd) {
+1 -1
drivers/mfd/syscon.c
··· 108 108 syscon_config.max_register = resource_size(&res) - reg_io_width; 109 109 110 110 regmap = regmap_init_mmio(NULL, base, &syscon_config); 111 - kfree(syscon_config.name); 112 111 if (IS_ERR(regmap)) { 113 112 pr_err("regmap init failed\n"); 114 113 ret = PTR_ERR(regmap); ··· 144 145 regmap_exit(regmap); 145 146 err_regmap: 146 147 iounmap(base); 148 + kfree(syscon_config.name); 147 149 err_map: 148 150 kfree(syscon); 149 151 return ERR_PTR(ret);
+3 -6
drivers/mfd/wcd934x.c
··· 219 219 return -ENOMEM; 220 220 221 221 ddata->irq = of_irq_get(np, 0); 222 - if (ddata->irq < 0) { 223 - if (ddata->irq != -EPROBE_DEFER) 224 - dev_err(ddata->dev, "Failed to get IRQ: err = %d\n", 225 - ddata->irq); 226 - return ddata->irq; 227 - } 222 + if (ddata->irq < 0) 223 + return dev_err_probe(ddata->dev, ddata->irq, 224 + "Failed to get IRQ\n"); 228 225 229 226 reset_gpio = of_get_named_gpio(np, "reset-gpios", 0); 230 227 if (reset_gpio < 0) {
+10
drivers/pwm/Kconfig
··· 428 428 To compile this driver as a module, choose M here: the module 429 429 will be called pwm-sifive. 430 430 431 + config PWM_SL28CPLD 432 + tristate "Kontron sl28cpld PWM support" 433 + depends on MFD_SL28CPLD || COMPILE_TEST 434 + help 435 + Generic PWM framework driver for board management controller 436 + found on the Kontron sl28 CPLD. 437 + 438 + To compile this driver as a module, choose M here: the module 439 + will be called pwm-sl28cpld. 440 + 431 441 config PWM_SPEAR 432 442 tristate "STMicroelectronics SPEAr PWM support" 433 443 depends on PLAT_SPEAR || COMPILE_TEST
+1
drivers/pwm/Makefile
··· 40 40 obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o 41 41 obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o 42 42 obj-$(CONFIG_PWM_SIFIVE) += pwm-sifive.o 43 + obj-$(CONFIG_PWM_SL28CPLD) += pwm-sl28cpld.o 43 44 obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o 44 45 obj-$(CONFIG_PWM_SPRD) += pwm-sprd.o 45 46 obj-$(CONFIG_PWM_STI) += pwm-sti.o
+270
drivers/pwm/pwm-sl28cpld.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * sl28cpld PWM driver 4 + * 5 + * Copyright (c) 2020 Michael Walle <michael@walle.cc> 6 + * 7 + * There is no public datasheet available for this PWM core. But it is easy 8 + * enough to be briefly explained. It consists of one 8-bit counter. The PWM 9 + * supports four distinct frequencies by selecting when to reset the counter. 10 + * With the prescaler setting you can select which bit of the counter is used 11 + * to reset it. This implies that the higher the frequency the less remaining 12 + * bits are available for the actual counter. 13 + * 14 + * Let cnt[7:0] be the counter, clocked at 32kHz: 15 + * +-----------+--------+--------------+-----------+---------------+ 16 + * | prescaler | reset | counter bits | frequency | period length | 17 + * +-----------+--------+--------------+-----------+---------------+ 18 + * | 0 | cnt[7] | cnt[6:0] | 250 Hz | 4000000 ns | 19 + * | 1 | cnt[6] | cnt[5:0] | 500 Hz | 2000000 ns | 20 + * | 2 | cnt[5] | cnt[4:0] | 1 kHz | 1000000 ns | 21 + * | 3 | cnt[4] | cnt[3:0] | 2 kHz | 500000 ns | 22 + * +-----------+--------+--------------+-----------+---------------+ 23 + * 24 + * Limitations: 25 + * - The hardware cannot generate a 100% duty cycle if the prescaler is 0. 26 + * - The hardware cannot atomically set the prescaler and the counter value, 27 + * which might lead to glitches and inconsistent states if a write fails. 28 + * - The counter is not reset if you switch the prescaler which leads 29 + * to glitches, too. 30 + * - The duty cycle will switch immediately and not after a complete cycle. 31 + * - Depending on the actual implementation, disabling the PWM might have 32 + * side effects. For example, if the output pin is shared with a GPIO pin 33 + * it will automatically switch back to GPIO mode. 34 + */ 35 + 36 + #include <linux/bitfield.h> 37 + #include <linux/kernel.h> 38 + #include <linux/mod_devicetable.h> 39 + #include <linux/module.h> 40 + #include <linux/platform_device.h> 41 + #include <linux/pwm.h> 42 + #include <linux/regmap.h> 43 + 44 + /* 45 + * PWM timer block registers. 46 + */ 47 + #define SL28CPLD_PWM_CTRL 0x00 48 + #define SL28CPLD_PWM_CTRL_ENABLE BIT(7) 49 + #define SL28CPLD_PWM_CTRL_PRESCALER_MASK GENMASK(1, 0) 50 + #define SL28CPLD_PWM_CYCLE 0x01 51 + #define SL28CPLD_PWM_CYCLE_MAX GENMASK(6, 0) 52 + 53 + #define SL28CPLD_PWM_CLK 32000 /* 32 kHz */ 54 + #define SL28CPLD_PWM_MAX_DUTY_CYCLE(prescaler) (1 << (7 - (prescaler))) 55 + #define SL28CPLD_PWM_PERIOD(prescaler) \ 56 + (NSEC_PER_SEC / SL28CPLD_PWM_CLK * SL28CPLD_PWM_MAX_DUTY_CYCLE(prescaler)) 57 + 58 + /* 59 + * We calculate the duty cycle like this: 60 + * duty_cycle_ns = pwm_cycle_reg * max_period_ns / max_duty_cycle 61 + * 62 + * With 63 + * max_period_ns = 1 << (7 - prescaler) / SL28CPLD_PWM_CLK * NSEC_PER_SEC 64 + * max_duty_cycle = 1 << (7 - prescaler) 65 + * this then simplifies to: 66 + * duty_cycle_ns = pwm_cycle_reg / SL28CPLD_PWM_CLK * NSEC_PER_SEC 67 + * = NSEC_PER_SEC / SL28CPLD_PWM_CLK * pwm_cycle_reg 68 + * 69 + * NSEC_PER_SEC is a multiple of SL28CPLD_PWM_CLK, therefore we're not losing 70 + * precision by doing the divison first. 71 + */ 72 + #define SL28CPLD_PWM_TO_DUTY_CYCLE(reg) \ 73 + (NSEC_PER_SEC / SL28CPLD_PWM_CLK * (reg)) 74 + #define SL28CPLD_PWM_FROM_DUTY_CYCLE(duty_cycle) \ 75 + (DIV_ROUND_DOWN_ULL((duty_cycle), NSEC_PER_SEC / SL28CPLD_PWM_CLK)) 76 + 77 + #define sl28cpld_pwm_read(priv, reg, val) \ 78 + regmap_read((priv)->regmap, (priv)->offset + (reg), (val)) 79 + #define sl28cpld_pwm_write(priv, reg, val) \ 80 + regmap_write((priv)->regmap, (priv)->offset + (reg), (val)) 81 + 82 + struct sl28cpld_pwm { 83 + struct pwm_chip pwm_chip; 84 + struct regmap *regmap; 85 + u32 offset; 86 + }; 87 + 88 + static void sl28cpld_pwm_get_state(struct pwm_chip *chip, 89 + struct pwm_device *pwm, 90 + struct pwm_state *state) 91 + { 92 + struct sl28cpld_pwm *priv = dev_get_drvdata(chip->dev); 93 + unsigned int reg; 94 + int prescaler; 95 + 96 + sl28cpld_pwm_read(priv, SL28CPLD_PWM_CTRL, &reg); 97 + 98 + state->enabled = reg & SL28CPLD_PWM_CTRL_ENABLE; 99 + 100 + prescaler = FIELD_GET(SL28CPLD_PWM_CTRL_PRESCALER_MASK, reg); 101 + state->period = SL28CPLD_PWM_PERIOD(prescaler); 102 + 103 + sl28cpld_pwm_read(priv, SL28CPLD_PWM_CYCLE, &reg); 104 + state->duty_cycle = SL28CPLD_PWM_TO_DUTY_CYCLE(reg); 105 + state->polarity = PWM_POLARITY_NORMAL; 106 + 107 + /* 108 + * Sanitize values for the PWM core. Depending on the prescaler it 109 + * might happen that we calculate a duty_cycle greater than the actual 110 + * period. This might happen if someone (e.g. the bootloader) sets an 111 + * invalid combination of values. The behavior of the hardware is 112 + * undefined in this case. But we need to report sane values back to 113 + * the PWM core. 114 + */ 115 + state->duty_cycle = min(state->duty_cycle, state->period); 116 + } 117 + 118 + static int sl28cpld_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 119 + const struct pwm_state *state) 120 + { 121 + struct sl28cpld_pwm *priv = dev_get_drvdata(chip->dev); 122 + unsigned int cycle, prescaler; 123 + bool write_duty_cycle_first; 124 + int ret; 125 + u8 ctrl; 126 + 127 + /* Polarity inversion is not supported */ 128 + if (state->polarity != PWM_POLARITY_NORMAL) 129 + return -EINVAL; 130 + 131 + /* 132 + * Calculate the prescaler. Pick the biggest period that isn't 133 + * bigger than the requested period. 134 + */ 135 + prescaler = DIV_ROUND_UP_ULL(SL28CPLD_PWM_PERIOD(0), state->period); 136 + prescaler = order_base_2(prescaler); 137 + 138 + if (prescaler > field_max(SL28CPLD_PWM_CTRL_PRESCALER_MASK)) 139 + return -ERANGE; 140 + 141 + ctrl = FIELD_PREP(SL28CPLD_PWM_CTRL_PRESCALER_MASK, prescaler); 142 + if (state->enabled) 143 + ctrl |= SL28CPLD_PWM_CTRL_ENABLE; 144 + 145 + cycle = SL28CPLD_PWM_FROM_DUTY_CYCLE(state->duty_cycle); 146 + cycle = min_t(unsigned int, cycle, SL28CPLD_PWM_MAX_DUTY_CYCLE(prescaler)); 147 + 148 + /* 149 + * Work around the hardware limitation. See also above. Trap 100% duty 150 + * cycle if the prescaler is 0. Set prescaler to 1 instead. We don't 151 + * care about the frequency because its "all-one" in either case. 152 + * 153 + * We don't need to check the actual prescaler setting, because only 154 + * if the prescaler is 0 we can have this particular value. 155 + */ 156 + if (cycle == SL28CPLD_PWM_MAX_DUTY_CYCLE(0)) { 157 + ctrl &= ~SL28CPLD_PWM_CTRL_PRESCALER_MASK; 158 + ctrl |= FIELD_PREP(SL28CPLD_PWM_CTRL_PRESCALER_MASK, 1); 159 + cycle = SL28CPLD_PWM_MAX_DUTY_CYCLE(1); 160 + } 161 + 162 + /* 163 + * To avoid glitches when we switch the prescaler, we have to make sure 164 + * we have a valid duty cycle for the new mode. 165 + * 166 + * Take the current prescaler (or the current period length) into 167 + * account to decide whether we have to write the duty cycle or the new 168 + * prescaler first. If the period length is decreasing we have to 169 + * write the duty cycle first. 170 + */ 171 + write_duty_cycle_first = pwm->state.period > state->period; 172 + 173 + if (write_duty_cycle_first) { 174 + ret = sl28cpld_pwm_write(priv, SL28CPLD_PWM_CYCLE, cycle); 175 + if (ret) 176 + return ret; 177 + } 178 + 179 + ret = sl28cpld_pwm_write(priv, SL28CPLD_PWM_CTRL, ctrl); 180 + if (ret) 181 + return ret; 182 + 183 + if (!write_duty_cycle_first) { 184 + ret = sl28cpld_pwm_write(priv, SL28CPLD_PWM_CYCLE, cycle); 185 + if (ret) 186 + return ret; 187 + } 188 + 189 + return 0; 190 + } 191 + 192 + static const struct pwm_ops sl28cpld_pwm_ops = { 193 + .apply = sl28cpld_pwm_apply, 194 + .get_state = sl28cpld_pwm_get_state, 195 + .owner = THIS_MODULE, 196 + }; 197 + 198 + static int sl28cpld_pwm_probe(struct platform_device *pdev) 199 + { 200 + struct sl28cpld_pwm *priv; 201 + struct pwm_chip *chip; 202 + int ret; 203 + 204 + if (!pdev->dev.parent) { 205 + dev_err(&pdev->dev, "no parent device\n"); 206 + return -ENODEV; 207 + } 208 + 209 + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 210 + if (!priv) 211 + return -ENOMEM; 212 + 213 + priv->regmap = dev_get_regmap(pdev->dev.parent, NULL); 214 + if (!priv->regmap) { 215 + dev_err(&pdev->dev, "could not get parent regmap\n"); 216 + return -ENODEV; 217 + } 218 + 219 + ret = device_property_read_u32(&pdev->dev, "reg", &priv->offset); 220 + if (ret) { 221 + dev_err(&pdev->dev, "no 'reg' property found (%pe)\n", 222 + ERR_PTR(ret)); 223 + return -EINVAL; 224 + } 225 + 226 + /* Initialize the pwm_chip structure */ 227 + chip = &priv->pwm_chip; 228 + chip->dev = &pdev->dev; 229 + chip->ops = &sl28cpld_pwm_ops; 230 + chip->base = -1; 231 + chip->npwm = 1; 232 + 233 + ret = pwmchip_add(&priv->pwm_chip); 234 + if (ret) { 235 + dev_err(&pdev->dev, "failed to add PWM chip (%pe)", 236 + ERR_PTR(ret)); 237 + return ret; 238 + } 239 + 240 + platform_set_drvdata(pdev, priv); 241 + 242 + return 0; 243 + } 244 + 245 + static int sl28cpld_pwm_remove(struct platform_device *pdev) 246 + { 247 + struct sl28cpld_pwm *priv = platform_get_drvdata(pdev); 248 + 249 + return pwmchip_remove(&priv->pwm_chip); 250 + } 251 + 252 + static const struct of_device_id sl28cpld_pwm_of_match[] = { 253 + { .compatible = "kontron,sl28cpld-pwm" }, 254 + {} 255 + }; 256 + MODULE_DEVICE_TABLE(of, sl28cpld_pwm_of_match); 257 + 258 + static struct platform_driver sl28cpld_pwm_driver = { 259 + .probe = sl28cpld_pwm_probe, 260 + .remove = sl28cpld_pwm_remove, 261 + .driver = { 262 + .name = "sl28cpld-pwm", 263 + .of_match_table = sl28cpld_pwm_of_match, 264 + }, 265 + }; 266 + module_platform_driver(sl28cpld_pwm_driver); 267 + 268 + MODULE_DESCRIPTION("sl28cpld PWM Driver"); 269 + MODULE_AUTHOR("Michael Walle <michael@walle.cc>"); 270 + MODULE_LICENSE("GPL");
+11
drivers/watchdog/Kconfig
··· 340 340 To compile this driver as a module, choose M here: the 341 341 module will be called mlx-wdt. 342 342 343 + config SL28CPLD_WATCHDOG 344 + tristate "Kontron sl28cpld Watchdog" 345 + depends on MFD_SL28CPLD || COMPILE_TEST 346 + select WATCHDOG_CORE 347 + help 348 + Say Y here to include support for the watchdog timer 349 + on the Kontron sl28 CPLD. 350 + 351 + To compile this driver as a module, choose M here: the 352 + module will be called sl28cpld_wdt. 353 + 343 354 # ALPHA Architecture 344 355 345 356 # ARM Architecture
+1
drivers/watchdog/Makefile
··· 225 225 obj-$(CONFIG_MENZ069_WATCHDOG) += menz69_wdt.o 226 226 obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o 227 227 obj-$(CONFIG_STPMIC1_WATCHDOG) += stpmic1_wdt.o 228 + obj-$(CONFIG_SL28CPLD_WATCHDOG) += sl28cpld_wdt.o
+229
drivers/watchdog/sl28cpld_wdt.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * sl28cpld watchdog driver 4 + * 5 + * Copyright 2020 Kontron Europe GmbH 6 + */ 7 + 8 + #include <linux/kernel.h> 9 + #include <linux/mod_devicetable.h> 10 + #include <linux/module.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/property.h> 13 + #include <linux/regmap.h> 14 + #include <linux/watchdog.h> 15 + 16 + /* 17 + * Watchdog timer block registers. 18 + */ 19 + #define WDT_CTRL 0x00 20 + #define WDT_CTRL_EN BIT(0) 21 + #define WDT_CTRL_LOCK BIT(2) 22 + #define WDT_CTRL_ASSERT_SYS_RESET BIT(6) 23 + #define WDT_CTRL_ASSERT_WDT_TIMEOUT BIT(7) 24 + #define WDT_TIMEOUT 0x01 25 + #define WDT_KICK 0x02 26 + #define WDT_KICK_VALUE 0x6b 27 + #define WDT_COUNT 0x03 28 + 29 + #define WDT_DEFAULT_TIMEOUT 10 30 + 31 + static bool nowayout = WATCHDOG_NOWAYOUT; 32 + module_param(nowayout, bool, 0); 33 + MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 34 + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 35 + 36 + static int timeout; 37 + module_param(timeout, int, 0); 38 + MODULE_PARM_DESC(timeout, "Initial watchdog timeout in seconds"); 39 + 40 + struct sl28cpld_wdt { 41 + struct watchdog_device wdd; 42 + struct regmap *regmap; 43 + u32 offset; 44 + bool assert_wdt_timeout; 45 + }; 46 + 47 + static int sl28cpld_wdt_ping(struct watchdog_device *wdd) 48 + { 49 + struct sl28cpld_wdt *wdt = watchdog_get_drvdata(wdd); 50 + 51 + return regmap_write(wdt->regmap, wdt->offset + WDT_KICK, 52 + WDT_KICK_VALUE); 53 + } 54 + 55 + static int sl28cpld_wdt_start(struct watchdog_device *wdd) 56 + { 57 + struct sl28cpld_wdt *wdt = watchdog_get_drvdata(wdd); 58 + unsigned int val; 59 + 60 + val = WDT_CTRL_EN | WDT_CTRL_ASSERT_SYS_RESET; 61 + if (wdt->assert_wdt_timeout) 62 + val |= WDT_CTRL_ASSERT_WDT_TIMEOUT; 63 + if (nowayout) 64 + val |= WDT_CTRL_LOCK; 65 + 66 + return regmap_update_bits(wdt->regmap, wdt->offset + WDT_CTRL, 67 + val, val); 68 + } 69 + 70 + static int sl28cpld_wdt_stop(struct watchdog_device *wdd) 71 + { 72 + struct sl28cpld_wdt *wdt = watchdog_get_drvdata(wdd); 73 + 74 + return regmap_update_bits(wdt->regmap, wdt->offset + WDT_CTRL, 75 + WDT_CTRL_EN, 0); 76 + } 77 + 78 + static unsigned int sl28cpld_wdt_get_timeleft(struct watchdog_device *wdd) 79 + { 80 + struct sl28cpld_wdt *wdt = watchdog_get_drvdata(wdd); 81 + unsigned int val; 82 + int ret; 83 + 84 + ret = regmap_read(wdt->regmap, wdt->offset + WDT_COUNT, &val); 85 + if (ret) 86 + return 0; 87 + 88 + return val; 89 + } 90 + 91 + static int sl28cpld_wdt_set_timeout(struct watchdog_device *wdd, 92 + unsigned int timeout) 93 + { 94 + struct sl28cpld_wdt *wdt = watchdog_get_drvdata(wdd); 95 + int ret; 96 + 97 + ret = regmap_write(wdt->regmap, wdt->offset + WDT_TIMEOUT, timeout); 98 + if (ret) 99 + return ret; 100 + 101 + wdd->timeout = timeout; 102 + 103 + return 0; 104 + } 105 + 106 + static const struct watchdog_info sl28cpld_wdt_info = { 107 + .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 108 + .identity = "sl28cpld watchdog", 109 + }; 110 + 111 + static struct watchdog_ops sl28cpld_wdt_ops = { 112 + .owner = THIS_MODULE, 113 + .start = sl28cpld_wdt_start, 114 + .stop = sl28cpld_wdt_stop, 115 + .ping = sl28cpld_wdt_ping, 116 + .set_timeout = sl28cpld_wdt_set_timeout, 117 + .get_timeleft = sl28cpld_wdt_get_timeleft, 118 + }; 119 + 120 + static int sl28cpld_wdt_probe(struct platform_device *pdev) 121 + { 122 + struct watchdog_device *wdd; 123 + struct sl28cpld_wdt *wdt; 124 + unsigned int status; 125 + unsigned int val; 126 + int ret; 127 + 128 + if (!pdev->dev.parent) 129 + return -ENODEV; 130 + 131 + wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); 132 + if (!wdt) 133 + return -ENOMEM; 134 + 135 + wdt->regmap = dev_get_regmap(pdev->dev.parent, NULL); 136 + if (!wdt->regmap) 137 + return -ENODEV; 138 + 139 + ret = device_property_read_u32(&pdev->dev, "reg", &wdt->offset); 140 + if (ret) 141 + return -EINVAL; 142 + 143 + wdt->assert_wdt_timeout = device_property_read_bool(&pdev->dev, 144 + "kontron,assert-wdt-timeout-pin"); 145 + 146 + /* initialize struct watchdog_device */ 147 + wdd = &wdt->wdd; 148 + wdd->parent = &pdev->dev; 149 + wdd->info = &sl28cpld_wdt_info; 150 + wdd->ops = &sl28cpld_wdt_ops; 151 + wdd->min_timeout = 1; 152 + wdd->max_timeout = 255; 153 + 154 + watchdog_set_drvdata(wdd, wdt); 155 + watchdog_stop_on_reboot(wdd); 156 + 157 + /* 158 + * Read the status early, in case of an error, we haven't modified the 159 + * hardware. 160 + */ 161 + ret = regmap_read(wdt->regmap, wdt->offset + WDT_CTRL, &status); 162 + if (ret) 163 + return ret; 164 + 165 + /* 166 + * Initial timeout value, may be overwritten by device tree or module 167 + * parmeter in watchdog_init_timeout(). 168 + * 169 + * Reading a zero here means that either the hardware has a default 170 + * value of zero (which is very unlikely and definitely a hardware 171 + * bug) or the bootloader set it to zero. In any case, we handle 172 + * this case gracefully and set out own timeout. 173 + */ 174 + ret = regmap_read(wdt->regmap, wdt->offset + WDT_TIMEOUT, &val); 175 + if (ret) 176 + return ret; 177 + 178 + if (val) 179 + wdd->timeout = val; 180 + else 181 + wdd->timeout = WDT_DEFAULT_TIMEOUT; 182 + 183 + watchdog_init_timeout(wdd, timeout, &pdev->dev); 184 + sl28cpld_wdt_set_timeout(wdd, wdd->timeout); 185 + 186 + /* if the watchdog is locked, we set nowayout */ 187 + if (status & WDT_CTRL_LOCK) 188 + nowayout = true; 189 + watchdog_set_nowayout(wdd, nowayout); 190 + 191 + /* 192 + * If watchdog is already running, keep it enabled, but make 193 + * sure its mode is set correctly. 194 + */ 195 + if (status & WDT_CTRL_EN) { 196 + sl28cpld_wdt_start(wdd); 197 + set_bit(WDOG_HW_RUNNING, &wdd->status); 198 + } 199 + 200 + ret = devm_watchdog_register_device(&pdev->dev, wdd); 201 + if (ret < 0) { 202 + dev_err(&pdev->dev, "failed to register watchdog device\n"); 203 + return ret; 204 + } 205 + 206 + dev_info(&pdev->dev, "initial timeout %d sec%s\n", 207 + wdd->timeout, nowayout ? ", nowayout" : ""); 208 + 209 + return 0; 210 + } 211 + 212 + static const struct of_device_id sl28cpld_wdt_of_match[] = { 213 + { .compatible = "kontron,sl28cpld-wdt" }, 214 + {} 215 + }; 216 + MODULE_DEVICE_TABLE(of, sl28cpld_wdt_of_match); 217 + 218 + static struct platform_driver sl28cpld_wdt_driver = { 219 + .probe = sl28cpld_wdt_probe, 220 + .driver = { 221 + .name = "sl28cpld-wdt", 222 + .of_match_table = sl28cpld_wdt_of_match, 223 + }, 224 + }; 225 + module_platform_driver(sl28cpld_wdt_driver); 226 + 227 + MODULE_DESCRIPTION("sl28cpld Watchdog Driver"); 228 + MODULE_AUTHOR("Michael Walle <michael@walle.cc>"); 229 + MODULE_LICENSE("GPL");
+65
include/linux/mfd/intel-m10-bmc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Intel MAX 10 Board Management Controller chip. 4 + * 5 + * Copyright (C) 2018-2020 Intel Corporation, Inc. 6 + */ 7 + #ifndef __MFD_INTEL_M10_BMC_H 8 + #define __MFD_INTEL_M10_BMC_H 9 + 10 + #include <linux/regmap.h> 11 + 12 + #define M10BMC_LEGACY_SYS_BASE 0x300400 13 + #define M10BMC_SYS_BASE 0x300800 14 + #define M10BMC_MEM_END 0x200000fc 15 + 16 + /* Register offset of system registers */ 17 + #define NIOS2_FW_VERSION 0x0 18 + #define M10BMC_TEST_REG 0x3c 19 + #define M10BMC_BUILD_VER 0x68 20 + #define M10BMC_VER_MAJOR_MSK GENMASK(23, 16) 21 + #define M10BMC_VER_PCB_INFO_MSK GENMASK(31, 24) 22 + #define M10BMC_VER_LEGACY_INVALID 0xffffffff 23 + 24 + /** 25 + * struct intel_m10bmc - Intel MAX 10 BMC parent driver data structure 26 + * @dev: this device 27 + * @regmap: the regmap used to access registers by m10bmc itself 28 + */ 29 + struct intel_m10bmc { 30 + struct device *dev; 31 + struct regmap *regmap; 32 + }; 33 + 34 + /* 35 + * register access helper functions. 36 + * 37 + * m10bmc_raw_read - read m10bmc register per addr 38 + * m10bmc_sys_read - read m10bmc system register per offset 39 + */ 40 + static inline int 41 + m10bmc_raw_read(struct intel_m10bmc *m10bmc, unsigned int addr, 42 + unsigned int *val) 43 + { 44 + int ret; 45 + 46 + ret = regmap_read(m10bmc->regmap, addr, val); 47 + if (ret) 48 + dev_err(m10bmc->dev, "fail to read raw reg %x: %d\n", 49 + addr, ret); 50 + 51 + return ret; 52 + } 53 + 54 + /* 55 + * The base of the system registers could be configured by HW developers, and 56 + * in HW SPEC, the base is not added to the addresses of the system registers. 57 + * 58 + * This macro helps to simplify the accessing of the system registers. And if 59 + * the base is reconfigured in HW, SW developers could simply change the 60 + * M10BMC_SYS_BASE accordingly. 61 + */ 62 + #define m10bmc_sys_read(m10bmc, offset, val) \ 63 + m10bmc_raw_read(m10bmc, M10BMC_SYS_BASE + (offset), val) 64 + 65 + #endif /* __MFD_INTEL_M10_BMC_H */
+1
include/linux/mfd/lp87565.h
··· 14 14 15 15 enum lp87565_device_type { 16 16 LP87565_DEVICE_TYPE_UNKNOWN = 0, 17 + LP87565_DEVICE_TYPE_LP87524_Q1, 17 18 LP87565_DEVICE_TYPE_LP87561_Q1, 18 19 LP87565_DEVICE_TYPE_LP87565_Q1, 19 20 };