diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-07 11:35:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-07 11:35:35 -0400 |
commit | d042380886fb2fc6c4b0fcfe1214ba473769a8e9 (patch) | |
tree | 61e29ff167e0f83f67930ee9911062415030e1ef | |
parent | 3477d168ba61c5b0ca42d3d4642f3463609a5417 (diff) | |
parent | b8d336ed90f541097a2ce583be430bb3e895dfbd (diff) |
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
...
80 files changed, 3111 insertions, 445 deletions
diff --git a/Documentation/devicetree/bindings/mfd/ac100.txt b/Documentation/devicetree/bindings/mfd/ac100.txt new file mode 100644 index 000000000000..b8ef00667599 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/ac100.txt | |||
@@ -0,0 +1,54 @@ | |||
1 | X-Powers AC100 Codec/RTC IC Device Tree bindings | ||
2 | |||
3 | AC100 is a audio codec and RTC subsystem combo IC. The 2 parts are | ||
4 | separated, including power supplies and interrupt lines, but share | ||
5 | a common register address space and host interface. | ||
6 | |||
7 | Required properties: | ||
8 | - compatible: "x-powers,ac100" | ||
9 | - reg: The I2C slave address or RSB hardware address for the chip | ||
10 | - sub-nodes: | ||
11 | - codec | ||
12 | - compatible: "x-powers,ac100-codec" | ||
13 | - interrupt-parent: The parent interrupt controller | ||
14 | - interrupts: SoC NMI / GPIO interrupt connected to the | ||
15 | IRQ_AUDIO pin | ||
16 | - #clock-cells: Shall be 0 | ||
17 | - clock-output-names: "4M_adda" | ||
18 | |||
19 | - see clock/clock-bindings.txt for common clock bindings | ||
20 | |||
21 | - rtc | ||
22 | - compatible: "x-powers,ac100-rtc" | ||
23 | - interrupt-parent: The parent interrupt controller | ||
24 | - interrupts: SoC NMI / GPIO interrupt connected to the | ||
25 | IRQ_RTC pin | ||
26 | - clocks: A phandle to the codec's "4M_adda" clock | ||
27 | - #clock-cells: Shall be 1 | ||
28 | - clock-output-names: "cko1_rtc", "cko2_rtc", "cko3_rtc" | ||
29 | |||
30 | - see clock/clock-bindings.txt for common clock bindings | ||
31 | |||
32 | Example: | ||
33 | |||
34 | ac100: codec@e89 { | ||
35 | compatible = "x-powers,ac100"; | ||
36 | reg = <0xe89>; | ||
37 | |||
38 | ac100_codec: codec { | ||
39 | compatible = "x-powers,ac100-codec"; | ||
40 | interrupt-parent = <&r_pio>; | ||
41 | interrupts = <0 9 IRQ_TYPE_LEVEL_LOW>; /* PL9 */ | ||
42 | #clock-cells = <0>; | ||
43 | clock-output-names = "4M_adda"; | ||
44 | }; | ||
45 | |||
46 | ac100_rtc: rtc { | ||
47 | compatible = "x-powers,ac100-rtc"; | ||
48 | interrupt-parent = <&nmi_intc>; | ||
49 | interrupts = <0 IRQ_TYPE_LEVEL_LOW>; | ||
50 | clocks = <&ac100_codec>; | ||
51 | #clock-cells = <1>; | ||
52 | clock-output-names = "cko1_rtc", "cko2_rtc", "cko3_rtc"; | ||
53 | }; | ||
54 | }; | ||
diff --git a/Documentation/devicetree/bindings/mfd/act8945a.txt b/Documentation/devicetree/bindings/mfd/act8945a.txt index f71283055685..462819ac3da8 100644 --- a/Documentation/devicetree/bindings/mfd/act8945a.txt +++ b/Documentation/devicetree/bindings/mfd/act8945a.txt | |||
@@ -14,13 +14,6 @@ Example: | |||
14 | reg = <0x5b>; | 14 | reg = <0x5b>; |
15 | status = "okay"; | 15 | status = "okay"; |
16 | 16 | ||
17 | pinctrl-names = "default"; | ||
18 | pinctrl-0 = <&pinctrl_charger_chglev>; | ||
19 | active-semi,chglev-gpio = <&pioA 12 GPIO_ACTIVE_HIGH>; | ||
20 | active-semi,input-voltage-threshold-microvolt = <6600>; | ||
21 | active-semi,precondition-timeout = <40>; | ||
22 | active-semi,total-timeout = <3>; | ||
23 | |||
24 | active-semi,vsel-high; | 17 | active-semi,vsel-high; |
25 | 18 | ||
26 | regulators { | 19 | regulators { |
@@ -73,4 +66,19 @@ Example: | |||
73 | regulator-always-on; | 66 | regulator-always-on; |
74 | }; | 67 | }; |
75 | }; | 68 | }; |
69 | |||
70 | charger { | ||
71 | compatible = "active-semi,act8945a-charger"; | ||
72 | pinctrl-names = "default"; | ||
73 | pinctrl-0 = <&pinctrl_charger_chglev &pinctrl_charger_lbo &pinctrl_charger_irq>; | ||
74 | interrupt-parent = <&pioA>; | ||
75 | interrupts = <45 GPIO_ACTIVE_LOW>; | ||
76 | |||
77 | active-semi,chglev-gpios = <&pioA 12 GPIO_ACTIVE_HIGH>; | ||
78 | active-semi,lbo-gpios = <&pioA 72 GPIO_ACTIVE_LOW>; | ||
79 | active-semi,input-voltage-threshold-microvolt = <6600>; | ||
80 | active-semi,precondition-timeout = <40>; | ||
81 | active-semi,total-timeout = <3>; | ||
82 | status = "okay"; | ||
83 | }; | ||
76 | }; | 84 | }; |
diff --git a/Documentation/devicetree/bindings/mfd/arizona.txt b/Documentation/devicetree/bindings/mfd/arizona.txt index a6e2ea41160c..8f2e2822238d 100644 --- a/Documentation/devicetree/bindings/mfd/arizona.txt +++ b/Documentation/devicetree/bindings/mfd/arizona.txt | |||
@@ -85,6 +85,24 @@ Optional properties: | |||
85 | present, the number of values should be less than or equal to the | 85 | present, the number of values should be less than or equal to the |
86 | number of inputs, unspecified inputs will use the chip default. | 86 | number of inputs, unspecified inputs will use the chip default. |
87 | 87 | ||
88 | - wlf,max-channels-clocked : The maximum number of channels to be clocked on | ||
89 | each AIF, useful for I2S systems with multiple data lines being mastered. | ||
90 | Specify one cell for each AIF to be configured, specify zero for AIFs that | ||
91 | should be handled normally. | ||
92 | If present, number of cells must be less than or equal to the number of | ||
93 | AIFs. If less than the number of AIFs, for cells that have not been | ||
94 | specified the corresponding AIFs will be treated as default setting. | ||
95 | |||
96 | - wlf,spk-fmt : PDM speaker data format, must contain 2 cells (OUT5 and OUT6). | ||
97 | See the datasheet for values. | ||
98 | The second cell is ignored for codecs that do not have OUT6 (wm5102, wm8997, | ||
99 | wm8998, wm1814) | ||
100 | |||
101 | - wlf,spk-mute : PDM speaker mute setting, must contain 2 cells (OUT5 and OUT6). | ||
102 | See the datasheet for values. | ||
103 | The second cell is ignored for codecs that do not have OUT6 (wm5102, wm8997, | ||
104 | wm8998, wm1814) | ||
105 | |||
88 | - DCVDD-supply, MICVDD-supply : Power supplies, only need to be specified if | 106 | - DCVDD-supply, MICVDD-supply : Power supplies, only need to be specified if |
89 | they are being externally supplied. As covered in | 107 | they are being externally supplied. As covered in |
90 | Documentation/devicetree/bindings/regulator/regulator.txt | 108 | Documentation/devicetree/bindings/regulator/regulator.txt |
diff --git a/Documentation/devicetree/bindings/mfd/aspeed-scu.txt b/Documentation/devicetree/bindings/mfd/aspeed-scu.txt new file mode 100644 index 000000000000..4fc5b83726d6 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/aspeed-scu.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | The Aspeed System Control Unit manages the global behaviour of the SoC, | ||
2 | configuring elements such as clocks, pinmux, and reset. | ||
3 | |||
4 | Required properties: | ||
5 | - compatible: One of: | ||
6 | "aspeed,ast2400-scu", "syscon", "simple-mfd" | ||
7 | "aspeed,g4-scu", "syscon", "simple-mfd" | ||
8 | "aspeed,ast2500-scu", "syscon", "simple-mfd" | ||
9 | "aspeed,g5-scu", "syscon", "simple-mfd" | ||
10 | |||
11 | - reg: contains the offset and length of the SCU memory region | ||
12 | |||
13 | Example: | ||
14 | |||
15 | syscon: syscon@1e6e2000 { | ||
16 | compatible = "aspeed,ast2400-scu", "syscon", "simple-mfd"; | ||
17 | reg = <0x1e6e2000 0x1a8>; | ||
18 | }; | ||
diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt index 585a95546288..8f3ad9ab4637 100644 --- a/Documentation/devicetree/bindings/mfd/axp20x.txt +++ b/Documentation/devicetree/bindings/mfd/axp20x.txt | |||
@@ -10,7 +10,8 @@ axp809 (X-Powers) | |||
10 | 10 | ||
11 | Required properties: | 11 | Required properties: |
12 | - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209", | 12 | - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209", |
13 | "x-powers,axp221", "x-powers,axp223", "x-powers,axp809" | 13 | "x-powers,axp221", "x-powers,axp223", "x-powers,axp806", |
14 | "x-powers,axp809" | ||
14 | - reg: The I2C slave address or RSB hardware address for the AXP chip | 15 | - reg: The I2C slave address or RSB hardware address for the AXP chip |
15 | - interrupt-parent: The parent interrupt controller | 16 | - interrupt-parent: The parent interrupt controller |
16 | - interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin | 17 | - interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin |
@@ -47,7 +48,6 @@ Optional properties for DCDC regulators: | |||
47 | probably makes sense for HiFi audio related | 48 | probably makes sense for HiFi audio related |
48 | applications that aren't battery constrained. | 49 | applications that aren't battery constrained. |
49 | 50 | ||
50 | |||
51 | AXP202/AXP209 regulators, type, and corresponding input supply names: | 51 | AXP202/AXP209 regulators, type, and corresponding input supply names: |
52 | 52 | ||
53 | Regulator Type Supply Name Notes | 53 | Regulator Type Supply Name Notes |
@@ -86,6 +86,30 @@ LDO_IO1 : LDO : ips-supply : GPIO 1 | |||
86 | RTC_LDO : LDO : ips-supply : always on | 86 | RTC_LDO : LDO : ips-supply : always on |
87 | DRIVEVBUS : Enable output : drivevbus-supply : external regulator | 87 | DRIVEVBUS : Enable output : drivevbus-supply : external regulator |
88 | 88 | ||
89 | AXP806 regulators, type, and corresponding input supply names: | ||
90 | |||
91 | Regulator Type Supply Name Notes | ||
92 | --------- ---- ----------- ----- | ||
93 | DCDCA : DC-DC buck : vina-supply : poly-phase capable | ||
94 | DCDCB : DC-DC buck : vinb-supply : poly-phase capable | ||
95 | DCDCC : DC-DC buck : vinc-supply : poly-phase capable | ||
96 | DCDCD : DC-DC buck : vind-supply : poly-phase capable | ||
97 | DCDCE : DC-DC buck : vine-supply : poly-phase capable | ||
98 | ALDO1 : LDO : aldoin-supply : shared supply | ||
99 | ALDO2 : LDO : aldoin-supply : shared supply | ||
100 | ALDO3 : LDO : aldoin-supply : shared supply | ||
101 | BLDO1 : LDO : bldoin-supply : shared supply | ||
102 | BLDO2 : LDO : bldoin-supply : shared supply | ||
103 | BLDO3 : LDO : bldoin-supply : shared supply | ||
104 | BLDO4 : LDO : bldoin-supply : shared supply | ||
105 | CLDO1 : LDO : cldoin-supply : shared supply | ||
106 | CLDO2 : LDO : cldoin-supply : shared supply | ||
107 | CLDO3 : LDO : cldoin-supply : shared supply | ||
108 | SW : On/Off Switch : swin-supply | ||
109 | |||
110 | Additionally, the AXP806 DC-DC regulators support poly-phase arrangements | ||
111 | for higher output current. The possible groupings are: A+B, A+B+C, D+E. | ||
112 | |||
89 | AXP809 regulators, type, and corresponding input supply names: | 113 | AXP809 regulators, type, and corresponding input supply names: |
90 | 114 | ||
91 | Regulator Type Supply Name Notes | 115 | Regulator Type Supply Name Notes |
diff --git a/Documentation/devicetree/bindings/mfd/lp873x.txt b/Documentation/devicetree/bindings/mfd/lp873x.txt new file mode 100644 index 000000000000..52766c2035f7 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/lp873x.txt | |||
@@ -0,0 +1,59 @@ | |||
1 | TI LP873X PMIC MFD driver | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: "ti,lp8732", "ti,lp8733" | ||
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 | - regulators: List of child nodes that specify the regulator | ||
11 | initialization data. | ||
12 | Example: | ||
13 | |||
14 | pmic: lp8733@60 { | ||
15 | compatible = "ti,lp8733"; | ||
16 | reg = <0x60>; | ||
17 | gpio-controller; | ||
18 | #gpio-cells = <2>; | ||
19 | |||
20 | regulators { | ||
21 | lp8733_buck0: buck0 { | ||
22 | regulator-name = "lp8733-buck0"; | ||
23 | regulator-min-microvolt = <800000>; | ||
24 | regulator-max-microvolt = <1400000>; | ||
25 | regulator-min-microamp = <1500000>; | ||
26 | regulator-max-microamp = <4000000>; | ||
27 | regulator-ramp-delay = <10000>; | ||
28 | regulator-always-on; | ||
29 | regulator-boot-on; | ||
30 | }; | ||
31 | |||
32 | lp8733_buck1: buck1 { | ||
33 | regulator-name = "lp8733-buck1"; | ||
34 | regulator-min-microvolt = <800000>; | ||
35 | regulator-max-microvolt = <1400000>; | ||
36 | regulator-min-microamp = <1500000>; | ||
37 | regulator-max-microamp = <4000000>; | ||
38 | regulator-ramp-delay = <10000>; | ||
39 | regulator-boot-on; | ||
40 | regulator-always-on; | ||
41 | }; | ||
42 | |||
43 | lp8733_ldo0: ldo0 { | ||
44 | regulator-name = "lp8733-ldo0"; | ||
45 | regulator-min-microvolt = <800000>; | ||
46 | regulator-max-microvolt = <3000000>; | ||
47 | regulator-boot-on; | ||
48 | regulator-always-on; | ||
49 | }; | ||
50 | |||
51 | lp8733_ldo1: ldo1 { | ||
52 | regulator-name = "lp8733-ldo1"; | ||
53 | regulator-min-microvolt = <800000>; | ||
54 | regulator-max-microvolt = <3000000>; | ||
55 | regulator-always-on; | ||
56 | regulator-boot-on; | ||
57 | }; | ||
58 | }; | ||
59 | }; | ||
diff --git a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt index f24f33409164..37a088f9a648 100644 --- a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt +++ b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt | |||
@@ -62,6 +62,7 @@ The below bindings specify the set of valid subnodes. | |||
62 | "qcom,pm8058-rtc" | 62 | "qcom,pm8058-rtc" |
63 | "qcom,pm8921-rtc" | 63 | "qcom,pm8921-rtc" |
64 | "qcom,pm8941-rtc" | 64 | "qcom,pm8941-rtc" |
65 | "qcom,pm8018-rtc" | ||
65 | 66 | ||
66 | - reg: | 67 | - reg: |
67 | Usage: required | 68 | Usage: required |
diff --git a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt index b98b291a31ba..485bc59fcc48 100644 --- a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt +++ b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt | |||
@@ -13,6 +13,7 @@ frequencies. | |||
13 | "qcom,rpm-msm8660" | 13 | "qcom,rpm-msm8660" |
14 | "qcom,rpm-msm8960" | 14 | "qcom,rpm-msm8960" |
15 | "qcom,rpm-ipq8064" | 15 | "qcom,rpm-ipq8064" |
16 | "qcom,rpm-mdm9615" | ||
16 | 17 | ||
17 | - reg: | 18 | - reg: |
18 | Usage: required | 19 | Usage: required |
@@ -59,6 +60,7 @@ Regulator nodes are identified by their compatible: | |||
59 | "qcom,rpm-pm8058-regulators" | 60 | "qcom,rpm-pm8058-regulators" |
60 | "qcom,rpm-pm8901-regulators" | 61 | "qcom,rpm-pm8901-regulators" |
61 | "qcom,rpm-pm8921-regulators" | 62 | "qcom,rpm-pm8921-regulators" |
63 | "qcom,rpm-pm8018-regulators" | ||
62 | 64 | ||
63 | - vdd_l0_l1_lvs-supply: | 65 | - vdd_l0_l1_lvs-supply: |
64 | - vdd_l2_l11_l12-supply: | 66 | - vdd_l2_l11_l12-supply: |
@@ -137,6 +139,15 @@ Regulator nodes are identified by their compatible: | |||
137 | Definition: reference to regulator supplying the input pin, as | 139 | Definition: reference to regulator supplying the input pin, as |
138 | described in the data sheet | 140 | described in the data sheet |
139 | 141 | ||
142 | - vin_lvs1-supply: | ||
143 | - vdd_l7-supply: | ||
144 | - vdd_l8-supply: | ||
145 | - vdd_l9_l10_l11_l12-supply: | ||
146 | Usage: optional (pm8018 only) | ||
147 | Value type: <phandle> | ||
148 | Definition: reference to regulator supplying the input pin, as | ||
149 | described in the data sheet | ||
150 | |||
140 | The regulator node houses sub-nodes for each regulator within the device. Each | 151 | The regulator node houses sub-nodes for each regulator within the device. Each |
141 | sub-node is identified using the node's name, with valid values listed for each | 152 | sub-node is identified using the node's name, with valid values listed for each |
142 | of the pmics below. | 153 | of the pmics below. |
@@ -156,6 +167,10 @@ pm8921: | |||
156 | l29, lvs1, lvs2, lvs3, lvs4, lvs5, lvs6, lvs7, usb-switch, hdmi-switch, | 167 | l29, lvs1, lvs2, lvs3, lvs4, lvs5, lvs6, lvs7, usb-switch, hdmi-switch, |
157 | ncp | 168 | ncp |
158 | 169 | ||
170 | pm8018: | ||
171 | s1, s2, s3, s4, s5, , l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, | ||
172 | l12, l14, lvs1 | ||
173 | |||
159 | The content of each sub-node is defined by the standard binding for regulators - | 174 | The content of each sub-node is defined by the standard binding for regulators - |
160 | see regulator.txt - with additional custom properties described below: | 175 | see regulator.txt - with additional custom properties described below: |
161 | 176 | ||
diff --git a/Documentation/devicetree/bindings/mfd/rk808.txt b/Documentation/devicetree/bindings/mfd/rk808.txt index 4ca6aab4273a..9636ae8d8d41 100644 --- a/Documentation/devicetree/bindings/mfd/rk808.txt +++ b/Documentation/devicetree/bindings/mfd/rk808.txt | |||
@@ -1,7 +1,11 @@ | |||
1 | RK808 Power Management Integrated Circuit | 1 | RK8XX Power Management Integrated Circuit |
2 | |||
3 | The rk8xx family current members: | ||
4 | rk808 | ||
5 | rk818 | ||
2 | 6 | ||
3 | Required properties: | 7 | Required properties: |
4 | - compatible: "rockchip,rk808" | 8 | - compatible: "rockchip,rk808", "rockchip,rk818" |
5 | - reg: I2C slave address | 9 | - reg: I2C slave address |
6 | - interrupt-parent: The parent interrupt controller. | 10 | - interrupt-parent: The parent interrupt controller. |
7 | - interrupts: the interrupt outputs of the controller. | 11 | - interrupts: the interrupt outputs of the controller. |
@@ -13,6 +17,8 @@ Optional properties: | |||
13 | default output clock name | 17 | default output clock name |
14 | - rockchip,system-power-controller: Telling whether or not this pmic is controlling | 18 | - rockchip,system-power-controller: Telling whether or not this pmic is controlling |
15 | the system power. | 19 | the system power. |
20 | |||
21 | Optional RK808 properties: | ||
16 | - vcc1-supply: The input supply for DCDC_REG1 | 22 | - vcc1-supply: The input supply for DCDC_REG1 |
17 | - vcc2-supply: The input supply for DCDC_REG2 | 23 | - vcc2-supply: The input supply for DCDC_REG2 |
18 | - vcc3-supply: The input supply for DCDC_REG3 | 24 | - vcc3-supply: The input supply for DCDC_REG3 |
@@ -29,7 +35,20 @@ Optional properties: | |||
29 | the gpio controller. If DVS GPIOs aren't present, voltage changes will happen | 35 | the gpio controller. If DVS GPIOs aren't present, voltage changes will happen |
30 | very quickly with no slow ramp time. | 36 | very quickly with no slow ramp time. |
31 | 37 | ||
32 | Regulators: All the regulators of RK808 to be instantiated shall be | 38 | Optional RK818 properties: |
39 | - vcc1-supply: The input supply for DCDC_REG1 | ||
40 | - vcc2-supply: The input supply for DCDC_REG2 | ||
41 | - vcc3-supply: The input supply for DCDC_REG3 | ||
42 | - vcc4-supply: The input supply for DCDC_REG4 | ||
43 | - boost-supply: The input supply for DCDC_BOOST | ||
44 | - vcc6-supply: The input supply for LDO_REG1 and LDO_REG2 | ||
45 | - vcc7-supply: The input supply for LDO_REG3, LDO_REG5 and LDO_REG7 | ||
46 | - vcc8-supply: The input supply for LDO_REG4, LDO_REG6 and LDO_REG8 | ||
47 | - vcc9-supply: The input supply for LDO_REG9 and SWITCH_REG | ||
48 | - h_5v-supply: The input supply for HDMI_SWITCH | ||
49 | - usb-supply: The input supply for OTG_SWITCH | ||
50 | |||
51 | Regulators: All the regulators of RK8XX to be instantiated shall be | ||
33 | listed in a child node named 'regulators'. Each regulator is represented | 52 | listed in a child node named 'regulators'. Each regulator is represented |
34 | by a child node of the 'regulators' node. | 53 | by a child node of the 'regulators' node. |
35 | 54 | ||
@@ -48,6 +67,18 @@ number as described in RK808 datasheet. | |||
48 | - SWITCH_REGn | 67 | - SWITCH_REGn |
49 | - valid values for n are 1 to 2 | 68 | - valid values for n are 1 to 2 |
50 | 69 | ||
70 | Following regulators of the RK818 PMIC block are supported. Note that | ||
71 | the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO | ||
72 | number as described in RK818 datasheet. | ||
73 | |||
74 | - DCDC_REGn | ||
75 | - valid values for n are 1 to 4. | ||
76 | - LDO_REGn | ||
77 | - valid values for n are 1 to 9. | ||
78 | - SWITCH_REG | ||
79 | - HDMI_SWITCH | ||
80 | - OTG_SWITCH | ||
81 | |||
51 | Standard regulator bindings are used inside regulator subnodes. Check | 82 | Standard regulator bindings are used inside regulator subnodes. Check |
52 | Documentation/devicetree/bindings/regulator/regulator.txt | 83 | Documentation/devicetree/bindings/regulator/regulator.txt |
53 | for more details | 84 | for more details |
diff --git a/Documentation/devicetree/bindings/mfd/samsung,exynos5433-lpass.txt b/Documentation/devicetree/bindings/mfd/samsung,exynos5433-lpass.txt new file mode 100644 index 000000000000..c110e118b79f --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/samsung,exynos5433-lpass.txt | |||
@@ -0,0 +1,70 @@ | |||
1 | Samsung Exynos SoC Low Power Audio Subsystem (LPASS) | ||
2 | |||
3 | Required properties: | ||
4 | |||
5 | - compatible : "samsung,exynos5433-lpass" | ||
6 | - reg : should contain the LPASS top SFR region location | ||
7 | and size | ||
8 | - samsung,pmu-syscon : the phandle to the Power Management Unit node | ||
9 | - #address-cells : should be 1 | ||
10 | - #size-cells : should be 1 | ||
11 | - ranges : must be present | ||
12 | |||
13 | Each IP block of the Low Power Audio Subsystem should be specified as | ||
14 | an optional sub-node. For "samsung,exynos5433-lpass" compatible this includes: | ||
15 | UART, SLIMBUS, PCM, I2S, DMAC, Timers 0...4, VIC, WDT 0...1 devices. | ||
16 | |||
17 | Bindings of the sub-nodes are described in: | ||
18 | ../serial/samsung_uart.txt | ||
19 | ../sound/samsung-i2s.txt | ||
20 | ../dma/arm-pl330.txt | ||
21 | |||
22 | |||
23 | Example: | ||
24 | |||
25 | audio-subsystem { | ||
26 | compatible = "samsung,exynos5433-lpass"; | ||
27 | reg = <0x11400000 0x100>, <0x11500000 0x08>; | ||
28 | samsung,pmu-syscon = <&pmu_system_controller>; | ||
29 | #address-cells = <1>; | ||
30 | #size-cells = <1>; | ||
31 | ranges; | ||
32 | |||
33 | adma: adma@11420000 { | ||
34 | compatible = "arm,pl330", "arm,primecell"; | ||
35 | reg = <0x11420000 0x1000>; | ||
36 | interrupts = <0 73 0>; | ||
37 | clocks = <&cmu_aud CLK_ACLK_DMAC>; | ||
38 | clock-names = "apb_pclk"; | ||
39 | #dma-cells = <1>; | ||
40 | #dma-channels = <8>; | ||
41 | #dma-requests = <32>; | ||
42 | }; | ||
43 | |||
44 | i2s0: i2s0@11440000 { | ||
45 | compatible = "samsung,exynos7-i2s"; | ||
46 | reg = <0x11440000 0x100>; | ||
47 | dmas = <&adma 0 &adma 2>; | ||
48 | dma-names = "tx", "rx"; | ||
49 | interrupts = <0 70 0>; | ||
50 | clocks = <&cmu_aud CLK_PCLK_AUD_I2S>, | ||
51 | <&cmu_aud CLK_SCLK_AUD_I2S>, | ||
52 | <&cmu_aud CLK_SCLK_I2S_BCLK>; | ||
53 | clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; | ||
54 | pinctrl-names = "default"; | ||
55 | pinctrl-0 = <&i2s0_bus>; | ||
56 | status = "disabled"; | ||
57 | }; | ||
58 | |||
59 | serial_3: serial@11460000 { | ||
60 | compatible = "samsung,exynos5433-uart"; | ||
61 | reg = <0x11460000 0x100>; | ||
62 | interrupts = <0 67 0>; | ||
63 | clocks = <&cmu_aud CLK_PCLK_AUD_UART>, | ||
64 | <&cmu_aud CLK_SCLK_AUD_UART>; | ||
65 | clock-names = "uart", "clk_uart_baud0"; | ||
66 | pinctrl-names = "default"; | ||
67 | pinctrl-0 = <&uart_aud_bus>; | ||
68 | status = "disabled"; | ||
69 | }; | ||
70 | }; | ||
diff --git a/Documentation/devicetree/bindings/mfd/twl6040.txt b/Documentation/devicetree/bindings/mfd/twl6040.txt index e6afdfa3543d..9a98ee7c323d 100644 --- a/Documentation/devicetree/bindings/mfd/twl6040.txt +++ b/Documentation/devicetree/bindings/mfd/twl6040.txt | |||
@@ -12,6 +12,7 @@ Required properties: | |||
12 | - interrupt-parent: The parent interrupt controller | 12 | - interrupt-parent: The parent interrupt controller |
13 | - gpio-controller: | 13 | - gpio-controller: |
14 | - #gpio-cells = <1>: twl6040 provides GPO lines. | 14 | - #gpio-cells = <1>: twl6040 provides GPO lines. |
15 | - #clock-cells = <0>; twl6040 is a provider of pdmclk which is used by McPDM | ||
15 | - twl6040,audpwron-gpio: Power on GPIO line for the twl6040 | 16 | - twl6040,audpwron-gpio: Power on GPIO line for the twl6040 |
16 | 17 | ||
17 | - vio-supply: Regulator for the twl6040 VIO supply | 18 | - vio-supply: Regulator for the twl6040 VIO supply |
diff --git a/MAINTAINERS b/MAINTAINERS index 40f462966564..58c520517107 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -8098,6 +8098,7 @@ MULTIFUNCTION DEVICES (MFD) | |||
8098 | M: Lee Jones <lee.jones@linaro.org> | 8098 | M: Lee Jones <lee.jones@linaro.org> |
8099 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git | 8099 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git |
8100 | S: Supported | 8100 | S: Supported |
8101 | F: Documentation/devicetree/bindings/mfd/ | ||
8101 | F: drivers/mfd/ | 8102 | F: drivers/mfd/ |
8102 | F: include/linux/mfd/ | 8103 | F: include/linux/mfd/ |
8103 | 8104 | ||
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 4b0878f35471..25943e9bc8bf 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/input.h> | 27 | #include <linux/input.h> |
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/notifier.h> | ||
30 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
31 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
32 | #include <linux/input/matrix_keypad.h> | 33 | #include <linux/input/matrix_keypad.h> |
@@ -44,6 +45,7 @@ | |||
44 | * @dev: Device pointer | 45 | * @dev: Device pointer |
45 | * @idev: Input device | 46 | * @idev: Input device |
46 | * @ec: Top level ChromeOS device to use to talk to EC | 47 | * @ec: Top level ChromeOS device to use to talk to EC |
48 | * @notifier: interrupt event notifier for transport devices | ||
47 | */ | 49 | */ |
48 | struct cros_ec_keyb { | 50 | struct cros_ec_keyb { |
49 | unsigned int rows; | 51 | unsigned int rows; |
@@ -57,6 +59,7 @@ struct cros_ec_keyb { | |||
57 | struct device *dev; | 59 | struct device *dev; |
58 | struct input_dev *idev; | 60 | struct input_dev *idev; |
59 | struct cros_ec_device *ec; | 61 | struct cros_ec_device *ec; |
62 | struct notifier_block notifier; | ||
60 | }; | 63 | }; |
61 | 64 | ||
62 | 65 | ||
@@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev, | |||
146 | input_sync(ckdev->idev); | 149 | input_sync(ckdev->idev); |
147 | } | 150 | } |
148 | 151 | ||
149 | static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state) | 152 | static int cros_ec_keyb_open(struct input_dev *dev) |
150 | { | ||
151 | int ret = 0; | ||
152 | struct cros_ec_command *msg; | ||
153 | |||
154 | msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL); | ||
155 | if (!msg) | ||
156 | return -ENOMEM; | ||
157 | |||
158 | msg->version = 0; | ||
159 | msg->command = EC_CMD_MKBP_STATE; | ||
160 | msg->insize = ckdev->cols; | ||
161 | msg->outsize = 0; | ||
162 | |||
163 | ret = cros_ec_cmd_xfer(ckdev->ec, msg); | ||
164 | if (ret < 0) { | ||
165 | dev_err(ckdev->dev, "Error transferring EC message %d\n", ret); | ||
166 | goto exit; | ||
167 | } | ||
168 | |||
169 | memcpy(kb_state, msg->data, ckdev->cols); | ||
170 | exit: | ||
171 | kfree(msg); | ||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | static irqreturn_t cros_ec_keyb_irq(int irq, void *data) | ||
176 | { | 153 | { |
177 | struct cros_ec_keyb *ckdev = data; | 154 | struct cros_ec_keyb *ckdev = input_get_drvdata(dev); |
178 | struct cros_ec_device *ec = ckdev->ec; | ||
179 | int ret; | ||
180 | uint8_t kb_state[ckdev->cols]; | ||
181 | |||
182 | if (device_may_wakeup(ec->dev)) | ||
183 | pm_wakeup_event(ec->dev, 0); | ||
184 | |||
185 | ret = cros_ec_keyb_get_state(ckdev, kb_state); | ||
186 | if (ret >= 0) | ||
187 | cros_ec_keyb_process(ckdev, kb_state, ret); | ||
188 | else | ||
189 | dev_err(ckdev->dev, "failed to get keyboard state: %d\n", ret); | ||
190 | 155 | ||
191 | return IRQ_HANDLED; | 156 | return blocking_notifier_chain_register(&ckdev->ec->event_notifier, |
157 | &ckdev->notifier); | ||
192 | } | 158 | } |
193 | 159 | ||
194 | static int cros_ec_keyb_open(struct input_dev *dev) | 160 | static void cros_ec_keyb_close(struct input_dev *dev) |
195 | { | 161 | { |
196 | struct cros_ec_keyb *ckdev = input_get_drvdata(dev); | 162 | struct cros_ec_keyb *ckdev = input_get_drvdata(dev); |
197 | struct cros_ec_device *ec = ckdev->ec; | ||
198 | 163 | ||
199 | return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq, | 164 | blocking_notifier_chain_unregister(&ckdev->ec->event_notifier, |
200 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | 165 | &ckdev->notifier); |
201 | "cros_ec_keyb", ckdev); | ||
202 | } | 166 | } |
203 | 167 | ||
204 | static void cros_ec_keyb_close(struct input_dev *dev) | 168 | static int cros_ec_keyb_work(struct notifier_block *nb, |
169 | unsigned long queued_during_suspend, void *_notify) | ||
205 | { | 170 | { |
206 | struct cros_ec_keyb *ckdev = input_get_drvdata(dev); | 171 | struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb, |
207 | struct cros_ec_device *ec = ckdev->ec; | 172 | notifier); |
208 | 173 | ||
209 | free_irq(ec->irq, ckdev); | 174 | if (ckdev->ec->event_data.event_type != EC_MKBP_EVENT_KEY_MATRIX) |
175 | return NOTIFY_DONE; | ||
176 | /* | ||
177 | * If EC is not the wake source, discard key state changes during | ||
178 | * suspend. | ||
179 | */ | ||
180 | if (queued_during_suspend) | ||
181 | return NOTIFY_OK; | ||
182 | if (ckdev->ec->event_size != ckdev->cols) { | ||
183 | dev_err(ckdev->dev, | ||
184 | "Discarded incomplete key matrix event.\n"); | ||
185 | return NOTIFY_OK; | ||
186 | } | ||
187 | cros_ec_keyb_process(ckdev, ckdev->ec->event_data.data.key_matrix, | ||
188 | ckdev->ec->event_size); | ||
189 | return NOTIFY_OK; | ||
210 | } | 190 | } |
211 | 191 | ||
212 | /* | 192 | /* |
@@ -265,12 +245,8 @@ static int cros_ec_keyb_probe(struct platform_device *pdev) | |||
265 | if (!idev) | 245 | if (!idev) |
266 | return -ENOMEM; | 246 | return -ENOMEM; |
267 | 247 | ||
268 | if (!ec->irq) { | ||
269 | dev_err(dev, "no EC IRQ specified\n"); | ||
270 | return -EINVAL; | ||
271 | } | ||
272 | |||
273 | ckdev->ec = ec; | 248 | ckdev->ec = ec; |
249 | ckdev->notifier.notifier_call = cros_ec_keyb_work; | ||
274 | ckdev->dev = dev; | 250 | ckdev->dev = dev; |
275 | dev_set_drvdata(dev, ckdev); | 251 | dev_set_drvdata(dev, ckdev); |
276 | 252 | ||
@@ -311,54 +287,6 @@ static int cros_ec_keyb_probe(struct platform_device *pdev) | |||
311 | return 0; | 287 | return 0; |
312 | } | 288 | } |
313 | 289 | ||
314 | #ifdef CONFIG_PM_SLEEP | ||
315 | /* Clear any keys in the buffer */ | ||
316 | static void cros_ec_keyb_clear_keyboard(struct cros_ec_keyb *ckdev) | ||
317 | { | ||
318 | uint8_t old_state[ckdev->cols]; | ||
319 | uint8_t new_state[ckdev->cols]; | ||
320 | unsigned long duration; | ||
321 | int i, ret; | ||
322 | |||
323 | /* | ||
324 | * Keep reading until we see that the scan state does not change. | ||
325 | * That indicates that we are done. | ||
326 | * | ||
327 | * Assume that the EC keyscan buffer is at most 32 deep. | ||
328 | */ | ||
329 | duration = jiffies; | ||
330 | ret = cros_ec_keyb_get_state(ckdev, new_state); | ||
331 | for (i = 1; !ret && i < 32; i++) { | ||
332 | memcpy(old_state, new_state, sizeof(old_state)); | ||
333 | ret = cros_ec_keyb_get_state(ckdev, new_state); | ||
334 | if (0 == memcmp(old_state, new_state, sizeof(old_state))) | ||
335 | break; | ||
336 | } | ||
337 | duration = jiffies - duration; | ||
338 | dev_info(ckdev->dev, "Discarded %d keyscan(s) in %dus\n", i, | ||
339 | jiffies_to_usecs(duration)); | ||
340 | } | ||
341 | |||
342 | static int cros_ec_keyb_resume(struct device *dev) | ||
343 | { | ||
344 | struct cros_ec_keyb *ckdev = dev_get_drvdata(dev); | ||
345 | |||
346 | /* | ||
347 | * When the EC is not a wake source, then it could not have caused the | ||
348 | * resume, so we clear the EC's key scan buffer. If the EC was a | ||
349 | * wake source (e.g. the lid is open and the user might press a key to | ||
350 | * wake) then the key scan buffer should be preserved. | ||
351 | */ | ||
352 | if (!ckdev->ec->was_wake_device) | ||
353 | cros_ec_keyb_clear_keyboard(ckdev); | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | #endif | ||
359 | |||
360 | static SIMPLE_DEV_PM_OPS(cros_ec_keyb_pm_ops, NULL, cros_ec_keyb_resume); | ||
361 | |||
362 | #ifdef CONFIG_OF | 290 | #ifdef CONFIG_OF |
363 | static const struct of_device_id cros_ec_keyb_of_match[] = { | 291 | static const struct of_device_id cros_ec_keyb_of_match[] = { |
364 | { .compatible = "google,cros-ec-keyb" }, | 292 | { .compatible = "google,cros-ec-keyb" }, |
@@ -372,7 +300,6 @@ static struct platform_driver cros_ec_keyb_driver = { | |||
372 | .driver = { | 300 | .driver = { |
373 | .name = "cros-ec-keyb", | 301 | .name = "cros-ec-keyb", |
374 | .of_match_table = of_match_ptr(cros_ec_keyb_of_match), | 302 | .of_match_table = of_match_ptr(cros_ec_keyb_of_match), |
375 | .pm = &cros_ec_keyb_pm_ops, | ||
376 | }, | 303 | }, |
377 | }; | 304 | }; |
378 | 305 | ||
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 2caf7e967390..c6df6442ba2b 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -50,7 +50,7 @@ config MFD_AS3711 | |||
50 | Support for the AS3711 PMIC from AMS | 50 | Support for the AS3711 PMIC from AMS |
51 | 51 | ||
52 | config MFD_AS3722 | 52 | config MFD_AS3722 |
53 | bool "ams AS3722 Power Management IC" | 53 | tristate "ams AS3722 Power Management IC" |
54 | select MFD_CORE | 54 | select MFD_CORE |
55 | select REGMAP_I2C | 55 | select REGMAP_I2C |
56 | select REGMAP_IRQ | 56 | select REGMAP_IRQ |
@@ -112,6 +112,16 @@ config MFD_BCM590XX | |||
112 | help | 112 | help |
113 | Support for the BCM590xx PMUs from Broadcom | 113 | Support for the BCM590xx PMUs from Broadcom |
114 | 114 | ||
115 | config MFD_AC100 | ||
116 | tristate "X-Powers AC100" | ||
117 | select MFD_CORE | ||
118 | depends on SUNXI_RSB | ||
119 | help | ||
120 | If you say Y here you get support for the X-Powers AC100 audio codec | ||
121 | IC. | ||
122 | This driver include only the core APIs. You have to select individual | ||
123 | components like codecs or RTC under the corresponding menus. | ||
124 | |||
115 | config MFD_AXP20X | 125 | config MFD_AXP20X |
116 | tristate | 126 | tristate |
117 | select MFD_CORE | 127 | select MFD_CORE |
@@ -281,6 +291,14 @@ config MFD_DLN2 | |||
281 | etc. must be enabled in order to use the functionality of | 291 | etc. must be enabled in order to use the functionality of |
282 | the device. | 292 | the device. |
283 | 293 | ||
294 | config MFD_EXYNOS_LPASS | ||
295 | tristate "Samsung Exynos SoC Low Power Audio Subsystem" | ||
296 | select MFD_CORE | ||
297 | select REGMAP_MMIO | ||
298 | help | ||
299 | Select this option to enable support for Samsung Exynos Low Power | ||
300 | Audio Subsystem. | ||
301 | |||
284 | config MFD_MC13XXX | 302 | config MFD_MC13XXX |
285 | tristate | 303 | tristate |
286 | depends on (SPI_MASTER || I2C) | 304 | depends on (SPI_MASTER || I2C) |
@@ -844,13 +862,13 @@ config MFD_RC5T583 | |||
844 | different functionality of the device. | 862 | different functionality of the device. |
845 | 863 | ||
846 | config MFD_RK808 | 864 | config MFD_RK808 |
847 | tristate "Rockchip RK808 Power Management chip" | 865 | tristate "Rockchip RK808/RK818 Power Management Chip" |
848 | depends on I2C && OF | 866 | depends on I2C && OF |
849 | select MFD_CORE | 867 | select MFD_CORE |
850 | select REGMAP_I2C | 868 | select REGMAP_I2C |
851 | select REGMAP_IRQ | 869 | select REGMAP_IRQ |
852 | help | 870 | help |
853 | If you say yes here you get support for the RK808 | 871 | If you say yes here you get support for the RK808 and RK818 |
854 | Power Management chips. | 872 | Power Management chips. |
855 | This driver provides common support for accessing the device | 873 | This driver provides common support for accessing the device |
856 | through I2C interface. The device supports multiple sub-devices | 874 | through I2C interface. The device supports multiple sub-devices |
@@ -1206,6 +1224,7 @@ config MFD_TPS65217 | |||
1206 | depends on I2C | 1224 | depends on I2C |
1207 | select MFD_CORE | 1225 | select MFD_CORE |
1208 | select REGMAP_I2C | 1226 | select REGMAP_I2C |
1227 | select IRQ_DOMAIN | ||
1209 | help | 1228 | help |
1210 | If you say yes here you get support for the TPS65217 series of | 1229 | If you say yes here you get support for the TPS65217 series of |
1211 | Power Management / White LED chips. | 1230 | Power Management / White LED chips. |
@@ -1555,6 +1574,7 @@ config MFD_WM8350 | |||
1555 | config MFD_WM8350_I2C | 1574 | config MFD_WM8350_I2C |
1556 | bool "Wolfson Microelectronics WM8350 with I2C" | 1575 | bool "Wolfson Microelectronics WM8350 with I2C" |
1557 | select MFD_WM8350 | 1576 | select MFD_WM8350 |
1577 | select REGMAP_I2C | ||
1558 | depends on I2C=y | 1578 | depends on I2C=y |
1559 | help | 1579 | help |
1560 | The WM8350 is an integrated audio and power management | 1580 | The WM8350 is an integrated audio and power management |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 2bf6a1ac7428..9834e669d985 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o | |||
13 | obj-$(CONFIG_MFD_CROS_EC) += cros_ec.o | 13 | obj-$(CONFIG_MFD_CROS_EC) += cros_ec.o |
14 | obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o | 14 | obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o |
15 | obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o | 15 | obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o |
16 | obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o | ||
16 | 17 | ||
17 | rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o | 18 | rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o |
18 | obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o | 19 | obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o |
@@ -114,6 +115,8 @@ obj-$(CONFIG_PMIC_DA9052) += da9052-irq.o | |||
114 | obj-$(CONFIG_PMIC_DA9052) += da9052-core.o | 115 | obj-$(CONFIG_PMIC_DA9052) += da9052-core.o |
115 | obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o | 116 | obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o |
116 | obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o | 117 | obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o |
118 | |||
119 | obj-$(CONFIG_MFD_AC100) += ac100.o | ||
117 | obj-$(CONFIG_MFD_AXP20X) += axp20x.o | 120 | obj-$(CONFIG_MFD_AXP20X) += axp20x.o |
118 | obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o | 121 | obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o |
119 | obj-$(CONFIG_MFD_AXP20X_RSB) += axp20x-rsb.o | 122 | obj-$(CONFIG_MFD_AXP20X_RSB) += axp20x-rsb.o |
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 0aecd7bd35f8..acf6c00b14b9 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c | |||
@@ -153,14 +153,14 @@ static struct hwreg_cfg hwreg_cfg = { | |||
153 | 153 | ||
154 | #define AB8500_NAME_STRING "ab8500" | 154 | #define AB8500_NAME_STRING "ab8500" |
155 | #define AB8500_ADC_NAME_STRING "gpadc" | 155 | #define AB8500_ADC_NAME_STRING "gpadc" |
156 | #define AB8500_NUM_BANKS 24 | 156 | #define AB8500_NUM_BANKS AB8500_DEBUG_FIELD_LAST |
157 | 157 | ||
158 | #define AB8500_REV_REG 0x80 | 158 | #define AB8500_REV_REG 0x80 |
159 | 159 | ||
160 | static struct ab8500_prcmu_ranges *debug_ranges; | 160 | static struct ab8500_prcmu_ranges *debug_ranges; |
161 | 161 | ||
162 | static struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = { | 162 | static struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = { |
163 | [0x0] = { | 163 | [AB8500_M_FSM_RANK] = { |
164 | .num_ranges = 0, | 164 | .num_ranges = 0, |
165 | .range = NULL, | 165 | .range = NULL, |
166 | }, | 166 | }, |
@@ -315,7 +315,7 @@ static struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = { | |||
315 | }, | 315 | }, |
316 | }, | 316 | }, |
317 | }, | 317 | }, |
318 | [0x9] = { | 318 | [AB8500_RESERVED] = { |
319 | .num_ranges = 0, | 319 | .num_ranges = 0, |
320 | .range = NULL, | 320 | .range = NULL, |
321 | }, | 321 | }, |
@@ -386,24 +386,6 @@ static struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = { | |||
386 | }, | 386 | }, |
387 | }, | 387 | }, |
388 | }, | 388 | }, |
389 | [AB8500_DEVELOPMENT] = { | ||
390 | .num_ranges = 1, | ||
391 | .range = (struct ab8500_reg_range[]) { | ||
392 | { | ||
393 | .first = 0x00, | ||
394 | .last = 0x00, | ||
395 | }, | ||
396 | }, | ||
397 | }, | ||
398 | [AB8500_DEBUG] = { | ||
399 | .num_ranges = 1, | ||
400 | .range = (struct ab8500_reg_range[]) { | ||
401 | { | ||
402 | .first = 0x05, | ||
403 | .last = 0x07, | ||
404 | }, | ||
405 | }, | ||
406 | }, | ||
407 | [AB8500_AUDIO] = { | 389 | [AB8500_AUDIO] = { |
408 | .num_ranges = 1, | 390 | .num_ranges = 1, |
409 | .range = (struct ab8500_reg_range[]) { | 391 | .range = (struct ab8500_reg_range[]) { |
@@ -463,19 +445,29 @@ static struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = { | |||
463 | }, | 445 | }, |
464 | }, | 446 | }, |
465 | }, | 447 | }, |
466 | [0x11] = { | 448 | [AB8500_DEVELOPMENT] = { |
467 | .num_ranges = 0, | 449 | .num_ranges = 1, |
468 | .range = NULL, | 450 | .range = (struct ab8500_reg_range[]) { |
451 | { | ||
452 | .first = 0x00, | ||
453 | .last = 0x00, | ||
454 | }, | ||
455 | }, | ||
469 | }, | 456 | }, |
470 | [0x12] = { | 457 | [AB8500_DEBUG] = { |
471 | .num_ranges = 0, | 458 | .num_ranges = 1, |
472 | .range = NULL, | 459 | .range = (struct ab8500_reg_range[]) { |
460 | { | ||
461 | .first = 0x05, | ||
462 | .last = 0x07, | ||
463 | }, | ||
464 | }, | ||
473 | }, | 465 | }, |
474 | [0x13] = { | 466 | [AB8500_PROD_TEST] = { |
475 | .num_ranges = 0, | 467 | .num_ranges = 0, |
476 | .range = NULL, | 468 | .range = NULL, |
477 | }, | 469 | }, |
478 | [0x14] = { | 470 | [AB8500_STE_TEST] = { |
479 | .num_ranges = 0, | 471 | .num_ranges = 0, |
480 | .range = NULL, | 472 | .range = NULL, |
481 | }, | 473 | }, |
@@ -1382,60 +1374,6 @@ void ab8500_dump_all_banks(struct device *dev) | |||
1382 | } | 1374 | } |
1383 | } | 1375 | } |
1384 | 1376 | ||
1385 | /* Space for 500 registers. */ | ||
1386 | #define DUMP_MAX_REGS 700 | ||
1387 | static struct ab8500_register_dump | ||
1388 | { | ||
1389 | u8 bank; | ||
1390 | u8 reg; | ||
1391 | u8 value; | ||
1392 | } ab8500_complete_register_dump[DUMP_MAX_REGS]; | ||
1393 | |||
1394 | /* This shall only be called upon kernel panic! */ | ||
1395 | void ab8500_dump_all_banks_to_mem(void) | ||
1396 | { | ||
1397 | int i, r = 0; | ||
1398 | u8 bank; | ||
1399 | int err = 0; | ||
1400 | |||
1401 | pr_info("Saving all ABB registers for crash analysis.\n"); | ||
1402 | |||
1403 | for (bank = 0; bank < AB8500_NUM_BANKS; bank++) { | ||
1404 | for (i = 0; i < debug_ranges[bank].num_ranges; i++) { | ||
1405 | u8 reg; | ||
1406 | |||
1407 | for (reg = debug_ranges[bank].range[i].first; | ||
1408 | reg <= debug_ranges[bank].range[i].last; | ||
1409 | reg++) { | ||
1410 | u8 value; | ||
1411 | |||
1412 | err = prcmu_abb_read(bank, reg, &value, 1); | ||
1413 | |||
1414 | if (err < 0) | ||
1415 | goto out; | ||
1416 | |||
1417 | ab8500_complete_register_dump[r].bank = bank; | ||
1418 | ab8500_complete_register_dump[r].reg = reg; | ||
1419 | ab8500_complete_register_dump[r].value = value; | ||
1420 | |||
1421 | r++; | ||
1422 | |||
1423 | if (r >= DUMP_MAX_REGS) { | ||
1424 | pr_err("%s: too many register to dump!\n", | ||
1425 | __func__); | ||
1426 | err = -EINVAL; | ||
1427 | goto out; | ||
1428 | } | ||
1429 | } | ||
1430 | } | ||
1431 | } | ||
1432 | out: | ||
1433 | if (err >= 0) | ||
1434 | pr_info("Saved all ABB registers.\n"); | ||
1435 | else | ||
1436 | pr_info("Failed to save all ABB registers.\n"); | ||
1437 | } | ||
1438 | |||
1439 | static int ab8500_all_banks_open(struct inode *inode, struct file *file) | 1377 | static int ab8500_all_banks_open(struct inode *inode, struct file *file) |
1440 | { | 1378 | { |
1441 | struct seq_file *s; | 1379 | struct seq_file *s; |
@@ -1584,18 +1522,10 @@ static u32 num_interrupts[AB8500_MAX_NR_IRQS]; | |||
1584 | static u32 num_wake_interrupts[AB8500_MAX_NR_IRQS]; | 1522 | static u32 num_wake_interrupts[AB8500_MAX_NR_IRQS]; |
1585 | static int num_interrupt_lines; | 1523 | static int num_interrupt_lines; |
1586 | 1524 | ||
1587 | bool __attribute__((weak)) suspend_test_wake_cause_interrupt_is_mine(u32 my_int) | ||
1588 | { | ||
1589 | return false; | ||
1590 | } | ||
1591 | |||
1592 | void ab8500_debug_register_interrupt(int line) | 1525 | void ab8500_debug_register_interrupt(int line) |
1593 | { | 1526 | { |
1594 | if (line < num_interrupt_lines) { | 1527 | if (line < num_interrupt_lines) |
1595 | num_interrupts[line]++; | 1528 | num_interrupts[line]++; |
1596 | if (suspend_test_wake_cause_interrupt_is_mine(irq_ab8500)) | ||
1597 | num_wake_interrupts[line]++; | ||
1598 | } | ||
1599 | } | 1529 | } |
1600 | 1530 | ||
1601 | static int ab8500_interrupts_print(struct seq_file *s, void *p) | 1531 | static int ab8500_interrupts_print(struct seq_file *s, void *p) |
diff --git a/drivers/mfd/ac100.c b/drivers/mfd/ac100.c new file mode 100644 index 000000000000..9bc69cd7807d --- /dev/null +++ b/drivers/mfd/ac100.c | |||
@@ -0,0 +1,137 @@ | |||
1 | /* | ||
2 | * MFD core driver for X-Powers' AC100 Audio Codec IC | ||
3 | * | ||
4 | * The AC100 is a highly integrated audio codec and RTC subsystem designed | ||
5 | * for mobile applications. It has 3 I2S/PCM interfaces, a 2 channel DAC, | ||
6 | * a 2 channel ADC with 5 inputs and a builtin mixer. The RTC subsystem has | ||
7 | * 3 clock outputs. | ||
8 | * | ||
9 | * The audio codec and RTC parts are completely separate, sharing only the | ||
10 | * host interface for access to its registers. | ||
11 | * | ||
12 | * Copyright (2016) Chen-Yu Tsai | ||
13 | * | ||
14 | * Author: Chen-Yu Tsai <wens@csie.org> | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License version 2 as | ||
18 | * published by the Free Software Foundation. | ||
19 | */ | ||
20 | |||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/mfd/core.h> | ||
24 | #include <linux/mfd/ac100.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/of.h> | ||
27 | #include <linux/regmap.h> | ||
28 | #include <linux/sunxi-rsb.h> | ||
29 | |||
30 | static const struct regmap_range ac100_writeable_ranges[] = { | ||
31 | regmap_reg_range(AC100_CHIP_AUDIO_RST, AC100_I2S_SR_CTRL), | ||
32 | regmap_reg_range(AC100_I2S1_CLK_CTRL, AC100_I2S1_MXR_GAIN), | ||
33 | regmap_reg_range(AC100_I2S2_CLK_CTRL, AC100_I2S2_MXR_GAIN), | ||
34 | regmap_reg_range(AC100_I2S3_CLK_CTRL, AC100_I2S3_SIG_PATH_CTRL), | ||
35 | regmap_reg_range(AC100_ADC_DIG_CTRL, AC100_ADC_VOL_CTRL), | ||
36 | regmap_reg_range(AC100_HMIC_CTRL1, AC100_HMIC_STATUS), | ||
37 | regmap_reg_range(AC100_DAC_DIG_CTRL, AC100_DAC_MXR_GAIN), | ||
38 | regmap_reg_range(AC100_ADC_APC_CTRL, AC100_LINEOUT_CTRL), | ||
39 | regmap_reg_range(AC100_ADC_DAP_L_CTRL, AC100_ADC_DAP_OPT), | ||
40 | regmap_reg_range(AC100_DAC_DAP_CTRL, AC100_DAC_DAP_OPT), | ||
41 | regmap_reg_range(AC100_ADC_DAP_ENA, AC100_DAC_DAP_ENA), | ||
42 | regmap_reg_range(AC100_SRC1_CTRL1, AC100_SRC1_CTRL2), | ||
43 | regmap_reg_range(AC100_SRC2_CTRL1, AC100_SRC2_CTRL2), | ||
44 | regmap_reg_range(AC100_CLK32K_ANALOG_CTRL, AC100_CLKOUT_CTRL3), | ||
45 | regmap_reg_range(AC100_RTC_RST, AC100_RTC_UPD), | ||
46 | regmap_reg_range(AC100_ALM_INT_ENA, AC100_ALM_INT_STA), | ||
47 | regmap_reg_range(AC100_ALM_SEC, AC100_RTC_GP(15)), | ||
48 | }; | ||
49 | |||
50 | static const struct regmap_range ac100_volatile_ranges[] = { | ||
51 | regmap_reg_range(AC100_CHIP_AUDIO_RST, AC100_PLL_CTRL2), | ||
52 | regmap_reg_range(AC100_HMIC_STATUS, AC100_HMIC_STATUS), | ||
53 | regmap_reg_range(AC100_ADC_DAP_L_STA, AC100_ADC_DAP_L_STA), | ||
54 | regmap_reg_range(AC100_SRC1_CTRL1, AC100_SRC1_CTRL1), | ||
55 | regmap_reg_range(AC100_SRC1_CTRL3, AC100_SRC2_CTRL1), | ||
56 | regmap_reg_range(AC100_SRC2_CTRL3, AC100_SRC2_CTRL4), | ||
57 | regmap_reg_range(AC100_RTC_RST, AC100_RTC_RST), | ||
58 | regmap_reg_range(AC100_RTC_SEC, AC100_ALM_INT_STA), | ||
59 | regmap_reg_range(AC100_ALM_SEC, AC100_ALM_UPD), | ||
60 | }; | ||
61 | |||
62 | static const struct regmap_access_table ac100_writeable_table = { | ||
63 | .yes_ranges = ac100_writeable_ranges, | ||
64 | .n_yes_ranges = ARRAY_SIZE(ac100_writeable_ranges), | ||
65 | }; | ||
66 | |||
67 | static const struct regmap_access_table ac100_volatile_table = { | ||
68 | .yes_ranges = ac100_volatile_ranges, | ||
69 | .n_yes_ranges = ARRAY_SIZE(ac100_volatile_ranges), | ||
70 | }; | ||
71 | |||
72 | static const struct regmap_config ac100_regmap_config = { | ||
73 | .reg_bits = 8, | ||
74 | .val_bits = 16, | ||
75 | .wr_table = &ac100_writeable_table, | ||
76 | .volatile_table = &ac100_volatile_table, | ||
77 | .max_register = AC100_RTC_GP(15), | ||
78 | .cache_type = REGCACHE_RBTREE, | ||
79 | }; | ||
80 | |||
81 | static struct mfd_cell ac100_cells[] = { | ||
82 | { | ||
83 | .name = "ac100-codec", | ||
84 | .of_compatible = "x-powers,ac100-codec", | ||
85 | }, { | ||
86 | .name = "ac100-rtc", | ||
87 | .of_compatible = "x-powers,ac100-rtc", | ||
88 | }, | ||
89 | }; | ||
90 | |||
91 | static int ac100_rsb_probe(struct sunxi_rsb_device *rdev) | ||
92 | { | ||
93 | struct ac100_dev *ac100; | ||
94 | int ret; | ||
95 | |||
96 | ac100 = devm_kzalloc(&rdev->dev, sizeof(*ac100), GFP_KERNEL); | ||
97 | if (!ac100) | ||
98 | return -ENOMEM; | ||
99 | |||
100 | ac100->dev = &rdev->dev; | ||
101 | sunxi_rsb_device_set_drvdata(rdev, ac100); | ||
102 | |||
103 | ac100->regmap = devm_regmap_init_sunxi_rsb(rdev, &ac100_regmap_config); | ||
104 | if (IS_ERR(ac100->regmap)) { | ||
105 | ret = PTR_ERR(ac100->regmap); | ||
106 | dev_err(ac100->dev, "regmap init failed: %d\n", ret); | ||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | ret = devm_mfd_add_devices(ac100->dev, PLATFORM_DEVID_NONE, ac100_cells, | ||
111 | ARRAY_SIZE(ac100_cells), NULL, 0, NULL); | ||
112 | if (ret) { | ||
113 | dev_err(ac100->dev, "failed to add MFD devices: %d\n", ret); | ||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static const struct of_device_id ac100_of_match[] = { | ||
121 | { .compatible = "x-powers,ac100" }, | ||
122 | { }, | ||
123 | }; | ||
124 | MODULE_DEVICE_TABLE(of, ac100_of_match); | ||
125 | |||
126 | static struct sunxi_rsb_driver ac100_rsb_driver = { | ||
127 | .driver = { | ||
128 | .name = "ac100", | ||
129 | .of_match_table = of_match_ptr(ac100_of_match), | ||
130 | }, | ||
131 | .probe = ac100_rsb_probe, | ||
132 | }; | ||
133 | module_sunxi_rsb_driver(ac100_rsb_driver); | ||
134 | |||
135 | MODULE_DESCRIPTION("Audio codec MFD core driver for AC100"); | ||
136 | MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>"); | ||
137 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/act8945a.c b/drivers/mfd/act8945a.c index 10c6d2da8822..a4024d91da01 100644 --- a/drivers/mfd/act8945a.c +++ b/drivers/mfd/act8945a.c | |||
@@ -23,6 +23,7 @@ static const struct mfd_cell act8945a_devs[] = { | |||
23 | }, | 23 | }, |
24 | { | 24 | { |
25 | .name = "act8945a-charger", | 25 | .name = "act8945a-charger", |
26 | .of_compatible = "active-semi,act8945a-charger", | ||
26 | }, | 27 | }, |
27 | }; | 28 | }; |
28 | 29 | ||
diff --git a/drivers/mfd/altera-a10sr.c b/drivers/mfd/altera-a10sr.c index c05aa4ff57fd..06e1f7fc5605 100644 --- a/drivers/mfd/altera-a10sr.c +++ b/drivers/mfd/altera-a10sr.c | |||
@@ -1,4 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Altera Arria10 DevKit System Resource MFD Driver | ||
3 | * | ||
4 | * Author: Thor Thayer <tthayer@opensource.altera.com> | ||
5 | * | ||
2 | * Copyright Intel Corporation (C) 2014-2016. All Rights Reserved | 6 | * Copyright Intel Corporation (C) 2014-2016. All Rights Reserved |
3 | * | 7 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
@@ -20,7 +24,7 @@ | |||
20 | 24 | ||
21 | #include <linux/mfd/altera-a10sr.h> | 25 | #include <linux/mfd/altera-a10sr.h> |
22 | #include <linux/mfd/core.h> | 26 | #include <linux/mfd/core.h> |
23 | #include <linux/module.h> | 27 | #include <linux/init.h> |
24 | #include <linux/of.h> | 28 | #include <linux/of.h> |
25 | #include <linux/spi/spi.h> | 29 | #include <linux/spi/spi.h> |
26 | 30 | ||
@@ -94,7 +98,7 @@ static bool altr_a10sr_reg_volatile(struct device *dev, unsigned int reg) | |||
94 | } | 98 | } |
95 | } | 99 | } |
96 | 100 | ||
97 | const struct regmap_config altr_a10sr_regmap_config = { | 101 | static const struct regmap_config altr_a10sr_regmap_config = { |
98 | .reg_bits = 8, | 102 | .reg_bits = 8, |
99 | .val_bits = 8, | 103 | .val_bits = 8, |
100 | 104 | ||
@@ -152,7 +156,6 @@ static const struct of_device_id altr_a10sr_spi_of_match[] = { | |||
152 | { .compatible = "altr,a10sr" }, | 156 | { .compatible = "altr,a10sr" }, |
153 | { }, | 157 | { }, |
154 | }; | 158 | }; |
155 | MODULE_DEVICE_TABLE(of, altr_a10sr_spi_of_match); | ||
156 | 159 | ||
157 | static struct spi_driver altr_a10sr_spi_driver = { | 160 | static struct spi_driver altr_a10sr_spi_driver = { |
158 | .probe = altr_a10sr_spi_probe, | 161 | .probe = altr_a10sr_spi_probe, |
@@ -161,9 +164,4 @@ static struct spi_driver altr_a10sr_spi_driver = { | |||
161 | .of_match_table = of_match_ptr(altr_a10sr_spi_of_match), | 164 | .of_match_table = of_match_ptr(altr_a10sr_spi_of_match), |
162 | }, | 165 | }, |
163 | }; | 166 | }; |
164 | 167 | builtin_driver(altr_a10sr_spi_driver, spi_register_driver) | |
165 | module_spi_driver(altr_a10sr_spi_driver); | ||
166 | |||
167 | MODULE_LICENSE("GPL v2"); | ||
168 | MODULE_AUTHOR("Thor Thayer <tthayer@opensource.altera.com>"); | ||
169 | MODULE_DESCRIPTION("Altera Arria10 DevKit System Resource MFD Driver"); | ||
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index e4f97b3c824b..41767f7239bb 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/clk.h> | ||
13 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
14 | #include <linux/err.h> | 15 | #include <linux/err.h> |
15 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
@@ -49,7 +50,15 @@ int arizona_clk32k_enable(struct arizona *arizona) | |||
49 | case ARIZONA_32KZ_MCLK1: | 50 | case ARIZONA_32KZ_MCLK1: |
50 | ret = pm_runtime_get_sync(arizona->dev); | 51 | ret = pm_runtime_get_sync(arizona->dev); |
51 | if (ret != 0) | 52 | if (ret != 0) |
52 | goto out; | 53 | goto err_ref; |
54 | ret = clk_prepare_enable(arizona->mclk[ARIZONA_MCLK1]); | ||
55 | if (ret != 0) | ||
56 | goto err_pm; | ||
57 | break; | ||
58 | case ARIZONA_32KZ_MCLK2: | ||
59 | ret = clk_prepare_enable(arizona->mclk[ARIZONA_MCLK2]); | ||
60 | if (ret != 0) | ||
61 | goto err_ref; | ||
53 | break; | 62 | break; |
54 | } | 63 | } |
55 | 64 | ||
@@ -58,7 +67,9 @@ int arizona_clk32k_enable(struct arizona *arizona) | |||
58 | ARIZONA_CLK_32K_ENA); | 67 | ARIZONA_CLK_32K_ENA); |
59 | } | 68 | } |
60 | 69 | ||
61 | out: | 70 | err_pm: |
71 | pm_runtime_put_sync(arizona->dev); | ||
72 | err_ref: | ||
62 | if (ret != 0) | 73 | if (ret != 0) |
63 | arizona->clk32k_ref--; | 74 | arizona->clk32k_ref--; |
64 | 75 | ||
@@ -83,6 +94,10 @@ int arizona_clk32k_disable(struct arizona *arizona) | |||
83 | switch (arizona->pdata.clk32k_src) { | 94 | switch (arizona->pdata.clk32k_src) { |
84 | case ARIZONA_32KZ_MCLK1: | 95 | case ARIZONA_32KZ_MCLK1: |
85 | pm_runtime_put_sync(arizona->dev); | 96 | pm_runtime_put_sync(arizona->dev); |
97 | clk_disable_unprepare(arizona->mclk[ARIZONA_MCLK1]); | ||
98 | break; | ||
99 | case ARIZONA_32KZ_MCLK2: | ||
100 | clk_disable_unprepare(arizona->mclk[ARIZONA_MCLK2]); | ||
86 | break; | 101 | break; |
87 | } | 102 | } |
88 | } | 103 | } |
@@ -735,7 +750,7 @@ static int arizona_suspend(struct device *dev) | |||
735 | return 0; | 750 | return 0; |
736 | } | 751 | } |
737 | 752 | ||
738 | static int arizona_suspend_late(struct device *dev) | 753 | static int arizona_suspend_noirq(struct device *dev) |
739 | { | 754 | { |
740 | struct arizona *arizona = dev_get_drvdata(dev); | 755 | struct arizona *arizona = dev_get_drvdata(dev); |
741 | 756 | ||
@@ -759,7 +774,7 @@ static int arizona_resume(struct device *dev) | |||
759 | { | 774 | { |
760 | struct arizona *arizona = dev_get_drvdata(dev); | 775 | struct arizona *arizona = dev_get_drvdata(dev); |
761 | 776 | ||
762 | dev_dbg(arizona->dev, "Late resume, reenabling IRQ\n"); | 777 | dev_dbg(arizona->dev, "Resume, reenabling IRQ\n"); |
763 | enable_irq(arizona->irq); | 778 | enable_irq(arizona->irq); |
764 | 779 | ||
765 | return 0; | 780 | return 0; |
@@ -771,10 +786,8 @@ const struct dev_pm_ops arizona_pm_ops = { | |||
771 | arizona_runtime_resume, | 786 | arizona_runtime_resume, |
772 | NULL) | 787 | NULL) |
773 | SET_SYSTEM_SLEEP_PM_OPS(arizona_suspend, arizona_resume) | 788 | SET_SYSTEM_SLEEP_PM_OPS(arizona_suspend, arizona_resume) |
774 | #ifdef CONFIG_PM_SLEEP | 789 | SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(arizona_suspend_noirq, |
775 | .suspend_late = arizona_suspend_late, | 790 | arizona_resume_noirq) |
776 | .resume_noirq = arizona_resume_noirq, | ||
777 | #endif | ||
778 | }; | 791 | }; |
779 | EXPORT_SYMBOL_GPL(arizona_pm_ops); | 792 | EXPORT_SYMBOL_GPL(arizona_pm_ops); |
780 | 793 | ||
@@ -790,35 +803,25 @@ unsigned long arizona_of_get_type(struct device *dev) | |||
790 | } | 803 | } |
791 | EXPORT_SYMBOL_GPL(arizona_of_get_type); | 804 | EXPORT_SYMBOL_GPL(arizona_of_get_type); |
792 | 805 | ||
793 | int arizona_of_get_named_gpio(struct arizona *arizona, const char *prop, | ||
794 | bool mandatory) | ||
795 | { | ||
796 | int gpio; | ||
797 | |||
798 | gpio = of_get_named_gpio(arizona->dev->of_node, prop, 0); | ||
799 | if (gpio < 0) { | ||
800 | if (mandatory) | ||
801 | dev_err(arizona->dev, | ||
802 | "Mandatory DT gpio %s missing/malformed: %d\n", | ||
803 | prop, gpio); | ||
804 | |||
805 | gpio = 0; | ||
806 | } | ||
807 | |||
808 | return gpio; | ||
809 | } | ||
810 | EXPORT_SYMBOL_GPL(arizona_of_get_named_gpio); | ||
811 | |||
812 | static int arizona_of_get_core_pdata(struct arizona *arizona) | 806 | static int arizona_of_get_core_pdata(struct arizona *arizona) |
813 | { | 807 | { |
814 | struct arizona_pdata *pdata = &arizona->pdata; | 808 | struct arizona_pdata *pdata = &arizona->pdata; |
815 | struct property *prop; | 809 | struct property *prop; |
816 | const __be32 *cur; | 810 | const __be32 *cur; |
817 | u32 val; | 811 | u32 val; |
812 | u32 pdm_val[ARIZONA_MAX_PDM_SPK]; | ||
818 | int ret, i; | 813 | int ret, i; |
819 | int count = 0; | 814 | int count = 0; |
820 | 815 | ||
821 | pdata->reset = arizona_of_get_named_gpio(arizona, "wlf,reset", true); | 816 | pdata->reset = of_get_named_gpio(arizona->dev->of_node, "wlf,reset", 0); |
817 | if (pdata->reset == -EPROBE_DEFER) { | ||
818 | return pdata->reset; | ||
819 | } else if (pdata->reset < 0) { | ||
820 | dev_err(arizona->dev, "Reset GPIO missing/malformed: %d\n", | ||
821 | pdata->reset); | ||
822 | |||
823 | pdata->reset = 0; | ||
824 | } | ||
822 | 825 | ||
823 | ret = of_property_read_u32_array(arizona->dev->of_node, | 826 | ret = of_property_read_u32_array(arizona->dev->of_node, |
824 | "wlf,gpio-defaults", | 827 | "wlf,gpio-defaults", |
@@ -871,6 +874,35 @@ static int arizona_of_get_core_pdata(struct arizona *arizona) | |||
871 | count++; | 874 | count++; |
872 | } | 875 | } |
873 | 876 | ||
877 | count = 0; | ||
878 | of_property_for_each_u32(arizona->dev->of_node, | ||
879 | "wlf,max-channels-clocked", | ||
880 | prop, cur, val) { | ||
881 | if (count == ARRAY_SIZE(pdata->max_channels_clocked)) | ||
882 | break; | ||
883 | |||
884 | pdata->max_channels_clocked[count] = val; | ||
885 | count++; | ||
886 | } | ||
887 | |||
888 | ret = of_property_read_u32_array(arizona->dev->of_node, | ||
889 | "wlf,spk-fmt", | ||
890 | pdm_val, | ||
891 | ARRAY_SIZE(pdm_val)); | ||
892 | |||
893 | if (ret >= 0) | ||
894 | for (count = 0; count < ARRAY_SIZE(pdata->spk_fmt); ++count) | ||
895 | pdata->spk_fmt[count] = pdm_val[count]; | ||
896 | |||
897 | ret = of_property_read_u32_array(arizona->dev->of_node, | ||
898 | "wlf,spk-mute", | ||
899 | pdm_val, | ||
900 | ARRAY_SIZE(pdm_val)); | ||
901 | |||
902 | if (ret >= 0) | ||
903 | for (count = 0; count < ARRAY_SIZE(pdata->spk_mute); ++count) | ||
904 | pdata->spk_mute[count] = pdm_val[count]; | ||
905 | |||
874 | return 0; | 906 | return 0; |
875 | } | 907 | } |
876 | 908 | ||
@@ -1000,6 +1032,7 @@ static const struct mfd_cell wm8998_devs[] = { | |||
1000 | 1032 | ||
1001 | int arizona_dev_init(struct arizona *arizona) | 1033 | int arizona_dev_init(struct arizona *arizona) |
1002 | { | 1034 | { |
1035 | const char * const mclk_name[] = { "mclk1", "mclk2" }; | ||
1003 | struct device *dev = arizona->dev; | 1036 | struct device *dev = arizona->dev; |
1004 | const char *type_name = NULL; | 1037 | const char *type_name = NULL; |
1005 | unsigned int reg, val, mask; | 1038 | unsigned int reg, val, mask; |
@@ -1010,11 +1043,24 @@ int arizona_dev_init(struct arizona *arizona) | |||
1010 | dev_set_drvdata(arizona->dev, arizona); | 1043 | dev_set_drvdata(arizona->dev, arizona); |
1011 | mutex_init(&arizona->clk_lock); | 1044 | mutex_init(&arizona->clk_lock); |
1012 | 1045 | ||
1013 | if (dev_get_platdata(arizona->dev)) | 1046 | if (dev_get_platdata(arizona->dev)) { |
1014 | memcpy(&arizona->pdata, dev_get_platdata(arizona->dev), | 1047 | memcpy(&arizona->pdata, dev_get_platdata(arizona->dev), |
1015 | sizeof(arizona->pdata)); | 1048 | sizeof(arizona->pdata)); |
1016 | else | 1049 | } else { |
1017 | arizona_of_get_core_pdata(arizona); | 1050 | ret = arizona_of_get_core_pdata(arizona); |
1051 | if (ret < 0) | ||
1052 | return ret; | ||
1053 | } | ||
1054 | |||
1055 | BUILD_BUG_ON(ARRAY_SIZE(arizona->mclk) != ARRAY_SIZE(mclk_name)); | ||
1056 | for (i = 0; i < ARRAY_SIZE(arizona->mclk); i++) { | ||
1057 | arizona->mclk[i] = devm_clk_get(arizona->dev, mclk_name[i]); | ||
1058 | if (IS_ERR(arizona->mclk[i])) { | ||
1059 | dev_info(arizona->dev, "Failed to get %s: %ld\n", | ||
1060 | mclk_name[i], PTR_ERR(arizona->mclk[i])); | ||
1061 | arizona->mclk[i] = NULL; | ||
1062 | } | ||
1063 | } | ||
1018 | 1064 | ||
1019 | regcache_cache_only(arizona->regmap, true); | 1065 | regcache_cache_only(arizona->regmap, true); |
1020 | 1066 | ||
@@ -1035,7 +1081,7 @@ int arizona_dev_init(struct arizona *arizona) | |||
1035 | default: | 1081 | default: |
1036 | dev_err(arizona->dev, "Unknown device type %d\n", | 1082 | dev_err(arizona->dev, "Unknown device type %d\n", |
1037 | arizona->type); | 1083 | arizona->type); |
1038 | return -EINVAL; | 1084 | return -ENODEV; |
1039 | } | 1085 | } |
1040 | 1086 | ||
1041 | /* Mark DCVDD as external, LDO1 driver will clear if internal */ | 1087 | /* Mark DCVDD as external, LDO1 driver will clear if internal */ |
@@ -1121,6 +1167,7 @@ int arizona_dev_init(struct arizona *arizona) | |||
1121 | break; | 1167 | break; |
1122 | default: | 1168 | default: |
1123 | dev_err(arizona->dev, "Unknown device ID: %x\n", reg); | 1169 | dev_err(arizona->dev, "Unknown device ID: %x\n", reg); |
1170 | ret = -ENODEV; | ||
1124 | goto err_reset; | 1171 | goto err_reset; |
1125 | } | 1172 | } |
1126 | 1173 | ||
@@ -1280,12 +1327,14 @@ int arizona_dev_init(struct arizona *arizona) | |||
1280 | break; | 1327 | break; |
1281 | default: | 1328 | default: |
1282 | dev_err(arizona->dev, "Unknown device ID %x\n", reg); | 1329 | dev_err(arizona->dev, "Unknown device ID %x\n", reg); |
1330 | ret = -ENODEV; | ||
1283 | goto err_reset; | 1331 | goto err_reset; |
1284 | } | 1332 | } |
1285 | 1333 | ||
1286 | if (!subdevs) { | 1334 | if (!subdevs) { |
1287 | dev_err(arizona->dev, | 1335 | dev_err(arizona->dev, |
1288 | "No kernel support for device ID %x\n", reg); | 1336 | "No kernel support for device ID %x\n", reg); |
1337 | ret = -ENODEV; | ||
1289 | goto err_reset; | 1338 | goto err_reset; |
1290 | } | 1339 | } |
1291 | 1340 | ||
diff --git a/drivers/mfd/atmel-hlcdc.c b/drivers/mfd/atmel-hlcdc.c index eca7ea69b81c..4b15b0840f16 100644 --- a/drivers/mfd/atmel-hlcdc.c +++ b/drivers/mfd/atmel-hlcdc.c | |||
@@ -50,8 +50,9 @@ static int regmap_atmel_hlcdc_reg_write(void *context, unsigned int reg, | |||
50 | if (reg <= ATMEL_HLCDC_DIS) { | 50 | if (reg <= ATMEL_HLCDC_DIS) { |
51 | u32 status; | 51 | u32 status; |
52 | 52 | ||
53 | readl_poll_timeout(hregmap->regs + ATMEL_HLCDC_SR, status, | 53 | readl_poll_timeout_atomic(hregmap->regs + ATMEL_HLCDC_SR, |
54 | !(status & ATMEL_HLCDC_SIP), 1, 100); | 54 | status, !(status & ATMEL_HLCDC_SIP), |
55 | 1, 100); | ||
55 | } | 56 | } |
56 | 57 | ||
57 | writel(val, hregmap->regs + reg); | 58 | writel(val, hregmap->regs + reg); |
diff --git a/drivers/mfd/axp20x-rsb.c b/drivers/mfd/axp20x-rsb.c index a407527bcd09..a732cb50bcff 100644 --- a/drivers/mfd/axp20x-rsb.c +++ b/drivers/mfd/axp20x-rsb.c | |||
@@ -61,6 +61,7 @@ static int axp20x_rsb_remove(struct sunxi_rsb_device *rdev) | |||
61 | 61 | ||
62 | static const struct of_device_id axp20x_rsb_of_match[] = { | 62 | static const struct of_device_id axp20x_rsb_of_match[] = { |
63 | { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, | 63 | { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, |
64 | { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID }, | ||
64 | { .compatible = "x-powers,axp809", .data = (void *)AXP809_ID }, | 65 | { .compatible = "x-powers,axp809", .data = (void *)AXP809_ID }, |
65 | { }, | 66 | { }, |
66 | }; | 67 | }; |
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index fd80b0981f0f..ba130be32e61 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c | |||
@@ -38,6 +38,7 @@ static const char * const axp20x_model_names[] = { | |||
38 | "AXP221", | 38 | "AXP221", |
39 | "AXP223", | 39 | "AXP223", |
40 | "AXP288", | 40 | "AXP288", |
41 | "AXP806", | ||
41 | "AXP809", | 42 | "AXP809", |
42 | }; | 43 | }; |
43 | 44 | ||
@@ -129,6 +130,27 @@ static const struct regmap_access_table axp288_volatile_table = { | |||
129 | .n_yes_ranges = ARRAY_SIZE(axp288_volatile_ranges), | 130 | .n_yes_ranges = ARRAY_SIZE(axp288_volatile_ranges), |
130 | }; | 131 | }; |
131 | 132 | ||
133 | static const struct regmap_range axp806_writeable_ranges[] = { | ||
134 | regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_DATACACHE(3)), | ||
135 | regmap_reg_range(AXP806_PWR_OUT_CTRL1, AXP806_CLDO3_V_CTRL), | ||
136 | regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ2_EN), | ||
137 | regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE), | ||
138 | }; | ||
139 | |||
140 | static const struct regmap_range axp806_volatile_ranges[] = { | ||
141 | regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE), | ||
142 | }; | ||
143 | |||
144 | static const struct regmap_access_table axp806_writeable_table = { | ||
145 | .yes_ranges = axp806_writeable_ranges, | ||
146 | .n_yes_ranges = ARRAY_SIZE(axp806_writeable_ranges), | ||
147 | }; | ||
148 | |||
149 | static const struct regmap_access_table axp806_volatile_table = { | ||
150 | .yes_ranges = axp806_volatile_ranges, | ||
151 | .n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges), | ||
152 | }; | ||
153 | |||
132 | static struct resource axp152_pek_resources[] = { | 154 | static struct resource axp152_pek_resources[] = { |
133 | DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"), | 155 | DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"), |
134 | DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"), | 156 | DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"), |
@@ -278,6 +300,15 @@ static const struct regmap_config axp288_regmap_config = { | |||
278 | .cache_type = REGCACHE_RBTREE, | 300 | .cache_type = REGCACHE_RBTREE, |
279 | }; | 301 | }; |
280 | 302 | ||
303 | static const struct regmap_config axp806_regmap_config = { | ||
304 | .reg_bits = 8, | ||
305 | .val_bits = 8, | ||
306 | .wr_table = &axp806_writeable_table, | ||
307 | .volatile_table = &axp806_volatile_table, | ||
308 | .max_register = AXP806_VREF_TEMP_WARN_L, | ||
309 | .cache_type = REGCACHE_RBTREE, | ||
310 | }; | ||
311 | |||
281 | #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \ | 312 | #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \ |
282 | [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) } | 313 | [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) } |
283 | 314 | ||
@@ -409,6 +440,21 @@ static const struct regmap_irq axp288_regmap_irqs[] = { | |||
409 | INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1), | 440 | INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1), |
410 | }; | 441 | }; |
411 | 442 | ||
443 | static const struct regmap_irq axp806_regmap_irqs[] = { | ||
444 | INIT_REGMAP_IRQ(AXP806, DIE_TEMP_HIGH_LV1, 0, 0), | ||
445 | INIT_REGMAP_IRQ(AXP806, DIE_TEMP_HIGH_LV2, 0, 1), | ||
446 | INIT_REGMAP_IRQ(AXP806, DCDCA_V_LOW, 0, 3), | ||
447 | INIT_REGMAP_IRQ(AXP806, DCDCB_V_LOW, 0, 4), | ||
448 | INIT_REGMAP_IRQ(AXP806, DCDCC_V_LOW, 0, 5), | ||
449 | INIT_REGMAP_IRQ(AXP806, DCDCD_V_LOW, 0, 6), | ||
450 | INIT_REGMAP_IRQ(AXP806, DCDCE_V_LOW, 0, 7), | ||
451 | INIT_REGMAP_IRQ(AXP806, PWROK_LONG, 1, 0), | ||
452 | INIT_REGMAP_IRQ(AXP806, PWROK_SHORT, 1, 1), | ||
453 | INIT_REGMAP_IRQ(AXP806, WAKEUP, 1, 4), | ||
454 | INIT_REGMAP_IRQ(AXP806, PWROK_FALL, 1, 5), | ||
455 | INIT_REGMAP_IRQ(AXP806, PWROK_RISE, 1, 6), | ||
456 | }; | ||
457 | |||
412 | static const struct regmap_irq axp809_regmap_irqs[] = { | 458 | static const struct regmap_irq axp809_regmap_irqs[] = { |
413 | INIT_REGMAP_IRQ(AXP809, ACIN_OVER_V, 0, 7), | 459 | INIT_REGMAP_IRQ(AXP809, ACIN_OVER_V, 0, 7), |
414 | INIT_REGMAP_IRQ(AXP809, ACIN_PLUGIN, 0, 6), | 460 | INIT_REGMAP_IRQ(AXP809, ACIN_PLUGIN, 0, 6), |
@@ -494,6 +540,18 @@ static const struct regmap_irq_chip axp288_regmap_irq_chip = { | |||
494 | 540 | ||
495 | }; | 541 | }; |
496 | 542 | ||
543 | static const struct regmap_irq_chip axp806_regmap_irq_chip = { | ||
544 | .name = "axp806", | ||
545 | .status_base = AXP20X_IRQ1_STATE, | ||
546 | .ack_base = AXP20X_IRQ1_STATE, | ||
547 | .mask_base = AXP20X_IRQ1_EN, | ||
548 | .mask_invert = true, | ||
549 | .init_ack_masked = true, | ||
550 | .irqs = axp806_regmap_irqs, | ||
551 | .num_irqs = ARRAY_SIZE(axp806_regmap_irqs), | ||
552 | .num_regs = 2, | ||
553 | }; | ||
554 | |||
497 | static const struct regmap_irq_chip axp809_regmap_irq_chip = { | 555 | static const struct regmap_irq_chip axp809_regmap_irq_chip = { |
498 | .name = "axp809", | 556 | .name = "axp809", |
499 | .status_base = AXP20X_IRQ1_STATE, | 557 | .status_base = AXP20X_IRQ1_STATE, |
@@ -508,6 +566,9 @@ static const struct regmap_irq_chip axp809_regmap_irq_chip = { | |||
508 | 566 | ||
509 | static struct mfd_cell axp20x_cells[] = { | 567 | static struct mfd_cell axp20x_cells[] = { |
510 | { | 568 | { |
569 | .name = "axp20x-gpio", | ||
570 | .of_compatible = "x-powers,axp209-gpio", | ||
571 | }, { | ||
511 | .name = "axp20x-pek", | 572 | .name = "axp20x-pek", |
512 | .num_resources = ARRAY_SIZE(axp20x_pek_resources), | 573 | .num_resources = ARRAY_SIZE(axp20x_pek_resources), |
513 | .resources = axp20x_pek_resources, | 574 | .resources = axp20x_pek_resources, |
@@ -660,12 +721,20 @@ static struct mfd_cell axp288_cells[] = { | |||
660 | }, | 721 | }, |
661 | }; | 722 | }; |
662 | 723 | ||
724 | static struct mfd_cell axp806_cells[] = { | ||
725 | { | ||
726 | .id = 2, | ||
727 | .name = "axp20x-regulator", | ||
728 | }, | ||
729 | }; | ||
730 | |||
663 | static struct mfd_cell axp809_cells[] = { | 731 | static struct mfd_cell axp809_cells[] = { |
664 | { | 732 | { |
665 | .name = "axp20x-pek", | 733 | .name = "axp20x-pek", |
666 | .num_resources = ARRAY_SIZE(axp809_pek_resources), | 734 | .num_resources = ARRAY_SIZE(axp809_pek_resources), |
667 | .resources = axp809_pek_resources, | 735 | .resources = axp809_pek_resources, |
668 | }, { | 736 | }, { |
737 | .id = 1, | ||
669 | .name = "axp20x-regulator", | 738 | .name = "axp20x-regulator", |
670 | }, | 739 | }, |
671 | }; | 740 | }; |
@@ -732,6 +801,12 @@ int axp20x_match_device(struct axp20x_dev *axp20x) | |||
732 | axp20x->regmap_cfg = &axp288_regmap_config; | 801 | axp20x->regmap_cfg = &axp288_regmap_config; |
733 | axp20x->regmap_irq_chip = &axp288_regmap_irq_chip; | 802 | axp20x->regmap_irq_chip = &axp288_regmap_irq_chip; |
734 | break; | 803 | break; |
804 | case AXP806_ID: | ||
805 | axp20x->nr_cells = ARRAY_SIZE(axp806_cells); | ||
806 | axp20x->cells = axp806_cells; | ||
807 | axp20x->regmap_cfg = &axp806_regmap_config; | ||
808 | axp20x->regmap_irq_chip = &axp806_regmap_irq_chip; | ||
809 | break; | ||
735 | case AXP809_ID: | 810 | case AXP809_ID: |
736 | axp20x->nr_cells = ARRAY_SIZE(axp809_cells); | 811 | axp20x->nr_cells = ARRAY_SIZE(axp809_cells); |
737 | axp20x->cells = axp809_cells; | 812 | axp20x->cells = axp809_cells; |
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c index 0eee63542038..abd83424b498 100644 --- a/drivers/mfd/cros_ec.c +++ b/drivers/mfd/cros_ec.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/mfd/core.h> | 24 | #include <linux/mfd/core.h> |
25 | #include <linux/mfd/cros_ec.h> | 25 | #include <linux/mfd/cros_ec.h> |
26 | #include <asm/unaligned.h> | ||
26 | 27 | ||
27 | #define CROS_EC_DEV_EC_INDEX 0 | 28 | #define CROS_EC_DEV_EC_INDEX 0 |
28 | #define CROS_EC_DEV_PD_INDEX 1 | 29 | #define CROS_EC_DEV_PD_INDEX 1 |
@@ -49,11 +50,28 @@ static const struct mfd_cell ec_pd_cell = { | |||
49 | .pdata_size = sizeof(pd_p), | 50 | .pdata_size = sizeof(pd_p), |
50 | }; | 51 | }; |
51 | 52 | ||
53 | static irqreturn_t ec_irq_thread(int irq, void *data) | ||
54 | { | ||
55 | struct cros_ec_device *ec_dev = data; | ||
56 | int ret; | ||
57 | |||
58 | if (device_may_wakeup(ec_dev->dev)) | ||
59 | pm_wakeup_event(ec_dev->dev, 0); | ||
60 | |||
61 | ret = cros_ec_get_next_event(ec_dev); | ||
62 | if (ret > 0) | ||
63 | blocking_notifier_call_chain(&ec_dev->event_notifier, | ||
64 | 0, ec_dev); | ||
65 | return IRQ_HANDLED; | ||
66 | } | ||
67 | |||
52 | int cros_ec_register(struct cros_ec_device *ec_dev) | 68 | int cros_ec_register(struct cros_ec_device *ec_dev) |
53 | { | 69 | { |
54 | struct device *dev = ec_dev->dev; | 70 | struct device *dev = ec_dev->dev; |
55 | int err = 0; | 71 | int err = 0; |
56 | 72 | ||
73 | BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier); | ||
74 | |||
57 | ec_dev->max_request = sizeof(struct ec_params_hello); | 75 | ec_dev->max_request = sizeof(struct ec_params_hello); |
58 | ec_dev->max_response = sizeof(struct ec_response_get_protocol_info); | 76 | ec_dev->max_response = sizeof(struct ec_response_get_protocol_info); |
59 | ec_dev->max_passthru = 0; | 77 | ec_dev->max_passthru = 0; |
@@ -70,13 +88,24 @@ int cros_ec_register(struct cros_ec_device *ec_dev) | |||
70 | 88 | ||
71 | cros_ec_query_all(ec_dev); | 89 | cros_ec_query_all(ec_dev); |
72 | 90 | ||
91 | if (ec_dev->irq) { | ||
92 | err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread, | ||
93 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
94 | "chromeos-ec", ec_dev); | ||
95 | if (err) { | ||
96 | dev_err(dev, "Failed to request IRQ %d: %d", | ||
97 | ec_dev->irq, err); | ||
98 | return err; | ||
99 | } | ||
100 | } | ||
101 | |||
73 | err = mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO, &ec_cell, 1, | 102 | err = mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO, &ec_cell, 1, |
74 | NULL, ec_dev->irq, NULL); | 103 | NULL, ec_dev->irq, NULL); |
75 | if (err) { | 104 | if (err) { |
76 | dev_err(dev, | 105 | dev_err(dev, |
77 | "Failed to register Embedded Controller subdevice %d\n", | 106 | "Failed to register Embedded Controller subdevice %d\n", |
78 | err); | 107 | err); |
79 | return err; | 108 | goto fail_mfd; |
80 | } | 109 | } |
81 | 110 | ||
82 | if (ec_dev->max_passthru) { | 111 | if (ec_dev->max_passthru) { |
@@ -94,7 +123,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev) | |||
94 | dev_err(dev, | 123 | dev_err(dev, |
95 | "Failed to register Power Delivery subdevice %d\n", | 124 | "Failed to register Power Delivery subdevice %d\n", |
96 | err); | 125 | err); |
97 | return err; | 126 | goto fail_mfd; |
98 | } | 127 | } |
99 | } | 128 | } |
100 | 129 | ||
@@ -103,13 +132,18 @@ int cros_ec_register(struct cros_ec_device *ec_dev) | |||
103 | if (err) { | 132 | if (err) { |
104 | mfd_remove_devices(dev); | 133 | mfd_remove_devices(dev); |
105 | dev_err(dev, "Failed to register sub-devices\n"); | 134 | dev_err(dev, "Failed to register sub-devices\n"); |
106 | return err; | 135 | goto fail_mfd; |
107 | } | 136 | } |
108 | } | 137 | } |
109 | 138 | ||
110 | dev_info(dev, "Chrome EC device registered\n"); | 139 | dev_info(dev, "Chrome EC device registered\n"); |
111 | 140 | ||
112 | return 0; | 141 | return 0; |
142 | |||
143 | fail_mfd: | ||
144 | if (ec_dev->irq) | ||
145 | free_irq(ec_dev->irq, ec_dev); | ||
146 | return err; | ||
113 | } | 147 | } |
114 | EXPORT_SYMBOL(cros_ec_register); | 148 | EXPORT_SYMBOL(cros_ec_register); |
115 | 149 | ||
@@ -136,13 +170,31 @@ int cros_ec_suspend(struct cros_ec_device *ec_dev) | |||
136 | } | 170 | } |
137 | EXPORT_SYMBOL(cros_ec_suspend); | 171 | EXPORT_SYMBOL(cros_ec_suspend); |
138 | 172 | ||
173 | static void cros_ec_drain_events(struct cros_ec_device *ec_dev) | ||
174 | { | ||
175 | while (cros_ec_get_next_event(ec_dev) > 0) | ||
176 | blocking_notifier_call_chain(&ec_dev->event_notifier, | ||
177 | 1, ec_dev); | ||
178 | } | ||
179 | |||
139 | int cros_ec_resume(struct cros_ec_device *ec_dev) | 180 | int cros_ec_resume(struct cros_ec_device *ec_dev) |
140 | { | 181 | { |
141 | enable_irq(ec_dev->irq); | 182 | enable_irq(ec_dev->irq); |
142 | 183 | ||
184 | /* | ||
185 | * In some cases, we need to distinguish between events that occur | ||
186 | * during suspend if the EC is not a wake source. For example, | ||
187 | * keypresses during suspend should be discarded if it does not wake | ||
188 | * the system. | ||
189 | * | ||
190 | * If the EC is not a wake source, drain the event queue and mark them | ||
191 | * as "queued during suspend". | ||
192 | */ | ||
143 | if (ec_dev->wake_enabled) { | 193 | if (ec_dev->wake_enabled) { |
144 | disable_irq_wake(ec_dev->irq); | 194 | disable_irq_wake(ec_dev->irq); |
145 | ec_dev->wake_enabled = 0; | 195 | ec_dev->wake_enabled = 0; |
196 | } else { | ||
197 | cros_ec_drain_events(ec_dev); | ||
146 | } | 198 | } |
147 | 199 | ||
148 | return 0; | 200 | return 0; |
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c index ebe9b9477cb2..a518832ed5f5 100644 --- a/drivers/mfd/cros_ec_spi.c +++ b/drivers/mfd/cros_ec_spi.c | |||
@@ -366,7 +366,6 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev, | |||
366 | static int cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev, | 366 | static int cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev, |
367 | struct cros_ec_command *ec_msg) | 367 | struct cros_ec_command *ec_msg) |
368 | { | 368 | { |
369 | struct ec_host_request *request; | ||
370 | struct ec_host_response *response; | 369 | struct ec_host_response *response; |
371 | struct cros_ec_spi *ec_spi = ec_dev->priv; | 370 | struct cros_ec_spi *ec_spi = ec_dev->priv; |
372 | struct spi_transfer trans, trans_delay; | 371 | struct spi_transfer trans, trans_delay; |
@@ -378,7 +377,6 @@ static int cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev, | |||
378 | int ret = 0, final_ret; | 377 | int ret = 0, final_ret; |
379 | 378 | ||
380 | len = cros_ec_prepare_tx(ec_dev, ec_msg); | 379 | len = cros_ec_prepare_tx(ec_dev, ec_msg); |
381 | request = (struct ec_host_request *)ec_dev->dout; | ||
382 | dev_dbg(ec_dev->dev, "prepared, len=%d\n", len); | 380 | dev_dbg(ec_dev->dev, "prepared, len=%d\n", len); |
383 | 381 | ||
384 | /* If it's too soon to do another transaction, wait */ | 382 | /* If it's too soon to do another transaction, wait */ |
diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c index c0bf68a3e614..a88c2065d8ab 100644 --- a/drivers/mfd/da9052-core.c +++ b/drivers/mfd/da9052-core.c | |||
@@ -167,6 +167,7 @@ static bool da9052_reg_writeable(struct device *dev, unsigned int reg) | |||
167 | case DA9052_EVENT_B_REG: | 167 | case DA9052_EVENT_B_REG: |
168 | case DA9052_EVENT_C_REG: | 168 | case DA9052_EVENT_C_REG: |
169 | case DA9052_EVENT_D_REG: | 169 | case DA9052_EVENT_D_REG: |
170 | case DA9052_FAULTLOG_REG: | ||
170 | case DA9052_IRQ_MASK_A_REG: | 171 | case DA9052_IRQ_MASK_A_REG: |
171 | case DA9052_IRQ_MASK_B_REG: | 172 | case DA9052_IRQ_MASK_B_REG: |
172 | case DA9052_IRQ_MASK_C_REG: | 173 | case DA9052_IRQ_MASK_C_REG: |
@@ -541,6 +542,52 @@ const struct regmap_config da9052_regmap_config = { | |||
541 | }; | 542 | }; |
542 | EXPORT_SYMBOL_GPL(da9052_regmap_config); | 543 | EXPORT_SYMBOL_GPL(da9052_regmap_config); |
543 | 544 | ||
545 | static int da9052_clear_fault_log(struct da9052 *da9052) | ||
546 | { | ||
547 | int ret = 0; | ||
548 | int fault_log = 0; | ||
549 | |||
550 | fault_log = da9052_reg_read(da9052, DA9052_FAULTLOG_REG); | ||
551 | if (fault_log < 0) { | ||
552 | dev_err(da9052->dev, | ||
553 | "Cannot read FAULT_LOG %d\n", fault_log); | ||
554 | return fault_log; | ||
555 | } | ||
556 | |||
557 | if (fault_log) { | ||
558 | if (fault_log & DA9052_FAULTLOG_TWDERROR) | ||
559 | dev_dbg(da9052->dev, | ||
560 | "Fault log entry detected: TWD_ERROR\n"); | ||
561 | if (fault_log & DA9052_FAULTLOG_VDDFAULT) | ||
562 | dev_dbg(da9052->dev, | ||
563 | "Fault log entry detected: VDD_FAULT\n"); | ||
564 | if (fault_log & DA9052_FAULTLOG_VDDSTART) | ||
565 | dev_dbg(da9052->dev, | ||
566 | "Fault log entry detected: VDD_START\n"); | ||
567 | if (fault_log & DA9052_FAULTLOG_TEMPOVER) | ||
568 | dev_dbg(da9052->dev, | ||
569 | "Fault log entry detected: TEMP_OVER\n"); | ||
570 | if (fault_log & DA9052_FAULTLOG_KEYSHUT) | ||
571 | dev_dbg(da9052->dev, | ||
572 | "Fault log entry detected: KEY_SHUT\n"); | ||
573 | if (fault_log & DA9052_FAULTLOG_NSDSET) | ||
574 | dev_dbg(da9052->dev, | ||
575 | "Fault log entry detected: nSD_SHUT\n"); | ||
576 | if (fault_log & DA9052_FAULTLOG_WAITSET) | ||
577 | dev_dbg(da9052->dev, | ||
578 | "Fault log entry detected: WAIT_SHUT\n"); | ||
579 | |||
580 | ret = da9052_reg_write(da9052, | ||
581 | DA9052_FAULTLOG_REG, | ||
582 | 0xFF); | ||
583 | if (ret < 0) | ||
584 | dev_err(da9052->dev, | ||
585 | "Cannot reset FAULT_LOG values %d\n", ret); | ||
586 | } | ||
587 | |||
588 | return ret; | ||
589 | } | ||
590 | |||
544 | int da9052_device_init(struct da9052 *da9052, u8 chip_id) | 591 | int da9052_device_init(struct da9052 *da9052, u8 chip_id) |
545 | { | 592 | { |
546 | struct da9052_pdata *pdata = dev_get_platdata(da9052->dev); | 593 | struct da9052_pdata *pdata = dev_get_platdata(da9052->dev); |
@@ -549,6 +596,10 @@ int da9052_device_init(struct da9052 *da9052, u8 chip_id) | |||
549 | mutex_init(&da9052->auxadc_lock); | 596 | mutex_init(&da9052->auxadc_lock); |
550 | init_completion(&da9052->done); | 597 | init_completion(&da9052->done); |
551 | 598 | ||
599 | ret = da9052_clear_fault_log(da9052); | ||
600 | if (ret < 0) | ||
601 | dev_warn(da9052->dev, "Cannot clear FAULT_LOG\n"); | ||
602 | |||
552 | if (pdata && pdata->init != NULL) | 603 | if (pdata && pdata->init != NULL) |
553 | pdata->init(da9052); | 604 | pdata->init(da9052); |
554 | 605 | ||
diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c index af841c165787..6c2870d4e754 100644 --- a/drivers/mfd/da9063-core.c +++ b/drivers/mfd/da9063-core.c | |||
@@ -4,8 +4,8 @@ | |||
4 | * Copyright 2012 Dialog Semiconductors Ltd. | 4 | * Copyright 2012 Dialog Semiconductors Ltd. |
5 | * Copyright 2013 Philipp Zabel, Pengutronix | 5 | * Copyright 2013 Philipp Zabel, Pengutronix |
6 | * | 6 | * |
7 | * Author: Krystian Garbaciak <krystian.garbaciak@diasemi.com>, | 7 | * Author: Krystian Garbaciak, Dialog Semiconductor |
8 | * Michal Hajduk <michal.hajduk@diasemi.com> | 8 | * Author: Michal Hajduk, Dialog Semiconductor |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
11 | * under the terms of the GNU General Public License as published by the | 11 | * under the terms of the GNU General Public License as published by the |
@@ -242,5 +242,6 @@ void da9063_device_exit(struct da9063 *da9063) | |||
242 | } | 242 | } |
243 | 243 | ||
244 | MODULE_DESCRIPTION("PMIC driver for Dialog DA9063"); | 244 | MODULE_DESCRIPTION("PMIC driver for Dialog DA9063"); |
245 | MODULE_AUTHOR("Krystian Garbaciak <krystian.garbaciak@diasemi.com>, Michal Hajduk <michal.hajduk@diasemi.com>"); | 245 | MODULE_AUTHOR("Krystian Garbaciak"); |
246 | MODULE_AUTHOR("Michal Hajduk"); | ||
246 | MODULE_LICENSE("GPL"); | 247 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/mfd/da9063-i2c.c b/drivers/mfd/da9063-i2c.c index 73901084945f..981805a2c521 100644 --- a/drivers/mfd/da9063-i2c.c +++ b/drivers/mfd/da9063-i2c.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * Copyright 2012 Dialog Semiconductor Ltd. | 3 | * Copyright 2012 Dialog Semiconductor Ltd. |
4 | * Copyright 2013 Philipp Zabel, Pengutronix | 4 | * Copyright 2013 Philipp Zabel, Pengutronix |
5 | * | 5 | * |
6 | * Author: Krystian Garbaciak <krystian.garbaciak@diasemi.com> | 6 | * Author: Krystian Garbaciak, Dialog Semiconductor |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms of the GNU General Public License as published by the | 9 | * under the terms of the GNU General Public License as published by the |
diff --git a/drivers/mfd/da9063-irq.c b/drivers/mfd/da9063-irq.c index 7e903fcb8813..207bbfe55449 100644 --- a/drivers/mfd/da9063-irq.c +++ b/drivers/mfd/da9063-irq.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * Copyright 2012 Dialog Semiconductor Ltd. | 3 | * Copyright 2012 Dialog Semiconductor Ltd. |
4 | * Copyright 2013 Philipp Zabel, Pengutronix | 4 | * Copyright 2013 Philipp Zabel, Pengutronix |
5 | * | 5 | * |
6 | * Author: Michal Hajduk <michal.hajduk@diasemi.com> | 6 | * Author: Michal Hajduk, Dialog Semiconductor |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms of the GNU General Public License as published by the | 9 | * under the terms of the GNU General Public License as published by the |
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 388e268b9bcf..ca38a6a14110 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c | |||
@@ -938,25 +938,6 @@ int db8500_prcmu_get_ddr_opp(void) | |||
938 | return readb(PRCM_DDR_SUBSYS_APE_MINBW); | 938 | return readb(PRCM_DDR_SUBSYS_APE_MINBW); |
939 | } | 939 | } |
940 | 940 | ||
941 | /** | ||
942 | * db8500_set_ddr_opp - set the appropriate DDR OPP | ||
943 | * @opp: The new DDR operating point to which transition is to be made | ||
944 | * Returns: 0 on success, non-zero on failure | ||
945 | * | ||
946 | * This function sets the operating point of the DDR. | ||
947 | */ | ||
948 | static bool enable_set_ddr_opp; | ||
949 | int db8500_prcmu_set_ddr_opp(u8 opp) | ||
950 | { | ||
951 | if (opp < DDR_100_OPP || opp > DDR_25_OPP) | ||
952 | return -EINVAL; | ||
953 | /* Changing the DDR OPP can hang the hardware pre-v21 */ | ||
954 | if (enable_set_ddr_opp) | ||
955 | writeb(opp, PRCM_DDR_SUBSYS_APE_MINBW); | ||
956 | |||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | /* Divide the frequency of certain clocks by 2 for APE_50_PARTLY_25_OPP. */ | 941 | /* Divide the frequency of certain clocks by 2 for APE_50_PARTLY_25_OPP. */ |
961 | static void request_even_slower_clocks(bool enable) | 942 | static void request_even_slower_clocks(bool enable) |
962 | { | 943 | { |
diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c index 270e19c0bba1..86eca614507b 100644 --- a/drivers/mfd/dm355evm_msp.c +++ b/drivers/mfd/dm355evm_msp.c | |||
@@ -209,7 +209,7 @@ static struct device *add_child(struct i2c_client *client, const char *name, | |||
209 | status = platform_device_add_data(pdev, pdata, pdata_len); | 209 | status = platform_device_add_data(pdev, pdata, pdata_len); |
210 | if (status < 0) { | 210 | if (status < 0) { |
211 | dev_dbg(&pdev->dev, "can't add platform_data\n"); | 211 | dev_dbg(&pdev->dev, "can't add platform_data\n"); |
212 | goto err; | 212 | goto put_device; |
213 | } | 213 | } |
214 | } | 214 | } |
215 | 215 | ||
@@ -222,19 +222,20 @@ static struct device *add_child(struct i2c_client *client, const char *name, | |||
222 | status = platform_device_add_resources(pdev, &r, 1); | 222 | status = platform_device_add_resources(pdev, &r, 1); |
223 | if (status < 0) { | 223 | if (status < 0) { |
224 | dev_dbg(&pdev->dev, "can't add irq\n"); | 224 | dev_dbg(&pdev->dev, "can't add irq\n"); |
225 | goto err; | 225 | goto put_device; |
226 | } | 226 | } |
227 | } | 227 | } |
228 | 228 | ||
229 | status = platform_device_add(pdev); | 229 | status = platform_device_add(pdev); |
230 | if (status) | ||
231 | goto put_device; | ||
230 | 232 | ||
231 | err: | ||
232 | if (status < 0) { | ||
233 | platform_device_put(pdev); | ||
234 | dev_err(&client->dev, "can't add %s dev\n", name); | ||
235 | return ERR_PTR(status); | ||
236 | } | ||
237 | return &pdev->dev; | 233 | return &pdev->dev; |
234 | |||
235 | put_device: | ||
236 | platform_device_put(pdev); | ||
237 | dev_err(&client->dev, "failed to add device %s\n", name); | ||
238 | return ERR_PTR(status); | ||
238 | } | 239 | } |
239 | 240 | ||
240 | static int add_children(struct i2c_client *client) | 241 | static int add_children(struct i2c_client *client) |
diff --git a/drivers/mfd/exynos-lpass.c b/drivers/mfd/exynos-lpass.c new file mode 100644 index 000000000000..2e064fb8826f --- /dev/null +++ b/drivers/mfd/exynos-lpass.c | |||
@@ -0,0 +1,185 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 - 2016 Samsung Electronics Co., Ltd. | ||
3 | * | ||
4 | * Authors: Inha Song <ideal.song@samsung.com> | ||
5 | * Sylwester Nawrocki <s.nawrocki@samsung.com> | ||
6 | * | ||
7 | * Samsung Exynos SoC series Low Power Audio Subsystem driver. | ||
8 | * | ||
9 | * This module provides regmap for the Top SFR region and instantiates | ||
10 | * devices for IP blocks like DMAC, I2S, UART. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 and | ||
14 | * only version 2 as published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <linux/delay.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/mfd/syscon.h> | ||
21 | #include <linux/mfd/syscon/exynos5-pmu.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/of_platform.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/regmap.h> | ||
26 | #include <linux/types.h> | ||
27 | |||
28 | /* LPASS Top register definitions */ | ||
29 | #define SFR_LPASS_CORE_SW_RESET 0x08 | ||
30 | #define LPASS_SB_SW_RESET BIT(11) | ||
31 | #define LPASS_UART_SW_RESET BIT(10) | ||
32 | #define LPASS_PCM_SW_RESET BIT(9) | ||
33 | #define LPASS_I2S_SW_RESET BIT(8) | ||
34 | #define LPASS_WDT1_SW_RESET BIT(4) | ||
35 | #define LPASS_WDT0_SW_RESET BIT(3) | ||
36 | #define LPASS_TIMER_SW_RESET BIT(2) | ||
37 | #define LPASS_MEM_SW_RESET BIT(1) | ||
38 | #define LPASS_DMA_SW_RESET BIT(0) | ||
39 | |||
40 | #define SFR_LPASS_INTR_CA5_MASK 0x48 | ||
41 | #define SFR_LPASS_INTR_CPU_MASK 0x58 | ||
42 | #define LPASS_INTR_APM BIT(9) | ||
43 | #define LPASS_INTR_MIF BIT(8) | ||
44 | #define LPASS_INTR_TIMER BIT(7) | ||
45 | #define LPASS_INTR_DMA BIT(6) | ||
46 | #define LPASS_INTR_GPIO BIT(5) | ||
47 | #define LPASS_INTR_I2S BIT(4) | ||
48 | #define LPASS_INTR_PCM BIT(3) | ||
49 | #define LPASS_INTR_SLIMBUS BIT(2) | ||
50 | #define LPASS_INTR_UART BIT(1) | ||
51 | #define LPASS_INTR_SFR BIT(0) | ||
52 | |||
53 | struct exynos_lpass { | ||
54 | /* pointer to the Power Management Unit regmap */ | ||
55 | struct regmap *pmu; | ||
56 | /* pointer to the LPASS TOP regmap */ | ||
57 | struct regmap *top; | ||
58 | }; | ||
59 | |||
60 | static void exynos_lpass_core_sw_reset(struct exynos_lpass *lpass, int mask) | ||
61 | { | ||
62 | unsigned int val = 0; | ||
63 | |||
64 | regmap_read(lpass->top, SFR_LPASS_CORE_SW_RESET, &val); | ||
65 | |||
66 | val &= ~mask; | ||
67 | regmap_write(lpass->top, SFR_LPASS_CORE_SW_RESET, val); | ||
68 | |||
69 | usleep_range(100, 150); | ||
70 | |||
71 | val |= mask; | ||
72 | regmap_write(lpass->top, SFR_LPASS_CORE_SW_RESET, val); | ||
73 | } | ||
74 | |||
75 | static void exynos_lpass_enable(struct exynos_lpass *lpass) | ||
76 | { | ||
77 | /* Unmask SFR, DMA and I2S interrupt */ | ||
78 | regmap_write(lpass->top, SFR_LPASS_INTR_CA5_MASK, | ||
79 | LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S); | ||
80 | |||
81 | regmap_write(lpass->top, SFR_LPASS_INTR_CPU_MASK, | ||
82 | LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S); | ||
83 | |||
84 | /* Activate related PADs from retention state */ | ||
85 | regmap_write(lpass->pmu, EXYNOS5433_PAD_RETENTION_AUD_OPTION, | ||
86 | EXYNOS5433_PAD_INITIATE_WAKEUP_FROM_LOWPWR); | ||
87 | |||
88 | exynos_lpass_core_sw_reset(lpass, LPASS_I2S_SW_RESET); | ||
89 | exynos_lpass_core_sw_reset(lpass, LPASS_DMA_SW_RESET); | ||
90 | exynos_lpass_core_sw_reset(lpass, LPASS_MEM_SW_RESET); | ||
91 | } | ||
92 | |||
93 | static void exynos_lpass_disable(struct exynos_lpass *lpass) | ||
94 | { | ||
95 | /* Mask any unmasked IP interrupt sources */ | ||
96 | regmap_write(lpass->top, SFR_LPASS_INTR_CPU_MASK, 0); | ||
97 | regmap_write(lpass->top, SFR_LPASS_INTR_CA5_MASK, 0); | ||
98 | |||
99 | /* Deactivate related PADs from retention state */ | ||
100 | regmap_write(lpass->pmu, EXYNOS5433_PAD_RETENTION_AUD_OPTION, 0); | ||
101 | } | ||
102 | |||
103 | static const struct regmap_config exynos_lpass_reg_conf = { | ||
104 | .reg_bits = 32, | ||
105 | .reg_stride = 4, | ||
106 | .val_bits = 32, | ||
107 | .max_register = 0xfc, | ||
108 | .fast_io = true, | ||
109 | }; | ||
110 | |||
111 | static int exynos_lpass_probe(struct platform_device *pdev) | ||
112 | { | ||
113 | struct device *dev = &pdev->dev; | ||
114 | struct exynos_lpass *lpass; | ||
115 | void __iomem *base_top; | ||
116 | struct resource *res; | ||
117 | |||
118 | lpass = devm_kzalloc(dev, sizeof(*lpass), GFP_KERNEL); | ||
119 | if (!lpass) | ||
120 | return -ENOMEM; | ||
121 | |||
122 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
123 | base_top = devm_ioremap_resource(dev, res); | ||
124 | if (IS_ERR(base_top)) | ||
125 | return PTR_ERR(base_top); | ||
126 | |||
127 | lpass->top = regmap_init_mmio(dev, base_top, | ||
128 | &exynos_lpass_reg_conf); | ||
129 | if (IS_ERR(lpass->top)) { | ||
130 | dev_err(dev, "LPASS top regmap initialization failed\n"); | ||
131 | return PTR_ERR(lpass->top); | ||
132 | } | ||
133 | |||
134 | lpass->pmu = syscon_regmap_lookup_by_phandle(dev->of_node, | ||
135 | "samsung,pmu-syscon"); | ||
136 | if (IS_ERR(lpass->pmu)) { | ||
137 | dev_err(dev, "Failed to lookup PMU regmap\n"); | ||
138 | return PTR_ERR(lpass->pmu); | ||
139 | } | ||
140 | |||
141 | platform_set_drvdata(pdev, lpass); | ||
142 | exynos_lpass_enable(lpass); | ||
143 | |||
144 | return of_platform_populate(dev->of_node, NULL, NULL, dev); | ||
145 | } | ||
146 | |||
147 | static int __maybe_unused exynos_lpass_suspend(struct device *dev) | ||
148 | { | ||
149 | struct exynos_lpass *lpass = dev_get_drvdata(dev); | ||
150 | |||
151 | exynos_lpass_disable(lpass); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static int __maybe_unused exynos_lpass_resume(struct device *dev) | ||
157 | { | ||
158 | struct exynos_lpass *lpass = dev_get_drvdata(dev); | ||
159 | |||
160 | exynos_lpass_enable(lpass); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static SIMPLE_DEV_PM_OPS(lpass_pm_ops, exynos_lpass_suspend, | ||
166 | exynos_lpass_resume); | ||
167 | |||
168 | static const struct of_device_id exynos_lpass_of_match[] = { | ||
169 | { .compatible = "samsung,exynos5433-lpass" }, | ||
170 | { }, | ||
171 | }; | ||
172 | MODULE_DEVICE_TABLE(of, exynos_lpass_of_match); | ||
173 | |||
174 | static struct platform_driver exynos_lpass_driver = { | ||
175 | .driver = { | ||
176 | .name = "exynos-lpass", | ||
177 | .pm = &lpass_pm_ops, | ||
178 | .of_match_table = exynos_lpass_of_match, | ||
179 | }, | ||
180 | .probe = exynos_lpass_probe, | ||
181 | }; | ||
182 | module_platform_driver(exynos_lpass_driver); | ||
183 | |||
184 | MODULE_DESCRIPTION("Samsung Low Power Audio Subsystem driver"); | ||
185 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/intel-lpss-acpi.c b/drivers/mfd/intel-lpss-acpi.c index 7ddc4a9563ea..6bf8d643d942 100644 --- a/drivers/mfd/intel-lpss-acpi.c +++ b/drivers/mfd/intel-lpss-acpi.c | |||
@@ -52,6 +52,18 @@ static const struct intel_lpss_platform_info bxt_i2c_info = { | |||
52 | .properties = bxt_i2c_properties, | 52 | .properties = bxt_i2c_properties, |
53 | }; | 53 | }; |
54 | 54 | ||
55 | static struct property_entry apl_i2c_properties[] = { | ||
56 | PROPERTY_ENTRY_U32("i2c-sda-hold-time-ns", 207), | ||
57 | PROPERTY_ENTRY_U32("i2c-sda-falling-time-ns", 171), | ||
58 | PROPERTY_ENTRY_U32("i2c-scl-falling-time-ns", 208), | ||
59 | { }, | ||
60 | }; | ||
61 | |||
62 | static const struct intel_lpss_platform_info apl_i2c_info = { | ||
63 | .clk_rate = 133000000, | ||
64 | .properties = apl_i2c_properties, | ||
65 | }; | ||
66 | |||
55 | static const struct acpi_device_id intel_lpss_acpi_ids[] = { | 67 | static const struct acpi_device_id intel_lpss_acpi_ids[] = { |
56 | /* SPT */ | 68 | /* SPT */ |
57 | { "INT3446", (kernel_ulong_t)&spt_i2c_info }, | 69 | { "INT3446", (kernel_ulong_t)&spt_i2c_info }, |
@@ -61,7 +73,7 @@ static const struct acpi_device_id intel_lpss_acpi_ids[] = { | |||
61 | { "80860ABC", (kernel_ulong_t)&bxt_info }, | 73 | { "80860ABC", (kernel_ulong_t)&bxt_info }, |
62 | { "80860AC2", (kernel_ulong_t)&bxt_info }, | 74 | { "80860AC2", (kernel_ulong_t)&bxt_info }, |
63 | /* APL */ | 75 | /* APL */ |
64 | { "80865AAC", (kernel_ulong_t)&bxt_i2c_info }, | 76 | { "80865AAC", (kernel_ulong_t)&apl_i2c_info }, |
65 | { "80865ABC", (kernel_ulong_t)&bxt_info }, | 77 | { "80865ABC", (kernel_ulong_t)&bxt_info }, |
66 | { "80865AC2", (kernel_ulong_t)&bxt_info }, | 78 | { "80865AC2", (kernel_ulong_t)&bxt_info }, |
67 | { } | 79 | { } |
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index 1d79a3c9370f..3228fd182a99 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c | |||
@@ -111,6 +111,31 @@ static const struct intel_lpss_platform_info bxt_i2c_info = { | |||
111 | .properties = bxt_i2c_properties, | 111 | .properties = bxt_i2c_properties, |
112 | }; | 112 | }; |
113 | 113 | ||
114 | static struct property_entry apl_i2c_properties[] = { | ||
115 | PROPERTY_ENTRY_U32("i2c-sda-hold-time-ns", 207), | ||
116 | PROPERTY_ENTRY_U32("i2c-sda-falling-time-ns", 171), | ||
117 | PROPERTY_ENTRY_U32("i2c-scl-falling-time-ns", 208), | ||
118 | { }, | ||
119 | }; | ||
120 | |||
121 | static const struct intel_lpss_platform_info apl_i2c_info = { | ||
122 | .clk_rate = 133000000, | ||
123 | .properties = apl_i2c_properties, | ||
124 | }; | ||
125 | |||
126 | static const struct intel_lpss_platform_info kbl_info = { | ||
127 | .clk_rate = 120000000, | ||
128 | }; | ||
129 | |||
130 | static const struct intel_lpss_platform_info kbl_uart_info = { | ||
131 | .clk_rate = 120000000, | ||
132 | .clk_con_id = "baudclk", | ||
133 | }; | ||
134 | |||
135 | static const struct intel_lpss_platform_info kbl_i2c_info = { | ||
136 | .clk_rate = 133000000, | ||
137 | }; | ||
138 | |||
114 | static const struct pci_device_id intel_lpss_pci_ids[] = { | 139 | static const struct pci_device_id intel_lpss_pci_ids[] = { |
115 | /* BXT A-Step */ | 140 | /* BXT A-Step */ |
116 | { PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info }, | 141 | { PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info }, |
@@ -146,14 +171,14 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { | |||
146 | { PCI_VDEVICE(INTEL, 0x1aee), (kernel_ulong_t)&bxt_uart_info }, | 171 | { PCI_VDEVICE(INTEL, 0x1aee), (kernel_ulong_t)&bxt_uart_info }, |
147 | 172 | ||
148 | /* APL */ | 173 | /* APL */ |
149 | { PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&bxt_i2c_info }, | 174 | { PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&apl_i2c_info }, |
150 | { PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&bxt_i2c_info }, | 175 | { PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&apl_i2c_info }, |
151 | { PCI_VDEVICE(INTEL, 0x5ab0), (kernel_ulong_t)&bxt_i2c_info }, | 176 | { PCI_VDEVICE(INTEL, 0x5ab0), (kernel_ulong_t)&apl_i2c_info }, |
152 | { PCI_VDEVICE(INTEL, 0x5ab2), (kernel_ulong_t)&bxt_i2c_info }, | 177 | { PCI_VDEVICE(INTEL, 0x5ab2), (kernel_ulong_t)&apl_i2c_info }, |
153 | { PCI_VDEVICE(INTEL, 0x5ab4), (kernel_ulong_t)&bxt_i2c_info }, | 178 | { PCI_VDEVICE(INTEL, 0x5ab4), (kernel_ulong_t)&apl_i2c_info }, |
154 | { PCI_VDEVICE(INTEL, 0x5ab6), (kernel_ulong_t)&bxt_i2c_info }, | 179 | { PCI_VDEVICE(INTEL, 0x5ab6), (kernel_ulong_t)&apl_i2c_info }, |
155 | { PCI_VDEVICE(INTEL, 0x5ab8), (kernel_ulong_t)&bxt_i2c_info }, | 180 | { PCI_VDEVICE(INTEL, 0x5ab8), (kernel_ulong_t)&apl_i2c_info }, |
156 | { PCI_VDEVICE(INTEL, 0x5aba), (kernel_ulong_t)&bxt_i2c_info }, | 181 | { PCI_VDEVICE(INTEL, 0x5aba), (kernel_ulong_t)&apl_i2c_info }, |
157 | { PCI_VDEVICE(INTEL, 0x5abc), (kernel_ulong_t)&bxt_uart_info }, | 182 | { PCI_VDEVICE(INTEL, 0x5abc), (kernel_ulong_t)&bxt_uart_info }, |
158 | { PCI_VDEVICE(INTEL, 0x5abe), (kernel_ulong_t)&bxt_uart_info }, | 183 | { PCI_VDEVICE(INTEL, 0x5abe), (kernel_ulong_t)&bxt_uart_info }, |
159 | { PCI_VDEVICE(INTEL, 0x5ac0), (kernel_ulong_t)&bxt_uart_info }, | 184 | { PCI_VDEVICE(INTEL, 0x5ac0), (kernel_ulong_t)&bxt_uart_info }, |
@@ -181,6 +206,16 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { | |||
181 | { PCI_VDEVICE(INTEL, 0xa160), (kernel_ulong_t)&spt_i2c_info }, | 206 | { PCI_VDEVICE(INTEL, 0xa160), (kernel_ulong_t)&spt_i2c_info }, |
182 | { PCI_VDEVICE(INTEL, 0xa161), (kernel_ulong_t)&spt_i2c_info }, | 207 | { PCI_VDEVICE(INTEL, 0xa161), (kernel_ulong_t)&spt_i2c_info }, |
183 | { PCI_VDEVICE(INTEL, 0xa166), (kernel_ulong_t)&spt_uart_info }, | 208 | { PCI_VDEVICE(INTEL, 0xa166), (kernel_ulong_t)&spt_uart_info }, |
209 | /* KBL-H */ | ||
210 | { PCI_VDEVICE(INTEL, 0xa2a7), (kernel_ulong_t)&kbl_uart_info }, | ||
211 | { PCI_VDEVICE(INTEL, 0xa2a8), (kernel_ulong_t)&kbl_uart_info }, | ||
212 | { PCI_VDEVICE(INTEL, 0xa2a9), (kernel_ulong_t)&kbl_info }, | ||
213 | { PCI_VDEVICE(INTEL, 0xa2aa), (kernel_ulong_t)&kbl_info }, | ||
214 | { PCI_VDEVICE(INTEL, 0xa2e0), (kernel_ulong_t)&kbl_i2c_info }, | ||
215 | { PCI_VDEVICE(INTEL, 0xa2e1), (kernel_ulong_t)&kbl_i2c_info }, | ||
216 | { PCI_VDEVICE(INTEL, 0xa2e2), (kernel_ulong_t)&kbl_i2c_info }, | ||
217 | { PCI_VDEVICE(INTEL, 0xa2e3), (kernel_ulong_t)&kbl_i2c_info }, | ||
218 | { PCI_VDEVICE(INTEL, 0xa2e6), (kernel_ulong_t)&kbl_uart_info }, | ||
184 | { } | 219 | { } |
185 | }; | 220 | }; |
186 | MODULE_DEVICE_TABLE(pci, intel_lpss_pci_ids); | 221 | MODULE_DEVICE_TABLE(pci, intel_lpss_pci_ids); |
diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c index 25d486c543cb..2017446c5b4b 100644 --- a/drivers/mfd/intel_msic.c +++ b/drivers/mfd/intel_msic.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/err.h> | 12 | #include <linux/err.h> |
13 | #include <linux/gpio.h> | 13 | #include <linux/gpio.h> |
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <linux/module.h> | 15 | #include <linux/init.h> |
16 | #include <linux/mfd/core.h> | 16 | #include <linux/mfd/core.h> |
17 | #include <linux/mfd/intel_msic.h> | 17 | #include <linux/mfd/intel_msic.h> |
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
@@ -449,9 +449,4 @@ static struct platform_driver intel_msic_driver = { | |||
449 | .name = "intel_msic", | 449 | .name = "intel_msic", |
450 | }, | 450 | }, |
451 | }; | 451 | }; |
452 | 452 | builtin_platform_driver(intel_msic_driver); | |
453 | module_platform_driver(intel_msic_driver); | ||
454 | |||
455 | MODULE_DESCRIPTION("Driver for Intel MSIC"); | ||
456 | MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); | ||
457 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c index b9428767e615..43e54b7e908f 100644 --- a/drivers/mfd/intel_soc_pmic_bxtwc.c +++ b/drivers/mfd/intel_soc_pmic_bxtwc.c | |||
@@ -47,6 +47,8 @@ | |||
47 | #define BXTWC_MIRQLVL1 0x4E0E | 47 | #define BXTWC_MIRQLVL1 0x4E0E |
48 | #define BXTWC_MPWRTNIRQ 0x4E0F | 48 | #define BXTWC_MPWRTNIRQ 0x4E0F |
49 | 49 | ||
50 | #define BXTWC_MIRQLVL1_MCHGR BIT(5) | ||
51 | |||
50 | #define BXTWC_MTHRM0IRQ 0x4E12 | 52 | #define BXTWC_MTHRM0IRQ 0x4E12 |
51 | #define BXTWC_MTHRM1IRQ 0x4E13 | 53 | #define BXTWC_MTHRM1IRQ 0x4E13 |
52 | #define BXTWC_MTHRM2IRQ 0x4E14 | 54 | #define BXTWC_MTHRM2IRQ 0x4E14 |
@@ -109,7 +111,7 @@ static const struct regmap_irq bxtwc_regmap_irqs_level2[] = { | |||
109 | REGMAP_IRQ_REG(BXTWC_THRM2_IRQ, 2, 0xff), | 111 | REGMAP_IRQ_REG(BXTWC_THRM2_IRQ, 2, 0xff), |
110 | REGMAP_IRQ_REG(BXTWC_BCU_IRQ, 3, 0x1f), | 112 | REGMAP_IRQ_REG(BXTWC_BCU_IRQ, 3, 0x1f), |
111 | REGMAP_IRQ_REG(BXTWC_ADC_IRQ, 4, 0xff), | 113 | REGMAP_IRQ_REG(BXTWC_ADC_IRQ, 4, 0xff), |
112 | REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 5, 0x1f), | 114 | REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 5, 0x3f), |
113 | REGMAP_IRQ_REG(BXTWC_CHGR1_IRQ, 6, 0x1f), | 115 | REGMAP_IRQ_REG(BXTWC_CHGR1_IRQ, 6, 0x1f), |
114 | REGMAP_IRQ_REG(BXTWC_GPIO0_IRQ, 7, 0xff), | 116 | REGMAP_IRQ_REG(BXTWC_GPIO0_IRQ, 7, 0xff), |
115 | REGMAP_IRQ_REG(BXTWC_GPIO1_IRQ, 8, 0x3f), | 117 | REGMAP_IRQ_REG(BXTWC_GPIO1_IRQ, 8, 0x3f), |
@@ -143,6 +145,10 @@ static struct resource adc_resources[] = { | |||
143 | DEFINE_RES_IRQ_NAMED(BXTWC_ADC_IRQ, "ADC"), | 145 | DEFINE_RES_IRQ_NAMED(BXTWC_ADC_IRQ, "ADC"), |
144 | }; | 146 | }; |
145 | 147 | ||
148 | static struct resource usbc_resources[] = { | ||
149 | DEFINE_RES_IRQ_NAMED(BXTWC_CHGR0_IRQ, "USBC"), | ||
150 | }; | ||
151 | |||
146 | static struct resource charger_resources[] = { | 152 | static struct resource charger_resources[] = { |
147 | DEFINE_RES_IRQ_NAMED(BXTWC_CHGR0_IRQ, "CHARGER"), | 153 | DEFINE_RES_IRQ_NAMED(BXTWC_CHGR0_IRQ, "CHARGER"), |
148 | DEFINE_RES_IRQ_NAMED(BXTWC_CHGR1_IRQ, "CHARGER1"), | 154 | DEFINE_RES_IRQ_NAMED(BXTWC_CHGR1_IRQ, "CHARGER1"), |
@@ -170,6 +176,11 @@ static struct mfd_cell bxt_wc_dev[] = { | |||
170 | .resources = thermal_resources, | 176 | .resources = thermal_resources, |
171 | }, | 177 | }, |
172 | { | 178 | { |
179 | .name = "bxt_wcove_usbc", | ||
180 | .num_resources = ARRAY_SIZE(usbc_resources), | ||
181 | .resources = usbc_resources, | ||
182 | }, | ||
183 | { | ||
173 | .name = "bxt_wcove_ext_charger", | 184 | .name = "bxt_wcove_ext_charger", |
174 | .num_resources = ARRAY_SIZE(charger_resources), | 185 | .num_resources = ARRAY_SIZE(charger_resources), |
175 | .resources = charger_resources, | 186 | .resources = charger_resources, |
@@ -403,6 +414,16 @@ static int bxtwc_probe(struct platform_device *pdev) | |||
403 | goto err_sysfs; | 414 | goto err_sysfs; |
404 | } | 415 | } |
405 | 416 | ||
417 | /* | ||
418 | * There is known hw bug. Upon reset BIT 5 of register | ||
419 | * BXTWC_CHGR_LVL1_IRQ is 0 which is the expected value. However, | ||
420 | * later it's set to 1(masked) automatically by hardware. So we | ||
421 | * have the software workaround here to unmaksed it in order to let | ||
422 | * charger interrutp work. | ||
423 | */ | ||
424 | regmap_update_bits(pmic->regmap, BXTWC_MIRQLVL1, | ||
425 | BXTWC_MIRQLVL1_MCHGR, 0); | ||
426 | |||
406 | return 0; | 427 | return 0; |
407 | 428 | ||
408 | err_sysfs: | 429 | err_sysfs: |
diff --git a/drivers/mfd/lp873x.c b/drivers/mfd/lp873x.c index 9af064c940ee..873c608e6a5d 100644 --- a/drivers/mfd/lp873x.c +++ b/drivers/mfd/lp873x.c | |||
@@ -53,8 +53,6 @@ static int lp873x_probe(struct i2c_client *client, | |||
53 | return ret; | 53 | return ret; |
54 | } | 54 | } |
55 | 55 | ||
56 | mutex_init(&lp873->lock); | ||
57 | |||
58 | ret = regmap_read(lp873->regmap, LP873X_REG_OTP_REV, &otpid); | 56 | ret = regmap_read(lp873->regmap, LP873X_REG_OTP_REV, &otpid); |
59 | if (ret) { | 57 | if (ret) { |
60 | dev_err(lp873->dev, "Failed to read OTP ID\n"); | 58 | dev_err(lp873->dev, "Failed to read OTP ID\n"); |
diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c index 6c245128ab2e..6cbe96b28f42 100644 --- a/drivers/mfd/max14577.c +++ b/drivers/mfd/max14577.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2014 Samsung Electronics | 4 | * Copyright (C) 2014 Samsung Electronics |
5 | * Chanwoo Choi <cw00.choi@samsung.com> | 5 | * Chanwoo Choi <cw00.choi@samsung.com> |
6 | * Krzysztof Kozlowski <k.kozlowski@samsung.com> | 6 | * Krzysztof Kozlowski <krzk@kernel.org> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -569,6 +569,6 @@ static void __exit max14577_i2c_exit(void) | |||
569 | } | 569 | } |
570 | module_exit(max14577_i2c_exit); | 570 | module_exit(max14577_i2c_exit); |
571 | 571 | ||
572 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>"); | 572 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <krzk@kernel.org>"); |
573 | MODULE_DESCRIPTION("Maxim 14577/77836 multi-function core driver"); | 573 | MODULE_DESCRIPTION("Maxim 14577/77836 multi-function core driver"); |
574 | MODULE_LICENSE("GPL"); | 574 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c index b95a46d79b9d..326f17b632a7 100644 --- a/drivers/mfd/max8997-irq.c +++ b/drivers/mfd/max8997-irq.c | |||
@@ -139,7 +139,7 @@ static void max8997_irq_sync_unlock(struct irq_data *data) | |||
139 | mutex_unlock(&max8997->irqlock); | 139 | mutex_unlock(&max8997->irqlock); |
140 | } | 140 | } |
141 | 141 | ||
142 | static const inline struct max8997_irq_data * | 142 | inline static const struct max8997_irq_data * |
143 | irq_to_max8997_irq(struct max8997_dev *max8997, struct irq_data *data) | 143 | irq_to_max8997_irq(struct max8997_dev *max8997, struct irq_data *data) |
144 | { | 144 | { |
145 | return &max8997_irqs[data->hwirq]; | 145 | return &max8997_irqs[data->hwirq]; |
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 1d924d1533c0..7aab376ecb84 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c | |||
@@ -162,7 +162,7 @@ static const char * const port_modes[] = { | |||
162 | * provided port mode string as per the port_modes table. | 162 | * provided port mode string as per the port_modes table. |
163 | * If no match is found it returns -ENODEV | 163 | * If no match is found it returns -ENODEV |
164 | */ | 164 | */ |
165 | static const int omap_usbhs_get_dt_port_mode(const char *mode) | 165 | static int omap_usbhs_get_dt_port_mode(const char *mode) |
166 | { | 166 | { |
167 | int i; | 167 | int i; |
168 | 168 | ||
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c index 1b7ec0870c2a..0e3a2ea25942 100644 --- a/drivers/mfd/pm8921-core.c +++ b/drivers/mfd/pm8921-core.c | |||
@@ -309,6 +309,7 @@ static const struct regmap_config ssbi_regmap_config = { | |||
309 | }; | 309 | }; |
310 | 310 | ||
311 | static const struct of_device_id pm8921_id_table[] = { | 311 | static const struct of_device_id pm8921_id_table[] = { |
312 | { .compatible = "qcom,pm8018", }, | ||
312 | { .compatible = "qcom,pm8058", }, | 313 | { .compatible = "qcom,pm8058", }, |
313 | { .compatible = "qcom,pm8921", }, | 314 | { .compatible = "qcom,pm8921", }, |
314 | { } | 315 | { } |
diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c index 2e44323455dd..52fafea06067 100644 --- a/drivers/mfd/qcom_rpm.c +++ b/drivers/mfd/qcom_rpm.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/mfd/qcom_rpm.h> | 21 | #include <linux/mfd/qcom_rpm.h> |
22 | #include <linux/mfd/syscon.h> | 22 | #include <linux/mfd/syscon.h> |
23 | #include <linux/regmap.h> | 23 | #include <linux/regmap.h> |
24 | #include <linux/clk.h> | ||
24 | 25 | ||
25 | #include <dt-bindings/mfd/qcom-rpm.h> | 26 | #include <dt-bindings/mfd/qcom-rpm.h> |
26 | 27 | ||
@@ -48,6 +49,7 @@ struct qcom_rpm { | |||
48 | struct regmap *ipc_regmap; | 49 | struct regmap *ipc_regmap; |
49 | unsigned ipc_offset; | 50 | unsigned ipc_offset; |
50 | unsigned ipc_bit; | 51 | unsigned ipc_bit; |
52 | struct clk *ramclk; | ||
51 | 53 | ||
52 | struct completion ack; | 54 | struct completion ack; |
53 | struct mutex lock; | 55 | struct mutex lock; |
@@ -388,11 +390,62 @@ static const struct qcom_rpm_data ipq806x_template = { | |||
388 | .ack_sel_size = 7, | 390 | .ack_sel_size = 7, |
389 | }; | 391 | }; |
390 | 392 | ||
393 | static const struct qcom_rpm_resource mdm9615_rpm_resource_table[] = { | ||
394 | [QCOM_RPM_CXO_CLK] = { 25, 9, 5, 1 }, | ||
395 | [QCOM_RPM_SYS_FABRIC_CLK] = { 26, 10, 9, 1 }, | ||
396 | [QCOM_RPM_DAYTONA_FABRIC_CLK] = { 27, 11, 11, 1 }, | ||
397 | [QCOM_RPM_SFPB_CLK] = { 28, 12, 12, 1 }, | ||
398 | [QCOM_RPM_CFPB_CLK] = { 29, 13, 13, 1 }, | ||
399 | [QCOM_RPM_EBI1_CLK] = { 30, 14, 16, 1 }, | ||
400 | [QCOM_RPM_APPS_FABRIC_HALT] = { 31, 15, 22, 2 }, | ||
401 | [QCOM_RPM_APPS_FABRIC_MODE] = { 33, 16, 23, 3 }, | ||
402 | [QCOM_RPM_APPS_FABRIC_IOCTL] = { 36, 17, 24, 1 }, | ||
403 | [QCOM_RPM_APPS_FABRIC_ARB] = { 37, 18, 25, 27 }, | ||
404 | [QCOM_RPM_PM8018_SMPS1] = { 64, 19, 30, 2 }, | ||
405 | [QCOM_RPM_PM8018_SMPS2] = { 66, 21, 31, 2 }, | ||
406 | [QCOM_RPM_PM8018_SMPS3] = { 68, 23, 32, 2 }, | ||
407 | [QCOM_RPM_PM8018_SMPS4] = { 70, 25, 33, 2 }, | ||
408 | [QCOM_RPM_PM8018_SMPS5] = { 72, 27, 34, 2 }, | ||
409 | [QCOM_RPM_PM8018_LDO1] = { 74, 29, 35, 2 }, | ||
410 | [QCOM_RPM_PM8018_LDO2] = { 76, 31, 36, 2 }, | ||
411 | [QCOM_RPM_PM8018_LDO3] = { 78, 33, 37, 2 }, | ||
412 | [QCOM_RPM_PM8018_LDO4] = { 80, 35, 38, 2 }, | ||
413 | [QCOM_RPM_PM8018_LDO5] = { 82, 37, 39, 2 }, | ||
414 | [QCOM_RPM_PM8018_LDO6] = { 84, 39, 40, 2 }, | ||
415 | [QCOM_RPM_PM8018_LDO7] = { 86, 41, 41, 2 }, | ||
416 | [QCOM_RPM_PM8018_LDO8] = { 88, 43, 42, 2 }, | ||
417 | [QCOM_RPM_PM8018_LDO9] = { 90, 45, 43, 2 }, | ||
418 | [QCOM_RPM_PM8018_LDO10] = { 92, 47, 44, 2 }, | ||
419 | [QCOM_RPM_PM8018_LDO11] = { 94, 49, 45, 2 }, | ||
420 | [QCOM_RPM_PM8018_LDO12] = { 96, 51, 46, 2 }, | ||
421 | [QCOM_RPM_PM8018_LDO13] = { 98, 53, 47, 2 }, | ||
422 | [QCOM_RPM_PM8018_LDO14] = { 100, 55, 48, 2 }, | ||
423 | [QCOM_RPM_PM8018_LVS1] = { 102, 57, 49, 1 }, | ||
424 | [QCOM_RPM_PM8018_NCP] = { 103, 58, 80, 2 }, | ||
425 | [QCOM_RPM_CXO_BUFFERS] = { 105, 60, 81, 1 }, | ||
426 | [QCOM_RPM_USB_OTG_SWITCH] = { 106, 61, 82, 1 }, | ||
427 | [QCOM_RPM_HDMI_SWITCH] = { 107, 62, 83, 1 }, | ||
428 | [QCOM_RPM_VOLTAGE_CORNER] = { 109, 64, 87, 1 }, | ||
429 | }; | ||
430 | |||
431 | static const struct qcom_rpm_data mdm9615_template = { | ||
432 | .version = 3, | ||
433 | .resource_table = mdm9615_rpm_resource_table, | ||
434 | .n_resources = ARRAY_SIZE(mdm9615_rpm_resource_table), | ||
435 | .req_ctx_off = 3, | ||
436 | .req_sel_off = 11, | ||
437 | .ack_ctx_off = 15, | ||
438 | .ack_sel_off = 23, | ||
439 | .req_sel_size = 4, | ||
440 | .ack_sel_size = 7, | ||
441 | }; | ||
442 | |||
391 | static const struct of_device_id qcom_rpm_of_match[] = { | 443 | static const struct of_device_id qcom_rpm_of_match[] = { |
392 | { .compatible = "qcom,rpm-apq8064", .data = &apq8064_template }, | 444 | { .compatible = "qcom,rpm-apq8064", .data = &apq8064_template }, |
393 | { .compatible = "qcom,rpm-msm8660", .data = &msm8660_template }, | 445 | { .compatible = "qcom,rpm-msm8660", .data = &msm8660_template }, |
394 | { .compatible = "qcom,rpm-msm8960", .data = &msm8960_template }, | 446 | { .compatible = "qcom,rpm-msm8960", .data = &msm8960_template }, |
395 | { .compatible = "qcom,rpm-ipq8064", .data = &ipq806x_template }, | 447 | { .compatible = "qcom,rpm-ipq8064", .data = &ipq806x_template }, |
448 | { .compatible = "qcom,rpm-mdm9615", .data = &mdm9615_template }, | ||
396 | { } | 449 | { } |
397 | }; | 450 | }; |
398 | MODULE_DEVICE_TABLE(of, qcom_rpm_of_match); | 451 | MODULE_DEVICE_TABLE(of, qcom_rpm_of_match); |
@@ -501,6 +554,20 @@ static int qcom_rpm_probe(struct platform_device *pdev) | |||
501 | mutex_init(&rpm->lock); | 554 | mutex_init(&rpm->lock); |
502 | init_completion(&rpm->ack); | 555 | init_completion(&rpm->ack); |
503 | 556 | ||
557 | /* Enable message RAM clock */ | ||
558 | rpm->ramclk = devm_clk_get(&pdev->dev, "ram"); | ||
559 | if (IS_ERR(rpm->ramclk)) { | ||
560 | ret = PTR_ERR(rpm->ramclk); | ||
561 | if (ret == -EPROBE_DEFER) | ||
562 | return ret; | ||
563 | /* | ||
564 | * Fall through in all other cases, as the clock is | ||
565 | * optional. (Does not exist on all platforms.) | ||
566 | */ | ||
567 | rpm->ramclk = NULL; | ||
568 | } | ||
569 | clk_prepare_enable(rpm->ramclk); /* Accepts NULL */ | ||
570 | |||
504 | irq_ack = platform_get_irq_byname(pdev, "ack"); | 571 | irq_ack = platform_get_irq_byname(pdev, "ack"); |
505 | if (irq_ack < 0) { | 572 | if (irq_ack < 0) { |
506 | dev_err(&pdev->dev, "required ack interrupt missing\n"); | 573 | dev_err(&pdev->dev, "required ack interrupt missing\n"); |
@@ -538,6 +605,7 @@ static int qcom_rpm_probe(struct platform_device *pdev) | |||
538 | } | 605 | } |
539 | 606 | ||
540 | rpm->ipc_regmap = syscon_node_to_regmap(syscon_np); | 607 | rpm->ipc_regmap = syscon_node_to_regmap(syscon_np); |
608 | of_node_put(syscon_np); | ||
541 | if (IS_ERR(rpm->ipc_regmap)) | 609 | if (IS_ERR(rpm->ipc_regmap)) |
542 | return PTR_ERR(rpm->ipc_regmap); | 610 | return PTR_ERR(rpm->ipc_regmap); |
543 | 611 | ||
@@ -620,7 +688,11 @@ static int qcom_rpm_probe(struct platform_device *pdev) | |||
620 | 688 | ||
621 | static int qcom_rpm_remove(struct platform_device *pdev) | 689 | static int qcom_rpm_remove(struct platform_device *pdev) |
622 | { | 690 | { |
691 | struct qcom_rpm *rpm = dev_get_drvdata(&pdev->dev); | ||
692 | |||
623 | of_platform_depopulate(&pdev->dev); | 693 | of_platform_depopulate(&pdev->dev); |
694 | clk_disable_unprepare(rpm->ramclk); | ||
695 | |||
624 | return 0; | 696 | return 0; |
625 | } | 697 | } |
626 | 698 | ||
diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 49d7f624fc94..0f8acc5882a4 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c | |||
@@ -1,11 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * MFD core driver for Rockchip RK808 | 2 | * MFD core driver for Rockchip RK808/RK818 |
3 | * | 3 | * |
4 | * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd | 4 | * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd |
5 | * | 5 | * |
6 | * Author: Chris Zhong <zyw@rock-chips.com> | 6 | * Author: Chris Zhong <zyw@rock-chips.com> |
7 | * Author: Zhang Qing <zhangqing@rock-chips.com> | 7 | * Author: Zhang Qing <zhangqing@rock-chips.com> |
8 | * | 8 | * |
9 | * Copyright (C) 2016 PHYTEC Messtechnik GmbH | ||
10 | * | ||
11 | * Author: Wadim Egorov <w.egorov@phytec.de> | ||
12 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | 13 | * This program is free software; you can redistribute it and/or modify it |
10 | * under the terms and conditions of the GNU General Public License, | 14 | * under the terms and conditions of the GNU General Public License, |
11 | * version 2, as published by the Free Software Foundation. | 15 | * version 2, as published by the Free Software Foundation. |
@@ -21,6 +25,7 @@ | |||
21 | #include <linux/mfd/rk808.h> | 25 | #include <linux/mfd/rk808.h> |
22 | #include <linux/mfd/core.h> | 26 | #include <linux/mfd/core.h> |
23 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/of_device.h> | ||
24 | #include <linux/regmap.h> | 29 | #include <linux/regmap.h> |
25 | 30 | ||
26 | struct rk808_reg_data { | 31 | struct rk808_reg_data { |
@@ -57,6 +62,14 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) | |||
57 | return false; | 62 | return false; |
58 | } | 63 | } |
59 | 64 | ||
65 | static const struct regmap_config rk818_regmap_config = { | ||
66 | .reg_bits = 8, | ||
67 | .val_bits = 8, | ||
68 | .max_register = RK818_USB_CTRL_REG, | ||
69 | .cache_type = REGCACHE_RBTREE, | ||
70 | .volatile_reg = rk808_is_volatile_reg, | ||
71 | }; | ||
72 | |||
60 | static const struct regmap_config rk808_regmap_config = { | 73 | static const struct regmap_config rk808_regmap_config = { |
61 | .reg_bits = 8, | 74 | .reg_bits = 8, |
62 | .val_bits = 8, | 75 | .val_bits = 8, |
@@ -79,11 +92,21 @@ static const struct mfd_cell rk808s[] = { | |||
79 | { | 92 | { |
80 | .name = "rk808-rtc", | 93 | .name = "rk808-rtc", |
81 | .num_resources = ARRAY_SIZE(rtc_resources), | 94 | .num_resources = ARRAY_SIZE(rtc_resources), |
82 | .resources = &rtc_resources[0], | 95 | .resources = rtc_resources, |
83 | }, | 96 | }, |
84 | }; | 97 | }; |
85 | 98 | ||
86 | static const struct rk808_reg_data pre_init_reg[] = { | 99 | static const struct mfd_cell rk818s[] = { |
100 | { .name = "rk808-clkout", }, | ||
101 | { .name = "rk808-regulator", }, | ||
102 | { | ||
103 | .name = "rk808-rtc", | ||
104 | .num_resources = ARRAY_SIZE(rtc_resources), | ||
105 | .resources = rtc_resources, | ||
106 | }, | ||
107 | }; | ||
108 | |||
109 | static const struct rk808_reg_data rk808_pre_init_reg[] = { | ||
87 | { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA }, | 110 | { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA }, |
88 | { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA }, | 111 | { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA }, |
89 | { RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA }, | 112 | { RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA }, |
@@ -94,6 +117,24 @@ static const struct rk808_reg_data pre_init_reg[] = { | |||
94 | VB_LO_SEL_3500MV }, | 117 | VB_LO_SEL_3500MV }, |
95 | }; | 118 | }; |
96 | 119 | ||
120 | static const struct rk808_reg_data rk818_pre_init_reg[] = { | ||
121 | /* improve efficiency */ | ||
122 | { RK818_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_250MA }, | ||
123 | { RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA }, | ||
124 | { RK818_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA }, | ||
125 | { RK818_USB_CTRL_REG, RK818_USB_ILIM_SEL_MASK, | ||
126 | RK818_USB_ILMIN_2000MA }, | ||
127 | /* close charger when usb lower then 3.4V */ | ||
128 | { RK818_USB_CTRL_REG, RK818_USB_CHG_SD_VSEL_MASK, | ||
129 | (0x7 << 4) }, | ||
130 | /* no action when vref */ | ||
131 | { RK818_H5V_EN_REG, BIT(1), RK818_REF_RDY_CTRL }, | ||
132 | /* enable HDMI 5V */ | ||
133 | { RK818_H5V_EN_REG, BIT(0), RK818_H5V_EN }, | ||
134 | { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT | | ||
135 | VB_LO_SEL_3500MV }, | ||
136 | }; | ||
137 | |||
97 | static const struct regmap_irq rk808_irqs[] = { | 138 | static const struct regmap_irq rk808_irqs[] = { |
98 | /* INT_STS */ | 139 | /* INT_STS */ |
99 | [RK808_IRQ_VOUT_LO] = { | 140 | [RK808_IRQ_VOUT_LO] = { |
@@ -136,6 +177,76 @@ static const struct regmap_irq rk808_irqs[] = { | |||
136 | }, | 177 | }, |
137 | }; | 178 | }; |
138 | 179 | ||
180 | static const struct regmap_irq rk818_irqs[] = { | ||
181 | /* INT_STS */ | ||
182 | [RK818_IRQ_VOUT_LO] = { | ||
183 | .mask = RK818_IRQ_VOUT_LO_MSK, | ||
184 | .reg_offset = 0, | ||
185 | }, | ||
186 | [RK818_IRQ_VB_LO] = { | ||
187 | .mask = RK818_IRQ_VB_LO_MSK, | ||
188 | .reg_offset = 0, | ||
189 | }, | ||
190 | [RK818_IRQ_PWRON] = { | ||
191 | .mask = RK818_IRQ_PWRON_MSK, | ||
192 | .reg_offset = 0, | ||
193 | }, | ||
194 | [RK818_IRQ_PWRON_LP] = { | ||
195 | .mask = RK818_IRQ_PWRON_LP_MSK, | ||
196 | .reg_offset = 0, | ||
197 | }, | ||
198 | [RK818_IRQ_HOTDIE] = { | ||
199 | .mask = RK818_IRQ_HOTDIE_MSK, | ||
200 | .reg_offset = 0, | ||
201 | }, | ||
202 | [RK818_IRQ_RTC_ALARM] = { | ||
203 | .mask = RK818_IRQ_RTC_ALARM_MSK, | ||
204 | .reg_offset = 0, | ||
205 | }, | ||
206 | [RK818_IRQ_RTC_PERIOD] = { | ||
207 | .mask = RK818_IRQ_RTC_PERIOD_MSK, | ||
208 | .reg_offset = 0, | ||
209 | }, | ||
210 | [RK818_IRQ_USB_OV] = { | ||
211 | .mask = RK818_IRQ_USB_OV_MSK, | ||
212 | .reg_offset = 0, | ||
213 | }, | ||
214 | |||
215 | /* INT_STS2 */ | ||
216 | [RK818_IRQ_PLUG_IN] = { | ||
217 | .mask = RK818_IRQ_PLUG_IN_MSK, | ||
218 | .reg_offset = 1, | ||
219 | }, | ||
220 | [RK818_IRQ_PLUG_OUT] = { | ||
221 | .mask = RK818_IRQ_PLUG_OUT_MSK, | ||
222 | .reg_offset = 1, | ||
223 | }, | ||
224 | [RK818_IRQ_CHG_OK] = { | ||
225 | .mask = RK818_IRQ_CHG_OK_MSK, | ||
226 | .reg_offset = 1, | ||
227 | }, | ||
228 | [RK818_IRQ_CHG_TE] = { | ||
229 | .mask = RK818_IRQ_CHG_TE_MSK, | ||
230 | .reg_offset = 1, | ||
231 | }, | ||
232 | [RK818_IRQ_CHG_TS1] = { | ||
233 | .mask = RK818_IRQ_CHG_TS1_MSK, | ||
234 | .reg_offset = 1, | ||
235 | }, | ||
236 | [RK818_IRQ_TS2] = { | ||
237 | .mask = RK818_IRQ_TS2_MSK, | ||
238 | .reg_offset = 1, | ||
239 | }, | ||
240 | [RK818_IRQ_CHG_CVTLIM] = { | ||
241 | .mask = RK818_IRQ_CHG_CVTLIM_MSK, | ||
242 | .reg_offset = 1, | ||
243 | }, | ||
244 | [RK818_IRQ_DISCHG_ILIM] = { | ||
245 | .mask = RK818_IRQ_DISCHG_ILIM_MSK, | ||
246 | .reg_offset = 1, | ||
247 | }, | ||
248 | }; | ||
249 | |||
139 | static struct regmap_irq_chip rk808_irq_chip = { | 250 | static struct regmap_irq_chip rk808_irq_chip = { |
140 | .name = "rk808", | 251 | .name = "rk808", |
141 | .irqs = rk808_irqs, | 252 | .irqs = rk808_irqs, |
@@ -148,6 +259,18 @@ static struct regmap_irq_chip rk808_irq_chip = { | |||
148 | .init_ack_masked = true, | 259 | .init_ack_masked = true, |
149 | }; | 260 | }; |
150 | 261 | ||
262 | static struct regmap_irq_chip rk818_irq_chip = { | ||
263 | .name = "rk818", | ||
264 | .irqs = rk818_irqs, | ||
265 | .num_irqs = ARRAY_SIZE(rk818_irqs), | ||
266 | .num_regs = 2, | ||
267 | .irq_reg_stride = 2, | ||
268 | .status_base = RK818_INT_STS_REG1, | ||
269 | .mask_base = RK818_INT_STS_MSK_REG1, | ||
270 | .ack_base = RK818_INT_STS_REG1, | ||
271 | .init_ack_masked = true, | ||
272 | }; | ||
273 | |||
151 | static struct i2c_client *rk808_i2c_client; | 274 | static struct i2c_client *rk808_i2c_client; |
152 | static void rk808_device_shutdown(void) | 275 | static void rk808_device_shutdown(void) |
153 | { | 276 | { |
@@ -167,55 +290,100 @@ static void rk808_device_shutdown(void) | |||
167 | dev_err(&rk808_i2c_client->dev, "power off error!\n"); | 290 | dev_err(&rk808_i2c_client->dev, "power off error!\n"); |
168 | } | 291 | } |
169 | 292 | ||
293 | static const struct of_device_id rk808_of_match[] = { | ||
294 | { .compatible = "rockchip,rk808" }, | ||
295 | { .compatible = "rockchip,rk818" }, | ||
296 | { }, | ||
297 | }; | ||
298 | MODULE_DEVICE_TABLE(of, rk808_of_match); | ||
299 | |||
170 | static int rk808_probe(struct i2c_client *client, | 300 | static int rk808_probe(struct i2c_client *client, |
171 | const struct i2c_device_id *id) | 301 | const struct i2c_device_id *id) |
172 | { | 302 | { |
173 | struct device_node *np = client->dev.of_node; | 303 | struct device_node *np = client->dev.of_node; |
174 | struct rk808 *rk808; | 304 | struct rk808 *rk808; |
305 | const struct rk808_reg_data *pre_init_reg; | ||
306 | const struct mfd_cell *cells; | ||
307 | int nr_pre_init_regs; | ||
308 | int nr_cells; | ||
175 | int pm_off = 0; | 309 | int pm_off = 0; |
176 | int ret; | 310 | int ret; |
177 | int i; | 311 | int i; |
178 | 312 | ||
179 | if (!client->irq) { | ||
180 | dev_err(&client->dev, "No interrupt support, no core IRQ\n"); | ||
181 | return -EINVAL; | ||
182 | } | ||
183 | |||
184 | rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL); | 313 | rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL); |
185 | if (!rk808) | 314 | if (!rk808) |
186 | return -ENOMEM; | 315 | return -ENOMEM; |
187 | 316 | ||
188 | rk808->regmap = devm_regmap_init_i2c(client, &rk808_regmap_config); | 317 | rk808->variant = i2c_smbus_read_word_data(client, RK808_ID_MSB); |
318 | if (rk808->variant < 0) { | ||
319 | dev_err(&client->dev, "Failed to read the chip id at 0x%02x\n", | ||
320 | RK808_ID_MSB); | ||
321 | return rk808->variant; | ||
322 | } | ||
323 | |||
324 | dev_dbg(&client->dev, "Chip id: 0x%x\n", (unsigned int)rk808->variant); | ||
325 | |||
326 | switch (rk808->variant) { | ||
327 | case RK808_ID: | ||
328 | rk808->regmap_cfg = &rk808_regmap_config; | ||
329 | rk808->regmap_irq_chip = &rk808_irq_chip; | ||
330 | pre_init_reg = rk808_pre_init_reg; | ||
331 | nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg); | ||
332 | cells = rk808s; | ||
333 | nr_cells = ARRAY_SIZE(rk808s); | ||
334 | break; | ||
335 | case RK818_ID: | ||
336 | rk808->regmap_cfg = &rk818_regmap_config; | ||
337 | rk808->regmap_irq_chip = &rk818_irq_chip; | ||
338 | pre_init_reg = rk818_pre_init_reg; | ||
339 | nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg); | ||
340 | cells = rk818s; | ||
341 | nr_cells = ARRAY_SIZE(rk818s); | ||
342 | break; | ||
343 | default: | ||
344 | dev_err(&client->dev, "Unsupported RK8XX ID %lu\n", | ||
345 | rk808->variant); | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | |||
349 | rk808->i2c = client; | ||
350 | i2c_set_clientdata(client, rk808); | ||
351 | |||
352 | rk808->regmap = devm_regmap_init_i2c(client, rk808->regmap_cfg); | ||
189 | if (IS_ERR(rk808->regmap)) { | 353 | if (IS_ERR(rk808->regmap)) { |
190 | dev_err(&client->dev, "regmap initialization failed\n"); | 354 | dev_err(&client->dev, "regmap initialization failed\n"); |
191 | return PTR_ERR(rk808->regmap); | 355 | return PTR_ERR(rk808->regmap); |
192 | } | 356 | } |
193 | 357 | ||
194 | for (i = 0; i < ARRAY_SIZE(pre_init_reg); i++) { | 358 | if (!client->irq) { |
195 | ret = regmap_update_bits(rk808->regmap, pre_init_reg[i].addr, | 359 | dev_err(&client->dev, "No interrupt support, no core IRQ\n"); |
196 | pre_init_reg[i].mask, | 360 | return -EINVAL; |
197 | pre_init_reg[i].value); | ||
198 | if (ret) { | ||
199 | dev_err(&client->dev, | ||
200 | "0x%x write err\n", pre_init_reg[i].addr); | ||
201 | return ret; | ||
202 | } | ||
203 | } | 361 | } |
204 | 362 | ||
205 | ret = regmap_add_irq_chip(rk808->regmap, client->irq, | 363 | ret = regmap_add_irq_chip(rk808->regmap, client->irq, |
206 | IRQF_ONESHOT, -1, | 364 | IRQF_ONESHOT, -1, |
207 | &rk808_irq_chip, &rk808->irq_data); | 365 | rk808->regmap_irq_chip, &rk808->irq_data); |
208 | if (ret) { | 366 | if (ret) { |
209 | dev_err(&client->dev, "Failed to add irq_chip %d\n", ret); | 367 | dev_err(&client->dev, "Failed to add irq_chip %d\n", ret); |
210 | return ret; | 368 | return ret; |
211 | } | 369 | } |
212 | 370 | ||
213 | rk808->i2c = client; | 371 | for (i = 0; i < nr_pre_init_regs; i++) { |
214 | i2c_set_clientdata(client, rk808); | 372 | ret = regmap_update_bits(rk808->regmap, |
373 | pre_init_reg[i].addr, | ||
374 | pre_init_reg[i].mask, | ||
375 | pre_init_reg[i].value); | ||
376 | if (ret) { | ||
377 | dev_err(&client->dev, | ||
378 | "0x%x write err\n", | ||
379 | pre_init_reg[i].addr); | ||
380 | return ret; | ||
381 | } | ||
382 | } | ||
215 | 383 | ||
216 | ret = devm_mfd_add_devices(&client->dev, -1, | 384 | ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, |
217 | rk808s, ARRAY_SIZE(rk808s), NULL, 0, | 385 | cells, nr_cells, NULL, 0, |
218 | regmap_irq_get_domain(rk808->irq_data)); | 386 | regmap_irq_get_domain(rk808->irq_data)); |
219 | if (ret) { | 387 | if (ret) { |
220 | dev_err(&client->dev, "failed to add MFD devices %d\n", ret); | 388 | dev_err(&client->dev, "failed to add MFD devices %d\n", ret); |
221 | goto err_irq; | 389 | goto err_irq; |
@@ -245,14 +413,9 @@ static int rk808_remove(struct i2c_client *client) | |||
245 | return 0; | 413 | return 0; |
246 | } | 414 | } |
247 | 415 | ||
248 | static const struct of_device_id rk808_of_match[] = { | ||
249 | { .compatible = "rockchip,rk808" }, | ||
250 | { }, | ||
251 | }; | ||
252 | MODULE_DEVICE_TABLE(of, rk808_of_match); | ||
253 | |||
254 | static const struct i2c_device_id rk808_ids[] = { | 416 | static const struct i2c_device_id rk808_ids[] = { |
255 | { "rk808" }, | 417 | { "rk808" }, |
418 | { "rk818" }, | ||
256 | { }, | 419 | { }, |
257 | }; | 420 | }; |
258 | MODULE_DEVICE_TABLE(i2c, rk808_ids); | 421 | MODULE_DEVICE_TABLE(i2c, rk808_ids); |
@@ -272,4 +435,5 @@ module_i2c_driver(rk808_i2c_driver); | |||
272 | MODULE_LICENSE("GPL"); | 435 | MODULE_LICENSE("GPL"); |
273 | MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>"); | 436 | MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>"); |
274 | MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>"); | 437 | MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>"); |
275 | MODULE_DESCRIPTION("RK808 PMIC driver"); | 438 | MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>"); |
439 | MODULE_DESCRIPTION("RK808/RK818 PMIC driver"); | ||
diff --git a/drivers/mfd/rtsx_usb.c b/drivers/mfd/rtsx_usb.c index dbd907d7170e..691dab791f7a 100644 --- a/drivers/mfd/rtsx_usb.c +++ b/drivers/mfd/rtsx_usb.c | |||
@@ -46,9 +46,6 @@ static void rtsx_usb_sg_timed_out(unsigned long data) | |||
46 | 46 | ||
47 | dev_dbg(&ucr->pusb_intf->dev, "%s: sg transfer timed out", __func__); | 47 | dev_dbg(&ucr->pusb_intf->dev, "%s: sg transfer timed out", __func__); |
48 | usb_sg_cancel(&ucr->current_sg); | 48 | usb_sg_cancel(&ucr->current_sg); |
49 | |||
50 | /* we know the cancellation is caused by time-out */ | ||
51 | ucr->current_sg.status = -ETIMEDOUT; | ||
52 | } | 49 | } |
53 | 50 | ||
54 | static int rtsx_usb_bulk_transfer_sglist(struct rtsx_ucr *ucr, | 51 | static int rtsx_usb_bulk_transfer_sglist(struct rtsx_ucr *ucr, |
@@ -67,12 +64,15 @@ static int rtsx_usb_bulk_transfer_sglist(struct rtsx_ucr *ucr, | |||
67 | ucr->sg_timer.expires = jiffies + msecs_to_jiffies(timeout); | 64 | ucr->sg_timer.expires = jiffies + msecs_to_jiffies(timeout); |
68 | add_timer(&ucr->sg_timer); | 65 | add_timer(&ucr->sg_timer); |
69 | usb_sg_wait(&ucr->current_sg); | 66 | usb_sg_wait(&ucr->current_sg); |
70 | del_timer_sync(&ucr->sg_timer); | 67 | if (!del_timer_sync(&ucr->sg_timer)) |
68 | ret = -ETIMEDOUT; | ||
69 | else | ||
70 | ret = ucr->current_sg.status; | ||
71 | 71 | ||
72 | if (act_len) | 72 | if (act_len) |
73 | *act_len = ucr->current_sg.bytes; | 73 | *act_len = ucr->current_sg.bytes; |
74 | 74 | ||
75 | return ucr->current_sg.status; | 75 | return ret; |
76 | } | 76 | } |
77 | 77 | ||
78 | int rtsx_usb_transfer_data(struct rtsx_ucr *ucr, unsigned int pipe, | 78 | int rtsx_usb_transfer_data(struct rtsx_ucr *ucr, unsigned int pipe, |
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 65cd0d2a822a..40534352e574 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c | |||
@@ -1001,7 +1001,7 @@ static int sm501_gpio_output(struct gpio_chip *chip, | |||
1001 | return 0; | 1001 | return 0; |
1002 | } | 1002 | } |
1003 | 1003 | ||
1004 | static struct gpio_chip gpio_chip_template = { | 1004 | static const struct gpio_chip gpio_chip_template = { |
1005 | .ngpio = 32, | 1005 | .ngpio = 32, |
1006 | .direction_input = sm501_gpio_input, | 1006 | .direction_input = sm501_gpio_input, |
1007 | .direction_output = sm501_gpio_output, | 1007 | .direction_output = sm501_gpio_output, |
diff --git a/drivers/mfd/smsc-ece1099.c b/drivers/mfd/smsc-ece1099.c index cd18c09827ef..1f40baf1234e 100644 --- a/drivers/mfd/smsc-ece1099.c +++ b/drivers/mfd/smsc-ece1099.c | |||
@@ -11,8 +11,7 @@ | |||
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/module.h> | 14 | #include <linux/init.h> |
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
17 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
18 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
@@ -81,7 +80,6 @@ static const struct i2c_device_id smsc_i2c_id[] = { | |||
81 | { "smscece1099", 0}, | 80 | { "smscece1099", 0}, |
82 | {}, | 81 | {}, |
83 | }; | 82 | }; |
84 | MODULE_DEVICE_TABLE(i2c, smsc_i2c_id); | ||
85 | 83 | ||
86 | static struct i2c_driver smsc_i2c_driver = { | 84 | static struct i2c_driver smsc_i2c_driver = { |
87 | .driver = { | 85 | .driver = { |
@@ -90,9 +88,4 @@ static struct i2c_driver smsc_i2c_driver = { | |||
90 | .probe = smsc_i2c_probe, | 88 | .probe = smsc_i2c_probe, |
91 | .id_table = smsc_i2c_id, | 89 | .id_table = smsc_i2c_id, |
92 | }; | 90 | }; |
93 | 91 | builtin_i2c_driver(smsc_i2c_driver); | |
94 | module_i2c_driver(smsc_i2c_driver); | ||
95 | |||
96 | MODULE_AUTHOR("Sourav Poddar <sourav.poddar@ti.com>"); | ||
97 | MODULE_DESCRIPTION("SMSC chip multi-function driver"); | ||
98 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/sun6i-prcm.c b/drivers/mfd/sun6i-prcm.c index 191173166d65..011fcc555945 100644 --- a/drivers/mfd/sun6i-prcm.c +++ b/drivers/mfd/sun6i-prcm.c | |||
@@ -9,7 +9,7 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/mfd/core.h> | 11 | #include <linux/mfd/core.h> |
12 | #include <linux/module.h> | 12 | #include <linux/init.h> |
13 | #include <linux/of.h> | 13 | #include <linux/of.h> |
14 | 14 | ||
15 | struct prcm_data { | 15 | struct prcm_data { |
@@ -170,8 +170,4 @@ static struct platform_driver sun6i_prcm_driver = { | |||
170 | }, | 170 | }, |
171 | .probe = sun6i_prcm_probe, | 171 | .probe = sun6i_prcm_probe, |
172 | }; | 172 | }; |
173 | module_platform_driver(sun6i_prcm_driver); | 173 | builtin_platform_driver(sun6i_prcm_driver); |
174 | |||
175 | MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>"); | ||
176 | MODULE_DESCRIPTION("Allwinner sun6i PRCM driver"); | ||
177 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index 049a6fcac651..9a4d8684dd32 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c | |||
@@ -15,22 +15,103 @@ | |||
15 | * GNU General Public License for more details. | 15 | * GNU General Public License for more details. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/device.h> | 18 | #include <linux/device.h> |
20 | #include <linux/module.h> | 19 | #include <linux/err.h> |
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/interrupt.h> | ||
23 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
24 | #include <linux/slab.h> | 23 | #include <linux/irq.h> |
25 | #include <linux/regmap.h> | 24 | #include <linux/irqdomain.h> |
26 | #include <linux/err.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/module.h> | ||
27 | #include <linux/of.h> | 27 | #include <linux/of.h> |
28 | #include <linux/of_device.h> | 28 | #include <linux/of_device.h> |
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/regmap.h> | ||
31 | #include <linux/slab.h> | ||
29 | 32 | ||
30 | #include <linux/mfd/core.h> | 33 | #include <linux/mfd/core.h> |
31 | #include <linux/mfd/tps65217.h> | 34 | #include <linux/mfd/tps65217.h> |
32 | 35 | ||
33 | static const struct mfd_cell tps65217s[] = { | 36 | static struct resource charger_resources[] = { |
37 | DEFINE_RES_IRQ_NAMED(TPS65217_IRQ_AC, "AC"), | ||
38 | DEFINE_RES_IRQ_NAMED(TPS65217_IRQ_USB, "USB"), | ||
39 | }; | ||
40 | |||
41 | static struct resource pb_resources[] = { | ||
42 | DEFINE_RES_IRQ_NAMED(TPS65217_IRQ_PB, "PB"), | ||
43 | }; | ||
44 | |||
45 | struct tps65217_irq { | ||
46 | int mask; | ||
47 | int interrupt; | ||
48 | }; | ||
49 | |||
50 | static const struct tps65217_irq tps65217_irqs[] = { | ||
51 | [TPS65217_IRQ_PB] = { | ||
52 | .mask = TPS65217_INT_PBM, | ||
53 | .interrupt = TPS65217_INT_PBI, | ||
54 | }, | ||
55 | [TPS65217_IRQ_AC] = { | ||
56 | .mask = TPS65217_INT_ACM, | ||
57 | .interrupt = TPS65217_INT_ACI, | ||
58 | }, | ||
59 | [TPS65217_IRQ_USB] = { | ||
60 | .mask = TPS65217_INT_USBM, | ||
61 | .interrupt = TPS65217_INT_USBI, | ||
62 | }, | ||
63 | }; | ||
64 | |||
65 | static void tps65217_irq_lock(struct irq_data *data) | ||
66 | { | ||
67 | struct tps65217 *tps = irq_data_get_irq_chip_data(data); | ||
68 | |||
69 | mutex_lock(&tps->irq_lock); | ||
70 | } | ||
71 | |||
72 | static void tps65217_irq_sync_unlock(struct irq_data *data) | ||
73 | { | ||
74 | struct tps65217 *tps = irq_data_get_irq_chip_data(data); | ||
75 | int ret; | ||
76 | |||
77 | ret = tps65217_reg_write(tps, TPS65217_REG_INT, tps->irq_mask, | ||
78 | TPS65217_PROTECT_NONE); | ||
79 | if (ret != 0) | ||
80 | dev_err(tps->dev, "Failed to sync IRQ masks\n"); | ||
81 | |||
82 | mutex_unlock(&tps->irq_lock); | ||
83 | } | ||
84 | |||
85 | static inline const struct tps65217_irq * | ||
86 | irq_to_tps65217_irq(struct tps65217 *tps, struct irq_data *data) | ||
87 | { | ||
88 | return &tps65217_irqs[data->hwirq]; | ||
89 | } | ||
90 | |||
91 | static void tps65217_irq_enable(struct irq_data *data) | ||
92 | { | ||
93 | struct tps65217 *tps = irq_data_get_irq_chip_data(data); | ||
94 | const struct tps65217_irq *irq_data = irq_to_tps65217_irq(tps, data); | ||
95 | |||
96 | tps->irq_mask &= ~irq_data->mask; | ||
97 | } | ||
98 | |||
99 | static void tps65217_irq_disable(struct irq_data *data) | ||
100 | { | ||
101 | struct tps65217 *tps = irq_data_get_irq_chip_data(data); | ||
102 | const struct tps65217_irq *irq_data = irq_to_tps65217_irq(tps, data); | ||
103 | |||
104 | tps->irq_mask |= irq_data->mask; | ||
105 | } | ||
106 | |||
107 | static struct irq_chip tps65217_irq_chip = { | ||
108 | .irq_bus_lock = tps65217_irq_lock, | ||
109 | .irq_bus_sync_unlock = tps65217_irq_sync_unlock, | ||
110 | .irq_enable = tps65217_irq_enable, | ||
111 | .irq_disable = tps65217_irq_disable, | ||
112 | }; | ||
113 | |||
114 | static struct mfd_cell tps65217s[] = { | ||
34 | { | 115 | { |
35 | .name = "tps65217-pmic", | 116 | .name = "tps65217-pmic", |
36 | .of_compatible = "ti,tps65217-pmic", | 117 | .of_compatible = "ti,tps65217-pmic", |
@@ -41,10 +122,96 @@ static const struct mfd_cell tps65217s[] = { | |||
41 | }, | 122 | }, |
42 | { | 123 | { |
43 | .name = "tps65217-charger", | 124 | .name = "tps65217-charger", |
125 | .num_resources = ARRAY_SIZE(charger_resources), | ||
126 | .resources = charger_resources, | ||
44 | .of_compatible = "ti,tps65217-charger", | 127 | .of_compatible = "ti,tps65217-charger", |
45 | }, | 128 | }, |
129 | { | ||
130 | .name = "tps65217-pwrbutton", | ||
131 | .num_resources = ARRAY_SIZE(pb_resources), | ||
132 | .resources = pb_resources, | ||
133 | .of_compatible = "ti,tps65217-pwrbutton", | ||
134 | }, | ||
135 | }; | ||
136 | |||
137 | static irqreturn_t tps65217_irq_thread(int irq, void *data) | ||
138 | { | ||
139 | struct tps65217 *tps = data; | ||
140 | unsigned int status; | ||
141 | bool handled = false; | ||
142 | int i; | ||
143 | int ret; | ||
144 | |||
145 | ret = tps65217_reg_read(tps, TPS65217_REG_INT, &status); | ||
146 | if (ret < 0) { | ||
147 | dev_err(tps->dev, "Failed to read IRQ status: %d\n", | ||
148 | ret); | ||
149 | return IRQ_NONE; | ||
150 | } | ||
151 | |||
152 | for (i = 0; i < ARRAY_SIZE(tps65217_irqs); i++) { | ||
153 | if (status & tps65217_irqs[i].interrupt) { | ||
154 | handle_nested_irq(irq_find_mapping(tps->irq_domain, i)); | ||
155 | handled = true; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | if (handled) | ||
160 | return IRQ_HANDLED; | ||
161 | |||
162 | return IRQ_NONE; | ||
163 | } | ||
164 | |||
165 | static int tps65217_irq_map(struct irq_domain *h, unsigned int virq, | ||
166 | irq_hw_number_t hw) | ||
167 | { | ||
168 | struct tps65217 *tps = h->host_data; | ||
169 | |||
170 | irq_set_chip_data(virq, tps); | ||
171 | irq_set_chip_and_handler(virq, &tps65217_irq_chip, handle_edge_irq); | ||
172 | irq_set_nested_thread(virq, 1); | ||
173 | irq_set_parent(virq, tps->irq); | ||
174 | irq_set_noprobe(virq); | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static const struct irq_domain_ops tps65217_irq_domain_ops = { | ||
180 | .map = tps65217_irq_map, | ||
46 | }; | 181 | }; |
47 | 182 | ||
183 | static int tps65217_irq_init(struct tps65217 *tps, int irq) | ||
184 | { | ||
185 | int ret; | ||
186 | |||
187 | mutex_init(&tps->irq_lock); | ||
188 | tps->irq = irq; | ||
189 | |||
190 | /* Mask all interrupt sources */ | ||
191 | tps->irq_mask = (TPS65217_INT_RESERVEDM | TPS65217_INT_PBM | ||
192 | | TPS65217_INT_ACM | TPS65217_INT_USBM); | ||
193 | tps65217_reg_write(tps, TPS65217_REG_INT, tps->irq_mask, | ||
194 | TPS65217_PROTECT_NONE); | ||
195 | |||
196 | tps->irq_domain = irq_domain_add_linear(tps->dev->of_node, | ||
197 | TPS65217_NUM_IRQ, &tps65217_irq_domain_ops, tps); | ||
198 | if (!tps->irq_domain) { | ||
199 | dev_err(tps->dev, "Could not create IRQ domain\n"); | ||
200 | return -ENOMEM; | ||
201 | } | ||
202 | |||
203 | ret = devm_request_threaded_irq(tps->dev, irq, NULL, | ||
204 | tps65217_irq_thread, IRQF_ONESHOT, | ||
205 | "tps65217-irq", tps); | ||
206 | if (ret) { | ||
207 | dev_err(tps->dev, "Failed to request IRQ %d: %d\n", | ||
208 | irq, ret); | ||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
48 | /** | 215 | /** |
49 | * tps65217_reg_read: Read a single tps65217 register. | 216 | * tps65217_reg_read: Read a single tps65217 register. |
50 | * | 217 | * |
@@ -149,11 +316,22 @@ int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg, | |||
149 | } | 316 | } |
150 | EXPORT_SYMBOL_GPL(tps65217_clear_bits); | 317 | EXPORT_SYMBOL_GPL(tps65217_clear_bits); |
151 | 318 | ||
319 | static bool tps65217_volatile_reg(struct device *dev, unsigned int reg) | ||
320 | { | ||
321 | switch (reg) { | ||
322 | case TPS65217_REG_INT: | ||
323 | return true; | ||
324 | default: | ||
325 | return false; | ||
326 | } | ||
327 | } | ||
328 | |||
152 | static const struct regmap_config tps65217_regmap_config = { | 329 | static const struct regmap_config tps65217_regmap_config = { |
153 | .reg_bits = 8, | 330 | .reg_bits = 8, |
154 | .val_bits = 8, | 331 | .val_bits = 8, |
155 | 332 | ||
156 | .max_register = TPS65217_REG_MAX, | 333 | .max_register = TPS65217_REG_MAX, |
334 | .volatile_reg = tps65217_volatile_reg, | ||
157 | }; | 335 | }; |
158 | 336 | ||
159 | static const struct of_device_id tps65217_of_match[] = { | 337 | static const struct of_device_id tps65217_of_match[] = { |
@@ -205,8 +383,19 @@ static int tps65217_probe(struct i2c_client *client, | |||
205 | return ret; | 383 | return ret; |
206 | } | 384 | } |
207 | 385 | ||
386 | if (client->irq) { | ||
387 | tps65217_irq_init(tps, client->irq); | ||
388 | } else { | ||
389 | int i; | ||
390 | |||
391 | /* Don't tell children about IRQ resources which won't fire */ | ||
392 | for (i = 0; i < ARRAY_SIZE(tps65217s); i++) | ||
393 | tps65217s[i].num_resources = 0; | ||
394 | } | ||
395 | |||
208 | ret = devm_mfd_add_devices(tps->dev, -1, tps65217s, | 396 | ret = devm_mfd_add_devices(tps->dev, -1, tps65217s, |
209 | ARRAY_SIZE(tps65217s), NULL, 0, NULL); | 397 | ARRAY_SIZE(tps65217s), NULL, 0, |
398 | tps->irq_domain); | ||
210 | if (ret < 0) { | 399 | if (ret < 0) { |
211 | dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret); | 400 | dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret); |
212 | return ret; | 401 | return ret; |
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index a49d3db6d936..c64615dca2bd 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c | |||
@@ -30,7 +30,6 @@ | |||
30 | 30 | ||
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
33 | #include <linux/module.h> | ||
34 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
35 | #include <linux/regmap.h> | 34 | #include <linux/regmap.h> |
36 | #include <linux/clk.h> | 35 | #include <linux/clk.h> |
@@ -1258,7 +1257,6 @@ static const struct i2c_device_id twl_ids[] = { | |||
1258 | { "twl6032", TWL6030_CLASS | TWL6032_SUBCLASS }, /* "Phoenix lite" */ | 1257 | { "twl6032", TWL6030_CLASS | TWL6032_SUBCLASS }, /* "Phoenix lite" */ |
1259 | { /* end of list */ }, | 1258 | { /* end of list */ }, |
1260 | }; | 1259 | }; |
1261 | MODULE_DEVICE_TABLE(i2c, twl_ids); | ||
1262 | 1260 | ||
1263 | /* One Client Driver , 4 Clients */ | 1261 | /* One Client Driver , 4 Clients */ |
1264 | static struct i2c_driver twl_driver = { | 1262 | static struct i2c_driver twl_driver = { |
@@ -1267,9 +1265,4 @@ static struct i2c_driver twl_driver = { | |||
1267 | .probe = twl_probe, | 1265 | .probe = twl_probe, |
1268 | .remove = twl_remove, | 1266 | .remove = twl_remove, |
1269 | }; | 1267 | }; |
1270 | 1268 | builtin_i2c_driver(twl_driver); | |
1271 | module_i2c_driver(twl_driver); | ||
1272 | |||
1273 | MODULE_AUTHOR("Texas Instruments, Inc."); | ||
1274 | MODULE_DESCRIPTION("I2C Core interface for TWL"); | ||
1275 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index ab328ec49353..d66502d36ba0 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c | |||
@@ -609,6 +609,7 @@ static const struct regmap_config twl6040_regmap_config = { | |||
609 | .writeable_reg = twl6040_writeable_reg, | 609 | .writeable_reg = twl6040_writeable_reg, |
610 | 610 | ||
611 | .cache_type = REGCACHE_RBTREE, | 611 | .cache_type = REGCACHE_RBTREE, |
612 | .use_single_rw = true, | ||
612 | }; | 613 | }; |
613 | 614 | ||
614 | static const struct regmap_irq twl6040_irqs[] = { | 615 | static const struct regmap_irq twl6040_irqs[] = { |
@@ -782,6 +783,11 @@ static int twl6040_probe(struct i2c_client *client, | |||
782 | cell->name = "twl6040-gpo"; | 783 | cell->name = "twl6040-gpo"; |
783 | children++; | 784 | children++; |
784 | 785 | ||
786 | /* PDM clock support */ | ||
787 | cell = &twl6040->cells[children]; | ||
788 | cell->name = "twl6040-pdmclk"; | ||
789 | children++; | ||
790 | |||
785 | /* The chip is powered down so mark regmap to cache only and dirty */ | 791 | /* The chip is powered down so mark regmap to cache only and dirty */ |
786 | regcache_cache_only(twl6040->regmap, true); | 792 | regcache_cache_only(twl6040->regmap, true); |
787 | regcache_mark_dirty(twl6040->regmap); | 793 | regcache_mark_dirty(twl6040->regmap); |
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index 9ab9ec47ea75..d6fb2e1a759a 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c | |||
@@ -446,10 +446,6 @@ static int ucb1x00_detect_irq(struct ucb1x00 *ucb) | |||
446 | unsigned long mask; | 446 | unsigned long mask; |
447 | 447 | ||
448 | mask = probe_irq_on(); | 448 | mask = probe_irq_on(); |
449 | if (!mask) { | ||
450 | probe_irq_off(mask); | ||
451 | return NO_IRQ; | ||
452 | } | ||
453 | 449 | ||
454 | /* | 450 | /* |
455 | * Enable the ADC interrupt. | 451 | * Enable the ADC interrupt. |
@@ -541,7 +537,7 @@ static int ucb1x00_probe(struct mcp *mcp) | |||
541 | ucb1x00_enable(ucb); | 537 | ucb1x00_enable(ucb); |
542 | ucb->irq = ucb1x00_detect_irq(ucb); | 538 | ucb->irq = ucb1x00_detect_irq(ucb); |
543 | ucb1x00_disable(ucb); | 539 | ucb1x00_disable(ucb); |
544 | if (ucb->irq == NO_IRQ) { | 540 | if (!ucb->irq) { |
545 | dev_err(&ucb->dev, "IRQ probe failed\n"); | 541 | dev_err(&ucb->dev, "IRQ probe failed\n"); |
546 | ret = -ENODEV; | 542 | ret = -ENODEV; |
547 | goto err_no_irq; | 543 | goto err_no_irq; |
diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index 6c084b266651..04053fe1e980 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/device.h> | 19 | #include <linux/device.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <asm/unaligned.h> | ||
22 | 23 | ||
23 | #define EC_COMMAND_RETRIES 50 | 24 | #define EC_COMMAND_RETRIES 50 |
24 | 25 | ||
@@ -234,11 +235,44 @@ static int cros_ec_host_command_proto_query_v2(struct cros_ec_device *ec_dev) | |||
234 | return ret; | 235 | return ret; |
235 | } | 236 | } |
236 | 237 | ||
238 | static int cros_ec_get_host_command_version_mask(struct cros_ec_device *ec_dev, | ||
239 | u16 cmd, u32 *mask) | ||
240 | { | ||
241 | struct ec_params_get_cmd_versions *pver; | ||
242 | struct ec_response_get_cmd_versions *rver; | ||
243 | struct cros_ec_command *msg; | ||
244 | int ret; | ||
245 | |||
246 | msg = kmalloc(sizeof(*msg) + max(sizeof(*rver), sizeof(*pver)), | ||
247 | GFP_KERNEL); | ||
248 | if (!msg) | ||
249 | return -ENOMEM; | ||
250 | |||
251 | msg->version = 0; | ||
252 | msg->command = EC_CMD_GET_CMD_VERSIONS; | ||
253 | msg->insize = sizeof(*rver); | ||
254 | msg->outsize = sizeof(*pver); | ||
255 | |||
256 | pver = (struct ec_params_get_cmd_versions *)msg->data; | ||
257 | pver->cmd = cmd; | ||
258 | |||
259 | ret = cros_ec_cmd_xfer(ec_dev, msg); | ||
260 | if (ret > 0) { | ||
261 | rver = (struct ec_response_get_cmd_versions *)msg->data; | ||
262 | *mask = rver->version_mask; | ||
263 | } | ||
264 | |||
265 | kfree(msg); | ||
266 | |||
267 | return ret; | ||
268 | } | ||
269 | |||
237 | int cros_ec_query_all(struct cros_ec_device *ec_dev) | 270 | int cros_ec_query_all(struct cros_ec_device *ec_dev) |
238 | { | 271 | { |
239 | struct device *dev = ec_dev->dev; | 272 | struct device *dev = ec_dev->dev; |
240 | struct cros_ec_command *proto_msg; | 273 | struct cros_ec_command *proto_msg; |
241 | struct ec_response_get_protocol_info *proto_info; | 274 | struct ec_response_get_protocol_info *proto_info; |
275 | u32 ver_mask = 0; | ||
242 | int ret; | 276 | int ret; |
243 | 277 | ||
244 | proto_msg = kzalloc(sizeof(*proto_msg) + sizeof(*proto_info), | 278 | proto_msg = kzalloc(sizeof(*proto_msg) + sizeof(*proto_info), |
@@ -328,6 +362,15 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev) | |||
328 | goto exit; | 362 | goto exit; |
329 | } | 363 | } |
330 | 364 | ||
365 | /* Probe if MKBP event is supported */ | ||
366 | ret = cros_ec_get_host_command_version_mask(ec_dev, | ||
367 | EC_CMD_GET_NEXT_EVENT, | ||
368 | &ver_mask); | ||
369 | if (ret < 0 || ver_mask == 0) | ||
370 | ec_dev->mkbp_event_supported = 0; | ||
371 | else | ||
372 | ec_dev->mkbp_event_supported = 1; | ||
373 | |||
331 | exit: | 374 | exit: |
332 | kfree(proto_msg); | 375 | kfree(proto_msg); |
333 | return ret; | 376 | return ret; |
@@ -397,3 +440,52 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev, | |||
397 | return ret; | 440 | return ret; |
398 | } | 441 | } |
399 | EXPORT_SYMBOL(cros_ec_cmd_xfer_status); | 442 | EXPORT_SYMBOL(cros_ec_cmd_xfer_status); |
443 | |||
444 | static int get_next_event(struct cros_ec_device *ec_dev) | ||
445 | { | ||
446 | u8 buffer[sizeof(struct cros_ec_command) + sizeof(ec_dev->event_data)]; | ||
447 | struct cros_ec_command *msg = (struct cros_ec_command *)&buffer; | ||
448 | int ret; | ||
449 | |||
450 | msg->version = 0; | ||
451 | msg->command = EC_CMD_GET_NEXT_EVENT; | ||
452 | msg->insize = sizeof(ec_dev->event_data); | ||
453 | msg->outsize = 0; | ||
454 | |||
455 | ret = cros_ec_cmd_xfer(ec_dev, msg); | ||
456 | if (ret > 0) { | ||
457 | ec_dev->event_size = ret - 1; | ||
458 | memcpy(&ec_dev->event_data, msg->data, | ||
459 | sizeof(ec_dev->event_data)); | ||
460 | } | ||
461 | |||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | static int get_keyboard_state_event(struct cros_ec_device *ec_dev) | ||
466 | { | ||
467 | u8 buffer[sizeof(struct cros_ec_command) + | ||
468 | sizeof(ec_dev->event_data.data)]; | ||
469 | struct cros_ec_command *msg = (struct cros_ec_command *)&buffer; | ||
470 | |||
471 | msg->version = 0; | ||
472 | msg->command = EC_CMD_MKBP_STATE; | ||
473 | msg->insize = sizeof(ec_dev->event_data.data); | ||
474 | msg->outsize = 0; | ||
475 | |||
476 | ec_dev->event_size = cros_ec_cmd_xfer(ec_dev, msg); | ||
477 | ec_dev->event_data.event_type = EC_MKBP_EVENT_KEY_MATRIX; | ||
478 | memcpy(&ec_dev->event_data.data, msg->data, | ||
479 | sizeof(ec_dev->event_data.data)); | ||
480 | |||
481 | return ec_dev->event_size; | ||
482 | } | ||
483 | |||
484 | int cros_ec_get_next_event(struct cros_ec_device *ec_dev) | ||
485 | { | ||
486 | if (ec_dev->mkbp_event_supported) | ||
487 | return get_next_event(ec_dev); | ||
488 | else | ||
489 | return get_keyboard_state_event(ec_dev); | ||
490 | } | ||
491 | EXPORT_SYMBOL(cros_ec_get_next_event); | ||
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 06c75186af80..936f7ccc9736 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -643,11 +643,11 @@ config REGULATOR_RC5T583 | |||
643 | outputs which can be controlled by i2c communication. | 643 | outputs which can be controlled by i2c communication. |
644 | 644 | ||
645 | config REGULATOR_RK808 | 645 | config REGULATOR_RK808 |
646 | tristate "Rockchip RK808 Power regulators" | 646 | tristate "Rockchip RK808/RK818 Power regulators" |
647 | depends on MFD_RK808 | 647 | depends on MFD_RK808 |
648 | help | 648 | help |
649 | Select this option to enable the power regulator of ROCKCHIP | 649 | Select this option to enable the power regulator of ROCKCHIP |
650 | PMIC RK808. | 650 | PMIC RK808 and RK818. |
651 | This driver supports the control of different power rails of device | 651 | This driver supports the control of different power rails of device |
652 | through regulator interface. The device supports multiple DCDC/LDO | 652 | through regulator interface. The device supports multiple DCDC/LDO |
653 | outputs which can be controlled by i2c communication. | 653 | outputs which can be controlled by i2c communication. |
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 6d9ac76a772f..54382ef902c6 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c | |||
@@ -244,16 +244,64 @@ static const struct regulator_desc axp22x_drivevbus_regulator = { | |||
244 | .ops = &axp20x_ops_sw, | 244 | .ops = &axp20x_ops_sw, |
245 | }; | 245 | }; |
246 | 246 | ||
247 | static const struct regulator_linear_range axp809_dcdc4_ranges[] = { | 247 | static const struct regulator_linear_range axp806_dcdca_ranges[] = { |
248 | REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2f, 20000), | 248 | REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000), |
249 | REGULATOR_LINEAR_RANGE(1800000, 0x30, 0x38, 100000), | 249 | REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000), |
250 | }; | 250 | }; |
251 | 251 | ||
252 | static const struct regulator_linear_range axp809_dldo1_ranges[] = { | 252 | static const struct regulator_linear_range axp806_dcdcd_ranges[] = { |
253 | REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2d, 20000), | ||
254 | REGULATOR_LINEAR_RANGE(1600000, 0x2e, 0x3f, 100000), | ||
255 | }; | ||
256 | |||
257 | static const struct regulator_linear_range axp806_cldo2_ranges[] = { | ||
253 | REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000), | 258 | REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000), |
254 | REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000), | 259 | REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000), |
255 | }; | 260 | }; |
256 | 261 | ||
262 | static const struct regulator_desc axp806_regulators[] = { | ||
263 | AXP_DESC_RANGES(AXP806, DCDCA, "dcdca", "vina", axp806_dcdca_ranges, | ||
264 | 72, AXP806_DCDCA_V_CTRL, 0x7f, AXP806_PWR_OUT_CTRL1, | ||
265 | BIT(0)), | ||
266 | AXP_DESC(AXP806, DCDCB, "dcdcb", "vinb", 1000, 2550, 50, | ||
267 | AXP806_DCDCB_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(1)), | ||
268 | AXP_DESC_RANGES(AXP806, DCDCC, "dcdcc", "vinc", axp806_dcdca_ranges, | ||
269 | 72, AXP806_DCDCC_V_CTRL, 0x7f, AXP806_PWR_OUT_CTRL1, | ||
270 | BIT(2)), | ||
271 | AXP_DESC_RANGES(AXP806, DCDCD, "dcdcd", "vind", axp806_dcdcd_ranges, | ||
272 | 64, AXP806_DCDCD_V_CTRL, 0x3f, AXP806_PWR_OUT_CTRL1, | ||
273 | BIT(3)), | ||
274 | AXP_DESC(AXP806, DCDCE, "dcdce", "vine", 1100, 3400, 100, | ||
275 | AXP806_DCDCB_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(4)), | ||
276 | AXP_DESC(AXP806, ALDO1, "aldo1", "aldoin", 700, 3300, 100, | ||
277 | AXP806_ALDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(5)), | ||
278 | AXP_DESC(AXP806, ALDO2, "aldo2", "aldoin", 700, 3400, 100, | ||
279 | AXP806_ALDO2_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(6)), | ||
280 | AXP_DESC(AXP806, ALDO3, "aldo3", "aldoin", 700, 3300, 100, | ||
281 | AXP806_ALDO3_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(7)), | ||
282 | AXP_DESC(AXP806, BLDO1, "bldo1", "bldoin", 700, 1900, 100, | ||
283 | AXP806_BLDO1_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(0)), | ||
284 | AXP_DESC(AXP806, BLDO2, "bldo2", "bldoin", 700, 1900, 100, | ||
285 | AXP806_BLDO2_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(1)), | ||
286 | AXP_DESC(AXP806, BLDO3, "bldo3", "bldoin", 700, 1900, 100, | ||
287 | AXP806_BLDO3_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(2)), | ||
288 | AXP_DESC(AXP806, BLDO4, "bldo4", "bldoin", 700, 1900, 100, | ||
289 | AXP806_BLDO4_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(3)), | ||
290 | AXP_DESC(AXP806, CLDO1, "cldo1", "cldoin", 700, 3300, 100, | ||
291 | AXP806_CLDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, BIT(4)), | ||
292 | AXP_DESC_RANGES(AXP806, CLDO2, "cldo2", "cldoin", axp806_cldo2_ranges, | ||
293 | 32, AXP806_CLDO2_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, | ||
294 | BIT(5)), | ||
295 | AXP_DESC(AXP806, CLDO3, "cldo3", "cldoin", 700, 3300, 100, | ||
296 | AXP806_CLDO3_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, BIT(6)), | ||
297 | AXP_DESC_SW(AXP806, SW, "sw", "swin", AXP806_PWR_OUT_CTRL2, BIT(7)), | ||
298 | }; | ||
299 | |||
300 | static const struct regulator_linear_range axp809_dcdc4_ranges[] = { | ||
301 | REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2f, 20000), | ||
302 | REGULATOR_LINEAR_RANGE(1800000, 0x30, 0x38, 100000), | ||
303 | }; | ||
304 | |||
257 | static const struct regulator_desc axp809_regulators[] = { | 305 | static const struct regulator_desc axp809_regulators[] = { |
258 | AXP_DESC(AXP809, DCDC1, "dcdc1", "vin1", 1600, 3400, 100, | 306 | AXP_DESC(AXP809, DCDC1, "dcdc1", "vin1", 1600, 3400, 100, |
259 | AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(1)), | 307 | AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(1)), |
@@ -278,7 +326,7 @@ static const struct regulator_desc axp809_regulators[] = { | |||
278 | AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)), | 326 | AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)), |
279 | AXP_DESC(AXP809, ALDO3, "aldo3", "aldoin", 700, 3300, 100, | 327 | AXP_DESC(AXP809, ALDO3, "aldo3", "aldoin", 700, 3300, 100, |
280 | AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)), | 328 | AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)), |
281 | AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp809_dldo1_ranges, | 329 | AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp806_cldo2_ranges, |
282 | 32, AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, | 330 | 32, AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, |
283 | BIT(3)), | 331 | BIT(3)), |
284 | AXP_DESC(AXP809, DLDO2, "dldo2", "dldoin", 700, 3300, 100, | 332 | AXP_DESC(AXP809, DLDO2, "dldo2", "dldoin", 700, 3300, 100, |
@@ -302,6 +350,7 @@ static const struct regulator_desc axp809_regulators[] = { | |||
302 | static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) | 350 | static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) |
303 | { | 351 | { |
304 | struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); | 352 | struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); |
353 | unsigned int reg = AXP20X_DCDC_FREQ; | ||
305 | u32 min, max, def, step; | 354 | u32 min, max, def, step; |
306 | 355 | ||
307 | switch (axp20x->variant) { | 356 | switch (axp20x->variant) { |
@@ -312,6 +361,14 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) | |||
312 | def = 1500; | 361 | def = 1500; |
313 | step = 75; | 362 | step = 75; |
314 | break; | 363 | break; |
364 | case AXP806_ID: | ||
365 | /* | ||
366 | * AXP806 DCDC work frequency setting has the same range and | ||
367 | * step as AXP22X, but at a different register. | ||
368 | * Fall through to the check below. | ||
369 | * (See include/linux/mfd/axp20x.h) | ||
370 | */ | ||
371 | reg = AXP806_DCDC_FREQ_CTRL; | ||
315 | case AXP221_ID: | 372 | case AXP221_ID: |
316 | case AXP223_ID: | 373 | case AXP223_ID: |
317 | case AXP809_ID: | 374 | case AXP809_ID: |
@@ -343,7 +400,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) | |||
343 | 400 | ||
344 | dcdcfreq = (dcdcfreq - min) / step; | 401 | dcdcfreq = (dcdcfreq - min) / step; |
345 | 402 | ||
346 | return regmap_update_bits(axp20x->regmap, AXP20X_DCDC_FREQ, | 403 | return regmap_update_bits(axp20x->regmap, reg, |
347 | AXP20X_FREQ_DCDC_MASK, dcdcfreq); | 404 | AXP20X_FREQ_DCDC_MASK, dcdcfreq); |
348 | } | 405 | } |
349 | 406 | ||
@@ -377,6 +434,7 @@ static int axp20x_regulator_parse_dt(struct platform_device *pdev) | |||
377 | static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode) | 434 | static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode) |
378 | { | 435 | { |
379 | struct axp20x_dev *axp20x = rdev_get_drvdata(rdev); | 436 | struct axp20x_dev *axp20x = rdev_get_drvdata(rdev); |
437 | unsigned int reg = AXP20X_DCDC_MODE; | ||
380 | unsigned int mask; | 438 | unsigned int mask; |
381 | 439 | ||
382 | switch (axp20x->variant) { | 440 | switch (axp20x->variant) { |
@@ -392,6 +450,13 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work | |||
392 | workmode <<= ffs(mask) - 1; | 450 | workmode <<= ffs(mask) - 1; |
393 | break; | 451 | break; |
394 | 452 | ||
453 | case AXP806_ID: | ||
454 | reg = AXP806_DCDC_MODE_CTRL2; | ||
455 | /* | ||
456 | * AXP806 DCDC regulator IDs have the same range as AXP22X. | ||
457 | * Fall through to the check below. | ||
458 | * (See include/linux/mfd/axp20x.h) | ||
459 | */ | ||
395 | case AXP221_ID: | 460 | case AXP221_ID: |
396 | case AXP223_ID: | 461 | case AXP223_ID: |
397 | case AXP809_ID: | 462 | case AXP809_ID: |
@@ -408,7 +473,34 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work | |||
408 | return -EINVAL; | 473 | return -EINVAL; |
409 | } | 474 | } |
410 | 475 | ||
411 | return regmap_update_bits(rdev->regmap, AXP20X_DCDC_MODE, mask, workmode); | 476 | return regmap_update_bits(rdev->regmap, reg, mask, workmode); |
477 | } | ||
478 | |||
479 | /* | ||
480 | * This function checks whether a regulator is part of a poly-phase | ||
481 | * output setup based on the registers settings. Returns true if it is. | ||
482 | */ | ||
483 | static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id) | ||
484 | { | ||
485 | u32 reg = 0; | ||
486 | |||
487 | /* Only AXP806 has poly-phase outputs */ | ||
488 | if (axp20x->variant != AXP806_ID) | ||
489 | return false; | ||
490 | |||
491 | regmap_read(axp20x->regmap, AXP806_DCDC_MODE_CTRL2, ®); | ||
492 | |||
493 | switch (id) { | ||
494 | case AXP806_DCDCB: | ||
495 | return (((reg & GENMASK(7, 6)) == BIT(6)) || | ||
496 | ((reg & GENMASK(7, 6)) == BIT(7))); | ||
497 | case AXP806_DCDCC: | ||
498 | return ((reg & GENMASK(7, 6)) == BIT(7)); | ||
499 | case AXP806_DCDCE: | ||
500 | return !!(reg & BIT(5)); | ||
501 | } | ||
502 | |||
503 | return false; | ||
412 | } | 504 | } |
413 | 505 | ||
414 | static int axp20x_regulator_probe(struct platform_device *pdev) | 506 | static int axp20x_regulator_probe(struct platform_device *pdev) |
@@ -440,6 +532,10 @@ static int axp20x_regulator_probe(struct platform_device *pdev) | |||
440 | drivevbus = of_property_read_bool(pdev->dev.parent->of_node, | 532 | drivevbus = of_property_read_bool(pdev->dev.parent->of_node, |
441 | "x-powers,drive-vbus-en"); | 533 | "x-powers,drive-vbus-en"); |
442 | break; | 534 | break; |
535 | case AXP806_ID: | ||
536 | regulators = axp806_regulators; | ||
537 | nregulators = AXP806_REG_ID_MAX; | ||
538 | break; | ||
443 | case AXP809_ID: | 539 | case AXP809_ID: |
444 | regulators = axp809_regulators; | 540 | regulators = axp809_regulators; |
445 | nregulators = AXP809_REG_ID_MAX; | 541 | nregulators = AXP809_REG_ID_MAX; |
@@ -458,6 +554,14 @@ static int axp20x_regulator_probe(struct platform_device *pdev) | |||
458 | struct regulator_desc *new_desc; | 554 | struct regulator_desc *new_desc; |
459 | 555 | ||
460 | /* | 556 | /* |
557 | * If this regulator is a slave in a poly-phase setup, | ||
558 | * skip it, as its controls are bound to the master | ||
559 | * regulator and won't work. | ||
560 | */ | ||
561 | if (axp20x_is_polyphase_slave(axp20x, i)) | ||
562 | continue; | ||
563 | |||
564 | /* | ||
461 | * Regulators DC1SW and DC5LDO are connected internally, | 565 | * Regulators DC1SW and DC5LDO are connected internally, |
462 | * so we have to handle their supply names separately. | 566 | * so we have to handle their supply names separately. |
463 | * | 567 | * |
diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c index e254272585b2..1b2acc43fea1 100644 --- a/drivers/regulator/qcom_rpm-regulator.c +++ b/drivers/regulator/qcom_rpm-regulator.c | |||
@@ -448,6 +448,44 @@ static struct regulator_ops switch_ops = { | |||
448 | }; | 448 | }; |
449 | 449 | ||
450 | /* | 450 | /* |
451 | * PM8018 regulators | ||
452 | */ | ||
453 | static const struct qcom_rpm_reg pm8018_pldo = { | ||
454 | .desc.linear_ranges = pldo_ranges, | ||
455 | .desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges), | ||
456 | .desc.n_voltages = 161, | ||
457 | .desc.ops = &uV_ops, | ||
458 | .parts = &rpm8960_ldo_parts, | ||
459 | .supports_force_mode_auto = false, | ||
460 | .supports_force_mode_bypass = false, | ||
461 | }; | ||
462 | |||
463 | static const struct qcom_rpm_reg pm8018_nldo = { | ||
464 | .desc.linear_ranges = nldo_ranges, | ||
465 | .desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges), | ||
466 | .desc.n_voltages = 64, | ||
467 | .desc.ops = &uV_ops, | ||
468 | .parts = &rpm8960_ldo_parts, | ||
469 | .supports_force_mode_auto = false, | ||
470 | .supports_force_mode_bypass = false, | ||
471 | }; | ||
472 | |||
473 | static const struct qcom_rpm_reg pm8018_smps = { | ||
474 | .desc.linear_ranges = smps_ranges, | ||
475 | .desc.n_linear_ranges = ARRAY_SIZE(smps_ranges), | ||
476 | .desc.n_voltages = 154, | ||
477 | .desc.ops = &uV_ops, | ||
478 | .parts = &rpm8960_smps_parts, | ||
479 | .supports_force_mode_auto = false, | ||
480 | .supports_force_mode_bypass = false, | ||
481 | }; | ||
482 | |||
483 | static const struct qcom_rpm_reg pm8018_switch = { | ||
484 | .desc.ops = &switch_ops, | ||
485 | .parts = &rpm8960_switch_parts, | ||
486 | }; | ||
487 | |||
488 | /* | ||
451 | * PM8058 regulators | 489 | * PM8058 regulators |
452 | */ | 490 | */ |
453 | static const struct qcom_rpm_reg pm8058_pldo = { | 491 | static const struct qcom_rpm_reg pm8058_pldo = { |
@@ -755,6 +793,32 @@ struct rpm_regulator_data { | |||
755 | const char *supply; | 793 | const char *supply; |
756 | }; | 794 | }; |
757 | 795 | ||
796 | static const struct rpm_regulator_data rpm_pm8018_regulators[] = { | ||
797 | { "s1", QCOM_RPM_PM8018_SMPS1, &pm8018_smps, "vdd_s1" }, | ||
798 | { "s2", QCOM_RPM_PM8018_SMPS2, &pm8018_smps, "vdd_s2" }, | ||
799 | { "s3", QCOM_RPM_PM8018_SMPS3, &pm8018_smps, "vdd_s3" }, | ||
800 | { "s4", QCOM_RPM_PM8018_SMPS4, &pm8018_smps, "vdd_s4" }, | ||
801 | { "s5", QCOM_RPM_PM8018_SMPS5, &pm8018_smps, "vdd_s5" }, | ||
802 | |||
803 | { "l2", QCOM_RPM_PM8018_LDO2, &pm8018_pldo, "vdd_l2" }, | ||
804 | { "l3", QCOM_RPM_PM8018_LDO3, &pm8018_pldo, "vdd_l3" }, | ||
805 | { "l4", QCOM_RPM_PM8018_LDO4, &pm8018_pldo, "vdd_l4" }, | ||
806 | { "l5", QCOM_RPM_PM8018_LDO5, &pm8018_pldo, "vdd_l5" }, | ||
807 | { "l6", QCOM_RPM_PM8018_LDO6, &pm8018_pldo, "vdd_l7" }, | ||
808 | { "l7", QCOM_RPM_PM8018_LDO7, &pm8018_pldo, "vdd_l7" }, | ||
809 | { "l8", QCOM_RPM_PM8018_LDO8, &pm8018_nldo, "vdd_l8" }, | ||
810 | { "l9", QCOM_RPM_PM8018_LDO9, &pm8921_nldo1200, | ||
811 | "vdd_l9_l10_l11_l12" }, | ||
812 | { "l10", QCOM_RPM_PM8018_LDO10, &pm8018_nldo, "vdd_l9_l10_l11_l12" }, | ||
813 | { "l11", QCOM_RPM_PM8018_LDO11, &pm8018_nldo, "vdd_l9_l10_l11_l12" }, | ||
814 | { "l12", QCOM_RPM_PM8018_LDO12, &pm8018_nldo, "vdd_l9_l10_l11_l12" }, | ||
815 | { "l14", QCOM_RPM_PM8018_LDO14, &pm8018_pldo, "vdd_l14" }, | ||
816 | |||
817 | { "lvs1", QCOM_RPM_PM8018_LVS1, &pm8018_switch, "lvs1_in" }, | ||
818 | |||
819 | { } | ||
820 | }; | ||
821 | |||
758 | static const struct rpm_regulator_data rpm_pm8058_regulators[] = { | 822 | static const struct rpm_regulator_data rpm_pm8058_regulators[] = { |
759 | { "l0", QCOM_RPM_PM8058_LDO0, &pm8058_nldo, "vdd_l0_l1_lvs" }, | 823 | { "l0", QCOM_RPM_PM8058_LDO0, &pm8058_nldo, "vdd_l0_l1_lvs" }, |
760 | { "l1", QCOM_RPM_PM8058_LDO1, &pm8058_nldo, "vdd_l0_l1_lvs" }, | 824 | { "l1", QCOM_RPM_PM8058_LDO1, &pm8058_nldo, "vdd_l0_l1_lvs" }, |
@@ -870,6 +934,8 @@ static const struct rpm_regulator_data rpm_pm8921_regulators[] = { | |||
870 | }; | 934 | }; |
871 | 935 | ||
872 | static const struct of_device_id rpm_of_match[] = { | 936 | static const struct of_device_id rpm_of_match[] = { |
937 | { .compatible = "qcom,rpm-pm8018-regulators", | ||
938 | .data = &rpm_pm8018_regulators }, | ||
873 | { .compatible = "qcom,rpm-pm8058-regulators", .data = &rpm_pm8058_regulators }, | 939 | { .compatible = "qcom,rpm-pm8058-regulators", .data = &rpm_pm8058_regulators }, |
874 | { .compatible = "qcom,rpm-pm8901-regulators", .data = &rpm_pm8901_regulators }, | 940 | { .compatible = "qcom,rpm-pm8901-regulators", .data = &rpm_pm8901_regulators }, |
875 | { .compatible = "qcom,rpm-pm8921-regulators", .data = &rpm_pm8921_regulators }, | 941 | { .compatible = "qcom,rpm-pm8921-regulators", .data = &rpm_pm8921_regulators }, |
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index a6767494d39b..3314bf299a51 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c | |||
@@ -1,11 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * Regulator driver for Rockchip RK808 | 2 | * Regulator driver for Rockchip RK808/RK818 |
3 | * | 3 | * |
4 | * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd | 4 | * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd |
5 | * | 5 | * |
6 | * Author: Chris Zhong <zyw@rock-chips.com> | 6 | * Author: Chris Zhong <zyw@rock-chips.com> |
7 | * Author: Zhang Qing <zhangqing@rock-chips.com> | 7 | * Author: Zhang Qing <zhangqing@rock-chips.com> |
8 | * | 8 | * |
9 | * Copyright (C) 2016 PHYTEC Messtechnik GmbH | ||
10 | * | ||
11 | * Author: Wadim Egorov <w.egorov@phytec.de> | ||
12 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | 13 | * This program is free software; you can redistribute it and/or modify it |
10 | * under the terms and conditions of the GNU General Public License, | 14 | * under the terms and conditions of the GNU General Public License, |
11 | * version 2, as published by the Free Software Foundation. | 15 | * version 2, as published by the Free Software Foundation. |
@@ -32,6 +36,12 @@ | |||
32 | #define RK808_BUCK4_VSEL_MASK 0xf | 36 | #define RK808_BUCK4_VSEL_MASK 0xf |
33 | #define RK808_LDO_VSEL_MASK 0x1f | 37 | #define RK808_LDO_VSEL_MASK 0x1f |
34 | 38 | ||
39 | #define RK818_BUCK_VSEL_MASK 0x3f | ||
40 | #define RK818_BUCK4_VSEL_MASK 0x1f | ||
41 | #define RK818_LDO_VSEL_MASK 0x1f | ||
42 | #define RK818_LDO3_ON_VSEL_MASK 0xf | ||
43 | #define RK818_BOOST_ON_VSEL_MASK 0xe0 | ||
44 | |||
35 | /* Ramp rate definitions for buck1 / buck2 only */ | 45 | /* Ramp rate definitions for buck1 / buck2 only */ |
36 | #define RK808_RAMP_RATE_OFFSET 3 | 46 | #define RK808_RAMP_RATE_OFFSET 3 |
37 | #define RK808_RAMP_RATE_MASK (3 << RK808_RAMP_RATE_OFFSET) | 47 | #define RK808_RAMP_RATE_MASK (3 << RK808_RAMP_RATE_OFFSET) |
@@ -454,6 +464,108 @@ static const struct regulator_desc rk808_reg[] = { | |||
454 | RK808_DCDC_EN_REG, BIT(6)), | 464 | RK808_DCDC_EN_REG, BIT(6)), |
455 | }; | 465 | }; |
456 | 466 | ||
467 | static const struct regulator_desc rk818_reg[] = { | ||
468 | { | ||
469 | .name = "DCDC_REG1", | ||
470 | .supply_name = "vcc1", | ||
471 | .of_match = of_match_ptr("DCDC_REG1"), | ||
472 | .regulators_node = of_match_ptr("regulators"), | ||
473 | .id = RK818_ID_DCDC1, | ||
474 | .ops = &rk808_reg_ops, | ||
475 | .type = REGULATOR_VOLTAGE, | ||
476 | .min_uV = 712500, | ||
477 | .uV_step = 12500, | ||
478 | .n_voltages = 64, | ||
479 | .vsel_reg = RK818_BUCK1_ON_VSEL_REG, | ||
480 | .vsel_mask = RK818_BUCK_VSEL_MASK, | ||
481 | .enable_reg = RK818_DCDC_EN_REG, | ||
482 | .enable_mask = BIT(0), | ||
483 | .owner = THIS_MODULE, | ||
484 | }, { | ||
485 | .name = "DCDC_REG2", | ||
486 | .supply_name = "vcc2", | ||
487 | .of_match = of_match_ptr("DCDC_REG2"), | ||
488 | .regulators_node = of_match_ptr("regulators"), | ||
489 | .id = RK818_ID_DCDC2, | ||
490 | .ops = &rk808_reg_ops, | ||
491 | .type = REGULATOR_VOLTAGE, | ||
492 | .min_uV = 712500, | ||
493 | .uV_step = 12500, | ||
494 | .n_voltages = 64, | ||
495 | .vsel_reg = RK818_BUCK2_ON_VSEL_REG, | ||
496 | .vsel_mask = RK818_BUCK_VSEL_MASK, | ||
497 | .enable_reg = RK818_DCDC_EN_REG, | ||
498 | .enable_mask = BIT(1), | ||
499 | .owner = THIS_MODULE, | ||
500 | }, { | ||
501 | .name = "DCDC_REG3", | ||
502 | .supply_name = "vcc3", | ||
503 | .of_match = of_match_ptr("DCDC_REG3"), | ||
504 | .regulators_node = of_match_ptr("regulators"), | ||
505 | .id = RK818_ID_DCDC3, | ||
506 | .ops = &rk808_switch_ops, | ||
507 | .type = REGULATOR_VOLTAGE, | ||
508 | .n_voltages = 1, | ||
509 | .enable_reg = RK818_DCDC_EN_REG, | ||
510 | .enable_mask = BIT(2), | ||
511 | .owner = THIS_MODULE, | ||
512 | }, | ||
513 | RK8XX_DESC(RK818_ID_DCDC4, "DCDC_REG4", "vcc4", 1800, 3600, 100, | ||
514 | RK818_BUCK4_ON_VSEL_REG, RK818_BUCK4_VSEL_MASK, | ||
515 | RK818_DCDC_EN_REG, BIT(3), 0), | ||
516 | RK8XX_DESC(RK818_ID_BOOST, "DCDC_BOOST", "boost", 4700, 5400, 100, | ||
517 | RK818_BOOST_LDO9_ON_VSEL_REG, RK818_BOOST_ON_VSEL_MASK, | ||
518 | RK818_DCDC_EN_REG, BIT(4), 0), | ||
519 | RK8XX_DESC(RK818_ID_LDO1, "LDO_REG1", "vcc6", 1800, 3400, 100, | ||
520 | RK818_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG, | ||
521 | BIT(0), 400), | ||
522 | RK8XX_DESC(RK818_ID_LDO2, "LDO_REG2", "vcc6", 1800, 3400, 100, | ||
523 | RK818_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG, | ||
524 | BIT(1), 400), | ||
525 | { | ||
526 | .name = "LDO_REG3", | ||
527 | .supply_name = "vcc7", | ||
528 | .of_match = of_match_ptr("LDO_REG3"), | ||
529 | .regulators_node = of_match_ptr("regulators"), | ||
530 | .id = RK818_ID_LDO3, | ||
531 | .ops = &rk808_reg_ops_ranges, | ||
532 | .type = REGULATOR_VOLTAGE, | ||
533 | .n_voltages = 16, | ||
534 | .linear_ranges = rk808_ldo3_voltage_ranges, | ||
535 | .n_linear_ranges = ARRAY_SIZE(rk808_ldo3_voltage_ranges), | ||
536 | .vsel_reg = RK818_LDO3_ON_VSEL_REG, | ||
537 | .vsel_mask = RK818_LDO3_ON_VSEL_MASK, | ||
538 | .enable_reg = RK818_LDO_EN_REG, | ||
539 | .enable_mask = BIT(2), | ||
540 | .enable_time = 400, | ||
541 | .owner = THIS_MODULE, | ||
542 | }, | ||
543 | RK8XX_DESC(RK818_ID_LDO4, "LDO_REG4", "vcc8", 1800, 3400, 100, | ||
544 | RK818_LDO4_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG, | ||
545 | BIT(3), 400), | ||
546 | RK8XX_DESC(RK818_ID_LDO5, "LDO_REG5", "vcc7", 1800, 3400, 100, | ||
547 | RK818_LDO5_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG, | ||
548 | BIT(4), 400), | ||
549 | RK8XX_DESC(RK818_ID_LDO6, "LDO_REG6", "vcc8", 800, 2500, 100, | ||
550 | RK818_LDO6_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG, | ||
551 | BIT(5), 400), | ||
552 | RK8XX_DESC(RK818_ID_LDO7, "LDO_REG7", "vcc7", 800, 2500, 100, | ||
553 | RK818_LDO7_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG, | ||
554 | BIT(6), 400), | ||
555 | RK8XX_DESC(RK818_ID_LDO8, "LDO_REG8", "vcc8", 1800, 3400, 100, | ||
556 | RK818_LDO8_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG, | ||
557 | BIT(7), 400), | ||
558 | RK8XX_DESC(RK818_ID_LDO9, "LDO_REG9", "vcc9", 1800, 3400, 100, | ||
559 | RK818_BOOST_LDO9_ON_VSEL_REG, RK818_LDO_VSEL_MASK, | ||
560 | RK818_DCDC_EN_REG, BIT(5), 400), | ||
561 | RK8XX_DESC_SWITCH(RK818_ID_SWITCH, "SWITCH_REG", "vcc9", | ||
562 | RK818_DCDC_EN_REG, BIT(6)), | ||
563 | RK8XX_DESC_SWITCH(RK818_ID_HDMI_SWITCH, "HDMI_SWITCH", "h_5v", | ||
564 | RK818_H5V_EN_REG, BIT(0)), | ||
565 | RK8XX_DESC_SWITCH(RK818_ID_OTG_SWITCH, "OTG_SWITCH", "usb", | ||
566 | RK818_DCDC_EN_REG, BIT(7)), | ||
567 | }; | ||
568 | |||
457 | static int rk808_regulator_dt_parse_pdata(struct device *dev, | 569 | static int rk808_regulator_dt_parse_pdata(struct device *dev, |
458 | struct device *client_dev, | 570 | struct device *client_dev, |
459 | struct regmap *map, | 571 | struct regmap *map, |
@@ -499,7 +611,8 @@ static int rk808_regulator_probe(struct platform_device *pdev) | |||
499 | struct regulator_config config = {}; | 611 | struct regulator_config config = {}; |
500 | struct regulator_dev *rk808_rdev; | 612 | struct regulator_dev *rk808_rdev; |
501 | struct rk808_regulator_data *pdata; | 613 | struct rk808_regulator_data *pdata; |
502 | int ret, i; | 614 | const struct regulator_desc *regulators; |
615 | int ret, i, nregulators; | ||
503 | 616 | ||
504 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 617 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
505 | if (!pdata) | 618 | if (!pdata) |
@@ -512,14 +625,29 @@ static int rk808_regulator_probe(struct platform_device *pdev) | |||
512 | 625 | ||
513 | platform_set_drvdata(pdev, pdata); | 626 | platform_set_drvdata(pdev, pdata); |
514 | 627 | ||
628 | switch (rk808->variant) { | ||
629 | case RK808_ID: | ||
630 | regulators = rk808_reg; | ||
631 | nregulators = RK808_NUM_REGULATORS; | ||
632 | break; | ||
633 | case RK818_ID: | ||
634 | regulators = rk818_reg; | ||
635 | nregulators = RK818_NUM_REGULATORS; | ||
636 | break; | ||
637 | default: | ||
638 | dev_err(&client->dev, "unsupported RK8XX ID %lu\n", | ||
639 | rk808->variant); | ||
640 | return -EINVAL; | ||
641 | } | ||
642 | |||
515 | config.dev = &client->dev; | 643 | config.dev = &client->dev; |
516 | config.driver_data = pdata; | 644 | config.driver_data = pdata; |
517 | config.regmap = rk808->regmap; | 645 | config.regmap = rk808->regmap; |
518 | 646 | ||
519 | /* Instantiate the regulators */ | 647 | /* Instantiate the regulators */ |
520 | for (i = 0; i < RK808_NUM_REGULATORS; i++) { | 648 | for (i = 0; i < nregulators; i++) { |
521 | rk808_rdev = devm_regulator_register(&pdev->dev, | 649 | rk808_rdev = devm_regulator_register(&pdev->dev, |
522 | &rk808_reg[i], &config); | 650 | ®ulators[i], &config); |
523 | if (IS_ERR(rk808_rdev)) { | 651 | if (IS_ERR(rk808_rdev)) { |
524 | dev_err(&client->dev, | 652 | dev_err(&client->dev, |
525 | "failed to register %d regulator\n", i); | 653 | "failed to register %d regulator\n", i); |
@@ -539,8 +667,9 @@ static struct platform_driver rk808_regulator_driver = { | |||
539 | 667 | ||
540 | module_platform_driver(rk808_regulator_driver); | 668 | module_platform_driver(rk808_regulator_driver); |
541 | 669 | ||
542 | MODULE_DESCRIPTION("regulator driver for the rk808 series PMICs"); | 670 | MODULE_DESCRIPTION("regulator driver for the RK808/RK818 series PMICs"); |
543 | MODULE_AUTHOR("Chris Zhong<zyw@rock-chips.com>"); | 671 | MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>"); |
544 | MODULE_AUTHOR("Zhang Qing<zhangqing@rock-chips.com>"); | 672 | MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>"); |
673 | MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>"); | ||
545 | MODULE_LICENSE("GPL"); | 674 | MODULE_LICENSE("GPL"); |
546 | MODULE_ALIAS("platform:rk808-regulator"); | 675 | MODULE_ALIAS("platform:rk808-regulator"); |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index e215f50794b6..d1e080701264 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -187,6 +187,16 @@ config RTC_DRV_ABX80X | |||
187 | This driver can also be built as a module. If so, the module | 187 | This driver can also be built as a module. If so, the module |
188 | will be called rtc-abx80x. | 188 | will be called rtc-abx80x. |
189 | 189 | ||
190 | config RTC_DRV_AC100 | ||
191 | tristate "X-Powers AC100" | ||
192 | depends on MFD_AC100 | ||
193 | help | ||
194 | If you say yes here you get support for the real-time clock found | ||
195 | in X-Powers AC100 family peripheral ICs. | ||
196 | |||
197 | This driver can also be built as a module. If so, the module | ||
198 | will be called rtc-ac100. | ||
199 | |||
190 | config RTC_DRV_AS3722 | 200 | config RTC_DRV_AS3722 |
191 | tristate "ams AS3722 RTC driver" | 201 | tristate "ams AS3722 RTC driver" |
192 | depends on MFD_AS3722 | 202 | depends on MFD_AS3722 |
@@ -328,11 +338,11 @@ config RTC_DRV_MAX77686 | |||
328 | will be called rtc-max77686. | 338 | will be called rtc-max77686. |
329 | 339 | ||
330 | config RTC_DRV_RK808 | 340 | config RTC_DRV_RK808 |
331 | tristate "Rockchip RK808 RTC" | 341 | tristate "Rockchip RK808/RK818 RTC" |
332 | depends on MFD_RK808 | 342 | depends on MFD_RK808 |
333 | help | 343 | help |
334 | If you say yes here you will get support for the | 344 | If you say yes here you will get support for the |
335 | RTC of RK808 PMIC. | 345 | RTC of RK808 and RK818 PMIC. |
336 | 346 | ||
337 | This driver can also be built as a module. If so, the module | 347 | This driver can also be built as a module. If so, the module |
338 | will be called rk808-rtc. | 348 | will be called rk808-rtc. |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 7cf7ad559c79..8fb994bacdf7 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -27,6 +27,7 @@ obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o | |||
27 | obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o | 27 | obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o |
28 | obj-$(CONFIG_RTC_DRV_ABB5ZES3) += rtc-ab-b5ze-s3.o | 28 | obj-$(CONFIG_RTC_DRV_ABB5ZES3) += rtc-ab-b5ze-s3.o |
29 | obj-$(CONFIG_RTC_DRV_ABX80X) += rtc-abx80x.o | 29 | obj-$(CONFIG_RTC_DRV_ABX80X) += rtc-abx80x.o |
30 | obj-$(CONFIG_RTC_DRV_AC100) += rtc-ac100.o | ||
30 | obj-$(CONFIG_RTC_DRV_ARMADA38X) += rtc-armada38x.o | 31 | obj-$(CONFIG_RTC_DRV_ARMADA38X) += rtc-armada38x.o |
31 | obj-$(CONFIG_RTC_DRV_AS3722) += rtc-as3722.o | 32 | obj-$(CONFIG_RTC_DRV_AS3722) += rtc-as3722.o |
32 | obj-$(CONFIG_RTC_DRV_ASM9260) += rtc-asm9260.o | 33 | obj-$(CONFIG_RTC_DRV_ASM9260) += rtc-asm9260.o |
diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c new file mode 100644 index 000000000000..70b4fd0f6122 --- /dev/null +++ b/drivers/rtc/rtc-ac100.c | |||
@@ -0,0 +1,627 @@ | |||
1 | /* | ||
2 | * RTC Driver for X-Powers AC100 | ||
3 | * | ||
4 | * Copyright (c) 2016 Chen-Yu Tsai | ||
5 | * | ||
6 | * Chen-Yu Tsai <wens@csie.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/bcd.h> | ||
19 | #include <linux/clk-provider.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/mfd/ac100.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/mutex.h> | ||
26 | #include <linux/of.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/regmap.h> | ||
29 | #include <linux/rtc.h> | ||
30 | #include <linux/types.h> | ||
31 | |||
32 | /* Control register */ | ||
33 | #define AC100_RTC_CTRL_24HOUR BIT(0) | ||
34 | |||
35 | /* Clock output register bits */ | ||
36 | #define AC100_CLKOUT_PRE_DIV_SHIFT 5 | ||
37 | #define AC100_CLKOUT_PRE_DIV_WIDTH 3 | ||
38 | #define AC100_CLKOUT_MUX_SHIFT 4 | ||
39 | #define AC100_CLKOUT_MUX_WIDTH 1 | ||
40 | #define AC100_CLKOUT_DIV_SHIFT 1 | ||
41 | #define AC100_CLKOUT_DIV_WIDTH 3 | ||
42 | #define AC100_CLKOUT_EN BIT(0) | ||
43 | |||
44 | /* RTC */ | ||
45 | #define AC100_RTC_SEC_MASK GENMASK(6, 0) | ||
46 | #define AC100_RTC_MIN_MASK GENMASK(6, 0) | ||
47 | #define AC100_RTC_HOU_MASK GENMASK(5, 0) | ||
48 | #define AC100_RTC_WEE_MASK GENMASK(2, 0) | ||
49 | #define AC100_RTC_DAY_MASK GENMASK(5, 0) | ||
50 | #define AC100_RTC_MON_MASK GENMASK(4, 0) | ||
51 | #define AC100_RTC_YEA_MASK GENMASK(7, 0) | ||
52 | #define AC100_RTC_YEA_LEAP BIT(15) | ||
53 | #define AC100_RTC_UPD_TRIGGER BIT(15) | ||
54 | |||
55 | /* Alarm (wall clock) */ | ||
56 | #define AC100_ALM_INT_ENABLE BIT(0) | ||
57 | |||
58 | #define AC100_ALM_SEC_MASK GENMASK(6, 0) | ||
59 | #define AC100_ALM_MIN_MASK GENMASK(6, 0) | ||
60 | #define AC100_ALM_HOU_MASK GENMASK(5, 0) | ||
61 | #define AC100_ALM_WEE_MASK GENMASK(2, 0) | ||
62 | #define AC100_ALM_DAY_MASK GENMASK(5, 0) | ||
63 | #define AC100_ALM_MON_MASK GENMASK(4, 0) | ||
64 | #define AC100_ALM_YEA_MASK GENMASK(7, 0) | ||
65 | #define AC100_ALM_ENABLE_FLAG BIT(15) | ||
66 | #define AC100_ALM_UPD_TRIGGER BIT(15) | ||
67 | |||
68 | /* | ||
69 | * The year parameter passed to the driver is usually an offset relative to | ||
70 | * the year 1900. This macro is used to convert this offset to another one | ||
71 | * relative to the minimum year allowed by the hardware. | ||
72 | * | ||
73 | * The year range is 1970 - 2069. This range is selected to match Allwinner's | ||
74 | * driver. | ||
75 | */ | ||
76 | #define AC100_YEAR_MIN 1970 | ||
77 | #define AC100_YEAR_MAX 2069 | ||
78 | #define AC100_YEAR_OFF (AC100_YEAR_MIN - 1900) | ||
79 | |||
80 | struct ac100_clkout { | ||
81 | struct clk_hw hw; | ||
82 | struct regmap *regmap; | ||
83 | u8 offset; | ||
84 | }; | ||
85 | |||
86 | #define to_ac100_clkout(_hw) container_of(_hw, struct ac100_clkout, hw) | ||
87 | |||
88 | #define AC100_RTC_32K_NAME "ac100-rtc-32k" | ||
89 | #define AC100_RTC_32K_RATE 32768 | ||
90 | #define AC100_CLKOUT_NUM 3 | ||
91 | |||
92 | static const char * const ac100_clkout_names[AC100_CLKOUT_NUM] = { | ||
93 | "ac100-cko1-rtc", | ||
94 | "ac100-cko2-rtc", | ||
95 | "ac100-cko3-rtc", | ||
96 | }; | ||
97 | |||
98 | struct ac100_rtc_dev { | ||
99 | struct rtc_device *rtc; | ||
100 | struct device *dev; | ||
101 | struct regmap *regmap; | ||
102 | int irq; | ||
103 | unsigned long alarm; | ||
104 | |||
105 | struct clk_hw *rtc_32k_clk; | ||
106 | struct ac100_clkout clks[AC100_CLKOUT_NUM]; | ||
107 | struct clk_hw_onecell_data *clk_data; | ||
108 | }; | ||
109 | |||
110 | /** | ||
111 | * Clock controls for 3 clock output pins | ||
112 | */ | ||
113 | |||
114 | static const struct clk_div_table ac100_clkout_prediv[] = { | ||
115 | { .val = 0, .div = 1 }, | ||
116 | { .val = 1, .div = 2 }, | ||
117 | { .val = 2, .div = 4 }, | ||
118 | { .val = 3, .div = 8 }, | ||
119 | { .val = 4, .div = 16 }, | ||
120 | { .val = 5, .div = 32 }, | ||
121 | { .val = 6, .div = 64 }, | ||
122 | { .val = 7, .div = 122 }, | ||
123 | { }, | ||
124 | }; | ||
125 | |||
126 | /* Abuse the fact that one parent is 32768 Hz, and the other is 4 MHz */ | ||
127 | static unsigned long ac100_clkout_recalc_rate(struct clk_hw *hw, | ||
128 | unsigned long prate) | ||
129 | { | ||
130 | struct ac100_clkout *clk = to_ac100_clkout(hw); | ||
131 | unsigned int reg, div; | ||
132 | |||
133 | regmap_read(clk->regmap, clk->offset, ®); | ||
134 | |||
135 | /* Handle pre-divider first */ | ||
136 | if (prate != AC100_RTC_32K_RATE) { | ||
137 | div = (reg >> AC100_CLKOUT_PRE_DIV_SHIFT) & | ||
138 | ((1 << AC100_CLKOUT_PRE_DIV_WIDTH) - 1); | ||
139 | prate = divider_recalc_rate(hw, prate, div, | ||
140 | ac100_clkout_prediv, 0); | ||
141 | } | ||
142 | |||
143 | div = (reg >> AC100_CLKOUT_DIV_SHIFT) & | ||
144 | (BIT(AC100_CLKOUT_DIV_WIDTH) - 1); | ||
145 | return divider_recalc_rate(hw, prate, div, NULL, | ||
146 | CLK_DIVIDER_POWER_OF_TWO); | ||
147 | } | ||
148 | |||
149 | static long ac100_clkout_round_rate(struct clk_hw *hw, unsigned long rate, | ||
150 | unsigned long prate) | ||
151 | { | ||
152 | unsigned long best_rate = 0, tmp_rate, tmp_prate; | ||
153 | int i; | ||
154 | |||
155 | if (prate == AC100_RTC_32K_RATE) | ||
156 | return divider_round_rate(hw, rate, &prate, NULL, | ||
157 | AC100_CLKOUT_DIV_WIDTH, | ||
158 | CLK_DIVIDER_POWER_OF_TWO); | ||
159 | |||
160 | for (i = 0; ac100_clkout_prediv[i].div; i++) { | ||
161 | tmp_prate = DIV_ROUND_UP(prate, ac100_clkout_prediv[i].val); | ||
162 | tmp_rate = divider_round_rate(hw, rate, &tmp_prate, NULL, | ||
163 | AC100_CLKOUT_DIV_WIDTH, | ||
164 | CLK_DIVIDER_POWER_OF_TWO); | ||
165 | |||
166 | if (tmp_rate > rate) | ||
167 | continue; | ||
168 | if (rate - tmp_rate < best_rate - tmp_rate) | ||
169 | best_rate = tmp_rate; | ||
170 | } | ||
171 | |||
172 | return best_rate; | ||
173 | } | ||
174 | |||
175 | static int ac100_clkout_determine_rate(struct clk_hw *hw, | ||
176 | struct clk_rate_request *req) | ||
177 | { | ||
178 | struct clk_hw *best_parent; | ||
179 | unsigned long best = 0; | ||
180 | int i, num_parents = clk_hw_get_num_parents(hw); | ||
181 | |||
182 | for (i = 0; i < num_parents; i++) { | ||
183 | struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i); | ||
184 | unsigned long tmp, prate = clk_hw_get_rate(parent); | ||
185 | |||
186 | tmp = ac100_clkout_round_rate(hw, req->rate, prate); | ||
187 | |||
188 | if (tmp > req->rate) | ||
189 | continue; | ||
190 | if (req->rate - tmp < req->rate - best) { | ||
191 | best = tmp; | ||
192 | best_parent = parent; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | if (!best) | ||
197 | return -EINVAL; | ||
198 | |||
199 | req->best_parent_hw = best_parent; | ||
200 | req->best_parent_rate = best; | ||
201 | req->rate = best; | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int ac100_clkout_set_rate(struct clk_hw *hw, unsigned long rate, | ||
207 | unsigned long prate) | ||
208 | { | ||
209 | struct ac100_clkout *clk = to_ac100_clkout(hw); | ||
210 | int div = 0, pre_div = 0; | ||
211 | |||
212 | do { | ||
213 | div = divider_get_val(rate * ac100_clkout_prediv[pre_div].div, | ||
214 | prate, NULL, AC100_CLKOUT_DIV_WIDTH, | ||
215 | CLK_DIVIDER_POWER_OF_TWO); | ||
216 | if (div >= 0) | ||
217 | break; | ||
218 | } while (prate != AC100_RTC_32K_RATE && | ||
219 | ac100_clkout_prediv[++pre_div].div); | ||
220 | |||
221 | if (div < 0) | ||
222 | return div; | ||
223 | |||
224 | pre_div = ac100_clkout_prediv[pre_div].val; | ||
225 | |||
226 | regmap_update_bits(clk->regmap, clk->offset, | ||
227 | ((1 << AC100_CLKOUT_DIV_WIDTH) - 1) << AC100_CLKOUT_DIV_SHIFT | | ||
228 | ((1 << AC100_CLKOUT_PRE_DIV_WIDTH) - 1) << AC100_CLKOUT_PRE_DIV_SHIFT, | ||
229 | (div - 1) << AC100_CLKOUT_DIV_SHIFT | | ||
230 | (pre_div - 1) << AC100_CLKOUT_PRE_DIV_SHIFT); | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static int ac100_clkout_prepare(struct clk_hw *hw) | ||
236 | { | ||
237 | struct ac100_clkout *clk = to_ac100_clkout(hw); | ||
238 | |||
239 | return regmap_update_bits(clk->regmap, clk->offset, AC100_CLKOUT_EN, | ||
240 | AC100_CLKOUT_EN); | ||
241 | } | ||
242 | |||
243 | static void ac100_clkout_unprepare(struct clk_hw *hw) | ||
244 | { | ||
245 | struct ac100_clkout *clk = to_ac100_clkout(hw); | ||
246 | |||
247 | regmap_update_bits(clk->regmap, clk->offset, AC100_CLKOUT_EN, 0); | ||
248 | } | ||
249 | |||
250 | static int ac100_clkout_is_prepared(struct clk_hw *hw) | ||
251 | { | ||
252 | struct ac100_clkout *clk = to_ac100_clkout(hw); | ||
253 | unsigned int reg; | ||
254 | |||
255 | regmap_read(clk->regmap, clk->offset, ®); | ||
256 | |||
257 | return reg & AC100_CLKOUT_EN; | ||
258 | } | ||
259 | |||
260 | static u8 ac100_clkout_get_parent(struct clk_hw *hw) | ||
261 | { | ||
262 | struct ac100_clkout *clk = to_ac100_clkout(hw); | ||
263 | unsigned int reg; | ||
264 | |||
265 | regmap_read(clk->regmap, clk->offset, ®); | ||
266 | |||
267 | return (reg >> AC100_CLKOUT_MUX_SHIFT) & 0x1; | ||
268 | } | ||
269 | |||
270 | static int ac100_clkout_set_parent(struct clk_hw *hw, u8 index) | ||
271 | { | ||
272 | struct ac100_clkout *clk = to_ac100_clkout(hw); | ||
273 | |||
274 | return regmap_update_bits(clk->regmap, clk->offset, | ||
275 | BIT(AC100_CLKOUT_MUX_SHIFT), | ||
276 | index ? BIT(AC100_CLKOUT_MUX_SHIFT) : 0); | ||
277 | } | ||
278 | |||
279 | static const struct clk_ops ac100_clkout_ops = { | ||
280 | .prepare = ac100_clkout_prepare, | ||
281 | .unprepare = ac100_clkout_unprepare, | ||
282 | .is_prepared = ac100_clkout_is_prepared, | ||
283 | .recalc_rate = ac100_clkout_recalc_rate, | ||
284 | .determine_rate = ac100_clkout_determine_rate, | ||
285 | .get_parent = ac100_clkout_get_parent, | ||
286 | .set_parent = ac100_clkout_set_parent, | ||
287 | .set_rate = ac100_clkout_set_rate, | ||
288 | }; | ||
289 | |||
290 | static int ac100_rtc_register_clks(struct ac100_rtc_dev *chip) | ||
291 | { | ||
292 | struct device_node *np = chip->dev->of_node; | ||
293 | const char *parents[2] = {AC100_RTC_32K_NAME}; | ||
294 | int i, ret; | ||
295 | |||
296 | chip->clk_data = devm_kzalloc(chip->dev, sizeof(*chip->clk_data) + | ||
297 | sizeof(*chip->clk_data->hws) * | ||
298 | AC100_CLKOUT_NUM, | ||
299 | GFP_KERNEL); | ||
300 | if (!chip->clk_data) | ||
301 | return -ENOMEM; | ||
302 | |||
303 | chip->rtc_32k_clk = clk_hw_register_fixed_rate(chip->dev, | ||
304 | AC100_RTC_32K_NAME, | ||
305 | NULL, 0, | ||
306 | AC100_RTC_32K_RATE); | ||
307 | if (IS_ERR(chip->rtc_32k_clk)) { | ||
308 | ret = PTR_ERR(chip->rtc_32k_clk); | ||
309 | dev_err(chip->dev, "Failed to register RTC-32k clock: %d\n", | ||
310 | ret); | ||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | parents[1] = of_clk_get_parent_name(np, 0); | ||
315 | if (!parents[1]) { | ||
316 | dev_err(chip->dev, "Failed to get ADDA 4M clock\n"); | ||
317 | return -EINVAL; | ||
318 | } | ||
319 | |||
320 | for (i = 0; i < AC100_CLKOUT_NUM; i++) { | ||
321 | struct ac100_clkout *clk = &chip->clks[i]; | ||
322 | struct clk_init_data init = { | ||
323 | .name = ac100_clkout_names[i], | ||
324 | .ops = &ac100_clkout_ops, | ||
325 | .parent_names = parents, | ||
326 | .num_parents = ARRAY_SIZE(parents), | ||
327 | .flags = 0, | ||
328 | }; | ||
329 | |||
330 | clk->regmap = chip->regmap; | ||
331 | clk->offset = AC100_CLKOUT_CTRL1 + i; | ||
332 | clk->hw.init = &init; | ||
333 | |||
334 | ret = devm_clk_hw_register(chip->dev, &clk->hw); | ||
335 | if (ret) { | ||
336 | dev_err(chip->dev, "Failed to register clk '%s': %d\n", | ||
337 | init.name, ret); | ||
338 | goto err_unregister_rtc_32k; | ||
339 | } | ||
340 | |||
341 | chip->clk_data->hws[i] = &clk->hw; | ||
342 | } | ||
343 | |||
344 | chip->clk_data->num = i; | ||
345 | ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, chip->clk_data); | ||
346 | if (ret) | ||
347 | goto err_unregister_rtc_32k; | ||
348 | |||
349 | return 0; | ||
350 | |||
351 | err_unregister_rtc_32k: | ||
352 | clk_unregister_fixed_rate(chip->rtc_32k_clk->clk); | ||
353 | |||
354 | return ret; | ||
355 | } | ||
356 | |||
357 | static void ac100_rtc_unregister_clks(struct ac100_rtc_dev *chip) | ||
358 | { | ||
359 | of_clk_del_provider(chip->dev->of_node); | ||
360 | clk_unregister_fixed_rate(chip->rtc_32k_clk->clk); | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * RTC related bits | ||
365 | */ | ||
366 | static int ac100_rtc_get_time(struct device *dev, struct rtc_time *rtc_tm) | ||
367 | { | ||
368 | struct ac100_rtc_dev *chip = dev_get_drvdata(dev); | ||
369 | struct regmap *regmap = chip->regmap; | ||
370 | u16 reg[7]; | ||
371 | int ret; | ||
372 | |||
373 | ret = regmap_bulk_read(regmap, AC100_RTC_SEC, reg, 7); | ||
374 | if (ret) | ||
375 | return ret; | ||
376 | |||
377 | rtc_tm->tm_sec = bcd2bin(reg[0] & AC100_RTC_SEC_MASK); | ||
378 | rtc_tm->tm_min = bcd2bin(reg[1] & AC100_RTC_MIN_MASK); | ||
379 | rtc_tm->tm_hour = bcd2bin(reg[2] & AC100_RTC_HOU_MASK); | ||
380 | rtc_tm->tm_wday = bcd2bin(reg[3] & AC100_RTC_WEE_MASK); | ||
381 | rtc_tm->tm_mday = bcd2bin(reg[4] & AC100_RTC_DAY_MASK); | ||
382 | rtc_tm->tm_mon = bcd2bin(reg[5] & AC100_RTC_MON_MASK) - 1; | ||
383 | rtc_tm->tm_year = bcd2bin(reg[6] & AC100_RTC_YEA_MASK) + | ||
384 | AC100_YEAR_OFF; | ||
385 | |||
386 | return rtc_valid_tm(rtc_tm); | ||
387 | } | ||
388 | |||
389 | static int ac100_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm) | ||
390 | { | ||
391 | struct ac100_rtc_dev *chip = dev_get_drvdata(dev); | ||
392 | struct regmap *regmap = chip->regmap; | ||
393 | int year; | ||
394 | u16 reg[8]; | ||
395 | |||
396 | /* our RTC has a limited year range... */ | ||
397 | year = rtc_tm->tm_year - AC100_YEAR_OFF; | ||
398 | if (year < 0 || year > (AC100_YEAR_MAX - 1900)) { | ||
399 | dev_err(dev, "rtc only supports year in range %d - %d\n", | ||
400 | AC100_YEAR_MIN, AC100_YEAR_MAX); | ||
401 | return -EINVAL; | ||
402 | } | ||
403 | |||
404 | /* convert to BCD */ | ||
405 | reg[0] = bin2bcd(rtc_tm->tm_sec) & AC100_RTC_SEC_MASK; | ||
406 | reg[1] = bin2bcd(rtc_tm->tm_min) & AC100_RTC_MIN_MASK; | ||
407 | reg[2] = bin2bcd(rtc_tm->tm_hour) & AC100_RTC_HOU_MASK; | ||
408 | reg[3] = bin2bcd(rtc_tm->tm_wday) & AC100_RTC_WEE_MASK; | ||
409 | reg[4] = bin2bcd(rtc_tm->tm_mday) & AC100_RTC_DAY_MASK; | ||
410 | reg[5] = bin2bcd(rtc_tm->tm_mon + 1) & AC100_RTC_MON_MASK; | ||
411 | reg[6] = bin2bcd(year) & AC100_RTC_YEA_MASK; | ||
412 | /* trigger write */ | ||
413 | reg[7] = AC100_RTC_UPD_TRIGGER; | ||
414 | |||
415 | /* Is it a leap year? */ | ||
416 | if (is_leap_year(year + AC100_YEAR_OFF + 1900)) | ||
417 | reg[6] |= AC100_RTC_YEA_LEAP; | ||
418 | |||
419 | return regmap_bulk_write(regmap, AC100_RTC_SEC, reg, 8); | ||
420 | } | ||
421 | |||
422 | static int ac100_rtc_alarm_irq_enable(struct device *dev, unsigned int en) | ||
423 | { | ||
424 | struct ac100_rtc_dev *chip = dev_get_drvdata(dev); | ||
425 | struct regmap *regmap = chip->regmap; | ||
426 | unsigned int val; | ||
427 | |||
428 | val = en ? AC100_ALM_INT_ENABLE : 0; | ||
429 | |||
430 | return regmap_write(regmap, AC100_ALM_INT_ENA, val); | ||
431 | } | ||
432 | |||
433 | static int ac100_rtc_get_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
434 | { | ||
435 | struct ac100_rtc_dev *chip = dev_get_drvdata(dev); | ||
436 | struct regmap *regmap = chip->regmap; | ||
437 | struct rtc_time *alrm_tm = &alrm->time; | ||
438 | u16 reg[7]; | ||
439 | unsigned int val; | ||
440 | int ret; | ||
441 | |||
442 | ret = regmap_read(regmap, AC100_ALM_INT_ENA, &val); | ||
443 | if (ret) | ||
444 | return ret; | ||
445 | |||
446 | alrm->enabled = !!(val & AC100_ALM_INT_ENABLE); | ||
447 | |||
448 | ret = regmap_bulk_read(regmap, AC100_ALM_SEC, reg, 7); | ||
449 | if (ret) | ||
450 | return ret; | ||
451 | |||
452 | alrm_tm->tm_sec = bcd2bin(reg[0] & AC100_ALM_SEC_MASK); | ||
453 | alrm_tm->tm_min = bcd2bin(reg[1] & AC100_ALM_MIN_MASK); | ||
454 | alrm_tm->tm_hour = bcd2bin(reg[2] & AC100_ALM_HOU_MASK); | ||
455 | alrm_tm->tm_wday = bcd2bin(reg[3] & AC100_ALM_WEE_MASK); | ||
456 | alrm_tm->tm_mday = bcd2bin(reg[4] & AC100_ALM_DAY_MASK); | ||
457 | alrm_tm->tm_mon = bcd2bin(reg[5] & AC100_ALM_MON_MASK) - 1; | ||
458 | alrm_tm->tm_year = bcd2bin(reg[6] & AC100_ALM_YEA_MASK) + | ||
459 | AC100_YEAR_OFF; | ||
460 | |||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | static int ac100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
465 | { | ||
466 | struct ac100_rtc_dev *chip = dev_get_drvdata(dev); | ||
467 | struct regmap *regmap = chip->regmap; | ||
468 | struct rtc_time *alrm_tm = &alrm->time; | ||
469 | u16 reg[8]; | ||
470 | int year; | ||
471 | int ret; | ||
472 | |||
473 | /* our alarm has a limited year range... */ | ||
474 | year = alrm_tm->tm_year - AC100_YEAR_OFF; | ||
475 | if (year < 0 || year > (AC100_YEAR_MAX - 1900)) { | ||
476 | dev_err(dev, "alarm only supports year in range %d - %d\n", | ||
477 | AC100_YEAR_MIN, AC100_YEAR_MAX); | ||
478 | return -EINVAL; | ||
479 | } | ||
480 | |||
481 | /* convert to BCD */ | ||
482 | reg[0] = (bin2bcd(alrm_tm->tm_sec) & AC100_ALM_SEC_MASK) | | ||
483 | AC100_ALM_ENABLE_FLAG; | ||
484 | reg[1] = (bin2bcd(alrm_tm->tm_min) & AC100_ALM_MIN_MASK) | | ||
485 | AC100_ALM_ENABLE_FLAG; | ||
486 | reg[2] = (bin2bcd(alrm_tm->tm_hour) & AC100_ALM_HOU_MASK) | | ||
487 | AC100_ALM_ENABLE_FLAG; | ||
488 | /* Do not enable weekday alarm */ | ||
489 | reg[3] = bin2bcd(alrm_tm->tm_wday) & AC100_ALM_WEE_MASK; | ||
490 | reg[4] = (bin2bcd(alrm_tm->tm_mday) & AC100_ALM_DAY_MASK) | | ||
491 | AC100_ALM_ENABLE_FLAG; | ||
492 | reg[5] = (bin2bcd(alrm_tm->tm_mon + 1) & AC100_ALM_MON_MASK) | | ||
493 | AC100_ALM_ENABLE_FLAG; | ||
494 | reg[6] = (bin2bcd(year) & AC100_ALM_YEA_MASK) | | ||
495 | AC100_ALM_ENABLE_FLAG; | ||
496 | /* trigger write */ | ||
497 | reg[7] = AC100_ALM_UPD_TRIGGER; | ||
498 | |||
499 | ret = regmap_bulk_write(regmap, AC100_ALM_SEC, reg, 8); | ||
500 | if (ret) | ||
501 | return ret; | ||
502 | |||
503 | return ac100_rtc_alarm_irq_enable(dev, alrm->enabled); | ||
504 | } | ||
505 | |||
506 | static irqreturn_t ac100_rtc_irq(int irq, void *data) | ||
507 | { | ||
508 | struct ac100_rtc_dev *chip = data; | ||
509 | struct regmap *regmap = chip->regmap; | ||
510 | unsigned int val = 0; | ||
511 | int ret; | ||
512 | |||
513 | mutex_lock(&chip->rtc->ops_lock); | ||
514 | |||
515 | /* read status */ | ||
516 | ret = regmap_read(regmap, AC100_ALM_INT_STA, &val); | ||
517 | if (ret) | ||
518 | goto out; | ||
519 | |||
520 | if (val & AC100_ALM_INT_ENABLE) { | ||
521 | /* signal rtc framework */ | ||
522 | rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF); | ||
523 | |||
524 | /* clear status */ | ||
525 | ret = regmap_write(regmap, AC100_ALM_INT_STA, val); | ||
526 | if (ret) | ||
527 | goto out; | ||
528 | |||
529 | /* disable interrupt */ | ||
530 | ret = ac100_rtc_alarm_irq_enable(chip->dev, 0); | ||
531 | if (ret) | ||
532 | goto out; | ||
533 | } | ||
534 | |||
535 | out: | ||
536 | mutex_unlock(&chip->rtc->ops_lock); | ||
537 | return IRQ_HANDLED; | ||
538 | } | ||
539 | |||
540 | static const struct rtc_class_ops ac100_rtc_ops = { | ||
541 | .read_time = ac100_rtc_get_time, | ||
542 | .set_time = ac100_rtc_set_time, | ||
543 | .read_alarm = ac100_rtc_get_alarm, | ||
544 | .set_alarm = ac100_rtc_set_alarm, | ||
545 | .alarm_irq_enable = ac100_rtc_alarm_irq_enable, | ||
546 | }; | ||
547 | |||
548 | static int ac100_rtc_probe(struct platform_device *pdev) | ||
549 | { | ||
550 | struct ac100_dev *ac100 = dev_get_drvdata(pdev->dev.parent); | ||
551 | struct ac100_rtc_dev *chip; | ||
552 | int ret; | ||
553 | |||
554 | chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); | ||
555 | platform_set_drvdata(pdev, chip); | ||
556 | chip->dev = &pdev->dev; | ||
557 | chip->regmap = ac100->regmap; | ||
558 | |||
559 | chip->irq = platform_get_irq(pdev, 0); | ||
560 | if (chip->irq < 0) { | ||
561 | dev_err(&pdev->dev, "No IRQ resource\n"); | ||
562 | return chip->irq; | ||
563 | } | ||
564 | |||
565 | ret = devm_request_threaded_irq(&pdev->dev, chip->irq, NULL, | ||
566 | ac100_rtc_irq, | ||
567 | IRQF_SHARED | IRQF_ONESHOT, | ||
568 | dev_name(&pdev->dev), chip); | ||
569 | if (ret) { | ||
570 | dev_err(&pdev->dev, "Could not request IRQ\n"); | ||
571 | return ret; | ||
572 | } | ||
573 | |||
574 | /* always use 24 hour mode */ | ||
575 | regmap_write_bits(chip->regmap, AC100_RTC_CTRL, AC100_RTC_CTRL_24HOUR, | ||
576 | AC100_RTC_CTRL_24HOUR); | ||
577 | |||
578 | /* disable counter alarm interrupt */ | ||
579 | regmap_write(chip->regmap, AC100_ALM_INT_ENA, 0); | ||
580 | |||
581 | /* clear counter alarm pending interrupts */ | ||
582 | regmap_write(chip->regmap, AC100_ALM_INT_STA, AC100_ALM_INT_ENABLE); | ||
583 | |||
584 | chip->rtc = devm_rtc_device_register(&pdev->dev, "rtc-ac100", | ||
585 | &ac100_rtc_ops, THIS_MODULE); | ||
586 | if (IS_ERR(chip->rtc)) { | ||
587 | dev_err(&pdev->dev, "unable to register device\n"); | ||
588 | return PTR_ERR(chip->rtc); | ||
589 | } | ||
590 | |||
591 | ret = ac100_rtc_register_clks(chip); | ||
592 | if (ret) | ||
593 | return ret; | ||
594 | |||
595 | dev_info(&pdev->dev, "RTC enabled\n"); | ||
596 | |||
597 | return 0; | ||
598 | } | ||
599 | |||
600 | static int ac100_rtc_remove(struct platform_device *pdev) | ||
601 | { | ||
602 | struct ac100_rtc_dev *chip = platform_get_drvdata(pdev); | ||
603 | |||
604 | ac100_rtc_unregister_clks(chip); | ||
605 | |||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | static const struct of_device_id ac100_rtc_match[] = { | ||
610 | { .compatible = "x-powers,ac100-rtc" }, | ||
611 | { }, | ||
612 | }; | ||
613 | MODULE_DEVICE_TABLE(of, ac100_rtc_match); | ||
614 | |||
615 | static struct platform_driver ac100_rtc_driver = { | ||
616 | .probe = ac100_rtc_probe, | ||
617 | .remove = ac100_rtc_remove, | ||
618 | .driver = { | ||
619 | .name = "ac100-rtc", | ||
620 | .of_match_table = of_match_ptr(ac100_rtc_match), | ||
621 | }, | ||
622 | }; | ||
623 | module_platform_driver(ac100_rtc_driver); | ||
624 | |||
625 | MODULE_DESCRIPTION("X-Powers AC100 RTC driver"); | ||
626 | MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>"); | ||
627 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index 795fcbd02ea3..fac835530671 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c | |||
@@ -428,6 +428,7 @@ static const struct pm8xxx_rtc_regs pm8941_regs = { | |||
428 | */ | 428 | */ |
429 | static const struct of_device_id pm8xxx_id_table[] = { | 429 | static const struct of_device_id pm8xxx_id_table[] = { |
430 | { .compatible = "qcom,pm8921-rtc", .data = &pm8921_regs }, | 430 | { .compatible = "qcom,pm8921-rtc", .data = &pm8921_regs }, |
431 | { .compatible = "qcom,pm8018-rtc", .data = &pm8921_regs }, | ||
431 | { .compatible = "qcom,pm8058-rtc", .data = &pm8058_regs }, | 432 | { .compatible = "qcom,pm8058-rtc", .data = &pm8058_regs }, |
432 | { .compatible = "qcom,pm8941-rtc", .data = &pm8941_regs }, | 433 | { .compatible = "qcom,pm8941-rtc", .data = &pm8941_regs }, |
433 | { }, | 434 | { }, |
diff --git a/include/dt-bindings/mfd/qcom-rpm.h b/include/dt-bindings/mfd/qcom-rpm.h index 13a9d4bf2662..54aef5e21763 100644 --- a/include/dt-bindings/mfd/qcom-rpm.h +++ b/include/dt-bindings/mfd/qcom-rpm.h | |||
@@ -147,6 +147,28 @@ | |||
147 | #define QCOM_RPM_SMB208_S1b 137 | 147 | #define QCOM_RPM_SMB208_S1b 137 |
148 | #define QCOM_RPM_SMB208_S2a 138 | 148 | #define QCOM_RPM_SMB208_S2a 138 |
149 | #define QCOM_RPM_SMB208_S2b 139 | 149 | #define QCOM_RPM_SMB208_S2b 139 |
150 | #define QCOM_RPM_PM8018_SMPS1 140 | ||
151 | #define QCOM_RPM_PM8018_SMPS2 141 | ||
152 | #define QCOM_RPM_PM8018_SMPS3 142 | ||
153 | #define QCOM_RPM_PM8018_SMPS4 143 | ||
154 | #define QCOM_RPM_PM8018_SMPS5 144 | ||
155 | #define QCOM_RPM_PM8018_LDO1 145 | ||
156 | #define QCOM_RPM_PM8018_LDO2 146 | ||
157 | #define QCOM_RPM_PM8018_LDO3 147 | ||
158 | #define QCOM_RPM_PM8018_LDO4 148 | ||
159 | #define QCOM_RPM_PM8018_LDO5 149 | ||
160 | #define QCOM_RPM_PM8018_LDO6 150 | ||
161 | #define QCOM_RPM_PM8018_LDO7 151 | ||
162 | #define QCOM_RPM_PM8018_LDO8 152 | ||
163 | #define QCOM_RPM_PM8018_LDO9 153 | ||
164 | #define QCOM_RPM_PM8018_LDO10 154 | ||
165 | #define QCOM_RPM_PM8018_LDO11 155 | ||
166 | #define QCOM_RPM_PM8018_LDO12 156 | ||
167 | #define QCOM_RPM_PM8018_LDO13 157 | ||
168 | #define QCOM_RPM_PM8018_LDO14 158 | ||
169 | #define QCOM_RPM_PM8018_LVS1 159 | ||
170 | #define QCOM_RPM_PM8018_NCP 160 | ||
171 | #define QCOM_RPM_VOLTAGE_CORNER 161 | ||
150 | 172 | ||
151 | /* | 173 | /* |
152 | * Constants used to select force mode for regulators. | 174 | * Constants used to select force mode for regulators. |
diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h index d409ceb2231e..c118a7ec94d6 100644 --- a/include/linux/mfd/88pm80x.h +++ b/include/linux/mfd/88pm80x.h | |||
@@ -350,7 +350,7 @@ static inline int pm80x_dev_suspend(struct device *dev) | |||
350 | int irq = platform_get_irq(pdev, 0); | 350 | int irq = platform_get_irq(pdev, 0); |
351 | 351 | ||
352 | if (device_may_wakeup(dev)) | 352 | if (device_may_wakeup(dev)) |
353 | set_bit((1 << irq), &chip->wu_flag); | 353 | set_bit(irq, &chip->wu_flag); |
354 | 354 | ||
355 | return 0; | 355 | return 0; |
356 | } | 356 | } |
@@ -362,7 +362,7 @@ static inline int pm80x_dev_resume(struct device *dev) | |||
362 | int irq = platform_get_irq(pdev, 0); | 362 | int irq = platform_get_irq(pdev, 0); |
363 | 363 | ||
364 | if (device_may_wakeup(dev)) | 364 | if (device_may_wakeup(dev)) |
365 | clear_bit((1 << irq), &chip->wu_flag); | 365 | clear_bit(irq, &chip->wu_flag); |
366 | 366 | ||
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index 9475fee2bfc5..d33c245e75ca 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h | |||
@@ -63,6 +63,8 @@ enum ab8500_version { | |||
63 | #define AB8500_STE_TEST 0x14 | 63 | #define AB8500_STE_TEST 0x14 |
64 | #define AB8500_OTP_EMUL 0x15 | 64 | #define AB8500_OTP_EMUL 0x15 |
65 | 65 | ||
66 | #define AB8500_DEBUG_FIELD_LAST 0x16 | ||
67 | |||
66 | /* | 68 | /* |
67 | * Interrupts | 69 | * Interrupts |
68 | * Values used to index into array ab8500_irq_regoffset[] defined in | 70 | * Values used to index into array ab8500_irq_regoffset[] defined in |
diff --git a/include/linux/mfd/ac100.h b/include/linux/mfd/ac100.h new file mode 100644 index 000000000000..3c148f196b9f --- /dev/null +++ b/include/linux/mfd/ac100.h | |||
@@ -0,0 +1,178 @@ | |||
1 | /* | ||
2 | * Functions and registers to access AC100 codec / RTC combo IC. | ||
3 | * | ||
4 | * Copyright (C) 2016 Chen-Yu Tsai | ||
5 | * | ||
6 | * Chen-Yu Tsai <wens@csie.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __LINUX_MFD_AC100_H | ||
14 | #define __LINUX_MFD_AC100_H | ||
15 | |||
16 | #include <linux/regmap.h> | ||
17 | |||
18 | struct ac100_dev { | ||
19 | struct device *dev; | ||
20 | struct regmap *regmap; | ||
21 | }; | ||
22 | |||
23 | /* Audio codec related registers */ | ||
24 | #define AC100_CHIP_AUDIO_RST 0x00 | ||
25 | #define AC100_PLL_CTRL1 0x01 | ||
26 | #define AC100_PLL_CTRL2 0x02 | ||
27 | #define AC100_SYSCLK_CTRL 0x03 | ||
28 | #define AC100_MOD_CLK_ENA 0x04 | ||
29 | #define AC100_MOD_RST_CTRL 0x05 | ||
30 | #define AC100_I2S_SR_CTRL 0x06 | ||
31 | |||
32 | /* I2S1 interface */ | ||
33 | #define AC100_I2S1_CLK_CTRL 0x10 | ||
34 | #define AC100_I2S1_SND_OUT_CTRL 0x11 | ||
35 | #define AC100_I2S1_SND_IN_CTRL 0x12 | ||
36 | #define AC100_I2S1_MXR_SRC 0x13 | ||
37 | #define AC100_I2S1_VOL_CTRL1 0x14 | ||
38 | #define AC100_I2S1_VOL_CTRL2 0x15 | ||
39 | #define AC100_I2S1_VOL_CTRL3 0x16 | ||
40 | #define AC100_I2S1_VOL_CTRL4 0x17 | ||
41 | #define AC100_I2S1_MXR_GAIN 0x18 | ||
42 | |||
43 | /* I2S2 interface */ | ||
44 | #define AC100_I2S2_CLK_CTRL 0x20 | ||
45 | #define AC100_I2S2_SND_OUT_CTRL 0x21 | ||
46 | #define AC100_I2S2_SND_IN_CTRL 0x22 | ||
47 | #define AC100_I2S2_MXR_SRC 0x23 | ||
48 | #define AC100_I2S2_VOL_CTRL1 0x24 | ||
49 | #define AC100_I2S2_VOL_CTRL2 0x25 | ||
50 | #define AC100_I2S2_VOL_CTRL3 0x26 | ||
51 | #define AC100_I2S2_VOL_CTRL4 0x27 | ||
52 | #define AC100_I2S2_MXR_GAIN 0x28 | ||
53 | |||
54 | /* I2S3 interface */ | ||
55 | #define AC100_I2S3_CLK_CTRL 0x30 | ||
56 | #define AC100_I2S3_SND_OUT_CTRL 0x31 | ||
57 | #define AC100_I2S3_SND_IN_CTRL 0x32 | ||
58 | #define AC100_I2S3_SIG_PATH_CTRL 0x33 | ||
59 | |||
60 | /* ADC digital controls */ | ||
61 | #define AC100_ADC_DIG_CTRL 0x40 | ||
62 | #define AC100_ADC_VOL_CTRL 0x41 | ||
63 | |||
64 | /* HMIC plug sensing / key detection */ | ||
65 | #define AC100_HMIC_CTRL1 0x44 | ||
66 | #define AC100_HMIC_CTRL2 0x45 | ||
67 | #define AC100_HMIC_STATUS 0x46 | ||
68 | |||
69 | /* DAC digital controls */ | ||
70 | #define AC100_DAC_DIG_CTRL 0x48 | ||
71 | #define AC100_DAC_VOL_CTRL 0x49 | ||
72 | #define AC100_DAC_MXR_SRC 0x4c | ||
73 | #define AC100_DAC_MXR_GAIN 0x4d | ||
74 | |||
75 | /* Analog controls */ | ||
76 | #define AC100_ADC_APC_CTRL 0x50 | ||
77 | #define AC100_ADC_SRC 0x51 | ||
78 | #define AC100_ADC_SRC_BST_CTRL 0x52 | ||
79 | #define AC100_OUT_MXR_DAC_A_CTRL 0x53 | ||
80 | #define AC100_OUT_MXR_SRC 0x54 | ||
81 | #define AC100_OUT_MXR_SRC_BST 0x55 | ||
82 | #define AC100_HPOUT_CTRL 0x56 | ||
83 | #define AC100_ERPOUT_CTRL 0x57 | ||
84 | #define AC100_SPKOUT_CTRL 0x58 | ||
85 | #define AC100_LINEOUT_CTRL 0x59 | ||
86 | |||
87 | /* ADC digital audio processing (high pass filter & auto gain control */ | ||
88 | #define AC100_ADC_DAP_L_STA 0x80 | ||
89 | #define AC100_ADC_DAP_R_STA 0x81 | ||
90 | #define AC100_ADC_DAP_L_CTRL 0x82 | ||
91 | #define AC100_ADC_DAP_R_CTRL 0x83 | ||
92 | #define AC100_ADC_DAP_L_T_L 0x84 /* Left Target Level */ | ||
93 | #define AC100_ADC_DAP_R_T_L 0x85 /* Right Target Level */ | ||
94 | #define AC100_ADC_DAP_L_H_A_C 0x86 /* Left High Avg. Coef */ | ||
95 | #define AC100_ADC_DAP_L_L_A_C 0x87 /* Left Low Avg. Coef */ | ||
96 | #define AC100_ADC_DAP_R_H_A_C 0x88 /* Right High Avg. Coef */ | ||
97 | #define AC100_ADC_DAP_R_L_A_C 0x89 /* Right Low Avg. Coef */ | ||
98 | #define AC100_ADC_DAP_L_D_T 0x8a /* Left Decay Time */ | ||
99 | #define AC100_ADC_DAP_L_A_T 0x8b /* Left Attack Time */ | ||
100 | #define AC100_ADC_DAP_R_D_T 0x8c /* Right Decay Time */ | ||
101 | #define AC100_ADC_DAP_R_A_T 0x8d /* Right Attack Time */ | ||
102 | #define AC100_ADC_DAP_N_TH 0x8e /* Noise Threshold */ | ||
103 | #define AC100_ADC_DAP_L_H_N_A_C 0x8f /* Left High Noise Avg. Coef */ | ||
104 | #define AC100_ADC_DAP_L_L_N_A_C 0x90 /* Left Low Noise Avg. Coef */ | ||
105 | #define AC100_ADC_DAP_R_H_N_A_C 0x91 /* Right High Noise Avg. Coef */ | ||
106 | #define AC100_ADC_DAP_R_L_N_A_C 0x92 /* Right Low Noise Avg. Coef */ | ||
107 | #define AC100_ADC_DAP_H_HPF_C 0x93 /* High High-Pass-Filter Coef */ | ||
108 | #define AC100_ADC_DAP_L_HPF_C 0x94 /* Low High-Pass-Filter Coef */ | ||
109 | #define AC100_ADC_DAP_OPT 0x95 /* AGC Optimum */ | ||
110 | |||
111 | /* DAC digital audio processing (high pass filter & dynamic range control) */ | ||
112 | #define AC100_DAC_DAP_CTRL 0xa0 | ||
113 | #define AC100_DAC_DAP_H_HPF_C 0xa1 /* High High-Pass-Filter Coef */ | ||
114 | #define AC100_DAC_DAP_L_HPF_C 0xa2 /* Low High-Pass-Filter Coef */ | ||
115 | #define AC100_DAC_DAP_L_H_E_A_C 0xa3 /* Left High Energy Avg Coef */ | ||
116 | #define AC100_DAC_DAP_L_L_E_A_C 0xa4 /* Left Low Energy Avg Coef */ | ||
117 | #define AC100_DAC_DAP_R_H_E_A_C 0xa5 /* Right High Energy Avg Coef */ | ||
118 | #define AC100_DAC_DAP_R_L_E_A_C 0xa6 /* Right Low Energy Avg Coef */ | ||
119 | #define AC100_DAC_DAP_H_G_D_T_C 0xa7 /* High Gain Delay Time Coef */ | ||
120 | #define AC100_DAC_DAP_L_G_D_T_C 0xa8 /* Low Gain Delay Time Coef */ | ||
121 | #define AC100_DAC_DAP_H_G_A_T_C 0xa9 /* High Gain Attack Time Coef */ | ||
122 | #define AC100_DAC_DAP_L_G_A_T_C 0xaa /* Low Gain Attack Time Coef */ | ||
123 | #define AC100_DAC_DAP_H_E_TH 0xab /* High Energy Threshold */ | ||
124 | #define AC100_DAC_DAP_L_E_TH 0xac /* Low Energy Threshold */ | ||
125 | #define AC100_DAC_DAP_H_G_K 0xad /* High Gain K parameter */ | ||
126 | #define AC100_DAC_DAP_L_G_K 0xae /* Low Gain K parameter */ | ||
127 | #define AC100_DAC_DAP_H_G_OFF 0xaf /* High Gain offset */ | ||
128 | #define AC100_DAC_DAP_L_G_OFF 0xb0 /* Low Gain offset */ | ||
129 | #define AC100_DAC_DAP_OPT 0xb1 /* DRC optimum */ | ||
130 | |||
131 | /* Digital audio processing enable */ | ||
132 | #define AC100_ADC_DAP_ENA 0xb4 | ||
133 | #define AC100_DAC_DAP_ENA 0xb5 | ||
134 | |||
135 | /* SRC control */ | ||
136 | #define AC100_SRC1_CTRL1 0xb8 | ||
137 | #define AC100_SRC1_CTRL2 0xb9 | ||
138 | #define AC100_SRC1_CTRL3 0xba | ||
139 | #define AC100_SRC1_CTRL4 0xbb | ||
140 | #define AC100_SRC2_CTRL1 0xbc | ||
141 | #define AC100_SRC2_CTRL2 0xbd | ||
142 | #define AC100_SRC2_CTRL3 0xbe | ||
143 | #define AC100_SRC2_CTRL4 0xbf | ||
144 | |||
145 | /* RTC clk control */ | ||
146 | #define AC100_CLK32K_ANALOG_CTRL 0xc0 | ||
147 | #define AC100_CLKOUT_CTRL1 0xc1 | ||
148 | #define AC100_CLKOUT_CTRL2 0xc2 | ||
149 | #define AC100_CLKOUT_CTRL3 0xc3 | ||
150 | |||
151 | /* RTC module */ | ||
152 | #define AC100_RTC_RST 0xc6 | ||
153 | #define AC100_RTC_CTRL 0xc7 | ||
154 | #define AC100_RTC_SEC 0xc8 /* second */ | ||
155 | #define AC100_RTC_MIN 0xc9 /* minute */ | ||
156 | #define AC100_RTC_HOU 0xca /* hour */ | ||
157 | #define AC100_RTC_WEE 0xcb /* weekday */ | ||
158 | #define AC100_RTC_DAY 0xcc /* day */ | ||
159 | #define AC100_RTC_MON 0xcd /* month */ | ||
160 | #define AC100_RTC_YEA 0xce /* year */ | ||
161 | #define AC100_RTC_UPD 0xcf /* update trigger */ | ||
162 | |||
163 | /* RTC alarm */ | ||
164 | #define AC100_ALM_INT_ENA 0xd0 | ||
165 | #define AC100_ALM_INT_STA 0xd1 | ||
166 | #define AC100_ALM_SEC 0xd8 | ||
167 | #define AC100_ALM_MIN 0xd9 | ||
168 | #define AC100_ALM_HOU 0xda | ||
169 | #define AC100_ALM_WEE 0xdb | ||
170 | #define AC100_ALM_DAY 0xdc | ||
171 | #define AC100_ALM_MON 0xdd | ||
172 | #define AC100_ALM_YEA 0xde | ||
173 | #define AC100_ALM_UPD 0xdf | ||
174 | |||
175 | /* RTC general purpose register 0 ~ 15 */ | ||
176 | #define AC100_RTC_GP(x) (0xe0 + (x)) | ||
177 | |||
178 | #endif /* __LINUX_MFD_AC100_H */ | ||
diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h index 58ab4c0fe761..b31b3be7f8c9 100644 --- a/include/linux/mfd/arizona/core.h +++ b/include/linux/mfd/arizona/core.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #ifndef _WM_ARIZONA_CORE_H | 13 | #ifndef _WM_ARIZONA_CORE_H |
14 | #define _WM_ARIZONA_CORE_H | 14 | #define _WM_ARIZONA_CORE_H |
15 | 15 | ||
16 | #include <linux/clk.h> | ||
16 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
17 | #include <linux/notifier.h> | 18 | #include <linux/notifier.h> |
18 | #include <linux/regmap.h> | 19 | #include <linux/regmap.h> |
@@ -21,6 +22,12 @@ | |||
21 | 22 | ||
22 | #define ARIZONA_MAX_CORE_SUPPLIES 2 | 23 | #define ARIZONA_MAX_CORE_SUPPLIES 2 |
23 | 24 | ||
25 | enum { | ||
26 | ARIZONA_MCLK1, | ||
27 | ARIZONA_MCLK2, | ||
28 | ARIZONA_NUM_MCLK | ||
29 | }; | ||
30 | |||
24 | enum arizona_type { | 31 | enum arizona_type { |
25 | WM5102 = 1, | 32 | WM5102 = 1, |
26 | WM5110 = 2, | 33 | WM5110 = 2, |
@@ -139,6 +146,8 @@ struct arizona { | |||
139 | struct mutex clk_lock; | 146 | struct mutex clk_lock; |
140 | int clk32k_ref; | 147 | int clk32k_ref; |
141 | 148 | ||
149 | struct clk *mclk[ARIZONA_NUM_MCLK]; | ||
150 | |||
142 | bool ctrlif_error; | 151 | bool ctrlif_error; |
143 | 152 | ||
144 | struct snd_soc_dapm_context *dapm; | 153 | struct snd_soc_dapm_context *dapm; |
@@ -182,7 +191,4 @@ int cs47l24_patch(struct arizona *arizona); | |||
182 | int wm8997_patch(struct arizona *arizona); | 191 | int wm8997_patch(struct arizona *arizona); |
183 | int wm8998_patch(struct arizona *arizona); | 192 | int wm8998_patch(struct arizona *arizona); |
184 | 193 | ||
185 | extern int arizona_of_get_named_gpio(struct arizona *arizona, const char *prop, | ||
186 | bool mandatory); | ||
187 | |||
188 | #endif | 194 | #endif |
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h index 0be4982f08fe..fec597fb34cb 100644 --- a/include/linux/mfd/axp20x.h +++ b/include/linux/mfd/axp20x.h | |||
@@ -20,6 +20,7 @@ enum { | |||
20 | AXP221_ID, | 20 | AXP221_ID, |
21 | AXP223_ID, | 21 | AXP223_ID, |
22 | AXP288_ID, | 22 | AXP288_ID, |
23 | AXP806_ID, | ||
23 | AXP809_ID, | 24 | AXP809_ID, |
24 | NR_AXP20X_VARIANTS, | 25 | NR_AXP20X_VARIANTS, |
25 | }; | 26 | }; |
@@ -91,6 +92,30 @@ enum { | |||
91 | #define AXP22X_ALDO3_V_OUT 0x2a | 92 | #define AXP22X_ALDO3_V_OUT 0x2a |
92 | #define AXP22X_CHRG_CTRL3 0x35 | 93 | #define AXP22X_CHRG_CTRL3 0x35 |
93 | 94 | ||
95 | #define AXP806_STARTUP_SRC 0x00 | ||
96 | #define AXP806_CHIP_ID 0x03 | ||
97 | #define AXP806_PWR_OUT_CTRL1 0x10 | ||
98 | #define AXP806_PWR_OUT_CTRL2 0x11 | ||
99 | #define AXP806_DCDCA_V_CTRL 0x12 | ||
100 | #define AXP806_DCDCB_V_CTRL 0x13 | ||
101 | #define AXP806_DCDCC_V_CTRL 0x14 | ||
102 | #define AXP806_DCDCD_V_CTRL 0x15 | ||
103 | #define AXP806_DCDCE_V_CTRL 0x16 | ||
104 | #define AXP806_ALDO1_V_CTRL 0x17 | ||
105 | #define AXP806_ALDO2_V_CTRL 0x18 | ||
106 | #define AXP806_ALDO3_V_CTRL 0x19 | ||
107 | #define AXP806_DCDC_MODE_CTRL1 0x1a | ||
108 | #define AXP806_DCDC_MODE_CTRL2 0x1b | ||
109 | #define AXP806_DCDC_FREQ_CTRL 0x1c | ||
110 | #define AXP806_BLDO1_V_CTRL 0x20 | ||
111 | #define AXP806_BLDO2_V_CTRL 0x21 | ||
112 | #define AXP806_BLDO3_V_CTRL 0x22 | ||
113 | #define AXP806_BLDO4_V_CTRL 0x23 | ||
114 | #define AXP806_CLDO1_V_CTRL 0x24 | ||
115 | #define AXP806_CLDO2_V_CTRL 0x25 | ||
116 | #define AXP806_CLDO3_V_CTRL 0x26 | ||
117 | #define AXP806_VREF_TEMP_WARN_L 0xf3 | ||
118 | |||
94 | /* Interrupt */ | 119 | /* Interrupt */ |
95 | #define AXP152_IRQ1_EN 0x40 | 120 | #define AXP152_IRQ1_EN 0x40 |
96 | #define AXP152_IRQ2_EN 0x41 | 121 | #define AXP152_IRQ2_EN 0x41 |
@@ -266,6 +291,26 @@ enum { | |||
266 | }; | 291 | }; |
267 | 292 | ||
268 | enum { | 293 | enum { |
294 | AXP806_DCDCA = 0, | ||
295 | AXP806_DCDCB, | ||
296 | AXP806_DCDCC, | ||
297 | AXP806_DCDCD, | ||
298 | AXP806_DCDCE, | ||
299 | AXP806_ALDO1, | ||
300 | AXP806_ALDO2, | ||
301 | AXP806_ALDO3, | ||
302 | AXP806_BLDO1, | ||
303 | AXP806_BLDO2, | ||
304 | AXP806_BLDO3, | ||
305 | AXP806_BLDO4, | ||
306 | AXP806_CLDO1, | ||
307 | AXP806_CLDO2, | ||
308 | AXP806_CLDO3, | ||
309 | AXP806_SW, | ||
310 | AXP806_REG_ID_MAX, | ||
311 | }; | ||
312 | |||
313 | enum { | ||
269 | AXP809_DCDC1 = 0, | 314 | AXP809_DCDC1 = 0, |
270 | AXP809_DCDC2, | 315 | AXP809_DCDC2, |
271 | AXP809_DCDC3, | 316 | AXP809_DCDC3, |
@@ -414,6 +459,21 @@ enum axp288_irqs { | |||
414 | AXP288_IRQ_BC_USB_CHNG, | 459 | AXP288_IRQ_BC_USB_CHNG, |
415 | }; | 460 | }; |
416 | 461 | ||
462 | enum axp806_irqs { | ||
463 | AXP806_IRQ_DIE_TEMP_HIGH_LV1, | ||
464 | AXP806_IRQ_DIE_TEMP_HIGH_LV2, | ||
465 | AXP806_IRQ_DCDCA_V_LOW, | ||
466 | AXP806_IRQ_DCDCB_V_LOW, | ||
467 | AXP806_IRQ_DCDCC_V_LOW, | ||
468 | AXP806_IRQ_DCDCD_V_LOW, | ||
469 | AXP806_IRQ_DCDCE_V_LOW, | ||
470 | AXP806_IRQ_PWROK_LONG, | ||
471 | AXP806_IRQ_PWROK_SHORT, | ||
472 | AXP806_IRQ_WAKEUP, | ||
473 | AXP806_IRQ_PWROK_FALL, | ||
474 | AXP806_IRQ_PWROK_RISE, | ||
475 | }; | ||
476 | |||
417 | enum axp809_irqs { | 477 | enum axp809_irqs { |
418 | AXP809_IRQ_ACIN_OVER_V = 1, | 478 | AXP809_IRQ_ACIN_OVER_V = 1, |
419 | AXP809_IRQ_ACIN_PLUGIN, | 479 | AXP809_IRQ_ACIN_PLUGIN, |
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h index d641a18abacb..76f7ef4d3a0d 100644 --- a/include/linux/mfd/cros_ec.h +++ b/include/linux/mfd/cros_ec.h | |||
@@ -109,6 +109,10 @@ struct cros_ec_command { | |||
109 | * should check msg.result for the EC's result code. | 109 | * should check msg.result for the EC's result code. |
110 | * @pkt_xfer: send packet to EC and get response | 110 | * @pkt_xfer: send packet to EC and get response |
111 | * @lock: one transaction at a time | 111 | * @lock: one transaction at a time |
112 | * @mkbp_event_supported: true if this EC supports the MKBP event protocol. | ||
113 | * @event_notifier: interrupt event notifier for transport devices. | ||
114 | * @event_data: raw payload transferred with the MKBP event. | ||
115 | * @event_size: size in bytes of the event data. | ||
112 | */ | 116 | */ |
113 | struct cros_ec_device { | 117 | struct cros_ec_device { |
114 | 118 | ||
@@ -137,6 +141,11 @@ struct cros_ec_device { | |||
137 | int (*pkt_xfer)(struct cros_ec_device *ec, | 141 | int (*pkt_xfer)(struct cros_ec_device *ec, |
138 | struct cros_ec_command *msg); | 142 | struct cros_ec_command *msg); |
139 | struct mutex lock; | 143 | struct mutex lock; |
144 | bool mkbp_event_supported; | ||
145 | struct blocking_notifier_head event_notifier; | ||
146 | |||
147 | struct ec_response_get_next_event event_data; | ||
148 | int event_size; | ||
140 | }; | 149 | }; |
141 | 150 | ||
142 | /* struct cros_ec_platform - ChromeOS EC platform information | 151 | /* struct cros_ec_platform - ChromeOS EC platform information |
@@ -269,6 +278,15 @@ int cros_ec_register(struct cros_ec_device *ec_dev); | |||
269 | */ | 278 | */ |
270 | int cros_ec_query_all(struct cros_ec_device *ec_dev); | 279 | int cros_ec_query_all(struct cros_ec_device *ec_dev); |
271 | 280 | ||
281 | /** | ||
282 | * cros_ec_get_next_event - Fetch next event from the ChromeOS EC | ||
283 | * | ||
284 | * @ec_dev: Device to fetch event from | ||
285 | * | ||
286 | * Returns: 0 on success, Linux error number on failure | ||
287 | */ | ||
288 | int cros_ec_get_next_event(struct cros_ec_device *ec_dev); | ||
289 | |||
272 | /* sysfs stuff */ | 290 | /* sysfs stuff */ |
273 | extern struct attribute_group cros_ec_attr_group; | 291 | extern struct attribute_group cros_ec_attr_group; |
274 | extern struct attribute_group cros_ec_lightbar_attr_group; | 292 | extern struct attribute_group cros_ec_lightbar_attr_group; |
diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h index 7e7a8d4b4551..76728ff37d01 100644 --- a/include/linux/mfd/cros_ec_commands.h +++ b/include/linux/mfd/cros_ec_commands.h | |||
@@ -1793,6 +1793,40 @@ struct ec_result_keyscan_seq_ctrl { | |||
1793 | }; | 1793 | }; |
1794 | } __packed; | 1794 | } __packed; |
1795 | 1795 | ||
1796 | /* | ||
1797 | * Command for retrieving the next pending MKBP event from the EC device | ||
1798 | * | ||
1799 | * The device replies with UNAVAILABLE if there aren't any pending events. | ||
1800 | */ | ||
1801 | #define EC_CMD_GET_NEXT_EVENT 0x67 | ||
1802 | |||
1803 | enum ec_mkbp_event { | ||
1804 | /* Keyboard matrix changed. The event data is the new matrix state. */ | ||
1805 | EC_MKBP_EVENT_KEY_MATRIX = 0, | ||
1806 | |||
1807 | /* New host event. The event data is 4 bytes of host event flags. */ | ||
1808 | EC_MKBP_EVENT_HOST_EVENT = 1, | ||
1809 | |||
1810 | /* New Sensor FIFO data. The event data is fifo_info structure. */ | ||
1811 | EC_MKBP_EVENT_SENSOR_FIFO = 2, | ||
1812 | |||
1813 | /* Number of MKBP events */ | ||
1814 | EC_MKBP_EVENT_COUNT, | ||
1815 | }; | ||
1816 | |||
1817 | union ec_response_get_next_data { | ||
1818 | uint8_t key_matrix[13]; | ||
1819 | |||
1820 | /* Unaligned */ | ||
1821 | uint32_t host_event; | ||
1822 | } __packed; | ||
1823 | |||
1824 | struct ec_response_get_next_event { | ||
1825 | uint8_t event_type; | ||
1826 | /* Followed by event data if any */ | ||
1827 | union ec_response_get_next_data data; | ||
1828 | } __packed; | ||
1829 | |||
1796 | /*****************************************************************************/ | 1830 | /*****************************************************************************/ |
1797 | /* Temperature sensor commands */ | 1831 | /* Temperature sensor commands */ |
1798 | 1832 | ||
diff --git a/include/linux/mfd/da9063/core.h b/include/linux/mfd/da9063/core.h index 621af82123c6..f3ae65db4c86 100644 --- a/include/linux/mfd/da9063/core.h +++ b/include/linux/mfd/da9063/core.h | |||
@@ -3,8 +3,8 @@ | |||
3 | * | 3 | * |
4 | * Copyright 2012 Dialog Semiconductor Ltd. | 4 | * Copyright 2012 Dialog Semiconductor Ltd. |
5 | * | 5 | * |
6 | * Author: Michal Hajduk <michal.hajduk@diasemi.com> | 6 | * Author: Michal Hajduk, Dialog Semiconductor |
7 | * Krystian Garbaciak <krystian.garbaciak@diasemi.com> | 7 | * Author: Krystian Garbaciak, Dialog Semiconductor |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify it | 9 | * This program is free software; you can redistribute it and/or modify it |
10 | * under the terms of the GNU General Public License as published by the | 10 | * under the terms of the GNU General Public License as published by the |
diff --git a/include/linux/mfd/da9063/pdata.h b/include/linux/mfd/da9063/pdata.h index 612383bd80ae..8a125701ef7b 100644 --- a/include/linux/mfd/da9063/pdata.h +++ b/include/linux/mfd/da9063/pdata.h | |||
@@ -3,8 +3,8 @@ | |||
3 | * | 3 | * |
4 | * Copyright 2012 Dialog Semiconductor Ltd. | 4 | * Copyright 2012 Dialog Semiconductor Ltd. |
5 | * | 5 | * |
6 | * Author: Michal Hajduk <michal.hajduk@diasemi.com> | 6 | * Author: Michal Hajduk, Dialog Semiconductor |
7 | * Author: Krystian Garbaciak <krystian.garbaciak@diasemi.com> | 7 | * Author: Krystian Garbaciak, Dialog Semiconductor |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify it | 9 | * This program is free software; you can redistribute it and/or modify it |
10 | * under the terms of the GNU General Public License as published by the | 10 | * under the terms of the GNU General Public License as published by the |
diff --git a/include/linux/mfd/da9063/registers.h b/include/linux/mfd/da9063/registers.h index 2e0ba6d5fbc3..5d42859cb441 100644 --- a/include/linux/mfd/da9063/registers.h +++ b/include/linux/mfd/da9063/registers.h | |||
@@ -3,8 +3,8 @@ | |||
3 | * | 3 | * |
4 | * Copyright 2012 Dialog Semiconductor Ltd. | 4 | * Copyright 2012 Dialog Semiconductor Ltd. |
5 | * | 5 | * |
6 | * Author: Michal Hajduk <michal.hajduk@diasemi.com> | 6 | * Author: Michal Hajduk, Dialog Semiconductor |
7 | * Krystian Garbaciak <krystian.garbaciak@diasemi.com> | 7 | * Author: Krystian Garbaciak, Dialog Semiconductor |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify it | 9 | * This program is free software; you can redistribute it and/or modify it |
10 | * under the terms of the GNU General Public License as published by the | 10 | * under the terms of the GNU General Public License as published by the |
diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h index 0bd69446bb05..7ba67b55b312 100644 --- a/include/linux/mfd/db8500-prcmu.h +++ b/include/linux/mfd/db8500-prcmu.h | |||
@@ -538,7 +538,6 @@ int db8500_prcmu_get_arm_opp(void); | |||
538 | int db8500_prcmu_set_ape_opp(u8 opp); | 538 | int db8500_prcmu_set_ape_opp(u8 opp); |
539 | int db8500_prcmu_get_ape_opp(void); | 539 | int db8500_prcmu_get_ape_opp(void); |
540 | int db8500_prcmu_request_ape_opp_100_voltage(bool enable); | 540 | int db8500_prcmu_request_ape_opp_100_voltage(bool enable); |
541 | int db8500_prcmu_set_ddr_opp(u8 opp); | ||
542 | int db8500_prcmu_get_ddr_opp(void); | 541 | int db8500_prcmu_get_ddr_opp(void); |
543 | 542 | ||
544 | u32 db8500_prcmu_read(unsigned int reg); | 543 | u32 db8500_prcmu_read(unsigned int reg); |
@@ -594,11 +593,6 @@ static inline int prcmu_release_usb_wakeup_state(void) | |||
594 | return 0; | 593 | return 0; |
595 | } | 594 | } |
596 | 595 | ||
597 | static inline int db8500_prcmu_set_ddr_opp(u8 opp) | ||
598 | { | ||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | static inline int db8500_prcmu_get_ddr_opp(void) | 596 | static inline int db8500_prcmu_get_ddr_opp(void) |
603 | { | 597 | { |
604 | return DDR_100_OPP; | 598 | return DDR_100_OPP; |
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h index 5d374601404c..2e2c6a63a065 100644 --- a/include/linux/mfd/dbx500-prcmu.h +++ b/include/linux/mfd/dbx500-prcmu.h | |||
@@ -269,10 +269,6 @@ unsigned long prcmu_clock_rate(u8 clock); | |||
269 | long prcmu_round_clock_rate(u8 clock, unsigned long rate); | 269 | long prcmu_round_clock_rate(u8 clock, unsigned long rate); |
270 | int prcmu_set_clock_rate(u8 clock, unsigned long rate); | 270 | int prcmu_set_clock_rate(u8 clock, unsigned long rate); |
271 | 271 | ||
272 | static inline int prcmu_set_ddr_opp(u8 opp) | ||
273 | { | ||
274 | return db8500_prcmu_set_ddr_opp(opp); | ||
275 | } | ||
276 | static inline int prcmu_get_ddr_opp(void) | 272 | static inline int prcmu_get_ddr_opp(void) |
277 | { | 273 | { |
278 | return db8500_prcmu_get_ddr_opp(); | 274 | return db8500_prcmu_get_ddr_opp(); |
@@ -489,11 +485,6 @@ static inline int prcmu_get_arm_opp(void) | |||
489 | return ARM_100_OPP; | 485 | return ARM_100_OPP; |
490 | } | 486 | } |
491 | 487 | ||
492 | static inline int prcmu_set_ddr_opp(u8 opp) | ||
493 | { | ||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | static inline int prcmu_get_ddr_opp(void) | 488 | static inline int prcmu_get_ddr_opp(void) |
498 | { | 489 | { |
499 | return DDR_100_OPP; | 490 | return DDR_100_OPP; |
diff --git a/include/linux/mfd/lp873x.h b/include/linux/mfd/lp873x.h index 83b1bd7588be..edbec8350a49 100644 --- a/include/linux/mfd/lp873x.h +++ b/include/linux/mfd/lp873x.h | |||
@@ -263,7 +263,6 @@ enum lp873x_regulator_id { | |||
263 | struct lp873x { | 263 | struct lp873x { |
264 | struct device *dev; | 264 | struct device *dev; |
265 | u8 rev; | 265 | u8 rev; |
266 | struct mutex lock; /* lock guarding the data structure */ | ||
267 | struct regmap *regmap; | 266 | struct regmap *regmap; |
268 | }; | 267 | }; |
269 | #endif /* __LINUX_MFD_LP873X_H */ | 268 | #endif /* __LINUX_MFD_LP873X_H */ |
diff --git a/include/linux/mfd/max14577-private.h b/include/linux/mfd/max14577-private.h index f01c1fae4d84..df75234f979d 100644 --- a/include/linux/mfd/max14577-private.h +++ b/include/linux/mfd/max14577-private.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2014 Samsung Electrnoics | 4 | * Copyright (C) 2014 Samsung Electrnoics |
5 | * Chanwoo Choi <cw00.choi@samsung.com> | 5 | * Chanwoo Choi <cw00.choi@samsung.com> |
6 | * Krzysztof Kozlowski <k.kozlowski@samsung.com> | 6 | * Krzysztof Kozlowski <krzk@kernel.org> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
diff --git a/include/linux/mfd/max14577.h b/include/linux/mfd/max14577.h index ccfaf952c31b..d81b52bb8bee 100644 --- a/include/linux/mfd/max14577.h +++ b/include/linux/mfd/max14577.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2014 Samsung Electrnoics | 4 | * Copyright (C) 2014 Samsung Electrnoics |
5 | * Chanwoo Choi <cw00.choi@samsung.com> | 5 | * Chanwoo Choi <cw00.choi@samsung.com> |
6 | * Krzysztof Kozlowski <k.kozlowski@samsung.com> | 6 | * Krzysztof Kozlowski <krzk@kernel.org> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index 441b6ee72691..6d435a3c06bc 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h | |||
@@ -1,11 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * rk808.h for Rockchip RK808 | 2 | * Register definitions for Rockchip's RK808/RK818 PMIC |
3 | * | 3 | * |
4 | * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd | 4 | * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd |
5 | * | 5 | * |
6 | * Author: Chris Zhong <zyw@rock-chips.com> | 6 | * Author: Chris Zhong <zyw@rock-chips.com> |
7 | * Author: Zhang Qing <zhangqing@rock-chips.com> | 7 | * Author: Zhang Qing <zhangqing@rock-chips.com> |
8 | * | 8 | * |
9 | * Copyright (C) 2016 PHYTEC Messtechnik GmbH | ||
10 | * | ||
11 | * Author: Wadim Egorov <w.egorov@phytec.de> | ||
12 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | 13 | * This program is free software; you can redistribute it and/or modify it |
10 | * under the terms and conditions of the GNU General Public License, | 14 | * under the terms and conditions of the GNU General Public License, |
11 | * version 2, as published by the Free Software Foundation. | 15 | * version 2, as published by the Free Software Foundation. |
@@ -16,8 +20,8 @@ | |||
16 | * more details. | 20 | * more details. |
17 | */ | 21 | */ |
18 | 22 | ||
19 | #ifndef __LINUX_REGULATOR_rk808_H | 23 | #ifndef __LINUX_REGULATOR_RK808_H |
20 | #define __LINUX_REGULATOR_rk808_H | 24 | #define __LINUX_REGULATOR_RK808_H |
21 | 25 | ||
22 | #include <linux/regulator/machine.h> | 26 | #include <linux/regulator/machine.h> |
23 | #include <linux/regmap.h> | 27 | #include <linux/regmap.h> |
@@ -28,7 +32,7 @@ | |||
28 | 32 | ||
29 | #define RK808_DCDC1 0 /* (0+RK808_START) */ | 33 | #define RK808_DCDC1 0 /* (0+RK808_START) */ |
30 | #define RK808_LDO1 4 /* (4+RK808_START) */ | 34 | #define RK808_LDO1 4 /* (4+RK808_START) */ |
31 | #define RK808_NUM_REGULATORS 14 | 35 | #define RK808_NUM_REGULATORS 14 |
32 | 36 | ||
33 | enum rk808_reg { | 37 | enum rk808_reg { |
34 | RK808_ID_DCDC1, | 38 | RK808_ID_DCDC1, |
@@ -65,6 +69,8 @@ enum rk808_reg { | |||
65 | #define RK808_RTC_INT_REG 0x12 | 69 | #define RK808_RTC_INT_REG 0x12 |
66 | #define RK808_RTC_COMP_LSB_REG 0x13 | 70 | #define RK808_RTC_COMP_LSB_REG 0x13 |
67 | #define RK808_RTC_COMP_MSB_REG 0x14 | 71 | #define RK808_RTC_COMP_MSB_REG 0x14 |
72 | #define RK808_ID_MSB 0x17 | ||
73 | #define RK808_ID_LSB 0x18 | ||
68 | #define RK808_CLK32OUT_REG 0x20 | 74 | #define RK808_CLK32OUT_REG 0x20 |
69 | #define RK808_VB_MON_REG 0x21 | 75 | #define RK808_VB_MON_REG 0x21 |
70 | #define RK808_THERMAL_REG 0x22 | 76 | #define RK808_THERMAL_REG 0x22 |
@@ -115,7 +121,92 @@ enum rk808_reg { | |||
115 | #define RK808_INT_STS_MSK_REG2 0x4f | 121 | #define RK808_INT_STS_MSK_REG2 0x4f |
116 | #define RK808_IO_POL_REG 0x50 | 122 | #define RK808_IO_POL_REG 0x50 |
117 | 123 | ||
118 | /* IRQ Definitions */ | 124 | /* RK818 */ |
125 | #define RK818_DCDC1 0 | ||
126 | #define RK818_LDO1 4 | ||
127 | #define RK818_NUM_REGULATORS 17 | ||
128 | |||
129 | enum rk818_reg { | ||
130 | RK818_ID_DCDC1, | ||
131 | RK818_ID_DCDC2, | ||
132 | RK818_ID_DCDC3, | ||
133 | RK818_ID_DCDC4, | ||
134 | RK818_ID_BOOST, | ||
135 | RK818_ID_LDO1, | ||
136 | RK818_ID_LDO2, | ||
137 | RK818_ID_LDO3, | ||
138 | RK818_ID_LDO4, | ||
139 | RK818_ID_LDO5, | ||
140 | RK818_ID_LDO6, | ||
141 | RK818_ID_LDO7, | ||
142 | RK818_ID_LDO8, | ||
143 | RK818_ID_LDO9, | ||
144 | RK818_ID_SWITCH, | ||
145 | RK818_ID_HDMI_SWITCH, | ||
146 | RK818_ID_OTG_SWITCH, | ||
147 | }; | ||
148 | |||
149 | #define RK818_DCDC_EN_REG 0x23 | ||
150 | #define RK818_LDO_EN_REG 0x24 | ||
151 | #define RK818_SLEEP_SET_OFF_REG1 0x25 | ||
152 | #define RK818_SLEEP_SET_OFF_REG2 0x26 | ||
153 | #define RK818_DCDC_UV_STS_REG 0x27 | ||
154 | #define RK818_DCDC_UV_ACT_REG 0x28 | ||
155 | #define RK818_LDO_UV_STS_REG 0x29 | ||
156 | #define RK818_LDO_UV_ACT_REG 0x2a | ||
157 | #define RK818_DCDC_PG_REG 0x2b | ||
158 | #define RK818_LDO_PG_REG 0x2c | ||
159 | #define RK818_VOUT_MON_TDB_REG 0x2d | ||
160 | #define RK818_BUCK1_CONFIG_REG 0x2e | ||
161 | #define RK818_BUCK1_ON_VSEL_REG 0x2f | ||
162 | #define RK818_BUCK1_SLP_VSEL_REG 0x30 | ||
163 | #define RK818_BUCK2_CONFIG_REG 0x32 | ||
164 | #define RK818_BUCK2_ON_VSEL_REG 0x33 | ||
165 | #define RK818_BUCK2_SLP_VSEL_REG 0x34 | ||
166 | #define RK818_BUCK3_CONFIG_REG 0x36 | ||
167 | #define RK818_BUCK4_CONFIG_REG 0x37 | ||
168 | #define RK818_BUCK4_ON_VSEL_REG 0x38 | ||
169 | #define RK818_BUCK4_SLP_VSEL_REG 0x39 | ||
170 | #define RK818_BOOST_CONFIG_REG 0x3a | ||
171 | #define RK818_LDO1_ON_VSEL_REG 0x3b | ||
172 | #define RK818_LDO1_SLP_VSEL_REG 0x3c | ||
173 | #define RK818_LDO2_ON_VSEL_REG 0x3d | ||
174 | #define RK818_LDO2_SLP_VSEL_REG 0x3e | ||
175 | #define RK818_LDO3_ON_VSEL_REG 0x3f | ||
176 | #define RK818_LDO3_SLP_VSEL_REG 0x40 | ||
177 | #define RK818_LDO4_ON_VSEL_REG 0x41 | ||
178 | #define RK818_LDO4_SLP_VSEL_REG 0x42 | ||
179 | #define RK818_LDO5_ON_VSEL_REG 0x43 | ||
180 | #define RK818_LDO5_SLP_VSEL_REG 0x44 | ||
181 | #define RK818_LDO6_ON_VSEL_REG 0x45 | ||
182 | #define RK818_LDO6_SLP_VSEL_REG 0x46 | ||
183 | #define RK818_LDO7_ON_VSEL_REG 0x47 | ||
184 | #define RK818_LDO7_SLP_VSEL_REG 0x48 | ||
185 | #define RK818_LDO8_ON_VSEL_REG 0x49 | ||
186 | #define RK818_LDO8_SLP_VSEL_REG 0x4a | ||
187 | #define RK818_BOOST_LDO9_ON_VSEL_REG 0x54 | ||
188 | #define RK818_BOOST_LDO9_SLP_VSEL_REG 0x55 | ||
189 | #define RK818_DEVCTRL_REG 0x4b | ||
190 | #define RK818_INT_STS_REG1 0X4c | ||
191 | #define RK818_INT_STS_MSK_REG1 0x4d | ||
192 | #define RK818_INT_STS_REG2 0x4e | ||
193 | #define RK818_INT_STS_MSK_REG2 0x4f | ||
194 | #define RK818_IO_POL_REG 0x50 | ||
195 | #define RK818_H5V_EN_REG 0x52 | ||
196 | #define RK818_SLEEP_SET_OFF_REG3 0x53 | ||
197 | #define RK818_BOOST_LDO9_ON_VSEL_REG 0x54 | ||
198 | #define RK818_BOOST_LDO9_SLP_VSEL_REG 0x55 | ||
199 | #define RK818_BOOST_CTRL_REG 0x56 | ||
200 | #define RK818_DCDC_ILMAX 0x90 | ||
201 | #define RK818_USB_CTRL_REG 0xa1 | ||
202 | |||
203 | #define RK818_H5V_EN BIT(0) | ||
204 | #define RK818_REF_RDY_CTRL BIT(1) | ||
205 | #define RK818_USB_ILIM_SEL_MASK 0xf | ||
206 | #define RK818_USB_ILMIN_2000MA 0x7 | ||
207 | #define RK818_USB_CHG_SD_VSEL_MASK 0x70 | ||
208 | |||
209 | /* RK808 IRQ Definitions */ | ||
119 | #define RK808_IRQ_VOUT_LO 0 | 210 | #define RK808_IRQ_VOUT_LO 0 |
120 | #define RK808_IRQ_VB_LO 1 | 211 | #define RK808_IRQ_VB_LO 1 |
121 | #define RK808_IRQ_PWRON 2 | 212 | #define RK808_IRQ_PWRON 2 |
@@ -137,6 +228,43 @@ enum rk808_reg { | |||
137 | #define RK808_IRQ_PLUG_IN_INT_MSK BIT(0) | 228 | #define RK808_IRQ_PLUG_IN_INT_MSK BIT(0) |
138 | #define RK808_IRQ_PLUG_OUT_INT_MSK BIT(1) | 229 | #define RK808_IRQ_PLUG_OUT_INT_MSK BIT(1) |
139 | 230 | ||
231 | /* RK818 IRQ Definitions */ | ||
232 | #define RK818_IRQ_VOUT_LO 0 | ||
233 | #define RK818_IRQ_VB_LO 1 | ||
234 | #define RK818_IRQ_PWRON 2 | ||
235 | #define RK818_IRQ_PWRON_LP 3 | ||
236 | #define RK818_IRQ_HOTDIE 4 | ||
237 | #define RK818_IRQ_RTC_ALARM 5 | ||
238 | #define RK818_IRQ_RTC_PERIOD 6 | ||
239 | #define RK818_IRQ_USB_OV 7 | ||
240 | #define RK818_IRQ_PLUG_IN 8 | ||
241 | #define RK818_IRQ_PLUG_OUT 9 | ||
242 | #define RK818_IRQ_CHG_OK 10 | ||
243 | #define RK818_IRQ_CHG_TE 11 | ||
244 | #define RK818_IRQ_CHG_TS1 12 | ||
245 | #define RK818_IRQ_TS2 13 | ||
246 | #define RK818_IRQ_CHG_CVTLIM 14 | ||
247 | #define RK818_IRQ_DISCHG_ILIM 15 | ||
248 | |||
249 | #define RK818_IRQ_VOUT_LO_MSK BIT(0) | ||
250 | #define RK818_IRQ_VB_LO_MSK BIT(1) | ||
251 | #define RK818_IRQ_PWRON_MSK BIT(2) | ||
252 | #define RK818_IRQ_PWRON_LP_MSK BIT(3) | ||
253 | #define RK818_IRQ_HOTDIE_MSK BIT(4) | ||
254 | #define RK818_IRQ_RTC_ALARM_MSK BIT(5) | ||
255 | #define RK818_IRQ_RTC_PERIOD_MSK BIT(6) | ||
256 | #define RK818_IRQ_USB_OV_MSK BIT(7) | ||
257 | #define RK818_IRQ_PLUG_IN_MSK BIT(0) | ||
258 | #define RK818_IRQ_PLUG_OUT_MSK BIT(1) | ||
259 | #define RK818_IRQ_CHG_OK_MSK BIT(2) | ||
260 | #define RK818_IRQ_CHG_TE_MSK BIT(3) | ||
261 | #define RK818_IRQ_CHG_TS1_MSK BIT(4) | ||
262 | #define RK818_IRQ_TS2_MSK BIT(5) | ||
263 | #define RK818_IRQ_CHG_CVTLIM_MSK BIT(6) | ||
264 | #define RK818_IRQ_DISCHG_ILIM_MSK BIT(7) | ||
265 | |||
266 | #define RK818_NUM_IRQ 16 | ||
267 | |||
140 | #define RK808_VBAT_LOW_2V8 0x00 | 268 | #define RK808_VBAT_LOW_2V8 0x00 |
141 | #define RK808_VBAT_LOW_2V9 0x01 | 269 | #define RK808_VBAT_LOW_2V9 0x01 |
142 | #define RK808_VBAT_LOW_3V0 0x02 | 270 | #define RK808_VBAT_LOW_3V0 0x02 |
@@ -191,9 +319,17 @@ enum { | |||
191 | BOOST_ILMIN_250MA, | 319 | BOOST_ILMIN_250MA, |
192 | }; | 320 | }; |
193 | 321 | ||
322 | enum { | ||
323 | RK808_ID = 0x0000, | ||
324 | RK818_ID = 0x8181, | ||
325 | }; | ||
326 | |||
194 | struct rk808 { | 327 | struct rk808 { |
195 | struct i2c_client *i2c; | 328 | struct i2c_client *i2c; |
196 | struct regmap_irq_chip_data *irq_data; | 329 | struct regmap_irq_chip_data *irq_data; |
197 | struct regmap *regmap; | 330 | struct regmap *regmap; |
331 | long variant; | ||
332 | const struct regmap_config *regmap_cfg; | ||
333 | const struct regmap_irq_chip *regmap_irq_chip; | ||
198 | }; | 334 | }; |
199 | #endif /* __LINUX_REGULATOR_rk808_H */ | 335 | #endif /* __LINUX_REGULATOR_RK808_H */ |
diff --git a/include/linux/mfd/syscon/exynos5-pmu.h b/include/linux/mfd/syscon/exynos5-pmu.h index 76f30f940c70..c28ff21ca4d2 100644 --- a/include/linux/mfd/syscon/exynos5-pmu.h +++ b/include/linux/mfd/syscon/exynos5-pmu.h | |||
@@ -43,8 +43,10 @@ | |||
43 | #define EXYNOS5433_MIPI_PHY2_CONTROL (0x718) | 43 | #define EXYNOS5433_MIPI_PHY2_CONTROL (0x718) |
44 | 44 | ||
45 | #define EXYNOS5_PHY_ENABLE BIT(0) | 45 | #define EXYNOS5_PHY_ENABLE BIT(0) |
46 | |||
47 | #define EXYNOS5_MIPI_PHY_S_RESETN BIT(1) | 46 | #define EXYNOS5_MIPI_PHY_S_RESETN BIT(1) |
48 | #define EXYNOS5_MIPI_PHY_M_RESETN BIT(2) | 47 | #define EXYNOS5_MIPI_PHY_M_RESETN BIT(2) |
49 | 48 | ||
49 | #define EXYNOS5433_PAD_RETENTION_AUD_OPTION (0x3028) | ||
50 | #define EXYNOS5433_PAD_INITIATE_WAKEUP_FROM_LOWPWR BIT(28) | ||
51 | |||
50 | #endif /* _LINUX_MFD_SYSCON_PMU_EXYNOS5_H_ */ | 52 | #endif /* _LINUX_MFD_SYSCON_PMU_EXYNOS5_H_ */ |
diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h index 1c88231496d3..4ccda8969639 100644 --- a/include/linux/mfd/tps65217.h +++ b/include/linux/mfd/tps65217.h | |||
@@ -73,6 +73,7 @@ | |||
73 | #define TPS65217_PPATH_AC_CURRENT_MASK 0x0C | 73 | #define TPS65217_PPATH_AC_CURRENT_MASK 0x0C |
74 | #define TPS65217_PPATH_USB_CURRENT_MASK 0x03 | 74 | #define TPS65217_PPATH_USB_CURRENT_MASK 0x03 |
75 | 75 | ||
76 | #define TPS65217_INT_RESERVEDM BIT(7) | ||
76 | #define TPS65217_INT_PBM BIT(6) | 77 | #define TPS65217_INT_PBM BIT(6) |
77 | #define TPS65217_INT_ACM BIT(5) | 78 | #define TPS65217_INT_ACM BIT(5) |
78 | #define TPS65217_INT_USBM BIT(4) | 79 | #define TPS65217_INT_USBM BIT(4) |
@@ -233,6 +234,13 @@ struct tps65217_bl_pdata { | |||
233 | int dft_brightness; | 234 | int dft_brightness; |
234 | }; | 235 | }; |
235 | 236 | ||
237 | enum tps65217_irq_type { | ||
238 | TPS65217_IRQ_PB, | ||
239 | TPS65217_IRQ_AC, | ||
240 | TPS65217_IRQ_USB, | ||
241 | TPS65217_NUM_IRQ | ||
242 | }; | ||
243 | |||
236 | /** | 244 | /** |
237 | * struct tps65217_board - packages regulator init data | 245 | * struct tps65217_board - packages regulator init data |
238 | * @tps65217_regulator_data: regulator initialization values | 246 | * @tps65217_regulator_data: regulator initialization values |
@@ -258,6 +266,10 @@ struct tps65217 { | |||
258 | struct regulator_desc desc[TPS65217_NUM_REGULATOR]; | 266 | struct regulator_desc desc[TPS65217_NUM_REGULATOR]; |
259 | struct regmap *regmap; | 267 | struct regmap *regmap; |
260 | u8 *strobes; | 268 | u8 *strobes; |
269 | struct irq_domain *irq_domain; | ||
270 | struct mutex irq_lock; | ||
271 | u8 irq_mask; | ||
272 | int irq; | ||
261 | }; | 273 | }; |
262 | 274 | ||
263 | static inline struct tps65217 *dev_to_tps65217(struct device *dev) | 275 | static inline struct tps65217 *dev_to_tps65217(struct device *dev) |
diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h index 36795a1be479..a2e88761c09f 100644 --- a/include/linux/mfd/twl6040.h +++ b/include/linux/mfd/twl6040.h | |||
@@ -168,7 +168,7 @@ | |||
168 | #define TWL6040_VIBROCDET 0x20 | 168 | #define TWL6040_VIBROCDET 0x20 |
169 | #define TWL6040_TSHUTDET 0x40 | 169 | #define TWL6040_TSHUTDET 0x40 |
170 | 170 | ||
171 | #define TWL6040_CELLS 3 | 171 | #define TWL6040_CELLS 4 |
172 | 172 | ||
173 | #define TWL6040_REV_ES1_0 0x00 | 173 | #define TWL6040_REV_ES1_0 0x00 |
174 | #define TWL6040_REV_ES1_1 0x01 /* Rev ES1.1 and ES1.2 */ | 174 | #define TWL6040_REV_ES1_1 0x01 /* Rev ES1.1 and ES1.2 */ |