aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/omapdrm/omap_irq.c
diff options
context:
space:
mode:
authorJanusz Krzysztofik <jkrzyszt@tis.icnet.pl>2011-02-10 13:24:32 +0100
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-02-11 11:00:30 +0000
commit8e6bfb9b1f79e07c18b0ae406c7c678fc54e4d8e (patch)
tree8bf730fcb5553ad71ceab2acc1baf55296d6e792 /drivers/gpu/drm/omapdrm/omap_irq.c
parentb66a70d5e9929f3b0df5a7177bba75652d2f4c3e (diff)
ASoC: CX20442: fix wrong reg_cache_default content
Content of the CX20442's snd_soc_codec_driver.reg_cache_default pointed area, introduced with my recent NULL pointer dereferece fix (commit f019ee5feb344ff0b22b58df4568676295aae14f), occured wrong after further testing, more thorough than just booting successfully. There are two problems with it: 1) It should read (1 << CX20442_TELOUT) | (1 << CX20442_MIC), not CX20442_TELOUT | CX20442_MIC. 2) While correctly matching actual codec hardware state on boot when fixed per 1), a few more code modifications would still be required to reflect that state not only into register cache, but also force them into DAPM pins state, otherwise an inconsitency occures which may prevent further codec state changes from being applied correctly. As a result, the phone stops ringing after reboot, until someone picks up the handset for the first time. Revert that reg_cache_default content to a working, previous de facto default value of 0, in hope this change can still be accepted as an rc cycle fix. Created and tested against linux-2.6.38-rc4 Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_irq.c')
0 files changed, 0 insertions, 0 deletions
Add support for v3 silicon mfd: lpc_ich: Add support for iTCO v3 mfd: lpc_ich: Remove lpc_ich_cfg struct use mfd: lpc_ich: Only configure watchdog or GPIO when present ...
Diffstat
-rw-r--r--Documentation/devicetree/bindings/iio/adc/twl4030-madc.txt24
-rw-r--r--Documentation/devicetree/bindings/mfd/arizona.txt23
-rw-r--r--Documentation/devicetree/bindings/mfd/bcm590xx.txt37
-rw-r--r--Documentation/devicetree/bindings/mfd/da9055.txt72
-rw-r--r--Documentation/devicetree/bindings/mfd/omap-usb-host.txt23
-rw-r--r--Documentation/devicetree/bindings/mfd/omap-usb-tll.txt10
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt96
-rw-r--r--Documentation/devicetree/bindings/mfd/s2mps11.txt24
-rw-r--r--arch/arm/boot/dts/omap4.dtsi6
-rw-r--r--arch/arm/boot/dts/omap5.dtsi6
-rw-r--r--arch/arm/mach-omap2/cclock3xxx_data.c4
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c6
-rw-r--r--drivers/clk/ti/clk-3xxx.c4
-rw-r--r--drivers/gpio/gpio-ich.c26
-rw-r--r--drivers/iio/adc/Kconfig10
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/twl4030-madc.c (renamed from drivers/mfd/twl4030-madc.c)321
-rw-r--r--drivers/mfd/88pm800.c3
-rw-r--r--drivers/mfd/88pm860x-core.c6
-rw-r--r--drivers/mfd/Kconfig98
-rw-r--r--drivers/mfd/Makefile6
-rw-r--r--drivers/mfd/adp5520.c1
-rw-r--r--drivers/mfd/as3722.c1
-rw-r--r--drivers/mfd/bcm590xx.c93
-rw-r--r--drivers/mfd/cs5535-mfd.c1
-rw-r--r--drivers/mfd/da9052-core.c3
-rw-r--r--drivers/mfd/da9052-i2c.c5
-rw-r--r--drivers/mfd/da9052-spi.c1
-rw-r--r--drivers/mfd/da9055-i2c.c8
-rw-r--r--drivers/mfd/da9063-core.c25
-rw-r--r--drivers/mfd/janz-cmodio.c1
-rw-r--r--drivers/mfd/kempld-core.c31
-rw-r--r--drivers/mfd/lpc_ich.c151
-rw-r--r--drivers/mfd/lpc_sch.c1
-rw-r--r--drivers/mfd/max14577.c6
-rw-r--r--drivers/mfd/max77686.c4
-rw-r--r--drivers/mfd/max77693.c12
-rw-r--r--drivers/mfd/max8925-i2c.c9
-rw-r--r--drivers/mfd/max8997.c18
-rw-r--r--drivers/mfd/max8998.c4
-rw-r--r--drivers/mfd/mc13xxx-spi.c5
-rw-r--r--drivers/mfd/mcp-sa11x0.c1
-rw-r--r--drivers/mfd/omap-usb-host.c189
-rw-r--r--drivers/mfd/omap-usb-tll.c2
-rw-r--r--drivers/mfd/pcf50633-adc.c1
-rw-r--r--drivers/mfd/pm8921-core.c419
-rw-r--r--drivers/mfd/pm8xxx-irq.c371
-rw-r--r--drivers/mfd/rc5t583-irq.c1
-rw-r--r--drivers/mfd/rdc321x-southbridge.c1
-rw-r--r--drivers/mfd/retu-mfd.c1
-rw-r--r--drivers/mfd/rtsx_usb.c760
-rw-r--r--drivers/mfd/sec-core.c17
-rw-r--r--drivers/mfd/smsc-ece1099.c1
-rw-r--r--drivers/mfd/stmpe.c2
-rw-r--r--drivers/mfd/stw481x.c8
-rw-r--r--drivers/mfd/syscon.c9
-rw-r--r--drivers/mfd/tc3589x.c84
-rw-r--r--drivers/mfd/ti-ssp.c465
-rw-r--r--drivers/mfd/ti_am335x_tscadc.c24
-rw-r--r--drivers/mfd/timberdale.c2
-rw-r--r--drivers/mfd/tps65218.c282
-rw-r--r--drivers/mfd/tps65910.c5
-rw-r--r--drivers/mfd/tps65912-core.c1
-rw-r--r--drivers/mfd/tps65912-irq.c1
-rw-r--r--drivers/mfd/twl-core.c10
-rw-r--r--drivers/mfd/twl4030-irq.c1
-rw-r--r--drivers/mfd/twl6030-irq.c1
-rw-r--r--drivers/mfd/twl6040.c6
-rw-r--r--drivers/mfd/ucb1x00-core.c4
-rw-r--r--drivers/mfd/vexpress-config.c3
-rw-r--r--drivers/mfd/vexpress-sysreg.c2
-rw-r--r--drivers/mfd/wm5102-tables.c36
-rw-r--r--drivers/mfd/wm5110-tables.c174
-rw-r--r--drivers/mfd/wm8350-core.c1
-rw-r--r--drivers/mfd/wm8350-irq.c1
-rw-r--r--drivers/mfd/wm8400-core.c22
-rw-r--r--drivers/watchdog/iTCO_wdt.c137
-rw-r--r--include/linux/i2c/twl.h12
-rw-r--r--include/linux/i2c/twl4030-madc.h2
-rw-r--r--include/linux/mfd/arizona/registers.h84
-rw-r--r--include/linux/mfd/bcm590xx.h31
-rw-r--r--include/linux/mfd/da9052/da9052.h1
-rw-r--r--include/linux/mfd/da9063/core.h6
-rw-r--r--include/linux/mfd/da9063/registers.h120
-rw-r--r--include/linux/mfd/lpc_ich.h25
-rw-r--r--include/linux/mfd/max14577-private.h8
-rw-r--r--include/linux/mfd/max14577.h5
-rw-r--r--include/linux/mfd/pm8xxx/irq.h59
-rw-r--r--include/linux/mfd/pm8xxx/pm8921.h30
-rw-r--r--include/linux/mfd/rtsx_usb.h628
-rw-r--r--include/linux/mfd/tps65218.h284
-rw-r--r--include/linux/ssbi.h20
92 files changed, 3958 insertions, 1588 deletions
diff --git a/Documentation/devicetree/bindings/iio/adc/twl4030-madc.txt b/Documentation/devicetree/bindings/iio/adc/twl4030-madc.txt
new file mode 100644
index 00000000000..6bdd21404b5
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/twl4030-madc.txt
@@ -0,0 +1,24 @@
+* TWL4030 Monitoring Analog to Digital Converter (MADC)
+
+The MADC subsystem in the TWL4030 consists of a 10-bit ADC
+combined with a 16-input analog multiplexer.
+
+Required properties:
+ - compatible: Should contain "ti,twl4030-madc".
+ - interrupts: IRQ line for the MADC submodule.
+ - #io-channel-cells: Should be set to <1>.
+
+Optional properties:
+ - ti,system-uses-second-madc-irq: boolean, set if the second madc irq register
+ should be used, which is intended to be used
+ by Co-Processors (e.g. a modem).
+
+Example:
+
+&twl {
+ madc {
+ compatible = "ti,twl4030-madc";
+ interrupts = <3>;
+ #io-channel-cells = <1>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/mfd/arizona.txt b/Documentation/devicetree/bindings/mfd/arizona.txt
index 0e295c9d893..36a0c3d8c72 100644
--- a/Documentation/devicetree/bindings/mfd/arizona.txt
+++ b/Documentation/devicetree/bindings/mfd/arizona.txt
@@ -5,9 +5,10 @@ of analogue I/O.
Required properties:
- - compatible : one of the following chip-specific strings:
- "wlf,wm5102"
- "wlf,wm5110"
+ - compatible : One of the following chip-specific strings:
+ "wlf,wm5102"
+ "wlf,wm5110"
+ "wlf,wm8997"
- reg : I2C slave address when connected using I2C, chip select number when
using SPI.
@@ -25,8 +26,9 @@ Required properties:
- #gpio-cells : Must be 2. The first cell is the pin number and the
second cell is used to specify optional parameters (currently unused).
- - AVDD1-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply, CPVDD-supply,
- SPKVDDL-supply, SPKVDDR-supply : power supplies for the device, as covered
+ - AVDD-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply (wm5102, wm5110),
+ CPVDD-supply, SPKVDDL-supply (wm5102, wm5110), SPKVDDR-supply (wm5102,
+ wm5110), SPKVDD-supply (wm8997) : Power supplies for the device, as covered
in Documentation/devicetree/bindings/regulator/regulator.txt
Optional properties:
@@ -46,6 +48,7 @@ codec: wm5102@1a {
compatible = "wlf,wm5102";
reg = <0x1a>;
interrupts = <347>;
+ interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&gic>;
@@ -53,10 +56,10 @@ codec: wm5102@1a {
#gpio-cells = <2>;
wlf,gpio-defaults = <
- 0x00000000, /* AIF1TXLRCLK */
- 0xffffffff,
- 0xffffffff,
- 0xffffffff,
- 0xffffffff,
+ 0x00000000 /* AIF1TXLRCLK */
+ 0xffffffff
+ 0xffffffff
+ 0xffffffff
+ 0xffffffff
>;
};
diff --git a/Documentation/devicetree/bindings/mfd/bcm590xx.txt b/Documentation/devicetree/bindings/mfd/bcm590xx.txt
new file mode 100644
index 00000000000..1fe30e2b10d
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/bcm590xx.txt
@@ -0,0 +1,37 @@
+-------------------------------
+BCM590xx Power Management Units
+-------------------------------
+
+Required properties:
+- compatible: "brcm,bcm59056"
+- reg: I2C slave address
+- interrupts: interrupt for the PMU. Generic interrupt client node bindings
+ are described in interrupt-controller/interrupts.txt
+
+------------------
+Voltage Regulators
+------------------
+
+Optional child nodes:
+- regulators: container node for regulators following the generic
+ regulator binding in regulator/regulator.txt
+
+ The valid regulator node names for BCM59056 are:
+ rfldo, camldo1, camldo2, simldo1, simldo2, sdldo, sdxldo,
+ mmcldo1, mmcldo2, audldo, micldo, usbldo, vibldo,
+ csr, iosr1, iosr2, msr, sdsr1, sdsr2, vsr
+
+Example:
+ pmu: bcm59056@8 {
+ compatible = "brcm,bcm59056";
+ reg = <0x08>;
+ interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
+ regulators {
+ rfldo_reg: rfldo {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ...
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/da9055.txt b/Documentation/devicetree/bindings/mfd/da9055.txt
new file mode 100644
index 00000000000..6dab34d34fc
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/da9055.txt
@@ -0,0 +1,72 @@
+* Dialog DA9055 Power Management Integrated Circuit (PMIC)
+
+DA9055 consists of a large and varied group of sub-devices (I2C Only):
+
+Device Supply Names Description
+------ ------------ -----------
+da9055-gpio : : GPIOs
+da9055-regulator : : Regulators
+da9055-onkey : : On key
+da9055-rtc : : RTC
+da9055-hwmon : : ADC
+da9055-watchdog : : Watchdog
+
+The CODEC device in DA9055 has a separate, configurable I2C address and so
+is instantiated separately from the PMIC.
+
+For details on accompanying CODEC I2C device, see the following:
+Documentation/devicetree/bindings/sound/da9055.txt
+
+======
+
+Required properties:
+- compatible : Should be "dlg,da9055-pmic"
+- reg: Specifies the I2C slave address (defaults to 0x5a but can be modified)
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+ the IRQs from da9055 are delivered to.
+- interrupts: IRQ line info for da9055 chip.
+- interrupt-controller: da9055 has internal IRQs (has own IRQ domain).
+- #interrupt-cells: Should be 1, is the local IRQ number for da9055.
+
+Sub-nodes:
+- regulators : Contain the regulator nodes. The DA9055 regulators are
+ bound using their names as listed below:
+
+ buck1 : regulator BUCK1
+ buck2 : regulator BUCK2
+ ldo1 : regulator LDO1
+ ldo2 : regulator LDO2
+ ldo3 : regulator LDO3
+ ldo4 : regulator LDO4
+ ldo5 : regulator LDO5
+ ldo6 : regulator LDO6
+
+ The bindings details of individual regulator device can be found in:
+ Documentation/devicetree/bindings/regulator/regulator.txt
+
+
+Example:
+
+ pmic: da9055-pmic@5a {
+ compatible = "dlg,da9055-pmic";
+ reg = <0x5a>;
+ interrupt-parent = <&intc>;
+ interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ regulators {
+ buck1: BUCK1 {
+ regulator-min-microvolt = <725000>;
+ regulator-max-microvolt = <2075000>;
+ };
+ buck2: BUCK2 {
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <2500000>;
+ };
+ ldo1: LDO1 {
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/omap-usb-host.txt b/Documentation/devicetree/bindings/mfd/omap-usb-host.txt
index b381fa696bf..4721b2d521e 100644
--- a/Documentation/devicetree/bindings/mfd/omap-usb-host.txt
+++ b/Documentation/devicetree/bindings/mfd/omap-usb-host.txt
@@ -32,6 +32,29 @@ Optional properties:
- single-ulpi-bypass: Must be present if the controller contains a single
ULPI bypass control bit. e.g. OMAP3 silicon <= ES2.1
+- clocks: a list of phandles and clock-specifier pairs, one for each entry in
+ clock-names.
+
+- clock-names: should include:
+ For OMAP3
+ * "usbhost_120m_fck" - 120MHz Functional clock.
+
+ For OMAP4+
+ * "refclk_60m_int" - 60MHz internal reference clock for UTMI clock mux
+ * "refclk_60m_ext_p1" - 60MHz external ref. clock for Port 1's UTMI clock mux.
+ * "refclk_60m_ext_p2" - 60MHz external ref. clock for Port 2's UTMI clock mux
+ * "utmi_p1_gfclk" - Port 1 UTMI clock mux.
+ * "utmi_p2_gfclk" - Port 2 UTMI clock mux.
+ * "usb_host_hs_utmi_p1_clk" - Port 1 UTMI clock gate.
+ * "usb_host_hs_utmi_p2_clk" - Port 2 UTMI clock gate.
+ * "usb_host_hs_utmi_p3_clk" - Port 3 UTMI clock gate.
+ * "usb_host_hs_hsic480m_p1_clk" - Port 1 480MHz HSIC clock gate.
+ * "usb_host_hs_hsic480m_p2_clk" - Port 2 480MHz HSIC clock gate.
+ * "usb_host_hs_hsic480m_p3_clk" - Port 3 480MHz HSIC clock gate.
+ * "usb_host_hs_hsic60m_p1_clk" - Port 1 60MHz HSIC clock gate.
+ * "usb_host_hs_hsic60m_p2_clk" - Port 2 60MHz HSIC clock gate.
+ * "usb_host_hs_hsic60m_p3_clk" - Port 3 60MHz HSIC clock gate.
+
Required properties if child node exists:
- #address-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/mfd/omap-usb-tll.txt b/Documentation/devicetree/bindings/mfd/omap-usb-tll.txt
index 62fe69724e3..c58d70437fc 100644
--- a/Documentation/devicetree/bindings/mfd/omap-usb-tll.txt
+++ b/Documentation/devicetree/bindings/mfd/omap-usb-tll.txt
@@ -7,6 +7,16 @@ Required properties:
- interrupts : should contain the TLL module's interrupt
- ti,hwmod : must contain "usb_tll_hs"
+Optional properties:
+
+- clocks: a list of phandles and clock-specifier pairs, one for each entry in
+ clock-names.
+
+- clock-names: should include:
+ * "usb_tll_hs_usb_ch0_clk" - USB TLL channel 0 clock
+ * "usb_tll_hs_usb_ch1_clk" - USB TLL channel 1 clock
+ * "usb_tll_hs_usb_ch2_clk" - USB TLL channel 2 clock
+
Example:
usbhstll: usbhstll@4a062000 {
diff --git a/Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt b/Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt
new file mode 100644
index 00000000000..03518dc8b6b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt
@@ -0,0 +1,96 @@
+Qualcomm PM8xxx PMIC multi-function devices
+
+The PM8xxx family of Power Management ICs are used to provide regulated
+voltages and other various functionality to Qualcomm SoCs.
+
+= PROPERTIES
+
+- compatible:
+ Usage: required
+ Value type: <string>
+ Definition: must be one of:
+ "qcom,pm8058"
+ "qcom,pm8921"
+
+- #address-cells:
+ Usage: required
+ Value type: <u32>
+ Definition: must be 1
+
+- #size-cells:
+ Usage: required
+ Value type: <u32>
+ Definition: must be 0
+
+- interrupts:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: specifies the interrupt that indicates a subdevice
+ has generated an interrupt (summary interrupt). The
+ format of the specifier is defined by the binding document
+ describing the node's interrupt parent.
+
+- #interrupt-cells:
+ Usage: required
+ Value type : <u32>
+ Definition: must be 2. Specifies the number of cells needed to encode
+ an interrupt source. The 1st cell contains the interrupt
+ number. The 2nd cell is the trigger type and level flags
+ encoded as follows:
+
+ 1 = low-to-high edge triggered
+ 2 = high-to-low edge triggered
+ 4 = active high level-sensitive
+ 8 = active low level-sensitive
+
+- interrupt-controller:
+ Usage: required
+ Value type: <empty>
+ Definition: identifies this node as an interrupt controller
+
+= SUBCOMPONENTS
+
+The PMIC contains multiple independent functions, each described in a subnode.
+The below bindings specify the set of valid subnodes.
+
+== Real-Time Clock
+
+- compatible:
+ Usage: required
+ Value type: <string>
+ Definition: must be one of:
+ "qcom,pm8058-rtc"
+ "qcom,pm8921-rtc"
+
+- reg:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: single entry specifying the base address of the RTC registers
+
+- interrupts:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: single entry specifying the RTC's alarm interrupt
+
+- allow-set-time:
+ Usage: optional
+ Value type: <empty>
+ Definition: indicates that the setting of RTC time is allowed by
+ the host CPU
+
+= EXAMPLE
+
+ pmicintc: pmic@0 {
+ compatible = "qcom,pm8921";
+ interrupts = <104 8>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc@11d {
+ compatible = "qcom,pm8921-rtc";
+ reg = <0x11d>;
+ interrupts = <0x27 0>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/s2mps11.txt b/Documentation/devicetree/bindings/mfd/s2mps11.txt
index f69bec294f0..802e839b082 100644
--- a/Documentation/devicetree/bindings/mfd/s2mps11.txt
+++ b/Documentation/devicetree/bindings/mfd/s2mps11.txt
@@ -16,20 +16,25 @@ Optional properties:
- interrupts: Interrupt specifiers for interrupt sources.
Optional nodes:
-- clocks: s2mps11 provides three(AP/CP/BT) buffered 32.768 KHz outputs, so to
- register these as clocks with common clock framework instantiate a sub-node
- named "clocks". It uses the common clock binding documented in :
+- clocks: s2mps11 and s5m8767 provide three(AP/CP/BT) buffered 32.768 KHz
+ outputs, so to register these as clocks with common clock framework
+ instantiate a sub-node named "clocks". It uses the common clock binding
+ documented in :
[Documentation/devicetree/bindings/clock/clock-bindings.txt]
+ The s2mps14 provides two (AP/BT) buffered 32.768 KHz outputs.
- #clock-cells: should be 1.
- The following is the list of clocks generated by the controller. Each clock
is assigned an identifier and client nodes use this identifier to specify
the clock which they consume.
- Clock ID
- ----------------------
- 32KhzAP 0
- 32KhzCP 1
- 32KhzBT 2
+ Clock ID Devices
+ ----------------------------------------------------------
+ 32KhzAP 0 S2MPS11, S2MPS14, S5M8767
+ 32KhzCP 1 S2MPS11, S5M8767
+ 32KhzBT 2 S2MPS11, S2MPS14, S5M8767
+
+ - compatible: Should be one of: "samsung,s2mps11-clk", "samsung,s2mps14-clk",
+ "samsung,s5m8767-clk"
- regulators: The regulators of s2mps11 that have to be instantiated should be
included in a sub-node named 'regulators'. Regulator nodes included in this
@@ -75,7 +80,8 @@ Example:
compatible = "samsung,s2mps11-pmic";
reg = <0x66>;
- s2m_osc: clocks{
+ s2m_osc: clocks {
+ compatible = "samsung,s2mps11-clk";
#clock-cells = 1;
clock-output-names = "xx", "yy", "zz";
};
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index fe61976dc1a..0769ec57a3f 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -733,6 +733,12 @@
#address-cells = <1>;
#size-cells = <1>;
ranges;
+ clocks = <&init_60m_fclk>,
+ <&xclk60mhsp1_ck>,
+ <&xclk60mhsp2_ck>;
+ clock-names = "refclk_60m_int",
+ "refclk_60m_ext_p1",
+ "refclk_60m_ext_p2";
usbhsohci: ohci@4a064800 {
compatible = "ti,ohci-omap3";
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 8292ad0fe69..19155bb8483 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -814,6 +814,12 @@
#address-cells = <1>;
#size-cells = <1>;
ranges;
+ clocks = <&l3init_60m_fclk>,
+ <&xclk60mhsp1_ck>,
+ <&xclk60mhsp2_ck>;
+ clock-names = "refclk_60m_int",
+ "refclk_60m_ext_p1",
+ "refclk_60m_ext_p2";
usbhsohci: ohci@4a064800 {
compatible = "ti,ohci-omap3";
diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
index 11ed9152e66..8f5121b8968 100644
--- a/arch/arm/mach-omap2/cclock3xxx_data.c
+++ b/arch/arm/mach-omap2/cclock3xxx_data.c
@@ -3497,10 +3497,6 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "dss_tv_fck", &dss_tv_fck),
CLK(NULL, "dss_96m_fck", &dss_96m_fck),
CLK(NULL, "dss2_alwon_fck", &dss2_alwon_fck),
- CLK(NULL, "utmi_p1_gfclk", &dummy_ck),
- CLK(NULL, "utmi_p2_gfclk", &dummy_ck),
- CLK(NULL, "xclk60mhsp1_ck", &dummy_ck),
- CLK(NULL, "xclk60mhsp2_ck", &dummy_ck),
CLK(NULL, "init_60m_fclk", &dummy_ck),
CLK(NULL, "gpt1_fck", &gpt1_fck),
CLK(NULL, "aes2_ick", &aes2_ick),
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 9c7e23aa0e7..a123ff0070b 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1955,10 +1955,6 @@ static struct omap_hwmod_class omap3xxx_usb_host_hs_hwmod_class = {
.sysc = &omap3xxx_usb_host_hs_sysc,
};
-static struct omap_hwmod_opt_clk omap3xxx_usb_host_hs_opt_clks[] = {
- { .role = "ehci_logic_fck", .clk = "usbhost_120m_fck", },
-};
-
static struct omap_hwmod_irq_info omap3xxx_usb_host_hs_irqs[] = {
{ .name = "ohci-irq", .irq = 76 + OMAP_INTC_START, },
{ .name = "ehci-irq", .irq = 77 + OMAP_INTC_START, },
@@ -1981,8 +1977,6 @@ static struct omap_hwmod omap3xxx_usb_host_hs_hwmod = {
.idlest_stdby_bit = OMAP3430ES2_ST_USBHOST_STDBY_SHIFT,
},
},
- .opt_clks = omap3xxx_usb_host_hs_opt_clks,
- .opt_clks_cnt = ARRAY_SIZE(omap3xxx_usb_host_hs_opt_clks),
/*
* Errata: USBHOST Configured In Smart-Idle Can Lead To a Deadlock
diff --git a/drivers/clk/ti/clk-3xxx.c b/drivers/clk/ti/clk-3xxx.c
index d3230234f07..0d1750a8aea 100644
--- a/drivers/clk/ti/clk-3xxx.c
+++ b/drivers/clk/ti/clk-3xxx.c
@@ -130,10 +130,6 @@ static struct ti_dt_clk omap3xxx_clks[] = {
DT_CLK(NULL, "dss_tv_fck", "dss_tv_fck"),
DT_CLK(NULL, "dss_96m_fck", "dss_96m_fck"),
DT_CLK(NULL, "dss2_alwon_fck", "dss2_alwon_fck"),
- DT_CLK(NULL, "utmi_p1_gfclk", "dummy_ck"),
- DT_CLK(NULL, "utmi_p2_gfclk", "dummy_ck"),
- DT_CLK(NULL, "xclk60mhsp1_ck", "dummy_ck"),
- DT_CLK(NULL, "xclk60mhsp2_ck", "dummy_ck"),
DT_CLK(NULL, "init_60m_fclk", "dummy_ck"),
DT_CLK(NULL, "gpt1_fck", "gpt1_fck"),
DT_CLK(NULL, "aes2_ick", "aes2_ick"),
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c
index bfef20f8ab4..e73c6755a5e 100644
--- a/drivers/gpio/gpio-ich.c
+++ b/drivers/gpio/gpio-ich.c
@@ -1,5 +1,5 @@
/*
- * Intel ICH6-10, Series 5 and 6 GPIO driver
+ * Intel ICH6-10, Series 5 and 6, Atom C2000 (Avoton/Rangeley) GPIO driver
*
* Copyright (C) 2010 Extreme Engineering Solutions.
*
@@ -55,6 +55,16 @@ static const u8 ichx_reglen[3] = {
0x30, 0x10, 0x10,
};
+static const u8 avoton_regs[4][3] = {
+ {0x00, 0x80, 0x00},
+ {0x04, 0x84, 0x00},
+ {0x08, 0x88, 0x00},
+};
+
+static const u8 avoton_reglen[3] = {
+ 0x10, 0x10, 0x00,
+};
+
#define ICHX_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start)
#define ICHX_READ(reg, base_res) inl((reg) + (base_res)->start)
@@ -353,6 +363,17 @@ static struct ichx_desc intel5_desc = {
.reglen = ichx_reglen,
};
+/* Avoton */
+static struct ichx_desc avoton_desc = {
+ /* Avoton has only 59 GPIOs, but we assume the first set of register
+ * (Core) has 32 instead of 31 to keep gpio-ich compliance
+ */
+ .ngpio = 60,
+ .regs = avoton_regs,
+ .reglen = avoton_reglen,
+ .use_outlvl_cache = true,
+};
+
static int ichx_gpio_request_regions(struct resource *res_base,
const char *name, u8 use_gpio)
{
@@ -427,6 +448,9 @@ static int ichx_gpio_probe(struct platform_device *pdev)
case ICH_V10CONS_GPIO:
ichx_priv.desc = &ich10_cons_desc;
break;
+ case AVOTON_GPIO:
+ ichx_priv.desc = &avoton_desc;
+ break;
default:
return -ENODEV;
}
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 4bf4c16de97..d86196cfe4b 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -193,6 +193,16 @@ config TI_AM335X_ADC
Say yes here to build support for Texas Instruments ADC
driver which is also a MFD client.
+config TWL4030_MADC
+ tristate "TWL4030 MADC (Monitoring A/D Converter)"
+ depends on TWL4030_CORE
+ help
+ This driver provides support for Triton TWL4030-MADC. The
+ driver supports both RT and SW conversion methods.
+
+ This driver can also be built as a module. If so, the module will be
+ called twl4030-madc.
+
config TWL6030_GPADC
tristate "TWL6030 GPADC (General Purpose A/D Converter) Support"
depends on TWL4030_CORE
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index bb252540664..ab346d88c68 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
obj-$(CONFIG_NAU7802) += nau7802.o
obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
+obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
obj-$(CONFIG_VF610_ADC) += vf610_adc.o
obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
diff --git a/drivers/mfd/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
index 4c583e47133..7de1c4c8794 100644
--- a/drivers/mfd/twl4030-madc.c
+++ b/drivers/iio/adc/twl4030-madc.c
@@ -29,7 +29,6 @@
*
*/
-#include <linux/init.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
@@ -47,20 +46,84 @@
#include <linux/gfp.h>
#include <linux/err.h>
-/*
+#include <linux/iio/iio.h>
+
+/**
* struct twl4030_madc_data - a container for madc info
- * @dev - pointer to device structure for madc
- * @lock - mutex protecting this data structure
- * @requests - Array of request struct corresponding to SW1, SW2 and RT
- * @imr - Interrupt mask register of MADC
- * @isr - Interrupt status register of MADC
+ * @dev: Pointer to device structure for madc
+ * @lock: Mutex protecting this data structure
+ * @requests: Array of request struct corresponding to SW1, SW2 and RT
+ * @use_second_irq: IRQ selection (main or co-processor)
+ * @imr: Interrupt mask register of MADC
+ * @isr: Interrupt status register of MADC
*/
struct twl4030_madc_data {
struct device *dev;
struct mutex lock; /* mutex protecting this data structure */
struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
- int imr;
- int isr;
+ bool use_second_irq;
+ u8 imr;
+ u8 isr;
+};
+
+static int twl4030_madc_read(struct iio_dev *iio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long mask)
+{
+ struct twl4030_madc_data *madc = iio_priv(iio_dev);
+ struct twl4030_madc_request req;
+ int ret;
+
+ req.method = madc->use_second_irq ? TWL4030_MADC_SW2 : TWL4030_MADC_SW1;
+
+ req.channels = BIT(chan->channel);
+ req.active = false;
+ req.func_cb = NULL;
+ req.type = TWL4030_MADC_WAIT;
+ req.raw = !(mask == IIO_CHAN_INFO_PROCESSED);
+ req.do_avg = (mask == IIO_CHAN_INFO_AVERAGE_RAW);
+
+ ret = twl4030_madc_conversion(&req);
+ if (ret < 0)
+ return ret;
+
+ *val = req.rbuf[chan->channel];
+
+ return IIO_VAL_INT;
+}
+
+static const struct iio_info twl4030_madc_iio_info = {
+ .read_raw = &twl4030_madc_read,
+ .driver_module = THIS_MODULE,
+};
+
+#define TWL4030_ADC_CHANNEL(_channel, _type, _name) { \
+ .type = _type, \
+ .channel = _channel, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_AVERAGE_RAW) | \
+ BIT(IIO_CHAN_INFO_PROCESSED), \
+ .datasheet_name = _name, \
+ .indexed = 1, \
+}
+
+static const struct iio_chan_spec twl4030_madc_iio_channels[] = {
+ TWL4030_ADC_CHANNEL(0, IIO_VOLTAGE, "ADCIN0"),
+ TWL4030_ADC_CHANNEL(1, IIO_TEMP, "ADCIN1"),
+ TWL4030_ADC_CHANNEL(2, IIO_VOLTAGE, "ADCIN2"),
+ TWL4030_ADC_CHANNEL(3, IIO_VOLTAGE, "ADCIN3"),
+ TWL4030_ADC_CHANNEL(4, IIO_VOLTAGE, "ADCIN4"),
+ TWL4030_ADC_CHANNEL(5, IIO_VOLTAGE, "ADCIN5"),
+ TWL4030_ADC_CHANNEL(6, IIO_VOLTAGE, "ADCIN6"),
+ TWL4030_ADC_CHANNEL(7, IIO_VOLTAGE, "ADCIN7"),
+ TWL4030_ADC_CHANNEL(8, IIO_VOLTAGE, "ADCIN8"),
+ TWL4030_ADC_CHANNEL(9, IIO_VOLTAGE, "ADCIN9"),
+ TWL4030_ADC_CHANNEL(10, IIO_CURRENT, "ADCIN10"),
+ TWL4030_ADC_CHANNEL(11, IIO_VOLTAGE, "ADCIN11"),
+ TWL4030_ADC_CHANNEL(12, IIO_VOLTAGE, "ADCIN12"),
+ TWL4030_ADC_CHANNEL(13, IIO_VOLTAGE, "ADCIN13"),
+ TWL4030_ADC_CHANNEL(14, IIO_VOLTAGE, "ADCIN14"),
+ TWL4030_ADC_CHANNEL(15, IIO_VOLTAGE, "ADCIN15"),
};
static struct twl4030_madc_data *twl4030_madc;
@@ -91,17 +154,16 @@ twl4030_divider_ratios[16] = {
};
-/*
- * Conversion table from -3 to 55 degree Celcius
- */
-static int therm_tbl[] = {
-30800, 29500, 28300, 27100,
-26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900,
-17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100,
-11600, 11200, 10800, 10400, 10000, 9630, 9280, 8950, 8620, 8310,
-8020, 7730, 7460, 7200, 6950, 6710, 6470, 6250, 6040, 5830,
-5640, 5450, 5260, 5090, 4920, 4760, 4600, 4450, 4310, 4170,
-4040, 3910, 3790, 3670, 3550
+/* Conversion table from -3 to 55 degrees Celcius */
+static int twl4030_therm_tbl[] = {
+ 30800, 29500, 28300, 27100,
+ 26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700,
+ 17900, 17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100,
+ 12600, 12100, 11600, 11200, 10800, 10400, 10000, 9630, 9280,
+ 8950, 8620, 8310, 8020, 7730, 7460, 7200, 6950, 6710,
+ 6470, 6250, 6040, 5830, 5640, 5450, 5260, 5090, 4920,
+ 4760, 4600, 4450, 4310, 4170, 4040, 3910, 3790, 3670,
+ 3550
};
/*
@@ -133,37 +195,32 @@ const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
},
};
-/*
- * Function to read a particular channel value.
- * @madc - pointer to struct twl4030_madc_data
- * @reg - lsb of ADC Channel
- * If the i2c read fails it returns an error else returns 0.
+/**
+ * twl4030_madc_channel_raw_read() - Function to read a particular channel value
+ * @madc: pointer to struct twl4030_madc_data
+ * @reg: lsb of ADC Channel
+ *
+ * Return: 0 on success, an error code otherwise.
*/
static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg)
{
- u8 msb, lsb;
+ u16 val;
int ret;
/*
* For each ADC channel, we have MSB and LSB register pair. MSB address
* is always LSB address+1. reg parameter is the address of LSB register
*/
- ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &msb, reg + 1);
+ ret = twl_i2c_read_u16(TWL4030_MODULE_MADC, &val, reg);
if (ret) {
- dev_err(madc->dev, "unable to read MSB register 0x%X\n",
- reg + 1);
- return ret;
- }
- ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &lsb, reg);
- if (ret) {
- dev_err(madc->dev, "unable to read LSB register 0x%X\n", reg);
+ dev_err(madc->dev, "unable to read register 0x%X\n", reg);
return ret;
}
- return (int)(((msb << 8) | lsb) >> 6);
+ return (int)(val >> 6);
}
/*
- * Return battery temperature
+ * Return battery temperature in degrees Celsius
* Or < 0 on failure.
*/
static int twl4030battery_temperature(int raw_volt)
@@ -172,18 +229,18 @@ static int twl4030battery_temperature(int raw_volt)
int temp, curr, volt, res, ret;
volt = (raw_volt * TEMP_STEP_SIZE) / TEMP_PSR_R;
- /* Getting and calculating the supply current in micro ampers */
+ /* Getting and calculating the supply current in micro amperes */
ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
REG_BCICTL2);
if (ret < 0)
return ret;
+
curr = ((val & TWL4030_BCI_ITHEN) + 1) * 10;
/* Getting and calculating the thermistor resistance in ohms */
res = volt * 1000 / curr;
/* calculating temperature */
for (temp = 58; temp >= 0; temp--) {
- int actual = therm_tbl[temp];
-
+ int actual = twl4030_therm_tbl[temp];
if ((actual - res) >= 0)
break;
}
@@ -205,11 +262,12 @@ static int twl4030battery_current(int raw_volt)
else /* slope of 0.88 mV/mA */
return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R2;
}
+
/*
* Function to read channel values
* @madc - pointer to twl4030_madc_data struct
* @reg_base - Base address of the first channel
- * @Channels - 16 bit bitmap. If the bit is set, channel value is read
+ * @Channels - 16 bit bitmap. If the bit is set, channel's value is read
* @buf - The channel values are stored here. if read fails error
* @raw - Return raw values without conversion
* value is stored
@@ -220,17 +278,17 @@ static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
long channels, int *buf,
bool raw)
{
- int count = 0, count_req = 0, i;
+ int count = 0;
+ int i;
u8 reg;
for_each_set_bit(i, &channels, TWL4030_MADC_MAX_CHANNELS) {
- reg = reg_base + 2 * i;
+ reg = reg_base + (2 * i);
buf[i] = twl4030_madc_channel_raw_read(madc, reg);
if (buf[i] < 0) {
- dev_err(madc->dev,
- "Unable to read register 0x%X\n", reg);
- count_req++;
- continue;
+ dev_err(madc->dev, "Unable to read register 0x%X\n",
+ reg);
+ return buf[i];
}
if (raw) {
count++;
@@ -241,7 +299,7 @@ static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
buf[i] = twl4030battery_current(buf[i]);
if (buf[i] < 0) {
dev_err(madc->dev, "err reading current\n");
- count_req++;
+ return buf[i];
} else {
count++;
buf[i] = buf[i] - 750;
@@ -251,7 +309,7 @@ static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
buf[i] = twl4030battery_temperature(buf[i]);
if (buf[i] < 0) {
dev_err(madc->dev, "err reading temperature\n");
- count_req++;
+ return buf[i];
} else {
buf[i] -= 3;
count++;
@@ -272,8 +330,6 @@ static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
twl4030_divider_ratios[i].numerator);
}
}
- if (count_req)
- dev_err(madc->dev, "%d channel conversion failed\n", count_req);
return count;
}
@@ -297,13 +353,13 @@ static int twl4030_madc_enable_irq(struct twl4030_madc_data *madc, u8 id)
madc->imr);
return ret;
}
+
val &= ~(1 << id);
ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
if (ret) {
dev_err(madc->dev,
"unable to write imr register 0x%X\n", madc->imr);
return ret;
-
}
return 0;
@@ -366,7 +422,7 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
continue;
ret = twl4030_madc_disable_irq(madc, i);
if (ret < 0)
- dev_dbg(madc->dev, "Disable interrupt failed%d\n", i);
+ dev_dbg(madc->dev, "Disable interrupt failed %d\n", i);
madc->requests[i].result_pending = 1;
}
for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
@@ -448,21 +504,17 @@ static int twl4030_madc_start_conversion(struct twl4030_madc_data *madc,
{
const struct twl4030_madc_conversion_method *method;
int ret = 0;
+
+ if (conv_method != TWL4030_MADC_SW1 && conv_method != TWL4030_MADC_SW2)
+ return -ENOTSUPP;
+
method = &twl4030_conversion_methods[conv_method];
- switch (conv_method) {
- case TWL4030_MADC_SW1:
- case TWL4030_MADC_SW2:
- ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
- TWL4030_MADC_SW_START, method->ctrl);
- if (ret) {
- dev_err(madc->dev,
- "unable to write ctrl register 0x%X\n",
- method->ctrl);
- return ret;
- }
- break;
- default:
- break;
+ ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, TWL4030_MADC_SW_START,
+ method->ctrl);
+ if (ret) {
+ dev_err(madc->dev, "unable to write ctrl register 0x%X\n",
+ method->ctrl);
+ return ret;
}
return 0;
@@ -513,7 +565,6 @@ static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc,
int twl4030_madc_conversion(struct twl4030_madc_request *req)
{
const struct twl4030_madc_conversion_method *method;
- u8 ch_msb, ch_lsb;
int ret;
if (!req || !twl4030_madc)
@@ -529,38 +580,22 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
ret = -EBUSY;
goto out;
}
- ch_msb = (req->channels >> 8) & 0xff;
- ch_lsb = req->channels & 0xff;
method = &twl4030_conversion_methods[req->method];
/* Select channels to be converted */
- ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_msb, method->sel + 1);
- if (ret) {
- dev_err(twl4030_madc->dev,
- "unable to write sel register 0x%X\n", method->sel + 1);
- goto out;
- }
- ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_lsb, method->sel);
+ ret = twl_i2c_write_u16(TWL4030_MODULE_MADC, req->channels, method->sel);
if (ret) {
dev_err(twl4030_madc->dev,
- "unable to write sel register 0x%X\n", method->sel + 1);
+ "unable to write sel register 0x%X\n", method->sel);
goto out;
}
/* Select averaging for all channels if do_avg is set */
if (req->do_avg) {
- ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
- ch_msb, method->avg + 1);
+ ret = twl_i2c_write_u16(TWL4030_MODULE_MADC, req->channels,
+ method->avg);
if (ret) {
dev_err(twl4030_madc->dev,
"unable to write avg register 0x%X\n",
- method->avg + 1);
- goto out;
- }
- ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
- ch_lsb, method->avg);
- if (ret) {
- dev_err(twl4030_madc->dev,
- "unable to write sel reg 0x%X\n",
- method->sel + 1);
+ method->avg);
goto out;
}
}
@@ -601,10 +636,6 @@ out:
}
EXPORT_SYMBOL_GPL(twl4030_madc_conversion);
-/*
- * Return channel value
- * Or < 0 on failure.
- */
int twl4030_get_madc_conversion(int channel_no)
{
struct twl4030_madc_request req;
@@ -625,20 +656,25 @@ int twl4030_get_madc_conversion(int channel_no)
}
EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion);
-/*
+/**
+ * twl4030_madc_set_current_generator() - setup bias current
+ *
+ * @madc: pointer to twl4030_madc_data struct
+ * @chan: can be one of the two values:
+ * TWL4030_BCI_ITHEN
+ * Enables bias current for main battery type reading
+ * TWL4030_BCI_TYPEN
+ * Enables bias current for main battery temperature sensing
+ * @on: enable or disable chan.
+ *
* Function to enable or disable bias current for
* main battery type reading or temperature sensing
- * @madc - pointer to twl4030_madc_data struct
- * @chan - can be one of the two values
- * TWL4030_BCI_ITHEN - Enables bias current for main battery type reading
- * TWL4030_BCI_TYPEN - Enables bias current for main battery temperature
- * sensing
- * @on - enable or disable chan.
*/
static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
int chan, int on)
{
int ret;
+ int regmask;
u8 regval;
ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
@@ -648,10 +684,13 @@ static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
TWL4030_BCI_BCICTL1);
return ret;
}
+
+ regmask = chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
if (on)
- regval |= chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
+ regval |= regmask;
else
- regval &= chan ? ~TWL4030_BCI_ITHEN : ~TWL4030_BCI_TYPEN;
+ regval &= ~regmask;
+
ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
regval, TWL4030_BCI_BCICTL1);
if (ret) {
@@ -666,7 +705,7 @@ static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
/*
* Function that sets MADC software power on bit to enable MADC
* @madc - pointer to twl4030_madc_data struct
- * @on - Enable or disable MADC software powen on bit.
+ * @on - Enable or disable MADC software power on bit.
* returns error if i2c read/write fails else 0
*/
static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
@@ -702,31 +741,52 @@ static int twl4030_madc_probe(struct platform_device *pdev)
{
struct twl4030_madc_data *madc;
struct twl4030_madc_platform_data *pdata = dev_get_platdata(&pdev->dev);
- int ret;
+ struct device_node *np = pdev->dev.of_node;
+ int irq, ret;
u8 regval;
+ struct iio_dev *iio_dev = NULL;
- if (!pdata) {
- dev_err(&pdev->dev, "platform_data not available\n");
+ if (!pdata && !np) {
+ dev_err(&pdev->dev, "neither platform data nor Device Tree node available\n");
return -EINVAL;
}
- madc = kzalloc(sizeof(*madc), GFP_KERNEL);
- if (!madc)
+
+ iio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*madc));
+ if (!iio_dev) {
+ dev_err(&pdev->dev, "failed allocating iio device\n");
return -ENOMEM;
+ }
+ madc = iio_priv(iio_dev);
madc->dev = &pdev->dev;
+ iio_dev->name = dev_name(&pdev->dev);
+ iio_dev->dev.parent = &pdev->dev;
+ iio_dev->dev.of_node = pdev->dev.of_node;
+ iio_dev->info = &twl4030_madc_iio_info;
+ iio_dev->modes = INDIO_DIRECT_MODE;
+ iio_dev->channels = twl4030_madc_iio_channels;
+ iio_dev->num_channels = ARRAY_SIZE(twl4030_madc_iio_channels);
+
/*
* Phoenix provides 2 interrupt lines. The first one is connected to
* the OMAP. The other one can be connected to the other processor such
* as modem. Hence two separate ISR and IMR registers.
*/
- madc->imr = (pdata->irq_line == 1) ?
- TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2;
- madc->isr = (pdata->irq_line == 1) ?
- TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2;
+ if (pdata)
+ madc->use_second_irq = (pdata->irq_line != 1);
+ else
+ madc->use_second_irq = of_property_read_bool(np,
+ "ti,system-uses-second-madc-irq");
+
+ madc->imr = madc->use_second_irq ? TWL4030_MADC_IMR2 :
+ TWL4030_MADC_IMR1;
+ madc->isr = madc->use_second_irq ? TWL4030_MADC_ISR2 :
+ TWL4030_MADC_ISR1;
+
ret = twl4030_madc_set_power(madc, 1);
if (ret < 0)
- goto err_power;
+ return ret;
ret = twl4030_madc_set_current_generator(madc, 0, 1);
if (ret < 0)
goto err_current_generator;
@@ -768,46 +828,63 @@ static int twl4030_madc_probe(struct platform_device *pdev)
}
}
- platform_set_drvdata(pdev, madc);
+ platform_set_drvdata(pdev, iio_dev);
mutex_init(&madc->lock);
- ret = request_threaded_irq(platform_get_irq(pdev, 0), NULL,
+
+ irq = platform_get_irq(pdev, 0);
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
twl4030_madc_threaded_irq_handler,
IRQF_TRIGGER_RISING, "twl4030_madc", madc);
if (ret) {
- dev_dbg(&pdev->dev, "could not request irq\n");
+ dev_err(&pdev->dev, "could not request irq\n");
goto err_i2c;
}
twl4030_madc = madc;
+
+ ret = iio_device_register(iio_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "could not register iio device\n");
+ goto err_i2c;
+ }
+
return 0;
+
err_i2c:
twl4030_madc_set_current_generator(madc, 0, 0);
err_current_generator:
twl4030_madc_set_power(madc, 0);
-err_power:
- kfree(madc);
-
return ret;
}
static int twl4030_madc_remove(struct platform_device *pdev)
{
- struct twl4030_madc_data *madc = platform_get_drvdata(pdev);
+ struct iio_dev *iio_dev = platform_get_drvdata(pdev);
+ struct twl4030_madc_data *madc = iio_priv(iio_dev);
+
+ iio_device_unregister(iio_dev);
- free_irq(platform_get_irq(pdev, 0), madc);
twl4030_madc_set_current_generator(madc, 0, 0);
twl4030_madc_set_power(madc, 0);
- kfree(madc);
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id twl_madc_of_match[] = {
+ { .compatible = "ti,twl4030-madc", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, twl_madc_of_match);
+#endif
+
static struct platform_driver twl4030_madc_driver = {
.probe = twl4030_madc_probe,
.remove = twl4030_madc_remove,
.driver = {
.name = "twl4030_madc",
.owner = THIS_MODULE,
- },
+ .of_match_table = of_match_ptr(twl_madc_of_match),
+ },
};
module_platform_driver(twl4030_madc_driver);
diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index 7dca1e64097..841717a2842 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -571,7 +571,7 @@ static int pm800_probe(struct i2c_client *client,
ret = pm800_pages_init(chip);
if (ret) {
dev_err(&client->dev, "pm800_pages_init failed!\n");
- goto err_page_init;
+ goto err_device_init;
}
ret = device_800_init(chip, pdata);
@@ -587,7 +587,6 @@ static int pm800_probe(struct i2c_client *client,
err_device_init:
pm800_pages_exit(chip);
-err_page_init:
err_subchip_alloc:
pm80x_deinit();
out_init:
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index c9b1f642294..bcfc9e85b4a 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -1179,12 +1179,18 @@ static int pm860x_probe(struct i2c_client *client,
chip->companion_addr = pdata->companion_addr;
chip->companion = i2c_new_dummy(chip->client->adapter,
chip->companion_addr);
+ if (!chip->companion) {
+ dev_err(&client->dev,
+ "Failed to allocate I2C companion device\n");
+ return -ENODEV;
+ }
chip->regmap_companion = regmap_init_i2c(chip->companion,
&pm860x_regmap_config);
if (IS_ERR(chip->regmap_companion)) {
ret = PTR_ERR(chip->regmap_companion);
dev_err(&chip->companion->dev,
"Failed to allocate register map: %d\n", ret);
+ i2c_unregister_device(chip->companion);
return ret;
}
i2c_set_clientdata(chip->companion, chip);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 49bb445d846..33834120d05 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -59,6 +59,14 @@ config MFD_AAT2870_CORE
additional drivers must be enabled in order to use the
functionality of the device.
+config MFD_BCM590XX
+ tristate "Broadcom BCM590xx PMUs"
+ select MFD_CORE
+ select REGMAP_I2C
+ depends on I2C
+ help
+ Support for the BCM590xx PMUs from Broadcom
+
config MFD_CROS_EC
tristate "ChromeOS Embedded Controller"
select MFD_CORE
@@ -100,7 +108,7 @@ config PMIC_DA903X
bool "Dialog Semiconductor DA9030/DA9034 PMIC Support"
depends on I2C=y
help
- Say yes here to support for Dialog Semiconductor DA9030 (a.k.a
+ Say yes here to add support for Dialog Semiconductor DA9030 (a.k.a
ARAVA) and DA9034 (a.k.a MICCO), these are Power Management IC
usually found on PXA processors-based platforms. This includes
the I2C driver and the core APIs _only_, you have to select
@@ -270,13 +278,18 @@ config MFD_KEMPLD
device may provide functions like watchdog, GPIO, UART and I2C bus.
The following modules are supported:
+ * COMe-bHL6
* COMe-bIP#
* COMe-bPC2 (ETXexpress-PC)
* COMe-bSC# (ETXexpress-SC T#)
+ * COMe-cBT6
* COMe-cCT6
* COMe-cDC2 (microETXexpress-DC)
+ * COMe-cHL6
* COMe-cPC2 (microETXexpress-PC)
+ * COMe-mBT10
* COMe-mCT10
+ * COMe-mTT10 (nanoETXexpress-TT)
* ETX-OH
This driver can also be built as a module. If so, the module
@@ -322,9 +335,10 @@ config MFD_MAX14577
depends on I2C=y
select MFD_CORE
select REGMAP_I2C
+ select REGMAP_IRQ
select IRQ_DOMAIN
help
- Say yes here to support for Maxim Semiconductor MAX14577.
+ Say yes here to add support for Maxim Semiconductor MAX14577.
This is a Micro-USB IC with Charger controls on chip.
This driver provides common support for accessing the device;
additional drivers must be enabled in order to use the functionality
@@ -337,7 +351,7 @@ config MFD_MAX77686
select REGMAP_I2C
select IRQ_DOMAIN
help
- Say yes here to support for Maxim Semiconductor MAX77686.
+ Say yes here to add support for Maxim Semiconductor MAX77686.
This is a Power Management IC with RTC on chip.
This driver provides common support for accessing the device;
additional drivers must be enabled in order to use the functionality
@@ -349,7 +363,7 @@ config MFD_MAX77693
select MFD_CORE
select REGMAP_I2C
help
- Say yes here to support for Maxim Semiconductor MAX77693.
+ Say yes here to add support for Maxim Semiconductor MAX77693.
This is a companion Power Management IC with Flash, Haptic, Charger,
and MUIC(Micro USB Interface Controller) controls on chip.
This driver provides common support for accessing the device;
@@ -363,7 +377,7 @@ config MFD_MAX8907
select REGMAP_I2C
select REGMAP_IRQ
help
- Say yes here to support for Maxim Semiconductor MAX8907. This is
+ Say yes here to add support for Maxim Semiconductor MAX8907. This is
a Power Management IC. This driver provides common support for
accessing the device; additional drivers must be enabled in order
to use the functionality of the device.
@@ -373,7 +387,7 @@ config MFD_MAX8925
depends on I2C=y
select MFD_CORE
help
- Say yes here to support for Maxim Semiconductor MAX8925. This is
+ Say yes here to add support for Maxim Semiconductor MAX8925. This is
a Power Management IC. This driver provides common support for
accessing the device, additional drivers must be enabled in order
to use the functionality of the device.
@@ -384,7 +398,7 @@ config MFD_MAX8997
select MFD_CORE
select IRQ_DOMAIN
help
- Say yes here to support for Maxim Semiconductor MAX8997/8966.
+ Say yes here to add support for Maxim Semiconductor MAX8997/8966.
This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic,
MUIC controls on chip.
This driver provides common support for accessing the device;
@@ -397,7 +411,7 @@ config MFD_MAX8998
select MFD_CORE
select IRQ_DOMAIN
help
- Say yes here to support for Maxim Semiconductor MAX8998 and
+ Say yes here to add support for Maxim Semiconductor MAX8998 and
National Semiconductor LP3974. This is a Power Management IC.
This driver provides common support for accessing the device,
additional drivers must be enabled in order to use the functionality
@@ -473,10 +487,11 @@ config MFD_PM8XXX
config MFD_PM8921_CORE
tristate "Qualcomm PM8921 PMIC chip"
- depends on (ARCH_MSM || HEXAGON)
- depends on BROKEN
+ depends on (ARM || HEXAGON)
+ select IRQ_DOMAIN
select MFD_CORE
select MFD_PM8XXX
+ select REGMAP
help
If you say yes to this option, support will be included for the
built-in PM8921 PMIC chip.
@@ -487,16 +502,6 @@ config MFD_PM8921_CORE
Say M here if you want to include support for PM8921 chip as a module.
This will build a module called "pm8921-core".
-config MFD_PM8XXX_IRQ
- bool "Qualcomm PM8xxx IRQ features"
- depends on MFD_PM8XXX
- default y if MFD_PM8XXX
- help
- This is the IRQ driver for Qualcomm PM 8xxx PMIC chips.
-
- This is required to use certain other PM 8xxx features, such as GPIO
- and MPP.
-
config MFD_RDC321X
tristate "RDC R-321x southbridge"
select MFD_CORE
@@ -516,6 +521,16 @@ config MFD_RTSX_PCI
types of memory cards, such as Memory Stick, Memory Stick Pro,
Secure Digital and MultiMediaCard.
+config MFD_RTSX_USB
+ tristate "Realtek USB card reader"
+ depends on USB
+ select MFD_CORE
+ help
+ Select this option to get support for Realtek USB 2.0 card readers
+ including RTS5129, RTS5139, RTS5179 and RTS5170.
+ Realtek card reader supports access to many types of memory cards,
+ such as Memory Stick Pro, Secure Digital and MultiMediaCard.
+
config MFD_RC5T583
bool "Ricoh RC5T583 Power Management system device"
depends on I2C=y
@@ -774,17 +789,6 @@ config MFD_PALMAS
If you say yes here you get support for the Palmas
series of PMIC chips from Texas Instruments.
-config MFD_TI_SSP
- tristate "TI Sequencer Serial Port support"
- depends on ARCH_DAVINCI_TNETV107X
- select MFD_CORE
- ---help---
- Say Y here if you want support for the Sequencer Serial Port
- in a Texas Instruments TNETV107X SoC.
-
- To compile this driver as a module, choose M here: the
- module will be called ti-ssp.
-
config TPS6105X
tristate "TI TPS61050/61052 Boost Converters"
depends on I2C
@@ -853,6 +857,22 @@ config MFD_TPS65217
This driver can also be built as a module. If so, the module
will be called tps65217.
+config MFD_TPS65218
+ tristate "TI TPS65218 Power Management chips"
+ depends on I2C
+ select MFD_CORE
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ help
+ If you say yes here you get support for the TPS65218 series of
+ Power Management chips.
+ These include voltage regulators, gpio and other features
+ that are often used in portable devices. Only regulator
+ component is currently supported.
+
+ This driver can also be built as a module. If so, the module
+ will be called tps65218.
+
config MFD_TPS6586X
bool "TI TPS6586x Power Management chips"
depends on I2C=y
@@ -935,16 +955,6 @@ config TWL4030_CORE
high speed USB OTG transceiver, an audio codec (on most
versions) and many other features.
-config TWL4030_MADC
- tristate "TI TWL4030 MADC"
- depends on TWL4030_CORE
- help
- This driver provides support for triton TWL4030-MADC. The
- driver supports both RT and SW conversion methods.
-
- This driver can be built as a module. If so it will be
- named twl4030-madc
-
config TWL4030_POWER
bool "TI TWL4030 power resources"
depends on TWL4030_CORE && ARM
@@ -1193,9 +1203,6 @@ config MFD_STW481X
in various ST Microelectronics and ST-Ericsson embedded
Nomadik series.
-endmenu
-endif
-
menu "Multimedia Capabilities Port drivers"
depends on ARCH_SA1100
@@ -1226,3 +1233,6 @@ config VEXPRESS_CONFIG
help
Platform configuration infrastructure for the ARM Ltd.
Versatile Express.
+
+endmenu
+endif
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 5aea5ef0a62..2851275e265 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -8,12 +8,14 @@ obj-$(CONFIG_MFD_88PM800) += 88pm800.o 88pm80x.o
obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o
obj-$(CONFIG_MFD_SM501) += sm501.o
obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
+obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
obj-$(CONFIG_MFD_CROS_EC) += cros_ec.o
obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o
+obj-$(CONFIG_MFD_RTSX_USB) += rtsx_usb.o
obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
@@ -21,7 +23,6 @@ obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o
obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o
obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
-obj-$(CONFIG_MFD_TI_SSP) += ti-ssp.o
obj-$(CONFIG_MFD_TI_AM335X_TSCADC) += ti_am335x_tscadc.o
obj-$(CONFIG_MFD_STA2X11) += sta2x11-mfd.o
@@ -62,6 +63,7 @@ obj-$(CONFIG_TPS6105X) += tps6105x.o
obj-$(CONFIG_TPS65010) += tps65010.o
obj-$(CONFIG_TPS6507X) += tps6507x.o
obj-$(CONFIG_MFD_TPS65217) += tps65217.o
+obj-$(CONFIG_MFD_TPS65218) += tps65218.o
obj-$(CONFIG_MFD_TPS65910) += tps65910.o
tps65912-objs := tps65912-core.o tps65912-irq.o
obj-$(CONFIG_MFD_TPS65912) += tps65912.o
@@ -71,7 +73,6 @@ obj-$(CONFIG_MFD_TPS80031) += tps80031.o
obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o
-obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o
obj-$(CONFIG_MFD_TWL4030_AUDIO) += twl4030-audio.o
obj-$(CONFIG_TWL6040_CORE) += twl6040.o
@@ -150,7 +151,6 @@ obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o
obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o
obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o omap-usb-tll.o
obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o ssbi.o
-obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o
obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
obj-$(CONFIG_MFD_TPS65090) += tps65090.o
obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c
index 62501553d63..f495b8b57dd 100644
--- a/drivers/mfd/adp5520.c
+++ b/drivers/mfd/adp5520.c
@@ -20,7 +20,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
diff --git a/drivers/mfd/as3722.c b/drivers/mfd/as3722.c
index c71ff0af154..39fa554f13b 100644
--- a/drivers/mfd/as3722.c
+++ b/drivers/mfd/as3722.c
@@ -277,6 +277,7 @@ static const struct regmap_range as3722_readable_ranges[] = {
regmap_reg_range(AS3722_ADC0_CONTROL_REG, AS3722_ADC_CONFIGURATION_REG),
regmap_reg_range(AS3722_ASIC_ID1_REG, AS3722_ASIC_ID2_REG),
regmap_reg_range(AS3722_LOCK_REG, AS3722_LOCK_REG),
+ regmap_reg_range(AS3722_FUSE7_REG, AS3722_FUSE7_REG),
};
static const struct regmap_access_table as3722_readable_table = {
diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c
new file mode 100644
index 00000000000..e9a33c79431
--- /dev/null
+++ b/drivers/mfd/bcm590xx.c
@@ -0,0 +1,93 @@
+/*
+ * Broadcom BCM590xx PMU
+ *
+ * Copyright 2014 Linaro Limited
+ * Author: Matt Porter <mporter@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/mfd/bcm590xx.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+static const struct mfd_cell bcm590xx_devs[] = {
+ {
+ .name = "bcm590xx-vregs",
+ },
+};
+
+static const struct regmap_config bcm590xx_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = BCM590XX_MAX_REGISTER,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int bcm590xx_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct bcm590xx *bcm590xx;
+ int ret;
+
+ bcm590xx = devm_kzalloc(&i2c->dev, sizeof(*bcm590xx), GFP_KERNEL);
+ if (!bcm590xx)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, bcm590xx);
+ bcm590xx->dev = &i2c->dev;
+ bcm590xx->i2c_client = i2c;
+
+ bcm590xx->regmap = devm_regmap_init_i2c(i2c, &bcm590xx_regmap_config);
+ if (IS_ERR(bcm590xx->regmap)) {
+ ret = PTR_ERR(bcm590xx->regmap);
+ dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = mfd_add_devices(&i2c->dev, -1, bcm590xx_devs,
+ ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL);
+ if (ret < 0)
+ dev_err(&i2c->dev, "failed to add sub-devices: %d\n", ret);
+
+ return ret;
+}
+
+static const struct of_device_id bcm590xx_of_match[] = {
+ { .compatible = "brcm,bcm59056" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, bcm590xx_of_match);
+
+static const struct i2c_device_id bcm590xx_i2c_id[] = {
+ { "bcm59056" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, bcm590xx_i2c_id);
+
+static struct i2c_driver bcm590xx_i2c_driver = {
+ .driver = {
+ .name = "bcm590xx",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(bcm590xx_of_match),
+ },
+ .probe = bcm590xx_i2c_probe,
+ .id_table = bcm590xx_i2c_id,
+};
+module_i2c_driver(bcm590xx_i2c_driver);
+
+MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
+MODULE_DESCRIPTION("BCM590xx multi-function driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:bcm590xx");
diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c
index 17c13012686..be91cb5d6e7 100644
--- a/drivers/mfd/cs5535-mfd.c
+++ b/drivers/mfd/cs5535-mfd.c
@@ -23,7 +23,6 @@
*/
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/pci.h>
diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c
index 25838f10b35..e8af816d73a 100644
--- a/drivers/mfd/da9052-core.c
+++ b/drivers/mfd/da9052-core.c
@@ -279,6 +279,9 @@ static bool da9052_reg_volatile(struct device *dev, unsigned int reg)
case DA9052_EVENT_B_REG:
case DA9052_EVENT_C_REG:
case DA9052_EVENT_D_REG:
+ case DA9052_CONTROL_B_REG:
+ case DA9052_CONTROL_D_REG:
+ case DA9052_SUPPLY_REG:
case DA9052_FAULTLOG_REG:
case DA9052_CHG_TIME_REG:
case DA9052_ADC_RES_L_REG:
diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c
index c319c4ef5d4..6da8ec8ff80 100644
--- a/drivers/mfd/da9052-i2c.c
+++ b/drivers/mfd/da9052-i2c.c
@@ -75,6 +75,7 @@ static int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg)
DA9052_PARK_REGISTER,
&val);
break;
+ case DA9053_BC:
default:
/*
* For other chips parking of I2C register
@@ -114,6 +115,7 @@ static const struct i2c_device_id da9052_i2c_id[] = {
{"da9053-aa", DA9053_AA},
{"da9053-ba", DA9053_BA},
{"da9053-bb", DA9053_BB},
+ {"da9053-bc", DA9053_BC},
{}
};
@@ -121,8 +123,9 @@ static const struct i2c_device_id da9052_i2c_id[] = {
static const struct of_device_id dialog_dt_ids[] = {
{ .compatible = "dlg,da9052", .data = &da9052_i2c_id[0] },
{ .compatible = "dlg,da9053-aa", .data = &da9052_i2c_id[1] },
- { .compatible = "dlg,da9053-ab", .data = &da9052_i2c_id[2] },
+ { .compatible = "dlg,da9053-ba", .data = &da9052_i2c_id[2] },
{ .compatible = "dlg,da9053-bb", .data = &da9052_i2c_id[3] },
+ { .compatible = "dlg,da9053-bc", .data = &da9052_i2c_id[4] },
{ /* sentinel */ }
};
#endif
diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c
index 0680bcbc53d..17666b40b70 100644
--- a/drivers/mfd/da9052-spi.c
+++ b/drivers/mfd/da9052-spi.c
@@ -71,6 +71,7 @@ static struct spi_device_id da9052_spi_id[] = {
{"da9053-aa", DA9053_AA},
{"da9053-ba", DA9053_BA},
{"da9053-bb", DA9053_BB},
+ {"da9053-bc", DA9053_BC},
{}
};
diff --git a/drivers/mfd/da9055-i2c.c b/drivers/mfd/da9055-i2c.c
index 8103e436213..d4d4c165eb9 100644
--- a/drivers/mfd/da9055-i2c.c
+++ b/drivers/mfd/da9055-i2c.c
@@ -15,6 +15,8 @@
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/mfd/da9055/core.h>
@@ -66,6 +68,11 @@ static struct i2c_device_id da9055_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, da9055_i2c_id);
+static const struct of_device_id da9055_of_match[] = {
+ { .compatible = "dlg,da9055-pmic", },
+ { }
+};
+
static struct i2c_driver da9055_i2c_driver = {
.probe = da9055_i2c_probe,
.remove = da9055_i2c_remove,
@@ -73,6 +80,7 @@ static struct i2c_driver da9055_i2c_driver = {
.driver = {
.name = "da9055-pmic",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(da9055_of_match),
},
};
diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c
index 26937cd0107..e70ae315abc 100644
--- a/drivers/mfd/da9063-core.c
+++ b/drivers/mfd/da9063-core.c
@@ -110,7 +110,7 @@ static const struct mfd_cell da9063_devs[] = {
int da9063_device_init(struct da9063 *da9063, unsigned int irq)
{
struct da9063_pdata *pdata = da9063->dev->platform_data;
- int model, revision;
+ int model, variant_id, variant_code;
int ret;
if (pdata) {
@@ -141,23 +141,26 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
return -ENODEV;
}
- ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_VARIANT, &revision);
+ ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_VARIANT, &variant_id);
if (ret < 0) {
- dev_err(da9063->dev, "Cannot read chip revision id.\n");
+ dev_err(da9063->dev, "Cannot read chip variant id.\n");
return -EIO;
}
- revision >>= DA9063_CHIP_VARIANT_SHIFT;
- if (revision != 3) {
- dev_err(da9063->dev, "Unknown chip revision: %d\n", revision);
+
+ variant_code = variant_id >> DA9063_CHIP_VARIANT_SHIFT;
+
+ dev_info(da9063->dev,
+ "Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n",
+ model, variant_id);
+
+ if (variant_code != PMIC_DA9063_BB) {
+ dev_err(da9063->dev, "Unknown chip variant code: 0x%02X\n",
+ variant_code);
return -ENODEV;
}
da9063->model = model;
- da9063->revision = revision;
-
- dev_info(da9063->dev,
- "Device detected (model-ID: 0x%02X rev-ID: 0x%02X)\n",
- model, revision);
+ da9063->variant_code = variant_code;
ret = da9063_irq_init(da9063);
if (ret) {
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c
index 81b7d88af31..433f823037d 100644
--- a/drivers/mfd/janz-cmodio.c
+++ b/drivers/mfd/janz-cmodio.c
@@ -13,7 +13,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/init.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c
index d3e23278d29..07692604e11 100644
--- a/drivers/mfd/kempld-core.c
+++ b/drivers/mfd/kempld-core.c
@@ -322,9 +322,12 @@ static int kempld_detect_device(struct kempld_device_data *pld)
return -ENODEV;
}
- /* Release hardware mutex if aquired */
- if (!(index_reg & KEMPLD_MUTEX_KEY))
+ /* Release hardware mutex if acquired */
+ if (!(index_reg & KEMPLD_MUTEX_KEY)) {
iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
+ /* PXT and COMe-cPC2 boards may require a second release */
+ iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
+ }
mutex_unlock(&pld->lock);
@@ -438,6 +441,14 @@ static struct dmi_system_id __initdata kempld_dmi_table[] = {
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
+ .ident = "CHL6",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+ DMI_MATCH(DMI_BOARD_NAME, "COMe-cHL6"),
+ },
+ .driver_data = (void *)&kempld_platform_data_generic,
+ .callback = kempld_create_platform_device,
+ }, {
.ident = "CHR2",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
@@ -510,6 +521,14 @@ static struct dmi_system_id __initdata kempld_dmi_table[] = {
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
+ .ident = "CVV6",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+ DMI_MATCH(DMI_BOARD_NAME, "COMe-cBT"),
+ },
+ .driver_data = (void *)&kempld_platform_data_generic,
+ .callback = kempld_create_platform_device,
+ }, {
.ident = "FRI2",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
@@ -533,6 +552,14 @@ static struct dmi_system_id __initdata kempld_dmi_table[] = {
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
+ .ident = "MVV1",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+ DMI_MATCH(DMI_BOARD_NAME, "COMe-mBT"),
+ },
+ .driver_data = (void *)&kempld_platform_data_generic,
+ .callback = kempld_create_platform_device,
+ }, {
.ident = "NTC1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index be93fa261de..3f10ea3f45d 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -58,7 +58,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
@@ -72,9 +71,11 @@
#define ACPIBASE_GPE_END 0x2f
#define ACPIBASE_SMI_OFF 0x30
#define ACPIBASE_SMI_END 0x33
+#define ACPIBASE_PMC_OFF 0x08
+#define ACPIBASE_PMC_END 0x0c
#define ACPIBASE_TCO_OFF 0x60
#define ACPIBASE_TCO_END 0x7f
-#define ACPICTRL 0x44
+#define ACPICTRL_PMCBASE 0x44
#define ACPIBASE_GCS_OFF 0x3410
#define ACPIBASE_GCS_END 0x3414
@@ -90,16 +91,17 @@
#define wdt_mem_res(i) wdt_res(ICH_RES_MEM_OFF, i)
#define wdt_res(b, i) (&wdt_ich_res[(b) + (i)])
-struct lpc_ich_cfg {
- int base;
- int ctrl;
- int save;
-};
-
struct lpc_ich_priv {
int chipset;
- struct lpc_ich_cfg acpi;
- struct lpc_ich_cfg gpio;
+
+ int abase; /* ACPI base */
+ int actrl_pbase; /* ACPI control or PMC base */
+ int gbase; /* GPIO base */
+ int gctrl; /* GPIO control */
+
+ int abase_save; /* Cached ACPI base value */
+ int actrl_pbase_save; /* Cached ACPI control or PMC base value */
+ int gctrl_save; /* Cached GPIO control value */
};
static struct resource wdt_ich_res[] = {
@@ -111,7 +113,7 @@ static struct resource wdt_ich_res[] = {
{
.flags = IORESOURCE_IO,
},
- /* GCS */
+ /* GCS or PMC */
{
.flags = IORESOURCE_MEM,
},
@@ -211,6 +213,7 @@ enum lpc_chipsets {
LPC_LPT_LP, /* Lynx Point-LP */
LPC_WBG, /* Wellsburg */
LPC_AVN, /* Avoton SoC */
+ LPC_BAYTRAIL, /* Bay Trail SoC */
LPC_COLETO, /* Coleto Creek */
LPC_WPT_LP, /* Wildcat Point-LP */
};
@@ -303,6 +306,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
[LPC_NM10] = {
.name = "NM10",
.iTCO_version = 2,
+ .gpio_version = ICH_V7_GPIO,
},
[LPC_ICH8] = {
.name = "ICH8 or ICH8R",
@@ -499,7 +503,12 @@ static struct lpc_ich_info lpc_chipset_info[] = {
},
[LPC_AVN] = {
.name = "Avoton SoC",
- .iTCO_version = 1,
+ .iTCO_version = 3,
+ .gpio_version = AVOTON_GPIO,
+ },
+ [LPC_BAYTRAIL] = {
+ .name = "Bay Trail SoC",
+ .iTCO_version = 3,
},
[LPC_COLETO] = {
.name = "Coleto Creek",
@@ -726,6 +735,7 @@ static const struct pci_device_id lpc_ich_ids[] = {
{ PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN},
{ PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN},
{ PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN},
+ { PCI_VDEVICE(INTEL, 0x0f1c), LPC_BAYTRAIL},
{ PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO},
{ PCI_VDEVICE(INTEL, 0x9cc1), LPC_WPT_LP},
{ PCI_VDEVICE(INTEL, 0x9cc2), LPC_WPT_LP},
@@ -742,14 +752,20 @@ static void lpc_ich_restore_config_space(struct pci_dev *dev)
{
struct lpc_ich_priv *priv = pci_get_drvdata(dev);
- if (priv->acpi.save >= 0) {
- pci_write_config_byte(dev, priv->acpi.ctrl, priv->acpi.save);
- priv->acpi.save = -1;
+ if (priv->abase_save >= 0) {
+ pci_write_config_byte(dev, priv->abase, priv->abase_save);
+ priv->abase_save = -1;
+ }
+
+ if (priv->actrl_pbase_save >= 0) {
+ pci_write_config_byte(dev, priv->actrl_pbase,
+ priv->actrl_pbase_save);
+ priv->actrl_pbase_save = -1;
}
- if (priv->gpio.save >= 0) {
- pci_write_config_byte(dev, priv->gpio.ctrl, priv->gpio.save);
- priv->gpio.save = -1;
+ if (priv->gctrl_save >= 0) {
+ pci_write_config_byte(dev, priv->gctrl, priv->gctrl_save);
+ priv->gctrl_save = -1;
}
}
@@ -758,9 +774,26 @@ static void lpc_ich_enable_acpi_space(struct pci_dev *dev)
struct lpc_ich_priv *priv = pci_get_drvdata(dev);
u8 reg_save;
- pci_read_config_byte(dev, priv->acpi.ctrl, &reg_save);
- pci_write_config_byte(dev, priv->acpi.ctrl, reg_save | 0x10);
- priv->acpi.save = reg_save;
+ switch (lpc_chipset_info[priv->chipset].iTCO_version) {
+ case 3:
+ /*
+ * Some chipsets (eg Avoton) enable the ACPI space in the
+ * ACPI BASE register.
+ */
+ pci_read_config_byte(dev, priv->abase, &reg_save);
+ pci_write_config_byte(dev, priv->abase, reg_save | 0x2);
+ priv->abase_save = reg_save;
+ break;
+ default:
+ /*
+ * Most chipsets enable the ACPI space in the ACPI control
+ * register.
+ */
+ pci_read_config_byte(dev, priv->actrl_pbase, &reg_save);
+ pci_write_config_byte(dev, priv->actrl_pbase, reg_save | 0x80);
+ priv->actrl_pbase_save = reg_save;
+ break;
+ }
}
static void lpc_ich_enable_gpio_space(struct pci_dev *dev)
@@ -768,9 +801,20 @@ static void lpc_ich_enable_gpio_space(struct pci_dev *dev)
struct lpc_ich_priv *priv = pci_get_drvdata(dev);
u8 reg_save;
- pci_read_config_byte(dev, priv->gpio.ctrl, &reg_save);
- pci_write_config_byte(dev, priv->gpio.ctrl, reg_save | 0x10);
- priv->gpio.save = reg_save;
+ pci_read_config_byte(dev, priv->gctrl, &reg_save);
+ pci_write_config_byte(dev, priv->gctrl, reg_save | 0x10);
+ priv->gctrl_save = reg_save;
+}
+
+static void lpc_ich_enable_pmc_space(struct pci_dev *dev)
+{
+ struct lpc_ich_priv *priv = pci_get_drvdata(dev);
+ u8 reg_save;
+
+ pci_read_config_byte(dev, priv->actrl_pbase, &reg_save);
+ pci_write_config_byte(dev, priv->actrl_pbase, reg_save | 0x2);
+
+ priv->actrl_pbase_save = reg_save;
}
static void lpc_ich_finalize_cell(struct pci_dev *dev, struct mfd_cell *cell)
@@ -815,7 +859,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev)
struct resource *res;
/* Setup power management base register */
- pci_read_config_dword(dev, priv->acpi.base, &base_addr_cfg);
+ pci_read_config_dword(dev, priv->abase, &base_addr_cfg);
base_addr = base_addr_cfg & 0x0000ff80;
if (!base_addr) {
dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n");
@@ -841,7 +885,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev)
gpe0_done:
/* Setup GPIO base register */
- pci_read_config_dword(dev, priv->gpio.base, &base_addr_cfg);
+ pci_read_config_dword(dev, priv->gbase, &base_addr_cfg);
base_addr = base_addr_cfg & 0x0000ff80;
if (!base_addr) {
dev_notice(&dev->dev, "I/O space for GPIO uninitialized\n");
@@ -891,7 +935,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
struct resource *res;
/* Setup power management base register */
- pci_read_config_dword(dev, priv->acpi.base, &base_addr_cfg);
+ pci_read_config_dword(dev, priv->abase, &base_addr_cfg);
base_addr = base_addr_cfg & 0x0000ff80;
if (!base_addr) {
dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n");
@@ -910,14 +954,20 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
lpc_ich_enable_acpi_space(dev);
/*
+ * iTCO v2:
* Get the Memory-Mapped GCS register. To get access to it
* we have to read RCBA from PCI Config space 0xf0 and use
* it as base. GCS = RCBA + ICH6_GCS(0x3410).
+ *
+ * iTCO v3:
+ * Get the Power Management Configuration register. To get access
+ * to it we have to read the PMC BASE from config space and address
+ * the register at offset 0x8.
*/
if (lpc_chipset_info[priv->chipset].iTCO_version == 1) {
/* Don't register iomem for TCO ver 1 */
lpc_ich_cells[LPC_WDT].num_resources--;
- } else {
+ } else if (lpc_chipset_info[priv->chipset].iTCO_version == 2) {
pci_read_config_dword(dev, RCBABASE, &base_addr_cfg);
base_addr = base_addr_cfg & 0xffffc000;
if (!(base_addr_cfg & 1)) {
@@ -926,9 +976,17 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
ret = -ENODEV;
goto wdt_done;
}
- res = wdt_mem_res(ICH_RES_MEM_GCS);
+ res = wdt_mem_res(ICH_RES_MEM_GCS_PMC);
res->start = base_addr + ACPIBASE_GCS_OFF;
res->end = base_addr + ACPIBASE_GCS_END;
+ } else if (lpc_chipset_info[priv->chipset].iTCO_version == 3) {
+ lpc_ich_enable_pmc_space(dev);
+ pci_read_config_dword(dev, ACPICTRL_PMCBASE, &base_addr_cfg);
+ base_addr = base_addr_cfg & 0xfffffe00;
+
+ res = wdt_mem_res(ICH_RES_MEM_GCS_PMC);
+ res->start = base_addr + ACPIBASE_PMC_OFF;
+ res->end = base_addr + ACPIBASE_PMC_END;
}
lpc_ich_finalize_cell(dev, &lpc_ich_cells[LPC_WDT]);
@@ -952,28 +1010,35 @@ static int lpc_ich_probe(struct pci_dev *dev,
return -ENOMEM;
priv->chipset = id->driver_data;
- priv->acpi.save = -1;
- priv->acpi.base = ACPIBASE;
- priv->acpi.ctrl = ACPICTRL;
- priv->gpio.save = -1;
+ priv->actrl_pbase_save = -1;
+ priv->abase_save = -1;
+
+ priv->abase = ACPIBASE;
+ priv->actrl_pbase = ACPICTRL_PMCBASE;
+
+ priv->gctrl_save = -1;
if (priv->chipset <= LPC_ICH5) {
- priv->gpio.base = GPIOBASE_ICH0;
- priv->gpio.ctrl = GPIOCTRL_ICH0;
+ priv->gbase = GPIOBASE_ICH0;
+ priv->gctrl = GPIOCTRL_ICH0;
} else {
- priv->gpio.base = GPIOBASE_ICH6;
- priv->gpio.ctrl = GPIOCTRL_ICH6;
+ priv->gbase = GPIOBASE_ICH6;
+ priv->gctrl = GPIOCTRL_ICH6;
}
pci_set_drvdata(dev, priv);
- ret = lpc_ich_init_wdt(dev);
- if (!ret)
- cell_added = true;
+ if (lpc_chipset_info[priv->chipset].iTCO_version) {
+ ret = lpc_ich_init_wdt(dev);
+ if (!ret)
+ cell_added = true;
+ }
- ret = lpc_ich_init_gpio(dev);
- if (!ret)
- cell_added = true;
+ if (lpc_chipset_info[priv->chipset].gpio_version) {
+ ret = lpc_ich_init_gpio(dev);
+ if (!ret)
+ cell_added = true;
+ }
/*
* We only care if at least one or none of the cells registered
diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c
index 3bb05c03c68..4ee755034f3 100644
--- a/drivers/mfd/lpc_sch.c
+++ b/drivers/mfd/lpc_sch.c
@@ -23,7 +23,6 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c
index 71aa14a6bfb..5f13cefe8de 100644
--- a/drivers/mfd/max14577.c
+++ b/drivers/mfd/max14577.c
@@ -18,6 +18,7 @@
* This driver is based on max8997.c
*/
+#include <linux/err.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
@@ -25,7 +26,10 @@
#include <linux/mfd/max14577-private.h>
static struct mfd_cell max14577_devs[] = {
- { .name = "max14577-muic", },
+ {
+ .name = "max14577-muic",
+ .of_compatible = "maxim,max14577-muic",
+ },
{
.name = "max14577-regulator",
.of_compatible = "maxim,max14577-regulator",
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index f53d5823a3f..e5fce765acc 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -121,6 +121,10 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
dev_info(max77686->dev, "device found\n");
max77686->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
+ if (!max77686->rtc) {
+ dev_err(max77686->dev, "Failed to allocate I2C device for RTC\n");
+ return -ENODEV;
+ }
i2c_set_clientdata(max77686->rtc, max77686);
max77686_irq_init(max77686);
diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
index e0859987ab6..c5535f01846 100644
--- a/drivers/mfd/max77693.c
+++ b/drivers/mfd/max77693.c
@@ -148,9 +148,18 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
dev_info(max77693->dev, "device ID: 0x%x\n", reg_data);
max77693->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC);
+ if (!max77693->muic) {
+ dev_err(max77693->dev, "Failed to allocate I2C device for MUIC\n");
+ return -ENODEV;
+ }
i2c_set_clientdata(max77693->muic, max77693);
max77693->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC);
+ if (!max77693->haptic) {
+ dev_err(max77693->dev, "Failed to allocate I2C device for Haptic\n");
+ ret = -ENODEV;
+ goto err_i2c_haptic;
+ }
i2c_set_clientdata(max77693->haptic, max77693);
/*
@@ -184,8 +193,9 @@ err_mfd:
max77693_irq_exit(max77693);
err_irq:
err_regmap_muic:
- i2c_unregister_device(max77693->muic);
i2c_unregister_device(max77693->haptic);
+err_i2c_haptic:
+ i2c_unregister_device(max77693->muic);
return ret;
}
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
index 176aa26fc78..a83eed5c15c 100644
--- a/drivers/mfd/max8925-i2c.c
+++ b/drivers/mfd/max8925-i2c.c
@@ -181,9 +181,18 @@ static int max8925_probe(struct i2c_client *client,
mutex_init(&chip->io_lock);
chip->rtc = i2c_new_dummy(chip->i2c->adapter, RTC_I2C_ADDR);
+ if (!chip->rtc) {
+ dev_err(chip->dev, "Failed to allocate I2C device for RTC\n");
+ return -ENODEV;
+ }
i2c_set_clientdata(chip->rtc, chip);
chip->adc = i2c_new_dummy(chip->i2c->adapter, ADC_I2C_ADDR);
+ if (!chip->adc) {
+ dev_err(chip->dev, "Failed to allocate I2C device for ADC\n");
+ i2c_unregister_device(chip->rtc);
+ return -ENODEV;
+ }
i2c_set_clientdata(chip->adc, chip);
device_init_wakeup(&client->dev, 1);
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index 5adede0fb04..8cf7a015cfe 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -208,10 +208,26 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
mutex_init(&max8997->iolock);
max8997->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
+ if (!max8997->rtc) {
+ dev_err(max8997->dev, "Failed to allocate I2C device for RTC\n");
+ return -ENODEV;
+ }
i2c_set_clientdata(max8997->rtc, max8997);
+
max8997->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC);
+ if (!max8997->haptic) {
+ dev_err(max8997->dev, "Failed to allocate I2C device for Haptic\n");
+ ret = -ENODEV;
+ goto err_i2c_haptic;
+ }
i2c_set_clientdata(max8997->haptic, max8997);
+
max8997->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC);
+ if (!max8997->muic) {
+ dev_err(max8997->dev, "Failed to allocate I2C device for MUIC\n");
+ ret = -ENODEV;
+ goto err_i2c_muic;
+ }
i2c_set_clientdata(max8997->muic, max8997);
pm_runtime_set_active(max8997->dev);
@@ -239,7 +255,9 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
err_mfd:
mfd_remove_devices(max8997->dev);
i2c_unregister_device(max8997->muic);
+err_i2c_muic:
i2c_unregister_device(max8997->haptic);
+err_i2c_haptic:
i2c_unregister_device(max8997->rtc);
return ret;
}
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c
index 5d5e186b5d8..592db06098e 100644
--- a/drivers/mfd/max8998.c
+++ b/drivers/mfd/max8998.c
@@ -215,6 +215,10 @@ static int max8998_i2c_probe(struct i2c_client *i2c,
mutex_init(&max8998->iolock);
max8998->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR);
+ if (!max8998->rtc) {
+ dev_err(&i2c->dev, "Failed to allocate I2C device for RTC\n");
+ return -ENODEV;
+ }
i2c_set_clientdata(max8998->rtc, max8998);
max8998_irq_init(max8998);
diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c
index 38ab6782979..702925e242c 100644
--- a/drivers/mfd/mc13xxx-spi.c
+++ b/drivers/mfd/mc13xxx-spi.c
@@ -140,6 +140,11 @@ static int mc13xxx_spi_probe(struct spi_device *spi)
mc13xxx->irq = spi->irq;
+ spi->max_speed_hz = spi->max_speed_hz ? : 26000000;
+ ret = spi_setup(spi);
+ if (ret)
+ return ret;
+
mc13xxx->regmap = devm_regmap_init(&spi->dev, &regmap_mc13xxx_bus,
&spi->dev,
&mc13xxx_regmap_spi_config);
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
index 41c31b3ac94..29d76986b40 100644
--- a/drivers/mfd/mcp-sa11x0.c
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -12,7 +12,6 @@
* MCP read/write timeouts from Jordi Colomer, rehacked by rmk.
*/
#include <linux/module.h>
-#include <linux/init.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/kernel.h>
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 90b630ccc8b..651e249287d 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -665,55 +665,78 @@ static int usbhs_omap_probe(struct platform_device *pdev)
goto err_mem;
}
- need_logic_fck = false;
+ /* Set all clocks as invalid to begin with */
+ omap->ehci_logic_fck = ERR_PTR(-ENODEV);
+ omap->init_60m_fclk = ERR_PTR(-ENODEV);
+ omap->utmi_p1_gfclk = ERR_PTR(-ENODEV);
+ omap->utmi_p2_gfclk = ERR_PTR(-ENODEV);
+ omap->xclk60mhsp1_ck = ERR_PTR(-ENODEV);
+ omap->xclk60mhsp2_ck = ERR_PTR(-ENODEV);
+
for (i = 0; i < omap->nports; i++) {
- if (is_ehci_phy_mode(i) || is_ehci_tll_mode(i) ||
- is_ehci_hsic_mode(i))
- need_logic_fck |= true;
+ omap->utmi_clk[i] = ERR_PTR(-ENODEV);
+ omap->hsic480m_clk[i] = ERR_PTR(-ENODEV);
+ omap->hsic60m_clk[i] = ERR_PTR(-ENODEV);
}
- omap->ehci_logic_fck = ERR_PTR(-EINVAL);
- if (need_logic_fck) {
- omap->ehci_logic_fck = clk_get(dev, "ehci_logic_fck");
- if (IS_ERR(omap->ehci_logic_fck)) {
- ret = PTR_ERR(omap->ehci_logic_fck);
- dev_dbg(dev, "ehci_logic_fck failed:%d\n", ret);
+ /* for OMAP3 i.e. USBHS REV1 */
+ if (omap->usbhs_rev == OMAP_USBHS_REV1) {
+ need_logic_fck = false;
+ for (i = 0; i < omap->nports; i++) {
+ if (is_ehci_phy_mode(pdata->port_mode[i]) ||
+ is_ehci_tll_mode(pdata->port_mode[i]) ||
+ is_ehci_hsic_mode(pdata->port_mode[i]))
+
+ need_logic_fck |= true;
}
+
+ if (need_logic_fck) {
+ omap->ehci_logic_fck = devm_clk_get(dev,
+ "usbhost_120m_fck");
+ if (IS_ERR(omap->ehci_logic_fck)) {
+ ret = PTR_ERR(omap->ehci_logic_fck);
+ dev_err(dev, "usbhost_120m_fck failed:%d\n",
+ ret);
+ goto err_mem;
+ }
+ }
+ goto initialize;
}
- omap->utmi_p1_gfclk = clk_get(dev, "utmi_p1_gfclk");
+ /* for OMAP4+ i.e. USBHS REV2+ */
+ omap->utmi_p1_gfclk = devm_clk_get(dev, "utmi_p1_gfclk");
if (IS_ERR(omap->utmi_p1_gfclk)) {
ret = PTR_ERR(omap->utmi_p1_gfclk);
dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret);
- goto err_p1_gfclk;
+ goto err_mem;
}
- omap->utmi_p2_gfclk = clk_get(dev, "utmi_p2_gfclk");
+ omap->utmi_p2_gfclk = devm_clk_get(dev, "utmi_p2_gfclk");
if (IS_ERR(omap->utmi_p2_gfclk)) {
ret = PTR_ERR(omap->utmi_p2_gfclk);
dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
- goto err_p2_gfclk;
+ goto err_mem;
}
- omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
+ omap->xclk60mhsp1_ck = devm_clk_get(dev, "refclk_60m_ext_p1");
if (IS_ERR(omap->xclk60mhsp1_ck)) {
ret = PTR_ERR(omap->xclk60mhsp1_ck);
- dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret);
- goto err_xclk60mhsp1;
+ dev_err(dev, "refclk_60m_ext_p1 failed error:%d\n", ret);
+ goto err_mem;
}
- omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck");
+ omap->xclk60mhsp2_ck = devm_clk_get(dev, "refclk_60m_ext_p2");
if (IS_ERR(omap->xclk60mhsp2_ck)) {
ret = PTR_ERR(omap->xclk60mhsp2_ck);
- dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret);
- goto err_xclk60mhsp2;
+ dev_err(dev, "refclk_60m_ext_p2 failed error:%d\n", ret);
+ goto err_mem;
}
- omap->init_60m_fclk = clk_get(dev, "init_60m_fclk");
+ omap->init_60m_fclk = devm_clk_get(dev, "refclk_60m_int");
if (IS_ERR(omap->init_60m_fclk)) {
ret = PTR_ERR(omap->init_60m_fclk);
- dev_err(dev, "init_60m_fclk failed error:%d\n", ret);
- goto err_init60m;
+ dev_err(dev, "refclk_60m_int failed error:%d\n", ret);
+ goto err_mem;
}
for (i = 0; i < omap->nports; i++) {
@@ -727,55 +750,72 @@ static int usbhs_omap_probe(struct platform_device *pdev)
* platforms have all clocks and we can function without
* them
*/
- omap->utmi_clk[i] = clk_get(dev, clkname);
- if (IS_ERR(omap->utmi_clk[i]))
- dev_dbg(dev, "Failed to get clock : %s : %ld\n",
- clkname, PTR_ERR(omap->utmi_clk[i]));
+ omap->utmi_clk[i] = devm_clk_get(dev, clkname);
+ if (IS_ERR(omap->utmi_clk[i])) {
+ ret = PTR_ERR(omap->utmi_clk[i]);
+ dev_err(dev, "Failed to get clock : %s : %d\n",
+ clkname, ret);
+ goto err_mem;
+ }
snprintf(clkname, sizeof(clkname),
"usb_host_hs_hsic480m_p%d_clk", i + 1);
- omap->hsic480m_clk[i] = clk_get(dev, clkname);
- if (IS_ERR(omap->hsic480m_clk[i]))
- dev_dbg(dev, "Failed to get clock : %s : %ld\n",
- clkname, PTR_ERR(omap->hsic480m_clk[i]));
+ omap->hsic480m_clk[i] = devm_clk_get(dev, clkname);
+ if (IS_ERR(omap->hsic480m_clk[i])) {
+ ret = PTR_ERR(omap->hsic480m_clk[i]);
+ dev_err(dev, "Failed to get clock : %s : %d\n",
+ clkname, ret);
+ goto err_mem;
+ }
snprintf(clkname, sizeof(clkname),
"usb_host_hs_hsic60m_p%d_clk", i + 1);
- omap->hsic60m_clk[i] = clk_get(dev, clkname);
- if (IS_ERR(omap->hsic60m_clk[i]))
- dev_dbg(dev, "Failed to get clock : %s : %ld\n",
- clkname, PTR_ERR(omap->hsic60m_clk[i]));
+ omap->hsic60m_clk[i] = devm_clk_get(dev, clkname);
+ if (IS_ERR(omap->hsic60m_clk[i])) {
+ ret = PTR_ERR(omap->hsic60m_clk[i]);
+ dev_err(dev, "Failed to get clock : %s : %d\n",
+ clkname, ret);
+ goto err_mem;
+ }
}
if (is_ehci_phy_mode(pdata->port_mode[0])) {
- /* for OMAP3, clk_set_parent fails */
ret = clk_set_parent(omap->utmi_p1_gfclk,
omap->xclk60mhsp1_ck);
- if (ret != 0)
- dev_dbg(dev, "xclk60mhsp1_ck set parent failed: %d\n",
- ret);
+ if (ret != 0) {
+ dev_err(dev, "xclk60mhsp1_ck set parent failed: %d\n",
+ ret);
+ goto err_mem;
+ }
} else if (is_ehci_tll_mode(pdata->port_mode[0])) {
ret = clk_set_parent(omap->utmi_p1_gfclk,
omap->init_60m_fclk);
- if (ret != 0)
- dev_dbg(dev, "P0 init_60m_fclk set parent failed: %d\n",
- ret);
+ if (ret != 0) {
+ dev_err(dev, "P0 init_60m_fclk set parent failed: %d\n",
+ ret);
+ goto err_mem;
+ }
}
if (is_ehci_phy_mode(pdata->port_mode[1])) {
ret = clk_set_parent(omap->utmi_p2_gfclk,
omap->xclk60mhsp2_ck);
- if (ret != 0)
- dev_dbg(dev, "xclk60mhsp2_ck set parent failed: %d\n",
- ret);
+ if (ret != 0) {
+ dev_err(dev, "xclk60mhsp2_ck set parent failed: %d\n",
+ ret);
+ goto err_mem;
+ }
} else if (is_ehci_tll_mode(pdata->port_mode[1])) {
ret = clk_set_parent(omap->utmi_p2_gfclk,
omap->init_60m_fclk);
- if (ret != 0)
- dev_dbg(dev, "P1 init_60m_fclk set parent failed: %d\n",
- ret);
+ if (ret != 0) {
+ dev_err(dev, "P1 init_60m_fclk set parent failed: %d\n",
+ ret);
+ goto err_mem;
+ }
}
+initialize:
omap_usbhs_init(dev);
if (dev->of_node) {
@@ -784,7 +824,7 @@ static int usbhs_omap_probe(struct platform_device *pdev)
if (ret) {
dev_err(dev, "Failed to create DT children: %d\n", ret);
- goto err_alloc;
+ goto err_mem;
}
} else {
@@ -792,40 +832,12 @@ static int usbhs_omap_probe(struct platform_device *pdev)
if (ret) {
dev_err(dev, "omap_usbhs_alloc_children failed: %d\n",
ret);
- goto err_alloc;
+ goto err_mem;
}
}
return 0;
-err_alloc:
- for (i = 0; i < omap->nports; i++) {
- if (!IS_ERR(omap->utmi_clk[i]))
- clk_put(omap->utmi_clk[i]);
- if (!IS_ERR(omap->hsic60m_clk[i]))
- clk_put(omap->hsic60m_clk[i]);
- if (!IS_ERR(omap->hsic480m_clk[i]))
- clk_put(omap->hsic480m_clk[i]);
- }
-
- clk_put(omap->init_60m_fclk);
-
-err_init60m:
- clk_put(omap->xclk60mhsp2_ck);
-
-err_xclk60mhsp2:
- clk_put(omap->xclk60mhsp1_ck);
-
-err_xclk60mhsp1:
- clk_put(omap->utmi_p2_gfclk);
-
-err_p2_gfclk:
- clk_put(omap->utmi_p1_gfclk);
-
-err_p1_gfclk:
- if (!IS_ERR(omap->ehci_logic_fck))
- clk_put(omap->ehci_logic_fck);
-
err_mem:
pm_runtime_disable(dev);
@@ -847,27 +859,6 @@ static int usbhs_omap_remove_child(struct device *dev, void *data)
*/
static int usbhs_omap_remove(struct platform_device *pdev)
{
- struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
- int i;
-
- for (i = 0; i < omap->nports; i++) {
- if (!IS_ERR(omap->utmi_clk[i]))
- clk_put(omap->utmi_clk[i]);
- if (!IS_ERR(omap->hsic60m_clk[i]))
- clk_put(omap->hsic60m_clk[i]);
- if (!IS_ERR(omap->hsic480m_clk[i]))
- clk_put(omap->hsic480m_clk[i]);
- }
-
- clk_put(omap->init_60m_fclk);
- clk_put(omap->utmi_p1_gfclk);
- clk_put(omap->utmi_p2_gfclk);
- clk_put(omap->xclk60mhsp2_ck);
- clk_put(omap->xclk60mhsp1_ck);
-
- if (!IS_ERR(omap->ehci_logic_fck))
- clk_put(omap->ehci_logic_fck);
-
pm_runtime_disable(&pdev->dev);
/* remove children */
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index 5ee50f779ef..532eacab6b4 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -252,7 +252,7 @@ static int usbtll_omap_probe(struct platform_device *pdev)
break;
}
- tll->ch_clk = devm_kzalloc(dev, sizeof(struct clk * [tll->nch]),
+ tll->ch_clk = devm_kzalloc(dev, sizeof(struct clk *) * tll->nch,
GFP_KERNEL);
if (!tll->ch_clk) {
ret = -ENOMEM;
diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c