diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-15 06:58:16 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-15 06:58:16 +0200 |
commit | fcc3a5d277571bc6048e7b4ef8cd391b935de629 (patch) | |
tree | 143954c115011c657f747a0e1470973b94ab3690 | |
parent | 50fa86172bec2769979b5eb0cd1a244391ae4bb0 (diff) | |
parent | d86c21fd31114e3ef9fae64be335c76aa22859dc (diff) | |
download | lwn-fcc3a5d277571bc6048e7b4ef8cd391b935de629.tar.gz lwn-fcc3a5d277571bc6048e7b4ef8cd391b935de629.zip |
Merge tag 'mfd-for-linus-3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones:
"Changes to existing drivers:
- DT clean-ups in da9055-core, max14577, rn5t618, arizona, hi6421, stmpe, twl4030
- Export symbols for use in modules in max14577
- Plenty of static code analysis/Coccinelle fixes throughout the SS
- Regmap clean-ups in arizona, wm5102, wm5110, da9052, tps65217, rk808
- Remove unused/duplicate code in da9052, 88pm860x, ti_ssp, lpc_sch, arizona
- Bug fixes in ti_am335x_tscadc, da9052, ti_am335x_tscadc, rtsx_pcr
- IRQ fixups in arizona, stmpe, max14577
- Regulator related changes in axp20x
- Pass DMA coherency information from parent => child in MFD core
- Rename DT document files for consistency
- Add ACPI support to the MFD core
- Add Andreas Werner to MAINTAINERS for MEN F21BMC
New drivers/supported devices:
- New driver for MEN 14F021P00 Board Management Controller
- New driver for Ricoh RN5T618 PMIC
- New driver for Rockchip RK808
- New driver for HiSilicon Hi6421 PMIC
- New driver for Qualcomm SPMI PMICs
- Add support for Intel Braswell in lpc_ich
- Add support for Intel 9 Series PCH in lpc_ich
- Add support for Intel Quark ILB in lpc_sch"
[ Delayed to after the poweer/reset pull due to Kconfig problems with
recursive Kconfig select/depends-on chains. - Linus ]
* tag 'mfd-for-linus-3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (79 commits)
mfd: cros_ec: wait for completion of commands that return IN_PROGRESS
i2c: i2c-cros-ec-tunnel: Set retries to 3
mfd: cros_ec: move locking into cros_ec_cmd_xfer
mfd: cros_ec: stop calling ->cmd_xfer() directly
mfd: cros_ec: Delay for 50ms when we see EC_CMD_REBOOT_EC
MAINTAINERS: Adds Andreas Werner to maintainers list for MEN F21BMC
mfd: arizona: Correct mask to allow setting micbias external cap
mfd: Add ACPI support
Revert "mfd: wm5102: Manually apply register patch"
mfd: ti_am335x_tscadc: Update logic in CTRL register for 5-wire TS
mfd: dt-bindings: atmel-gpbr: Rename doc file to conform to naming convention
mfd: dt-bindings: qcom-pm8xxx: Rename doc file to conform to naming convention
mfd: Inherit coherent_dma_mask from parent device
mfd: Document DT bindings for Qualcomm SPMI PMICs
mfd: Add support for Qualcomm SPMI PMICs
mfd: dt-bindings: pm8xxx: Add new compatible string
mfd: axp209x: Drop the parent supplies field
mfd: twl4030-power: Use 'ti,system-power-controller' as alternative way to support system power off
mfd: dt-bindings: twl4030-power: Use the standard property to mark power control
mfd: syscon: Add Atmel GPBR DT bindings documention
...
70 files changed, 2061 insertions, 403 deletions
diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt index e182be5e3c83..b60d2ab69497 100644 --- a/Documentation/acpi/enumeration.txt +++ b/Documentation/acpi/enumeration.txt @@ -312,3 +312,30 @@ a code like this: There are also devm_* versions of these functions which release the descriptors once the device is released. + +MFD devices +~~~~~~~~~~~ +The MFD devices register their children as platform devices. For the child +devices there needs to be an ACPI handle that they can use to reference +parts of the ACPI namespace that relate to them. In the Linux MFD subsystem +we provide two ways: + + o The children share the parent ACPI handle. + o The MFD cell can specify the ACPI id of the device. + +For the first case, the MFD drivers do not need to do anything. The +resulting child platform device will have its ACPI_COMPANION() set to point +to the parent device. + +If the ACPI namespace has a device that we can match using an ACPI id, +the id should be set like: + + static struct mfd_cell my_subdevice_cell = { + .name = "my_subdevice", + /* set the resources relative to the parent */ + .acpi_pnpid = "XYZ0001", + }; + +The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under +the MFD device and if found, that ACPI companion device is bound to the +resulting child platform device. diff --git a/Documentation/devicetree/bindings/mfd/arizona.txt b/Documentation/devicetree/bindings/mfd/arizona.txt index 5c7e7230984a..7bd1273f571a 100644 --- a/Documentation/devicetree/bindings/mfd/arizona.txt +++ b/Documentation/devicetree/bindings/mfd/arizona.txt @@ -42,6 +42,13 @@ Optional properties: the chip default will be used. If present exactly five values must be specified. + - wlf,inmode : A list of INn_MODE register values, where n is the number + of input signals. Valid values are 0 (Differential), 1 (Single-ended) and + 2 (Digital Microphone). If absent, INn_MODE registers set to 0 by default. + If present, values must be specified less than or equal to the number of + input singals. If values less than the number of input signals, elements + that has not been specifed are set to 0 by default. + - DCVDD-supply, MICVDD-supply : Power supplies, only need to be specified if they are being externally supplied. As covered in Documentation/devicetree/bindings/regulator/regulator.txt diff --git a/Documentation/devicetree/bindings/mfd/atmel-gpbr.txt b/Documentation/devicetree/bindings/mfd/atmel-gpbr.txt new file mode 100644 index 000000000000..a28569540683 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/atmel-gpbr.txt @@ -0,0 +1,15 @@ +* Device tree bindings for Atmel GPBR (General Purpose Backup Registers) + +The GPBR are a set of battery-backed registers. + +Required properties: +- compatible: "atmel,at91sam9260-gpbr", "syscon" +- reg: contains offset/length value of the GPBR memory + region. + +Example: + +gpbr: gpbr@fffffd50 { + compatible = "atmel,at91sam9260-gpbr", "syscon"; + reg = <0xfffffd50 0x10>; +}; diff --git a/Documentation/devicetree/bindings/mfd/hi6421.txt b/Documentation/devicetree/bindings/mfd/hi6421.txt new file mode 100644 index 000000000000..0d5a4466a494 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/hi6421.txt @@ -0,0 +1,38 @@ +* HI6421 Multi-Functional Device (MFD), by HiSilicon Ltd. + +Required parent device properties: +- compatible : contains "hisilicon,hi6421-pmic"; +- reg : register range space of hi6421; + +Supported Hi6421 sub-devices include: + +Device IRQ Names Supply Names Description +------ --------- ------------ ----------- +regulators : None : None : Regulators + +Required child device properties: +None. + +Example: + hi6421 { + compatible = "hisilicon,hi6421-pmic"; + reg = <0xfcc00000 0x0180>; /* 0x60 << 2 */ + + regulators { + // supply for MLC NAND/ eMMC + hi6421_vout0_reg: hi6421_vout0 { + regulator-name = "VOUT0"; + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; + + // supply for 26M Oscillator + hi6421_vout1_reg: hi6421_vout1 { + regulator-name = "VOUT1"; + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <2000000>; + regulator-boot-on; + regulator-always-on; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.txt b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.txt new file mode 100644 index 000000000000..7182b8857f57 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.txt @@ -0,0 +1,64 @@ + Qualcomm SPMI PMICs multi-function device bindings + +The Qualcomm SPMI series presently includes PM8941, PM8841 and PMA8084 +PMICs. These PMICs use a QPNP scheme through SPMI interface. +QPNP is effectively a partitioning scheme for dividing the SPMI extended +register space up into logical pieces, and set of fixed register +locations/definitions within these regions, with some of these regions +specifically used for interrupt handling. + +The QPNP PMICs are used with the Qualcomm Snapdragon series SoCs, and are +interfaced to the chip via the SPMI (System Power Management Interface) bus. +Support for multiple independent functions are implemented by splitting the +16-bit SPMI slave address space into 256 smaller fixed-size regions, 256 bytes +each. A function can consume one or more of these fixed-size register regions. + +Required properties: +- compatible: Should contain one of: + "qcom,pm8941" + "qcom,pm8841" + "qcom,pma8084" + or generalized "qcom,spmi-pmic". +- reg: Specifies the SPMI USID slave address for this device. + For more information see: + Documentation/devicetree/bindings/spmi/spmi.txt + +Required properties for peripheral child nodes: +- compatible: Should contain "qcom,xxx", where "xxx" is a peripheral name. + +Optional properties for peripheral child nodes: +- interrupts: Interrupts are specified as a 4-tuple. For more information + see: + Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt +- interrupt-names: Corresponding interrupt name to the interrupts property + +Each child node of SPMI slave id represents a function of the PMIC. In the +example below the rtc device node represents a peripheral of pm8941 +SID = 0. The regulator device node represents a peripheral of pm8941 SID = 1. + +Example: + + spmi { + compatible = "qcom,spmi-pmic-arb"; + + pm8941@0 { + compatible = "qcom,pm8941", "qcom,spmi-pmic"; + reg = <0x0 SPMI_USID>; + + rtc { + compatible = "qcom,rtc"; + interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "alarm"; + }; + }; + + pm8941@1 { + compatible = "qcom,pm8941", "qcom,spmi-pmic"; + reg = <0x1 SPMI_USID>; + + regulator { + compatible = "qcom,regulator"; + regulator-name = "8941_boost"; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt index 03518dc8b6bd..f24f33409164 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt +++ b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt @@ -61,6 +61,7 @@ The below bindings specify the set of valid subnodes. Definition: must be one of: "qcom,pm8058-rtc" "qcom,pm8921-rtc" + "qcom,pm8941-rtc" - reg: Usage: required diff --git a/Documentation/devicetree/bindings/mfd/rk808.txt b/Documentation/devicetree/bindings/mfd/rk808.txt new file mode 100644 index 000000000000..9e6e2592e5c8 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/rk808.txt @@ -0,0 +1,177 @@ +RK808 Power Management Integrated Circuit + +Required properties: +- compatible: "rockchip,rk808" +- reg: I2C slave address +- interrupt-parent: The parent interrupt controller. +- interrupts: the interrupt outputs of the controller. +- #clock-cells: from common clock binding; shall be set to 1 (multiple clock + outputs). See <dt-bindings/clock/rockchip,rk808.h> for clock IDs. + +Optional properties: +- clock-output-names: From common clock binding to override the + default output clock name +- rockchip,system-power-controller: Telling whether or not this pmic is controlling + the system power. +- vcc1-supply: The input supply for DCDC_REG1 +- vcc2-supply: The input supply for DCDC_REG2 +- vcc3-supply: The input supply for DCDC_REG3 +- vcc4-supply: The input supply for DCDC_REG4 +- vcc6-supply: The input supply for LDO_REG1 and LDO_REG2 +- vcc7-supply: The input supply for LDO_REG3 and LDO_REG7 +- vcc8-supply: The input supply for SWITCH_REG1 +- vcc9-supply: The input supply for LDO_REG4 and LDO_REG5 +- vcc10-supply: The input supply for LDO_REG6 +- vcc11-supply: The input supply for LDO_REG8 +- vcc12-supply: The input supply for SWITCH_REG2 + +Regulators: All the regulators of RK808 to be instantiated shall be +listed in a child node named 'regulators'. Each regulator is represented +by a child node of the 'regulators' node. + + regulator-name { + /* standard regulator bindings here */ + }; + +Following regulators of the RK808 PMIC block are supported. Note that +the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO +number as described in RK808 datasheet. + + - DCDC_REGn + - valid values for n are 1 to 4. + - LDO_REGn + - valid values for n are 1 to 8. + - SWITCH_REGn + - valid values for n are 1 to 2 + +Standard regulator bindings are used inside regulator subnodes. Check + Documentation/devicetree/bindings/regulator/regulator.txt +for more details + +Example: + rk808: pmic@1b { + compatible = "rockchip,rk808"; + clock-output-names = "xin32k", "rk808-clkout2"; + interrupt-parent = <&gpio0>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + reg = <0x1b>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + + vcc8-supply = <&vcc_18>; + vcc9-supply = <&vcc_io>; + vcc10-supply = <&vcc_io>; + vcc12-supply = <&vcc_io>; + vddio-supply = <&vccio_pmu>; + + regulators { + vdd_cpu: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1300000>; + regulator-name = "vdd_arm"; + }; + + vdd_gpu: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1250000>; + regulator-name = "vdd_gpu"; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + }; + + vcc_io: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_io"; + }; + + vccio_pmu: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_pmu"; + }; + + vcc_tp: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_tp"; + }; + + vdd_10: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-name = "vdd_10"; + }; + + vcc18_lcd: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc18_lcd"; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_sd"; + }; + + vdd10_lcd: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-name = "vdd10_lcd"; + }; + + vcc_18: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_18"; + }; + + vcca_codec: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcca_codec"; + }; + + vcc_wl: SWITCH_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_wl"; + }; + + vcc_lcd: SWITCH_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_lcd"; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/rn5t618.txt b/Documentation/devicetree/bindings/mfd/rn5t618.txt new file mode 100644 index 000000000000..937785a3eddc --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/rn5t618.txt @@ -0,0 +1,36 @@ +* Ricoh RN5T618 PMIC + +Ricoh RN5T618 is a power management IC which integrates 3 step-down +DCDC converters, 7 low-dropout regulators, a Li-ion battery charger, +fuel gauge, ADC, GPIOs and a watchdog timer. It can be controlled +through a I2C interface. + +Required properties: + - compatible: should be "ricoh,rn5t618" + - reg: the I2C slave address of the device + +Sub-nodes: + - regulators: the node is required if the regulator functionality is + needed. The valid regulator names are: DCDC1, DCDC2, DCDC3, LDO1, + LDO2, LDO3, LDO4, LDO5, LDORTC1 and LDORTC2. + The common bindings for each individual regulator can be found in: + Documentation/devicetree/bindings/regulator/regulator.txt + +Example: + + pmic@32 { + compatible = "ricoh,rn5t618"; + reg = <0x32>; + + regulators { + DCDC1 { + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1050000>; + }; + + DCDC2 { + regulator-min-microvolt = <1175000>; + regulator-max-microvolt = <1175000>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/stmpe.txt b/Documentation/devicetree/bindings/mfd/stmpe.txt index 56edb5520685..3fb68bfefc8b 100644 --- a/Documentation/devicetree/bindings/mfd/stmpe.txt +++ b/Documentation/devicetree/bindings/mfd/stmpe.txt @@ -13,6 +13,7 @@ Optional properties: - interrupt-parent : Specifies which IRQ controller we're connected to - wakeup-source : Marks the input device as wakable - st,autosleep-timeout : Valid entries (ms); 4, 16, 32, 64, 128, 256, 512 and 1024 + - irq-gpio : If present, which GPIO to use for event IRQ Example: diff --git a/Documentation/devicetree/bindings/mfd/twl4030-power.txt b/Documentation/devicetree/bindings/mfd/twl4030-power.txt index b9ee7b98d3e2..3d19963312ce 100644 --- a/Documentation/devicetree/bindings/mfd/twl4030-power.txt +++ b/Documentation/devicetree/bindings/mfd/twl4030-power.txt @@ -23,8 +23,13 @@ down during off-idle. Note that this does not work on all boards depending on how the external oscillator is wired. Optional properties: -- ti,use_poweroff: With this flag, the chip will initiates an ACTIVE-to-OFF or - SLEEP-to-OFF transition when the system poweroffs. + +- ti,system-power-controller: This indicates that TWL4030 is the + power supply master of the system. With this flag, the chip will + initiate an ACTIVE-to-OFF or SLEEP-to-OFF transition when the + system poweroffs. + +- ti,use_poweroff: Deprecated name for ti,system-power-controller Example: &i2c1 { diff --git a/MAINTAINERS b/MAINTAINERS index ee1bc5bc20ad..b0f17d59078e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6010,6 +6010,15 @@ S: Supported F: drivers/mcb/ F: include/linux/mcb.h +MEN F21BMC (Board Management Controller) +M: Andreas Werner <andreas.werner@men.de> +S: Supported +F: drivers/mfd/menf21bmc.c +F: drivers/watchdog/menf21bmc_wdt.c +F: drivers/leds/leds-menf21bmc.c +F: drivers/hwmon/menf21bmc_hwmon.c +F: Documentation/hwmon/menf21bmc + METAG ARCHITECTURE M: James Hogan <james.hogan@imgtec.com> L: linux-metag@vger.kernel.org diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c index 05e033c98115..8ca5cbbcec91 100644 --- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c @@ -16,6 +16,8 @@ #include <linux/platform_device.h> #include <linux/slab.h> +#define I2C_MAX_RETRIES 3 + /** * struct ec_i2c_device - Driver data for I2C tunnel * @@ -227,7 +229,7 @@ static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[], msg.indata = response; msg.insize = response_len; - result = bus->ec->cmd_xfer(bus->ec, &msg); + result = cros_ec_cmd_xfer(bus->ec, &msg); if (result < 0) goto exit; @@ -290,6 +292,7 @@ static int ec_i2c_probe(struct platform_device *pdev) bus->adap.algo_data = bus; bus->adap.dev.parent = &pdev->dev; bus->adap.dev.of_node = np; + bus->adap.retries = I2C_MAX_RETRIES; err = i2c_add_adapter(&bus->adap); if (err) { diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 72d3499bb029..5d773d20230a 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -157,7 +157,7 @@ static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state) .insize = ckdev->cols, }; - return ckdev->ec->cmd_xfer(ckdev->ec, &msg); + return cros_ec_cmd_xfer(ckdev->ec, &msg); } static irqreturn_t cros_ec_keyb_irq(int irq, void *data) diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c index a93b4d0134a2..84e313107233 100644 --- a/drivers/mfd/88pm860x-i2c.c +++ b/drivers/mfd/88pm860x-i2c.c @@ -122,7 +122,7 @@ static int read_device(struct i2c_client *i2c, int reg, static int write_device(struct i2c_client *i2c, int reg, int bytes, void *src) { - unsigned char buf[bytes + 1]; + unsigned char buf[2]; struct i2c_adapter *adap = i2c->adapter; struct i2c_msg msg; int ret; @@ -140,26 +140,6 @@ static int write_device(struct i2c_client *i2c, int reg, return 0; } -int pm860x_page_reg_read(struct i2c_client *i2c, int reg) -{ - unsigned char zero = 0; - unsigned char data; - int ret; - - i2c_lock_adapter(i2c->adapter); - read_device(i2c, 0xFA, 0, &zero); - read_device(i2c, 0xFB, 0, &zero); - read_device(i2c, 0xFF, 0, &zero); - ret = read_device(i2c, reg, 1, &data); - if (ret >= 0) - ret = (int)data; - read_device(i2c, 0xFE, 0, &zero); - read_device(i2c, 0xFC, 0, &zero); - i2c_unlock_adapter(i2c->adapter); - return ret; -} -EXPORT_SYMBOL(pm860x_page_reg_read); - int pm860x_page_reg_write(struct i2c_client *i2c, int reg, unsigned char data) { @@ -195,47 +175,3 @@ int pm860x_page_bulk_read(struct i2c_client *i2c, int reg, return ret; } EXPORT_SYMBOL(pm860x_page_bulk_read); - -int pm860x_page_bulk_write(struct i2c_client *i2c, int reg, - int count, unsigned char *buf) -{ - unsigned char zero = 0; - int ret; - - i2c_lock_adapter(i2c->adapter); - read_device(i2c, 0xFA, 0, &zero); - read_device(i2c, 0xFB, 0, &zero); - read_device(i2c, 0xFF, 0, &zero); - ret = write_device(i2c, reg, count, buf); - read_device(i2c, 0xFE, 0, &zero); - read_device(i2c, 0xFC, 0, &zero); - i2c_unlock_adapter(i2c->adapter); - i2c_unlock_adapter(i2c->adapter); - return ret; -} -EXPORT_SYMBOL(pm860x_page_bulk_write); - -int pm860x_page_set_bits(struct i2c_client *i2c, int reg, - unsigned char mask, unsigned char data) -{ - unsigned char zero; - unsigned char value; - int ret; - - i2c_lock_adapter(i2c->adapter); - read_device(i2c, 0xFA, 0, &zero); - read_device(i2c, 0xFB, 0, &zero); - read_device(i2c, 0xFF, 0, &zero); - ret = read_device(i2c, reg, 1, &value); - if (ret < 0) - goto out; - value &= ~mask; - value |= data; - ret = write_device(i2c, reg, 1, &value); -out: - read_device(i2c, 0xFE, 0, &zero); - read_device(i2c, 0xFC, 0, &zero); - i2c_unlock_adapter(i2c->adapter); - return ret; -} -EXPORT_SYMBOL(pm860x_page_set_bits); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index cf66ef1ffaf3..1456ea70bbc7 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -210,6 +210,19 @@ config MFD_MC13XXX_I2C help Select this if your MC13xxx is connected via an I2C bus. +config MFD_HI6421_PMIC + tristate "HiSilicon Hi6421 PMU/Codec IC" + depends on OF + select MFD_CORE + select REGMAP_MMIO + help + Add support for HiSilicon Hi6421 PMIC. Hi6421 includes multi- + functions, such as regulators, RTC, codec, Coulomb counter, etc. + This driver includes core APIs _only_. You have to select + individul components like voltage regulators under corresponding + menus in order to enable them. + We communicate with the Hi6421 via memory-mapped I/O. + config HTC_EGPIO bool "HTC EGPIO support" depends on GPIOLIB && ARM @@ -554,6 +567,21 @@ 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_SPMI_PMIC + tristate "Qualcomm SPMI PMICs" + depends on ARCH_QCOM || COMPILE_TEST + depends on OF + depends on SPMI + select REGMAP_SPMI + help + This enables support for the Qualcomm SPMI PMICs. + These PMICs are currently used with the Snapdragon 800 series of + SoCs. Note, that this will only be useful paired with descriptions + of the independent functions as children nodes in the device tree. + + Say M here if you want to include support for the SPMI PMIC + series as a module. The module will be called "qcom-spmi-pmic". + config MFD_RDC321X tristate "RDC R-321x southbridge" select MFD_CORE @@ -597,6 +625,30 @@ config MFD_RC5T583 Additional drivers must be enabled in order to use the different functionality of the device. +config MFD_RK808 + tristate "Rockchip RK808 Power Management chip" + depends on I2C && OF + select MFD_CORE + select REGMAP_I2C + select REGMAP_IRQ + help + If you say yes here you get support for the RK808 + Power Management chips. + This driver provides common support for accessing the device + through I2C interface. The device supports multiple sub-devices + including interrupts, RTC, LDO & DCDC regulators, and onkey. + +config MFD_RN5T618 + tristate "Ricoh RN5T5618 PMIC" + depends on I2C + select MFD_CORE + select REGMAP_I2C + help + Say yes here to add support for the Ricoh RN5T618 PMIC. This + driver provides common support for accessing the device, + additional drivers must be enabled in order to use the + functionality of the device. + config MFD_SEC_CORE bool "SAMSUNG Electronics PMIC Series Support" depends on I2C=y @@ -1243,11 +1295,11 @@ config MFD_WM8350_I2C selected to enable support for the functionality of the chip. config MFD_WM8994 - bool "Wolfson Microelectronics WM8994" + tristate "Wolfson Microelectronics WM8994" select MFD_CORE select REGMAP_I2C select REGMAP_IRQ - depends on I2C=y + depends on I2C help The WM8994 is a highly integrated hi-fi CODEC designed for smartphone applicatiosn. As well as audio functionality it diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index d58068aa8aa9..8bd54b1253af 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -153,6 +153,7 @@ 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_SPMI_PMIC) += qcom-spmi-pmic.o obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o obj-$(CONFIG_MFD_TPS65090) += tps65090.o obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o @@ -160,6 +161,8 @@ obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o obj-$(CONFIG_MFD_PALMAS) += palmas.o obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o +obj-$(CONFIG_MFD_RK808) += rk808.o +obj-$(CONFIG_MFD_RN5T618) += rn5t618.o obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o obj-$(CONFIG_MFD_SYSCON) += syscon.o obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o @@ -170,6 +173,7 @@ obj-$(CONFIG_MFD_AS3722) += as3722.o obj-$(CONFIG_MFD_STW481X) += stw481x.o obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o obj-$(CONFIG_MFD_MENF21BMC) += menf21bmc.o +obj-$(CONFIG_MFD_HI6421_PMIC) += hi6421-pmic-core.o intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 10a0cb90619a..bce7c0784b6b 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -393,18 +393,6 @@ static int arizona_runtime_resume(struct device *dev) break; } - switch (arizona->type) { - case WM5102: - ret = wm5102_patch(arizona); - if (ret != 0) { - dev_err(arizona->dev, "Failed to apply patch: %d\n", - ret); - goto err; - } - default: - break; - } - ret = regcache_sync(arizona->regmap); if (ret != 0) { dev_err(arizona->dev, "Failed to restore register cache\n"); @@ -534,7 +522,11 @@ EXPORT_SYMBOL_GPL(arizona_of_get_named_gpio); static int arizona_of_get_core_pdata(struct arizona *arizona) { struct arizona_pdata *pdata = &arizona->pdata; + struct property *prop; + const __be32 *cur; + u32 val; int ret, i; + int count = 0; pdata->reset = arizona_of_get_named_gpio(arizona, "wlf,reset", true); @@ -560,6 +552,15 @@ static int arizona_of_get_core_pdata(struct arizona *arizona) ret); } + of_property_for_each_u32(arizona->dev->of_node, "wlf,inmode", prop, + cur, val) { + if (count == ARRAY_SIZE(arizona->pdata.inmode)) + break; + + arizona->pdata.inmode[count] = val; + count++; + } + return 0; } @@ -784,7 +785,8 @@ int arizona_dev_init(struct arizona *arizona) /* Ensure device startup is complete */ switch (arizona->type) { case WM5102: - ret = regmap_read(arizona->regmap, 0x19, &val); + ret = regmap_read(arizona->regmap, + ARIZONA_WRITE_SEQUENCER_CTRL_3, &val); if (ret != 0) dev_err(dev, "Failed to check write sequencer state: %d\n", @@ -945,6 +947,7 @@ int arizona_dev_init(struct arizona *arizona) regmap_update_bits(arizona->regmap, ARIZONA_MIC_BIAS_CTRL_1 + i, ARIZONA_MICB1_LVL_MASK | + ARIZONA_MICB1_EXT_CAP | ARIZONA_MICB1_DISCH | ARIZONA_MICB1_BYPASS | ARIZONA_MICB1_RATE, val); diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c index d420dbc0e2b0..3a3fe7cc6d61 100644 --- a/drivers/mfd/arizona-irq.c +++ b/drivers/mfd/arizona-irq.c @@ -152,10 +152,18 @@ static void arizona_irq_disable(struct irq_data *data) { } +static int arizona_irq_set_wake(struct irq_data *data, unsigned int on) +{ + struct arizona *arizona = irq_data_get_irq_chip_data(data); + + return irq_set_irq_wake(arizona->irq, on); +} + static struct irq_chip arizona_irq_chip = { .name = "arizona", .irq_disable = arizona_irq_disable, .irq_enable = arizona_irq_enable, + .irq_set_wake = arizona_irq_set_wake, }; static int arizona_irq_map(struct irq_domain *h, unsigned int virq, @@ -164,7 +172,7 @@ static int arizona_irq_map(struct irq_domain *h, unsigned int virq, struct regmap_irq_chip_data *data = h->host_data; irq_set_chip_data(virq, data); - irq_set_chip_and_handler(virq, &arizona_irq_chip, handle_edge_irq); + irq_set_chip_and_handler(virq, &arizona_irq_chip, handle_simple_irq); irq_set_nested_thread(virq, 1); /* ARM needs us to explicitly flag the IRQ as valid @@ -282,7 +290,7 @@ int arizona_irq_init(struct arizona *arizona) ret = regmap_add_irq_chip(arizona->regmap, irq_create_mapping(arizona->virq, 0), - IRQF_ONESHOT, -1, aod, + IRQF_ONESHOT, 0, aod, &arizona->aod_irq_chip); if (ret != 0) { dev_err(arizona->dev, "Failed to add AOD IRQs: %d\n", ret); @@ -291,7 +299,7 @@ int arizona_irq_init(struct arizona *arizona) ret = regmap_add_irq_chip(arizona->regmap, irq_create_mapping(arizona->virq, 1), - IRQF_ONESHOT, -1, irq, + IRQF_ONESHOT, 0, irq, &arizona->irq_chip); if (ret != 0) { dev_err(arizona->dev, "Failed to add main IRQs: %d\n", ret); diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index dee653989e3a..6231adbb295d 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -140,15 +140,6 @@ static const struct regmap_irq_chip axp20x_regmap_irq_chip = { .init_ack_masked = true, }; -static const char * const axp20x_supplies[] = { - "acin", - "vin2", - "vin3", - "ldo24in", - "ldo3in", - "ldo5in", -}; - static struct mfd_cell axp20x_cells[] = { { .name = "axp20x-pek", @@ -156,8 +147,6 @@ static struct mfd_cell axp20x_cells[] = { .resources = axp20x_pek_resources, }, { .name = "axp20x-regulator", - .parent_supplies = axp20x_supplies, - .num_parent_supplies = ARRAY_SIZE(axp20x_supplies), }, }; diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c index 4873f9c50452..fc0c81ef04ff 100644 --- a/drivers/mfd/cros_ec.c +++ b/drivers/mfd/cros_ec.c @@ -23,6 +23,9 @@ #include <linux/mfd/core.h> #include <linux/mfd/cros_ec.h> #include <linux/mfd/cros_ec_commands.h> +#include <linux/delay.h> + +#define EC_COMMAND_RETRIES 50 int cros_ec_prepare_tx(struct cros_ec_device *ec_dev, struct cros_ec_command *msg) @@ -62,6 +65,49 @@ int cros_ec_check_result(struct cros_ec_device *ec_dev, } EXPORT_SYMBOL(cros_ec_check_result); +int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, + struct cros_ec_command *msg) +{ + int ret; + + mutex_lock(&ec_dev->lock); + ret = ec_dev->cmd_xfer(ec_dev, msg); + if (msg->result == EC_RES_IN_PROGRESS) { + int i; + struct cros_ec_command status_msg; + struct ec_response_get_comms_status status; + + status_msg.version = 0; + status_msg.command = EC_CMD_GET_COMMS_STATUS; + status_msg.outdata = NULL; + status_msg.outsize = 0; + status_msg.indata = (uint8_t *)&status; + status_msg.insize = sizeof(status); + + /* + * Query the EC's status until it's no longer busy or + * we encounter an error. + */ + for (i = 0; i < EC_COMMAND_RETRIES; i++) { + usleep_range(10000, 11000); + + ret = ec_dev->cmd_xfer(ec_dev, &status_msg); + if (ret < 0) + break; + + msg->result = status_msg.result; + if (status_msg.result != EC_RES_SUCCESS) + break; + if (!(status.flags & EC_COMMS_STATUS_PROCESSING)) + break; + } + } + mutex_unlock(&ec_dev->lock); + + return ret; +} +EXPORT_SYMBOL(cros_ec_cmd_xfer); + static const struct mfd_cell cros_devs[] = { { .name = "cros-ec-keyb", @@ -91,6 +137,8 @@ int cros_ec_register(struct cros_ec_device *ec_dev) return -ENOMEM; } + mutex_init(&ec_dev->lock); + err = mfd_add_devices(dev, 0, cros_devs, ARRAY_SIZE(cros_devs), NULL, ec_dev->irq, NULL); diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c index 588c700af39c..bf6e08e8013e 100644 --- a/drivers/mfd/cros_ec_spi.c +++ b/drivers/mfd/cros_ec_spi.c @@ -65,6 +65,12 @@ */ #define EC_SPI_RECOVERY_TIME_NS (200 * 1000) +/* + * The EC is unresponsive for a time after a reboot command. Add a + * simple delay to make sure that the bus stays locked. + */ +#define EC_REBOOT_DELAY_MS 50 + /** * struct cros_ec_spi - information about a SPI-connected EC * @@ -73,13 +79,11 @@ * if no record * @end_of_msg_delay: used to set the delay_usecs on the spi_transfer that * is sent when we want to turn off CS at the end of a transaction. - * @lock: mutex to ensure only one user of cros_ec_cmd_xfer_spi at a time */ struct cros_ec_spi { struct spi_device *spi; s64 last_transfer_ns; unsigned int end_of_msg_delay; - struct mutex lock; }; static void debug_packet(struct device *dev, const char *name, u8 *ptr, @@ -226,13 +230,6 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev, int sum; int ret = 0, final_ret; - /* - * We have the shared ec_dev buffer plus we do lots of separate spi_sync - * calls, so we need to make sure only one person is using this at a - * time. - */ - mutex_lock(&ec_spi->lock); - len = cros_ec_prepare_tx(ec_dev, ec_msg); dev_dbg(ec_dev->dev, "prepared, len=%d\n", len); @@ -318,7 +315,9 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev, ret = len; exit: - mutex_unlock(&ec_spi->lock); + if (ec_msg->command == EC_CMD_REBOOT_EC) + msleep(EC_REBOOT_DELAY_MS); + return ret; } @@ -350,7 +349,6 @@ static int cros_ec_spi_probe(struct spi_device *spi) if (ec_spi == NULL) return -ENOMEM; ec_spi->spi = spi; - mutex_init(&ec_spi->lock); ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL); if (!ec_dev) return -ENOMEM; diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c index e8af816d73a9..52a0c2f6264f 100644 --- a/drivers/mfd/da9052-core.c +++ b/drivers/mfd/da9052-core.c @@ -522,7 +522,7 @@ static const struct mfd_cell da9052_subdev_info[] = { }, }; -struct regmap_config da9052_regmap_config = { +const struct regmap_config da9052_regmap_config = { .reg_bits = 8, .val_bits = 8, diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c index 6da8ec8ff800..ec39287a245b 100644 --- a/drivers/mfd/da9052-i2c.c +++ b/drivers/mfd/da9052-i2c.c @@ -140,13 +140,6 @@ static int da9052_i2c_probe(struct i2c_client *client, if (!da9052) return -ENOMEM; - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_info(&client->dev, "Error in %s:i2c_check_functionality\n", - __func__); - return -ENODEV; - } - da9052->dev = &client->dev; da9052->chip_irq = client->irq; da9052->fix_io = da9052_i2c_fix; diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c index 17666b40b70c..45ae0b7d13ef 100644 --- a/drivers/mfd/da9052-spi.c +++ b/drivers/mfd/da9052-spi.c @@ -23,6 +23,7 @@ static int da9052_spi_probe(struct spi_device *spi) { + struct regmap_config config; int ret; const struct spi_device_id *id = spi_get_device_id(spi); struct da9052 *da9052; @@ -40,10 +41,10 @@ static int da9052_spi_probe(struct spi_device *spi) spi_set_drvdata(spi, da9052); - da9052_regmap_config.read_flag_mask = 1; - da9052_regmap_config.write_flag_mask = 0; + config = da9052_regmap_config; + config.read_flag_mask = 1; - da9052->regmap = devm_regmap_init_spi(spi, &da9052_regmap_config); + da9052->regmap = devm_regmap_init_spi(spi, &config); if (IS_ERR(da9052->regmap)) { ret = PTR_ERR(da9052->regmap); dev_err(&spi->dev, "Failed to allocate register map: %d\n", diff --git a/drivers/mfd/hi6421-pmic-core.c b/drivers/mfd/hi6421-pmic-core.c new file mode 100644 index 000000000000..321a2656fd00 --- /dev/null +++ b/drivers/mfd/hi6421-pmic-core.c @@ -0,0 +1,113 @@ +/* + * Device driver for Hi6421 IC + * + * Copyright (c) <2011-2014> HiSilicon Technologies Co., Ltd. + * http://www.hisilicon.com + * Copyright (c) <2013-2014> Linaro Ltd. + * http://www.linaro.org + * + * Author: Guodong Xu <guodong.xu@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. + * + * This program is distributed in the hope 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/>. + */ + +#include <linux/device.h> +#include <linux/err.h> +#include <linux/mfd/core.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/mfd/hi6421-pmic.h> + +static const struct mfd_cell hi6421_devs[] = { + { .name = "hi6421-regulator", }, +}; + +static struct regmap_config hi6421_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 8, + .max_register = HI6421_REG_TO_BUS_ADDR(HI6421_REG_MAX), +}; + +static int hi6421_pmic_probe(struct platform_device *pdev) +{ + struct hi6421_pmic *pmic; + struct resource *res; + void __iomem *base; + int ret; + + pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); + if (!pmic) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + pmic->regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base, + &hi6421_regmap_config); + if (IS_ERR(pmic->regmap)) { + dev_err(&pdev->dev, + "regmap init failed: %ld\n", PTR_ERR(pmic->regmap)); + return PTR_ERR(pmic->regmap); + } + + /* set over-current protection debounce 8ms */ + regmap_update_bits(pmic->regmap, HI6421_OCP_DEB_CTRL_REG, + (HI6421_OCP_DEB_SEL_MASK + | HI6421_OCP_EN_DEBOUNCE_MASK + | HI6421_OCP_AUTO_STOP_MASK), + (HI6421_OCP_DEB_SEL_8MS + | HI6421_OCP_EN_DEBOUNCE_ENABLE)); + + platform_set_drvdata(pdev, pmic); + + ret = mfd_add_devices(&pdev->dev, 0, hi6421_devs, + ARRAY_SIZE(hi6421_devs), NULL, 0, NULL); + if (ret) { + dev_err(&pdev->dev, "add mfd devices failed: %d\n", ret); + return ret; + } + + return 0; +} + +static int hi6421_pmic_remove(struct platform_device *pdev) +{ + mfd_remove_devices(&pdev->dev); + + return 0; +} + +static struct of_device_id of_hi6421_pmic_match_tbl[] = { + { .compatible = "hisilicon,hi6421-pmic", }, + { }, +}; + +static struct platform_driver hi6421_pmic_driver = { + .driver = { + .name = "hi6421_pmic", + .of_match_table = of_hi6421_pmic_match_tbl, + }, + .probe = hi6421_pmic_probe, + .remove = hi6421_pmic_remove, +}; +module_platform_driver(hi6421_pmic_driver); + +MODULE_AUTHOR("Guodong Xu <guodong.xu@linaro.org>"); +MODULE_DESCRIPTION("Hi6421 PMIC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c index adbbce0ff630..ebb9cf19e347 100644 --- a/drivers/mfd/htc-i2cpld.c +++ b/drivers/mfd/htc-i2cpld.c @@ -227,15 +227,12 @@ static irqreturn_t htcpld_handler(int irq, void *dev) static void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val) { struct i2c_client *client; - struct htcpld_chip *chip_data; + struct htcpld_chip *chip_data = + container_of(chip, struct htcpld_chip, chip_out); unsigned long flags; - chip_data = container_of(chip, struct htcpld_chip, chip_out); - if (!chip_data) - return; - client = chip_data->client; - if (client == NULL) + if (!client) return; spin_lock_irqsave(&chip_data->lock, flags); @@ -261,31 +258,18 @@ static void htcpld_chip_set_ni(struct work_struct *work) static int htcpld_chip_get(struct gpio_chip *chip, unsigned offset) { struct htcpld_chip *chip_data; - int val = 0; - int is_input = 0; - - /* Try out first */ - chip_data = container_of(chip, struct htcpld_chip, chip_out); - if (!chip_data) { - /* Try in */ - is_input = 1; - chip_data = container_of(chip, struct htcpld_chip, chip_in); - if (!chip_data) - return -EINVAL; - } + u8 cache; - /* Determine if this is an input or output GPIO */ - if (!is_input) - /* Use the output cache */ - val = (chip_data->cache_out >> offset) & 1; - else - /* Use the input cache */ - val = (chip_data->cache_in >> offset) & 1; + if (!strncmp(chip->label, "htcpld-out", 10)) { + chip_data = container_of(chip, struct htcpld_chip, chip_out); + cache = chip_data->cache_out; + } else if (!strncmp(chip->label, "htcpld-in", 9)) { + chip_data = container_of(chip, struct htcpld_chip, chip_in); + cache = chip_data->cache_in; + } else + return -EINVAL; - if (val) - return 1; - else - return 0; + return (cache >> offset) & 1; } static int htcpld_direction_output(struct gpio_chip *chip, @@ -376,7 +360,7 @@ static int htcpld_register_chip_i2c( plat_chip_data = &pdata->chip[chip_index]; adapter = i2c_get_adapter(pdata->i2c_adapter_id); - if (adapter == NULL) { + if (!adapter) { /* Eek, no such I2C adapter! Bail out. */ dev_warn(dev, "Chip at i2c address 0x%x: Invalid i2c adapter %d\n", plat_chip_data->addr, pdata->i2c_adapter_id); diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index 2720922f90b4..df7b0642a5b4 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -115,6 +115,7 @@ static void intel_soc_pmic_shutdown(struct i2c_client *i2c) return; } +#if defined(CONFIG_PM_SLEEP) static int intel_soc_pmic_suspend(struct device *dev) { struct intel_soc_pmic *pmic = dev_get_drvdata(dev); @@ -132,6 +133,7 @@ static int intel_soc_pmic_resume(struct device *dev) return 0; } +#endif static SIMPLE_DEV_PM_OPS(intel_soc_pmic_pm_ops, intel_soc_pmic_suspend, intel_soc_pmic_resume); diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index 7d8482ff5868..f35d4280b2f7 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -54,6 +54,7 @@ * document number TBD : Avoton SoC * document number TBD : Coleto Creek * document number TBD : Wildcat Point-LP + * document number TBD : 9 Series */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -216,6 +217,8 @@ enum lpc_chipsets { LPC_BAYTRAIL, /* Bay Trail SoC */ LPC_COLETO, /* Coleto Creek */ LPC_WPT_LP, /* Wildcat Point-LP */ + LPC_BRASWELL, /* Braswell SoC */ + LPC_9S, /* 9 Series */ }; static struct lpc_ich_info lpc_chipset_info[] = { @@ -519,6 +522,14 @@ static struct lpc_ich_info lpc_chipset_info[] = { .name = "Wildcat Point_LP", .iTCO_version = 2, }, + [LPC_BRASWELL] = { + .name = "Braswell SoC", + .iTCO_version = 3, + }, + [LPC_9S] = { + .name = "9 Series", + .iTCO_version = 2, + }, }; /* @@ -745,6 +756,12 @@ static const struct pci_device_id lpc_ich_ids[] = { { PCI_VDEVICE(INTEL, 0x9cc6), LPC_WPT_LP}, { PCI_VDEVICE(INTEL, 0x9cc7), LPC_WPT_LP}, { PCI_VDEVICE(INTEL, 0x9cc9), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x229c), LPC_BRASWELL}, + { PCI_VDEVICE(INTEL, 0x8cc1), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc2), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc3), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc4), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc6), LPC_9S}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, lpc_ich_ids); diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c index 4ee755034f3b..c980da479a35 100644 --- a/drivers/mfd/lpc_sch.c +++ b/drivers/mfd/lpc_sch.c @@ -7,6 +7,7 @@ * Configuration Registers. * * Copyright (c) 2010 CompuLab Ltd + * Copyright (c) 2014 Intel Corp. * Author: Denis Turischev <denis@compulab.co.il> * * This program is free software; you can redistribute it and/or modify @@ -17,10 +18,6 @@ * 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; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/kernel.h> @@ -37,123 +34,165 @@ #define GPIO_IO_SIZE 64 #define GPIO_IO_SIZE_CENTERTON 128 +/* Intel Quark X1000 GPIO IRQ Number */ +#define GPIO_IRQ_QUARK_X1000 9 + #define WDTBASE 0x84 #define WDT_IO_SIZE 64 -static struct resource smbus_sch_resource = { - .flags = IORESOURCE_IO, -}; - -static struct resource gpio_sch_resource = { - .flags = IORESOURCE_IO, -}; - -static struct resource wdt_sch_resource = { - .flags = IORESOURCE_IO, +enum sch_chipsets { + LPC_SCH = 0, /* Intel Poulsbo SCH */ + LPC_ITC, /* Intel Tunnel Creek */ + LPC_CENTERTON, /* Intel Centerton */ + LPC_QUARK_X1000, /* Intel Quark X1000 */ }; -static struct mfd_cell lpc_sch_cells[3]; - -static struct mfd_cell isch_smbus_cell = { - .name = "isch_smbus", - .num_resources = 1, - .resources = &smbus_sch_resource, - .ignore_resource_conflicts = true, +struct lpc_sch_info { + unsigned int io_size_smbus; + unsigned int io_size_gpio; + unsigned int io_size_wdt; + int irq_gpio; }; -static struct mfd_cell sch_gpio_cell = { - .name = "sch_gpio", - .num_resources = 1, - .resources = &gpio_sch_resource, - .ignore_resource_conflicts = true, -}; - -static struct mfd_cell wdt_sch_cell = { - .name = "ie6xx_wdt", - .num_resources = 1, - .resources = &wdt_sch_resource, - .ignore_resource_conflicts = true, +static struct lpc_sch_info sch_chipset_info[] = { + [LPC_SCH] = { + .io_size_smbus = SMBUS_IO_SIZE, + .io_size_gpio = GPIO_IO_SIZE, + .irq_gpio = -1, + }, + [LPC_ITC] = { + .io_size_smbus = SMBUS_IO_SIZE, + .io_size_gpio = GPIO_IO_SIZE, + .io_size_wdt = WDT_IO_SIZE, + .irq_gpio = -1, + }, + [LPC_CENTERTON] = { + .io_size_smbus = SMBUS_IO_SIZE, + .io_size_gpio = GPIO_IO_SIZE_CENTERTON, + .io_size_wdt = WDT_IO_SIZE, + .irq_gpio = -1, + }, + [LPC_QUARK_X1000] = { + .io_size_gpio = GPIO_IO_SIZE, + .irq_gpio = GPIO_IRQ_QUARK_X1000, + }, }; static const struct pci_device_id lpc_sch_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CENTERTON_ILB) }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC), LPC_SCH }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC), LPC_ITC }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CENTERTON_ILB), LPC_CENTERTON }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_QUARK_X1000_ILB), LPC_QUARK_X1000 }, { 0, } }; MODULE_DEVICE_TABLE(pci, lpc_sch_ids); -static int lpc_sch_probe(struct pci_dev *dev, - const struct pci_device_id *id) +#define LPC_NO_RESOURCE 1 +#define LPC_SKIP_RESOURCE 2 + +static int lpc_sch_get_io(struct pci_dev *pdev, int where, const char *name, + struct resource *res, int size) { unsigned int base_addr_cfg; unsigned short base_addr; - int i, cells = 0; - int ret; - pci_read_config_dword(dev, SMBASE, &base_addr_cfg); + if (size == 0) + return LPC_NO_RESOURCE; + + pci_read_config_dword(pdev, where, &base_addr_cfg); base_addr = 0; if (!(base_addr_cfg & (1 << 31))) - dev_warn(&dev->dev, "Decode of the SMBus I/O range disabled\n"); + dev_warn(&pdev->dev, "Decode of the %s I/O range disabled\n", + name); else base_addr = (unsigned short)base_addr_cfg; if (base_addr == 0) { - dev_warn(&dev->dev, "I/O space for SMBus uninitialized\n"); - } else { - lpc_sch_cells[cells++] = isch_smbus_cell; - smbus_sch_resource.start = base_addr; - smbus_sch_resource.end = base_addr + SMBUS_IO_SIZE - 1; + dev_warn(&pdev->dev, "I/O space for %s uninitialized\n", name); + return LPC_SKIP_RESOURCE; } - pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg); - base_addr = 0; - if (!(base_addr_cfg & (1 << 31))) - dev_warn(&dev->dev, "Decode of the GPIO I/O range disabled\n"); - else - base_addr = (unsigned short)base_addr_cfg; + res->start = base_addr; + res->end = base_addr + size - 1; + res->flags = IORESOURCE_IO; - if (base_addr == 0) { - dev_warn(&dev->dev, "I/O space for GPIO uninitialized\n"); - } else { - lpc_sch_cells[cells++] = sch_gpio_cell; - gpio_sch_resource.start = base_addr; - if (id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) - gpio_sch_resource.end = base_addr + GPIO_IO_SIZE_CENTERTON - 1; - else - gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1; - } + return 0; +} - if (id->device == PCI_DEVICE_ID_INTEL_ITC_LPC - || id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) { - pci_read_config_dword(dev, WDTBASE, &base_addr_cfg); - base_addr = 0; - if (!(base_addr_cfg & (1 << 31))) - dev_warn(&dev->dev, "Decode of the WDT I/O range disabled\n"); - else - base_addr = (unsigned short)base_addr_cfg; - if (base_addr == 0) - dev_warn(&dev->dev, "I/O space for WDT uninitialized\n"); - else { - lpc_sch_cells[cells++] = wdt_sch_cell; - wdt_sch_resource.start = base_addr; - wdt_sch_resource.end = base_addr + WDT_IO_SIZE - 1; - } - } +static int lpc_sch_populate_cell(struct pci_dev *pdev, int where, + const char *name, int size, int irq, + int id, struct mfd_cell *cell) +{ + struct resource *res; + int ret; - if (WARN_ON(cells > ARRAY_SIZE(lpc_sch_cells))) { - dev_err(&dev->dev, "Cell count exceeds array size"); - return -ENODEV; - } + res = devm_kcalloc(&pdev->dev, 2, sizeof(*res), GFP_KERNEL); + if (!res) + return -ENOMEM; + + ret = lpc_sch_get_io(pdev, where, name, res, size); + if (ret) + return ret; + + memset(cell, 0, sizeof(*cell)); + + cell->name = name; + cell->resources = res; + cell->num_resources = 1; + cell->ignore_resource_conflicts = true; + cell->id = id; + + /* Check if we need to add an IRQ resource */ + if (irq < 0) + return 0; + + res++; + + res->start = irq; + res->end = irq; + res->flags = IORESOURCE_IRQ; + + cell->num_resources++; + + return 0; +} + +static int lpc_sch_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct mfd_cell lpc_sch_cells[3]; + struct lpc_sch_info *info = &sch_chipset_info[id->driver_data]; + unsigned int cells = 0; + int ret; + + ret = lpc_sch_populate_cell(dev, SMBASE, "isch_smbus", + info->io_size_smbus, -1, + id->device, &lpc_sch_cells[cells]); + if (ret < 0) + return ret; + if (ret == 0) + cells++; + + ret = lpc_sch_populate_cell(dev, GPIOBASE, "sch_gpio", + info->io_size_gpio, info->irq_gpio, + id->device, &lpc_sch_cells[cells]); + if (ret < 0) + return ret; + if (ret == 0) + cells++; + + ret = lpc_sch_populate_cell(dev, WDTBASE, "ie6xx_wdt", + info->io_size_wdt, -1, + id->device, &lpc_sch_cells[cells]); + if (ret < 0) + return ret; + if (ret == 0) + cells++; if (cells == 0) { dev_err(&dev->dev, "All decode registers disabled.\n"); return -ENODEV; } - for (i = 0; i < cells; i++) - lpc_sch_cells[i].id = id->device; - ret = mfd_add_devices(&dev->dev, 0, lpc_sch_cells, cells, NULL, 0, NULL); if (ret) mfd_remove_devices(&dev->dev); diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c index b8af263be594..de96b7fb1f6d 100644 --- a/drivers/mfd/max14577.c +++ b/drivers/mfd/max14577.c @@ -456,8 +456,7 @@ static int max14577_i2c_probe(struct i2c_client *i2c, } ret = mfd_add_devices(max14577->dev, -1, mfd_devs, - mfd_devs_size, NULL, 0, - regmap_irq_get_domain(max14577->irq_data)); + mfd_devs_size, NULL, 0, NULL); if (ret < 0) goto err_mfd; diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index 86e552348db4..929795eae9fc 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -52,7 +52,7 @@ static const struct mfd_cell max77802_devs[] = { static bool max77802_pmic_is_accessible_reg(struct device *dev, unsigned int reg) { - return (reg >= MAX77802_REG_DEVICE_ID && reg < MAX77802_REG_PMIC_END); + return reg < MAX77802_REG_PMIC_END; } static bool max77802_rtc_is_accessible_reg(struct device *dev, diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index 249c139ef04a..cf008f45968c 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -44,9 +44,12 @@ static const struct mfd_cell max77693_devs[] = { { .name = "max77693-pmic", }, { .name = "max77693-charger", }, - { .name = "max77693-flash", }, { .name = "max77693-muic", }, { .name = "max77693-haptic", }, + { + .name = "max77693-flash", + .of_compatible = "maxim,max77693-flash", + }, }; static const struct regmap_config max77693_regmap_config = { diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c index ecbe78ead3b6..c880c895c5a6 100644 --- a/drivers/mfd/max8925-i2c.c +++ b/drivers/mfd/max8925-i2c.c @@ -37,7 +37,7 @@ static inline int max8925_read_device(struct i2c_client *i2c, static inline int max8925_write_device(struct i2c_client *i2c, int reg, int bytes, void *src) { - unsigned char buf[bytes + 1]; + unsigned char buf[9]; int ret; buf[0] = (unsigned char)reg; diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index 2b6bc868cd3d..64dde5d24b32 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c @@ -36,6 +36,9 @@ #define MC34708_REVISION_FIN (0x07 << 6) #define MC34708_REVISION_FAB (0x07 << 9) +#define MC13XXX_PWRCTRL 15 +#define MC13XXX_PWRCTRL_WDIRESET (1 << 12) + #define MC13XXX_ADC1 44 #define MC13XXX_ADC1_ADEN (1 << 0) #define MC13XXX_ADC1_RAND (1 << 1) @@ -416,6 +419,11 @@ int mc13xxx_common_init(struct device *dev) mc13xxx->variant->print_revision(mc13xxx, revision); + ret = mc13xxx_reg_rmw(mc13xxx, MC13XXX_PWRCTRL, + MC13XXX_PWRCTRL_WDIRESET, MC13XXX_PWRCTRL_WDIRESET); + if (ret) + return ret; + for (i = 0; i < ARRAY_SIZE(mc13xxx->irqs); i++) { mc13xxx->irqs[i].reg_offset = i / MC13XXX_IRQ_PER_REG; mc13xxx->irqs[i].mask = BIT(i % MC13XXX_IRQ_PER_REG); diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c index 5e2667afe2bc..9f01aef539dd 100644 --- a/drivers/mfd/menelaus.c +++ b/drivers/mfd/menelaus.c @@ -466,8 +466,6 @@ static int menelaus_set_voltage(const struct menelaus_vtg *vtg, int mV, struct i2c_client *c = the_menelaus->client; mutex_lock(&the_menelaus->lock); - if (!vtg) - goto set_voltage; ret = menelaus_read_reg(vtg->vtg_reg); if (ret < 0) @@ -482,7 +480,6 @@ static int menelaus_set_voltage(const struct menelaus_vtg *vtg, int mV, ret = menelaus_write_reg(vtg->vtg_reg, val); if (ret < 0) goto out; -set_voltage: ret = menelaus_write_reg(vtg->mode_reg, mode); out: mutex_unlock(&the_menelaus->lock); @@ -1186,7 +1183,7 @@ static int menelaus_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct menelaus_chip *menelaus; - int rev = 0, val; + int rev = 0; int err = 0; struct menelaus_platform_data *menelaus_pdata = dev_get_platdata(&client->dev); @@ -1239,10 +1236,10 @@ static int menelaus_probe(struct i2c_client *client, pr_info("Menelaus rev %d.%d\n", rev >> 4, rev & 0x0f); - val = menelaus_read_reg(MENELAUS_VCORE_CTRL1); - if (val < 0) + err = menelaus_read_reg(MENELAUS_VCORE_CTRL1); + if (err < 0) goto fail; - if (val & (1 << 7)) + if (err & BIT(7)) menelaus->vcore_hw_mode = 1; else menelaus->vcore_hw_mode = 0; diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 892d343193ad..f3338fe9d069 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -78,6 +78,44 @@ static int mfd_platform_add_cell(struct platform_device *pdev, return 0; } +#if IS_ENABLED(CONFIG_ACPI) +static void mfd_acpi_add_device(const struct mfd_cell *cell, + struct platform_device *pdev) +{ + struct acpi_device *parent_adev; + struct acpi_device *adev; + + parent_adev = ACPI_COMPANION(pdev->dev.parent); + if (!parent_adev) + return; + + /* + * MFD child device gets its ACPI handle either from the ACPI + * device directly under the parent that matches the acpi_pnpid or + * it will use the parent handle if is no acpi_pnpid is given. + */ + adev = parent_adev; + if (cell->acpi_pnpid) { + struct acpi_device_id ids[2] = {}; + struct acpi_device *child_adev; + + strlcpy(ids[0].id, cell->acpi_pnpid, sizeof(ids[0].id)); + list_for_each_entry(child_adev, &parent_adev->children, node) + if (acpi_match_device_ids(child_adev, ids)) { + adev = child_adev; + break; + } + } + + ACPI_COMPANION_SET(&pdev->dev, adev); +} +#else +static inline void mfd_acpi_add_device(const struct mfd_cell *cell, + struct platform_device *pdev) +{ +} +#endif + static int mfd_add_device(struct device *parent, int id, const struct mfd_cell *cell, atomic_t *usage_count, struct resource *mem_base, @@ -101,6 +139,7 @@ static int mfd_add_device(struct device *parent, int id, pdev->dev.type = &mfd_dev_type; pdev->dev.dma_mask = parent->dma_mask; pdev->dev.dma_parms = parent->dma_parms; + pdev->dev.coherent_dma_mask = parent->coherent_dma_mask; ret = regulator_bulk_register_supply_alias( &pdev->dev, cell->parent_supplies, @@ -118,6 +157,8 @@ static int mfd_add_device(struct device *parent, int id, } } + mfd_acpi_add_device(cell, pdev); + if (cell->pdata_size) { ret = platform_device_add_data(pdev, cell->platform_data, cell->pdata_size); diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index c87f7a0a53f8..43664eb69c93 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -106,10 +106,7 @@ static ssize_t show_dump_regs(struct device *dev, struct device_attribute *attr, } else dump[n1] = pcf50633_reg_read(pcf, n + n1); - hex_dump_to_buffer(dump, sizeof(dump), 16, 1, buf1, 128, 0); - buf1 += strlen(buf1); - *buf1++ = '\n'; - *buf1 = '\0'; + buf1 += sprintf(buf1, "%*ph\n", (int)sizeof(dump), dump); } return buf1 - buf; @@ -195,8 +192,9 @@ static int pcf50633_probe(struct i2c_client *client, const struct i2c_device_id *ids) { struct pcf50633 *pcf; + struct platform_device *pdev; struct pcf50633_platform_data *pdata = dev_get_platdata(&client->dev); - int i, ret; + int i, j, ret; int version, variant; if (!client->irq) { @@ -243,9 +241,6 @@ static int pcf50633_probe(struct i2c_client *client, for (i = 0; i < PCF50633_NUM_REGULATORS; i++) { - struct platform_device *pdev; - int j; - pdev = platform_device_alloc("pcf50633-regulator", i); if (!pdev) return -ENOMEM; @@ -253,25 +248,31 @@ static int pcf50633_probe(struct i2c_client *client, pdev->dev.parent = pcf->dev; ret = platform_device_add_data(pdev, &pdata->reg_init_data[i], sizeof(pdata->reg_init_data[i])); - if (ret) { - platform_device_put(pdev); - for (j = 0; j < i; j++) - platform_device_put(pcf->regulator_pdev[j]); - return ret; - } - pcf->regulator_pdev[i] = pdev; + if (ret) + goto err; + + ret = platform_device_add(pdev); + if (ret) + goto err; - platform_device_add(pdev); + pcf->regulator_pdev[i] = pdev; } ret = sysfs_create_group(&client->dev.kobj, &pcf_attr_group); if (ret) - dev_err(pcf->dev, "error creating sysfs entries\n"); + dev_warn(pcf->dev, "error creating sysfs entries\n"); if (pdata->probe_done) pdata->probe_done(pcf); return 0; + +err: + platform_device_put(pdev); + for (j = 0; j < i; j++) + platform_device_put(pcf->regulator_pdev[j]); + + return ret; } static int pcf50633_remove(struct i2c_client *client) diff --git a/drivers/mfd/qcom-spmi-pmic.c b/drivers/mfd/qcom-spmi-pmic.c new file mode 100644 index 000000000000..4b8beb2a1579 --- /dev/null +++ b/drivers/mfd/qcom-spmi-pmic.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014, The Linux Foundation. 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. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/spmi.h> +#include <linux/regmap.h> +#include <linux/of_platform.h> + +static const struct regmap_config spmi_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .max_register = 0xffff, + .fast_io = true, +}; + +static int pmic_spmi_probe(struct spmi_device *sdev) +{ + struct device_node *root = sdev->dev.of_node; + struct regmap *regmap; + + regmap = devm_regmap_init_spmi_ext(sdev, &spmi_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return of_platform_populate(root, NULL, NULL, &sdev->dev); +} + +static void pmic_spmi_remove(struct spmi_device *sdev) +{ + of_platform_depopulate(&sdev->dev); +} + +static const struct of_device_id pmic_spmi_id_table[] = { + { .compatible = "qcom,spmi-pmic" }, + { .compatible = "qcom,pm8941" }, + { .compatible = "qcom,pm8841" }, + { .compatible = "qcom,pma8084" }, + { } +}; +MODULE_DEVICE_TABLE(of, pmic_spmi_id_table); + +static struct spmi_driver pmic_spmi_driver = { + .probe = pmic_spmi_probe, + .remove = pmic_spmi_remove, + .driver = { + .name = "pmic-spmi", + .of_match_table = pmic_spmi_id_table, + }, +}; +module_spmi_driver(pmic_spmi_driver); + +MODULE_DESCRIPTION("Qualcomm SPMI PMIC driver"); +MODULE_ALIAS("spmi:spmi-pmic"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Josh Cartwright <joshc@codeaurora.org>"); +MODULE_AUTHOR("Stanimir Varbanov <svarbanov@mm-sol.com>"); diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c new file mode 100644 index 000000000000..bd0215069875 --- /dev/null +++ b/drivers/mfd/rk808.c @@ -0,0 +1,275 @@ +/* + * MFD core driver for Rockchip RK808 + * + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * + * Author: Chris Zhong <zyw@rock-chips.com> + * Author: Zhang Qing <zhangqing@rock-chips.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/mfd/rk808.h> +#include <linux/mfd/core.h> +#include <linux/module.h> +#include <linux/regmap.h> + +struct rk808_reg_data { + int addr; + int mask; + int value; +}; + +static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) +{ + /* + * Notes: + * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but + * we don't use that feature. It's better to cache. + * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since + * bits are cleared in case when we shutoff anyway, but better safe. + */ + + switch (reg) { + case RK808_SECONDS_REG ... RK808_WEEKS_REG: + case RK808_RTC_STATUS_REG: + case RK808_VB_MON_REG: + case RK808_THERMAL_REG: + case RK808_DCDC_UV_STS_REG: + case RK808_LDO_UV_STS_REG: + case RK808_DCDC_PG_REG: + case RK808_LDO_PG_REG: + case RK808_DEVCTRL_REG: + case RK808_INT_STS_REG1: + case RK808_INT_STS_REG2: + return true; + } + + return false; +} + +static const struct regmap_config rk808_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK808_IO_POL_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk808_is_volatile_reg, +}; + +static struct resource rtc_resources[] = { + { + .start = RK808_IRQ_RTC_ALARM, + .end = RK808_IRQ_RTC_ALARM, + .flags = IORESOURCE_IRQ, + } +}; + +static const struct mfd_cell rk808s[] = { + { .name = "rk808-clkout", }, + { .name = "rk808-regulator", }, + { + .name = "rk808-rtc", + .num_resources = ARRAY_SIZE(rtc_resources), + .resources = &rtc_resources[0], + }, +}; + +static const struct rk808_reg_data pre_init_reg[] = { + { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA }, + { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA }, + { RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA }, + { RK808_BUCK1_CONFIG_REG, BUCK1_RATE_MASK, BUCK_ILMIN_200MA }, + { RK808_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_200MA }, + { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT | + VB_LO_SEL_3500MV }, +}; + +static const struct regmap_irq rk808_irqs[] = { + /* INT_STS */ + [RK808_IRQ_VOUT_LO] = { + .mask = RK808_IRQ_VOUT_LO_MSK, + .reg_offset = 0, + }, + [RK808_IRQ_VB_LO] = { + .mask = RK808_IRQ_VB_LO_MSK, + .reg_offset = 0, + }, + [RK808_IRQ_PWRON] = { + .mask = RK808_IRQ_PWRON_MSK, + .reg_offset = 0, + }, + [RK808_IRQ_PWRON_LP] = { + .mask = RK808_IRQ_PWRON_LP_MSK, + .reg_offset = 0, + }, + [RK808_IRQ_HOTDIE] = { + .mask = RK808_IRQ_HOTDIE_MSK, + .reg_offset = 0, + }, + [RK808_IRQ_RTC_ALARM] = { + .mask = RK808_IRQ_RTC_ALARM_MSK, + .reg_offset = 0, + }, + [RK808_IRQ_RTC_PERIOD] = { + .mask = RK808_IRQ_RTC_PERIOD_MSK, + .reg_offset = 0, + }, + + /* INT_STS2 */ + [RK808_IRQ_PLUG_IN_INT] = { + .mask = RK808_IRQ_PLUG_IN_INT_MSK, + .reg_offset = 1, + }, + [RK808_IRQ_PLUG_OUT_INT] = { + .mask = RK808_IRQ_PLUG_OUT_INT_MSK, + .reg_offset = 1, + }, +}; + +static struct regmap_irq_chip rk808_irq_chip = { + .name = "rk808", + .irqs = rk808_irqs, + .num_irqs = ARRAY_SIZE(rk808_irqs), + .num_regs = 2, + .irq_reg_stride = 2, + .status_base = RK808_INT_STS_REG1, + .mask_base = RK808_INT_STS_MSK_REG1, + .ack_base = RK808_INT_STS_REG1, + .init_ack_masked = true, +}; + +static struct i2c_client *rk808_i2c_client; +static void rk808_device_shutdown(void) +{ + int ret; + struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); + + if (!rk808) { + dev_warn(&rk808_i2c_client->dev, + "have no rk808, so do nothing here\n"); + return; + } + + ret = regmap_update_bits(rk808->regmap, + RK808_DEVCTRL_REG, + DEV_OFF_RST, DEV_OFF_RST); + if (ret) + dev_err(&rk808_i2c_client->dev, "power off error!\n"); +} + +static int rk808_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device_node *np = client->dev.of_node; + struct rk808 *rk808; + int pm_off = 0; + int ret; + int i; + + if (!client->irq) { + dev_err(&client->dev, "No interrupt support, no core IRQ\n"); + return -EINVAL; + } + + rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL); + if (!rk808) + return -ENOMEM; + + rk808->regmap = devm_regmap_init_i2c(client, &rk808_regmap_config); + if (IS_ERR(rk808->regmap)) { + dev_err(&client->dev, "regmap initialization failed\n"); + return PTR_ERR(rk808->regmap); + } + + for (i = 0; i < ARRAY_SIZE(pre_init_reg); i++) { + ret = regmap_update_bits(rk808->regmap, pre_init_reg[i].addr, + pre_init_reg[i].mask, + pre_init_reg[i].value); + if (ret) { + dev_err(&client->dev, + "0x%x write err\n", pre_init_reg[i].addr); + return ret; + } + } + + ret = regmap_add_irq_chip(rk808->regmap, client->irq, + IRQF_ONESHOT, -1, + &rk808_irq_chip, &rk808->irq_data); + if (ret) { + dev_err(&client->dev, "Failed to add irq_chip %d\n", ret); + return ret; + } + + rk808->i2c = client; + i2c_set_clientdata(client, rk808); + + ret = mfd_add_devices(&client->dev, -1, + rk808s, ARRAY_SIZE(rk808s), + NULL, 0, regmap_irq_get_domain(rk808->irq_data)); + if (ret) { + dev_err(&client->dev, "failed to add MFD devices %d\n", ret); + goto err_irq; + } + + pm_off = of_property_read_bool(np, + "rockchip,system-power-controller"); + if (pm_off && !pm_power_off) { + rk808_i2c_client = client; + pm_power_off = rk808_device_shutdown; + } + + return 0; + +err_irq: + regmap_del_irq_chip(client->irq, rk808->irq_data); + return ret; +} + +static int rk808_remove(struct i2c_client *client) +{ + struct rk808 *rk808 = i2c_get_clientdata(client); + + regmap_del_irq_chip(client->irq, rk808->irq_data); + mfd_remove_devices(&client->dev); + pm_power_off = NULL; + + return 0; +} + +static struct of_device_id rk808_of_match[] = { + { .compatible = "rockchip,rk808" }, + { }, +}; +MODULE_DEVICE_TABLE(of, rk808_of_match); + +static const struct i2c_device_id rk808_ids[] = { + { "rk808" }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, rk808_ids); + +static struct i2c_driver rk808_i2c_driver = { + .driver = { + .name = "rk808", + .of_match_table = rk808_of_match, + }, + .probe = rk808_probe, + .remove = rk808_remove, + .id_table = rk808_ids, +}; + +module_i2c_driver(rk808_i2c_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>"); +MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>"); +MODULE_DESCRIPTION("RK808 PMIC driver"); diff --git a/drivers/mfd/rn5t618.c b/drivers/mfd/rn5t618.c new file mode 100644 index 000000000000..666857192dbe --- /dev/null +++ b/drivers/mfd/rn5t618.c @@ -0,0 +1,134 @@ +/* + * MFD core driver for Ricoh RN5T618 PMIC + * + * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/i2c.h> +#include <linux/mfd/core.h> +#include <linux/mfd/rn5t618.h> +#include <linux/module.h> +#include <linux/regmap.h> + +static const struct mfd_cell rn5t618_cells[] = { + { .name = "rn5t618-regulator" }, + { .name = "rn5t618-wdt" }, +}; + +static bool rn5t618_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RN5T618_WATCHDOGCNT: + case RN5T618_DCIRQ: + case RN5T618_ILIMDATAH ... RN5T618_AIN0DATAL: + case RN5T618_IR_ADC1 ... RN5T618_IR_ADC3: + case RN5T618_IR_GPR: + case RN5T618_IR_GPF: + case RN5T618_MON_IOIN: + case RN5T618_INTMON: + return true; + default: + return false; + } +} + +static const struct regmap_config rn5t618_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .volatile_reg = rn5t618_volatile_reg, + .max_register = RN5T618_MAX_REG, + .cache_type = REGCACHE_RBTREE, +}; + +static struct rn5t618 *rn5t618_pm_power_off; + +static void rn5t618_power_off(void) +{ + /* disable automatic repower-on */ + regmap_update_bits(rn5t618_pm_power_off->regmap, RN5T618_REPCNT, + RN5T618_REPCNT_REPWRON, 0); + /* start power-off sequence */ + regmap_update_bits(rn5t618_pm_power_off->regmap, RN5T618_SLPCNT, + RN5T618_SLPCNT_SWPWROFF, RN5T618_SLPCNT_SWPWROFF); +} + +static int rn5t618_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rn5t618 *priv; + int ret; + + priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + i2c_set_clientdata(i2c, priv); + + priv->regmap = devm_regmap_init_i2c(i2c, &rn5t618_regmap_config); + if (IS_ERR(priv->regmap)) { + ret = PTR_ERR(priv->regmap); + dev_err(&i2c->dev, "regmap init failed: %d\n", ret); + return ret; + } + + ret = mfd_add_devices(&i2c->dev, -1, rn5t618_cells, + ARRAY_SIZE(rn5t618_cells), NULL, 0, NULL); + if (ret) { + dev_err(&i2c->dev, "failed to add sub-devices: %d\n", ret); + return ret; + } + + if (!pm_power_off) { + rn5t618_pm_power_off = priv; + pm_power_off = rn5t618_power_off; + } + + return 0; +} + +static int rn5t618_i2c_remove(struct i2c_client *i2c) +{ + struct rn5t618 *priv = i2c_get_clientdata(i2c); + + if (priv == rn5t618_pm_power_off) { + rn5t618_pm_power_off = NULL; + pm_power_off = NULL; + } + + mfd_remove_devices(&i2c->dev); + return 0; +} + +static const struct of_device_id rn5t618_of_match[] = { + { .compatible = "ricoh,rn5t618" }, + { } +}; +MODULE_DEVICE_TABLE(of, rn5t618_of_match); + +static const struct i2c_device_id rn5t618_i2c_id[] = { + { } +}; +MODULE_DEVICE_TABLE(i2c, rn5t618_i2c_id); + +static struct i2c_driver rn5t618_i2c_driver = { + .driver = { + .name = "rn5t618", + .of_match_table = of_match_ptr(rn5t618_of_match), + }, + .probe = rn5t618_i2c_probe, + .remove = rn5t618_i2c_remove, + .id_table = rn5t618_i2c_id, +}; + +module_i2c_driver(rn5t618_i2c_driver); + +MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>"); +MODULE_DESCRIPTION("Ricoh RN5T618 MFD driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index d01b8c249231..f2643c221d34 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -1197,7 +1197,7 @@ static int rtsx_pci_probe(struct pci_dev *pcidev, pcr->msi_en = msi_en; if (pcr->msi_en) { ret = pci_enable_msi(pcidev); - if (ret < 0) + if (ret) pcr->msi_en = false; } diff --git a/drivers/mfd/rtsx_usb.c b/drivers/mfd/rtsx_usb.c index 71f387ce8cbd..9cf98d142d9a 100644 --- a/drivers/mfd/rtsx_usb.c +++ b/drivers/mfd/rtsx_usb.c @@ -684,7 +684,7 @@ 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", + dev_dbg(&intf->dev, "%s called with pm message 0x%04x\n", __func__, message.event); /* diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 02027b7f1223..6ce6e6200359 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -514,9 +514,9 @@ unsigned long sm501_set_clock(struct device *dev, unsigned long mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL); unsigned long gate = smc501_readl(sm->regs + SM501_CURRENT_GATE); unsigned long clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK); - unsigned char reg; unsigned int pll_reg = 0; unsigned long sm501_freq; /* the actual frequency achieved */ + u64 reg; struct sm501_clock to; diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 02a17c388e87..e2f9df1c0c36 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -249,7 +249,7 @@ int stmpe_set_altfunc(struct stmpe *stmpe, u32 pins, enum stmpe_block block) int af_bits = variant->af_bits; int numregs = DIV_ROUND_UP(stmpe->num_gpios * af_bits, 8); int mask = (1 << af_bits) - 1; - u8 regs[numregs]; + u8 regs[8]; int af, afperreg, ret; if (!variant->get_altfunc) @@ -854,7 +854,7 @@ static irqreturn_t stmpe_irq(int irq, void *data) struct stmpe_variant_info *variant = stmpe->variant; int num = DIV_ROUND_UP(variant->num_irqs, 8); u8 israddr; - u8 isr[num]; + u8 isr[3]; int ret; int i; @@ -1122,7 +1122,12 @@ static void stmpe_of_probe(struct stmpe_platform_data *pdata, if (pdata->id < 0) pdata->id = -1; - pdata->irq_trigger = IRQF_TRIGGER_NONE; + pdata->irq_gpio = of_get_named_gpio_flags(np, "irq-gpio", 0, + &pdata->irq_trigger); + if (gpio_is_valid(pdata->irq_gpio)) + pdata->irq_over_gpio = 1; + else + pdata->irq_trigger = IRQF_TRIGGER_NONE; of_property_read_u32(np, "st,autosleep-timeout", &pdata->autosleep_timeout); diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index dd4bf5816221..d877e777cce6 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -53,11 +53,11 @@ void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val) unsigned long flags; spin_lock_irqsave(&tsadc->reg_lock, flags); - tsadc->reg_se_cache = val; + tsadc->reg_se_cache |= val; if (tsadc->adc_waiting) wake_up(&tsadc->reg_se_wait); else if (!tsadc->adc_in_use) - tscadc_writel(tsadc, REG_SE, val); + tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); spin_unlock_irqrestore(&tsadc->reg_lock, flags); } @@ -96,6 +96,7 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc) void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val) { spin_lock_irq(&tsadc->reg_lock); + tsadc->reg_se_cache |= val; am335x_tscadc_need_adc(tsadc); tscadc_writel(tsadc, REG_SE, val); @@ -241,18 +242,20 @@ static int ti_tscadc_probe(struct platform_device *pdev) tscadc_writel(tscadc, REG_CLKDIV, tscadc->clk_div); /* Set the control register bits */ - ctrl = CNTRLREG_STEPCONFIGWRT | - CNTRLREG_STEPID; - if (tsc_wires > 0) - ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB; + ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID; tscadc_writel(tscadc, REG_CTRL, ctrl); /* Set register bits for Idle Config Mode */ - if (tsc_wires > 0) + if (tsc_wires > 0) { + tscadc->tsc_wires = tsc_wires; + if (tsc_wires == 5) + ctrl |= CNTRLREG_5WIRE | CNTRLREG_TSCENB; + else + ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB; tscadc_idle_config(tscadc); + } /* Enable the TSC module enable bit */ - ctrl = tscadc_readl(tscadc, REG_CTRL); ctrl |= CNTRLREG_TSCSSENB; tscadc_writel(tscadc, REG_CTRL, ctrl); @@ -324,21 +327,23 @@ static int tscadc_suspend(struct device *dev) static int tscadc_resume(struct device *dev) { struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev); - unsigned int restore, ctrl; + u32 ctrl; pm_runtime_get_sync(dev); /* context restore */ ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID; - if (tscadc_dev->tsc_cell != -1) - ctrl |= CNTRLREG_TSCENB | CNTRLREG_4WIRE; tscadc_writel(tscadc_dev, REG_CTRL, ctrl); - if (tscadc_dev->tsc_cell != -1) + if (tscadc_dev->tsc_cell != -1) { + if (tscadc_dev->tsc_wires == 5) + ctrl |= CNTRLREG_5WIRE | CNTRLREG_TSCENB; + else + ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB; tscadc_idle_config(tscadc_dev); - restore = tscadc_readl(tscadc_dev, REG_CTRL); - tscadc_writel(tscadc_dev, REG_CTRL, - (restore | CNTRLREG_TSCSSENB)); + } + ctrl |= CNTRLREG_TSCSSENB; + tscadc_writel(tscadc_dev, REG_CTRL, ctrl); tscadc_writel(tscadc_dev, REG_CLKDIV, tscadc_dev->clk_div); diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index 3cc4c7084b92..a8ee52c95f2f 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -146,6 +146,8 @@ EXPORT_SYMBOL_GPL(tps65217_clear_bits); static struct regmap_config tps65217_regmap_config = { .reg_bits = 8, .val_bits = 8, + + .max_register = TPS65217_REG_MAX, }; static const struct of_device_id tps65217_of_match[] = { diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index f243e75d28f3..7612d89850dd 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -486,6 +486,11 @@ static int tps65910_i2c_probe(struct i2c_client *i2c, tps65910->i2c_client = i2c; tps65910->id = chip_id; + /* Work around silicon erratum SWCZ010: the tps65910 may miss the + * first I2C transfer. So issue a dummy transfer before the first + * real transfer. + */ + i2c_master_send(i2c, "", 1); tps65910->regmap = devm_regmap_init_i2c(i2c, &tps65910_regmap_config); if (IS_ERR(tps65910->regmap)) { ret = PTR_ERR(tps65910->regmap); diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index b1dabba763cf..1b772ef761cb 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -396,13 +396,17 @@ static int twl4030_init_sih_modules(unsigned line) status = twl_i2c_read(sih->module, rxbuf, sih->mask[line].isr_offset, sih->bytes_ixr); if (status < 0) - pr_err("twl4030: err %d initializing %s %s\n", + pr_warn("twl4030: err %d initializing %s %s\n", status, sih->name, "ISR"); - if (!sih->set_cor) + if (!sih->set_cor) { status = twl_i2c_write(sih->module, buf, sih->mask[line].isr_offset, sih->bytes_ixr); + if (status < 0) + pr_warn("twl4030: write failed: %d\n", + status); + } /* * else COR=1 means read sufficed. * (for most SIH modules...) diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index 4d3ff3771491..cf92a6d1c532 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c @@ -627,6 +627,9 @@ static bool twl4030_power_use_poweroff(const struct twl4030_power_data *pdata, if (pdata && pdata->use_poweroff) return true; + if (of_property_read_bool(node, "ti,system-power-controller")) + return true; + if (of_property_read_bool(node, "ti,use_poweroff")) return true; diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index f9c06c542a41..9687645162ae 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -679,6 +679,7 @@ static int twl6040_probe(struct i2c_client *client, if (twl6040->rev < 0) { dev_err(&client->dev, "Failed to read revision register: %d\n", twl6040->rev); + ret = twl6040->rev; goto gpio_err; } diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c index fb4d4bb0f47d..d6f35bbf795b 100644 --- a/drivers/mfd/wm5102-tables.c +++ b/drivers/mfd/wm5102-tables.c @@ -87,6 +87,7 @@ int wm5102_patch(struct arizona *arizona) case 0: wm5102_patch = wm5102_reva_patch; patch_size = ARRAY_SIZE(wm5102_reva_patch); + break; default: wm5102_patch = wm5102_revb_patch; patch_size = ARRAY_SIZE(wm5102_revb_patch); @@ -245,9 +246,6 @@ const struct regmap_irq_chip wm5102_irq = { static const struct reg_default wm5102_reg_default[] = { { 0x00000008, 0x0019 }, /* R8 - Ctrl IF SPI CFG 1 */ { 0x00000009, 0x0001 }, /* R9 - Ctrl IF I2C1 CFG 1 */ - { 0x00000016, 0x0000 }, /* R22 - Write Sequencer Ctrl 0 */ - { 0x00000017, 0x0000 }, /* R23 - Write Sequencer Ctrl 1 */ - { 0x00000018, 0x0000 }, /* R24 - Write Sequencer Ctrl 2 */ { 0x00000020, 0x0000 }, /* R32 - Tone Generator 1 */ { 0x00000021, 0x1000 }, /* R33 - Tone Generator 2 */ { 0x00000022, 0x0000 }, /* R34 - Tone Generator 3 */ @@ -1016,6 +1014,7 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg) case ARIZONA_WRITE_SEQUENCER_CTRL_0: case ARIZONA_WRITE_SEQUENCER_CTRL_1: case ARIZONA_WRITE_SEQUENCER_CTRL_2: + case ARIZONA_WRITE_SEQUENCER_CTRL_3: case ARIZONA_WRITE_SEQUENCER_PROM: case ARIZONA_TONE_GENERATOR_1: case ARIZONA_TONE_GENERATOR_2: @@ -1060,6 +1059,8 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg) case ARIZONA_ASYNC_CLOCK_1: case ARIZONA_ASYNC_SAMPLE_RATE_1: case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS: + case ARIZONA_ASYNC_SAMPLE_RATE_2: + case ARIZONA_ASYNC_SAMPLE_RATE_2_STATUS: case ARIZONA_OUTPUT_SYSTEM_CLOCK: case ARIZONA_OUTPUT_ASYNC_CLOCK: case ARIZONA_RATE_ESTIMATOR_1: @@ -1880,6 +1881,10 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg) switch (reg) { case ARIZONA_SOFTWARE_RESET: case ARIZONA_DEVICE_REVISION: + case ARIZONA_WRITE_SEQUENCER_CTRL_0: + case ARIZONA_WRITE_SEQUENCER_CTRL_1: + case ARIZONA_WRITE_SEQUENCER_CTRL_2: + case ARIZONA_WRITE_SEQUENCER_CTRL_3: case ARIZONA_OUTPUT_STATUS_1: case ARIZONA_RAW_OUTPUT_STATUS_1: case ARIZONA_SLIMBUS_RX_PORT_STATUS: @@ -1889,8 +1894,13 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg) case ARIZONA_SAMPLE_RATE_3_STATUS: case ARIZONA_HAPTICS_STATUS: case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS: + case ARIZONA_ASYNC_SAMPLE_RATE_2_STATUS: case ARIZONA_FLL1_NCO_TEST_0: case ARIZONA_FLL2_NCO_TEST_0: + case ARIZONA_DAC_COMP_1: + case ARIZONA_DAC_COMP_2: + case ARIZONA_DAC_COMP_3: + case ARIZONA_DAC_COMP_4: case ARIZONA_FX_CTRL2: case ARIZONA_INTERRUPT_STATUS_1: case ARIZONA_INTERRUPT_STATUS_2: diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index 9b98ee559188..4642b5b816a0 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -666,9 +666,6 @@ static const struct reg_default wm5110_reg_default[] = { { 0x0000000A, 0x0001 }, /* R10 - Ctrl IF I2C2 CFG 1 */ { 0x0000000B, 0x0036 }, /* R11 - Ctrl IF I2C1 CFG 2 */ { 0x0000000C, 0x0036 }, /* R12 - Ctrl IF I2C2 CFG 2 */ - { 0x00000016, 0x0000 }, /* R22 - Write Sequencer Ctrl 0 */ - { 0x00000017, 0x0000 }, /* R23 - Write Sequencer Ctrl 1 */ - { 0x00000018, 0x0000 }, /* R24 - Write Sequencer Ctrl 2 */ { 0x00000020, 0x0000 }, /* R32 - Tone Generator 1 */ { 0x00000021, 0x1000 }, /* R33 - Tone Generator 2 */ { 0x00000022, 0x0000 }, /* R34 - Tone Generator 3 */ @@ -705,6 +702,7 @@ static const struct reg_default wm5110_reg_default[] = { { 0x00000104, 0x0011 }, /* R260 - Sample rate 3 */ { 0x00000112, 0x0305 }, /* R274 - Async clock 1 */ { 0x00000113, 0x0011 }, /* R275 - Async sample rate 1 */ + { 0x00000114, 0x0011 }, /* R276 - Async sample rate 2 */ { 0x00000149, 0x0000 }, /* R329 - Output system clock */ { 0x0000014A, 0x0000 }, /* R330 - Output async clock */ { 0x00000152, 0x0000 }, /* R338 - Rate Estimator 1 */ @@ -1741,6 +1739,8 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_ASYNC_CLOCK_1: case ARIZONA_ASYNC_SAMPLE_RATE_1: case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS: + case ARIZONA_ASYNC_SAMPLE_RATE_2: + case ARIZONA_ASYNC_SAMPLE_RATE_2_STATUS: case ARIZONA_OUTPUT_SYSTEM_CLOCK: case ARIZONA_OUTPUT_ASYNC_CLOCK: case ARIZONA_RATE_ESTIMATOR_1: @@ -2815,11 +2815,15 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg) switch (reg) { case ARIZONA_SOFTWARE_RESET: case ARIZONA_DEVICE_REVISION: + case ARIZONA_WRITE_SEQUENCER_CTRL_0: + case ARIZONA_WRITE_SEQUENCER_CTRL_1: + case ARIZONA_WRITE_SEQUENCER_CTRL_2: case ARIZONA_HAPTICS_STATUS: case ARIZONA_SAMPLE_RATE_1_STATUS: case ARIZONA_SAMPLE_RATE_2_STATUS: case ARIZONA_SAMPLE_RATE_3_STATUS: case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS: + case ARIZONA_ASYNC_SAMPLE_RATE_2_STATUS: case ARIZONA_MIC_DETECT_3: case ARIZONA_HEADPHONE_DETECT_2: case ARIZONA_INPUT_ENABLES_STATUS: diff --git a/drivers/mfd/wm8994-irq.c b/drivers/mfd/wm8994-irq.c index e74dedda5b55..a14407edbd89 100644 --- a/drivers/mfd/wm8994-irq.c +++ b/drivers/mfd/wm8994-irq.c @@ -262,8 +262,10 @@ int wm8994_irq_init(struct wm8994 *wm8994) return 0; } +EXPORT_SYMBOL(wm8994_irq_init); void wm8994_irq_exit(struct wm8994 *wm8994) { regmap_del_irq_chip(wm8994->irq, wm8994->irq_data); } +EXPORT_SYMBOL(wm8994_irq_exit); diff --git a/drivers/mfd/wm8994-regmap.c b/drivers/mfd/wm8994-regmap.c index 770a25696468..300e9b6a2e96 100644 --- a/drivers/mfd/wm8994-regmap.c +++ b/drivers/mfd/wm8994-regmap.c @@ -1252,6 +1252,7 @@ struct regmap_config wm1811_regmap_config = { .volatile_reg = wm1811_volatile_register, .readable_reg = wm1811_readable_register, }; +EXPORT_SYMBOL(wm1811_regmap_config); struct regmap_config wm8994_regmap_config = { .reg_bits = 16, @@ -1266,6 +1267,7 @@ struct regmap_config wm8994_regmap_config = { .volatile_reg = wm8994_volatile_register, .readable_reg = wm8994_readable_register, }; +EXPORT_SYMBOL(wm8994_regmap_config); struct regmap_config wm8958_regmap_config = { .reg_bits = 16, @@ -1280,8 +1282,10 @@ struct regmap_config wm8958_regmap_config = { .volatile_reg = wm8958_volatile_register, .readable_reg = wm8958_readable_register, }; +EXPORT_SYMBOL(wm8958_regmap_config); struct regmap_config wm8994_base_regmap_config = { .reg_bits = 16, .val_bits = 16, }; +EXPORT_SYMBOL(wm8994_base_regmap_config); diff --git a/include/dt-bindings/clock/rockchip,rk808.h b/include/dt-bindings/clock/rockchip,rk808.h new file mode 100644 index 000000000000..1a873432f965 --- /dev/null +++ b/include/dt-bindings/clock/rockchip,rk808.h @@ -0,0 +1,11 @@ +/* + * This header provides constants clk index RK808 pmic clkout + */ +#ifndef _CLK_ROCKCHIP_RK808 +#define _CLK_ROCKCHIP_RK808 + +/* CLOCKOUT index */ +#define RK808_CLKOUT0 0 +#define RK808_CLKOUT1 1 + +#endif diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h index dbd23c36de21..c0b075f6bc35 100644 --- a/include/linux/mfd/arizona/registers.h +++ b/include/linux/mfd/arizona/registers.h @@ -27,6 +27,7 @@ #define ARIZONA_WRITE_SEQUENCER_CTRL_0 0x16 #define ARIZONA_WRITE_SEQUENCER_CTRL_1 0x17 #define ARIZONA_WRITE_SEQUENCER_CTRL_2 0x18 +#define ARIZONA_WRITE_SEQUENCER_CTRL_3 0x19 #define ARIZONA_WRITE_SEQUENCER_PROM 0x1A #define ARIZONA_TONE_GENERATOR_1 0x20 #define ARIZONA_TONE_GENERATOR_2 0x21 @@ -70,7 +71,9 @@ #define ARIZONA_SAMPLE_RATE_3_STATUS 0x10C #define ARIZONA_ASYNC_CLOCK_1 0x112 #define ARIZONA_ASYNC_SAMPLE_RATE_1 0x113 +#define ARIZONA_ASYNC_SAMPLE_RATE_2 0x114 #define ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS 0x11B +#define ARIZONA_ASYNC_SAMPLE_RATE_2_STATUS 0x11C #define ARIZONA_OUTPUT_SYSTEM_CLOCK 0x149 #define ARIZONA_OUTPUT_ASYNC_CLOCK 0x14A #define ARIZONA_RATE_ESTIMATOR_1 0x152 @@ -1664,16 +1667,30 @@ /* * R275 (0x113) - Async sample rate 1 */ -#define ARIZONA_ASYNC_SAMPLE_RATE_MASK 0x001F /* ASYNC_SAMPLE_RATE - [4:0] */ -#define ARIZONA_ASYNC_SAMPLE_RATE_SHIFT 0 /* ASYNC_SAMPLE_RATE - [4:0] */ -#define ARIZONA_ASYNC_SAMPLE_RATE_WIDTH 5 /* ASYNC_SAMPLE_RATE - [4:0] */ +#define ARIZONA_ASYNC_SAMPLE_RATE_1_MASK 0x001F /* ASYNC_SAMPLE_RATE_1 - [4:0] */ +#define ARIZONA_ASYNC_SAMPLE_RATE_1_SHIFT 0 /* ASYNC_SAMPLE_RATE_1 - [4:0] */ +#define ARIZONA_ASYNC_SAMPLE_RATE_1_WIDTH 5 /* ASYNC_SAMPLE_RATE_1 - [4:0] */ + +/* + * R276 (0x114) - Async sample rate 2 + */ +#define ARIZONA_ASYNC_SAMPLE_RATE_2_MASK 0x001F /* ASYNC_SAMPLE_RATE_2 - [4:0] */ +#define ARIZONA_ASYNC_SAMPLE_RATE_2_SHIFT 0 /* ASYNC_SAMPLE_RATE_2 - [4:0] */ +#define ARIZONA_ASYNC_SAMPLE_RATE_2_WIDTH 5 /* ASYNC_SAMPLE_RATE_2 - [4:0] */ /* * R283 (0x11B) - Async sample rate 1 status */ -#define ARIZONA_ASYNC_SAMPLE_RATE_STS_MASK 0x001F /* ASYNC_SAMPLE_RATE_STS - [4:0] */ -#define ARIZONA_ASYNC_SAMPLE_RATE_STS_SHIFT 0 /* ASYNC_SAMPLE_RATE_STS - [4:0] */ -#define ARIZONA_ASYNC_SAMPLE_RATE_STS_WIDTH 5 /* ASYNC_SAMPLE_RATE_STS - [4:0] */ +#define ARIZONA_ASYNC_SAMPLE_RATE_1_STS_MASK 0x001F /* ASYNC_SAMPLE_RATE_1_STS - [4:0] */ +#define ARIZONA_ASYNC_SAMPLE_RATE_1_STS_SHIFT 0 /* ASYNC_SAMPLE_RATE_1_STS - [4:0] */ +#define ARIZONA_ASYNC_SAMPLE_RATE_1_STS_WIDTH 5 /* ASYNC_SAMPLE_RATE_1_STS - [4:0] */ + +/* + * R284 (0x11C) - Async sample rate 2 status + */ +#define ARIZONA_ASYNC_SAMPLE_RATE_2_STS_MASK 0x001F /* ASYNC_SAMPLE_RATE_2_STS - [4:0] */ +#define ARIZONA_ASYNC_SAMPLE_RATE_2_STS_SHIFT 0 /* ASYNC_SAMPLE_RATE_2_STS - [4:0] */ +#define ARIZONA_ASYNC_SAMPLE_RATE_2_STS_WIDTH 5 /* ASYNC_SAMPLE_RATE_2_STS - [4:0] */ /* * R329 (0x149) - Output system clock diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index f543de91ce19..73e1709d4c09 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -44,6 +44,9 @@ struct mfd_cell { */ const char *of_compatible; + /* Matches ACPI PNP id, either _HID or _CID */ + const char *acpi_pnpid; + /* * These resources can be specified relative to the parent device. * For accessing hardware you should use resources from the platform dev diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h index fcbe9d129a9d..0e166b92f5b4 100644 --- a/include/linux/mfd/cros_ec.h +++ b/include/linux/mfd/cros_ec.h @@ -62,10 +62,6 @@ struct cros_ec_command { * @dev: Device pointer * @was_wake_device: true if this device was set to wake the system from * sleep at the last suspend - * @cmd_xfer: send command to EC and get response - * Returns the number of bytes received if the communication succeeded, but - * that doesn't mean the EC was happy with the command. The caller - * should check msg.result for the EC's result code. * * @priv: Private data * @irq: Interrupt to use @@ -82,6 +78,10 @@ struct cros_ec_command { * @dout_size: size of dout buffer to allocate (zero to use static dout) * @parent: pointer to parent device (e.g. i2c or spi device) * @wake_enabled: true if this device can wake the system from sleep + * @cmd_xfer: send command to EC and get response + * Returns the number of bytes received if the communication succeeded, but + * that doesn't mean the EC was happy with the command. The caller + * should check msg.result for the EC's result code. * @lock: one transaction at a time */ struct cros_ec_device { @@ -92,8 +92,6 @@ struct cros_ec_device { struct device *dev; bool was_wake_device; struct class *cros_class; - int (*cmd_xfer)(struct cros_ec_device *ec, - struct cros_ec_command *msg); /* These are used to implement the platform-specific interface */ void *priv; @@ -104,6 +102,8 @@ struct cros_ec_device { int dout_size; struct device *parent; bool wake_enabled; + int (*cmd_xfer)(struct cros_ec_device *ec, + struct cros_ec_command *msg); struct mutex lock; }; @@ -153,6 +153,18 @@ int cros_ec_check_result(struct cros_ec_device *ec_dev, struct cros_ec_command *msg); /** + * cros_ec_cmd_xfer - Send a command to the ChromeOS EC + * + * Call this to send a command to the ChromeOS EC. This should be used + * instead of calling the EC's cmd_xfer() callback directly. + * + * @ec_dev: EC device + * @msg: Message to write + */ +int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, + struct cros_ec_command *msg); + +/** * cros_ec_remove - Remove a ChromeOS EC * * Call this to deregister a ChromeOS EC, then clean up any private data. diff --git a/include/linux/mfd/da9052/da9052.h b/include/linux/mfd/da9052/da9052.h index bba65f51a0b5..c18a4c19d6fc 100644 --- a/include/linux/mfd/da9052/da9052.h +++ b/include/linux/mfd/da9052/da9052.h @@ -211,7 +211,7 @@ static inline int da9052_reg_update(struct da9052 *da9052, unsigned char reg, int da9052_device_init(struct da9052 *da9052, u8 chip_id); void da9052_device_exit(struct da9052 *da9052); -extern struct regmap_config da9052_regmap_config; +extern const struct regmap_config da9052_regmap_config; int da9052_irq_init(struct da9052 *da9052); int da9052_irq_exit(struct da9052 *da9052); diff --git a/include/linux/mfd/davinci_voicecodec.h b/include/linux/mfd/davinci_voicecodec.h index 5166935ce66d..cb01496bfa49 100644 --- a/include/linux/mfd/davinci_voicecodec.h +++ b/include/linux/mfd/davinci_voicecodec.h @@ -21,7 +21,7 @@ */ #ifndef __LINUX_MFD_DAVINCI_VOICECODEC_H_ -#define __LINUX_MFD_DAVINIC_VOICECODEC_H_ +#define __LINUX_MFD_DAVINCI_VOICECODEC_H_ #include <linux/kernel.h> #include <linux/platform_device.h> diff --git a/include/linux/mfd/hi6421-pmic.h b/include/linux/mfd/hi6421-pmic.h new file mode 100644 index 000000000000..587273e35acf --- /dev/null +++ b/include/linux/mfd/hi6421-pmic.h @@ -0,0 +1,41 @@ +/* + * Header file for device driver Hi6421 PMIC + * + * Copyright (c) <2011-2014> HiSilicon Technologies Co., Ltd. + * http://www.hisilicon.com + * Copyright (c) <2013-2014> Linaro Ltd. + * http://www.linaro.org + * + * Author: Guodong Xu <guodong.xu@linaro.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __HI6421_PMIC_H +#define __HI6421_PMIC_H + +/* Hi6421 registers are mapped to memory bus in 4 bytes stride */ +#define HI6421_REG_TO_BUS_ADDR(x) (x << 2) + +/* Hi6421 maximum register number */ +#define HI6421_REG_MAX 0xFF + +/* Hi6421 OCP (over current protection) and DEB (debounce) control register */ +#define HI6421_OCP_DEB_CTRL_REG HI6421_REG_TO_BUS_ADDR(0x51) +#define HI6421_OCP_DEB_SEL_MASK 0x0C +#define HI6421_OCP_DEB_SEL_8MS 0x00 +#define HI6421_OCP_DEB_SEL_16MS 0x04 +#define HI6421_OCP_DEB_SEL_32MS 0x08 +#define HI6421_OCP_DEB_SEL_64MS 0x0C +#define HI6421_OCP_EN_DEBOUNCE_MASK 0x02 +#define HI6421_OCP_EN_DEBOUNCE_ENABLE 0x02 +#define HI6421_OCP_AUTO_STOP_MASK 0x01 +#define HI6421_OCP_AUTO_STOP_ENABLE 0x01 + +struct hi6421_pmic { + struct regmap *regmap; +}; + +#endif /* __HI6421_PMIC_H */ diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h index d0e578fd7053..fc17d56581b2 100644 --- a/include/linux/mfd/max77693-private.h +++ b/include/linux/mfd/max77693-private.h @@ -46,7 +46,7 @@ enum max77693_pmic_reg { MAX77693_LED_REG_VOUT_FLASH2 = 0x0C, MAX77693_LED_REG_FLASH_INT = 0x0E, MAX77693_LED_REG_FLASH_INT_MASK = 0x0F, - MAX77693_LED_REG_FLASH_INT_STATUS = 0x10, + MAX77693_LED_REG_FLASH_STATUS = 0x10, MAX77693_PMIC_REG_PMIC_ID1 = 0x20, MAX77693_PMIC_REG_PMIC_ID2 = 0x21, @@ -85,6 +85,65 @@ enum max77693_pmic_reg { MAX77693_PMIC_REG_END, }; +/* MAX77693 ITORCH register */ +#define TORCH_IOUT1_SHIFT 0 +#define TORCH_IOUT2_SHIFT 4 +#define TORCH_IOUT_MIN 15625 +#define TORCH_IOUT_MAX 250000 +#define TORCH_IOUT_STEP 15625 + +/* MAX77693 IFLASH1 and IFLASH2 registers */ +#define FLASH_IOUT_MIN 15625 +#define FLASH_IOUT_MAX_1LED 1000000 +#define FLASH_IOUT_MAX_2LEDS 625000 +#define FLASH_IOUT_STEP 15625 + +/* MAX77693 TORCH_TIMER register */ +#define TORCH_TMR_NO_TIMER 0x40 +#define TORCH_TIMEOUT_MIN 262000 +#define TORCH_TIMEOUT_MAX 15728000 + +/* MAX77693 FLASH_TIMER register */ +#define FLASH_TMR_LEVEL 0x80 +#define FLASH_TIMEOUT_MIN 62500 +#define FLASH_TIMEOUT_MAX 1000000 +#define FLASH_TIMEOUT_STEP 62500 + +/* MAX77693 FLASH_EN register */ +#define FLASH_EN_OFF 0x0 +#define FLASH_EN_FLASH 0x1 +#define FLASH_EN_TORCH 0x2 +#define FLASH_EN_ON 0x3 +#define FLASH_EN_SHIFT(x) (6 - ((x) - 1) * 2) +#define TORCH_EN_SHIFT(x) (2 - ((x) - 1) * 2) + +/* MAX77693 MAX_FLASH1 register */ +#define MAX_FLASH1_MAX_FL_EN 0x80 +#define MAX_FLASH1_VSYS_MIN 2400 +#define MAX_FLASH1_VSYS_MAX 3400 +#define MAX_FLASH1_VSYS_STEP 33 + +/* MAX77693 VOUT_CNTL register */ +#define FLASH_BOOST_FIXED 0x04 +#define FLASH_BOOST_LEDNUM_2 0x80 + +/* MAX77693 VOUT_FLASH1 register */ +#define FLASH_VOUT_MIN 3300 +#define FLASH_VOUT_MAX 5500 +#define FLASH_VOUT_STEP 25 +#define FLASH_VOUT_RMIN 0x0c + +/* MAX77693 FLASH_STATUS register */ +#define FLASH_STATUS_FLASH_ON BIT(3) +#define FLASH_STATUS_TORCH_ON BIT(2) + +/* MAX77693 FLASH_INT register */ +#define FLASH_INT_FLED2_OPEN BIT(0) +#define FLASH_INT_FLED2_SHORT BIT(1) +#define FLASH_INT_FLED1_OPEN BIT(2) +#define FLASH_INT_FLED1_SHORT BIT(3) +#define FLASH_INT_OVER_CURRENT BIT(4) + /* MAX77693 CHG_CNFG_00 register */ #define CHG_CNFG_00_CHG_MASK 0x1 #define CHG_CNFG_00_BUCK_MASK 0x4 diff --git a/include/linux/mfd/max77693.h b/include/linux/mfd/max77693.h index 3f3dc45f93ee..f0b6585cd874 100644 --- a/include/linux/mfd/max77693.h +++ b/include/linux/mfd/max77693.h @@ -63,6 +63,45 @@ struct max77693_muic_platform_data { int path_uart; }; +/* MAX77693 led flash */ + +/* triggers */ +enum max77693_led_trigger { + MAX77693_LED_TRIG_OFF, + MAX77693_LED_TRIG_FLASH, + MAX77693_LED_TRIG_TORCH, + MAX77693_LED_TRIG_EXT, + MAX77693_LED_TRIG_SOFT, +}; + +/* trigger types */ +enum max77693_led_trigger_type { + MAX77693_LED_TRIG_TYPE_EDGE, + MAX77693_LED_TRIG_TYPE_LEVEL, +}; + +/* boost modes */ +enum max77693_led_boost_mode { + MAX77693_LED_BOOST_NONE, + MAX77693_LED_BOOST_ADAPTIVE, + MAX77693_LED_BOOST_FIXED, +}; + +struct max77693_led_platform_data { + u32 fleds[2]; + u32 iout_torch[2]; + u32 iout_flash[2]; + u32 trigger[2]; + u32 trigger_type[2]; + u32 num_leds; + u32 boost_mode; + u32 flash_timeout; + u32 boost_vout; + u32 low_vsys; +}; + +/* MAX77693 */ + struct max77693_platform_data { /* regulator data */ struct max77693_regulator_data *regulators; @@ -70,5 +109,6 @@ struct max77693_platform_data { /* muic data */ struct max77693_muic_platform_data *muic_data; + struct max77693_led_platform_data *led_data; }; #endif /* __LINUX_MFD_MAX77693_H */ diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h new file mode 100644 index 000000000000..fb09312d854b --- /dev/null +++ b/include/linux/mfd/rk808.h @@ -0,0 +1,196 @@ +/* + * rk808.h for Rockchip RK808 + * + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * + * Author: Chris Zhong <zyw@rock-chips.com> + * Author: Zhang Qing <zhangqing@rock-chips.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#ifndef __LINUX_REGULATOR_rk808_H +#define __LINUX_REGULATOR_rk808_H + +#include <linux/regulator/machine.h> +#include <linux/regmap.h> + +/* + * rk808 Global Register Map. + */ + +#define RK808_DCDC1 0 /* (0+RK808_START) */ +#define RK808_LDO1 4 /* (4+RK808_START) */ +#define RK808_NUM_REGULATORS 14 + +enum rk808_reg { + RK808_ID_DCDC1, + RK808_ID_DCDC2, + RK808_ID_DCDC3, + RK808_ID_DCDC4, + RK808_ID_LDO1, + RK808_ID_LDO2, + RK808_ID_LDO3, + RK808_ID_LDO4, + RK808_ID_LDO5, + RK808_ID_LDO6, + RK808_ID_LDO7, + RK808_ID_LDO8, + RK808_ID_SWITCH1, + RK808_ID_SWITCH2, +}; + +#define RK808_SECONDS_REG 0x00 +#define RK808_MINUTES_REG 0x01 +#define RK808_HOURS_REG 0x02 +#define RK808_DAYS_REG 0x03 +#define RK808_MONTHS_REG 0x04 +#define RK808_YEARS_REG 0x05 +#define RK808_WEEKS_REG 0x06 +#define RK808_ALARM_SECONDS_REG 0x08 +#define RK808_ALARM_MINUTES_REG 0x09 +#define RK808_ALARM_HOURS_REG 0x0a +#define RK808_ALARM_DAYS_REG 0x0b +#define RK808_ALARM_MONTHS_REG 0x0c +#define RK808_ALARM_YEARS_REG 0x0d +#define RK808_RTC_CTRL_REG 0x10 +#define RK808_RTC_STATUS_REG 0x11 +#define RK808_RTC_INT_REG 0x12 +#define RK808_RTC_COMP_LSB_REG 0x13 +#define RK808_RTC_COMP_MSB_REG 0x14 +#define RK808_CLK32OUT_REG 0x20 +#define RK808_VB_MON_REG 0x21 +#define RK808_THERMAL_REG 0x22 +#define RK808_DCDC_EN_REG 0x23 +#define RK808_LDO_EN_REG 0x24 +#define RK808_SLEEP_SET_OFF_REG1 0x25 +#define RK808_SLEEP_SET_OFF_REG2 0x26 +#define RK808_DCDC_UV_STS_REG 0x27 +#define RK808_DCDC_UV_ACT_REG 0x28 +#define RK808_LDO_UV_STS_REG 0x29 +#define RK808_LDO_UV_ACT_REG 0x2a +#define RK808_DCDC_PG_REG 0x2b +#define RK808_LDO_PG_REG 0x2c +#define RK808_VOUT_MON_TDB_REG 0x2d +#define RK808_BUCK1_CONFIG_REG 0x2e +#define RK808_BUCK1_ON_VSEL_REG 0x2f +#define RK808_BUCK1_SLP_VSEL_REG 0x30 +#define RK808_BUCK1_DVS_VSEL_REG 0x31 +#define RK808_BUCK2_CONFIG_REG 0x32 +#define RK808_BUCK2_ON_VSEL_REG 0x33 +#define RK808_BUCK2_SLP_VSEL_REG 0x34 +#define RK808_BUCK2_DVS_VSEL_REG 0x35 +#define RK808_BUCK3_CONFIG_REG 0x36 +#define RK808_BUCK4_CONFIG_REG 0x37 +#define RK808_BUCK4_ON_VSEL_REG 0x38 +#define RK808_BUCK4_SLP_VSEL_REG 0x39 +#define RK808_BOOST_CONFIG_REG 0x3a +#define RK808_LDO1_ON_VSEL_REG 0x3b +#define RK808_LDO1_SLP_VSEL_REG 0x3c +#define RK808_LDO2_ON_VSEL_REG 0x3d +#define RK808_LDO2_SLP_VSEL_REG 0x3e +#define RK808_LDO3_ON_VSEL_REG 0x3f +#define RK808_LDO3_SLP_VSEL_REG 0x40 +#define RK808_LDO4_ON_VSEL_REG 0x41 +#define RK808_LDO4_SLP_VSEL_REG 0x42 +#define RK808_LDO5_ON_VSEL_REG 0x43 +#define RK808_LDO5_SLP_VSEL_REG 0x44 +#define RK808_LDO6_ON_VSEL_REG 0x45 +#define RK808_LDO6_SLP_VSEL_REG 0x46 +#define RK808_LDO7_ON_VSEL_REG 0x47 +#define RK808_LDO7_SLP_VSEL_REG 0x48 +#define RK808_LDO8_ON_VSEL_REG 0x49 +#define RK808_LDO8_SLP_VSEL_REG 0x4a +#define RK808_DEVCTRL_REG 0x4b +#define RK808_INT_STS_REG1 0x4c +#define RK808_INT_STS_MSK_REG1 0x4d +#define RK808_INT_STS_REG2 0x4e +#define RK808_INT_STS_MSK_REG2 0x4f +#define RK808_IO_POL_REG 0x50 + +/* IRQ Definitions */ +#define RK808_IRQ_VOUT_LO 0 +#define RK808_IRQ_VB_LO 1 +#define RK808_IRQ_PWRON 2 +#define RK808_IRQ_PWRON_LP 3 +#define RK808_IRQ_HOTDIE 4 +#define RK808_IRQ_RTC_ALARM 5 +#define RK808_IRQ_RTC_PERIOD 6 +#define RK808_IRQ_PLUG_IN_INT 7 +#define RK808_IRQ_PLUG_OUT_INT 8 +#define RK808_NUM_IRQ 9 + +#define RK808_IRQ_VOUT_LO_MSK BIT(0) +#define RK808_IRQ_VB_LO_MSK BIT(1) +#define RK808_IRQ_PWRON_MSK BIT(2) +#define RK808_IRQ_PWRON_LP_MSK BIT(3) +#define RK808_IRQ_HOTDIE_MSK BIT(4) +#define RK808_IRQ_RTC_ALARM_MSK BIT(5) +#define RK808_IRQ_RTC_PERIOD_MSK BIT(6) +#define RK808_IRQ_PLUG_IN_INT_MSK BIT(0) +#define RK808_IRQ_PLUG_OUT_INT_MSK BIT(1) + +#define RK808_VBAT_LOW_2V8 0x00 +#define RK808_VBAT_LOW_2V9 0x01 +#define RK808_VBAT_LOW_3V0 0x02 +#define RK808_VBAT_LOW_3V1 0x03 +#define RK808_VBAT_LOW_3V2 0x04 +#define RK808_VBAT_LOW_3V3 0x05 +#define RK808_VBAT_LOW_3V4 0x06 +#define RK808_VBAT_LOW_3V5 0x07 +#define VBAT_LOW_VOL_MASK (0x07 << 0) +#define EN_VABT_LOW_SHUT_DOWN (0x00 << 4) +#define EN_VBAT_LOW_IRQ (0x1 << 4) +#define VBAT_LOW_ACT_MASK (0x1 << 4) + +#define BUCK_ILMIN_MASK (7 << 0) +#define BOOST_ILMIN_MASK (7 << 0) +#define BUCK1_RATE_MASK (3 << 3) +#define BUCK2_RATE_MASK (3 << 3) +#define MASK_ALL 0xff + +#define SWITCH2_EN BIT(6) +#define SWITCH1_EN BIT(5) +#define DEV_OFF_RST BIT(3) + +#define VB_LO_ACT BIT(4) +#define VB_LO_SEL_3500MV (7 << 0) + +#define VOUT_LO_INT BIT(0) +#define CLK32KOUT2_EN BIT(0) + +enum { + BUCK_ILMIN_50MA, + BUCK_ILMIN_100MA, + BUCK_ILMIN_150MA, + BUCK_ILMIN_200MA, + BUCK_ILMIN_250MA, + BUCK_ILMIN_300MA, + BUCK_ILMIN_350MA, + BUCK_ILMIN_400MA, +}; + +enum { + BOOST_ILMIN_75MA, + BOOST_ILMIN_100MA, + BOOST_ILMIN_125MA, + BOOST_ILMIN_150MA, + BOOST_ILMIN_175MA, + BOOST_ILMIN_200MA, + BOOST_ILMIN_225MA, + BOOST_ILMIN_250MA, +}; + +struct rk808 { + struct i2c_client *i2c; + struct regmap_irq_chip_data *irq_data; + struct regmap *regmap; +}; +#endif /* __LINUX_REGULATOR_rk808_H */ diff --git a/include/linux/mfd/rn5t618.h b/include/linux/mfd/rn5t618.h new file mode 100644 index 000000000000..c72d5344f3b3 --- /dev/null +++ b/include/linux/mfd/rn5t618.h @@ -0,0 +1,228 @@ +/* + * MFD core driver for Ricoh RN5T618 PMIC + * + * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __LINUX_MFD_RN5T618_H +#define __LINUX_MFD_RN5T618_H + +#include <linux/regmap.h> + +#define RN5T618_LSIVER 0x00 +#define RN5T618_OTPVER 0x01 +#define RN5T618_IODAC 0x02 +#define RN5T618_VINDAC 0x03 +#define RN5T618_CPUCNT 0x06 +#define RN5T618_PSWR 0x07 +#define RN5T618_PONHIS 0x09 +#define RN5T618_POFFHIS 0x0a +#define RN5T618_WATCHDOG 0x0b +#define RN5T618_WATCHDOGCNT 0x0c +#define RN5T618_PWRFUNC 0x0d +#define RN5T618_SLPCNT 0x0e +#define RN5T618_REPCNT 0x0f +#define RN5T618_PWRONTIMSET 0x10 +#define RN5T618_NOETIMSETCNT 0x11 +#define RN5T618_PWRIREN 0x12 +#define RN5T618_PWRIRQ 0x13 +#define RN5T618_PWRMON 0x14 +#define RN5T618_PWRIRSEL 0x15 +#define RN5T618_DC1_SLOT 0x16 +#define RN5T618_DC2_SLOT 0x17 +#define RN5T618_DC3_SLOT 0x18 +#define RN5T618_LDO1_SLOT 0x1b +#define RN5T618_LDO2_SLOT 0x1c +#define RN5T618_LDO3_SLOT 0x1d +#define RN5T618_LDO4_SLOT 0x1e +#define RN5T618_LDO5_SLOT 0x1f +#define RN5T618_PSO0_SLOT 0x25 +#define RN5T618_PSO1_SLOT 0x26 +#define RN5T618_PSO2_SLOT 0x27 +#define RN5T618_PSO3_SLOT 0x28 +#define RN5T618_LDORTC1_SLOT 0x2a +#define RN5T618_DC1CTL 0x2c +#define RN5T618_DC1CTL2 0x2d +#define RN5T618_DC2CTL 0x2e +#define RN5T618_DC2CTL2 0x2f +#define RN5T618_DC3CTL 0x30 +#define RN5T618_DC3CTL2 0x31 +#define RN5T618_DC1DAC 0x36 +#define RN5T618_DC2DAC 0x37 +#define RN5T618_DC3DAC 0x38 +#define RN5T618_DC1DAC_SLP 0x3b +#define RN5T618_DC2DAC_SLP 0x3c +#define RN5T618_DC3DAC_SLP 0x3d +#define RN5T618_DCIREN 0x40 +#define RN5T618_DCIRQ 0x41 +#define RN5T618_DCIRMON 0x42 +#define RN5T618_LDOEN1 0x44 +#define RN5T618_LDOEN2 0x45 +#define RN5T618_LDODIS 0x46 +#define RN5T618_LDO1DAC 0x4c +#define RN5T618_LDO2DAC 0x4d +#define RN5T618_LDO3DAC 0x4e +#define RN5T618_LDO4DAC 0x4f +#define RN5T618_LDO5DAC 0x50 +#define RN5T618_LDORTCDAC 0x56 +#define RN5T618_LDORTC2DAC 0x57 +#define RN5T618_LDO1DAC_SLP 0x58 +#define RN5T618_LDO2DAC_SLP 0x59 +#define RN5T618_LDO3DAC_SLP 0x5a +#define RN5T618_LDO4DAC_SLP 0x5b +#define RN5T618_LDO5DAC_SLP 0x5c +#define RN5T618_ADCCNT1 0x64 +#define RN5T618_ADCCNT2 0x65 +#define RN5T618_ADCCNT3 0x66 +#define RN5T618_ILIMDATAH 0x68 +#define RN5T618_ILIMDATAL 0x69 +#define RN5T618_VBATDATAH 0x6a +#define RN5T618_VBATDATAL 0x6b +#define RN5T618_VADPDATAH 0x6c +#define RN5T618_VADPDATAL 0x6d +#define RN5T618_VUSBDATAH 0x6e +#define RN5T618_VUSBDATAL 0x6f +#define RN5T618_VSYSDATAH 0x70 +#define RN5T618_VSYSDATAL 0x71 +#define RN5T618_VTHMDATAH 0x72 +#define RN5T618_VTHMDATAL 0x73 +#define RN5T618_AIN1DATAH 0x74 +#define RN5T618_AIN1DATAL 0x75 +#define RN5T618_AIN0DATAH 0x76 +#define RN5T618_AIN0DATAL 0x77 +#define RN5T618_ILIMTHL 0x78 +#define RN5T618_ILIMTHH 0x79 +#define RN5T618_VBATTHL 0x7a +#define RN5T618_VBATTHH 0x7b +#define RN5T618_VADPTHL 0x7c +#define RN5T618_VADPTHH 0x7d +#define RN5T618_VUSBTHL 0x7e +#define RN5T618_VUSBTHH 0x7f +#define RN5T618_VSYSTHL 0x80 +#define RN5T618_VSYSTHH 0x81 +#define RN5T618_VTHMTHL 0x82 +#define RN5T618_VTHMTHH 0x83 +#define RN5T618_AIN1THL 0x84 +#define RN5T618_AIN1THH 0x85 +#define RN5T618_AIN0THL 0x86 +#define RN5T618_AIN0THH 0x87 +#define RN5T618_EN_ADCIR1 0x88 +#define RN5T618_EN_ADCIR2 0x89 +#define RN5T618_EN_ADCIR3 0x8a +#define RN5T618_IR_ADC1 0x8c +#define RN5T618_IR_ADC2 0x8d +#define RN5T618_IR_ADC3 0x8e +#define RN5T618_IOSEL 0x90 +#define RN5T618_IOOUT 0x91 +#define RN5T618_GPEDGE1 0x92 +#define RN5T618_GPEDGE2 0x93 +#define RN5T618_EN_GPIR 0x94 +#define RN5T618_IR_GPR 0x95 +#define RN5T618_IR_GPF 0x96 +#define RN5T618_MON_IOIN 0x97 +#define RN5T618_GPLED_FUNC 0x98 +#define RN5T618_INTPOL 0x9c +#define RN5T618_INTEN 0x9d +#define RN5T618_INTMON 0x9e +#define RN5T618_PREVINDAC 0xb0 +#define RN5T618_BATDAC 0xb1 +#define RN5T618_CHGCTL1 0xb3 +#define RN5T618_CHGCTL2 0xb4 +#define RN5T618_VSYSSET 0xb5 +#define RN5T618_REGISET1 0xb6 +#define RN5T618_REGISET2 0xb7 +#define RN5T618_CHGISET 0xb8 +#define RN5T618_TIMSET 0xb9 +#define RN5T618_BATSET1 0xba +#define RN5T618_BATSET2 0xbb +#define RN5T618_DIESET 0xbc +#define RN5T618_CHGSTATE 0xbd +#define RN5T618_CHGCTRL_IRFMASK 0xbe +#define RN5T618_CHGSTAT_IRFMASK1 0xbf +#define RN5T618_CHGSTAT_IRFMASK2 0xc0 +#define RN5T618_CHGERR_IRFMASK 0xc1 +#define RN5T618_CHGCTRL_IRR 0xc2 +#define RN5T618_CHGSTAT_IRR1 0xc3 +#define RN5T618_CHGSTAT_IRR2 0xc4 +#define RN5T618_CHGERR_IRR 0xc5 +#define RN5T618_CHGCTRL_MONI 0xc6 +#define RN5T618_CHGSTAT_MONI1 0xc7 +#define RN5T618_CHGSTAT_MONI2 0xc8 +#define RN5T618_CHGERR_MONI 0xc9 +#define RN5T618_CHGCTRL_DETMOD1 0xca +#define RN5T618_CHGCTRL_DETMOD2 0xcb +#define RN5T618_CHGSTAT_DETMOD1 0xcc +#define RN5T618_CHGSTAT_DETMOD2 0xcd +#define RN5T618_CHGSTAT_DETMOD3 0xce +#define RN5T618_CHGERR_DETMOD1 0xcf +#define RN5T618_CHGERR_DETMOD2 0xd0 +#define RN5T618_CHGOSCCTL 0xd4 +#define RN5T618_CHGOSCSCORESET1 0xd5 +#define RN5T618_CHGOSCSCORESET2 0xd6 +#define RN5T618_CHGOSCSCORESET3 0xd7 +#define RN5T618_CHGOSCFREQSET1 0xd8 +#define RN5T618_CHGOSCFREQSET2 0xd9 +#define RN5T618_CONTROL 0xe0 +#define RN5T618_SOC 0xe1 +#define RN5T618_RE_CAP_H 0xe2 +#define RN5T618_RE_CAP_L 0xe3 +#define RN5T618_FA_CAP_H 0xe4 +#define RN5T618_FA_CAP_L 0xe5 +#define RN5T618_AGE 0xe6 +#define RN5T618_TT_EMPTY_H 0xe7 +#define RN5T618_TT_EMPTY_L 0xe8 +#define RN5T618_TT_FULL_H 0xe9 +#define RN5T618_TT_FULL_L 0xea +#define RN5T618_VOLTAGE_1 0xeb +#define RN5T618_VOLTAGE_0 0xec +#define RN5T618_TEMP_1 0xed +#define RN5T618_TEMP_0 0xee +#define RN5T618_CC_CTRL 0xef +#define RN5T618_CC_COUNT2 0xf0 +#define RN5T618_CC_COUNT1 0xf1 +#define RN5T618_CC_COUNT0 0xf2 +#define RN5T618_CC_SUMREG3 0xf3 +#define RN5T618_CC_SUMREG2 0xf4 +#define RN5T618_CC_SUMREG1 0xf5 +#define RN5T618_CC_SUMREG0 0xf6 +#define RN5T618_CC_OFFREG1 0xf7 +#define RN5T618_CC_OFFREG0 0xf8 +#define RN5T618_CC_GAINREG1 0xf9 +#define RN5T618_CC_GAINREG0 0xfa +#define RN5T618_CC_AVEREG1 0xfb +#define RN5T618_CC_AVEREG0 0xfc +#define RN5T618_MAX_REG 0xfc + +#define RN5T618_REPCNT_REPWRON BIT(0) +#define RN5T618_SLPCNT_SWPWROFF BIT(0) +#define RN5T618_WATCHDOG_WDOGEN BIT(2) +#define RN5T618_WATCHDOG_WDOGTIM_M (BIT(0) | BIT(1)) +#define RN5T618_WATCHDOG_WDOGTIM_S 0 +#define RN5T618_PWRIRQ_IR_WDOG BIT(6) + +enum { + RN5T618_DCDC1, + RN5T618_DCDC2, + RN5T618_DCDC3, + RN5T618_LDO1, + RN5T618_LDO2, + RN5T618_LDO3, + RN5T618_LDO4, + RN5T618_LDO5, + RN5T618_LDORTC1, + RN5T618_LDORTC2, + RN5T618_REG_NUM, +}; + +struct rn5t618 { + struct regmap *regmap; +}; + +#endif /* __LINUX_MFD_RN5T618_H */ diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index fb96c84dada5..e2e70053470e 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -155,6 +155,7 @@ struct ti_tscadc_dev { void __iomem *tscadc_base; int irq; int used_cells; /* 1-2 */ + int tsc_wires; int tsc_cell; /* -1 if not used */ int adc_cell; /* -1 if not used */ struct mfd_cell cells[TSCADC_CELLS]; diff --git a/include/linux/mfd/ti_ssp.h b/include/linux/mfd/ti_ssp.h deleted file mode 100644 index dbb4b43bd20e..000000000000 --- a/include/linux/mfd/ti_ssp.h +++ /dev/null @@ -1,93 +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 - */ - -#ifndef __TI_SSP_H__ -#define __TI_SSP_H__ - -struct ti_ssp_dev_data { - const char *dev_name; - void *pdata; - size_t pdata_size; -}; - -struct ti_ssp_data { - unsigned long out_clock; - struct ti_ssp_dev_data dev_data[2]; -}; - -struct ti_ssp_spi_data { - unsigned long iosel; - int num_cs; - void (*select)(int cs); -}; - -/* - * Sequencer port IO pin configuration bits. These do not correlate 1-1 with - * the hardware. The iosel field in the port data combines iosel1 and iosel2, - * and is therefore not a direct map to register space. It is best to use the - * macros below to construct iosel values. - * - * least significant 16 bits --> iosel1 - * most significant 16 bits --> iosel2 - */ - -#define SSP_IN 0x0000 -#define SSP_DATA 0x0001 -#define SSP_CLOCK 0x0002 -#define SSP_CHIPSEL 0x0003 -#define SSP_OUT 0x0004 -#define SSP_PIN_SEL(pin, v) ((v) << ((pin) * 3)) -#define SSP_PIN_MASK(pin) SSP_PIN_SEL(pin, 0x7) -#define SSP_INPUT_SEL(pin) ((pin) << 16) - -/* Sequencer port config bits */ -#define SSP_EARLY_DIN BIT(8) -#define SSP_DELAY_DOUT BIT(9) - -/* Sequence map definitions */ -#define SSP_CLK_HIGH BIT(0) -#define SSP_CLK_LOW 0 -#define SSP_DATA_HIGH BIT(1) -#define SSP_DATA_LOW 0 -#define SSP_CS_HIGH BIT(2) -#define SSP_CS_LOW 0 -#define SSP_OUT_MODE BIT(3) -#define SSP_IN_MODE 0 -#define SSP_DATA_REG BIT(4) -#define SSP_ADDR_REG 0 - -#define SSP_OPCODE_DIRECT ((0x0) << 5) -#define SSP_OPCODE_TOGGLE ((0x1) << 5) -#define SSP_OPCODE_SHIFT ((0x2) << 5) -#define SSP_OPCODE_BRANCH0 ((0x4) << 5) -#define SSP_OPCODE_BRANCH1 ((0x5) << 5) -#define SSP_OPCODE_BRANCH ((0x6) << 5) -#define SSP_OPCODE_STOP ((0x7) << 5) -#define SSP_BRANCH(addr) ((addr) << 8) -#define SSP_COUNT(cycles) ((cycles) << 8) - -int ti_ssp_raw_read(struct device *dev); -int ti_ssp_raw_write(struct device *dev, u32 val); -int ti_ssp_load(struct device *dev, int offs, u32* prog, int len); -int ti_ssp_run(struct device *dev, u32 pc, u32 input, u32 *output); -int ti_ssp_set_mode(struct device *dev, int mode); -int ti_ssp_set_iosel(struct device *dev, u32 iosel); - -#endif /* __TI_SSP_H__ */ diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h index 95d6938737fd..ac7fba44d7e4 100644 --- a/include/linux/mfd/tps65217.h +++ b/include/linux/mfd/tps65217.h @@ -60,6 +60,8 @@ #define TPS65217_REG_SEQ5 0X1D #define TPS65217_REG_SEQ6 0X1E +#define TPS65217_REG_MAX TPS65217_REG_SEQ6 + /* Register field definitions */ #define TPS65217_CHIPID_CHIP_MASK 0xF0 #define TPS65217_CHIPID_REV_MASK 0x0F diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 24f97bf74266..1fa99a301817 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2560,6 +2560,7 @@ #define PCI_DEVICE_ID_INTEL_MFD_EMMC0 0x0823 #define PCI_DEVICE_ID_INTEL_MFD_EMMC1 0x0824 #define PCI_DEVICE_ID_INTEL_MRST_SD2 0x084F +#define PCI_DEVICE_ID_INTEL_QUARK_X1000_ILB 0x095E #define PCI_DEVICE_ID_INTEL_I960 0x0960 #define PCI_DEVICE_ID_INTEL_I960RM 0x0962 #define PCI_DEVICE_ID_INTEL_CENTERTON_ILB 0x0c60 diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 2c71f16bd661..0c05e7a7945f 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1220,7 +1220,7 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream, break; case ARIZONA_CLK_ASYNCCLK: snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1, - ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val); + ARIZONA_ASYNC_SAMPLE_RATE_1_MASK, sr_val); if (base) snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, ARIZONA_AIF1_RATE_MASK, |