summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-07 10:24:18 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-07 10:24:18 -0700
commite5744abb2fa3629aa5a94e21ca1eae32ff2fe00b (patch)
treeef90c96390256b073f5255d224aecb2fc1f6ee84
parentc29aa153ef0469cddf0146d41ce6494bd76be78b (diff)
parent2d28ca731b9bb6262f7711241628c7844b0cf7dc (diff)
downloadop-kernel-dev-e5744abb2fa3629aa5a94e21ca1eae32ff2fe00b.zip
op-kernel-dev-e5744abb2fa3629aa5a94e21ca1eae32ff2fe00b.tar.gz
Merge tag 'mfd-for-linus-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones: "Changes to existing drivers: - Use of managed resources - omap, twl4030, ti_am335x_tscadc - Advanced error handling - omap - Rework clk management - omap - Device Tree (re-)work - tc3589x, pm8921, da9055, sec - IRC management overhaul and !BROKEN - pm8921 - Convert to regmap - ssbi, pm8921 - Use simple power-management ops - ucb1x00 - Include file clean-up - adp5520, cs5535, janz, lpc_ich, - lpc_sch, max14577, mcp-sa11x0, pcf50633-adc, rc5t583, rdc321x-southbridge, retu, smsc-ece1099, ti-ssp, ti_am335x_tscadc, tps65912, vexpress-config, wm8350, ywm8350 - Various bug fixes across the subsystem - NULL/invalid pointer dereference prevention - Resource leak mitigation, - Variable used initialised - Staticise various containers - Enforce return value checks New drivers/supported devices: - Add support for s2mps14 and s2mpa01 to sec - Add support for da9063 (v5) to da9063 - Add support for atom-c2000 to gpio-ich - Add support for come-{mbt10,cbt6,chl6} to kempld - Add support for da9053 to da9052 - Add support for itco-wdt (v3) and baytrail to lpc_ich - Add new drivers for tps65218, rtsx_usb, bcm590xx (Re-)moved drivers: - twl4030 ==> drivers/iio - ti-ssp ==> /dev/null" * tag 'mfd-for-linus-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (103 commits) mfd: wm5110: Correct default for HEADPHONE_DETECT_1 mfd: arizona: Correct small errors in the DT binding documentation mfd: arizona: Mark DSP clocking register as volatile mfd: devicetree: bindings: Add pm8xxx RTC description mfd: kempld-core: Fix potential hang-up during boot mfd: sec-core: Fix uninitialized 'regmap_rtc' on S2MPA01 mfd: tps65910: Fix regmap_irq_chip_data leak on mfd_add_devices fail mfd: tps65910: Fix possible invalid pointer dereference on regmap_add_irq_chip fail mfd: sec-core: Fix I2C dummy device resource leak on probe failure mfd: sec-core: Add of_compatible strings for clock MFD cells mfd: Remove obsolete ti-ssp driver Documentation: mfd: s2mps11: Describe S5M8767 and S2MPS14 clocks mfd: bcm590xx: Fix type argument for module device table mfd: lpc_ich: Add support for Intel Bay Trail SoC mfd: lpc_ich: Add support for NM10 GPIO mfd: lpc_ich: Change Avoton to iTCO v3 watchdog: iTCO_wdt: 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 ...
-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 0000000..6bdd214
--- /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 0e295c9..36a0c3d 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 0000000..1fe30e2
--- /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 0000000..6dab34d
--- /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 b381fa6..4721b2d 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 62fe697..c58d704 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 0000000..03518dc
--- /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 f69bec2..802e839 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 fe61976..0769ec5 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 8292ad0..19155bb 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 11ed915..8f5121b 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 9c7e23a..a123ff0 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 d323023..0d1750a 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 bfef20f..e73c675 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 4bf4c16..d86196c 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 bb25254..ab346d8 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 4c583e4..7de1c4c 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 7dca1e6..841717a 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 c9b1f64..bcfc9e8 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 49bb445..3383412 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 5aea5ef..2851275 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 6250155..f495b8b 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 c71ff0a..39fa554 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 0000000..e9a33c7
--- /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 17c1301..be91cb5 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 25838f1..e8af816 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 c319c4e..6da8ec8 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 0680bcb..17666b4 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 8103e43..d4d4c16 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 26937cd..e70ae31 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 81b7d88..433f823 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 d3e2327..0769260 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 be93fa2..3f10ea3 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 3bb05c0..4ee7550 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 71aa14a..5f13cef 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 f53d582..e5fce76 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 e085998..c5535f0 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 176aa26..a83eed5 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 5adede0..8cf7a01 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 5d5e186..592db06 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 38ab678..702925e 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 41c31b3..29d7698 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 90b630c..651e249 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 5ee50f7..532eacab 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
index b8941a5..c1984b0 100644
--- a/drivers/mfd/pcf50633-adc.c
+++ b/drivers/mfd/pcf50633-adc.c
@@ -19,7 +19,6 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
-#include <linux/init.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/completion.h>
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 484fe66..b97a971 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -14,23 +14,316 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/ssbi.h>
+#include <linux/regmap.h>
+#include <linux/of_platform.h>
#include <linux/mfd/core.h>
-#include <linux/mfd/pm8xxx/pm8921.h>
#include <linux/mfd/pm8xxx/core.h>
+#define SSBI_REG_ADDR_IRQ_BASE 0x1BB
+
+#define SSBI_REG_ADDR_IRQ_ROOT (SSBI_REG_ADDR_IRQ_BASE + 0)
+#define SSBI_REG_ADDR_IRQ_M_STATUS1 (SSBI_REG_ADDR_IRQ_BASE + 1)
+#define SSBI_REG_ADDR_IRQ_M_STATUS2 (SSBI_REG_ADDR_IRQ_BASE + 2)
+#define SSBI_REG_ADDR_IRQ_M_STATUS3 (SSBI_REG_ADDR_IRQ_BASE + 3)
+#define SSBI_REG_ADDR_IRQ_M_STATUS4 (SSBI_REG_ADDR_IRQ_BASE + 4)
+#define SSBI_REG_ADDR_IRQ_BLK_SEL (SSBI_REG_ADDR_IRQ_BASE + 5)
+#define SSBI_REG_ADDR_IRQ_IT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 6)
+#define SSBI_REG_ADDR_IRQ_CONFIG (SSBI_REG_ADDR_IRQ_BASE + 7)
+#define SSBI_REG_ADDR_IRQ_RT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 8)
+
+#define PM_IRQF_LVL_SEL 0x01 /* level select */
+#define PM_IRQF_MASK_FE 0x02 /* mask falling edge */
+#define PM_IRQF_MASK_RE 0x04 /* mask rising edge */
+#define PM_IRQF_CLR 0x08 /* clear interrupt */
+#define PM_IRQF_BITS_MASK 0x70
+#define PM_IRQF_BITS_SHIFT 4
+#define PM_IRQF_WRITE 0x80
+
+#define PM_IRQF_MASK_ALL (PM_IRQF_MASK_FE | \
+ PM_IRQF_MASK_RE)
+
#define REG_HWREV 0x002 /* PMIC4 revision */
#define REG_HWREV_2 0x0E8 /* PMIC4 revision 2 */
+#define PM8921_NR_IRQS 256
+
+struct pm_irq_chip {
+ struct device *dev;
+ struct regmap *regmap;
+ spinlock_t pm_irq_lock;
+ struct irq_domain *irqdomain;
+ unsigned int num_irqs;
+ unsigned int num_blocks;
+ unsigned int num_masters;
+ u8 config[0];
+};
+
struct pm8921 {
struct device *dev;
struct pm_irq_chip *irq_chip;
};
+static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
+ unsigned int *ip)
+{
+ int rc;
+
+ spin_lock(&chip->pm_irq_lock);
+ rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
+ if (rc) {
+ pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
+ goto bail;
+ }
+
+ rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
+ if (rc)
+ pr_err("Failed Reading Status rc=%d\n", rc);
+bail:
+ spin_unlock(&chip->pm_irq_lock);
+ return rc;
+}
+
+static int
+pm8xxx_config_irq(struct pm_irq_chip *chip, unsigned int bp, unsigned int cp)
+{
+ int rc;
+
+ spin_lock(&chip->pm_irq_lock);
+ rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
+ if (rc) {
+ pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
+ goto bail;
+ }
+
+ cp |= PM_IRQF_WRITE;
+ rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_CONFIG, cp);
+ if (rc)
+ pr_err("Failed Configuring IRQ rc=%d\n", rc);
+bail:
+ spin_unlock(&chip->pm_irq_lock);
+ return rc;
+}
+
+static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
+{
+ int pmirq, irq, i, ret = 0;
+ unsigned int bits;
+
+ ret = pm8xxx_read_block_irq(chip, block, &bits);
+ if (ret) {
+ pr_err("Failed reading %d block ret=%d", block, ret);
+ return ret;
+ }
+ if (!bits) {
+ pr_err("block bit set in master but no irqs: %d", block);
+ return 0;
+ }
+
+ /* Check IRQ bits */
+ for (i = 0; i < 8; i++) {
+ if (bits & (1 << i)) {
+ pmirq = block * 8 + i;
+ irq = irq_find_mapping(chip->irqdomain, pmirq);
+ generic_handle_irq(irq);
+ }
+ }
+ return 0;
+}
+
+static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
+{
+ unsigned int blockbits;
+ int block_number, i, ret = 0;
+
+ ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_M_STATUS1 + master,
+ &blockbits);
+ if (ret) {
+ pr_err("Failed to read master %d ret=%d\n", master, ret);
+ return ret;
+ }
+ if (!blockbits) {
+ pr_err("master bit set in root but no blocks: %d", master);
+ return 0;
+ }
+
+ for (i = 0; i < 8; i++)
+ if (blockbits & (1 << i)) {
+ block_number = master * 8 + i; /* block # */
+ ret |= pm8xxx_irq_block_handler(chip, block_number);
+ }
+ return ret;
+}
+
+static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+ struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
+ struct irq_chip *irq_chip = irq_desc_get_chip(desc);
+ unsigned int root;
+ int i, ret, masters = 0;
+
+ chained_irq_enter(irq_chip, desc);
+
+ ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_ROOT, &root);
+ if (ret) {
+ pr_err("Can't read root status ret=%d\n", ret);
+ return;
+ }
+
+ /* on pm8xxx series masters start from bit 1 of the root */
+ masters = root >> 1;
+
+ /* Read allowed masters for blocks. */
+ for (i = 0; i < chip->num_masters; i++)
+ if (masters & (1 << i))
+ pm8xxx_irq_master_handler(chip, i);
+
+ chained_irq_exit(irq_chip, desc);
+}
+
+static void pm8xxx_irq_mask_ack(struct irq_data *d)
+{
+ struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+ unsigned int pmirq = irqd_to_hwirq(d);
+ int irq_bit;
+ u8 block, config;
+
+ block = pmirq / 8;
+ irq_bit = pmirq % 8;
+
+ config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
+ pm8xxx_config_irq(chip, block, config);
+}
+
+static void pm8xxx_irq_unmask(struct irq_data *d)
+{
+ struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+ unsigned int pmirq = irqd_to_hwirq(d);
+ int irq_bit;
+ u8 block, config;
+
+ block = pmirq / 8;
+ irq_bit = pmirq % 8;
+
+ config = chip->config[pmirq];
+ pm8xxx_config_irq(chip, block, config);
+}
+
+static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+ struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+ unsigned int pmirq = irqd_to_hwirq(d);
+ int irq_bit;
+ u8 block, config;
+
+ block = pmirq / 8;
+ irq_bit = pmirq % 8;
+
+ chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT)
+ | PM_IRQF_MASK_ALL;
+ if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
+ if (flow_type & IRQF_TRIGGER_RISING)
+ chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
+ if (flow_type & IRQF_TRIGGER_FALLING)
+ chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
+ } else {
+ chip->config[pmirq] |= PM_IRQF_LVL_SEL;
+
+ if (flow_type & IRQF_TRIGGER_HIGH)
+ chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
+ else
+ chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
+ }
+
+ config = chip->config[pmirq] | PM_IRQF_CLR;
+ return pm8xxx_config_irq(chip, block, config);
+}
+
+static struct irq_chip pm8xxx_irq_chip = {
+ .name = "pm8xxx",
+ .irq_mask_ack = pm8xxx_irq_mask_ack,
+ .irq_unmask = pm8xxx_irq_unmask,
+ .irq_set_type = pm8xxx_irq_set_type,
+ .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
+};
+
+/**
+ * pm8xxx_get_irq_stat - get the status of the irq line
+ * @chip: pointer to identify a pmic irq controller
+ * @irq: the irq number
+ *
+ * The pm8xxx gpio and mpp rely on the interrupt block to read
+ * the values on their pins. This function is to facilitate reading
+ * the status of a gpio or an mpp line. The caller has to convert the
+ * gpio number to irq number.
+ *
+ * RETURNS:
+ * an int indicating the value read on that line
+ */
+static int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
+{
+ int pmirq, rc;
+ unsigned int block, bits, bit;
+ unsigned long flags;
+ struct irq_data *irq_data = irq_get_irq_data(irq);
+
+ pmirq = irq_data->hwirq;
+
+ block = pmirq / 8;
+ bit = pmirq % 8;
+
+ spin_lock_irqsave(&chip->pm_irq_lock, flags);
+
+ rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
+ if (rc) {
+ pr_err("Failed Selecting block irq=%d pmirq=%d blk=%d rc=%d\n",
+ irq, pmirq, block, rc);
+ goto bail_out;
+ }
+
+ rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
+ if (rc) {
+ pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n",
+ irq, pmirq, block, rc);
+ goto bail_out;
+ }
+
+ rc = (bits & (1 << bit)) ? 1 : 0;
+
+bail_out:
+ spin_unlock_irqrestore(&chip->pm_irq_lock, flags);
+
+ return rc;
+}
+
+static int pm8xxx_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct pm_irq_chip *chip = d->host_data;
+
+ irq_set_chip_and_handler(irq, &pm8xxx_irq_chip, handle_level_irq);
+ irq_set_chip_data(irq, chip);
+#ifdef CONFIG_ARM
+ set_irq_flags(irq, IRQF_VALID);
+#else
+ irq_set_noprobe(irq);
+#endif
+ return 0;
+}
+
+static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
+ .xlate = irq_domain_xlate_twocell,
+ .map = pm8xxx_irq_domain_map,
+};
+
static int pm8921_readb(const struct device *dev, u16 addr, u8 *val)
{
const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
@@ -81,42 +374,35 @@ static struct pm8xxx_drvdata pm8921_drvdata = {
.pmic_read_irq_stat = pm8921_read_irq_stat,
};
-static int pm8921_add_subdevices(const struct pm8921_platform_data
- *pdata,
- struct pm8921 *pmic,
- u32 rev)
-{
- int ret = 0, irq_base = 0;
- struct pm_irq_chip *irq_chip;
-
- if (pdata->irq_pdata) {
- pdata->irq_pdata->irq_cdata.nirqs = PM8921_NR_IRQS;
- pdata->irq_pdata->irq_cdata.rev = rev;
- irq_base = pdata->irq_pdata->irq_base;
- irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata);
+static const struct regmap_config ssbi_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .max_register = 0x3ff,
+ .fast_io = true,
+ .reg_read = ssbi_reg_read,
+ .reg_write = ssbi_reg_write
+};
- if (IS_ERR(irq_chip)) {
- pr_err("Failed to init interrupts ret=%ld\n",
- PTR_ERR(irq_chip));
- return PTR_ERR(irq_chip);
- }
- pmic->irq_chip = irq_chip;
- }
- return ret;
-}
+static const struct of_device_id pm8921_id_table[] = {
+ { .compatible = "qcom,pm8058", },
+ { .compatible = "qcom,pm8921", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pm8921_id_table);
static int pm8921_probe(struct platform_device *pdev)
{
- const struct pm8921_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct pm8921 *pmic;
- int rc;
- u8 val;
+ struct regmap *regmap;
+ int irq, rc;
+ unsigned int val;
u32 rev;
+ struct pm_irq_chip *chip;
+ unsigned int nirqs = PM8921_NR_IRQS;
- if (!pdata) {
- pr_err("missing platform data\n");
- return -EINVAL;
- }
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
pmic = devm_kzalloc(&pdev->dev, sizeof(struct pm8921), GFP_KERNEL);
if (!pmic) {
@@ -124,8 +410,13 @@ static int pm8921_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ regmap = devm_regmap_init(&pdev->dev, NULL, pdev->dev.parent,
+ &ssbi_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
/* Read PMIC chip revision */
- rc = ssbi_read(pdev->dev.parent, REG_HWREV, &val, sizeof(val));
+ rc = regmap_read(regmap, REG_HWREV, &val);
if (rc) {
pr_err("Failed to read hw rev reg %d:rc=%d\n", REG_HWREV, rc);
return rc;
@@ -134,7 +425,7 @@ static int pm8921_probe(struct platform_device *pdev)
rev = val;
/* Read PMIC chip revision 2 */
- rc = ssbi_read(pdev->dev.parent, REG_HWREV_2, &val, sizeof(val));
+ rc = regmap_read(regmap, REG_HWREV_2, &val);
if (rc) {
pr_err("Failed to read hw rev 2 reg %d:rc=%d\n",
REG_HWREV_2, rc);
@@ -147,37 +438,56 @@ static int pm8921_probe(struct platform_device *pdev)
pm8921_drvdata.pm_chip_data = pmic;
platform_set_drvdata(pdev, &pm8921_drvdata);
- rc = pm8921_add_subdevices(pdata, pmic, rev);
+ chip = devm_kzalloc(&pdev->dev, sizeof(*chip) +
+ sizeof(chip->config[0]) * nirqs,
+ GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ pmic->irq_chip = chip;
+ chip->dev = &pdev->dev;
+ chip->regmap = regmap;
+ chip->num_irqs = nirqs;
+ chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
+ chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
+ spin_lock_init(&chip->pm_irq_lock);
+
+ chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node, nirqs,
+ &pm8xxx_irq_domain_ops,
+ chip);
+ if (!chip->irqdomain)
+ return -ENODEV;
+
+ irq_set_handler_data(irq, chip);
+ irq_set_chained_handler(irq, pm8xxx_irq_handler);
+ irq_set_irq_wake(irq, 1);
+
+ rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
if (rc) {
- pr_err("Cannot add subdevices rc=%d\n", rc);
- goto err;
+ irq_set_chained_handler(irq, NULL);
+ irq_set_handler_data(irq, NULL);
+ irq_domain_remove(chip->irqdomain);
}
- /* gpio might not work if no irq device is found */
- WARN_ON(pmic->irq_chip == NULL);
+ return rc;
+}
+static int pm8921_remove_child(struct device *dev, void *unused)
+{
+ platform_device_unregister(to_platform_device(dev));
return 0;
-
-err:
- mfd_remove_devices(pmic->dev);
- return rc;
}
static int pm8921_remove(struct platform_device *pdev)
{
- struct pm8xxx_drvdata *drvdata;
- struct pm8921 *pmic = NULL;
-
- drvdata = platform_get_drvdata(pdev);
- if (drvdata)
- pmic = drvdata->pm_chip_data;
- if (pmic) {
- mfd_remove_devices(pmic->dev);
- if (pmic->irq_chip) {
- pm8xxx_irq_exit(pmic->irq_chip);
- pmic->irq_chip = NULL;
- }
- }
+ int irq = platform_get_irq(pdev, 0);
+ struct pm8921 *pmic = pm8921_drvdata.pm_chip_data;
+ struct pm_irq_chip *chip = pmic->irq_chip;
+
+ device_for_each_child(&pdev->dev, NULL, pm8921_remove_child);
+ irq_set_chained_handler(irq, NULL);
+ irq_set_handler_data(irq, NULL);
+ irq_domain_remove(chip->irqdomain);
return 0;
}
@@ -188,6 +498,7 @@ static struct platform_driver pm8921_driver = {
.driver = {
.name = "pm8921-core",
.owner = THIS_MODULE,
+ .of_match_table = pm8921_id_table,
},
};
diff --git a/drivers/mfd/pm8xxx-irq.c b/drivers/mfd/pm8xxx-irq.c
deleted file mode 100644
index 1360e20..0000000
--- a/drivers/mfd/pm8xxx-irq.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#define pr_fmt(fmt) "%s: " fmt, __func__
-
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/mfd/pm8xxx/core.h>
-#include <linux/mfd/pm8xxx/irq.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-/* PMIC8xxx IRQ */
-
-#define SSBI_REG_ADDR_IRQ_BASE 0x1BB
-
-#define SSBI_REG_ADDR_IRQ_ROOT (SSBI_REG_ADDR_IRQ_BASE + 0)
-#define SSBI_REG_ADDR_IRQ_M_STATUS1 (SSBI_REG_ADDR_IRQ_BASE + 1)
-#define SSBI_REG_ADDR_IRQ_M_STATUS2 (SSBI_REG_ADDR_IRQ_BASE + 2)
-#define SSBI_REG_ADDR_IRQ_M_STATUS3 (SSBI_REG_ADDR_IRQ_BASE + 3)
-#define SSBI_REG_ADDR_IRQ_M_STATUS4 (SSBI_REG_ADDR_IRQ_BASE + 4)
-#define SSBI_REG_ADDR_IRQ_BLK_SEL (SSBI_REG_ADDR_IRQ_BASE + 5)
-#define SSBI_REG_ADDR_IRQ_IT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 6)
-#define SSBI_REG_ADDR_IRQ_CONFIG (SSBI_REG_ADDR_IRQ_BASE + 7)
-#define SSBI_REG_ADDR_IRQ_RT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 8)
-
-#define PM_IRQF_LVL_SEL 0x01 /* level select */
-#define PM_IRQF_MASK_FE 0x02 /* mask falling edge */
-#define PM_IRQF_MASK_RE 0x04 /* mask rising edge */
-#define PM_IRQF_CLR 0x08 /* clear interrupt */
-#define PM_IRQF_BITS_MASK 0x70
-#define PM_IRQF_BITS_SHIFT 4
-#define PM_IRQF_WRITE 0x80
-
-#define PM_IRQF_MASK_ALL (PM_IRQF_MASK_FE | \
- PM_IRQF_MASK_RE)
-
-struct pm_irq_chip {
- struct device *dev;
- spinlock_t pm_irq_lock;
- unsigned int devirq;
- unsigned int irq_base;
- unsigned int num_irqs;
- unsigned int num_blocks;
- unsigned int num_masters;
- u8 config[0];
-};
-
-static int pm8xxx_read_root_irq(const struct pm_irq_chip *chip, u8 *rp)
-{
- return pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_ROOT, rp);
-}
-
-static int pm8xxx_read_master_irq(const struct pm_irq_chip *chip, u8 m, u8 *bp)
-{
- return pm8xxx_readb(chip->dev,
- SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp);
-}
-
-static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, u8 bp, u8 *ip)
-{
- int rc;
-
- spin_lock(&chip->pm_irq_lock);
- rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
- if (rc) {
- pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
- goto bail;
- }
-
- rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
- if (rc)
- pr_err("Failed Reading Status rc=%d\n", rc);
-bail:
- spin_unlock(&chip->pm_irq_lock);
- return rc;
-}
-
-static int pm8xxx_config_irq(struct pm_irq_chip *chip, u8 bp, u8 cp)
-{
- int rc;
-
- spin_lock(&chip->pm_irq_lock);
- rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
- if (rc) {
- pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
- goto bail;
- }
-
- cp |= PM_IRQF_WRITE;
- rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp);
- if (rc)
- pr_err("Failed Configuring IRQ rc=%d\n", rc);
-bail:
- spin_unlock(&chip->pm_irq_lock);
- return rc;
-}
-
-static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
-{
- int pmirq, irq, i, ret = 0;
- u8 bits;
-
- ret = pm8xxx_read_block_irq(chip, block, &bits);
- if (ret) {
- pr_err("Failed reading %d block ret=%d", block, ret);
- return ret;
- }
- if (!bits) {
- pr_err("block bit set in master but no irqs: %d", block);
- return 0;
- }
-
- /* Check IRQ bits */
- for (i = 0; i < 8; i++) {
- if (bits & (1 << i)) {
- pmirq = block * 8 + i;
- irq = pmirq + chip->irq_base;
- generic_handle_irq(irq);
- }
- }
- return 0;
-}
-
-static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
-{
- u8 blockbits;
- int block_number, i, ret = 0;
-
- ret = pm8xxx_read_master_irq(chip, master, &blockbits);
- if (ret) {
- pr_err("Failed to read master %d ret=%d\n", master, ret);
- return ret;
- }
- if (!blockbits) {
- pr_err("master bit set in root but no blocks: %d", master);
- return 0;
- }
-
- for (i = 0; i < 8; i++)
- if (blockbits & (1 << i)) {
- block_number = master * 8 + i; /* block # */
- ret |= pm8xxx_irq_block_handler(chip, block_number);
- }
- return ret;
-}
-
-static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
- struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
- struct irq_chip *irq_chip = irq_desc_get_chip(desc);
- u8 root;
- int i, ret, masters = 0;
-
- ret = pm8xxx_read_root_irq(chip, &root);
- if (ret) {
- pr_err("Can't read root status ret=%d\n", ret);
- return;
- }
-
- /* on pm8xxx series masters start from bit 1 of the root */
- masters = root >> 1;
-
- /* Read allowed masters for blocks. */
- for (i = 0; i < chip->num_masters; i++)
- if (masters & (1 << i))
- pm8xxx_irq_master_handler(chip, i);
-
- irq_chip->irq_ack(&desc->irq_data);
-}
-
-static void pm8xxx_irq_mask_ack(struct irq_data *d)
-{
- struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
- unsigned int pmirq = d->irq - chip->irq_base;
- int master, irq_bit;
- u8 block, config;
-
- block = pmirq / 8;
- master = block / 8;
- irq_bit = pmirq % 8;
-
- config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
- pm8xxx_config_irq(chip, block, config);
-}
-
-static void pm8xxx_irq_unmask(struct irq_data *d)
-{
- struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
- unsigned int pmirq = d->irq - chip->irq_base;
- int master, irq_bit;
- u8 block, config;
-
- block = pmirq / 8;
- master = block / 8;
- irq_bit = pmirq % 8;
-
- config = chip->config[pmirq];
- pm8xxx_config_irq(chip, block, config);
-}
-
-static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
- struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
- unsigned int pmirq = d->irq - chip->irq_base;
- int master, irq_bit;
- u8 block, config;
-
- block = pmirq / 8;
- master = block / 8;
- irq_bit = pmirq % 8;
-
- chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT)
- | PM_IRQF_MASK_ALL;
- if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
- if (flow_type & IRQF_TRIGGER_RISING)
- chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
- if (flow_type & IRQF_TRIGGER_FALLING)
- chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
- } else {
- chip->config[pmirq] |= PM_IRQF_LVL_SEL;
-
- if (flow_type & IRQF_TRIGGER_HIGH)
- chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
- else
- chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
- }
-
- config = chip->config[pmirq] | PM_IRQF_CLR;
- return pm8xxx_config_irq(chip, block, config);
-}
-
-static int pm8xxx_irq_set_wake(struct irq_data *d, unsigned int on)
-{
- return 0;
-}
-
-static struct irq_chip pm8xxx_irq_chip = {
- .name = "pm8xxx",
- .irq_mask_ack = pm8xxx_irq_mask_ack,
- .irq_unmask = pm8xxx_irq_unmask,
- .irq_set_type = pm8xxx_irq_set_type,
- .irq_set_wake = pm8xxx_irq_set_wake,
- .flags = IRQCHIP_MASK_ON_SUSPEND,
-};
-
-/**
- * pm8xxx_get_irq_stat - get the status of the irq line
- * @chip: pointer to identify a pmic irq controller
- * @irq: the irq number
- *
- * The pm8xxx gpio and mpp rely on the interrupt block to read
- * the values on their pins. This function is to facilitate reading
- * the status of a gpio or an mpp line. The caller has to convert the
- * gpio number to irq number.
- *
- * RETURNS:
- * an int indicating the value read on that line
- */
-int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
-{
- int pmirq, rc;
- u8 block, bits, bit;
- unsigned long flags;
-
- if (chip == NULL || irq < chip->irq_base ||
- irq >= chip->irq_base + chip->num_irqs)
- return -EINVAL;
-
- pmirq = irq - chip->irq_base;
-
- block = pmirq / 8;
- bit = pmirq % 8;
-
- spin_lock_irqsave(&chip->pm_irq_lock, flags);
-
- rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
- if (rc) {
- pr_err("Failed Selecting block irq=%d pmirq=%d blk=%d rc=%d\n",
- irq, pmirq, block, rc);
- goto bail_out;
- }
-
- rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
- if (rc) {
- pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n",
- irq, pmirq, block, rc);
- goto bail_out;
- }
-
- rc = (bits & (1 << bit)) ? 1 : 0;
-
-bail_out:
- spin_unlock_irqrestore(&chip->pm_irq_lock, flags);
-
- return rc;
-}
-EXPORT_SYMBOL_GPL(pm8xxx_get_irq_stat);
-
-struct pm_irq_chip * pm8xxx_irq_init(struct device *dev,
- const struct pm8xxx_irq_platform_data *pdata)
-{
- struct pm_irq_chip *chip;
- int devirq, rc;
- unsigned int pmirq;
-
- if (!pdata) {
- pr_err("No platform data\n");
- return ERR_PTR(-EINVAL);
- }
-
- devirq = pdata->devirq;
- if (devirq < 0) {
- pr_err("missing devirq\n");
- rc = devirq;
- return ERR_PTR(-EINVAL);
- }
-
- chip = kzalloc(sizeof(struct pm_irq_chip)
- + sizeof(u8) * pdata->irq_cdata.nirqs, GFP_KERNEL);
- if (!chip) {
- pr_err("Cannot alloc pm_irq_chip struct\n");
- return ERR_PTR(-EINVAL);
- }
-
- chip->dev = dev;
- chip->devirq = devirq;
- chip->irq_base = pdata->irq_base;
- chip->num_irqs = pdata->irq_cdata.nirqs;
- chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
- chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
- spin_lock_init(&chip->pm_irq_lock);
-
- for (pmirq = 0; pmirq < chip->num_irqs; pmirq++) {
- irq_set_chip_and_handler(chip->irq_base + pmirq,
- &pm8xxx_irq_chip,
- handle_level_irq);
- irq_set_chip_data(chip->irq_base + pmirq, chip);
-#ifdef CONFIG_ARM
- set_irq_flags(chip->irq_base + pmirq, IRQF_VALID);
-#else
- irq_set_noprobe(chip->irq_base + pmirq);
-#endif
- }
-
- irq_set_irq_type(devirq, pdata->irq_trigger_flag);
- irq_set_handler_data(devirq, chip);
- irq_set_chained_handler(devirq, pm8xxx_irq_handler);
- set_irq_wake(devirq, 1);
-
- return chip;
-}
-
-int pm8xxx_irq_exit(struct pm_irq_chip *chip)
-{
- irq_set_chained_handler(chip->devirq, NULL);
- kfree(chip);
- return 0;
-}
diff --git a/drivers/mfd/rc5t583-irq.c b/drivers/mfd/rc5t583-irq.c
index b41db59..bb85020 100644
--- a/drivers/mfd/rc5t583-irq.c
+++ b/drivers/mfd/rc5t583-irq.c
@@ -22,7 +22,6 @@
*/
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/mfd/rc5t583.h>
diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c
index d346146..c795697 100644
--- a/drivers/mfd/rdc321x-southbridge.c
+++ b/drivers/mfd/rdc321x-southbridge.c
@@ -19,7 +19,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
-#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
diff --git a/drivers/mfd/retu-mfd.c b/drivers/mfd/retu-mfd.c
index c8f345f..663f8a3 100644
--- a/drivers/mfd/retu-mfd.c
+++ b/drivers/mfd/retu-mfd.c
@@ -19,7 +19,6 @@
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/irq.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/module.h>
diff --git a/drivers/mfd/rtsx_usb.c b/drivers/mfd/rtsx_usb.c
new file mode 100644
index 0000000..b53b9d4
--- /dev/null
+++ b/drivers/mfd/rtsx_usb.c
@@ -0,0 +1,760 @@
+/* Driver for Realtek USB card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ * Roger Tseng <rogerable@realtek.com>
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/usb.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/rtsx_usb.h>
+
+static int polling_pipe = 1;
+module_param(polling_pipe, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(polling_pipe, "polling pipe (0: ctl, 1: bulk)");
+
+static struct mfd_cell rtsx_usb_cells[] = {
+ [RTSX_USB_SD_CARD] = {
+ .name = "rtsx_usb_sdmmc",
+ .pdata_size = 0,
+ },
+ [RTSX_USB_MS_CARD] = {
+ .name = "rtsx_usb_ms",
+ .pdata_size = 0,
+ },
+};
+
+static void rtsx_usb_sg_timed_out(unsigned long data)
+{
+ struct rtsx_ucr *ucr = (struct rtsx_ucr *)data;
+
+ dev_dbg(&ucr->pusb_intf->dev, "%s: sg transfer timed out", __func__);
+ usb_sg_cancel(&ucr->current_sg);
+
+ /* we know the cancellation is caused by time-out */
+ ucr->current_sg.status = -ETIMEDOUT;
+}
+
+static int rtsx_usb_bulk_transfer_sglist(struct rtsx_ucr *ucr,
+ unsigned int pipe, struct scatterlist *sg, int num_sg,
+ unsigned int length, unsigned int *act_len, int timeout)
+{
+ int ret;
+
+ dev_dbg(&ucr->pusb_intf->dev, "%s: xfer %u bytes, %d entries\n",
+ __func__, length, num_sg);
+ ret = usb_sg_init(&ucr->current_sg, ucr->pusb_dev, pipe, 0,
+ sg, num_sg, length, GFP_NOIO);
+ if (ret)
+ return ret;
+
+ ucr->sg_timer.expires = jiffies + msecs_to_jiffies(timeout);
+ add_timer(&ucr->sg_timer);
+ usb_sg_wait(&ucr->current_sg);
+ del_timer(&ucr->sg_timer);
+
+ if (act_len)
+ *act_len = ucr->current_sg.bytes;
+
+ return ucr->current_sg.status;
+}
+
+int rtsx_usb_transfer_data(struct rtsx_ucr *ucr, unsigned int pipe,
+ void *buf, unsigned int len, int num_sg,
+ unsigned int *act_len, int timeout)
+{
+ if (timeout < 600)
+ timeout = 600;
+
+ if (num_sg)
+ return rtsx_usb_bulk_transfer_sglist(ucr, pipe,
+ (struct scatterlist *)buf, num_sg, len, act_len,
+ timeout);
+ else
+ return usb_bulk_msg(ucr->pusb_dev, pipe, buf, len, act_len,
+ timeout);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_transfer_data);
+
+static inline void rtsx_usb_seq_cmd_hdr(struct rtsx_ucr *ucr,
+ u16 addr, u16 len, u8 seq_type)
+{
+ rtsx_usb_cmd_hdr_tag(ucr);
+
+ ucr->cmd_buf[PACKET_TYPE] = seq_type;
+ ucr->cmd_buf[5] = (u8)(len >> 8);
+ ucr->cmd_buf[6] = (u8)len;
+ ucr->cmd_buf[8] = (u8)(addr >> 8);
+ ucr->cmd_buf[9] = (u8)addr;
+
+ if (seq_type == SEQ_WRITE)
+ ucr->cmd_buf[STAGE_FLAG] = 0;
+ else
+ ucr->cmd_buf[STAGE_FLAG] = STAGE_R;
+}
+
+static int rtsx_usb_seq_write_register(struct rtsx_ucr *ucr,
+ u16 addr, u16 len, u8 *data)
+{
+ u16 cmd_len = ALIGN(SEQ_WRITE_DATA_OFFSET + len, 4);
+
+ if (!data)
+ return -EINVAL;
+
+ if (cmd_len > IOBUF_SIZE)
+ return -EINVAL;
+
+ rtsx_usb_seq_cmd_hdr(ucr, addr, len, SEQ_WRITE);
+ memcpy(ucr->cmd_buf + SEQ_WRITE_DATA_OFFSET, data, len);
+
+ return rtsx_usb_transfer_data(ucr,
+ usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
+ ucr->cmd_buf, cmd_len, 0, NULL, 100);
+}
+
+static int rtsx_usb_seq_read_register(struct rtsx_ucr *ucr,
+ u16 addr, u16 len, u8 *data)
+{
+ int i, ret;
+ u16 rsp_len = round_down(len, 4);
+ u16 res_len = len - rsp_len;
+
+ if (!data)
+ return -EINVAL;
+
+ /* 4-byte aligned part */
+ if (rsp_len) {
+ rtsx_usb_seq_cmd_hdr(ucr, addr, len, SEQ_READ);
+ ret = rtsx_usb_transfer_data(ucr,
+ usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
+ ucr->cmd_buf, 12, 0, NULL, 100);
+ if (ret)
+ return ret;
+
+ ret = rtsx_usb_transfer_data(ucr,
+ usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN),
+ data, rsp_len, 0, NULL, 100);
+ if (ret)
+ return ret;
+ }
+
+ /* unaligned part */
+ for (i = 0; i < res_len; i++) {
+ ret = rtsx_usb_read_register(ucr, addr + rsp_len + i,
+ data + rsp_len + i);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+int rtsx_usb_read_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len)
+{
+ return rtsx_usb_seq_read_register(ucr, PPBUF_BASE2, (u16)buf_len, buf);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_read_ppbuf);
+
+int rtsx_usb_write_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len)
+{
+ return rtsx_usb_seq_write_register(ucr, PPBUF_BASE2, (u16)buf_len, buf);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_write_ppbuf);
+
+int rtsx_usb_ep0_write_register(struct rtsx_ucr *ucr, u16 addr,
+ u8 mask, u8 data)
+{
+ u16 value, index;
+
+ addr |= EP0_WRITE_REG_CMD << EP0_OP_SHIFT;
+ value = swab16(addr);
+ index = mask | data << 8;
+
+ return usb_control_msg(ucr->pusb_dev,
+ usb_sndctrlpipe(ucr->pusb_dev, 0), RTSX_USB_REQ_REG_OP,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, index, NULL, 0, 100);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_ep0_write_register);
+
+int rtsx_usb_ep0_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data)
+{
+ u16 value;
+
+ if (!data)
+ return -EINVAL;
+ *data = 0;
+
+ addr |= EP0_READ_REG_CMD << EP0_OP_SHIFT;
+ value = swab16(addr);
+
+ return usb_control_msg(ucr->pusb_dev,
+ usb_rcvctrlpipe(ucr->pusb_dev, 0), RTSX_USB_REQ_REG_OP,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, 0, data, 1, 100);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_ep0_read_register);
+
+void rtsx_usb_add_cmd(struct rtsx_ucr *ucr, u8 cmd_type, u16 reg_addr,
+ u8 mask, u8 data)
+{
+ int i;
+
+ if (ucr->cmd_idx < (IOBUF_SIZE - CMD_OFFSET) / 4) {
+ i = CMD_OFFSET + ucr->cmd_idx * 4;
+
+ ucr->cmd_buf[i++] = ((cmd_type & 0x03) << 6) |
+ (u8)((reg_addr >> 8) & 0x3F);
+ ucr->cmd_buf[i++] = (u8)reg_addr;
+ ucr->cmd_buf[i++] = mask;
+ ucr->cmd_buf[i++] = data;
+
+ ucr->cmd_idx++;
+ }
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_add_cmd);
+
+int rtsx_usb_send_cmd(struct rtsx_ucr *ucr, u8 flag, int timeout)
+{
+ int ret;
+
+ ucr->cmd_buf[CNT_H] = (u8)(ucr->cmd_idx >> 8);
+ ucr->cmd_buf[CNT_L] = (u8)(ucr->cmd_idx);
+ ucr->cmd_buf[STAGE_FLAG] = flag;
+
+ ret = rtsx_usb_transfer_data(ucr,
+ usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
+ ucr->cmd_buf, ucr->cmd_idx * 4 + CMD_OFFSET,
+ 0, NULL, timeout);
+ if (ret) {
+ rtsx_usb_clear_fsm_err(ucr);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_send_cmd);
+
+int rtsx_usb_get_rsp(struct rtsx_ucr *ucr, int rsp_len, int timeout)
+{
+ if (rsp_len <= 0)
+ return -EINVAL;
+
+ rsp_len = ALIGN(rsp_len, 4);
+
+ return rtsx_usb_transfer_data(ucr,
+ usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN),
+ ucr->rsp_buf, rsp_len, 0, NULL, timeout);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_get_rsp);
+
+static int rtsx_usb_get_status_with_bulk(struct rtsx_ucr *ucr, u16 *status)
+{
+ int ret;
+
+ rtsx_usb_init_cmd(ucr);
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_EXIST, 0x00, 0x00);
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, OCPSTAT, 0x00, 0x00);
+ ret = rtsx_usb_send_cmd(ucr, MODE_CR, 100);
+ if (ret)
+ return ret;
+
+ ret = rtsx_usb_get_rsp(ucr, 2, 100);
+ if (ret)
+ return ret;
+
+ *status = ((ucr->rsp_buf[0] >> 2) & 0x0f) |
+ ((ucr->rsp_buf[1] & 0x03) << 4);
+
+ return 0;
+}
+
+int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status)
+{
+ int ret;
+
+ if (!status)
+ return -EINVAL;
+
+ if (polling_pipe == 0)
+ ret = usb_control_msg(ucr->pusb_dev,
+ usb_rcvctrlpipe(ucr->pusb_dev, 0),
+ RTSX_USB_REQ_POLL,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, 0, status, 2, 100);
+ else
+ ret = rtsx_usb_get_status_with_bulk(ucr, status);
+
+ /* usb_control_msg may return positive when success */
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_get_card_status);
+
+static int rtsx_usb_write_phy_register(struct rtsx_ucr *ucr, u8 addr, u8 val)
+{
+ dev_dbg(&ucr->pusb_intf->dev, "Write 0x%x to phy register 0x%x\n",
+ val, addr);
+
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VSTAIN, 0xFF, val);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VCONTROL, 0xFF, addr & 0x0F);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VCONTROL,
+ 0xFF, (addr >> 4) & 0x0F);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01);
+
+ return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+
+int rtsx_usb_write_register(struct rtsx_ucr *ucr, u16 addr, u8 mask, u8 data)
+{
+ rtsx_usb_init_cmd(ucr);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, addr, mask, data);
+ return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_write_register);
+
+int rtsx_usb_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data)
+{
+ int ret;
+
+ if (data != NULL)
+ *data = 0;
+
+ rtsx_usb_init_cmd(ucr);
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, addr, 0, 0);
+ ret = rtsx_usb_send_cmd(ucr, MODE_CR, 100);
+ if (ret)
+ return ret;
+
+ ret = rtsx_usb_get_rsp(ucr, 1, 100);
+ if (ret)
+ return ret;
+
+ if (data != NULL)
+ *data = ucr->rsp_buf[0];
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_read_register);
+
+static inline u8 double_ssc_depth(u8 depth)
+{
+ return (depth > 1) ? (depth - 1) : depth;
+}
+
+static u8 revise_ssc_depth(u8 ssc_depth, u8 div)
+{
+ if (div > CLK_DIV_1) {
+ if (ssc_depth > div - 1)
+ ssc_depth -= (div - 1);
+ else
+ ssc_depth = SSC_DEPTH_2M;
+ }
+
+ return ssc_depth;
+}
+
+int rtsx_usb_switch_clock(struct rtsx_ucr *ucr, unsigned int card_clock,
+ u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk)
+{
+ int ret;
+ u8 n, clk_divider, mcu_cnt, div;
+
+ if (!card_clock) {
+ ucr->cur_clk = 0;
+ return 0;
+ }
+
+ if (initial_mode) {
+ /* We use 250k(around) here, in initial stage */
+ clk_divider = SD_CLK_DIVIDE_128;
+ card_clock = 30000000;
+ } else {
+ clk_divider = SD_CLK_DIVIDE_0;
+ }
+
+ ret = rtsx_usb_write_register(ucr, SD_CFG1,
+ SD_CLK_DIVIDE_MASK, clk_divider);
+ if (ret < 0)
+ return ret;
+
+ card_clock /= 1000000;
+ dev_dbg(&ucr->pusb_intf->dev,
+ "Switch card clock to %dMHz\n", card_clock);
+
+ if (!initial_mode && double_clk)
+ card_clock *= 2;
+ dev_dbg(&ucr->pusb_intf->dev,
+ "Internal SSC clock: %dMHz (cur_clk = %d)\n",
+ card_clock, ucr->cur_clk);
+
+ if (card_clock == ucr->cur_clk)
+ return 0;
+
+ /* Converting clock value into internal settings: n and div */
+ n = card_clock - 2;
+ if ((card_clock <= 2) || (n > MAX_DIV_N))
+ return -EINVAL;
+
+ mcu_cnt = 60/card_clock + 3;
+ if (mcu_cnt > 15)
+ mcu_cnt = 15;
+
+ /* Make sure that the SSC clock div_n is not less than MIN_DIV_N */
+
+ div = CLK_DIV_1;
+ while (n < MIN_DIV_N && div < CLK_DIV_4) {
+ n = (n + 2) * 2 - 2;
+ div++;
+ }
+ dev_dbg(&ucr->pusb_intf->dev, "n = %d, div = %d\n", n, div);
+
+ if (double_clk)
+ ssc_depth = double_ssc_depth(ssc_depth);
+
+ ssc_depth = revise_ssc_depth(ssc_depth, div);
+ dev_dbg(&ucr->pusb_intf->dev, "ssc_depth = %d\n", ssc_depth);
+
+ rtsx_usb_init_cmd(ucr);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, CLK_CHANGE);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV,
+ 0x3F, (div << 4) | mcu_cnt);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL2,
+ SSC_DEPTH_MASK, ssc_depth);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB);
+ if (vpclk) {
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+ PHASE_NOT_RESET, 0);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+ PHASE_NOT_RESET, PHASE_NOT_RESET);
+ }
+
+ ret = rtsx_usb_send_cmd(ucr, MODE_C, 2000);
+ if (ret < 0)
+ return ret;
+
+ ret = rtsx_usb_write_register(ucr, SSC_CTL1, 0xff,
+ SSC_RSTB | SSC_8X_EN | SSC_SEL_4M);
+ if (ret < 0)
+ return ret;
+
+ /* Wait SSC clock stable */
+ usleep_range(100, 1000);
+
+ ret = rtsx_usb_write_register(ucr, CLK_DIV, CLK_CHANGE, 0);
+ if (ret < 0)
+ return ret;
+
+ ucr->cur_clk = card_clock;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_switch_clock);
+
+int rtsx_usb_card_exclusive_check(struct rtsx_ucr *ucr, int card)
+{
+ int ret;
+ u16 val;
+ u16 cd_mask[] = {
+ [RTSX_USB_SD_CARD] = (CD_MASK & ~SD_CD),
+ [RTSX_USB_MS_CARD] = (CD_MASK & ~MS_CD)
+ };
+
+ ret = rtsx_usb_get_card_status(ucr, &val);
+ /*
+ * If get status fails, return 0 (ok) for the exclusive check
+ * and let the flow fail at somewhere else.
+ */
+ if (ret)
+ return 0;
+
+ if (val & cd_mask[card])
+ return -EIO;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_card_exclusive_check);
+
+static int rtsx_usb_reset_chip(struct rtsx_ucr *ucr)
+{
+ int ret;
+ u8 val;
+
+ rtsx_usb_init_cmd(ucr);
+
+ if (CHECK_PKG(ucr, LQFP48)) {
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
+ LDO3318_PWR_MASK, LDO_SUSPEND);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
+ FORCE_LDO_POWERB, FORCE_LDO_POWERB);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1,
+ 0x30, 0x10);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5,
+ 0x03, 0x01);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6,
+ 0x0C, 0x04);
+ }
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SYS_DUMMY0, NYET_MSAK, NYET_EN);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CD_DEGLITCH_WIDTH, 0xFF, 0x08);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ CD_DEGLITCH_EN, XD_CD_DEGLITCH_EN, 0x0);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD30_DRIVE_SEL,
+ SD30_DRIVE_MASK, DRIVER_TYPE_D);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ CARD_DRIVE_SEL, SD20_DRIVE_MASK, 0x0);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG, 0xE0, 0x0);
+
+ if (ucr->is_rts5179)
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ CARD_PULL_CTL5, 0x03, 0x01);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DMA1_CTL,
+ EXTEND_DMA1_ASYNC_SIGNAL, EXTEND_DMA1_ASYNC_SIGNAL);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_INT_PEND,
+ XD_INT | MS_INT | SD_INT,
+ XD_INT | MS_INT | SD_INT);
+
+ ret = rtsx_usb_send_cmd(ucr, MODE_C, 100);
+ if (ret)
+ return ret;
+
+ /* config non-crystal mode */
+ rtsx_usb_read_register(ucr, CFG_MODE, &val);
+ if ((val & XTAL_FREE) || ((val & CLK_MODE_MASK) == CLK_MODE_NON_XTAL)) {
+ ret = rtsx_usb_write_phy_register(ucr, 0xC2, 0x7C);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rtsx_usb_init_chip(struct rtsx_ucr *ucr)
+{
+ int ret;
+ u8 val;
+
+ rtsx_usb_clear_fsm_err(ucr);
+
+ /* power on SSC */
+ ret = rtsx_usb_write_register(ucr,
+ FPDCTL, SSC_POWER_MASK, SSC_POWER_ON);
+ if (ret)
+ return ret;
+
+ usleep_range(100, 1000);
+ ret = rtsx_usb_write_register(ucr, CLK_DIV, CLK_CHANGE, 0x00);
+ if (ret)
+ return ret;
+
+ /* determine IC version */
+ ret = rtsx_usb_read_register(ucr, HW_VERSION, &val);
+ if (ret)
+ return ret;
+
+ ucr->ic_version = val & HW_VER_MASK;
+
+ /* determine package */
+ ret = rtsx_usb_read_register(ucr, CARD_SHARE_MODE, &val);
+ if (ret)
+ return ret;
+
+ if (val & CARD_SHARE_LQFP_SEL) {
+ ucr->package = LQFP48;
+ dev_dbg(&ucr->pusb_intf->dev, "Package: LQFP48\n");
+ } else {
+ ucr->package = QFN24;
+ dev_dbg(&ucr->pusb_intf->dev, "Package: QFN24\n");
+ }
+
+ /* determine IC variations */
+ rtsx_usb_read_register(ucr, CFG_MODE_1, &val);
+ if (val & RTS5179) {
+ ucr->is_rts5179 = true;
+ dev_dbg(&ucr->pusb_intf->dev, "Device is rts5179\n");
+ } else {
+ ucr->is_rts5179 = false;
+ }
+
+ return rtsx_usb_reset_chip(ucr);
+}
+
+static int rtsx_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(intf);
+ struct rtsx_ucr *ucr;
+ int ret;
+
+ dev_dbg(&intf->dev,
+ ": Realtek USB Card Reader found at bus %03d address %03d\n",
+ usb_dev->bus->busnum, usb_dev->devnum);
+
+ ucr = devm_kzalloc(&intf->dev, sizeof(*ucr), GFP_KERNEL);
+ if (!ucr)
+ return -ENOMEM;
+
+ ucr->pusb_dev = usb_dev;
+
+ ucr->iobuf = usb_alloc_coherent(ucr->pusb_dev, IOBUF_SIZE,
+ GFP_KERNEL, &ucr->iobuf_dma);
+ if (!ucr->iobuf)
+ return -ENOMEM;
+
+ usb_set_intfdata(intf, ucr);
+
+ ucr->vendor_id = id->idVendor;
+ ucr->product_id = id->idProduct;
+ ucr->cmd_buf = ucr->rsp_buf = ucr->iobuf;
+
+ mutex_init(&ucr->dev_mutex);
+
+ ucr->pusb_intf = intf;
+
+ /* initialize */
+ ret = rtsx_usb_init_chip(ucr);
+ if (ret)
+ goto out_init_fail;
+
+ ret = mfd_add_devices(&intf->dev, usb_dev->devnum, rtsx_usb_cells,
+ ARRAY_SIZE(rtsx_usb_cells), NULL, 0, NULL);
+ if (ret)
+ goto out_init_fail;
+
+ /* initialize USB SG transfer timer */
+ init_timer(&ucr->sg_timer);
+ setup_timer(&ucr->sg_timer, rtsx_usb_sg_timed_out, (unsigned long) ucr);
+#ifdef CONFIG_PM
+ intf->needs_remote_wakeup = 1;
+ usb_enable_autosuspend(usb_dev);
+#endif
+
+ return 0;
+
+out_init_fail:
+ usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
+ ucr->iobuf_dma);
+ return ret;
+}
+
+static void rtsx_usb_disconnect(struct usb_interface *intf)
+{
+ struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf);
+
+ dev_dbg(&intf->dev, "%s called\n", __func__);
+
+ mfd_remove_devices(&intf->dev);
+
+ usb_set_intfdata(ucr->pusb_intf, NULL);
+ usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
+ ucr->iobuf_dma);
+}
+
+#ifdef CONFIG_PM
+static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct rtsx_ucr *ucr =
+ (struct rtsx_ucr *)usb_get_intfdata(intf);
+
+ dev_dbg(&intf->dev, "%s called with pm message 0x%04u\n",
+ __func__, message.event);
+
+ mutex_lock(&ucr->dev_mutex);
+ rtsx_usb_turn_off_led(ucr);
+ mutex_unlock(&ucr->dev_mutex);
+ return 0;
+}
+
+static int rtsx_usb_resume(struct usb_interface *intf)
+{
+ return 0;
+}
+
+static int rtsx_usb_reset_resume(struct usb_interface *intf)
+{
+ struct rtsx_ucr *ucr =
+ (struct rtsx_ucr *)usb_get_intfdata(intf);
+
+ rtsx_usb_reset_chip(ucr);
+ return 0;
+}
+
+#else /* CONFIG_PM */
+
+#define rtsx_usb_suspend NULL
+#define rtsx_usb_resume NULL
+#define rtsx_usb_reset_resume NULL
+
+#endif /* CONFIG_PM */
+
+
+static int rtsx_usb_pre_reset(struct usb_interface *intf)
+{
+ struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf);
+
+ mutex_lock(&ucr->dev_mutex);
+ return 0;
+}
+
+static int rtsx_usb_post_reset(struct usb_interface *intf)
+{
+ struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf);
+
+ mutex_unlock(&ucr->dev_mutex);
+ return 0;
+}
+
+static struct usb_device_id rtsx_usb_usb_ids[] = {
+ { USB_DEVICE(0x0BDA, 0x0129) },
+ { USB_DEVICE(0x0BDA, 0x0139) },
+ { USB_DEVICE(0x0BDA, 0x0140) },
+ { }
+};
+
+static struct usb_driver rtsx_usb_driver = {
+ .name = "rtsx_usb",
+ .probe = rtsx_usb_probe,
+ .disconnect = rtsx_usb_disconnect,
+ .suspend = rtsx_usb_suspend,
+ .resume = rtsx_usb_resume,
+ .reset_resume = rtsx_usb_reset_resume,
+ .pre_reset = rtsx_usb_pre_reset,
+ .post_reset = rtsx_usb_post_reset,
+ .id_table = rtsx_usb_usb_ids,
+ .supports_autosuspend = 1,
+ .soft_unbind = 1,
+};
+
+module_usb_driver(rtsx_usb_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Roger Tseng <rogerable@realtek.com>");
+MODULE_DESCRIPTION("Realtek USB Card Reader Driver");
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index 281a8274..1cf2752 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -60,6 +60,7 @@ static const struct mfd_cell s5m8767_devs[] = {
.name = "s5m-rtc",
}, {
.name = "s5m8767-clk",
+ .of_compatible = "samsung,s5m8767-clk",
}
};
@@ -68,6 +69,7 @@ static const struct mfd_cell s2mps11_devs[] = {
.name = "s2mps11-pmic",
}, {
.name = "s2mps11-clk",
+ .of_compatible = "samsung,s2mps11-clk",
}
};
@@ -78,6 +80,7 @@ static const struct mfd_cell s2mps14_devs[] = {
.name = "s2mps14-rtc",
}, {
.name = "s2mps14-clk",
+ .of_compatible = "samsung,s2mps14-clk",
}
};
@@ -295,6 +298,13 @@ static int sec_pmic_probe(struct i2c_client *i2c,
switch (sec_pmic->device_type) {
case S2MPA01:
regmap = &s2mpa01_regmap_config;
+ /*
+ * The rtc-s5m driver does not support S2MPA01 and there
+ * is no mfd_cell for S2MPA01 RTC device.
+ * However we must pass something to devm_regmap_init_i2c()
+ * so use S5M-like regmap config even though it wouldn't work.
+ */
+ regmap_rtc = &s5m_rtc_regmap_config;
break;
case S2MPS11X:
regmap = &s2mps11_regmap_config;
@@ -344,7 +354,7 @@ static int sec_pmic_probe(struct i2c_client *i2c,
ret = PTR_ERR(sec_pmic->regmap_rtc);
dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n",
ret);
- return ret;
+ goto err_regmap_rtc;
}
if (pdata && pdata->cfg_pmic_irq)
@@ -385,14 +395,15 @@ static int sec_pmic_probe(struct i2c_client *i2c,
}
if (ret)
- goto err;
+ goto err_mfd;
device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup);
return ret;
-err:
+err_mfd:
sec_irq_exit(sec_pmic);
+err_regmap_rtc:
i2c_unregister_device(sec_pmic->rtc);
return ret;
}
diff --git a/drivers/mfd/smsc-ece1099.c b/drivers/mfd/smsc-ece1099.c
index 24ae3d8..90112d4 100644
--- a/drivers/mfd/smsc-ece1099.c
+++ b/drivers/mfd/smsc-ece1099.c
@@ -13,7 +13,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index 42ccd05..4a91f67 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -706,7 +706,7 @@ static int stmpe1801_reset(struct stmpe *stmpe)
if (!(ret & STMPE1801_MSK_SYS_CTRL_RESET))
return 0;
usleep_range(100, 200);
- };
+ }
return -EIO;
}
diff --git a/drivers/mfd/stw481x.c b/drivers/mfd/stw481x.c
index 1243d5c..7ceb3df 100644
--- a/drivers/mfd/stw481x.c
+++ b/drivers/mfd/stw481x.c
@@ -167,7 +167,7 @@ static struct mfd_cell stw481x_cells[] = {
},
};
-const struct regmap_config stw481x_regmap_config = {
+static const struct regmap_config stw481x_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
@@ -186,6 +186,12 @@ static int stw481x_probe(struct i2c_client *client,
i2c_set_clientdata(client, stw481x);
stw481x->client = client;
stw481x->map = devm_regmap_init_i2c(client, &stw481x_regmap_config);
+ if (IS_ERR(stw481x->map)) {
+ ret = PTR_ERR(stw481x->map);
+ dev_err(&client->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
ret = stw481x_startup(stw481x);
if (ret) {
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 71841f9..dbea55d 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -69,13 +69,6 @@ EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_compatible);
static int syscon_match_pdevname(struct device *dev, void *data)
{
- struct platform_device *pdev = to_platform_device(dev);
- const struct platform_device_id *id = platform_get_device_id(pdev);
-
- if (id)
- if (!strcmp(id->name, (const char *)data))
- return 1;
-
return !strcmp(dev_name(dev), (const char *)data);
}
@@ -152,7 +145,7 @@ static int syscon_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, syscon);
- dev_info(dev, "regmap %pR registered\n", res);
+ dev_dbg(dev, "regmap %pR registered\n", res);
return 0;
}
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
index 2cf636c..bd83acc 100644
--- a/drivers/mfd/tc3589x.c
+++ b/drivers/mfd/tc3589x.c
@@ -13,8 +13,10 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tc3589x.h>
+#include <linux/err.h>
/**
* enum tc3589x_version - indicates the TC3589x version
@@ -160,7 +162,7 @@ static const struct mfd_cell tc3589x_dev_gpio[] = {
.name = "tc3589x-gpio",
.num_resources = ARRAY_SIZE(gpio_resources),
.resources = &gpio_resources[0],
- .of_compatible = "tc3589x-gpio",
+ .of_compatible = "toshiba,tc3589x-gpio",
},
};
@@ -169,7 +171,7 @@ static const struct mfd_cell tc3589x_dev_keypad[] = {
.name = "tc3589x-keypad",
.num_resources = ARRAY_SIZE(keypad_resources),
.resources = &keypad_resources[0],
- .of_compatible = "tc3589x-keypad",
+ .of_compatible = "toshiba,tc3589x-keypad",
},
};
@@ -318,45 +320,74 @@ static int tc3589x_device_init(struct tc3589x *tc3589x)
return ret;
}
-static int tc3589x_of_probe(struct device_node *np,
- struct tc3589x_platform_data *pdata)
+#ifdef CONFIG_OF
+static const struct of_device_id tc3589x_match[] = {
+ /* Legacy compatible string */
+ { .compatible = "tc3589x", .data = (void *) TC3589X_UNKNOWN },
+ { .compatible = "toshiba,tc35890", .data = (void *) TC3589X_TC35890 },
+ { .compatible = "toshiba,tc35892", .data = (void *) TC3589X_TC35892 },
+ { .compatible = "toshiba,tc35893", .data = (void *) TC3589X_TC35893 },
+ { .compatible = "toshiba,tc35894", .data = (void *) TC3589X_TC35894 },
+ { .compatible = "toshiba,tc35895", .data = (void *) TC3589X_TC35895 },
+ { .compatible = "toshiba,tc35896", .data = (void *) TC3589X_TC35896 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, tc3589x_match);
+
+static struct tc3589x_platform_data *
+tc3589x_of_probe(struct device *dev, enum tc3589x_version *version)
{
+ struct device_node *np = dev->of_node;
+ struct tc3589x_platform_data *pdata;
struct device_node *child;
+ const struct of_device_id *of_id;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ of_id = of_match_device(tc3589x_match, dev);
+ if (!of_id)
+ return ERR_PTR(-ENODEV);
+ *version = (enum tc3589x_version) of_id->data;
for_each_child_of_node(np, child) {
- if (!strcmp(child->name, "tc3589x_gpio")) {
+ if (of_device_is_compatible(child, "toshiba,tc3589x-gpio"))
pdata->block |= TC3589x_BLOCK_GPIO;
- }
- if (!strcmp(child->name, "tc3589x_keypad")) {
+ if (of_device_is_compatible(child, "toshiba,tc3589x-keypad"))
pdata->block |= TC3589x_BLOCK_KEYPAD;
- }
}
- return 0;
+ return pdata;
}
+#else
+static inline struct tc3589x_platform_data *
+tc3589x_of_probe(struct device *dev, enum tc3589x_version *version)
+{
+ dev_err(dev, "no device tree support\n");
+ return ERR_PTR(-ENODEV);
+}
+#endif
static int tc3589x_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
- struct tc3589x_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct device_node *np = i2c->dev.of_node;
+ struct tc3589x_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct tc3589x *tc3589x;
+ enum tc3589x_version version;
int ret;
if (!pdata) {
- if (np) {
- pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- return -ENOMEM;
-
- ret = tc3589x_of_probe(np, pdata);
- if (ret)
- return ret;
- }
- else {
+ pdata = tc3589x_of_probe(&i2c->dev, &version);
+ if (IS_ERR(pdata)) {
dev_err(&i2c->dev, "No platform data or DT found\n");
- return -EINVAL;
+ return PTR_ERR(pdata);
}
+ } else {
+ /* When not probing from device tree we have this ID */
+ version = id->driver_data;
}
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
@@ -375,7 +406,7 @@ static int tc3589x_probe(struct i2c_client *i2c,
tc3589x->pdata = pdata;
tc3589x->irq_base = pdata->irq_base;
- switch (id->driver_data) {
+ switch (version) {
case TC3589X_TC35893:
case TC3589X_TC35895:
case TC3589X_TC35896:
@@ -471,9 +502,12 @@ static const struct i2c_device_id tc3589x_id[] = {
MODULE_DEVICE_TABLE(i2c, tc3589x_id);
static struct i2c_driver tc3589x_driver = {
- .driver.name = "tc3589x",
- .driver.owner = THIS_MODULE,
- .driver.pm = &tc3589x_dev_pm_ops,
+ .driver = {
+ .name = "tc3589x",
+ .owner = THIS_MODULE,
+ .pm = &tc3589x_dev_pm_ops,
+ .of_match_table = of_match_ptr(tc3589x_match),
+ },
.probe = tc3589x_probe,
.remove = tc3589x_remove,
.id_table = tc3589x_id,
diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c
deleted file mode 100644
index a542457..0000000
--- a/drivers/mfd/ti-ssp.c
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * Sequencer Serial Port (SSP) driver for Texas Instruments' SoCs
- *
- * Copyright (C) 2010 Texas Instruments Inc
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/spinlock.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/sched.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/ti_ssp.h>
-
-/* Register Offsets */
-#define REG_REV 0x00
-#define REG_IOSEL_1 0x04
-#define REG_IOSEL_2 0x08
-#define REG_PREDIV 0x0c
-#define REG_INTR_ST 0x10
-#define REG_INTR_EN 0x14
-#define REG_TEST_CTRL 0x18
-
-/* Per port registers */
-#define PORT_CFG_2 0x00
-#define PORT_ADDR 0x04
-#define PORT_DATA 0x08
-#define PORT_CFG_1 0x0c
-#define PORT_STATE 0x10
-
-#define SSP_PORT_CONFIG_MASK (SSP_EARLY_DIN | SSP_DELAY_DOUT)
-#define SSP_PORT_CLKRATE_MASK 0x0f
-
-#define SSP_SEQRAM_WR_EN BIT(4)
-#define SSP_SEQRAM_RD_EN BIT(5)
-#define SSP_START BIT(15)
-#define SSP_BUSY BIT(10)
-#define SSP_PORT_ASL BIT(7)
-#define SSP_PORT_CFO1 BIT(6)
-
-#define SSP_PORT_SEQRAM_SIZE 32
-
-static const int ssp_port_base[] = {0x040, 0x080};
-static const int ssp_port_seqram[] = {0x100, 0x180};
-
-struct ti_ssp {
- struct resource *res;
- struct device *dev;
- void __iomem *regs;
- spinlock_t lock;
- struct clk *clk;
- int irq;
- wait_queue_head_t wqh;
-
- /*
- * Some of the iosel2 register bits always read-back as 0, we need to
- * remember these values so that we don't clobber previously set
- * values.
- */
- u32 iosel2;
-};
-
-static inline struct ti_ssp *dev_to_ssp(struct device *dev)
-{
- return dev_get_drvdata(dev->parent);
-}
-
-static inline int dev_to_port(struct device *dev)
-{
- return to_platform_device(dev)->id;
-}
-
-/* Register Access Helpers, rmw() functions need to run locked */
-static inline u32 ssp_read(struct ti_ssp *ssp, int reg)
-{
- return __raw_readl(ssp->regs + reg);
-}
-
-static inline void ssp_write(struct ti_ssp *ssp, int reg, u32 val)
-{
- __raw_writel(val, ssp->regs + reg);
-}
-
-static inline void ssp_rmw(struct ti_ssp *ssp, int reg, u32 mask, u32 bits)
-{
- ssp_write(ssp, reg, (ssp_read(ssp, reg) & ~mask) | bits);
-}
-
-static inline u32 ssp_port_read(struct ti_ssp *ssp, int port, int reg)
-{
- return ssp_read(ssp, ssp_port_base[port] + reg);
-}
-
-static inline void ssp_port_write(struct ti_ssp *ssp, int port, int reg,
- u32 val)
-{
- ssp_write(ssp, ssp_port_base[port] + reg, val);
-}
-
-static inline void ssp_port_rmw(struct ti_ssp *ssp, int port, int reg,
- u32 mask, u32 bits)
-{
- ssp_rmw(ssp, ssp_port_base[port] + reg, mask, bits);
-}
-
-static inline void ssp_port_clr_bits(struct ti_ssp *ssp, int port, int reg,
- u32 bits)
-{
- ssp_port_rmw(ssp, port, reg, bits, 0);
-}
-
-static inline void ssp_port_set_bits(struct ti_ssp *ssp, int port, int reg,
- u32 bits)
-{
- ssp_port_rmw(ssp, port, reg, 0, bits);
-}
-
-/* Called to setup port clock mode, caller must hold ssp->lock */
-static int __set_mode(struct ti_ssp *ssp, int port, int mode)
-{
- mode &= SSP_PORT_CONFIG_MASK;
- ssp_port_rmw(ssp, port, PORT_CFG_1, SSP_PORT_CONFIG_MASK, mode);
-
- return 0;
-}
-
-int ti_ssp_set_mode(struct device *dev, int mode)
-{
- struct ti_ssp *ssp = dev_to_ssp(dev);
- int port = dev_to_port(dev);
- int ret;
-
- spin_lock(&ssp->lock);
- ret = __set_mode(ssp, port, mode);
- spin_unlock(&ssp->lock);
-
- return ret;
-}
-EXPORT_SYMBOL(ti_ssp_set_mode);
-
-/* Called to setup iosel2, caller must hold ssp->lock */
-static void __set_iosel2(struct ti_ssp *ssp, u32 mask, u32 val)
-{
- ssp->iosel2 = (ssp->iosel2 & ~mask) | val;
- ssp_write(ssp, REG_IOSEL_2, ssp->iosel2);
-}
-
-/* Called to setup port iosel, caller must hold ssp->lock */
-static void __set_iosel(struct ti_ssp *ssp, int port, u32 iosel)
-{
- unsigned val, shift = port ? 16 : 0;
-
- /* IOSEL1 gets the least significant 16 bits */
- val = ssp_read(ssp, REG_IOSEL_1);
- val &= 0xffff << (port ? 0 : 16);
- val |= (iosel & 0xffff) << (port ? 16 : 0);
- ssp_write(ssp, REG_IOSEL_1, val);
-
- /* IOSEL2 gets the most significant 16 bits */
- val = (iosel >> 16) & 0x7;
- __set_iosel2(ssp, 0x7 << shift, val << shift);
-}
-
-int ti_ssp_set_iosel(struct device *dev, u32 iosel)
-{
- struct ti_ssp *ssp = dev_to_ssp(dev);
- int port = dev_to_port(dev);
-
- spin_lock(&ssp->lock);
- __set_iosel(ssp, port, iosel);
- spin_unlock(&ssp->lock);
-
- return 0;
-}
-EXPORT_SYMBOL(ti_ssp_set_iosel);
-
-int ti_ssp_load(struct device *dev, int offs, u32* prog, int len)
-{
- struct ti_ssp *ssp = dev_to_ssp(dev);
- int port = dev_to_port(dev);
- int i;
-
- if (len > SSP_PORT_SEQRAM_SIZE)
- return -ENOSPC;
-
- spin_lock(&ssp->lock);
-
- /* Enable SeqRAM access */
- ssp_port_set_bits(ssp, port, PORT_CFG_2, SSP_SEQRAM_WR_EN);
-
- /* Copy code */
- for (i = 0; i < len; i++) {
- __raw_writel(prog[i], ssp->regs + offs + 4*i +
- ssp_port_seqram[port]);
- }
-
- /* Disable SeqRAM access */
- ssp_port_clr_bits(ssp, port, PORT_CFG_2, SSP_SEQRAM_WR_EN);
-
- spin_unlock(&ssp->lock);
-
- return 0;
-}
-EXPORT_SYMBOL(ti_ssp_load);
-
-int ti_ssp_raw_read(struct device *dev)
-{
- struct ti_ssp *ssp = dev_to_ssp(dev);
- int port = dev_to_port(dev);
- int shift = port ? 27 : 11;
-
- return (ssp_read(ssp, REG_IOSEL_2) >> shift) & 0xf;
-}
-EXPORT_SYMBOL(ti_ssp_raw_read);
-
-int ti_ssp_raw_write(struct device *dev, u32 val)
-{
- struct ti_ssp *ssp = dev_to_ssp(dev);
- int port = dev_to_port(dev), shift;
-
- spin_lock(&ssp->lock);
-
- shift = port ? 22 : 6;
- val &= 0xf;
- __set_iosel2(ssp, 0xf << shift, val << shift);
-
- spin_unlock(&ssp->lock);
-
- return 0;
-}
-EXPORT_SYMBOL(ti_ssp_raw_write);
-
-static inline int __xfer_done(struct ti_ssp *ssp, int port)
-{
- return !(ssp_port_read(ssp, port, PORT_CFG_1) & SSP_BUSY);
-}
-
-int ti_ssp_run(struct device *dev, u32 pc, u32 input, u32 *output)
-{
- struct ti_ssp *ssp = dev_to_ssp(dev);
- int port = dev_to_port(dev);
- int ret;
-
- if (pc & ~(0x3f))
- return -EINVAL;
-
- /* Grab ssp->lock to serialize rmw on ssp registers */
- spin_lock(&ssp->lock);
-
- ssp_port_write(ssp, port, PORT_ADDR, input >> 16);
- ssp_port_write(ssp, port, PORT_DATA, input & 0xffff);
- ssp_port_rmw(ssp, port, PORT_CFG_1, 0x3f, pc);
-
- /* grab wait queue head lock to avoid race with the isr */
- spin_lock_irq(&ssp->wqh.lock);
-
- /* kick off sequence execution in hardware */
- ssp_port_set_bits(ssp, port, PORT_CFG_1, SSP_START);
-
- /* drop ssp lock; no register writes beyond this */
- spin_unlock(&ssp->lock);
-
- ret = wait_event_interruptible_locked_irq(ssp->wqh,
- __xfer_done(ssp, port));
- spin_unlock_irq(&ssp->wqh.lock);
-
- if (ret < 0)
- return ret;
-
- if (output) {
- *output = (ssp_port_read(ssp, port, PORT_ADDR) << 16) |
- (ssp_port_read(ssp, port, PORT_DATA) & 0xffff);
- }
-
- ret = ssp_port_read(ssp, port, PORT_STATE) & 0x3f; /* stop address */
-
- return ret;
-}
-EXPORT_SYMBOL(ti_ssp_run);
-
-static irqreturn_t ti_ssp_interrupt(int irq, void *dev_data)
-{
- struct ti_ssp *ssp = dev_data;
-
- spin_lock(&ssp->wqh.lock);
-
- ssp_write(ssp, REG_INTR_ST, 0x3);
- wake_up_locked(&ssp->wqh);
-
- spin_unlock(&ssp->wqh.lock);
-
- return IRQ_HANDLED;
-}
-
-static int ti_ssp_probe(struct platform_device *pdev)
-{
- static struct ti_ssp *ssp;
- const struct ti_ssp_data *pdata = dev_get_platdata(&pdev->dev);
- int error = 0, prediv = 0xff, id;
- unsigned long sysclk;
- struct device *dev = &pdev->dev;
- struct mfd_cell cells[2];
-
- ssp = kzalloc(sizeof(*ssp), GFP_KERNEL);
- if (!ssp) {
- dev_err(dev, "cannot allocate device info\n");
- return -ENOMEM;
- }
-
- ssp->dev = dev;
- dev_set_drvdata(dev, ssp);
-
- ssp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!ssp->res) {
- error = -ENODEV;
- dev_err(dev, "cannot determine register area\n");
- goto error_res;
- }
-
- if (!request_mem_region(ssp->res->start, resource_size(ssp->res),
- pdev->name)) {
- error = -ENOMEM;
- dev_err(dev, "cannot claim register memory\n");
- goto error_res;
- }
-
- ssp->regs = ioremap(ssp->res->start, resource_size(ssp->res));
- if (!ssp->regs) {
- error = -ENOMEM;
- dev_err(dev, "cannot map register memory\n");
- goto error_map;
- }
-
- ssp->clk = clk_get(dev, NULL);
- if (IS_ERR(ssp->clk)) {
- error = PTR_ERR(ssp->clk);
- dev_err(dev, "cannot claim device clock\n");
- goto error_clk;
- }
-
- ssp->irq = platform_get_irq(pdev, 0);
- if (ssp->irq < 0) {
- error = -ENODEV;
- dev_err(dev, "unknown irq\n");
- goto error_irq;
- }
-
- error = request_threaded_irq(ssp->irq, NULL, ti_ssp_interrupt, 0,
- dev_name(dev), ssp);
- if (error < 0) {
- dev_err(dev, "cannot acquire irq\n");
- goto error_irq;
- }
-
- spin_lock_init(&ssp->lock);
- init_waitqueue_head(&ssp->wqh);
-
- /* Power on and initialize SSP */
- error = clk_enable(ssp->clk);
- if (error) {
- dev_err(dev, "cannot enable device clock\n");
- goto error_enable;
- }
-
- /* Reset registers to a sensible known state */
- ssp_write(ssp, REG_IOSEL_1, 0);
- ssp_write(ssp, REG_IOSEL_2, 0);
- ssp_write(ssp, REG_INTR_EN, 0x3);
- ssp_write(ssp, REG_INTR_ST, 0x3);
- ssp_write(ssp, REG_TEST_CTRL, 0);
- ssp_port_write(ssp, 0, PORT_CFG_1, SSP_PORT_ASL);
- ssp_port_write(ssp, 1, PORT_CFG_1, SSP_PORT_ASL);
- ssp_port_write(ssp, 0, PORT_CFG_2, SSP_PORT_CFO1);
- ssp_port_write(ssp, 1, PORT_CFG_2, SSP_PORT_CFO1);
-
- sysclk = clk_get_rate(ssp->clk);
- if (pdata && pdata->out_clock)
- prediv = (sysclk / pdata->out_clock) - 1;
- prediv = clamp(prediv, 0, 0xff);
- ssp_rmw(ssp, REG_PREDIV, 0xff, prediv);
-
- memset(cells, 0, sizeof(cells));
- for (id = 0; id < 2; id++) {
- const struct ti_ssp_dev_data *data = &pdata->dev_data[id];
-
- cells[id].id = id;
- cells[id].name = data->dev_name;
- cells[id].platform_data = data->pdata;
- }
-
- error = mfd_add_devices(dev, 0, cells, 2, NULL, 0, NULL);
- if (error < 0) {
- dev_err(dev, "cannot add mfd cells\n");
- goto error_enable;
- }
-
- return 0;
-
-error_enable:
- free_irq(ssp->irq, ssp);
-error_irq:
- clk_put(ssp->clk);
-error_clk:
- iounmap(ssp->regs);
-error_map:
- release_mem_region(ssp->res->start, resource_size(ssp->res));
-error_res:
- kfree(ssp);
- return error;
-}
-
-static int ti_ssp_remove(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct ti_ssp *ssp = dev_get_drvdata(dev);
-
- mfd_remove_devices(dev);
- clk_disable(ssp->clk);
- free_irq(ssp->irq, ssp);
- clk_put(ssp->clk);
- iounmap(ssp->regs);
- release_mem_region(ssp->res->start, resource_size(ssp->res));
- kfree(ssp);
- return 0;
-}
-
-static struct platform_driver ti_ssp_driver = {
- .probe = ti_ssp_probe,
- .remove = ti_ssp_remove,
- .driver = {
- .name = "ti-ssp",
- .owner = THIS_MODULE,
- }
-};
-
-module_platform_driver(ti_ssp_driver);
-
-MODULE_DESCRIPTION("Sequencer Serial Port (SSP) Driver");
-MODULE_AUTHOR("Cyril Chemparathy");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:ti-ssp");
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index d4e8604..dd4bf58 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -14,7 +14,6 @@
*/
#include <linux/module.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/io.h>
@@ -184,12 +183,6 @@ static int ti_tscadc_probe(struct platform_device *pdev)
return -EINVAL;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "no memory resource defined.\n");
- return -EINVAL;
- }
-
/* Allocate memory for device */
tscadc = devm_kzalloc(&pdev->dev,
sizeof(struct ti_tscadc_dev), GFP_KERNEL);
@@ -206,19 +199,10 @@ static int ti_tscadc_probe(struct platform_device *pdev)
} else
tscadc->irq = err;
- res = devm_request_mem_region(&pdev->dev,
- res->start, resource_size(res), pdev->name);
- if (!res) {
- dev_err(&pdev->dev, "failed to reserve registers.\n");
- return -EBUSY;
- }
-
- tscadc->tscadc_base = devm_ioremap(&pdev->dev,
- res->start, resource_size(res));
- if (!tscadc->tscadc_base) {
- dev_err(&pdev->dev, "failed to map registers.\n");
- return -ENOMEM;
- }
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(tscadc->tscadc_base))
+ return PTR_ERR(tscadc->tscadc_base);
tscadc->regmap_tscadc = devm_regmap_init_mmio(&pdev->dev,
tscadc->tscadc_base, &tscadc_regmap_config);
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
index 2bc5cfb..6ce36d6 100644
--- a/drivers/mfd/timberdale.c
+++ b/drivers/mfd/timberdale.c
@@ -715,7 +715,7 @@ static int timb_probe(struct pci_dev *dev,
for (i = 0; i < TIMBERDALE_NR_IRQS; i++)
msix_entries[i].entry = i;
- err = pci_enable_msix(dev, msix_entries, TIMBERDALE_NR_IRQS);
+ err = pci_enable_msix_exact(dev, msix_entries, TIMBERDALE_NR_IRQS);
if (err) {
dev_err(&dev->dev,
"MSI-X init failed: %d, expected entries: %d\n",
diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c
new file mode 100644
index 0000000..a74bfb5
--- /dev/null
+++ b/drivers/mfd/tps65218.c
@@ -0,0 +1,282 @@
+/*
+ * Driver for TPS65218 Integrated power management chipsets
+ *
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether expressed or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License version 2 for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps65218.h>
+
+#define TPS65218_PASSWORD_REGS_UNLOCK 0x7D
+
+/**
+ * tps65218_reg_read: Read a single tps65218 register.
+ *
+ * @tps: Device to read from.
+ * @reg: Register to read.
+ * @val: Contians the value
+ */
+int tps65218_reg_read(struct tps65218 *tps, unsigned int reg,
+ unsigned int *val)
+{
+ return regmap_read(tps->regmap, reg, val);
+}
+EXPORT_SYMBOL_GPL(tps65218_reg_read);
+
+/**
+ * tps65218_reg_write: Write a single tps65218 register.
+ *
+ * @tps65218: Device to write to.
+ * @reg: Register to write to.
+ * @val: Value to write.
+ * @level: Password protected level
+ */
+int tps65218_reg_write(struct tps65218 *tps, unsigned int reg,
+ unsigned int val, unsigned int level)
+{
+ int ret;
+ unsigned int xor_reg_val;
+
+ switch (level) {
+ case TPS65218_PROTECT_NONE:
+ return regmap_write(tps->regmap, reg, val);
+ case TPS65218_PROTECT_L1:
+ xor_reg_val = reg ^ TPS65218_PASSWORD_REGS_UNLOCK;
+ ret = regmap_write(tps->regmap, TPS65218_REG_PASSWORD,
+ xor_reg_val);
+ if (ret < 0)
+ return ret;
+
+ return regmap_write(tps->regmap, reg, val);
+ default:
+ return -EINVAL;
+ }
+}
+EXPORT_SYMBOL_GPL(tps65218_reg_write);
+
+/**
+ * tps65218_update_bits: Modify bits w.r.t mask, val and level.
+ *
+ * @tps65218: Device to write to.
+ * @reg: Register to read-write to.
+ * @mask: Mask.
+ * @val: Value to write.
+ * @level: Password protected level
+ */
+static int tps65218_update_bits(struct tps65218 *tps, unsigned int reg,
+ unsigned int mask, unsigned int val, unsigned int level)
+{
+ int ret;
+ unsigned int data;
+
+ ret = tps65218_reg_read(tps, reg, &data);
+ if (ret) {
+ dev_err(tps->dev, "Read from reg 0x%x failed\n", reg);
+ return ret;
+ }
+
+ data &= ~mask;
+ data |= val & mask;
+
+ mutex_lock(&tps->tps_lock);
+ ret = tps65218_reg_write(tps, reg, data, level);
+ if (ret)
+ dev_err(tps->dev, "Write for reg 0x%x failed\n", reg);
+ mutex_unlock(&tps->tps_lock);
+
+ return ret;
+}
+
+int tps65218_set_bits(struct tps65218 *tps, unsigned int reg,
+ unsigned int mask, unsigned int val, unsigned int level)
+{
+ return tps65218_update_bits(tps, reg, mask, val, level);
+}
+EXPORT_SYMBOL_GPL(tps65218_set_bits);
+
+int tps65218_clear_bits(struct tps65218 *tps, unsigned int reg,
+ unsigned int mask, unsigned int level)
+{
+ return tps65218_update_bits(tps, reg, mask, 0, level);
+}
+EXPORT_SYMBOL_GPL(tps65218_clear_bits);
+
+static struct regmap_config tps65218_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static const struct regmap_irq tps65218_irqs[] = {
+ /* INT1 IRQs */
+ [TPS65218_PRGC_IRQ] = {
+ .mask = TPS65218_INT1_PRGC,
+ },
+ [TPS65218_CC_AQC_IRQ] = {
+ .mask = TPS65218_INT1_CC_AQC,
+ },
+ [TPS65218_HOT_IRQ] = {
+ .mask = TPS65218_INT1_HOT,
+ },
+ [TPS65218_PB_IRQ] = {
+ .mask = TPS65218_INT1_PB,
+ },
+ [TPS65218_AC_IRQ] = {
+ .mask = TPS65218_INT1_AC,
+ },
+ [TPS65218_VPRG_IRQ] = {
+ .mask = TPS65218_INT1_VPRG,
+ },
+ [TPS65218_INVALID1_IRQ] = {
+ },
+ [TPS65218_INVALID2_IRQ] = {
+ },
+ /* INT2 IRQs*/
+ [TPS65218_LS1_I_IRQ] = {
+ .mask = TPS65218_INT2_LS1_I,
+ .reg_offset = 1,
+ },
+ [TPS65218_LS2_I_IRQ] = {
+ .mask = TPS65218_INT2_LS2_I,
+ .reg_offset = 1,
+ },
+ [TPS65218_LS3_I_IRQ] = {
+ .mask = TPS65218_INT2_LS3_I,
+ .reg_offset = 1,
+ },
+ [TPS65218_LS1_F_IRQ] = {
+ .mask = TPS65218_INT2_LS1_F,
+ .reg_offset = 1,
+ },
+ [TPS65218_LS2_F_IRQ] = {
+ .mask = TPS65218_INT2_LS2_F,
+ .reg_offset = 1,
+ },
+ [TPS65218_LS3_F_IRQ] = {
+ .mask = TPS65218_INT2_LS3_F,
+ .reg_offset = 1,
+ },
+ [TPS65218_INVALID3_IRQ] = {
+ },
+ [TPS65218_INVALID4_IRQ] = {
+ },
+};
+
+static struct regmap_irq_chip tps65218_irq_chip = {
+ .name = "tps65218",
+ .irqs = tps65218_irqs,
+ .num_irqs = ARRAY_SIZE(tps65218_irqs),
+
+ .num_regs = 2,
+ .mask_base = TPS65218_REG_INT_MASK1,
+};
+
+static const struct of_device_id of_tps65218_match_table[] = {
+ { .compatible = "ti,tps65218", },
+};
+
+static int tps65218_probe(struct i2c_client *client,
+ const struct i2c_device_id *ids)
+{
+ struct tps65218 *tps;
+ const struct of_device_id *match;
+ int ret;
+
+ match = of_match_device(of_tps65218_match_table, &client->dev);
+ if (!match) {
+ dev_err(&client->dev,
+ "Failed to find matching dt id\n");
+ return -EINVAL;
+ }
+
+ tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+ if (!tps)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, tps);
+ tps->dev = &client->dev;
+ tps->irq = client->irq;
+ tps->regmap = devm_regmap_init_i2c(client, &tps65218_regmap_config);
+ if (IS_ERR(tps->regmap)) {
+ ret = PTR_ERR(tps->regmap);
+ dev_err(tps->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ mutex_init(&tps->tps_lock);
+
+ ret = regmap_add_irq_chip(tps->regmap, tps->irq,
+ IRQF_ONESHOT, 0, &tps65218_irq_chip,
+ &tps->irq_data);
+ if (ret < 0)
+ return ret;
+
+ ret = of_platform_populate(client->dev.of_node, NULL, NULL,
+ &client->dev);
+ if (ret < 0)
+ goto err_irq;
+
+ return 0;
+
+err_irq:
+ regmap_del_irq_chip(tps->irq, tps->irq_data);
+
+ return ret;
+}
+
+static int tps65218_remove(struct i2c_client *client)
+{
+ struct tps65218 *tps = i2c_get_clientdata(client);
+
+ regmap_del_irq_chip(tps->irq, tps->irq_data);
+
+ return 0;
+}
+
+static const struct i2c_device_id tps65218_id_table[] = {
+ { "tps65218", TPS65218 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, tps65218_id_table);
+
+static struct i2c_driver tps65218_driver = {
+ .driver = {
+ .name = "tps65218",
+ .owner = THIS_MODULE,
+ .of_match_table = of_tps65218_match_table,
+ },
+ .probe = tps65218_probe,
+ .remove = tps65218_remove,
+ .id_table = tps65218_id_table,
+};
+
+module_i2c_driver(tps65218_driver);
+
+MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
+MODULE_DESCRIPTION("TPS65218 chip family multi-function driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index 1f142d7..460a014 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -255,8 +255,10 @@ static int tps65910_irq_init(struct tps65910 *tps65910, int irq,
ret = regmap_add_irq_chip(tps65910->regmap, tps65910->chip_irq,
IRQF_ONESHOT, pdata->irq_base,
tps6591x_irqs_chip, &tps65910->irq_data);
- if (ret < 0)
+ if (ret < 0) {
dev_warn(tps65910->dev, "Failed to add irq_chip %d\n", ret);
+ tps65910->chip_irq = 0;
+ }
return ret;
}
@@ -509,6 +511,7 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
regmap_irq_get_domain(tps65910->irq_data));
if (ret < 0) {
dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret);
+ tps65910_irq_exit(tps65910);
return ret;
}
diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c
index 27a518e..1f82d60 100644
--- a/drivers/mfd/tps65912-core.c
+++ b/drivers/mfd/tps65912-core.c
@@ -15,7 +15,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/mfd/core.h>
diff --git a/drivers/mfd/tps65912-irq.c b/drivers/mfd/tps65912-irq.c
index d360a83..fbecec7 100644
--- a/drivers/mfd/tps65912-irq.c
+++ b/drivers/mfd/tps65912-irq.c
@@ -15,7 +15,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/init.h>
#include <linux/bug.h>
#include <linux/device.h>
#include <linux/interrupt.h>
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index ed71832..e87140b 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -282,11 +282,11 @@ static struct reg_default twl4030_49_defaults[] = {
static bool twl4030_49_nop_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
- case 0:
- case 3:
- case 40:
- case 41:
- case 42:
+ case 0x00:
+ case 0x03:
+ case 0x40:
+ case 0x41:
+ case 0x42:
return false;
default:
return true;
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index 9aa6d1e..596b1f6 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -27,7 +27,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/init.h>
#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index 18a607e..a6bb17d 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -31,7 +31,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/init.h>
#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c
index 75316fb..6e88f25 100644
--- a/drivers/mfd/twl6040.c
+++ b/drivers/mfd/twl6040.c
@@ -661,6 +661,11 @@ static int twl6040_probe(struct i2c_client *client,
init_completion(&twl6040->ready);
twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
+ if (twl6040->rev < 0) {
+ dev_err(&client->dev, "Failed to read revision register: %d\n",
+ twl6040->rev);
+ goto gpio_err;
+ }
/* ERRATA: Automatic power-up is not possible in ES1.0 */
if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0)
@@ -703,7 +708,6 @@ static int twl6040_probe(struct i2c_client *client,
}
/* dual-access registers controlled by I2C only */
- twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL);
regmap_register_patch(twl6040->regmap, twl6040_patch,
ARRAY_SIZE(twl6040_patch));
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index 0313f83..153d595 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -742,9 +742,7 @@ static int ucb1x00_resume(struct device *dev)
}
#endif
-static const struct dev_pm_ops ucb1x00_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(ucb1x00_suspend, ucb1x00_resume)
-};
+static SIMPLE_DEV_PM_OPS(ucb1x00_pm_ops, ucb1x00_suspend, ucb1x00_resume);
static struct mcp_driver ucb1x00_driver = {
.drv = {
diff --git a/drivers/mfd/vexpress-config.c b/drivers/mfd/vexpress-config.c
index 84ce6b9..d0db89d 100644
--- a/drivers/mfd/vexpress-config.c
+++ b/drivers/mfd/vexpress-config.c
@@ -16,7 +16,6 @@
#include <linux/bitops.h>
#include <linux/completion.h>
#include <linux/export.h>
-#include <linux/init.h>
#include <linux/list.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -27,7 +26,7 @@
#define VEXPRESS_CONFIG_MAX_BRIDGES 2
-struct vexpress_config_bridge {
+static struct vexpress_config_bridge {
struct device_node *node;
struct vexpress_config_bridge_info *info;
struct list_head transactions;
diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c
index 981bef4..35281e8 100644
--- a/drivers/mfd/vexpress-sysreg.c
+++ b/drivers/mfd/vexpress-sysreg.c
@@ -168,7 +168,7 @@ static void *vexpress_sysreg_config_func_get(struct device *dev,
struct device_node *node)
{
struct vexpress_sysreg_config_func *config_func;
- u32 site;
+ u32 site = 0;
u32 position = 0;
u32 dcc = 0;
u32 func_device[2];
diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c
index bffc584..070f8cf 100644
--- a/drivers/mfd/wm5102-tables.c
+++ b/drivers/mfd/wm5102-tables.c
@@ -73,6 +73,7 @@ static const struct reg_default wm5102_revb_patch[] = {
{ 0x171, 0x0000 },
{ 0x35E, 0x000C },
{ 0x2D4, 0x0000 },
+ { 0x4DC, 0x0900 },
{ 0x80, 0x0000 },
};
@@ -1839,6 +1840,23 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_DSP1_STATUS_1:
case ARIZONA_DSP1_STATUS_2:
case ARIZONA_DSP1_STATUS_3:
+ case ARIZONA_DSP1_WDMA_BUFFER_1:
+ case ARIZONA_DSP1_WDMA_BUFFER_2:
+ case ARIZONA_DSP1_WDMA_BUFFER_3:
+ case ARIZONA_DSP1_WDMA_BUFFER_4:
+ case ARIZONA_DSP1_WDMA_BUFFER_5:
+ case ARIZONA_DSP1_WDMA_BUFFER_6:
+ case ARIZONA_DSP1_WDMA_BUFFER_7:
+ case ARIZONA_DSP1_WDMA_BUFFER_8:
+ case ARIZONA_DSP1_RDMA_BUFFER_1:
+ case ARIZONA_DSP1_RDMA_BUFFER_2:
+ case ARIZONA_DSP1_RDMA_BUFFER_3:
+ case ARIZONA_DSP1_RDMA_BUFFER_4:
+ case ARIZONA_DSP1_RDMA_BUFFER_5:
+ case ARIZONA_DSP1_RDMA_BUFFER_6:
+ case ARIZONA_DSP1_WDMA_CONFIG_1:
+ case ARIZONA_DSP1_WDMA_CONFIG_2:
+ case ARIZONA_DSP1_RDMA_CONFIG_1:
case ARIZONA_DSP1_SCRATCH_0:
case ARIZONA_DSP1_SCRATCH_1:
case ARIZONA_DSP1_SCRATCH_2:
@@ -1894,9 +1912,27 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg)
case ARIZONA_AOD_IRQ1:
case ARIZONA_AOD_IRQ2:
case ARIZONA_AOD_IRQ_RAW_STATUS:
+ case ARIZONA_DSP1_CLOCKING_1:
case ARIZONA_DSP1_STATUS_1:
case ARIZONA_DSP1_STATUS_2:
case ARIZONA_DSP1_STATUS_3:
+ case ARIZONA_DSP1_WDMA_BUFFER_1:
+ case ARIZONA_DSP1_WDMA_BUFFER_2:
+ case ARIZONA_DSP1_WDMA_BUFFER_3:
+ case ARIZONA_DSP1_WDMA_BUFFER_4:
+ case ARIZONA_DSP1_WDMA_BUFFER_5:
+ case ARIZONA_DSP1_WDMA_BUFFER_6:
+ case ARIZONA_DSP1_WDMA_BUFFER_7:
+ case ARIZONA_DSP1_WDMA_BUFFER_8:
+ case ARIZONA_DSP1_RDMA_BUFFER_1:
+ case ARIZONA_DSP1_RDMA_BUFFER_2:
+ case ARIZONA_DSP1_RDMA_BUFFER_3:
+ case ARIZONA_DSP1_RDMA_BUFFER_4:
+ case ARIZONA_DSP1_RDMA_BUFFER_5:
+ case ARIZONA_DSP1_RDMA_BUFFER_6:
+ case ARIZONA_DSP1_WDMA_CONFIG_1:
+ case ARIZONA_DSP1_WDMA_CONFIG_2:
+ case ARIZONA_DSP1_RDMA_CONFIG_1:
case ARIZONA_DSP1_SCRATCH_0:
case ARIZONA_DSP1_SCRATCH_1:
case ARIZONA_DSP1_SCRATCH_2:
diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c
index 11632f1..1942b6f 100644
--- a/drivers/mfd/wm5110-tables.c
+++ b/drivers/mfd/wm5110-tables.c
@@ -538,7 +538,7 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x00000219, 0x01A6 }, /* R537 - Mic Bias Ctrl 2 */
{ 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */
{ 0x00000293, 0x0000 }, /* R659 - Accessory Detect Mode 1 */
- { 0x0000029B, 0x0020 }, /* R667 - Headphone Detect 1 */
+ { 0x0000029B, 0x0028 }, /* R667 - Headphone Detect 1 */
{ 0x0000029C, 0x0000 }, /* R668 - Headphone Detect 2 */
{ 0x000002A2, 0x0000 }, /* R674 - Micd clamp control */
{ 0x000002A3, 0x1102 }, /* R675 - Mic Detect 1 */
@@ -2461,6 +2461,27 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_DSP1_STATUS_1:
case ARIZONA_DSP1_STATUS_2:
case ARIZONA_DSP1_STATUS_3:
+ case ARIZONA_DSP1_STATUS_4:
+ case ARIZONA_DSP1_WDMA_BUFFER_1:
+ case ARIZONA_DSP1_WDMA_BUFFER_2:
+ case ARIZONA_DSP1_WDMA_BUFFER_3:
+ case ARIZONA_DSP1_WDMA_BUFFER_4:
+ case ARIZONA_DSP1_WDMA_BUFFER_5:
+ case ARIZONA_DSP1_WDMA_BUFFER_6:
+ case ARIZONA_DSP1_WDMA_BUFFER_7:
+ case ARIZONA_DSP1_WDMA_BUFFER_8:
+ case ARIZONA_DSP1_RDMA_BUFFER_1:
+ case ARIZONA_DSP1_RDMA_BUFFER_2:
+ case ARIZONA_DSP1_RDMA_BUFFER_3:
+ case ARIZONA_DSP1_RDMA_BUFFER_4:
+ case ARIZONA_DSP1_RDMA_BUFFER_5:
+ case ARIZONA_DSP1_RDMA_BUFFER_6:
+ case ARIZONA_DSP1_WDMA_CONFIG_1:
+ case ARIZONA_DSP1_WDMA_CONFIG_2:
+ case ARIZONA_DSP1_WDMA_OFFSET_1:
+ case ARIZONA_DSP1_RDMA_CONFIG_1:
+ case ARIZONA_DSP1_RDMA_OFFSET_1:
+ case ARIZONA_DSP1_EXTERNAL_START_SELECT_1:
case ARIZONA_DSP1_SCRATCH_0:
case ARIZONA_DSP1_SCRATCH_1:
case ARIZONA_DSP1_SCRATCH_2:
@@ -2470,6 +2491,27 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_DSP2_STATUS_1:
case ARIZONA_DSP2_STATUS_2:
case ARIZONA_DSP2_STATUS_3:
+ case ARIZONA_DSP2_STATUS_4:
+ case ARIZONA_DSP2_WDMA_BUFFER_1:
+ case ARIZONA_DSP2_WDMA_BUFFER_2:
+ case ARIZONA_DSP2_WDMA_BUFFER_3:
+ case ARIZONA_DSP2_WDMA_BUFFER_4:
+ case ARIZONA_DSP2_WDMA_BUFFER_5:
+ case ARIZONA_DSP2_WDMA_BUFFER_6:
+ case ARIZONA_DSP2_WDMA_BUFFER_7:
+ case ARIZONA_DSP2_WDMA_BUFFER_8:
+ case ARIZONA_DSP2_RDMA_BUFFER_1:
+ case ARIZONA_DSP2_RDMA_BUFFER_2:
+ case ARIZONA_DSP2_RDMA_BUFFER_3:
+ case ARIZONA_DSP2_RDMA_BUFFER_4:
+ case ARIZONA_DSP2_RDMA_BUFFER_5:
+ case ARIZONA_DSP2_RDMA_BUFFER_6:
+ case ARIZONA_DSP2_WDMA_CONFIG_1:
+ case ARIZONA_DSP2_WDMA_CONFIG_2:
+ case ARIZONA_DSP2_WDMA_OFFSET_1:
+ case ARIZONA_DSP2_RDMA_CONFIG_1:
+ case ARIZONA_DSP2_RDMA_OFFSET_1:
+ case ARIZONA_DSP2_EXTERNAL_START_SELECT_1:
case ARIZONA_DSP2_SCRATCH_0:
case ARIZONA_DSP2_SCRATCH_1:
case ARIZONA_DSP2_SCRATCH_2:
@@ -2479,6 +2521,27 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_DSP3_STATUS_1:
case ARIZONA_DSP3_STATUS_2:
case ARIZONA_DSP3_STATUS_3:
+ case ARIZONA_DSP3_STATUS_4:
+ case ARIZONA_DSP3_WDMA_BUFFER_1:
+ case ARIZONA_DSP3_WDMA_BUFFER_2:
+ case ARIZONA_DSP3_WDMA_BUFFER_3:
+ case ARIZONA_DSP3_WDMA_BUFFER_4:
+ case ARIZONA_DSP3_WDMA_BUFFER_5:
+ case ARIZONA_DSP3_WDMA_BUFFER_6:
+ case ARIZONA_DSP3_WDMA_BUFFER_7:
+ case ARIZONA_DSP3_WDMA_BUFFER_8:
+ case ARIZONA_DSP3_RDMA_BUFFER_1:
+ case ARIZONA_DSP3_RDMA_BUFFER_2:
+ case ARIZONA_DSP3_RDMA_BUFFER_3:
+ case ARIZONA_DSP3_RDMA_BUFFER_4:
+ case ARIZONA_DSP3_RDMA_BUFFER_5:
+ case ARIZONA_DSP3_RDMA_BUFFER_6:
+ case ARIZONA_DSP3_WDMA_CONFIG_1:
+ case ARIZONA_DSP3_WDMA_CONFIG_2:
+ case ARIZONA_DSP3_WDMA_OFFSET_1:
+ case ARIZONA_DSP3_RDMA_CONFIG_1:
+ case ARIZONA_DSP3_RDMA_OFFSET_1:
+ case ARIZONA_DSP3_EXTERNAL_START_SELECT_1:
case ARIZONA_DSP3_SCRATCH_0:
case ARIZONA_DSP3_SCRATCH_1:
case ARIZONA_DSP3_SCRATCH_2:
@@ -2488,6 +2551,27 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_DSP4_STATUS_1:
case ARIZONA_DSP4_STATUS_2:
case ARIZONA_DSP4_STATUS_3:
+ case ARIZONA_DSP4_STATUS_4:
+ case ARIZONA_DSP4_WDMA_BUFFER_1:
+ case ARIZONA_DSP4_WDMA_BUFFER_2:
+ case ARIZONA_DSP4_WDMA_BUFFER_3:
+ case ARIZONA_DSP4_WDMA_BUFFER_4:
+ case ARIZONA_DSP4_WDMA_BUFFER_5:
+ case ARIZONA_DSP4_WDMA_BUFFER_6:
+ case ARIZONA_DSP4_WDMA_BUFFER_7:
+ case ARIZONA_DSP4_WDMA_BUFFER_8:
+ case ARIZONA_DSP4_RDMA_BUFFER_1:
+ case ARIZONA_DSP4_RDMA_BUFFER_2:
+ case ARIZONA_DSP4_RDMA_BUFFER_3:
+ case ARIZONA_DSP4_RDMA_BUFFER_4:
+ case ARIZONA_DSP4_RDMA_BUFFER_5:
+ case ARIZONA_DSP4_RDMA_BUFFER_6:
+ case ARIZONA_DSP4_WDMA_CONFIG_1:
+ case ARIZONA_DSP4_WDMA_CONFIG_2:
+ case ARIZONA_DSP4_WDMA_OFFSET_1:
+ case ARIZONA_DSP4_RDMA_CONFIG_1:
+ case ARIZONA_DSP4_RDMA_OFFSET_1:
+ case ARIZONA_DSP4_EXTERNAL_START_SELECT_1:
case ARIZONA_DSP4_SCRATCH_0:
case ARIZONA_DSP4_SCRATCH_1:
case ARIZONA_DSP4_SCRATCH_2:
@@ -2543,31 +2627,119 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
case ARIZONA_DSP1_STATUS_1:
case ARIZONA_DSP1_STATUS_2:
case ARIZONA_DSP1_STATUS_3:
+ case ARIZONA_DSP1_STATUS_4:
+ case ARIZONA_DSP1_WDMA_BUFFER_1:
+ case ARIZONA_DSP1_WDMA_BUFFER_2:
+ case ARIZONA_DSP1_WDMA_BUFFER_3:
+ case ARIZONA_DSP1_WDMA_BUFFER_4:
+ case ARIZONA_DSP1_WDMA_BUFFER_5:
+ case ARIZONA_DSP1_WDMA_BUFFER_6:
+ case ARIZONA_DSP1_WDMA_BUFFER_7:
+ case ARIZONA_DSP1_WDMA_BUFFER_8:
+ case ARIZONA_DSP1_RDMA_BUFFER_1:
+ case ARIZONA_DSP1_RDMA_BUFFER_2:
+ case ARIZONA_DSP1_RDMA_BUFFER_3:
+ case ARIZONA_DSP1_RDMA_BUFFER_4:
+ case ARIZONA_DSP1_RDMA_BUFFER_5:
+ case ARIZONA_DSP1_RDMA_BUFFER_6:
+ case ARIZONA_DSP1_WDMA_CONFIG_1:
+ case ARIZONA_DSP1_WDMA_CONFIG_2:
+ case ARIZONA_DSP1_WDMA_OFFSET_1:
+ case ARIZONA_DSP1_RDMA_CONFIG_1:
+ case ARIZONA_DSP1_RDMA_OFFSET_1:
+ case ARIZONA_DSP1_EXTERNAL_START_SELECT_1:
case ARIZONA_DSP1_SCRATCH_0:
case ARIZONA_DSP1_SCRATCH_1:
case ARIZONA_DSP1_SCRATCH_2:
case ARIZONA_DSP1_SCRATCH_3:
+ case ARIZONA_DSP1_CLOCKING_1:
case ARIZONA_DSP2_STATUS_1:
case ARIZONA_DSP2_STATUS_2:
case ARIZONA_DSP2_STATUS_3:
+ case ARIZONA_DSP2_STATUS_4:
+ case ARIZONA_DSP2_WDMA_BUFFER_1:
+ case ARIZONA_DSP2_WDMA_BUFFER_2:
+ case ARIZONA_DSP2_WDMA_BUFFER_3:
+ case ARIZONA_DSP2_WDMA_BUFFER_4:
+ case ARIZONA_DSP2_WDMA_BUFFER_5:
+ case ARIZONA_DSP2_WDMA_BUFFER_6:
+ case ARIZONA_DSP2_WDMA_BUFFER_7:
+ case ARIZONA_DSP2_WDMA_BUFFER_8:
+ case ARIZONA_DSP2_RDMA_BUFFER_1:
+ case ARIZONA_DSP2_RDMA_BUFFER_2:
+ case ARIZONA_DSP2_RDMA_BUFFER_3:
+ case ARIZONA_DSP2_RDMA_BUFFER_4:
+ case ARIZONA_DSP2_RDMA_BUFFER_5:
+ case ARIZONA_DSP2_RDMA_BUFFER_6:
+ case ARIZONA_DSP2_WDMA_CONFIG_1:
+ case ARIZONA_DSP2_WDMA_CONFIG_2:
+ case ARIZONA_DSP2_WDMA_OFFSET_1:
+ case ARIZONA_DSP2_RDMA_CONFIG_1:
+ case ARIZONA_DSP2_RDMA_OFFSET_1:
+ case ARIZONA_DSP2_EXTERNAL_START_SELECT_1:
case ARIZONA_DSP2_SCRATCH_0:
case ARIZONA_DSP2_SCRATCH_1:
case ARIZONA_DSP2_SCRATCH_2:
case ARIZONA_DSP2_SCRATCH_3:
+ case ARIZONA_DSP2_CLOCKING_1:
case ARIZONA_DSP3_STATUS_1:
case ARIZONA_DSP3_STATUS_2:
case ARIZONA_DSP3_STATUS_3:
+ case ARIZONA_DSP3_STATUS_4:
+ case ARIZONA_DSP3_WDMA_BUFFER_1:
+ case ARIZONA_DSP3_WDMA_BUFFER_2:
+ case ARIZONA_DSP3_WDMA_BUFFER_3:
+ case ARIZONA_DSP3_WDMA_BUFFER_4:
+ case ARIZONA_DSP3_WDMA_BUFFER_5:
+ case ARIZONA_DSP3_WDMA_BUFFER_6:
+ case ARIZONA_DSP3_WDMA_BUFFER_7:
+ case ARIZONA_DSP3_WDMA_BUFFER_8:
+ case ARIZONA_DSP3_RDMA_BUFFER_1:
+ case ARIZONA_DSP3_RDMA_BUFFER_2:
+ case ARIZONA_DSP3_RDMA_BUFFER_3:
+ case ARIZONA_DSP3_RDMA_BUFFER_4:
+ case ARIZONA_DSP3_RDMA_BUFFER_5:
+ case ARIZONA_DSP3_RDMA_BUFFER_6:
+ case ARIZONA_DSP3_WDMA_CONFIG_1:
+ case ARIZONA_DSP3_WDMA_CONFIG_2:
+ case ARIZONA_DSP3_WDMA_OFFSET_1:
+ case ARIZONA_DSP3_RDMA_CONFIG_1:
+ case ARIZONA_DSP3_RDMA_OFFSET_1:
+ case ARIZONA_DSP3_EXTERNAL_START_SELECT_1:
case ARIZONA_DSP3_SCRATCH_0:
case ARIZONA_DSP3_SCRATCH_1:
case ARIZONA_DSP3_SCRATCH_2:
case ARIZONA_DSP3_SCRATCH_3:
+ case ARIZONA_DSP3_CLOCKING_1:
case ARIZONA_DSP4_STATUS_1:
case ARIZONA_DSP4_STATUS_2:
case ARIZONA_DSP4_STATUS_3:
+ case ARIZONA_DSP4_STATUS_4:
+ case ARIZONA_DSP4_WDMA_BUFFER_1:
+ case ARIZONA_DSP4_WDMA_BUFFER_2:
+ case ARIZONA_DSP4_WDMA_BUFFER_3:
+ case ARIZONA_DSP4_WDMA_BUFFER_4:
+ case ARIZONA_DSP4_WDMA_BUFFER_5:
+ case ARIZONA_DSP4_WDMA_BUFFER_6:
+ case ARIZONA_DSP4_WDMA_BUFFER_7:
+ case ARIZONA_DSP4_WDMA_BUFFER_8:
+ case ARIZONA_DSP4_RDMA_BUFFER_1:
+ case ARIZONA_DSP4_RDMA_BUFFER_2:
+ case ARIZONA_DSP4_RDMA_BUFFER_3:
+ case ARIZONA_DSP4_RDMA_BUFFER_4:
+ case ARIZONA_DSP4_RDMA_BUFFER_5:
+ case ARIZONA_DSP4_RDMA_BUFFER_6:
+ case ARIZONA_DSP4_WDMA_CONFIG_1:
+ case ARIZONA_DSP4_WDMA_CONFIG_2:
+ case ARIZONA_DSP4_WDMA_OFFSET_1:
+ case ARIZONA_DSP4_RDMA_CONFIG_1:
+ case ARIZONA_DSP4_RDMA_OFFSET_1:
+ case ARIZONA_DSP4_EXTERNAL_START_SELECT_1:
case ARIZONA_DSP4_SCRATCH_0:
case ARIZONA_DSP4_SCRATCH_1:
case ARIZONA_DSP4_SCRATCH_2:
case ARIZONA_DSP4_SCRATCH_3:
+ case ARIZONA_DSP4_CLOCKING_1:
return true;
default:
return wm5110_is_adsp_memory(dev, reg);
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
index 7c1ae24..4ab527f 100644
--- a/drivers/mfd/wm8350-core.c
+++ b/drivers/mfd/wm8350-core.c
@@ -14,7 +14,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/bug.h>
#include <linux/device.h>
diff --git a/drivers/mfd/wm8350-irq.c b/drivers/mfd/wm8350-irq.c
index 624ff90..cd01f79 100644
--- a/drivers/mfd/wm8350-irq.c
+++ b/drivers/mfd/wm8350-irq.c
@@ -14,7 +14,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/init.h>
#include <linux/bug.h>
#include <linux/device.h>
#include <linux/interrupt.h>
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
index d66d256..e5eae75 100644
--- a/drivers/mfd/wm8400-core.c
+++ b/drivers/mfd/wm8400-core.c
@@ -161,31 +161,19 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8400 *wm8400;
- int ret;
wm8400 = devm_kzalloc(&i2c->dev, sizeof(struct wm8400), GFP_KERNEL);
- if (wm8400 == NULL) {
- ret = -ENOMEM;
- goto err;
- }
+ if (!wm8400)
+ return -ENOMEM;
wm8400->regmap = devm_regmap_init_i2c(i2c, &wm8400_regmap_config);
- if (IS_ERR(wm8400->regmap)) {
- ret = PTR_ERR(wm8400->regmap);
- goto err;
- }
+ if (IS_ERR(wm8400->regmap))
+ return PTR_ERR(wm8400->regmap);
wm8400->dev = &i2c->dev;
i2c_set_clientdata(i2c, wm8400);
- ret = wm8400_init(wm8400, dev_get_platdata(&i2c->dev));
- if (ret != 0)
- goto err;
-
- return 0;
-
-err:
- return ret;
+ return wm8400_init(wm8400, dev_get_platdata(&i2c->dev));
}
static int wm8400_i2c_remove(struct i2c_client *i2c)
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 0e6c033..0ba1b7c 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -48,7 +48,7 @@
/* Module and version information */
#define DRV_NAME "iTCO_wdt"
-#define DRV_VERSION "1.10"
+#define DRV_VERSION "1.11"
/* Includes */
#include <linux/module.h> /* For module specific items */
@@ -92,9 +92,12 @@ static struct { /* this is private data for the iTCO_wdt device */
unsigned int iTCO_version;
struct resource *tco_res;
struct resource *smi_res;
- struct resource *gcs_res;
- /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/
- unsigned long __iomem *gcs;
+ /*
+ * NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2),
+ * or memory-mapped PMC register bit 4 (TCO version 3).
+ */
+ struct resource *gcs_pmc_res;
+ unsigned long __iomem *gcs_pmc;
/* the lock for io operations */
spinlock_t io_lock;
struct platform_device *dev;
@@ -125,11 +128,19 @@ MODULE_PARM_DESC(turn_SMI_watchdog_clear_off,
* Some TCO specific functions
*/
-static inline unsigned int seconds_to_ticks(int seconds)
+/*
+ * The iTCO v1 and v2's internal timer is stored as ticks which decrement
+ * every 0.6 seconds. v3's internal timer is stored as seconds (some
+ * datasheets incorrectly state 0.6 seconds).
+ */
+static inline unsigned int seconds_to_ticks(int secs)
{
- /* the internal timer is stored as ticks which decrement
- * every 0.6 seconds */
- return (seconds * 10) / 6;
+ return iTCO_wdt_private.iTCO_version == 3 ? secs : (secs * 10) / 6;
+}
+
+static inline unsigned int ticks_to_seconds(int ticks)
+{
+ return iTCO_wdt_private.iTCO_version == 3 ? ticks : (ticks * 6) / 10;
}
static void iTCO_wdt_set_NO_REBOOT_bit(void)
@@ -137,10 +148,14 @@ static void iTCO_wdt_set_NO_REBOOT_bit(void)
u32 val32;
/* Set the NO_REBOOT bit: this disables reboots */
- if (iTCO_wdt_private.iTCO_version == 2) {
- val32 = readl(iTCO_wdt_private.gcs);
+ if (iTCO_wdt_private.iTCO_version == 3) {
+ val32 = readl(iTCO_wdt_private.gcs_pmc);
+ val32 |= 0x00000010;
+ writel(val32, iTCO_wdt_private.gcs_pmc);
+ } else if (iTCO_wdt_private.iTCO_version == 2) {
+ val32 = readl(iTCO_wdt_private.gcs_pmc);
val32 |= 0x00000020;
- writel(val32, iTCO_wdt_private.gcs);
+ writel(val32, iTCO_wdt_private.gcs_pmc);
} else if (iTCO_wdt_private.iTCO_version == 1) {
pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
val32 |= 0x00000002;
@@ -154,12 +169,20 @@ static int iTCO_wdt_unset_NO_REBOOT_bit(void)
u32 val32;
/* Unset the NO_REBOOT bit: this enables reboots */
- if (iTCO_wdt_private.iTCO_version == 2) {
- val32 = readl(iTCO_wdt_private.gcs);
+ if (iTCO_wdt_private.iTCO_version == 3) {
+ val32 = readl(iTCO_wdt_private.gcs_pmc);
+ val32 &= 0xffffffef;
+ writel(val32, iTCO_wdt_private.gcs_pmc);
+
+ val32 = readl(iTCO_wdt_private.gcs_pmc);
+ if (val32 & 0x00000010)
+ ret = -EIO;
+ } else if (iTCO_wdt_private.iTCO_version == 2) {
+ val32 = readl(iTCO_wdt_private.gcs_pmc);
val32 &= 0xffffffdf;
- writel(val32, iTCO_wdt_private.gcs);
+ writel(val32, iTCO_wdt_private.gcs_pmc);
- val32 = readl(iTCO_wdt_private.gcs);
+ val32 = readl(iTCO_wdt_private.gcs_pmc);
if (val32 & 0x00000020)
ret = -EIO;
} else if (iTCO_wdt_private.iTCO_version == 1) {
@@ -192,7 +215,7 @@ static int iTCO_wdt_start(struct watchdog_device *wd_dev)
/* Force the timer to its reload value by writing to the TCO_RLD
register */
- if (iTCO_wdt_private.iTCO_version == 2)
+ if (iTCO_wdt_private.iTCO_version >= 2)
outw(0x01, TCO_RLD);
else if (iTCO_wdt_private.iTCO_version == 1)
outb(0x01, TCO_RLD);
@@ -240,9 +263,9 @@ static int iTCO_wdt_ping(struct watchdog_device *wd_dev)
iTCO_vendor_pre_keepalive(iTCO_wdt_private.smi_res, wd_dev->timeout);
/* Reload the timer by writing to the TCO Timer Counter register */
- if (iTCO_wdt_private.iTCO_version == 2)
+ if (iTCO_wdt_private.iTCO_version >= 2) {
outw(0x01, TCO_RLD);
- else if (iTCO_wdt_private.iTCO_version == 1) {
+ } else if (iTCO_wdt_private.iTCO_version == 1) {
/* Reset the timeout status bit so that the timer
* needs to count down twice again before rebooting */
outw(0x0008, TCO1_STS); /* write 1 to clear bit */
@@ -270,14 +293,14 @@ static int iTCO_wdt_set_timeout(struct watchdog_device *wd_dev, unsigned int t)
/* "Values of 0h-3h are ignored and should not be attempted" */
if (tmrval < 0x04)
return -EINVAL;
- if (((iTCO_wdt_private.iTCO_version == 2) && (tmrval > 0x3ff)) ||
+ if (((iTCO_wdt_private.iTCO_version >= 2) && (tmrval > 0x3ff)) ||
((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f)))
return -EINVAL;
iTCO_vendor_pre_set_heartbeat(tmrval);
/* Write new heartbeat to watchdog */
- if (iTCO_wdt_private.iTCO_version == 2) {
+ if (iTCO_wdt_private.iTCO_version >= 2) {
spin_lock(&iTCO_wdt_private.io_lock);
val16 = inw(TCOv2_TMR);
val16 &= 0xfc00;
@@ -312,13 +335,13 @@ static unsigned int iTCO_wdt_get_timeleft(struct watchdog_device *wd_dev)
unsigned int time_left = 0;
/* read the TCO Timer */
- if (iTCO_wdt_private.iTCO_version == 2) {
+ if (iTCO_wdt_private.iTCO_version >= 2) {
spin_lock(&iTCO_wdt_private.io_lock);
val16 = inw(TCO_RLD);
val16 &= 0x3ff;
spin_unlock(&iTCO_wdt_private.io_lock);
- time_left = (val16 * 6) / 10;
+ time_left = ticks_to_seconds(val16);
} else if (iTCO_wdt_private.iTCO_version == 1) {
spin_lock(&iTCO_wdt_private.io_lock);
val8 = inb(TCO_RLD);
@@ -327,7 +350,7 @@ static unsigned int iTCO_wdt_get_timeleft(struct watchdog_device *wd_dev)
val8 += (inb(TCOv1_TMR) & 0x3f);
spin_unlock(&iTCO_wdt_private.io_lock);
- time_left = (val8 * 6) / 10;
+ time_left = ticks_to_seconds(val8);
}
return time_left;
}
@@ -376,16 +399,16 @@ static void iTCO_wdt_cleanup(void)
resource_size(iTCO_wdt_private.tco_res));
release_region(iTCO_wdt_private.smi_res->start,
resource_size(iTCO_wdt_private.smi_res));
- if (iTCO_wdt_private.iTCO_version == 2) {
- iounmap(iTCO_wdt_private.gcs);
- release_mem_region(iTCO_wdt_private.gcs_res->start,
- resource_size(iTCO_wdt_private.gcs_res));
+ if (iTCO_wdt_private.iTCO_version >= 2) {
+ iounmap(iTCO_wdt_private.gcs_pmc);
+ release_mem_region(iTCO_wdt_private.gcs_pmc_res->start,
+ resource_size(iTCO_wdt_private.gcs_pmc_res));
}
iTCO_wdt_private.tco_res = NULL;
iTCO_wdt_private.smi_res = NULL;
- iTCO_wdt_private.gcs_res = NULL;
- iTCO_wdt_private.gcs = NULL;
+ iTCO_wdt_private.gcs_pmc_res = NULL;
+ iTCO_wdt_private.gcs_pmc = NULL;
}
static int iTCO_wdt_probe(struct platform_device *dev)
@@ -414,27 +437,27 @@ static int iTCO_wdt_probe(struct platform_device *dev)
iTCO_wdt_private.pdev = to_pci_dev(dev->dev.parent);
/*
- * Get the Memory-Mapped GCS register, we need it for the
- * NO_REBOOT flag (TCO v2).
+ * Get the Memory-Mapped GCS or PMC register, we need it for the
+ * NO_REBOOT flag (TCO v2 and v3).
*/
- if (iTCO_wdt_private.iTCO_version == 2) {
- iTCO_wdt_private.gcs_res = platform_get_resource(dev,
+ if (iTCO_wdt_private.iTCO_version >= 2) {
+ iTCO_wdt_private.gcs_pmc_res = platform_get_resource(dev,
IORESOURCE_MEM,
- ICH_RES_MEM_GCS);
+ ICH_RES_MEM_GCS_PMC);
- if (!iTCO_wdt_private.gcs_res)
+ if (!iTCO_wdt_private.gcs_pmc_res)
goto out;
- if (!request_mem_region(iTCO_wdt_private.gcs_res->start,
- resource_size(iTCO_wdt_private.gcs_res), dev->name)) {
+ if (!request_mem_region(iTCO_wdt_private.gcs_pmc_res->start,
+ resource_size(iTCO_wdt_private.gcs_pmc_res), dev->name)) {
ret = -EBUSY;
goto out;
}
- iTCO_wdt_private.gcs = ioremap(iTCO_wdt_private.gcs_res->start,
- resource_size(iTCO_wdt_private.gcs_res));
- if (!iTCO_wdt_private.gcs) {
+ iTCO_wdt_private.gcs_pmc = ioremap(iTCO_wdt_private.gcs_pmc_res->start,
+ resource_size(iTCO_wdt_private.gcs_pmc_res));
+ if (!iTCO_wdt_private.gcs_pmc) {
ret = -EIO;
- goto unreg_gcs;
+ goto unreg_gcs_pmc;
}
}
@@ -442,7 +465,7 @@ static int iTCO_wdt_probe(struct platform_device *dev)
if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n");
ret = -ENODEV; /* Cannot reset NO_REBOOT bit */
- goto unmap_gcs;
+ goto unmap_gcs_pmc;
}
/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
@@ -454,7 +477,7 @@ static int iTCO_wdt_probe(struct platform_device *dev)
pr_err("I/O address 0x%04llx already in use, device disabled\n",
(u64)SMI_EN);
ret = -EBUSY;
- goto unmap_gcs;
+ goto unmap_gcs_pmc;
}
if (turn_SMI_watchdog_clear_off >= iTCO_wdt_private.iTCO_version) {
/*
@@ -478,9 +501,13 @@ static int iTCO_wdt_probe(struct platform_device *dev)
ich_info->name, ich_info->iTCO_version, (u64)TCOBASE);
/* Clear out the (probably old) status */
- outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */
- outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */
- outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */
+ if (iTCO_wdt_private.iTCO_version == 3) {
+ outl(0x20008, TCO1_STS);
+ } else {
+ outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */
+ outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */
+ outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */
+ }
iTCO_wdt_watchdog_dev.bootstatus = 0;
iTCO_wdt_watchdog_dev.timeout = WATCHDOG_TIMEOUT;
@@ -515,18 +542,18 @@ unreg_tco:
unreg_smi:
release_region(iTCO_wdt_private.smi_res->start,
resource_size(iTCO_wdt_private.smi_res));
-unmap_gcs:
- if (iTCO_wdt_private.iTCO_version == 2)
- iounmap(iTCO_wdt_private.gcs);
-unreg_gcs:
- if (iTCO_wdt_private.iTCO_version == 2)
- release_mem_region(iTCO_wdt_private.gcs_res->start,
- resource_size(iTCO_wdt_private.gcs_res));
+unmap_gcs_pmc:
+ if (iTCO_wdt_private.iTCO_version >= 2)
+ iounmap(iTCO_wdt_private.gcs_pmc);
+unreg_gcs_pmc:
+ if (iTCO_wdt_private.iTCO_version >= 2)
+ release_mem_region(iTCO_wdt_private.gcs_pmc_res->start,
+ resource_size(iTCO_wdt_private.gcs_pmc_res));
out:
iTCO_wdt_private.tco_res = NULL;
iTCO_wdt_private.smi_res = NULL;
- iTCO_wdt_private.gcs_res = NULL;
- iTCO_wdt_private.gcs = NULL;
+ iTCO_wdt_private.gcs_pmc_res = NULL;
+ iTCO_wdt_private.gcs_pmc = NULL;
return ret;
}
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index ade1c06..d2b1670 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -195,6 +195,18 @@ static inline int twl_i2c_read_u8(u8 mod_no, u8 *val, u8 reg) {
return twl_i2c_read(mod_no, val, reg, 1);
}
+static inline int twl_i2c_write_u16(u8 mod_no, u16 val, u8 reg) {
+ val = cpu_to_le16(val);
+ return twl_i2c_write(mod_no, (u8*) &val, reg, 2);
+}
+
+static inline int twl_i2c_read_u16(u8 mod_no, u16 *val, u8 reg) {
+ int ret;
+ ret = twl_i2c_read(mod_no, (u8*) val, reg, 2);
+ *val = le16_to_cpu(*val);
+ return ret;
+}
+
int twl_get_type(void);
int twl_get_version(void);
int twl_get_hfclk_rate(void);
diff --git a/include/linux/i2c/twl4030-madc.h b/include/linux/i2c/twl4030-madc.h
index 01f5951..1c0134d 100644
--- a/include/linux/i2c/twl4030-madc.h
+++ b/include/linux/i2c/twl4030-madc.h
@@ -44,7 +44,7 @@ struct twl4030_madc_conversion_method {
struct twl4030_madc_request {
unsigned long channels;
- u16 do_avg;
+ bool do_avg;
u16 method;
u16 type;
bool active;
diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h
index 3ddaa63..7b35c21 100644
--- a/include/linux/mfd/arizona/registers.h
+++ b/include/linux/mfd/arizona/registers.h
@@ -1034,6 +1034,27 @@
#define ARIZONA_DSP1_STATUS_1 0x1104
#define ARIZONA_DSP1_STATUS_2 0x1105
#define ARIZONA_DSP1_STATUS_3 0x1106
+#define ARIZONA_DSP1_STATUS_4 0x1107
+#define ARIZONA_DSP1_WDMA_BUFFER_1 0x1110
+#define ARIZONA_DSP1_WDMA_BUFFER_2 0x1111
+#define ARIZONA_DSP1_WDMA_BUFFER_3 0x1112
+#define ARIZONA_DSP1_WDMA_BUFFER_4 0x1113
+#define ARIZONA_DSP1_WDMA_BUFFER_5 0x1114
+#define ARIZONA_DSP1_WDMA_BUFFER_6 0x1115
+#define ARIZONA_DSP1_WDMA_BUFFER_7 0x1116
+#define ARIZONA_DSP1_WDMA_BUFFER_8 0x1117
+#define ARIZONA_DSP1_RDMA_BUFFER_1 0x1120
+#define ARIZONA_DSP1_RDMA_BUFFER_2 0x1121
+#define ARIZONA_DSP1_RDMA_BUFFER_3 0x1122
+#define ARIZONA_DSP1_RDMA_BUFFER_4 0x1123
+#define ARIZONA_DSP1_RDMA_BUFFER_5 0x1124
+#define ARIZONA_DSP1_RDMA_BUFFER_6 0x1125
+#define ARIZONA_DSP1_WDMA_CONFIG_1 0x1130
+#define ARIZONA_DSP1_WDMA_CONFIG_2 0x1131
+#define ARIZONA_DSP1_WDMA_OFFSET_1 0x1132
+#define ARIZONA_DSP1_RDMA_CONFIG_1 0x1134
+#define ARIZONA_DSP1_RDMA_OFFSET_1 0x1135
+#define ARIZONA_DSP1_EXTERNAL_START_SELECT_1 0x1138
#define ARIZONA_DSP1_SCRATCH_0 0x1140
#define ARIZONA_DSP1_SCRATCH_1 0x1141
#define ARIZONA_DSP1_SCRATCH_2 0x1142
@@ -1043,6 +1064,27 @@
#define ARIZONA_DSP2_STATUS_1 0x1204
#define ARIZONA_DSP2_STATUS_2 0x1205
#define ARIZONA_DSP2_STATUS_3 0x1206
+#define ARIZONA_DSP2_STATUS_4 0x1207
+#define ARIZONA_DSP2_WDMA_BUFFER_1 0x1210
+#define ARIZONA_DSP2_WDMA_BUFFER_2 0x1211
+#define ARIZONA_DSP2_WDMA_BUFFER_3 0x1212
+#define ARIZONA_DSP2_WDMA_BUFFER_4 0x1213
+#define ARIZONA_DSP2_WDMA_BUFFER_5 0x1214
+#define ARIZONA_DSP2_WDMA_BUFFER_6 0x1215
+#define ARIZONA_DSP2_WDMA_BUFFER_7 0x1216
+#define ARIZONA_DSP2_WDMA_BUFFER_8 0x1217
+#define ARIZONA_DSP2_RDMA_BUFFER_1 0x1220
+#define ARIZONA_DSP2_RDMA_BUFFER_2 0x1221
+#define ARIZONA_DSP2_RDMA_BUFFER_3 0x1222
+#define ARIZONA_DSP2_RDMA_BUFFER_4 0x1223
+#define ARIZONA_DSP2_RDMA_BUFFER_5 0x1224
+#define ARIZONA_DSP2_RDMA_BUFFER_6 0x1225
+#define ARIZONA_DSP2_WDMA_CONFIG_1 0x1230
+#define ARIZONA_DSP2_WDMA_CONFIG_2 0x1231
+#define ARIZONA_DSP2_WDMA_OFFSET_1 0x1232
+#define ARIZONA_DSP2_RDMA_CONFIG_1 0x1234
+#define ARIZONA_DSP2_RDMA_OFFSET_1 0x1235
+#define ARIZONA_DSP2_EXTERNAL_START_SELECT_1 0x1238
#define ARIZONA_DSP2_SCRATCH_0 0x1240
#define ARIZONA_DSP2_SCRATCH_1 0x1241
#define ARIZONA_DSP2_SCRATCH_2 0x1242
@@ -1052,6 +1094,27 @@
#define ARIZONA_DSP3_STATUS_1 0x1304
#define ARIZONA_DSP3_STATUS_2 0x1305
#define ARIZONA_DSP3_STATUS_3 0x1306
+#define ARIZONA_DSP3_STATUS_4 0x1307
+#define ARIZONA_DSP3_WDMA_BUFFER_1 0x1310
+#define ARIZONA_DSP3_WDMA_BUFFER_2 0x1311
+#define ARIZONA_DSP3_WDMA_BUFFER_3 0x1312
+#define ARIZONA_DSP3_WDMA_BUFFER_4 0x1313
+#define ARIZONA_DSP3_WDMA_BUFFER_5 0x1314
+#define ARIZONA_DSP3_WDMA_BUFFER_6 0x1315
+#define ARIZONA_DSP3_WDMA_BUFFER_7 0x1316
+#define ARIZONA_DSP3_WDMA_BUFFER_8 0x1317
+#define ARIZONA_DSP3_RDMA_BUFFER_1 0x1320
+#define ARIZONA_DSP3_RDMA_BUFFER_2 0x1321
+#define ARIZONA_DSP3_RDMA_BUFFER_3 0x1322
+#define ARIZONA_DSP3_RDMA_BUFFER_4 0x1323
+#define ARIZONA_DSP3_RDMA_BUFFER_5 0x1324
+#define ARIZONA_DSP3_RDMA_BUFFER_6 0x1325
+#define ARIZONA_DSP3_WDMA_CONFIG_1 0x1330
+#define ARIZONA_DSP3_WDMA_CONFIG_2 0x1331
+#define ARIZONA_DSP3_WDMA_OFFSET_1 0x1332
+#define ARIZONA_DSP3_RDMA_CONFIG_1 0x1334
+#define ARIZONA_DSP3_RDMA_OFFSET_1 0x1335
+#define ARIZONA_DSP3_EXTERNAL_START_SELECT_1 0x1338
#define ARIZONA_DSP3_SCRATCH_0 0x1340
#define ARIZONA_DSP3_SCRATCH_1 0x1341
#define ARIZONA_DSP3_SCRATCH_2 0x1342
@@ -1061,6 +1124,27 @@
#define ARIZONA_DSP4_STATUS_1 0x1404
#define ARIZONA_DSP4_STATUS_2 0x1405
#define ARIZONA_DSP4_STATUS_3 0x1406
+#define ARIZONA_DSP4_STATUS_4 0x1407
+#define ARIZONA_DSP4_WDMA_BUFFER_1 0x1410
+#define ARIZONA_DSP4_WDMA_BUFFER_2 0x1411
+#define ARIZONA_DSP4_WDMA_BUFFER_3 0x1412
+#define ARIZONA_DSP4_WDMA_BUFFER_4 0x1413
+#define ARIZONA_DSP4_WDMA_BUFFER_5 0x1414
+#define ARIZONA_DSP4_WDMA_BUFFER_6 0x1415
+#define ARIZONA_DSP4_WDMA_BUFFER_7 0x1416
+#define ARIZONA_DSP4_WDMA_BUFFER_8 0x1417
+#define ARIZONA_DSP4_RDMA_BUFFER_1 0x1420
+#define ARIZONA_DSP4_RDMA_BUFFER_2 0x1421
+#define ARIZONA_DSP4_RDMA_BUFFER_3 0x1422
+#define ARIZONA_DSP4_RDMA_BUFFER_4 0x1423
+#define ARIZONA_DSP4_RDMA_BUFFER_5 0x1424
+#define ARIZONA_DSP4_RDMA_BUFFER_6 0x1425
+#define ARIZONA_DSP4_WDMA_CONFIG_1 0x1430
+#define ARIZONA_DSP4_WDMA_CONFIG_2 0x1431
+#define ARIZONA_DSP4_WDMA_OFFSET_1 0x1432
+#define ARIZONA_DSP4_RDMA_CONFIG_1 0x1434
+#define ARIZONA_DSP4_RDMA_OFFSET_1 0x1435
+#define ARIZONA_DSP4_EXTERNAL_START_SELECT_1 0x1438
#define ARIZONA_DSP4_SCRATCH_0 0x1440
#define ARIZONA_DSP4_SCRATCH_1 0x1441
#define ARIZONA_DSP4_SCRATCH_2 0x1442
diff --git a/include/linux/mfd/bcm590xx.h b/include/linux/mfd/bcm590xx.h
new file mode 100644
index 0000000..434df2d
--- /dev/null
+++ b/include/linux/mfd/bcm590xx.h
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef __LINUX_MFD_BCM590XX_H
+#define __LINUX_MFD_BCM590XX_H
+
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+/* max register address */
+#define BCM590XX_MAX_REGISTER 0xe7
+
+struct bcm590xx {
+ struct device *dev;
+ struct i2c_client *i2c_client;
+ struct regmap *regmap;
+ unsigned int id;
+};
+
+#endif /* __LINUX_MFD_BCM590XX_H */
diff --git a/include/linux/mfd/da9052/da9052.h b/include/linux/mfd/da9052/da9052.h
index 21e21b8..bba65f5 100644
--- a/include/linux/mfd/da9052/da9052.h
+++ b/include/linux/mfd/da9052/da9052.h
@@ -83,6 +83,7 @@ enum da9052_chip_id {
DA9053_AA,
DA9053_BA,
DA9053_BB,
+ DA9053_BC,
};
struct da9052_pdata;
diff --git a/include/linux/mfd/da9063/core.h b/include/linux/mfd/da9063/core.h
index 2d2a0af..00a9aac 100644
--- a/include/linux/mfd/da9063/core.h
+++ b/include/linux/mfd/da9063/core.h
@@ -33,6 +33,10 @@ enum da9063_models {
PMIC_DA9063 = 0x61,
};
+enum da9063_variant_codes {
+ PMIC_DA9063_BB = 0x5
+};
+
/* Interrupts */
enum da9063_irqs {
DA9063_IRQ_ONKEY = 0,
@@ -72,7 +76,7 @@ struct da9063 {
/* Device */
struct device *dev;
unsigned short model;
- unsigned short revision;
+ unsigned char variant_code;
unsigned int flags;
/* Control interface */
diff --git a/include/linux/mfd/da9063/registers.h b/include/linux/mfd/da9063/registers.h
index 5834813..09a85c6 100644
--- a/include/linux/mfd/da9063/registers.h
+++ b/include/linux/mfd/da9063/registers.h
@@ -17,11 +17,7 @@
#define _DA9063_REG_H
#define DA9063_I2C_PAGE_SEL_SHIFT 1
-
#define DA9063_EVENT_REG_NUM 4
-#define DA9210_EVENT_REG_NUM 2
-#define DA9063_EXT_EVENT_REG_NUM (DA9063_EVENT_REG_NUM + \
- DA9210_EVENT_REG_NUM)
/* Page selection I2C or SPI always in the begining of any page. */
/* Page 0 : I2C access 0x000 - 0x0FF SPI access 0x000 - 0x07F */
@@ -61,9 +57,9 @@
#define DA9063_REG_GPIO_10_11 0x1A
#define DA9063_REG_GPIO_12_13 0x1B
#define DA9063_REG_GPIO_14_15 0x1C
-#define DA9063_REG_GPIO_MODE_0_7 0x1D
-#define DA9063_REG_GPIO_MODE_8_15 0x1E
-#define DA9063_REG_GPIO_SWITCH_CONT 0x1F
+#define DA9063_REG_GPIO_MODE0_7 0x1D
+#define DA9063_REG_GPIO_MODE8_15 0x1E
+#define DA9063_REG_SWITCH_CONT 0x1F
/* Regulator Control Registers */
#define DA9063_REG_BCORE2_CONT 0x20
@@ -83,7 +79,7 @@
#define DA9063_REG_LDO9_CONT 0x2E
#define DA9063_REG_LDO10_CONT 0x2F
#define DA9063_REG_LDO11_CONT 0x30
-#define DA9063_REG_VIB 0x31
+#define DA9063_REG_SUPPLIES 0x31
#define DA9063_REG_DVC_1 0x32
#define DA9063_REG_DVC_2 0x33
@@ -97,9 +93,9 @@
#define DA9063_REG_ADCIN1_RES 0x3A
#define DA9063_REG_ADCIN2_RES 0x3B
#define DA9063_REG_ADCIN3_RES 0x3C
-#define DA9063_REG_MON1_RES 0x3D
-#define DA9063_REG_MON2_RES 0x3E
-#define DA9063_REG_MON3_RES 0x3F
+#define DA9063_REG_MON_A8_RES 0x3D
+#define DA9063_REG_MON_A9_RES 0x3E
+#define DA9063_REG_MON_A10_RES 0x3F
/* RTC Calendar and Alarm Registers */
#define DA9063_REG_COUNT_S 0x40
@@ -108,15 +104,16 @@
#define DA9063_REG_COUNT_D 0x43
#define DA9063_REG_COUNT_MO 0x44
#define DA9063_REG_COUNT_Y 0x45
-#define DA9063_REG_ALARM_MI 0x46
-#define DA9063_REG_ALARM_H 0x47
-#define DA9063_REG_ALARM_D 0x48
-#define DA9063_REG_ALARM_MO 0x49
-#define DA9063_REG_ALARM_Y 0x4A
-#define DA9063_REG_SECOND_A 0x4B
-#define DA9063_REG_SECOND_B 0x4C
-#define DA9063_REG_SECOND_C 0x4D
-#define DA9063_REG_SECOND_D 0x4E
+#define DA9063_REG_ALARM_S 0x46
+#define DA9063_REG_ALARM_MI 0x47
+#define DA9063_REG_ALARM_H 0x48
+#define DA9063_REG_ALARM_D 0x49
+#define DA9063_REG_ALARM_MO 0x4A
+#define DA9063_REG_ALARM_Y 0x4B
+#define DA9063_REG_SECOND_A 0x4C
+#define DA9063_REG_SECOND_B 0x4D
+#define DA9063_REG_SECOND_C 0x4E
+#define DA9063_REG_SECOND_D 0x4F
/* Sequencer Control Registers */
#define DA9063_REG_SEQ 0x81
@@ -226,35 +223,37 @@
#define DA9063_REG_CONFIG_J 0x10F
#define DA9063_REG_CONFIG_K 0x110
#define DA9063_REG_CONFIG_L 0x111
-#define DA9063_REG_MON_REG_1 0x112
-#define DA9063_REG_MON_REG_2 0x113
-#define DA9063_REG_MON_REG_3 0x114
-#define DA9063_REG_MON_REG_4 0x115
-#define DA9063_REG_MON_REG_5 0x116
-#define DA9063_REG_MON_REG_6 0x117
-#define DA9063_REG_TRIM_CLDR 0x118
-
+#define DA9063_REG_CONFIG_M 0x112
+#define DA9063_REG_CONFIG_N 0x113
+
+#define DA9063_REG_MON_REG_1 0x114
+#define DA9063_REG_MON_REG_2 0x115
+#define DA9063_REG_MON_REG_3 0x116
+#define DA9063_REG_MON_REG_4 0x117
+#define DA9063_REG_MON_REG_5 0x11E
+#define DA9063_REG_MON_REG_6 0x11F
+#define DA9063_REG_TRIM_CLDR 0x120
/* General Purpose Registers */
-#define DA9063_REG_GP_ID_0 0x119
-#define DA9063_REG_GP_ID_1 0x11A
-#define DA9063_REG_GP_ID_2 0x11B
-#define DA9063_REG_GP_ID_3 0x11C
-#define DA9063_REG_GP_ID_4 0x11D
-#define DA9063_REG_GP_ID_5 0x11E
-#define DA9063_REG_GP_ID_6 0x11F
-#define DA9063_REG_GP_ID_7 0x120
-#define DA9063_REG_GP_ID_8 0x121
-#define DA9063_REG_GP_ID_9 0x122
-#define DA9063_REG_GP_ID_10 0x123
-#define DA9063_REG_GP_ID_11 0x124
-#define DA9063_REG_GP_ID_12 0x125
-#define DA9063_REG_GP_ID_13 0x126
-#define DA9063_REG_GP_ID_14 0x127
-#define DA9063_REG_GP_ID_15 0x128
-#define DA9063_REG_GP_ID_16 0x129
-#define DA9063_REG_GP_ID_17 0x12A
-#define DA9063_REG_GP_ID_18 0x12B
-#define DA9063_REG_GP_ID_19 0x12C
+#define DA9063_REG_GP_ID_0 0x121
+#define DA9063_REG_GP_ID_1 0x122
+#define DA9063_REG_GP_ID_2 0x123
+#define DA9063_REG_GP_ID_3 0x124
+#define DA9063_REG_GP_ID_4 0x125
+#define DA9063_REG_GP_ID_5 0x126
+#define DA9063_REG_GP_ID_6 0x127
+#define DA9063_REG_GP_ID_7 0x128
+#define DA9063_REG_GP_ID_8 0x129
+#define DA9063_REG_GP_ID_9 0x12A
+#define DA9063_REG_GP_ID_10 0x12B
+#define DA9063_REG_GP_ID_11 0x12C
+#define DA9063_REG_GP_ID_12 0x12D
+#define DA9063_REG_GP_ID_13 0x12E
+#define DA9063_REG_GP_ID_14 0x12F
+#define DA9063_REG_GP_ID_15 0x130
+#define DA9063_REG_GP_ID_16 0x131
+#define DA9063_REG_GP_ID_17 0x132
+#define DA9063_REG_GP_ID_18 0x133
+#define DA9063_REG_GP_ID_19 0x134
/* Chip ID and variant */
#define DA9063_REG_CHIP_ID 0x181
@@ -405,8 +404,10 @@
/* DA9063_REG_CONTROL_B (addr=0x0F) */
#define DA9063_CHG_SEL 0x01
#define DA9063_WATCHDOG_PD 0x02
+#define DA9063_RESET_BLINKING 0x04
#define DA9063_NRES_MODE 0x08
#define DA9063_NONKEY_LOCK 0x10
+#define DA9063_BUCK_SLOWSTART 0x80
/* DA9063_REG_CONTROL_C (addr=0x10) */
#define DA9063_DEBOUNCING_MASK 0x07
@@ -466,6 +467,7 @@
#define DA9063_GPADC_PAUSE 0x02
#define DA9063_PMIF_DIS 0x04
#define DA9063_HS2WIRE_DIS 0x08
+#define DA9063_CLDR_PAUSE 0x10
#define DA9063_BBAT_DIS 0x20
#define DA9063_OUT_32K_PAUSE 0x40
#define DA9063_PMCONT_DIS 0x80
@@ -660,7 +662,7 @@
#define DA9063_GPIO15_TYPE_GPO 0x04
#define DA9063_GPIO15_NO_WAKEUP 0x80
-/* DA9063_REG_GPIO_MODE_0_7 (addr=0x1D) */
+/* DA9063_REG_GPIO_MODE0_7 (addr=0x1D) */
#define DA9063_GPIO0_MODE 0x01
#define DA9063_GPIO1_MODE 0x02
#define DA9063_GPIO2_MODE 0x04
@@ -670,7 +672,7 @@
#define DA9063_GPIO6_MODE 0x40
#define DA9063_GPIO7_MODE 0x80
-/* DA9063_REG_GPIO_MODE_8_15 (addr=0x1E) */
+/* DA9063_REG_GPIO_MODE8_15 (addr=0x1E) */
#define DA9063_GPIO8_MODE 0x01
#define DA9063_GPIO9_MODE 0x02
#define DA9063_GPIO10_MODE 0x04
@@ -702,12 +704,12 @@
#define DA9063_SWITCH_SR_5MV 0x10
#define DA9063_SWITCH_SR_10MV 0x20
#define DA9063_SWITCH_SR_50MV 0x30
-#define DA9063_SWITCH_SR_DIS 0x40
+#define DA9063_CORE_SW_INTERNAL 0x40
#define DA9063_CP_EN_MODE 0x80
/* DA9063_REGL_Bxxxx_CONT common bits (addr=0x20-0x25) */
#define DA9063_BUCK_EN 0x01
-#define DA9063_BUCK_GPI_MASK 0x06
+#define DA9063_BUCK_GPI_MASK 0x06
#define DA9063_BUCK_GPI_OFF 0x00
#define DA9063_BUCK_GPI_GPIO1 0x02
#define DA9063_BUCK_GPI_GPIO2 0x04
@@ -841,25 +843,27 @@
#define DA9063_COUNT_YEAR_MASK 0x3F
#define DA9063_MONITOR 0x40
-/* DA9063_REG_ALARM_MI (addr=0x46) */
+/* DA9063_REG_ALARM_S (addr=0x46) */
+#define DA9063_ALARM_S_MASK 0x3F
#define DA9063_ALARM_STATUS_ALARM 0x80
#define DA9063_ALARM_STATUS_TICK 0x40
+/* DA9063_REG_ALARM_MI (addr=0x47) */
#define DA9063_ALARM_MIN_MASK 0x3F
-/* DA9063_REG_ALARM_H (addr=0x47) */
+/* DA9063_REG_ALARM_H (addr=0x48) */
#define DA9063_ALARM_HOUR_MASK 0x1F
-/* DA9063_REG_ALARM_D (addr=0x48) */
+/* DA9063_REG_ALARM_D (addr=0x49) */
#define DA9063_ALARM_DAY_MASK 0x1F
-/* DA9063_REG_ALARM_MO (addr=0x49) */
+/* DA9063_REG_ALARM_MO (addr=0x4A) */
#define DA9063_TICK_WAKE 0x20
#define DA9063_TICK_TYPE 0x10
#define DA9063_TICK_TYPE_SEC 0x00
#define DA9063_TICK_TYPE_MIN 0x10
#define DA9063_ALARM_MONTH_MASK 0x0F
-/* DA9063_REG_ALARM_Y (addr=0x4A) */
+/* DA9063_REG_ALARM_Y (addr=0x4B) */
#define DA9063_TICK_ON 0x80
#define DA9063_ALARM_ON 0x40
#define DA9063_ALARM_YEAR_MASK 0x3F
@@ -906,7 +910,7 @@
/* DA9063_REG_Bxxxx_CFG common bits (addr=0x9D-0xA2) */
#define DA9063_BUCK_FB_MASK 0x07
-#define DA9063_BUCK_PD_DIS_SHIFT 5
+#define DA9063_BUCK_PD_DIS_MASK 0x20
#define DA9063_BUCK_MODE_MASK 0xC0
#define DA9063_BUCK_MODE_MANUAL 0x00
#define DA9063_BUCK_MODE_SLEEP 0x40
diff --git a/include/linux/mfd/lpc_ich.h b/include/linux/mfd/lpc_ich.h
index 3e1df64..8feac78 100644
--- a/include/linux/mfd/lpc_ich.h
+++ b/include/linux/mfd/lpc_ich.h
@@ -21,23 +21,26 @@
#define LPC_ICH_H
/* Watchdog resources */
-#define ICH_RES_IO_TCO 0
-#define ICH_RES_IO_SMI 1
-#define ICH_RES_MEM_OFF 2
-#define ICH_RES_MEM_GCS 0
+#define ICH_RES_IO_TCO 0
+#define ICH_RES_IO_SMI 1
+#define ICH_RES_MEM_OFF 2
+#define ICH_RES_MEM_GCS_PMC 0
/* GPIO resources */
#define ICH_RES_GPIO 0
#define ICH_RES_GPE0 1
/* GPIO compatibility */
-#define ICH_I3100_GPIO 0x401
-#define ICH_V5_GPIO 0x501
-#define ICH_V6_GPIO 0x601
-#define ICH_V7_GPIO 0x701
-#define ICH_V9_GPIO 0x801
-#define ICH_V10CORP_GPIO 0xa01
-#define ICH_V10CONS_GPIO 0xa11
+enum {
+ ICH_I3100_GPIO,
+ ICH_V5_GPIO,
+ ICH_V6_GPIO,
+ ICH_V7_GPIO,
+ ICH_V9_GPIO,
+ ICH_V10CORP_GPIO,
+ ICH_V10CONS_GPIO,
+ AVOTON_GPIO,
+};
struct lpc_ich_info {
char name[32];
diff --git a/include/linux/mfd/max14577-private.h b/include/linux/mfd/max14577-private.h
index a3d0185..c9b332f 100644
--- a/include/linux/mfd/max14577-private.h
+++ b/include/linux/mfd/max14577-private.h
@@ -248,14 +248,6 @@ enum max14577_charger_reg {
/* MAX14577 regulator SFOUT LDO voltage, fixed, uV */
#define MAX14577_REGULATOR_SAFEOUT_VOLTAGE 4900000
-enum max14577_irq_source {
- MAX14577_IRQ_INT1 = 0,
- MAX14577_IRQ_INT2,
- MAX14577_IRQ_INT3,
-
- MAX14577_IRQ_REGS_NUM,
-};
-
enum max14577_irq {
/* INT1 */
MAX14577_IRQ_INT1_ADC,
diff --git a/include/linux/mfd/max14577.h b/include/linux/mfd/max14577.h
index 247b021..736d39c 100644
--- a/include/linux/mfd/max14577.h
+++ b/include/linux/mfd/max14577.h
@@ -25,13 +25,8 @@
#ifndef __MAX14577_H__
#define __MAX14577_H__
-#include <linux/mfd/max14577-private.h>
#include <linux/regulator/consumer.h>
-/*
- * MAX14577 Regulator
- */
-
/* MAX14577 regulator IDs */
enum max14577_regulators {
MAX14577_SAFEOUT = 0,
diff --git a/include/linux/mfd/pm8xxx/irq.h b/include/linux/mfd/pm8xxx/irq.h
deleted file mode 100644
index f83d6b4..0000000
--- a/include/linux/mfd/pm8xxx/irq.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-/*
- * Qualcomm PMIC irq 8xxx driver header file
- *
- */
-
-#ifndef __MFD_PM8XXX_IRQ_H
-#define __MFD_PM8XXX_IRQ_H
-
-#include <linux/errno.h>
-#include <linux/err.h>
-
-struct pm8xxx_irq_core_data {
- u32 rev;
- int nirqs;
-};
-
-struct pm8xxx_irq_platform_data {
- int irq_base;
- struct pm8xxx_irq_core_data irq_cdata;
- int devirq;
- int irq_trigger_flag;
-};
-
-struct pm_irq_chip;
-
-#ifdef CONFIG_MFD_PM8XXX_IRQ
-int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq);
-struct pm_irq_chip *pm8xxx_irq_init(struct device *dev,
- const struct pm8xxx_irq_platform_data *pdata);
-int pm8xxx_irq_exit(struct pm_irq_chip *chip);
-#else
-static inline int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
-{
- return -ENXIO;
-}
-static inline struct pm_irq_chip *pm8xxx_irq_init(
- const struct device *dev,
- const struct pm8xxx_irq_platform_data *pdata)
-{
- return ERR_PTR(-ENXIO);
-}
-static inline int pm8xxx_irq_exit(struct pm_irq_chip *chip)
-{
- return -ENXIO;
-}
-#endif /* CONFIG_MFD_PM8XXX_IRQ */
-#endif /* __MFD_PM8XXX_IRQ_H */
diff --git a/include/linux/mfd/pm8xxx/pm8921.h b/include/linux/mfd/pm8xxx/pm8921.h
deleted file mode 100644
index 00fa3de..0000000
--- a/include/linux/mfd/pm8xxx/pm8921.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-/*
- * Qualcomm PMIC 8921 driver header file
- *
- */
-
-#ifndef __MFD_PM8921_H
-#define __MFD_PM8921_H
-
-#include <linux/mfd/pm8xxx/irq.h>
-
-#define PM8921_NR_IRQS 256
-
-struct pm8921_platform_data {
- int irq_base;
- struct pm8xxx_irq_platform_data *irq_pdata;
-};
-
-#endif
diff --git a/include/linux/mfd/rtsx_usb.h b/include/linux/mfd/rtsx_usb.h
new file mode 100644
index 0000000..c446e4f
--- /dev/null
+++ b/include/linux/mfd/rtsx_usb.h
@@ -0,0 +1,628 @@
+/* Driver for Realtek RTS5139 USB card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ * Roger Tseng <rogerable@realtek.com>
+ */
+
+#ifndef __RTSX_USB_H
+#define __RTSX_USB_H
+
+#include <linux/usb.h>
+
+/* related module names */
+#define RTSX_USB_SD_CARD 0
+#define RTSX_USB_MS_CARD 1
+
+/* endpoint numbers */
+#define EP_BULK_OUT 1
+#define EP_BULK_IN 2
+#define EP_INTR_IN 3
+
+/* USB vendor requests */
+#define RTSX_USB_REQ_REG_OP 0x00
+#define RTSX_USB_REQ_POLL 0x02
+
+/* miscellaneous parameters */
+#define MIN_DIV_N 60
+#define MAX_DIV_N 120
+
+#define MAX_PHASE 15
+#define RX_TUNING_CNT 3
+
+#define QFN24 0
+#define LQFP48 1
+#define CHECK_PKG(ucr, pkg) ((ucr)->package == (pkg))
+
+/* data structures */
+struct rtsx_ucr {
+ u16 vendor_id;
+ u16 product_id;
+
+ int package;
+ u8 ic_version;
+ bool is_rts5179;
+
+ unsigned int cur_clk;
+
+ u8 *cmd_buf;
+ unsigned int cmd_idx;
+ u8 *rsp_buf;
+
+ struct usb_device *pusb_dev;
+ struct usb_interface *pusb_intf;
+ struct usb_sg_request current_sg;
+ unsigned char *iobuf;
+ dma_addr_t iobuf_dma;
+
+ struct timer_list sg_timer;
+ struct mutex dev_mutex;
+};
+
+/* buffer size */
+#define IOBUF_SIZE 1024
+
+/* prototypes of exported functions */
+extern int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status);
+
+extern int rtsx_usb_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data);
+extern int rtsx_usb_write_register(struct rtsx_ucr *ucr, u16 addr, u8 mask,
+ u8 data);
+
+extern int rtsx_usb_ep0_write_register(struct rtsx_ucr *ucr, u16 addr, u8 mask,
+ u8 data);
+extern int rtsx_usb_ep0_read_register(struct rtsx_ucr *ucr, u16 addr,
+ u8 *data);
+
+extern void rtsx_usb_add_cmd(struct rtsx_ucr *ucr, u8 cmd_type,
+ u16 reg_addr, u8 mask, u8 data);
+extern int rtsx_usb_send_cmd(struct rtsx_ucr *ucr, u8 flag, int timeout);
+extern int rtsx_usb_get_rsp(struct rtsx_ucr *ucr, int rsp_len, int timeout);
+extern int rtsx_usb_transfer_data(struct rtsx_ucr *ucr, unsigned int pipe,
+ void *buf, unsigned int len, int use_sg,
+ unsigned int *act_len, int timeout);
+
+extern int rtsx_usb_read_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len);
+extern int rtsx_usb_write_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len);
+extern int rtsx_usb_switch_clock(struct rtsx_ucr *ucr, unsigned int card_clock,
+ u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk);
+extern int rtsx_usb_card_exclusive_check(struct rtsx_ucr *ucr, int card);
+
+/* card status */
+#define SD_CD 0x01
+#define MS_CD 0x02
+#define XD_CD 0x04
+#define CD_MASK (SD_CD | MS_CD | XD_CD)
+#define SD_WP 0x08
+
+/* reader command field offset & parameters */
+#define READ_REG_CMD 0
+#define WRITE_REG_CMD 1
+#define CHECK_REG_CMD 2
+
+#define PACKET_TYPE 4
+#define CNT_H 5
+#define CNT_L 6
+#define STAGE_FLAG 7
+#define CMD_OFFSET 8
+#define SEQ_WRITE_DATA_OFFSET 12
+
+#define BATCH_CMD 0
+#define SEQ_READ 1
+#define SEQ_WRITE 2
+
+#define STAGE_R 0x01
+#define STAGE_DI 0x02
+#define STAGE_DO 0x04
+#define STAGE_MS_STATUS 0x08
+#define STAGE_XD_STATUS 0x10
+#define MODE_C 0x00
+#define MODE_CR (STAGE_R)
+#define MODE_CDIR (STAGE_R | STAGE_DI)
+#define MODE_CDOR (STAGE_R | STAGE_DO)
+
+#define EP0_OP_SHIFT 14
+#define EP0_READ_REG_CMD 2
+#define EP0_WRITE_REG_CMD 3
+
+#define rtsx_usb_cmd_hdr_tag(ucr) \
+ do { \
+ ucr->cmd_buf[0] = 'R'; \
+ ucr->cmd_buf[1] = 'T'; \
+ ucr->cmd_buf[2] = 'C'; \
+ ucr->cmd_buf[3] = 'R'; \
+ } while (0)
+
+static inline void rtsx_usb_init_cmd(struct rtsx_ucr *ucr)
+{
+ rtsx_usb_cmd_hdr_tag(ucr);
+ ucr->cmd_idx = 0;
+ ucr->cmd_buf[PACKET_TYPE] = BATCH_CMD;
+}
+
+/* internal register address */
+#define FPDCTL 0xFC00
+#define SSC_DIV_N_0 0xFC07
+#define SSC_CTL1 0xFC09
+#define SSC_CTL2 0xFC0A
+#define CFG_MODE 0xFC0E
+#define CFG_MODE_1 0xFC0F
+#define RCCTL 0xFC14
+#define SOF_WDOG 0xFC28
+#define SYS_DUMMY0 0xFC30
+
+#define MS_BLKEND 0xFD30
+#define MS_READ_START 0xFD31
+#define MS_READ_COUNT 0xFD32
+#define MS_WRITE_START 0xFD33
+#define MS_WRITE_COUNT 0xFD34
+#define MS_COMMAND 0xFD35
+#define MS_OLD_BLOCK_0 0xFD36
+#define MS_OLD_BLOCK_1 0xFD37
+#define MS_NEW_BLOCK_0 0xFD38
+#define MS_NEW_BLOCK_1 0xFD39
+#define MS_LOG_BLOCK_0 0xFD3A
+#define MS_LOG_BLOCK_1 0xFD3B
+#define MS_BUS_WIDTH 0xFD3C
+#define MS_PAGE_START 0xFD3D
+#define MS_PAGE_LENGTH 0xFD3E
+#define MS_CFG 0xFD40
+#define MS_TPC 0xFD41
+#define MS_TRANS_CFG 0xFD42
+#define MS_TRANSFER 0xFD43
+#define MS_INT_REG 0xFD44
+#define MS_BYTE_CNT 0xFD45
+#define MS_SECTOR_CNT_L 0xFD46
+#define MS_SECTOR_CNT_H 0xFD47
+#define MS_DBUS_H 0xFD48
+
+#define CARD_DMA1_CTL 0xFD5C
+#define CARD_PULL_CTL1 0xFD60
+#define CARD_PULL_CTL2 0xFD61
+#define CARD_PULL_CTL3 0xFD62
+#define CARD_PULL_CTL4 0xFD63
+#define CARD_PULL_CTL5 0xFD64
+#define CARD_PULL_CTL6 0xFD65
+#define CARD_EXIST 0xFD6F
+#define CARD_INT_PEND 0xFD71
+
+#define LDO_POWER_CFG 0xFD7B
+
+#define SD_CFG1 0xFDA0
+#define SD_CFG2 0xFDA1
+#define SD_CFG3 0xFDA2
+#define SD_STAT1 0xFDA3
+#define SD_STAT2 0xFDA4
+#define SD_BUS_STAT 0xFDA5
+#define SD_PAD_CTL 0xFDA6
+#define SD_SAMPLE_POINT_CTL 0xFDA7
+#define SD_PUSH_POINT_CTL 0xFDA8
+#define SD_CMD0 0xFDA9
+#define SD_CMD1 0xFDAA
+#define SD_CMD2 0xFDAB
+#define SD_CMD3 0xFDAC
+#define SD_CMD4 0xFDAD
+#define SD_CMD5 0xFDAE
+#define SD_BYTE_CNT_L 0xFDAF
+#define SD_BYTE_CNT_H 0xFDB0
+#define SD_BLOCK_CNT_L 0xFDB1
+#define SD_BLOCK_CNT_H 0xFDB2
+#define SD_TRANSFER 0xFDB3
+#define SD_CMD_STATE 0xFDB5
+#define SD_DATA_STATE 0xFDB6
+#define SD_VPCLK0_CTL 0xFC2A
+#define SD_VPCLK1_CTL 0xFC2B
+#define SD_DCMPS0_CTL 0xFC2C
+#define SD_DCMPS1_CTL 0xFC2D
+
+#define CARD_DMA1_CTL 0xFD5C
+
+#define HW_VERSION 0xFC01
+
+#define SSC_CLK_FPGA_SEL 0xFC02
+#define CLK_DIV 0xFC03
+#define SFSM_ED 0xFC04
+
+#define CD_DEGLITCH_WIDTH 0xFC20
+#define CD_DEGLITCH_EN 0xFC21
+#define AUTO_DELINK_EN 0xFC23
+
+#define FPGA_PULL_CTL 0xFC1D
+#define CARD_CLK_SOURCE 0xFC2E
+
+#define CARD_SHARE_MODE 0xFD51
+#define CARD_DRIVE_SEL 0xFD52
+#define CARD_STOP 0xFD53
+#define CARD_OE 0xFD54
+#define CARD_AUTO_BLINK 0xFD55
+#define CARD_GPIO 0xFD56
+#define SD30_DRIVE_SEL 0xFD57
+
+#define CARD_DATA_SOURCE 0xFD5D
+#define CARD_SELECT 0xFD5E
+
+#define CARD_CLK_EN 0xFD79
+#define CARD_PWR_CTL 0xFD7A
+
+#define OCPCTL 0xFD80
+#define OCPPARA1 0xFD81
+#define OCPPARA2 0xFD82
+#define OCPSTAT 0xFD83
+
+#define HS_USB_STAT 0xFE01
+#define HS_VCONTROL 0xFE26
+#define HS_VSTAIN 0xFE27
+#define HS_VLOADM 0xFE28
+#define HS_VSTAOUT 0xFE29
+
+#define MC_IRQ 0xFF00
+#define MC_IRQEN 0xFF01
+#define MC_FIFO_CTL 0xFF02
+#define MC_FIFO_BC0 0xFF03
+#define MC_FIFO_BC1 0xFF04
+#define MC_FIFO_STAT 0xFF05
+#define MC_FIFO_MODE 0xFF06
+#define MC_FIFO_RD_PTR0 0xFF07
+#define MC_FIFO_RD_PTR1 0xFF08
+#define MC_DMA_CTL 0xFF10
+#define MC_DMA_TC0 0xFF11
+#define MC_DMA_TC1 0xFF12
+#define MC_DMA_TC2 0xFF13
+#define MC_DMA_TC3 0xFF14
+#define MC_DMA_RST 0xFF15
+
+#define RBUF_SIZE_MASK 0xFBFF
+#define RBUF_BASE 0xF000
+#define PPBUF_BASE1 0xF800
+#define PPBUF_BASE2 0xFA00
+
+/* internal register value macros */
+#define POWER_OFF 0x03
+#define PARTIAL_POWER_ON 0x02
+#define POWER_ON 0x00
+#define POWER_MASK 0x03
+#define LDO3318_PWR_MASK 0x0C
+#define LDO_ON 0x00
+#define LDO_SUSPEND 0x08
+#define LDO_OFF 0x0C
+#define DV3318_AUTO_PWR_OFF 0x10
+#define FORCE_LDO_POWERB 0x60
+
+/* LDO_POWER_CFG */
+#define TUNE_SD18_MASK 0x1C
+#define TUNE_SD18_1V7 0x00
+#define TUNE_SD18_1V8 (0x01 << 2)
+#define TUNE_SD18_1V9 (0x02 << 2)
+#define TUNE_SD18_2V0 (0x03 << 2)
+#define TUNE_SD18_2V7 (0x04 << 2)
+#define TUNE_SD18_2V8 (0x05 << 2)
+#define TUNE_SD18_2V9 (0x06 << 2)
+#define TUNE_SD18_3V3 (0x07 << 2)
+
+/* CLK_DIV */
+#define CLK_CHANGE 0x80
+#define CLK_DIV_1 0x00
+#define CLK_DIV_2 0x01
+#define CLK_DIV_4 0x02
+#define CLK_DIV_8 0x03
+
+#define SSC_POWER_MASK 0x01
+#define SSC_POWER_DOWN 0x01
+#define SSC_POWER_ON 0x00
+
+#define FPGA_VER 0x80
+#define HW_VER_MASK 0x0F
+
+#define EXTEND_DMA1_ASYNC_SIGNAL 0x02
+
+/* CFG_MODE*/
+#define XTAL_FREE 0x80
+#define CLK_MODE_MASK 0x03
+#define CLK_MODE_12M_XTAL 0x00
+#define CLK_MODE_NON_XTAL 0x01
+#define CLK_MODE_24M_OSC 0x02
+#define CLK_MODE_48M_OSC 0x03
+
+/* CFG_MODE_1*/
+#define RTS5179 0x02
+
+#define NYET_EN 0x01
+#define NYET_MSAK 0x01
+
+#define SD30_DRIVE_MASK 0x07
+#define SD20_DRIVE_MASK 0x03
+
+#define DISABLE_SD_CD 0x08
+#define DISABLE_MS_CD 0x10
+#define DISABLE_XD_CD 0x20
+#define SD_CD_DEGLITCH_EN 0x01
+#define MS_CD_DEGLITCH_EN 0x02
+#define XD_CD_DEGLITCH_EN 0x04
+
+#define CARD_SHARE_LQFP48 0x04
+#define CARD_SHARE_QFN24 0x00
+#define CARD_SHARE_LQFP_SEL 0x04
+#define CARD_SHARE_XD 0x00
+#define CARD_SHARE_SD 0x01
+#define CARD_SHARE_MS 0x02
+#define CARD_SHARE_MASK 0x03
+
+
+/* SD30_DRIVE_SEL */
+#define DRIVER_TYPE_A 0x05
+#define DRIVER_TYPE_B 0x03
+#define DRIVER_TYPE_C 0x02
+#define DRIVER_TYPE_D 0x01
+
+/* SD_BUS_STAT */
+#define SD_CLK_TOGGLE_EN 0x80
+#define SD_CLK_FORCE_STOP 0x40
+#define SD_DAT3_STATUS 0x10
+#define SD_DAT2_STATUS 0x08
+#define SD_DAT1_STATUS 0x04
+#define SD_DAT0_STATUS 0x02
+#define SD_CMD_STATUS 0x01
+
+/* SD_PAD_CTL */
+#define SD_IO_USING_1V8 0x80
+#define SD_IO_USING_3V3 0x7F
+#define TYPE_A_DRIVING 0x00
+#define TYPE_B_DRIVING 0x01
+#define TYPE_C_DRIVING 0x02
+#define TYPE_D_DRIVING 0x03
+
+/* CARD_CLK_EN */
+#define SD_CLK_EN 0x04
+#define MS_CLK_EN 0x08
+
+/* CARD_SELECT */
+#define SD_MOD_SEL 2
+#define MS_MOD_SEL 3
+
+/* CARD_SHARE_MODE */
+#define CARD_SHARE_LQFP48 0x04
+#define CARD_SHARE_QFN24 0x00
+#define CARD_SHARE_LQFP_SEL 0x04
+#define CARD_SHARE_XD 0x00
+#define CARD_SHARE_SD 0x01
+#define CARD_SHARE_MS 0x02
+#define CARD_SHARE_MASK 0x03
+
+/* SSC_CTL1 */
+#define SSC_RSTB 0x80
+#define SSC_8X_EN 0x40
+#define SSC_FIX_FRAC 0x20
+#define SSC_SEL_1M 0x00
+#define SSC_SEL_2M 0x08
+#define SSC_SEL_4M 0x10
+#define SSC_SEL_8M 0x18
+
+/* SSC_CTL2 */
+#define SSC_DEPTH_MASK 0x03
+#define SSC_DEPTH_DISALBE 0x00
+#define SSC_DEPTH_2M 0x01
+#define SSC_DEPTH_1M 0x02
+#define SSC_DEPTH_512K 0x03
+
+/* SD_VPCLK0_CTL */
+#define PHASE_CHANGE 0x80
+#define PHASE_NOT_RESET 0x40
+
+/* SD_TRANSFER */
+#define SD_TRANSFER_START 0x80
+#define SD_TRANSFER_END 0x40
+#define SD_STAT_IDLE 0x20
+#define SD_TRANSFER_ERR 0x10
+#define SD_TM_NORMAL_WRITE 0x00
+#define SD_TM_AUTO_WRITE_3 0x01
+#define SD_TM_AUTO_WRITE_4 0x02
+#define SD_TM_AUTO_READ_3 0x05
+#define SD_TM_AUTO_READ_4 0x06
+#define SD_TM_CMD_RSP 0x08
+#define SD_TM_AUTO_WRITE_1 0x09
+#define SD_TM_AUTO_WRITE_2 0x0A
+#define SD_TM_NORMAL_READ 0x0C
+#define SD_TM_AUTO_READ_1 0x0D
+#define SD_TM_AUTO_READ_2 0x0E
+#define SD_TM_AUTO_TUNING 0x0F
+
+/* SD_CFG1 */
+#define SD_CLK_DIVIDE_0 0x00
+#define SD_CLK_DIVIDE_256 0xC0
+#define SD_CLK_DIVIDE_128 0x80
+#define SD_CLK_DIVIDE_MASK 0xC0
+#define SD_BUS_WIDTH_1BIT 0x00
+#define SD_BUS_WIDTH_4BIT 0x01
+#define SD_BUS_WIDTH_8BIT 0x02
+#define SD_ASYNC_FIFO_RST 0x10
+#define SD_20_MODE 0x00
+#define SD_DDR_MODE 0x04
+#define SD_30_MODE 0x08
+
+/* SD_CFG2 */
+#define SD_CALCULATE_CRC7 0x00
+#define SD_NO_CALCULATE_CRC7 0x80
+#define SD_CHECK_CRC16 0x00
+#define SD_NO_CHECK_CRC16 0x40
+#define SD_WAIT_CRC_TO_EN 0x20
+#define SD_WAIT_BUSY_END 0x08
+#define SD_NO_WAIT_BUSY_END 0x00
+#define SD_CHECK_CRC7 0x00
+#define SD_NO_CHECK_CRC7 0x04
+#define SD_RSP_LEN_0 0x00
+#define SD_RSP_LEN_6 0x01
+#define SD_RSP_LEN_17 0x02
+#define SD_RSP_TYPE_R0 0x04
+#define SD_RSP_TYPE_R1 0x01
+#define SD_RSP_TYPE_R1b 0x09
+#define SD_RSP_TYPE_R2 0x02
+#define SD_RSP_TYPE_R3 0x05
+#define SD_RSP_TYPE_R4 0x05
+#define SD_RSP_TYPE_R5 0x01
+#define SD_RSP_TYPE_R6 0x01
+#define SD_RSP_TYPE_R7 0x01
+
+/* SD_STAT1 */
+#define SD_CRC7_ERR 0x80
+#define SD_CRC16_ERR 0x40
+#define SD_CRC_WRITE_ERR 0x20
+#define SD_CRC_WRITE_ERR_MASK 0x1C
+#define GET_CRC_TIME_OUT 0x02
+#define SD_TUNING_COMPARE_ERR 0x01
+
+/* SD_DATA_STATE */
+#define SD_DATA_IDLE 0x80
+
+/* CARD_DATA_SOURCE */
+#define PINGPONG_BUFFER 0x01
+#define RING_BUFFER 0x00
+
+/* CARD_OE */
+#define SD_OUTPUT_EN 0x04
+#define MS_OUTPUT_EN 0x08
+
+/* CARD_STOP */
+#define SD_STOP 0x04
+#define MS_STOP 0x08
+#define SD_CLR_ERR 0x40
+#define MS_CLR_ERR 0x80
+
+/* CARD_CLK_SOURCE */
+#define CRC_FIX_CLK (0x00 << 0)
+#define CRC_VAR_CLK0 (0x01 << 0)
+#define CRC_VAR_CLK1 (0x02 << 0)
+#define SD30_FIX_CLK (0x00 << 2)
+#define SD30_VAR_CLK0 (0x01 << 2)
+#define SD30_VAR_CLK1 (0x02 << 2)
+#define SAMPLE_FIX_CLK (0x00 << 4)
+#define SAMPLE_VAR_CLK0 (0x01 << 4)
+#define SAMPLE_VAR_CLK1 (0x02 << 4)
+
+/* SD_SAMPLE_POINT_CTL */
+#define DDR_FIX_RX_DAT 0x00
+#define DDR_VAR_RX_DAT 0x80
+#define DDR_FIX_RX_DAT_EDGE 0x00
+#define DDR_FIX_RX_DAT_14_DELAY 0x40
+#define DDR_FIX_RX_CMD 0x00
+#define DDR_VAR_RX_CMD 0x20
+#define DDR_FIX_RX_CMD_POS_EDGE 0x00
+#define DDR_FIX_RX_CMD_14_DELAY 0x10
+#define SD20_RX_POS_EDGE 0x00
+#define SD20_RX_14_DELAY 0x08
+#define SD20_RX_SEL_MASK 0x08
+
+/* SD_PUSH_POINT_CTL */
+#define DDR_FIX_TX_CMD_DAT 0x00
+#define DDR_VAR_TX_CMD_DAT 0x80
+#define DDR_FIX_TX_DAT_14_TSU 0x00
+#define DDR_FIX_TX_DAT_12_TSU 0x40
+#define DDR_FIX_TX_CMD_NEG_EDGE 0x00
+#define DDR_FIX_TX_CMD_14_AHEAD 0x20
+#define SD20_TX_NEG_EDGE 0x00
+#define SD20_TX_14_AHEAD 0x10
+#define SD20_TX_SEL_MASK 0x10
+#define DDR_VAR_SDCLK_POL_SWAP 0x01
+
+/* MS_CFG */
+#define SAMPLE_TIME_RISING 0x00
+#define SAMPLE_TIME_FALLING 0x80
+#define PUSH_TIME_DEFAULT 0x00
+#define PUSH_TIME_ODD 0x40
+#define NO_EXTEND_TOGGLE 0x00
+#define EXTEND_TOGGLE_CHK 0x20
+#define MS_BUS_WIDTH_1 0x00
+#define MS_BUS_WIDTH_4 0x10
+#define MS_BUS_WIDTH_8 0x18
+#define MS_2K_SECTOR_MODE 0x04
+#define MS_512_SECTOR_MODE 0x00
+#define MS_TOGGLE_TIMEOUT_EN 0x00
+#define MS_TOGGLE_TIMEOUT_DISEN 0x01
+#define MS_NO_CHECK_INT 0x02
+
+/* MS_TRANS_CFG */
+#define WAIT_INT 0x80
+#define NO_WAIT_INT 0x00
+#define NO_AUTO_READ_INT_REG 0x00
+#define AUTO_READ_INT_REG 0x40
+#define MS_CRC16_ERR 0x20
+#define MS_RDY_TIMEOUT 0x10
+#define MS_INT_CMDNK 0x08
+#define MS_INT_BREQ 0x04
+#define MS_INT_ERR 0x02
+#define MS_INT_CED 0x01
+
+/* MS_TRANSFER */
+#define MS_TRANSFER_START 0x80
+#define MS_TRANSFER_END 0x40
+#define MS_TRANSFER_ERR 0x20
+#define MS_BS_STATE 0x10
+#define MS_TM_READ_BYTES 0x00
+#define MS_TM_NORMAL_READ 0x01
+#define MS_TM_WRITE_BYTES 0x04
+#define MS_TM_NORMAL_WRITE 0x05
+#define MS_TM_AUTO_READ 0x08
+#define MS_TM_AUTO_WRITE 0x0C
+#define MS_TM_SET_CMD 0x06
+#define MS_TM_COPY_PAGE 0x07
+#define MS_TM_MULTI_READ 0x02
+#define MS_TM_MULTI_WRITE 0x03
+
+/* MC_FIFO_CTL */
+#define FIFO_FLUSH 0x01
+
+/* MC_DMA_RST */
+#define DMA_RESET 0x01
+
+/* MC_DMA_CTL */
+#define DMA_TC_EQ_0 0x80
+#define DMA_DIR_TO_CARD 0x00
+#define DMA_DIR_FROM_CARD 0x02
+#define DMA_EN 0x01
+#define DMA_128 (0 << 2)
+#define DMA_256 (1 << 2)
+#define DMA_512 (2 << 2)
+#define DMA_1024 (3 << 2)
+#define DMA_PACK_SIZE_MASK 0x0C
+
+/* CARD_INT_PEND */
+#define XD_INT 0x10
+#define MS_INT 0x08
+#define SD_INT 0x04
+
+/* LED operations*/
+static inline int rtsx_usb_turn_on_led(struct rtsx_ucr *ucr)
+{
+ return rtsx_usb_ep0_write_register(ucr, CARD_GPIO, 0x03, 0x02);
+}
+
+static inline int rtsx_usb_turn_off_led(struct rtsx_ucr *ucr)
+{
+ return rtsx_usb_ep0_write_register(ucr, CARD_GPIO, 0x03, 0x03);
+}
+
+/* HW error clearing */
+static inline void rtsx_usb_clear_fsm_err(struct rtsx_ucr *ucr)
+{
+ rtsx_usb_ep0_write_register(ucr, SFSM_ED, 0xf8, 0xf8);
+}
+
+static inline void rtsx_usb_clear_dma_err(struct rtsx_ucr *ucr)
+{
+ rtsx_usb_ep0_write_register(ucr, MC_FIFO_CTL,
+ FIFO_FLUSH, FIFO_FLUSH);
+ rtsx_usb_ep0_write_register(ucr, MC_DMA_RST, DMA_RESET, DMA_RESET);
+}
+#endif /* __RTS51139_H */
diff --git a/include/linux/mfd/tps65218.h b/include/linux/mfd/tps65218.h
new file mode 100644
index 0000000..d2e357d
--- /dev/null
+++ b/include/linux/mfd/tps65218.h
@@ -0,0 +1,284 @@
+/*
+ * linux/mfd/tps65218.h
+ *
+ * Functions to access TPS65219 power management chip.
+ *
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether expressed or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License version 2 for more details.
+ */
+
+#ifndef __LINUX_MFD_TPS65218_H
+#define __LINUX_MFD_TPS65218_H
+
+#include <linux/i2c.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/bitops.h>
+
+/* TPS chip id list */
+#define TPS65218 0xF0
+
+/* I2C ID for TPS65218 part */
+#define TPS65218_I2C_ID 0x24
+
+/* All register addresses */
+#define TPS65218_REG_CHIPID 0x00
+#define TPS65218_REG_INT1 0x01
+#define TPS65218_REG_INT2 0x02
+#define TPS65218_REG_INT_MASK1 0x03
+#define TPS65218_REG_INT_MASK2 0x04
+#define TPS65218_REG_STATUS 0x05
+#define TPS65218_REG_CONTROL 0x06
+#define TPS65218_REG_FLAG 0x07
+
+#define TPS65218_REG_PASSWORD 0x10
+#define TPS65218_REG_ENABLE1 0x11
+#define TPS65218_REG_ENABLE2 0x12
+#define TPS65218_REG_CONFIG1 0x13
+#define TPS65218_REG_CONFIG2 0x14
+#define TPS65218_REG_CONFIG3 0x15
+#define TPS65218_REG_CONTROL_DCDC1 0x16
+#define TPS65218_REG_CONTROL_DCDC2 0x17
+#define TPS65218_REG_CONTROL_DCDC3 0x18
+#define TPS65218_REG_CONTROL_DCDC4 0x19
+#define TPS65218_REG_CONTRL_SLEW_RATE 0x1A
+#define TPS65218_REG_CONTROL_LDO1 0x1B
+#define TPS65218_REG_SEQ1 0x20
+#define TPS65218_REG_SEQ2 0x21
+#define TPS65218_REG_SEQ3 0x22
+#define TPS65218_REG_SEQ4 0x23
+#define TPS65218_REG_SEQ5 0x24
+#define TPS65218_REG_SEQ6 0x25
+#define TPS65218_REG_SEQ7 0x26
+
+/* Register field definitions */
+#define TPS65218_CHIPID_CHIP_MASK 0xF8
+#define TPS65218_CHIPID_REV_MASK 0x07
+
+#define TPS65218_INT1_VPRG BIT(5)
+#define TPS65218_INT1_AC BIT(4)
+#define TPS65218_INT1_PB BIT(3)
+#define TPS65218_INT1_HOT BIT(2)
+#define TPS65218_INT1_CC_AQC BIT(1)
+#define TPS65218_INT1_PRGC BIT(0)
+
+#define TPS65218_INT2_LS3_F BIT(5)
+#define TPS65218_INT2_LS2_F BIT(4)
+#define TPS65218_INT2_LS1_F BIT(3)
+#define TPS65218_INT2_LS3_I BIT(2)
+#define TPS65218_INT2_LS2_I BIT(1)
+#define TPS65218_INT2_LS1_I BIT(0)
+
+#define TPS65218_INT_MASK1_VPRG BIT(5)
+#define TPS65218_INT_MASK1_AC BIT(4)
+#define TPS65218_INT_MASK1_PB BIT(3)
+#define TPS65218_INT_MASK1_HOT BIT(2)
+#define TPS65218_INT_MASK1_CC_AQC BIT(1)
+#define TPS65218_INT_MASK1_PRGC BIT(0)
+
+#define TPS65218_INT_MASK2_LS3_F BIT(5)
+#define TPS65218_INT_MASK2_LS2_F BIT(4)
+#define TPS65218_INT_MASK2_LS1_F BIT(3)
+#define TPS65218_INT_MASK2_LS3_I BIT(2)
+#define TPS65218_INT_MASK2_LS2_I BIT(1)
+#define TPS65218_INT_MASK2_LS1_I BIT(0)
+
+#define TPS65218_STATUS_FSEAL BIT(7)
+#define TPS65218_STATUS_EE BIT(6)
+#define TPS65218_STATUS_AC_STATE BIT(5)
+#define TPS65218_STATUS_PB_STATE BIT(4)
+#define TPS65218_STATUS_STATE_MASK 0xC
+#define TPS65218_STATUS_CC_STAT 0x3
+
+#define TPS65218_CONTROL_OFFNPFO BIT(1)
+#define TPS65218_CONTROL_CC_AQ BIT(0)
+
+#define TPS65218_FLAG_GPO3_FLG BIT(7)
+#define TPS65218_FLAG_GPO2_FLG BIT(6)
+#define TPS65218_FLAG_GPO1_FLG BIT(5)
+#define TPS65218_FLAG_LDO1_FLG BIT(4)
+#define TPS65218_FLAG_DC4_FLG BIT(3)
+#define TPS65218_FLAG_DC3_FLG BIT(2)
+#define TPS65218_FLAG_DC2_FLG BIT(1)
+#define TPS65218_FLAG_DC1_FLG BIT(0)
+
+#define TPS65218_ENABLE1_DC6_EN BIT(5)
+#define TPS65218_ENABLE1_DC5_EN BIT(4)
+#define TPS65218_ENABLE1_DC4_EN BIT(3)
+#define TPS65218_ENABLE1_DC3_EN BIT(2)
+#define TPS65218_ENABLE1_DC2_EN BIT(1)
+#define TPS65218_ENABLE1_DC1_EN BIT(0)
+
+#define TPS65218_ENABLE2_GPIO3 BIT(6)
+#define TPS65218_ENABLE2_GPIO2 BIT(5)
+#define TPS65218_ENABLE2_GPIO1 BIT(4)
+#define TPS65218_ENABLE2_LS3_EN BIT(3)
+#define TPS65218_ENABLE2_LS2_EN BIT(2)
+#define TPS65218_ENABLE2_LS1_EN BIT(1)
+#define TPS65218_ENABLE2_LDO1_EN BIT(0)
+
+
+#define TPS65218_CONFIG1_TRST BIT(7)
+#define TPS65218_CONFIG1_GPO2_BUF BIT(6)
+#define TPS65218_CONFIG1_IO1_SEL BIT(5)
+#define TPS65218_CONFIG1_PGDLY_MASK 0x18
+#define TPS65218_CONFIG1_STRICT BIT(2)
+#define TPS65218_CONFIG1_UVLO_MASK 0x3
+
+#define TPS65218_CONFIG2_DC12_RST BIT(7)
+#define TPS65218_CONFIG2_UVLOHYS BIT(6)
+#define TPS65218_CONFIG2_LS3ILIM_MASK 0xC
+#define TPS65218_CONFIG2_LS2ILIM_MASK 0x3
+
+#define TPS65218_CONFIG3_LS3NPFO BIT(5)
+#define TPS65218_CONFIG3_LS2NPFO BIT(4)
+#define TPS65218_CONFIG3_LS1NPFO BIT(3)
+#define TPS65218_CONFIG3_LS3DCHRG BIT(2)
+#define TPS65218_CONFIG3_LS2DCHRG BIT(1)
+#define TPS65218_CONFIG3_LS1DCHRG BIT(0)
+
+#define TPS65218_CONTROL_DCDC1_PFM BIT(7)
+#define TPS65218_CONTROL_DCDC1_MASK 0x7F
+
+#define TPS65218_CONTROL_DCDC2_PFM BIT(7)
+#define TPS65218_CONTROL_DCDC2_MASK 0x3F
+
+#define TPS65218_CONTROL_DCDC3_PFM BIT(7)
+#define TPS65218_CONTROL_DCDC3_MASK 0x3F
+
+#define TPS65218_CONTROL_DCDC4_PFM BIT(7)
+#define TPS65218_CONTROL_DCDC4_MASK 0x3F
+
+#define TPS65218_SLEW_RATE_GO BIT(7)
+#define TPS65218_SLEW_RATE_GODSBL BIT(6)
+#define TPS65218_SLEW_RATE_SLEW_MASK 0x7
+
+#define TPS65218_CONTROL_LDO1_MASK 0x3F
+
+#define TPS65218_SEQ1_DLY8 BIT(7)
+#define TPS65218_SEQ1_DLY7 BIT(6)
+#define TPS65218_SEQ1_DLY6 BIT(5)
+#define TPS65218_SEQ1_DLY5 BIT(4)
+#define TPS65218_SEQ1_DLY4 BIT(3)
+#define TPS65218_SEQ1_DLY3 BIT(2)
+#define TPS65218_SEQ1_DLY2 BIT(1)
+#define TPS65218_SEQ1_DLY1 BIT(0)
+
+#define TPS65218_SEQ2_DLYFCTR BIT(7)
+#define TPS65218_SEQ2_DLY9 BIT(0)
+
+#define TPS65218_SEQ3_DC2_SEQ_MASK 0xF0
+#define TPS65218_SEQ3_DC1_SEQ_MASK 0xF
+
+#define TPS65218_SEQ4_DC4_SEQ_MASK 0xF0
+#define TPS65218_SEQ4_DC3_SEQ_MASK 0xF
+
+#define TPS65218_SEQ5_DC6_SEQ_MASK 0xF0
+#define TPS65218_SEQ5_DC5_SEQ_MASK 0xF
+
+#define TPS65218_SEQ6_LS1_SEQ_MASK 0xF0
+#define TPS65218_SEQ6_LDO1_SEQ_MASK 0xF
+
+#define TPS65218_SEQ7_GPO3_SEQ_MASK 0xF0
+#define TPS65218_SEQ7_GPO1_SEQ_MASK 0xF
+#define TPS65218_PROTECT_NONE 0
+#define TPS65218_PROTECT_L1 1
+
+enum tps65218_regulator_id {
+ /* DCDC's */
+ TPS65218_DCDC_1,
+ TPS65218_DCDC_2,
+ TPS65218_DCDC_3,
+ TPS65218_DCDC_4,
+ TPS65218_DCDC_5,
+ TPS65218_DCDC_6,
+ /* LDOs */
+ TPS65218_LDO_1,
+};
+
+#define TPS65218_MAX_REG_ID TPS65218_LDO_1
+
+/* Number of step-down converters available */
+#define TPS65218_NUM_DCDC 6
+/* Number of LDO voltage regulators available */
+#define TPS65218_NUM_LDO 1
+/* Number of total regulators available */
+#define TPS65218_NUM_REGULATOR (TPS65218_NUM_DCDC + TPS65218_NUM_LDO)
+
+/* Define the TPS65218 IRQ numbers */
+enum tps65218_irqs {
+ /* INT1 registers */
+ TPS65218_PRGC_IRQ,
+ TPS65218_CC_AQC_IRQ,
+ TPS65218_HOT_IRQ,
+ TPS65218_PB_IRQ,
+ TPS65218_AC_IRQ,
+ TPS65218_VPRG_IRQ,
+ TPS65218_INVALID1_IRQ,
+ TPS65218_INVALID2_IRQ,
+ /* INT2 registers */
+ TPS65218_LS1_I_IRQ,
+ TPS65218_LS2_I_IRQ,
+ TPS65218_LS3_I_IRQ,
+ TPS65218_LS1_F_IRQ,
+ TPS65218_LS2_F_IRQ,
+ TPS65218_LS3_F_IRQ,
+ TPS65218_INVALID3_IRQ,
+ TPS65218_INVALID4_IRQ,
+};
+
+/**
+ * struct tps_info - packages regulator constraints
+ * @id: Id of the regulator
+ * @name: Voltage regulator name
+ * @min_uV: minimum micro volts
+ * @max_uV: minimum micro volts
+ *
+ * This data is used to check the regualtor voltage limits while setting.
+ */
+struct tps_info {
+ int id;
+ const char *name;
+ int min_uV;
+ int max_uV;
+};
+
+/**
+ * struct tps65218 - tps65218 sub-driver chip access routines
+ *
+ * Device data may be used to access the TPS65218 chip
+ */
+
+struct tps65218 {
+ struct device *dev;
+ unsigned int id;
+
+ struct mutex tps_lock; /* lock guarding the data structure */
+ /* IRQ Data */
+ int irq;
+ u32 irq_mask;
+ struct regmap_irq_chip_data *irq_data;
+ struct regulator_desc desc[TPS65218_NUM_REGULATOR];
+ struct regulator_dev *rdev[TPS65218_NUM_REGULATOR];
+ struct tps_info *info[TPS65218_NUM_REGULATOR];
+ struct regmap *regmap;
+};
+
+int tps65218_reg_read(struct tps65218 *tps, unsigned int reg,
+ unsigned int *val);
+int tps65218_reg_write(struct tps65218 *tps, unsigned int reg,
+ unsigned int val, unsigned int level);
+int tps65218_set_bits(struct tps65218 *tps, unsigned int reg,
+ unsigned int mask, unsigned int val, unsigned int level);
+int tps65218_clear_bits(struct tps65218 *tps, unsigned int reg,
+ unsigned int mask, unsigned int level);
+
+#endif /* __LINUX_MFD_TPS65218_H */
diff --git a/include/linux/ssbi.h b/include/linux/ssbi.h
index bcbb642..087b08a 100644
--- a/include/linux/ssbi.h
+++ b/include/linux/ssbi.h
@@ -20,4 +20,24 @@
int ssbi_write(struct device *dev, u16 addr, const u8 *buf, int len);
int ssbi_read(struct device *dev, u16 addr, u8 *buf, int len);
+static inline int
+ssbi_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ int ret;
+ u8 v;
+
+ ret = ssbi_read(context, reg, &v, 1);
+ if (!ret)
+ *val = v;
+
+ return ret;
+}
+
+static inline int
+ssbi_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ u8 v = val;
+ return ssbi_write(context, reg, &v, 1);
+}
+
#endif
OpenPOWER on IntegriCloud