mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
== 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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) iQIcBAABAgAGBQJTQmHbAAoJEFGvii+H/HdhXgAQAI6dNLb3AfNol49pNh5nEcrt sixQwu56xe64xozcMq41oXcbIe6NOvd/Sgf57fowCqrNyXd3k2sp6/KzA1yM8yfc 2Xfm2fzzMoyH3lEopepT0zKMEyeOKxCNJWInXjRDmR6EN8szV/gAvwEptXnXKq8n sANQCBr2A1sDAlxu5onDI6SGEibCZgSsW+EElPyNKjXyIXdATv+ZLSuNCapt2Zg2 H/KM+CY2hlcl6quWwjEUtPF4Ux0hIv3ePkwDKQicXMgndxL3+aL5L66UHsIovgxW o9H2aA6cfOQJuAXAZUvHlsNlefFW5qpFFR8kXiW87Say3+7nijoe5DhH/RBSZN+i O0rbxWVa1rW9eYmHuKAPNMR8Lp4FN9OvBo/Yv3UfmMV661vLVLOvTwJI9GZg7v8o UPMDhYNgEnRNrWqf7Wkj9ywgvGaO8qggm7gpE2cFD8DGDR7aZQ9goRKpaVSjTNmW 4staek1u4g7YQ9s2UXxQ0JFc7esMbUbXxv5Bmk+4JPiI3P4gDMTg7jhh5iKDcEs5 BVUIfdYKF9LInfYT3o9Uvo6TbYeAfwwzOdMFDWa5BjGOCLD9ttOEGtqMD/bkANbn YsaD6xKEL+su37CocSPnekgU+IS0uLb15jpa06CmoaALPGAZcRffKMygSHtlyGtR pNazlO93tu9JXQcL5B+A =p4SP -----END PGP SIGNATURE----- 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 ...
This commit is contained in:
commit
e5744abb2f
24
Documentation/devicetree/bindings/iio/adc/twl4030-madc.txt
Normal file
24
Documentation/devicetree/bindings/iio/adc/twl4030-madc.txt
Normal file
@ -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>;
|
||||
};
|
||||
};
|
@ -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
|
||||
>;
|
||||
};
|
||||
|
37
Documentation/devicetree/bindings/mfd/bcm590xx.txt
Normal file
37
Documentation/devicetree/bindings/mfd/bcm590xx.txt
Normal file
@ -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>;
|
||||
};
|
||||
|
||||
...
|
||||
};
|
||||
};
|
72
Documentation/devicetree/bindings/mfd/da9055.txt
Normal file
72
Documentation/devicetree/bindings/mfd/da9055.txt
Normal file
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
@ -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
|
||||
|
@ -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 {
|
||||
|
96
Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt
Normal file
96
Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt
Normal file
@ -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>;
|
||||
};
|
||||
};
|
@ -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";
|
||||
};
|
||||
|
@ -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";
|
||||
|
@ -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";
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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"),
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
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);
|
||||
goto out;
|
||||
}
|
||||
ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_lsb, 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)
|
||||
return -ENOMEM;
|
||||
|
||||
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);
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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 = {
|
||||
|
93
drivers/mfd/bcm590xx.c
Normal file
93
drivers/mfd/bcm590xx.c
Normal file
@ -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");
|
@ -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>
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -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),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
||||
@ -437,6 +440,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 = {
|
||||
@ -509,6 +520,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 = {
|
||||
@ -532,6 +551,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 = {
|
||||
|
@ -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->gpio.save >= 0) {
|
||||
pci_write_config_byte(dev, priv->gpio.ctrl, priv->gpio.save);
|
||||
priv->gpio.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->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, ®_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, ®_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, ®_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, ®_save);
|
||||
pci_write_config_byte(dev, priv->gpio.ctrl, reg_save | 0x10);
|
||||
priv->gpio.save = reg_save;
|
||||
pci_read_config_byte(dev, priv->gctrl, ®_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, ®_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
|
||||
|
@ -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>
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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, ®map_mc13xxx_bus,
|
||||
&spi->dev,
|
||||
&mc13xxx_regmap_spi_config);
|
||||
|
@ -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>
|
||||
|
@ -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))
|
||||
omap->utmi_clk[i] = ERR_PTR(-ENODEV);
|
||||
omap->hsic480m_clk[i] = ERR_PTR(-ENODEV);
|
||||
omap->hsic60m_clk[i] = ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 */
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
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 (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);
|
||||
|
||||
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 0;
|
||||
|
||||
err:
|
||||
mfd_remove_devices(pmic->dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int pm8921_remove_child(struct device *dev, void *unused)
|
||||
{
|
||||
platform_device_unregister(to_platform_device(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pm8921_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct pm8xxx_drvdata *drvdata;
|
||||
struct pm8921 *pmic = NULL;
|
||||
int irq = platform_get_irq(pdev, 0);
|
||||
struct pm8921 *pmic = pm8921_drvdata.pm_chip_data;
|
||||
struct pm_irq_chip *chip = pmic->irq_chip;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
760
drivers/mfd/rtsx_usb.c
Normal file
760
drivers/mfd/rtsx_usb.c
Normal file
@ -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");
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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");
|
@ -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);
|
||||
|
@ -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",
|
||||
|
282
drivers/mfd/tps65218.c
Normal file
282
drivers/mfd/tps65218.c
Normal file
@ -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");
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
val32 &= 0xffffffdf;
|
||||
writel(val32, 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);
|
||||
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_pmc);
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
31
include/linux/mfd/bcm590xx.h
Normal file
31
include/linux/mfd/bcm590xx.h
Normal file
@ -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 */
|
@ -83,6 +83,7 @@ enum da9052_chip_id {
|
||||
DA9053_AA,
|
||||
DA9053_BA,
|
||||
DA9053_BB,
|
||||
DA9053_BC,
|
||||
};
|
||||
|
||||
struct da9052_pdata;
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
@ -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
|
628
include/linux/mfd/rtsx_usb.h
Normal file
628
include/linux/mfd/rtsx_usb.h
Normal file
@ -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 */
|
284
include/linux/mfd/tps65218.h
Normal file
284
include/linux/mfd/tps65218.h
Normal file
@ -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 */
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user