You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'mfd-for-linus-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones:
"Core framework:
- Add the MFD bindings doc to MAINTAINERS
New drivers:
- X-Powers AC100 Audio CODEC and RTC
- TI LP873x PMIC
- Rockchip RK808 PMIC
- Samsung Exynos Low Power Audio
New device support:
- Add support for STMPE1600 variant to stmpe
- Add support for PM8018 PMIC to pm8921-core
- Add support for AXP806 PMIC in axp20x
- Add support for AXP209 GPIO in axp20x
New functionality:
- Add support for Reset to all STMPE variants
- Add support for MKBP event support to cros_ec
- Add support for USB to intel_soc_pmic_bxtwc
- Add support for IRQs and Power Button to tps65217
Fix-ups:
- Clean-up defunct author emails (da9063, max14577)
- Kconfig fixups (wm8350-i2c, as37220
- Constify (altera-a10sr, sm501)
- Supply PCI IDs (intel-lpss-pci)
- Improve clocking (qcom_rpm)
- Fix IRQ probing (ucb1x00-core)
- Ensure fault log is cleared (da9052)
- Remove NO_IRQ check (ucb1x00-core)
- Supply I2C properties (intel-lpss-acpi, intel-lpss-pci)
- Non standard declaration (tps65217, max8997-irq)
- Remove unused code (lp873x, db8500-prcmu, ab8500-debugfs,
cros_ec_spi)
- Make non-modular (altera-a10sr, intel_msic, smsc-ece1099,
sun6i-prcm, twl-core)
- OF bindings (ac100, stmpe, qcom-pm8xxx, qcom-rpm, rk808, axp20x,
lp873x, exynos5433-lpass, act8945a, aspeed-scu, twl6040, arizona)
Bugfixes:
- Release OF pointer (qcom_rpm)
- Avoid double shifting in suspend/resume (88pm80x)
- Fix 'defined but not used' error (exynos-lpass)
- Fix 'sleeping whilst attomic' (atmel-hlcdc)"
* tag 'mfd-for-linus-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (69 commits)
mfd: arizona: Handle probe deferral for reset GPIO
mfd: arizona: Remove arizona_of_get_named_gpio helper function
mfd: arizona: Add DT options for max_channels_clocked and PDM speaker config
mfd: twl6040: Register child device for twl6040-pdmclk
mfd: cros_ec_spi: Remove unused variable 'request'
mfd: omap-usb-host: Return value is not 'const int'
mfd: ab8500-debugfs: Remove 'weak' function suspend_test_wake_cause_interrupt_is_mine()
mfd: ab8500-debugfs: Remove ab8500_dump_all_banks_to_mem()
mfd: db8500-prcmu: Remove unused *prcmu_set_ddr_opp() calls
mfd: ab8500-debugfs: Prevent initialised field from being over-written
mfd: max8997-irq: 'inline' should be at the beginning of the declaration
mfd: rk808: Fix RK818_IRQ_DISCHG_ILIM initializer
mfd: tps65217: Fix nonstandard declaration
mfd: lp873x: Remove unused mutex lock from struct lp873x
mfd: atmel-hlcdc: Do not sleep in atomic context
mfd: exynos-lpass: Mark PM functions as __maybe_unused
mfd: intel-lpss: Add default I2C device properties for Apollo Lake
mfd: twl-core: Make it explicitly non-modular
mfd: sun6i-prcm: Make it explicitly non-modular
mfd: smsc-ece1099: Make it explicitly non-modular
...
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
X-Powers AC100 Codec/RTC IC Device Tree bindings
|
||||
|
||||
AC100 is a audio codec and RTC subsystem combo IC. The 2 parts are
|
||||
separated, including power supplies and interrupt lines, but share
|
||||
a common register address space and host interface.
|
||||
|
||||
Required properties:
|
||||
- compatible: "x-powers,ac100"
|
||||
- reg: The I2C slave address or RSB hardware address for the chip
|
||||
- sub-nodes:
|
||||
- codec
|
||||
- compatible: "x-powers,ac100-codec"
|
||||
- interrupt-parent: The parent interrupt controller
|
||||
- interrupts: SoC NMI / GPIO interrupt connected to the
|
||||
IRQ_AUDIO pin
|
||||
- #clock-cells: Shall be 0
|
||||
- clock-output-names: "4M_adda"
|
||||
|
||||
- see clock/clock-bindings.txt for common clock bindings
|
||||
|
||||
- rtc
|
||||
- compatible: "x-powers,ac100-rtc"
|
||||
- interrupt-parent: The parent interrupt controller
|
||||
- interrupts: SoC NMI / GPIO interrupt connected to the
|
||||
IRQ_RTC pin
|
||||
- clocks: A phandle to the codec's "4M_adda" clock
|
||||
- #clock-cells: Shall be 1
|
||||
- clock-output-names: "cko1_rtc", "cko2_rtc", "cko3_rtc"
|
||||
|
||||
- see clock/clock-bindings.txt for common clock bindings
|
||||
|
||||
Example:
|
||||
|
||||
ac100: codec@e89 {
|
||||
compatible = "x-powers,ac100";
|
||||
reg = <0xe89>;
|
||||
|
||||
ac100_codec: codec {
|
||||
compatible = "x-powers,ac100-codec";
|
||||
interrupt-parent = <&r_pio>;
|
||||
interrupts = <0 9 IRQ_TYPE_LEVEL_LOW>; /* PL9 */
|
||||
#clock-cells = <0>;
|
||||
clock-output-names = "4M_adda";
|
||||
};
|
||||
|
||||
ac100_rtc: rtc {
|
||||
compatible = "x-powers,ac100-rtc";
|
||||
interrupt-parent = <&nmi_intc>;
|
||||
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
|
||||
clocks = <&ac100_codec>;
|
||||
#clock-cells = <1>;
|
||||
clock-output-names = "cko1_rtc", "cko2_rtc", "cko3_rtc";
|
||||
};
|
||||
};
|
||||
@@ -14,13 +14,6 @@ Example:
|
||||
reg = <0x5b>;
|
||||
status = "okay";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_charger_chglev>;
|
||||
active-semi,chglev-gpio = <&pioA 12 GPIO_ACTIVE_HIGH>;
|
||||
active-semi,input-voltage-threshold-microvolt = <6600>;
|
||||
active-semi,precondition-timeout = <40>;
|
||||
active-semi,total-timeout = <3>;
|
||||
|
||||
active-semi,vsel-high;
|
||||
|
||||
regulators {
|
||||
@@ -73,4 +66,19 @@ Example:
|
||||
regulator-always-on;
|
||||
};
|
||||
};
|
||||
|
||||
charger {
|
||||
compatible = "active-semi,act8945a-charger";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_charger_chglev &pinctrl_charger_lbo &pinctrl_charger_irq>;
|
||||
interrupt-parent = <&pioA>;
|
||||
interrupts = <45 GPIO_ACTIVE_LOW>;
|
||||
|
||||
active-semi,chglev-gpios = <&pioA 12 GPIO_ACTIVE_HIGH>;
|
||||
active-semi,lbo-gpios = <&pioA 72 GPIO_ACTIVE_LOW>;
|
||||
active-semi,input-voltage-threshold-microvolt = <6600>;
|
||||
active-semi,precondition-timeout = <40>;
|
||||
active-semi,total-timeout = <3>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -85,6 +85,24 @@ Optional properties:
|
||||
present, the number of values should be less than or equal to the
|
||||
number of inputs, unspecified inputs will use the chip default.
|
||||
|
||||
- wlf,max-channels-clocked : The maximum number of channels to be clocked on
|
||||
each AIF, useful for I2S systems with multiple data lines being mastered.
|
||||
Specify one cell for each AIF to be configured, specify zero for AIFs that
|
||||
should be handled normally.
|
||||
If present, number of cells must be less than or equal to the number of
|
||||
AIFs. If less than the number of AIFs, for cells that have not been
|
||||
specified the corresponding AIFs will be treated as default setting.
|
||||
|
||||
- wlf,spk-fmt : PDM speaker data format, must contain 2 cells (OUT5 and OUT6).
|
||||
See the datasheet for values.
|
||||
The second cell is ignored for codecs that do not have OUT6 (wm5102, wm8997,
|
||||
wm8998, wm1814)
|
||||
|
||||
- wlf,spk-mute : PDM speaker mute setting, must contain 2 cells (OUT5 and OUT6).
|
||||
See the datasheet for values.
|
||||
The second cell is ignored for codecs that do not have OUT6 (wm5102, wm8997,
|
||||
wm8998, wm1814)
|
||||
|
||||
- DCVDD-supply, MICVDD-supply : Power supplies, only need to be specified if
|
||||
they are being externally supplied. As covered in
|
||||
Documentation/devicetree/bindings/regulator/regulator.txt
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
The Aspeed System Control Unit manages the global behaviour of the SoC,
|
||||
configuring elements such as clocks, pinmux, and reset.
|
||||
|
||||
Required properties:
|
||||
- compatible: One of:
|
||||
"aspeed,ast2400-scu", "syscon", "simple-mfd"
|
||||
"aspeed,g4-scu", "syscon", "simple-mfd"
|
||||
"aspeed,ast2500-scu", "syscon", "simple-mfd"
|
||||
"aspeed,g5-scu", "syscon", "simple-mfd"
|
||||
|
||||
- reg: contains the offset and length of the SCU memory region
|
||||
|
||||
Example:
|
||||
|
||||
syscon: syscon@1e6e2000 {
|
||||
compatible = "aspeed,ast2400-scu", "syscon", "simple-mfd";
|
||||
reg = <0x1e6e2000 0x1a8>;
|
||||
};
|
||||
@@ -10,7 +10,8 @@ axp809 (X-Powers)
|
||||
|
||||
Required properties:
|
||||
- compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209",
|
||||
"x-powers,axp221", "x-powers,axp223", "x-powers,axp809"
|
||||
"x-powers,axp221", "x-powers,axp223", "x-powers,axp806",
|
||||
"x-powers,axp809"
|
||||
- reg: The I2C slave address or RSB hardware address for the AXP chip
|
||||
- interrupt-parent: The parent interrupt controller
|
||||
- interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
|
||||
@@ -47,7 +48,6 @@ Optional properties for DCDC regulators:
|
||||
probably makes sense for HiFi audio related
|
||||
applications that aren't battery constrained.
|
||||
|
||||
|
||||
AXP202/AXP209 regulators, type, and corresponding input supply names:
|
||||
|
||||
Regulator Type Supply Name Notes
|
||||
@@ -86,6 +86,30 @@ LDO_IO1 : LDO : ips-supply : GPIO 1
|
||||
RTC_LDO : LDO : ips-supply : always on
|
||||
DRIVEVBUS : Enable output : drivevbus-supply : external regulator
|
||||
|
||||
AXP806 regulators, type, and corresponding input supply names:
|
||||
|
||||
Regulator Type Supply Name Notes
|
||||
--------- ---- ----------- -----
|
||||
DCDCA : DC-DC buck : vina-supply : poly-phase capable
|
||||
DCDCB : DC-DC buck : vinb-supply : poly-phase capable
|
||||
DCDCC : DC-DC buck : vinc-supply : poly-phase capable
|
||||
DCDCD : DC-DC buck : vind-supply : poly-phase capable
|
||||
DCDCE : DC-DC buck : vine-supply : poly-phase capable
|
||||
ALDO1 : LDO : aldoin-supply : shared supply
|
||||
ALDO2 : LDO : aldoin-supply : shared supply
|
||||
ALDO3 : LDO : aldoin-supply : shared supply
|
||||
BLDO1 : LDO : bldoin-supply : shared supply
|
||||
BLDO2 : LDO : bldoin-supply : shared supply
|
||||
BLDO3 : LDO : bldoin-supply : shared supply
|
||||
BLDO4 : LDO : bldoin-supply : shared supply
|
||||
CLDO1 : LDO : cldoin-supply : shared supply
|
||||
CLDO2 : LDO : cldoin-supply : shared supply
|
||||
CLDO3 : LDO : cldoin-supply : shared supply
|
||||
SW : On/Off Switch : swin-supply
|
||||
|
||||
Additionally, the AXP806 DC-DC regulators support poly-phase arrangements
|
||||
for higher output current. The possible groupings are: A+B, A+B+C, D+E.
|
||||
|
||||
AXP809 regulators, type, and corresponding input supply names:
|
||||
|
||||
Regulator Type Supply Name Notes
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
TI LP873X PMIC MFD driver
|
||||
|
||||
Required properties:
|
||||
- compatible: "ti,lp8732", "ti,lp8733"
|
||||
- reg: I2C slave address.
|
||||
- gpio-controller: Marks the device node as a GPIO Controller.
|
||||
- #gpio-cells: Should be two. The first cell is the pin number and
|
||||
the second cell is used to specify flags.
|
||||
See ../gpio/gpio.txt for more information.
|
||||
- regulators: List of child nodes that specify the regulator
|
||||
initialization data.
|
||||
Example:
|
||||
|
||||
pmic: lp8733@60 {
|
||||
compatible = "ti,lp8733";
|
||||
reg = <0x60>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
regulators {
|
||||
lp8733_buck0: buck0 {
|
||||
regulator-name = "lp8733-buck0";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <1400000>;
|
||||
regulator-min-microamp = <1500000>;
|
||||
regulator-max-microamp = <4000000>;
|
||||
regulator-ramp-delay = <10000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
lp8733_buck1: buck1 {
|
||||
regulator-name = "lp8733-buck1";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <1400000>;
|
||||
regulator-min-microamp = <1500000>;
|
||||
regulator-max-microamp = <4000000>;
|
||||
regulator-ramp-delay = <10000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
lp8733_ldo0: ldo0 {
|
||||
regulator-name = "lp8733-ldo0";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <3000000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
lp8733_ldo1: ldo1 {
|
||||
regulator-name = "lp8733-ldo1";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <3000000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -62,6 +62,7 @@ The below bindings specify the set of valid subnodes.
|
||||
"qcom,pm8058-rtc"
|
||||
"qcom,pm8921-rtc"
|
||||
"qcom,pm8941-rtc"
|
||||
"qcom,pm8018-rtc"
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
|
||||
@@ -13,6 +13,7 @@ frequencies.
|
||||
"qcom,rpm-msm8660"
|
||||
"qcom,rpm-msm8960"
|
||||
"qcom,rpm-ipq8064"
|
||||
"qcom,rpm-mdm9615"
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
@@ -59,6 +60,7 @@ Regulator nodes are identified by their compatible:
|
||||
"qcom,rpm-pm8058-regulators"
|
||||
"qcom,rpm-pm8901-regulators"
|
||||
"qcom,rpm-pm8921-regulators"
|
||||
"qcom,rpm-pm8018-regulators"
|
||||
|
||||
- vdd_l0_l1_lvs-supply:
|
||||
- vdd_l2_l11_l12-supply:
|
||||
@@ -137,6 +139,15 @@ Regulator nodes are identified by their compatible:
|
||||
Definition: reference to regulator supplying the input pin, as
|
||||
described in the data sheet
|
||||
|
||||
- vin_lvs1-supply:
|
||||
- vdd_l7-supply:
|
||||
- vdd_l8-supply:
|
||||
- vdd_l9_l10_l11_l12-supply:
|
||||
Usage: optional (pm8018 only)
|
||||
Value type: <phandle>
|
||||
Definition: reference to regulator supplying the input pin, as
|
||||
described in the data sheet
|
||||
|
||||
The regulator node houses sub-nodes for each regulator within the device. Each
|
||||
sub-node is identified using the node's name, with valid values listed for each
|
||||
of the pmics below.
|
||||
@@ -156,6 +167,10 @@ pm8921:
|
||||
l29, lvs1, lvs2, lvs3, lvs4, lvs5, lvs6, lvs7, usb-switch, hdmi-switch,
|
||||
ncp
|
||||
|
||||
pm8018:
|
||||
s1, s2, s3, s4, s5, , l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11,
|
||||
l12, l14, lvs1
|
||||
|
||||
The content of each sub-node is defined by the standard binding for regulators -
|
||||
see regulator.txt - with additional custom properties described below:
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
RK808 Power Management Integrated Circuit
|
||||
RK8XX Power Management Integrated Circuit
|
||||
|
||||
The rk8xx family current members:
|
||||
rk808
|
||||
rk818
|
||||
|
||||
Required properties:
|
||||
- compatible: "rockchip,rk808"
|
||||
- compatible: "rockchip,rk808", "rockchip,rk818"
|
||||
- reg: I2C slave address
|
||||
- interrupt-parent: The parent interrupt controller.
|
||||
- interrupts: the interrupt outputs of the controller.
|
||||
@@ -13,6 +17,8 @@ Optional properties:
|
||||
default output clock name
|
||||
- rockchip,system-power-controller: Telling whether or not this pmic is controlling
|
||||
the system power.
|
||||
|
||||
Optional RK808 properties:
|
||||
- vcc1-supply: The input supply for DCDC_REG1
|
||||
- vcc2-supply: The input supply for DCDC_REG2
|
||||
- vcc3-supply: The input supply for DCDC_REG3
|
||||
@@ -29,7 +35,20 @@ Optional properties:
|
||||
the gpio controller. If DVS GPIOs aren't present, voltage changes will happen
|
||||
very quickly with no slow ramp time.
|
||||
|
||||
Regulators: All the regulators of RK808 to be instantiated shall be
|
||||
Optional RK818 properties:
|
||||
- vcc1-supply: The input supply for DCDC_REG1
|
||||
- vcc2-supply: The input supply for DCDC_REG2
|
||||
- vcc3-supply: The input supply for DCDC_REG3
|
||||
- vcc4-supply: The input supply for DCDC_REG4
|
||||
- boost-supply: The input supply for DCDC_BOOST
|
||||
- vcc6-supply: The input supply for LDO_REG1 and LDO_REG2
|
||||
- vcc7-supply: The input supply for LDO_REG3, LDO_REG5 and LDO_REG7
|
||||
- vcc8-supply: The input supply for LDO_REG4, LDO_REG6 and LDO_REG8
|
||||
- vcc9-supply: The input supply for LDO_REG9 and SWITCH_REG
|
||||
- h_5v-supply: The input supply for HDMI_SWITCH
|
||||
- usb-supply: The input supply for OTG_SWITCH
|
||||
|
||||
Regulators: All the regulators of RK8XX to be instantiated shall be
|
||||
listed in a child node named 'regulators'. Each regulator is represented
|
||||
by a child node of the 'regulators' node.
|
||||
|
||||
@@ -48,6 +67,18 @@ number as described in RK808 datasheet.
|
||||
- SWITCH_REGn
|
||||
- valid values for n are 1 to 2
|
||||
|
||||
Following regulators of the RK818 PMIC block are supported. Note that
|
||||
the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO
|
||||
number as described in RK818 datasheet.
|
||||
|
||||
- DCDC_REGn
|
||||
- valid values for n are 1 to 4.
|
||||
- LDO_REGn
|
||||
- valid values for n are 1 to 9.
|
||||
- SWITCH_REG
|
||||
- HDMI_SWITCH
|
||||
- OTG_SWITCH
|
||||
|
||||
Standard regulator bindings are used inside regulator subnodes. Check
|
||||
Documentation/devicetree/bindings/regulator/regulator.txt
|
||||
for more details
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
Samsung Exynos SoC Low Power Audio Subsystem (LPASS)
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "samsung,exynos5433-lpass"
|
||||
- reg : should contain the LPASS top SFR region location
|
||||
and size
|
||||
- samsung,pmu-syscon : the phandle to the Power Management Unit node
|
||||
- #address-cells : should be 1
|
||||
- #size-cells : should be 1
|
||||
- ranges : must be present
|
||||
|
||||
Each IP block of the Low Power Audio Subsystem should be specified as
|
||||
an optional sub-node. For "samsung,exynos5433-lpass" compatible this includes:
|
||||
UART, SLIMBUS, PCM, I2S, DMAC, Timers 0...4, VIC, WDT 0...1 devices.
|
||||
|
||||
Bindings of the sub-nodes are described in:
|
||||
../serial/samsung_uart.txt
|
||||
../sound/samsung-i2s.txt
|
||||
../dma/arm-pl330.txt
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
audio-subsystem {
|
||||
compatible = "samsung,exynos5433-lpass";
|
||||
reg = <0x11400000 0x100>, <0x11500000 0x08>;
|
||||
samsung,pmu-syscon = <&pmu_system_controller>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
adma: adma@11420000 {
|
||||
compatible = "arm,pl330", "arm,primecell";
|
||||
reg = <0x11420000 0x1000>;
|
||||
interrupts = <0 73 0>;
|
||||
clocks = <&cmu_aud CLK_ACLK_DMAC>;
|
||||
clock-names = "apb_pclk";
|
||||
#dma-cells = <1>;
|
||||
#dma-channels = <8>;
|
||||
#dma-requests = <32>;
|
||||
};
|
||||
|
||||
i2s0: i2s0@11440000 {
|
||||
compatible = "samsung,exynos7-i2s";
|
||||
reg = <0x11440000 0x100>;
|
||||
dmas = <&adma 0 &adma 2>;
|
||||
dma-names = "tx", "rx";
|
||||
interrupts = <0 70 0>;
|
||||
clocks = <&cmu_aud CLK_PCLK_AUD_I2S>,
|
||||
<&cmu_aud CLK_SCLK_AUD_I2S>,
|
||||
<&cmu_aud CLK_SCLK_I2S_BCLK>;
|
||||
clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2s0_bus>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
serial_3: serial@11460000 {
|
||||
compatible = "samsung,exynos5433-uart";
|
||||
reg = <0x11460000 0x100>;
|
||||
interrupts = <0 67 0>;
|
||||
clocks = <&cmu_aud CLK_PCLK_AUD_UART>,
|
||||
<&cmu_aud CLK_SCLK_AUD_UART>;
|
||||
clock-names = "uart", "clk_uart_baud0";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart_aud_bus>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
@@ -12,6 +12,7 @@ Required properties:
|
||||
- interrupt-parent: The parent interrupt controller
|
||||
- gpio-controller:
|
||||
- #gpio-cells = <1>: twl6040 provides GPO lines.
|
||||
- #clock-cells = <0>; twl6040 is a provider of pdmclk which is used by McPDM
|
||||
- twl6040,audpwron-gpio: Power on GPIO line for the twl6040
|
||||
|
||||
- vio-supply: Regulator for the twl6040 VIO supply
|
||||
|
||||
@@ -8098,6 +8098,7 @@ MULTIFUNCTION DEVICES (MFD)
|
||||
M: Lee Jones <lee.jones@linaro.org>
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/mfd/
|
||||
F: drivers/mfd/
|
||||
F: include/linux/mfd/
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/input/matrix_keypad.h>
|
||||
@@ -44,6 +45,7 @@
|
||||
* @dev: Device pointer
|
||||
* @idev: Input device
|
||||
* @ec: Top level ChromeOS device to use to talk to EC
|
||||
* @notifier: interrupt event notifier for transport devices
|
||||
*/
|
||||
struct cros_ec_keyb {
|
||||
unsigned int rows;
|
||||
@@ -57,6 +59,7 @@ struct cros_ec_keyb {
|
||||
struct device *dev;
|
||||
struct input_dev *idev;
|
||||
struct cros_ec_device *ec;
|
||||
struct notifier_block notifier;
|
||||
};
|
||||
|
||||
|
||||
@@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
|
||||
input_sync(ckdev->idev);
|
||||
}
|
||||
|
||||
static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cros_ec_command *msg;
|
||||
|
||||
msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
msg->version = 0;
|
||||
msg->command = EC_CMD_MKBP_STATE;
|
||||
msg->insize = ckdev->cols;
|
||||
msg->outsize = 0;
|
||||
|
||||
ret = cros_ec_cmd_xfer(ckdev->ec, msg);
|
||||
if (ret < 0) {
|
||||
dev_err(ckdev->dev, "Error transferring EC message %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(kb_state, msg->data, ckdev->cols);
|
||||
exit:
|
||||
kfree(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
|
||||
{
|
||||
struct cros_ec_keyb *ckdev = data;
|
||||
struct cros_ec_device *ec = ckdev->ec;
|
||||
int ret;
|
||||
uint8_t kb_state[ckdev->cols];
|
||||
|
||||
if (device_may_wakeup(ec->dev))
|
||||
pm_wakeup_event(ec->dev, 0);
|
||||
|
||||
ret = cros_ec_keyb_get_state(ckdev, kb_state);
|
||||
if (ret >= 0)
|
||||
cros_ec_keyb_process(ckdev, kb_state, ret);
|
||||
else
|
||||
dev_err(ckdev->dev, "failed to get keyboard state: %d\n", ret);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int cros_ec_keyb_open(struct input_dev *dev)
|
||||
{
|
||||
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
|
||||
struct cros_ec_device *ec = ckdev->ec;
|
||||
|
||||
return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
"cros_ec_keyb", ckdev);
|
||||
return blocking_notifier_chain_register(&ckdev->ec->event_notifier,
|
||||
&ckdev->notifier);
|
||||
}
|
||||
|
||||
static void cros_ec_keyb_close(struct input_dev *dev)
|
||||
{
|
||||
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
|
||||
struct cros_ec_device *ec = ckdev->ec;
|
||||
|
||||
free_irq(ec->irq, ckdev);
|
||||
blocking_notifier_chain_unregister(&ckdev->ec->event_notifier,
|
||||
&ckdev->notifier);
|
||||
}
|
||||
|
||||
static int cros_ec_keyb_work(struct notifier_block *nb,
|
||||
unsigned long queued_during_suspend, void *_notify)
|
||||
{
|
||||
struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
|
||||
notifier);
|
||||
|
||||
if (ckdev->ec->event_data.event_type != EC_MKBP_EVENT_KEY_MATRIX)
|
||||
return NOTIFY_DONE;
|
||||
/*
|
||||
* If EC is not the wake source, discard key state changes during
|
||||
* suspend.
|
||||
*/
|
||||
if (queued_during_suspend)
|
||||
return NOTIFY_OK;
|
||||
if (ckdev->ec->event_size != ckdev->cols) {
|
||||
dev_err(ckdev->dev,
|
||||
"Discarded incomplete key matrix event.\n");
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
cros_ec_keyb_process(ckdev, ckdev->ec->event_data.data.key_matrix,
|
||||
ckdev->ec->event_size);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -265,12 +245,8 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
|
||||
if (!idev)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!ec->irq) {
|
||||
dev_err(dev, "no EC IRQ specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ckdev->ec = ec;
|
||||
ckdev->notifier.notifier_call = cros_ec_keyb_work;
|
||||
ckdev->dev = dev;
|
||||
dev_set_drvdata(dev, ckdev);
|
||||
|
||||
@@ -311,54 +287,6 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
/* Clear any keys in the buffer */
|
||||
static void cros_ec_keyb_clear_keyboard(struct cros_ec_keyb *ckdev)
|
||||
{
|
||||
uint8_t old_state[ckdev->cols];
|
||||
uint8_t new_state[ckdev->cols];
|
||||
unsigned long duration;
|
||||
int i, ret;
|
||||
|
||||
/*
|
||||
* Keep reading until we see that the scan state does not change.
|
||||
* That indicates that we are done.
|
||||
*
|
||||
* Assume that the EC keyscan buffer is at most 32 deep.
|
||||
*/
|
||||
duration = jiffies;
|
||||
ret = cros_ec_keyb_get_state(ckdev, new_state);
|
||||
for (i = 1; !ret && i < 32; i++) {
|
||||
memcpy(old_state, new_state, sizeof(old_state));
|
||||
ret = cros_ec_keyb_get_state(ckdev, new_state);
|
||||
if (0 == memcmp(old_state, new_state, sizeof(old_state)))
|
||||
break;
|
||||
}
|
||||
duration = jiffies - duration;
|
||||
dev_info(ckdev->dev, "Discarded %d keyscan(s) in %dus\n", i,
|
||||
jiffies_to_usecs(duration));
|
||||
}
|
||||
|
||||
static int cros_ec_keyb_resume(struct device *dev)
|
||||
{
|
||||
struct cros_ec_keyb *ckdev = dev_get_drvdata(dev);
|
||||
|
||||
/*
|
||||
* When the EC is not a wake source, then it could not have caused the
|
||||
* resume, so we clear the EC's key scan buffer. If the EC was a
|
||||
* wake source (e.g. the lid is open and the user might press a key to
|
||||
* wake) then the key scan buffer should be preserved.
|
||||
*/
|
||||
if (!ckdev->ec->was_wake_device)
|
||||
cros_ec_keyb_clear_keyboard(ckdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(cros_ec_keyb_pm_ops, NULL, cros_ec_keyb_resume);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id cros_ec_keyb_of_match[] = {
|
||||
{ .compatible = "google,cros-ec-keyb" },
|
||||
@@ -372,7 +300,6 @@ static struct platform_driver cros_ec_keyb_driver = {
|
||||
.driver = {
|
||||
.name = "cros-ec-keyb",
|
||||
.of_match_table = of_match_ptr(cros_ec_keyb_of_match),
|
||||
.pm = &cros_ec_keyb_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
+23
-3
@@ -50,7 +50,7 @@ config MFD_AS3711
|
||||
Support for the AS3711 PMIC from AMS
|
||||
|
||||
config MFD_AS3722
|
||||
bool "ams AS3722 Power Management IC"
|
||||
tristate "ams AS3722 Power Management IC"
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
@@ -112,6 +112,16 @@ config MFD_BCM590XX
|
||||
help
|
||||
Support for the BCM590xx PMUs from Broadcom
|
||||
|
||||
config MFD_AC100
|
||||
tristate "X-Powers AC100"
|
||||
select MFD_CORE
|
||||
depends on SUNXI_RSB
|
||||
help
|
||||
If you say Y here you get support for the X-Powers AC100 audio codec
|
||||
IC.
|
||||
This driver include only the core APIs. You have to select individual
|
||||
components like codecs or RTC under the corresponding menus.
|
||||
|
||||
config MFD_AXP20X
|
||||
tristate
|
||||
select MFD_CORE
|
||||
@@ -281,6 +291,14 @@ config MFD_DLN2
|
||||
etc. must be enabled in order to use the functionality of
|
||||
the device.
|
||||
|
||||
config MFD_EXYNOS_LPASS
|
||||
tristate "Samsung Exynos SoC Low Power Audio Subsystem"
|
||||
select MFD_CORE
|
||||
select REGMAP_MMIO
|
||||
help
|
||||
Select this option to enable support for Samsung Exynos Low Power
|
||||
Audio Subsystem.
|
||||
|
||||
config MFD_MC13XXX
|
||||
tristate
|
||||
depends on (SPI_MASTER || I2C)
|
||||
@@ -844,13 +862,13 @@ config MFD_RC5T583
|
||||
different functionality of the device.
|
||||
|
||||
config MFD_RK808
|
||||
tristate "Rockchip RK808 Power Management chip"
|
||||
tristate "Rockchip RK808/RK818 Power Management Chip"
|
||||
depends on I2C && OF
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
help
|
||||
If you say yes here you get support for the RK808
|
||||
If you say yes here you get support for the RK808 and RK818
|
||||
Power Management chips.
|
||||
This driver provides common support for accessing the device
|
||||
through I2C interface. The device supports multiple sub-devices
|
||||
@@ -1206,6 +1224,7 @@ config MFD_TPS65217
|
||||
depends on I2C
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select IRQ_DOMAIN
|
||||
help
|
||||
If you say yes here you get support for the TPS65217 series of
|
||||
Power Management / White LED chips.
|
||||
@@ -1555,6 +1574,7 @@ config MFD_WM8350
|
||||
config MFD_WM8350_I2C
|
||||
bool "Wolfson Microelectronics WM8350 with I2C"
|
||||
select MFD_WM8350
|
||||
select REGMAP_I2C
|
||||
depends on I2C=y
|
||||
help
|
||||
The WM8350 is an integrated audio and power management
|
||||
|
||||
@@ -13,6 +13,7 @@ obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
|
||||
obj-$(CONFIG_MFD_CROS_EC) += cros_ec.o
|
||||
obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
|
||||
obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
|
||||
obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o
|
||||
|
||||
rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
|
||||
obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o
|
||||
@@ -114,6 +115,8 @@ obj-$(CONFIG_PMIC_DA9052) += da9052-irq.o
|
||||
obj-$(CONFIG_PMIC_DA9052) += da9052-core.o
|
||||
obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o
|
||||
obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o
|
||||
|
||||
obj-$(CONFIG_MFD_AC100) += ac100.o
|
||||
obj-$(CONFIG_MFD_AXP20X) += axp20x.o
|
||||
obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o
|
||||
obj-$(CONFIG_MFD_AXP20X_RSB) += axp20x-rsb.o
|
||||
|
||||
@@ -153,14 +153,14 @@ static struct hwreg_cfg hwreg_cfg = {
|
||||
|
||||
#define AB8500_NAME_STRING "ab8500"
|
||||
#define AB8500_ADC_NAME_STRING "gpadc"
|
||||
#define AB8500_NUM_BANKS 24
|
||||
#define AB8500_NUM_BANKS AB8500_DEBUG_FIELD_LAST
|
||||
|
||||
#define AB8500_REV_REG 0x80
|
||||
|
||||
static struct ab8500_prcmu_ranges *debug_ranges;
|
||||
|
||||
static struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = {
|
||||
[0x0] = {
|
||||
[AB8500_M_FSM_RANK] = {
|
||||
.num_ranges = 0,
|
||||
.range = NULL,
|
||||
},
|
||||
@@ -315,7 +315,7 @@ static struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = {
|
||||
},
|
||||
},
|
||||
},
|
||||
[0x9] = {
|
||||
[AB8500_RESERVED] = {
|
||||
.num_ranges = 0,
|
||||
.range = NULL,
|
||||
},
|
||||
@@ -386,24 +386,6 @@ static struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = {
|
||||
},
|
||||
},
|
||||
},
|
||||
[AB8500_DEVELOPMENT] = {
|
||||
.num_ranges = 1,
|
||||
.range = (struct ab8500_reg_range[]) {
|
||||
{
|
||||
.first = 0x00,
|
||||
.last = 0x00,
|
||||
},
|
||||
},
|
||||
},
|
||||
[AB8500_DEBUG] = {
|
||||
.num_ranges = 1,
|
||||
.range = (struct ab8500_reg_range[]) {
|
||||
{
|
||||
.first = 0x05,
|
||||
.last = 0x07,
|
||||
},
|
||||
},
|
||||
},
|
||||
[AB8500_AUDIO] = {
|
||||
.num_ranges = 1,
|
||||
.range = (struct ab8500_reg_range[]) {
|
||||
@@ -463,19 +445,29 @@ static struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = {
|
||||
},
|
||||
},
|
||||
},
|
||||
[0x11] = {
|
||||
[AB8500_DEVELOPMENT] = {
|
||||
.num_ranges = 1,
|
||||
.range = (struct ab8500_reg_range[]) {
|
||||
{
|
||||
.first = 0x00,
|
||||
.last = 0x00,
|
||||
},
|
||||
},
|
||||
},
|
||||
[AB8500_DEBUG] = {
|
||||
.num_ranges = 1,
|
||||
.range = (struct ab8500_reg_range[]) {
|
||||
{
|
||||
.first = 0x05,
|
||||
.last = 0x07,
|
||||
},
|
||||
},
|
||||
},
|
||||
[AB8500_PROD_TEST] = {
|
||||
.num_ranges = 0,
|
||||
.range = NULL,
|
||||
},
|
||||
[0x12] = {
|
||||
.num_ranges = 0,
|
||||
.range = NULL,
|
||||
},
|
||||
[0x13] = {
|
||||
.num_ranges = 0,
|
||||
.range = NULL,
|
||||
},
|
||||
[0x14] = {
|
||||
[AB8500_STE_TEST] = {
|
||||
.num_ranges = 0,
|
||||
.range = NULL,
|
||||
},
|
||||
@@ -1382,60 +1374,6 @@ void ab8500_dump_all_banks(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
/* Space for 500 registers. */
|
||||
#define DUMP_MAX_REGS 700
|
||||
static struct ab8500_register_dump
|
||||
{
|
||||
u8 bank;
|
||||
u8 reg;
|
||||
u8 value;
|
||||
} ab8500_complete_register_dump[DUMP_MAX_REGS];
|
||||
|
||||
/* This shall only be called upon kernel panic! */
|
||||
void ab8500_dump_all_banks_to_mem(void)
|
||||
{
|
||||
int i, r = 0;
|
||||
u8 bank;
|
||||
int err = 0;
|
||||
|
||||
pr_info("Saving all ABB registers for crash analysis.\n");
|
||||
|
||||
for (bank = 0; bank < AB8500_NUM_BANKS; bank++) {
|
||||
for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
|
||||
u8 reg;
|
||||
|
||||
for (reg = debug_ranges[bank].range[i].first;
|
||||
reg <= debug_ranges[bank].range[i].last;
|
||||
reg++) {
|
||||
u8 value;
|
||||
|
||||
err = prcmu_abb_read(bank, reg, &value, 1);
|
||||
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
ab8500_complete_register_dump[r].bank = bank;
|
||||
ab8500_complete_register_dump[r].reg = reg;
|
||||
ab8500_complete_register_dump[r].value = value;
|
||||
|
||||
r++;
|
||||
|
||||
if (r >= DUMP_MAX_REGS) {
|
||||
pr_err("%s: too many register to dump!\n",
|
||||
__func__);
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (err >= 0)
|
||||
pr_info("Saved all ABB registers.\n");
|
||||
else
|
||||
pr_info("Failed to save all ABB registers.\n");
|
||||
}
|
||||
|
||||
static int ab8500_all_banks_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct seq_file *s;
|
||||
@@ -1584,18 +1522,10 @@ static u32 num_interrupts[AB8500_MAX_NR_IRQS];
|
||||
static u32 num_wake_interrupts[AB8500_MAX_NR_IRQS];
|
||||
static int num_interrupt_lines;
|
||||
|
||||
bool __attribute__((weak)) suspend_test_wake_cause_interrupt_is_mine(u32 my_int)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void ab8500_debug_register_interrupt(int line)
|
||||
{
|
||||
if (line < num_interrupt_lines) {
|
||||
if (line < num_interrupt_lines)
|
||||
num_interrupts[line]++;
|
||||
if (suspend_test_wake_cause_interrupt_is_mine(irq_ab8500))
|
||||
num_wake_interrupts[line]++;
|
||||
}
|
||||
}
|
||||
|
||||
static int ab8500_interrupts_print(struct seq_file *s, void *p)
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* MFD core driver for X-Powers' AC100 Audio Codec IC
|
||||
*
|
||||
* The AC100 is a highly integrated audio codec and RTC subsystem designed
|
||||
* for mobile applications. It has 3 I2S/PCM interfaces, a 2 channel DAC,
|
||||
* a 2 channel ADC with 5 inputs and a builtin mixer. The RTC subsystem has
|
||||
* 3 clock outputs.
|
||||
*
|
||||
* The audio codec and RTC parts are completely separate, sharing only the
|
||||
* host interface for access to its registers.
|
||||
*
|
||||
* Copyright (2016) Chen-Yu Tsai
|
||||
*
|
||||
* Author: Chen-Yu Tsai <wens@csie.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/ac100.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/sunxi-rsb.h>
|
||||
|
||||
static const struct regmap_range ac100_writeable_ranges[] = {
|
||||
regmap_reg_range(AC100_CHIP_AUDIO_RST, AC100_I2S_SR_CTRL),
|
||||
regmap_reg_range(AC100_I2S1_CLK_CTRL, AC100_I2S1_MXR_GAIN),
|
||||
regmap_reg_range(AC100_I2S2_CLK_CTRL, AC100_I2S2_MXR_GAIN),
|
||||
regmap_reg_range(AC100_I2S3_CLK_CTRL, AC100_I2S3_SIG_PATH_CTRL),
|
||||
regmap_reg_range(AC100_ADC_DIG_CTRL, AC100_ADC_VOL_CTRL),
|
||||
regmap_reg_range(AC100_HMIC_CTRL1, AC100_HMIC_STATUS),
|
||||
regmap_reg_range(AC100_DAC_DIG_CTRL, AC100_DAC_MXR_GAIN),
|
||||
regmap_reg_range(AC100_ADC_APC_CTRL, AC100_LINEOUT_CTRL),
|
||||
regmap_reg_range(AC100_ADC_DAP_L_CTRL, AC100_ADC_DAP_OPT),
|
||||
regmap_reg_range(AC100_DAC_DAP_CTRL, AC100_DAC_DAP_OPT),
|
||||
regmap_reg_range(AC100_ADC_DAP_ENA, AC100_DAC_DAP_ENA),
|
||||
regmap_reg_range(AC100_SRC1_CTRL1, AC100_SRC1_CTRL2),
|
||||
regmap_reg_range(AC100_SRC2_CTRL1, AC100_SRC2_CTRL2),
|
||||
regmap_reg_range(AC100_CLK32K_ANALOG_CTRL, AC100_CLKOUT_CTRL3),
|
||||
regmap_reg_range(AC100_RTC_RST, AC100_RTC_UPD),
|
||||
regmap_reg_range(AC100_ALM_INT_ENA, AC100_ALM_INT_STA),
|
||||
regmap_reg_range(AC100_ALM_SEC, AC100_RTC_GP(15)),
|
||||
};
|
||||
|
||||
static const struct regmap_range ac100_volatile_ranges[] = {
|
||||
regmap_reg_range(AC100_CHIP_AUDIO_RST, AC100_PLL_CTRL2),
|
||||
regmap_reg_range(AC100_HMIC_STATUS, AC100_HMIC_STATUS),
|
||||
regmap_reg_range(AC100_ADC_DAP_L_STA, AC100_ADC_DAP_L_STA),
|
||||
regmap_reg_range(AC100_SRC1_CTRL1, AC100_SRC1_CTRL1),
|
||||
regmap_reg_range(AC100_SRC1_CTRL3, AC100_SRC2_CTRL1),
|
||||
regmap_reg_range(AC100_SRC2_CTRL3, AC100_SRC2_CTRL4),
|
||||
regmap_reg_range(AC100_RTC_RST, AC100_RTC_RST),
|
||||
regmap_reg_range(AC100_RTC_SEC, AC100_ALM_INT_STA),
|
||||
regmap_reg_range(AC100_ALM_SEC, AC100_ALM_UPD),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table ac100_writeable_table = {
|
||||
.yes_ranges = ac100_writeable_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(ac100_writeable_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table ac100_volatile_table = {
|
||||
.yes_ranges = ac100_volatile_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(ac100_volatile_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_config ac100_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 16,
|
||||
.wr_table = &ac100_writeable_table,
|
||||
.volatile_table = &ac100_volatile_table,
|
||||
.max_register = AC100_RTC_GP(15),
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static struct mfd_cell ac100_cells[] = {
|
||||
{
|
||||
.name = "ac100-codec",
|
||||
.of_compatible = "x-powers,ac100-codec",
|
||||
}, {
|
||||
.name = "ac100-rtc",
|
||||
.of_compatible = "x-powers,ac100-rtc",
|
||||
},
|
||||
};
|
||||
|
||||
static int ac100_rsb_probe(struct sunxi_rsb_device *rdev)
|
||||
{
|
||||
struct ac100_dev *ac100;
|
||||
int ret;
|
||||
|
||||
ac100 = devm_kzalloc(&rdev->dev, sizeof(*ac100), GFP_KERNEL);
|
||||
if (!ac100)
|
||||
return -ENOMEM;
|
||||
|
||||
ac100->dev = &rdev->dev;
|
||||
sunxi_rsb_device_set_drvdata(rdev, ac100);
|
||||
|
||||
ac100->regmap = devm_regmap_init_sunxi_rsb(rdev, &ac100_regmap_config);
|
||||
if (IS_ERR(ac100->regmap)) {
|
||||
ret = PTR_ERR(ac100->regmap);
|
||||
dev_err(ac100->dev, "regmap init failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_mfd_add_devices(ac100->dev, PLATFORM_DEVID_NONE, ac100_cells,
|
||||
ARRAY_SIZE(ac100_cells), NULL, 0, NULL);
|
||||
if (ret) {
|
||||
dev_err(ac100->dev, "failed to add MFD devices: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id ac100_of_match[] = {
|
||||
{ .compatible = "x-powers,ac100" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ac100_of_match);
|
||||
|
||||
static struct sunxi_rsb_driver ac100_rsb_driver = {
|
||||
.driver = {
|
||||
.name = "ac100",
|
||||
.of_match_table = of_match_ptr(ac100_of_match),
|
||||
},
|
||||
.probe = ac100_rsb_probe,
|
||||
};
|
||||
module_sunxi_rsb_driver(ac100_rsb_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Audio codec MFD core driver for AC100");
|
||||
MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
@@ -23,6 +23,7 @@ static const struct mfd_cell act8945a_devs[] = {
|
||||
},
|
||||
{
|
||||
.name = "act8945a-charger",
|
||||
.of_compatible = "active-semi,act8945a-charger",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
/*
|
||||
* Altera Arria10 DevKit System Resource MFD Driver
|
||||
*
|
||||
* Author: Thor Thayer <tthayer@opensource.altera.com>
|
||||
*
|
||||
* Copyright Intel Corporation (C) 2014-2016. All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -20,7 +24,7 @@
|
||||
|
||||
#include <linux/mfd/altera-a10sr.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
@@ -94,7 +98,7 @@ static bool altr_a10sr_reg_volatile(struct device *dev, unsigned int reg)
|
||||
}
|
||||
}
|
||||
|
||||
const struct regmap_config altr_a10sr_regmap_config = {
|
||||
static const struct regmap_config altr_a10sr_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
@@ -152,7 +156,6 @@ static const struct of_device_id altr_a10sr_spi_of_match[] = {
|
||||
{ .compatible = "altr,a10sr" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, altr_a10sr_spi_of_match);
|
||||
|
||||
static struct spi_driver altr_a10sr_spi_driver = {
|
||||
.probe = altr_a10sr_spi_probe,
|
||||
@@ -161,9 +164,4 @@ static struct spi_driver altr_a10sr_spi_driver = {
|
||||
.of_match_table = of_match_ptr(altr_a10sr_spi_of_match),
|
||||
},
|
||||
};
|
||||
|
||||
module_spi_driver(altr_a10sr_spi_driver);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Thor Thayer <tthayer@opensource.altera.com>");
|
||||
MODULE_DESCRIPTION("Altera Arria10 DevKit System Resource MFD Driver");
|
||||
builtin_driver(altr_a10sr_spi_driver, spi_register_driver)
|
||||
|
||||
+81
-32
@@ -10,6 +10,7 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
@@ -49,7 +50,15 @@ int arizona_clk32k_enable(struct arizona *arizona)
|
||||
case ARIZONA_32KZ_MCLK1:
|
||||
ret = pm_runtime_get_sync(arizona->dev);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
goto err_ref;
|
||||
ret = clk_prepare_enable(arizona->mclk[ARIZONA_MCLK1]);
|
||||
if (ret != 0)
|
||||
goto err_pm;
|
||||
break;
|
||||
case ARIZONA_32KZ_MCLK2:
|
||||
ret = clk_prepare_enable(arizona->mclk[ARIZONA_MCLK2]);
|
||||
if (ret != 0)
|
||||
goto err_ref;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -58,7 +67,9 @@ int arizona_clk32k_enable(struct arizona *arizona)
|
||||
ARIZONA_CLK_32K_ENA);
|
||||
}
|
||||
|
||||
out:
|
||||
err_pm:
|
||||
pm_runtime_put_sync(arizona->dev);
|
||||
err_ref:
|
||||
if (ret != 0)
|
||||
arizona->clk32k_ref--;
|
||||
|
||||
@@ -83,6 +94,10 @@ int arizona_clk32k_disable(struct arizona *arizona)
|
||||
switch (arizona->pdata.clk32k_src) {
|
||||
case ARIZONA_32KZ_MCLK1:
|
||||
pm_runtime_put_sync(arizona->dev);
|
||||
clk_disable_unprepare(arizona->mclk[ARIZONA_MCLK1]);
|
||||
break;
|
||||
case ARIZONA_32KZ_MCLK2:
|
||||
clk_disable_unprepare(arizona->mclk[ARIZONA_MCLK2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -735,7 +750,7 @@ static int arizona_suspend(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arizona_suspend_late(struct device *dev)
|
||||
static int arizona_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct arizona *arizona = dev_get_drvdata(dev);
|
||||
|
||||
@@ -759,7 +774,7 @@ static int arizona_resume(struct device *dev)
|
||||
{
|
||||
struct arizona *arizona = dev_get_drvdata(dev);
|
||||
|
||||
dev_dbg(arizona->dev, "Late resume, reenabling IRQ\n");
|
||||
dev_dbg(arizona->dev, "Resume, reenabling IRQ\n");
|
||||
enable_irq(arizona->irq);
|
||||
|
||||
return 0;
|
||||
@@ -771,10 +786,8 @@ const struct dev_pm_ops arizona_pm_ops = {
|
||||
arizona_runtime_resume,
|
||||
NULL)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(arizona_suspend, arizona_resume)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.suspend_late = arizona_suspend_late,
|
||||
.resume_noirq = arizona_resume_noirq,
|
||||
#endif
|
||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(arizona_suspend_noirq,
|
||||
arizona_resume_noirq)
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(arizona_pm_ops);
|
||||
|
||||
@@ -790,35 +803,25 @@ unsigned long arizona_of_get_type(struct device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_of_get_type);
|
||||
|
||||
int arizona_of_get_named_gpio(struct arizona *arizona, const char *prop,
|
||||
bool mandatory)
|
||||
{
|
||||
int gpio;
|
||||
|
||||
gpio = of_get_named_gpio(arizona->dev->of_node, prop, 0);
|
||||
if (gpio < 0) {
|
||||
if (mandatory)
|
||||
dev_err(arizona->dev,
|
||||
"Mandatory DT gpio %s missing/malformed: %d\n",
|
||||
prop, gpio);
|
||||
|
||||
gpio = 0;
|
||||
}
|
||||
|
||||
return gpio;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arizona_of_get_named_gpio);
|
||||
|
||||
static int arizona_of_get_core_pdata(struct arizona *arizona)
|
||||
{
|
||||
struct arizona_pdata *pdata = &arizona->pdata;
|
||||
struct property *prop;
|
||||
const __be32 *cur;
|
||||
u32 val;
|
||||
u32 pdm_val[ARIZONA_MAX_PDM_SPK];
|
||||
int ret, i;
|
||||
int count = 0;
|
||||
|
||||
pdata->reset = arizona_of_get_named_gpio(arizona, "wlf,reset", true);
|
||||
pdata->reset = of_get_named_gpio(arizona->dev->of_node, "wlf,reset", 0);
|
||||
if (pdata->reset == -EPROBE_DEFER) {
|
||||
return pdata->reset;
|
||||
} else if (pdata->reset < 0) {
|
||||
dev_err(arizona->dev, "Reset GPIO missing/malformed: %d\n",
|
||||
pdata->reset);
|
||||
|
||||
pdata->reset = 0;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32_array(arizona->dev->of_node,
|
||||
"wlf,gpio-defaults",
|
||||
@@ -871,6 +874,35 @@ static int arizona_of_get_core_pdata(struct arizona *arizona)
|
||||
count++;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
of_property_for_each_u32(arizona->dev->of_node,
|
||||
"wlf,max-channels-clocked",
|
||||
prop, cur, val) {
|
||||
if (count == ARRAY_SIZE(pdata->max_channels_clocked))
|
||||
break;
|
||||
|
||||
pdata->max_channels_clocked[count] = val;
|
||||
count++;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32_array(arizona->dev->of_node,
|
||||
"wlf,spk-fmt",
|
||||
pdm_val,
|
||||
ARRAY_SIZE(pdm_val));
|
||||
|
||||
if (ret >= 0)
|
||||
for (count = 0; count < ARRAY_SIZE(pdata->spk_fmt); ++count)
|
||||
pdata->spk_fmt[count] = pdm_val[count];
|
||||
|
||||
ret = of_property_read_u32_array(arizona->dev->of_node,
|
||||
"wlf,spk-mute",
|
||||
pdm_val,
|
||||
ARRAY_SIZE(pdm_val));
|
||||
|
||||
if (ret >= 0)
|
||||
for (count = 0; count < ARRAY_SIZE(pdata->spk_mute); ++count)
|
||||
pdata->spk_mute[count] = pdm_val[count];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1000,6 +1032,7 @@ static const struct mfd_cell wm8998_devs[] = {
|
||||
|
||||
int arizona_dev_init(struct arizona *arizona)
|
||||
{
|
||||
const char * const mclk_name[] = { "mclk1", "mclk2" };
|
||||
struct device *dev = arizona->dev;
|
||||
const char *type_name = NULL;
|
||||
unsigned int reg, val, mask;
|
||||
@@ -1010,11 +1043,24 @@ int arizona_dev_init(struct arizona *arizona)
|
||||
dev_set_drvdata(arizona->dev, arizona);
|
||||
mutex_init(&arizona->clk_lock);
|
||||
|
||||
if (dev_get_platdata(arizona->dev))
|
||||
if (dev_get_platdata(arizona->dev)) {
|
||||
memcpy(&arizona->pdata, dev_get_platdata(arizona->dev),
|
||||
sizeof(arizona->pdata));
|
||||
else
|
||||
arizona_of_get_core_pdata(arizona);
|
||||
} else {
|
||||
ret = arizona_of_get_core_pdata(arizona);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(arizona->mclk) != ARRAY_SIZE(mclk_name));
|
||||
for (i = 0; i < ARRAY_SIZE(arizona->mclk); i++) {
|
||||
arizona->mclk[i] = devm_clk_get(arizona->dev, mclk_name[i]);
|
||||
if (IS_ERR(arizona->mclk[i])) {
|
||||
dev_info(arizona->dev, "Failed to get %s: %ld\n",
|
||||
mclk_name[i], PTR_ERR(arizona->mclk[i]));
|
||||
arizona->mclk[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
regcache_cache_only(arizona->regmap, true);
|
||||
|
||||
@@ -1035,7 +1081,7 @@ int arizona_dev_init(struct arizona *arizona)
|
||||
default:
|
||||
dev_err(arizona->dev, "Unknown device type %d\n",
|
||||
arizona->type);
|
||||
return -EINVAL;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Mark DCVDD as external, LDO1 driver will clear if internal */
|
||||
@@ -1121,6 +1167,7 @@ int arizona_dev_init(struct arizona *arizona)
|
||||
break;
|
||||
default:
|
||||
dev_err(arizona->dev, "Unknown device ID: %x\n", reg);
|
||||
ret = -ENODEV;
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
@@ -1280,12 +1327,14 @@ int arizona_dev_init(struct arizona *arizona)
|
||||
break;
|
||||
default:
|
||||
dev_err(arizona->dev, "Unknown device ID %x\n", reg);
|
||||
ret = -ENODEV;
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
if (!subdevs) {
|
||||
dev_err(arizona->dev,
|
||||
"No kernel support for device ID %x\n", reg);
|
||||
ret = -ENODEV;
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user