Commit bc914532 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mfd-for-linus-4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd

Pull MFD updates from Lee Jones:
 "New Device Support:
   - Add support for 88pm860; 88pm80x
   - Add support for 24c08 EEPROM; at24
   - Add support for Broxton Whiskey Cove; intel*
   - Add support for RTS522A; rts5227
   - Add support for I2C devices; intel_quark_i2c_gpio

  New Functionality:
   - Add microphone support; arizona
   - Add general purpose switch support; arizona
   - Add fuel-gauge support; da9150-core
   - Add shutdown support; sec-core
   - Add charger support; tps65217
   - Add flexible serial communication unit support; atmel-flexcom
   - Add power button support; axp20x
   - Add led-flash support; rt5033

  Core Frameworks:
   - Supply a generic macro for defining Regmap IRQs
   - Rework ACPI child device matching

  Fix-ups:
   - Use Regmap to access registers; tps6105x
   - Use DEFINE_RES_IRQ_NAMED() macro; da9150
   - Re-arrange device registration order; intel_quark_i2c_gpio
   - Allow OF matching; cros_ec_i2c, atmel-hlcdc, hi6421-pmic, max8997, sm501
   - Handle deferred probe; twl6040
   - Improve accuracy of headphone detect; arizona
   - Unnecessary MODULE_ALIAS() removal; bcm590xx, rt5033
   - Remove unused code; htc-i2cpld, arizona, pcf50633-irq, sec-core
   - Simplify code; kempld, rts5209, da903x, lm3533, da9052, arizona
   - Remove #iffery; arizona
   - DT binding adaptions; many

  Bug Fixes:
   - Fix possible NULL pointer dereference; wm831x, tps6105x
   - Fix 64bit bug; intel_soc_pmic_bxtwc
   - Fix signedness issue; arizona"

* tag 'mfd-for-linus-4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (73 commits)
  bindings: mfd: s2mps11: Add documentation for s2mps15 PMIC
  mfd: sec-core: Remove unused s2mpu02-rtc and s2mpu02-clk children
  extcon: arizona: Add extcon specific device tree binding document
  MAINTAINERS: Add binding docs for Cirrus Logic/Wolfson Arizona devices
  mfd: arizona: Remove bindings covered in new subsystem specific docs
  mfd: rt5033: Add RT5033 Flash led sub device
  mfd: lpss: Add Intel Broxton PCI IDs
  mfd: lpss: Add Broxton ACPI IDs
  mfd: arizona: Signedness bug in arizona_runtime_suspend()
  mfd: axp20x: Add a cell for the power button part of the, axp288 PMICs
  mfd: dt-bindings: Document pulled down WRSTBI pin on S2MPS1X
  mfd: sec-core: Disable buck voltage reset on watchdog falling edge
  mfd: sec-core: Dump PMIC revision to find out the HW
  mfd: arizona: Use correct type ID for device tree config
  mfd: arizona: Remove use of codec build config #ifdefs
  mfd: arizona: Simplify adding subdevices
  mfd: arizona: Downgrade type mismatch messages to dev_warn
  mfd: arizona: Factor out checking of jack detection state
  mfd: arizona: Factor out DCVDD isolation control
  mfd: Make TPS6105X select REGMAP_I2C
  ...
parents 54727e6e 271bb177
...@@ -347,13 +347,18 @@ For the first case, the MFD drivers do not need to do anything. The ...@@ -347,13 +347,18 @@ 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 resulting child platform device will have its ACPI_COMPANION() set to point
to the parent device. to the parent device.
If the ACPI namespace has a device that we can match using an ACPI id, If the ACPI namespace has a device that we can match using an ACPI id or ACPI
the id should be set like: adr, the cell should be set like:
static struct mfd_cell_acpi_match my_subdevice_cell_acpi_match = {
.pnpid = "XYZ0001",
.adr = 0,
};
static struct mfd_cell my_subdevice_cell = { static struct mfd_cell my_subdevice_cell = {
.name = "my_subdevice", .name = "my_subdevice",
/* set the resources relative to the parent */ /* set the resources relative to the parent */
.acpi_pnpid = "XYZ0001", .acpi_match = &my_subdevice_cell_acpi_match,
}; };
The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under
......
Cirrus Logic Arizona class audio SoCs
These devices are audio SoCs with extensive digital capabilities and a range
of analogue I/O.
This document lists Extcon specific bindings, see the primary binding document:
../mfd/arizona.txt
Optional properties:
- wlf,hpdet-channel : Headphone detection channel.
ARIZONA_ACCDET_MODE_HPL or 1 - Headphone detect mode is set to HPDETL
ARIZONA_ACCDET_MODE_HPR or 2 - Headphone detect mode is set to HPDETR
If this node is not mentioned or if the value is unknown, then
headphone detection mode is set to HPDETL.
...@@ -44,7 +44,6 @@ Required properties: ...@@ -44,7 +44,6 @@ Required properties:
Optional properties: Optional properties:
- wlf,reset : GPIO specifier for the GPIO controlling /RESET - wlf,reset : GPIO specifier for the GPIO controlling /RESET
- wlf,ldoena : GPIO specifier for the GPIO controlling LDOENA
- wlf,gpio-defaults : A list of GPIO configuration register values. Defines - wlf,gpio-defaults : A list of GPIO configuration register values. Defines
for the appropriate values can found in <dt-bindings/mfd/arizona.txt>. If for the appropriate values can found in <dt-bindings/mfd/arizona.txt>. If
...@@ -67,21 +66,13 @@ Optional properties: ...@@ -67,21 +66,13 @@ Optional properties:
present, the number of values should be less than or equal to the present, the number of values should be less than or equal to the
number of inputs, unspecified inputs will use the chip default. number of inputs, unspecified inputs will use the chip default.
- wlf,hpdet-channel : Headphone detection channel.
ARIZONA_ACCDET_MODE_HPL or 1 - Headphone detect mode is set to HPDETL
ARIZONA_ACCDET_MODE_HPR or 2 - Headphone detect mode is set to HPDETR
If this node is not mentioned or if the value is unknown, then
headphone detection mode is set to HPDETL.
- DCVDD-supply, MICVDD-supply : Power supplies, only need to be specified if - DCVDD-supply, MICVDD-supply : Power supplies, only need to be specified if
they are being externally supplied. As covered in they are being externally supplied. As covered in
Documentation/devicetree/bindings/regulator/regulator.txt Documentation/devicetree/bindings/regulator/regulator.txt
Optional subnodes: Also see child specific device properties:
- ldo1 : Initial data for the LDO1 regulator, as covered in Regulator - ../regulator/arizona-regulator.txt
Documentation/devicetree/bindings/regulator/regulator.txt Extcon - ../extcon/extcon-arizona.txt
- micvdd : Initial data for the MICVDD regulator, as covered in
Documentation/devicetree/bindings/regulator/regulator.txt
Example: Example:
......
* Device tree bindings for Atmel Flexcom (Flexible Serial Communication Unit)
The Atmel Flexcom is just a wrapper which embeds a SPI controller, an I2C
controller and an USART. Only one function can be used at a time and is chosen
at boot time according to the device tree.
Required properties:
- compatible: Should be "atmel,sama5d2-flexcom"
- reg: Should be the offset/length value for Flexcom dedicated
I/O registers (without USART, TWI or SPI registers).
- clocks: Should be the Flexcom peripheral clock from PMC.
- #address-cells: Should be <1>
- #size-cells: Should be <1>
- ranges: Should be one range for the full I/O register region
(including USART, TWI and SPI registers).
- atmel,flexcom-mode: Should be one of the following values:
- <1> for USART
- <2> for SPI
- <3> for I2C
Required child:
A single available child device of type matching the "atmel,flexcom-mode"
property.
The phandle provided by the clocks property of the child is the same as one for
the Flexcom parent.
For other properties, please refer to the documentations of the respective
device:
- ../serial/atmel-usart.txt
- ../spi/spi_atmel.txt
- ../i2c/i2c-at91.txt
Example:
flexcom@f8034000 {
compatible = "atmel,sama5d2-flexcom";
reg = <0xf8034000 0x200>;
clocks = <&flx0_clk>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0xf8034000 0x800>;
atmel,flexcom-mode = <2>;
spi@400 {
compatible = "atmel,at91rm9200-spi";
reg = <0x400 0x200>;
interrupts = <19 IRQ_TYPE_LEVEL_HIGH 7>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flx0_default>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&flx0_clk>;
clock-names = "spi_clk";
atmel,fifo-size = <32>;
mtd_dataflash@0 {
compatible = "atmel,at25f512b";
reg = <0>;
spi-max-frequency = <20000000>;
};
};
};
...@@ -34,6 +34,10 @@ Required properties (LPC): ...@@ -34,6 +34,10 @@ Required properties (LPC):
- compatible: "google,cros-ec-lpc" - compatible: "google,cros-ec-lpc"
- reg: List of (IO address, size) pairs defining the interface uses - reg: List of (IO address, size) pairs defining the interface uses
Optional properties (all):
- google,has-vbc-nvram: Some implementations of the EC include a small
nvram space used to store verified boot context data. This boolean flag
is used to specify whether this nvram is present or not.
Example for I2C: Example for I2C:
......
...@@ -6,6 +6,7 @@ Device Description ...@@ -6,6 +6,7 @@ Device Description
------ ----------- ------ -----------
da9150-gpadc : General Purpose ADC da9150-gpadc : General Purpose ADC
da9150-charger : Battery Charger da9150-charger : Battery Charger
da9150-fg : Battery Fuel-Gauge
====== ======
...@@ -16,13 +17,13 @@ Required properties: ...@@ -16,13 +17,13 @@ Required properties:
the IRQs from da9150 are delivered to. the IRQs from da9150 are delivered to.
- interrupts: IRQ line info for da9150 chip. - interrupts: IRQ line info for da9150 chip.
- interrupt-controller: da9150 has internal IRQs (own IRQ domain). - interrupt-controller: da9150 has internal IRQs (own IRQ domain).
(See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for (See ../interrupt-controller/interrupts.txt for
further information relating to interrupt properties) further information relating to interrupt properties)
Sub-devices: Sub-devices:
- da9150-gpadc: See Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt - da9150-gpadc: See ../iio/adc/da9150-gpadc.txt
- da9150-charger: See Documentation/devicetree/bindings/power/da9150-charger.txt - da9150-charger: See ../power/da9150-charger.txt
- da9150-fg: See ../power/da9150-fg.txt
Example: Example:
...@@ -34,10 +35,28 @@ Example: ...@@ -34,10 +35,28 @@ Example:
interrupt-controller; interrupt-controller;
gpadc: da9150-gpadc { gpadc: da9150-gpadc {
... compatible = "dlg,da9150-gpadc";
#io-channel-cells = <1>;
};
charger {
compatible = "dlg,da9150-charger";
io-channels = <&gpadc 0>,
<&gpadc 2>,
<&gpadc 8>,
<&gpadc 5>;
io-channel-names = "CHAN_IBUS",
"CHAN_VBUS",
"CHAN_TJUNC",
"CHAN_VBAT";
}; };
da9150-charger { fuel-gauge {
... compatible = "dlg,da9150-fuel-gauge";
dlg,update-interval = <10000>;
dlg,warn-soc-level = /bits/ 8 <15>;
dlg,crit-soc-level = /bits/ 8 <5>
}; };
}; };
* Samsung S2MPS11, S2MPS13, S2MPS14 and S2MPU02 Voltage and Current Regulator * Samsung S2MPS11/13/14/15 and S2MPU02 Voltage and Current Regulator
The Samsung S2MPS11 is a multi-function device which includes voltage and The Samsung S2MPS11 is a multi-function device which includes voltage and
current regulators, RTC, charger controller and other sub-blocks. It is current regulators, RTC, charger controller and other sub-blocks. It is
...@@ -7,17 +7,24 @@ interfaced to the host controller using an I2C interface. Each sub-block is ...@@ -7,17 +7,24 @@ interfaced to the host controller using an I2C interface. Each sub-block is
addressed by the host system using different I2C slave addresses. addressed by the host system using different I2C slave addresses.
Required properties: Required properties:
- compatible: Should be "samsung,s2mps11-pmic" or "samsung,s2mps13-pmic" - compatible: Should be one of the following
or "samsung,s2mps14-pmic" or "samsung,s2mpu02-pmic". - "samsung,s2mps11-pmic"
- "samsung,s2mps13-pmic"
- "samsung,s2mps14-pmic"
- "samsung,s2mps15-pmic"
- "samsung,s2mpu02-pmic".
- reg: Specifies the I2C slave address of the pmic block. It should be 0x66. - reg: Specifies the I2C slave address of the pmic block. It should be 0x66.
Optional properties: Optional properties:
- interrupt-parent: Specifies the phandle of the interrupt controller to which - interrupt-parent: Specifies the phandle of the interrupt controller to which
the interrupts from s2mps11 are delivered to. the interrupts from s2mps11 are delivered to.
- interrupts: Interrupt specifiers for interrupt sources. - interrupts: Interrupt specifiers for interrupt sources.
- samsung,s2mps11-wrstbi-ground: Indicates that WRSTBI pin of PMIC is pulled
down. When the system is suspended it will always go down thus triggerring
unwanted buck warm reset (setting buck voltages to default values).
Optional nodes: Optional nodes:
- clocks: s2mps11, s2mps13 and s5m8767 provide three(AP/CP/BT) buffered 32.768 - clocks: s2mps11, s2mps13, s2mps15 and s5m8767 provide three(AP/CP/BT) buffered 32.768
KHz outputs, so to register these as clocks with common clock framework KHz outputs, so to register these as clocks with common clock framework
instantiate a sub-node named "clocks". It uses the common clock binding instantiate a sub-node named "clocks". It uses the common clock binding
documented in : documented in :
...@@ -30,12 +37,13 @@ Optional nodes: ...@@ -30,12 +37,13 @@ Optional nodes:
the clock which they consume. the clock which they consume.
Clock ID Devices Clock ID Devices
---------------------------------------------------------- ----------------------------------------------------------
32KhzAP 0 S2MPS11, S2MPS13, S2MPS14, S5M8767 32KhzAP 0 S2MPS11, S2MPS13, S2MPS14, S2MPS15, S5M8767
32KhzCP 1 S2MPS11, S2MPS13, S5M8767 32KhzCP 1 S2MPS11, S2MPS13, S2MPS15, S5M8767
32KhzBT 2 S2MPS11, S2MPS13, S2MPS14, S5M8767 32KhzBT 2 S2MPS11, S2MPS13, S2MPS14, S2MPS15, S5M8767
- compatible: Should be one of: "samsung,s2mps11-clk", "samsung,s2mps13-clk", - compatible: Should be one of: "samsung,s2mps11-clk", "samsung,s2mps13-clk",
"samsung,s2mps14-clk", "samsung,s5m8767-clk" "samsung,s2mps14-clk", "samsung,s5m8767-clk"
The s2msp15 uses the same compatible as s2mps13, as both provides similar clocks.
- regulators: The regulators of s2mps11 that have to be instantiated should be - regulators: The regulators of s2mps11 that have to be instantiated should be
included in a sub-node named 'regulators'. Regulator nodes included in this included in a sub-node named 'regulators'. Regulator nodes included in this
...@@ -83,6 +91,7 @@ as per the datasheet of s2mps11. ...@@ -83,6 +91,7 @@ as per the datasheet of s2mps11.
- S2MPS11: 1 to 38 - S2MPS11: 1 to 38
- S2MPS13: 1 to 40 - S2MPS13: 1 to 40
- S2MPS14: 1 to 25 - S2MPS14: 1 to 25
- S2MPS15: 1 to 27
- S2MPU02: 1 to 28 - S2MPU02: 1 to 28
- Example: LDO1, LDO2, LDO28 - Example: LDO1, LDO2, LDO28
- BUCKn - BUCKn
...@@ -90,6 +99,7 @@ as per the datasheet of s2mps11. ...@@ -90,6 +99,7 @@ as per the datasheet of s2mps11.
- S2MPS11: 1 to 10 - S2MPS11: 1 to 10
- S2MPS13: 1 to 10 - S2MPS13: 1 to 10
- S2MPS14: 1 to 5 - S2MPS14: 1 to 5
- S2MPS15: 1 to 10
- S2MPU02: 1 to 7 - S2MPU02: 1 to 7
- Example: BUCK1, BUCK2, BUCK9 - Example: BUCK1, BUCK2, BUCK9
......
Dialog Semiconductor DA9150 Fuel-Gauge Power Supply bindings
Required properties:
- compatible: "dlg,da9150-fuel-gauge" for DA9150 Fuel-Gauge Power Supply
Optional properties:
- dlg,update-interval: Interval time (milliseconds) between battery level checks.
- dlg,warn-soc-level: Battery discharge level (%) where warning event raised.
[1 - 100]
- dlg,crit-soc-level: Battery discharge level (%) where critical event raised.
This value should be lower than the warning level.
[1 - 100]
Example:
fuel-gauge {
compatible = "dlg,da9150-fuel-gauge";
dlg,update-interval = <10000>;
dlg,warn-soc-level = /bits/ 8 <15>;
dlg,crit-soc-level = /bits/ 8 <5>;
};
...@@ -7162,7 +7162,6 @@ F: drivers/media/i2c/mt9v032.c ...@@ -7162,7 +7162,6 @@ F: drivers/media/i2c/mt9v032.c
F: include/media/mt9v032.h F: include/media/mt9v032.h
MULTIFUNCTION DEVICES (MFD) MULTIFUNCTION DEVICES (MFD)
M: Samuel Ortiz <sameo@linux.intel.com>
M: Lee Jones <lee.jones@linaro.org> M: Lee Jones <lee.jones@linaro.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
S: Supported S: Supported
...@@ -11567,6 +11566,9 @@ T: git https://github.com/CirrusLogic/linux-drivers.git ...@@ -11567,6 +11566,9 @@ T: git https://github.com/CirrusLogic/linux-drivers.git
W: https://github.com/CirrusLogic/linux-drivers/wiki W: https://github.com/CirrusLogic/linux-drivers/wiki
S: Supported S: Supported
F: Documentation/hwmon/wm83?? F: Documentation/hwmon/wm83??
F: Documentation/devicetree/bindings/extcon/extcon-arizona.txt
F: Documentation/devicetree/bindings/regulator/arizona-regulator.txt
F: Documentation/devicetree/bindings/mfd/arizona.txt
F: arch/arm/mach-s3c64xx/mach-crag6410* F: arch/arm/mach-s3c64xx/mach-crag6410*
F: drivers/clk/clk-wm83*.c F: drivers/clk/clk-wm83*.c
F: drivers/extcon/extcon-arizona.c F: drivers/extcon/extcon-arizona.c
......
...@@ -33,6 +33,8 @@ static struct pm80x_chip_mapping chip_mapping[] = { ...@@ -33,6 +33,8 @@ static struct pm80x_chip_mapping chip_mapping[] = {
{0x3, CHIP_PM800}, {0x3, CHIP_PM800},
/* 88PM805 chip id number */ /* 88PM805 chip id number */
{0x0, CHIP_PM805}, {0x0, CHIP_PM805},
/* 88PM860 chip id number */
{0x4, CHIP_PM860},
}; };
/* /*
......
...@@ -60,6 +60,17 @@ config MFD_AAT2870_CORE ...@@ -60,6 +60,17 @@ config MFD_AAT2870_CORE
additional drivers must be enabled in order to use the additional drivers must be enabled in order to use the
functionality of the device. functionality of the device.
config MFD_ATMEL_FLEXCOM
tristate "Atmel Flexcom (Flexible Serial Communication Unit)"
select MFD_CORE
depends on OF
help
Select this to get support for Atmel Flexcom. This is a wrapper
which embeds a SPI controller, a I2C controller and a USART. Only
one function can be used at a time. The choice is done at boot time
by the probe function of this MFD driver according to a device tree
property.
config MFD_ATMEL_HLCDC config MFD_ATMEL_HLCDC
tristate "Atmel HLCDC (High-end LCD Controller)" tristate "Atmel HLCDC (High-end LCD Controller)"
select MFD_CORE select MFD_CORE
...@@ -725,9 +736,10 @@ config MFD_RTSX_PCI ...@@ -725,9 +736,10 @@ config MFD_RTSX_PCI
select MFD_CORE select MFD_CORE
help help
This supports for Realtek PCI-Express card reader including rts5209, This supports for Realtek PCI-Express card reader including rts5209,
rts5229, rtl8411, etc. Realtek card reader supports access to many rts5227, rts522A, rts5229, rts5249, rts524A, rts525A, rtl8411, etc.
types of memory cards, such as Memory Stick, Memory Stick Pro, Realtek card reader supports access to many types of memory cards,
Secure Digital and MultiMediaCard. such as Memory Stick, Memory Stick Pro, Secure Digital and
MultiMediaCard.
config MFD_RT5033 config MFD_RT5033
tristate "Richtek RT5033 Power Management IC" tristate "Richtek RT5033 Power Management IC"
...@@ -1059,6 +1071,7 @@ config MFD_PALMAS ...@@ -1059,6 +1071,7 @@ config MFD_PALMAS
config TPS6105X config TPS6105X
tristate "TI TPS61050/61052 Boost Converters" tristate "TI TPS61050/61052 Boost Converters"
depends on I2C depends on I2C
select REGMAP_I2C
select REGULATOR select REGULATOR
select MFD_CORE select MFD_CORE
select REGULATOR_FIXED_VOLTAGE select REGULATOR_FIXED_VOLTAGE
...@@ -1471,7 +1484,7 @@ config MFD_WM8994 ...@@ -1471,7 +1484,7 @@ config MFD_WM8994
config MFD_STW481X config MFD_STW481X
tristate "Support for ST Microelectronics STw481x" tristate "Support for ST Microelectronics STw481x"
depends on I2C && ARCH_NOMADIK depends on I2C && (ARCH_NOMADIK || COMPILE_TEST)
select REGMAP_I2C select REGMAP_I2C
select MFD_CORE select MFD_CORE
help help
......
...@@ -164,6 +164,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o ...@@ -164,6 +164,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o
obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
obj-$(CONFIG_MFD_TPS65090) += tps65090.o obj-$(CONFIG_MFD_TPS65090) += tps65090.o
obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
obj-$(CONFIG_MFD_ATMEL_FLEXCOM) += atmel-flexcom.o
obj-$(CONFIG_MFD_ATMEL_HLCDC) += atmel-hlcdc.o obj-$(CONFIG_MFD_ATMEL_HLCDC) += atmel-hlcdc.o
obj-$(CONFIG_MFD_INTEL_LPSS) += intel-lpss.o obj-$(CONFIG_MFD_INTEL_LPSS) += intel-lpss.o
obj-$(CONFIG_MFD_INTEL_LPSS_PCI) += intel-lpss-pci.o obj-$(CONFIG_MFD_INTEL_LPSS_PCI) += intel-lpss-pci.o
...@@ -190,5 +191,6 @@ obj-$(CONFIG_MFD_RT5033) += rt5033.o ...@@ -190,5 +191,6 @@ obj-$(CONFIG_MFD_RT5033) += rt5033.o
obj-$(CONFIG_MFD_SKY81452) += sky81452.o obj-$(CONFIG_MFD_SKY81452) += sky81452.o
intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC) += intel_soc_pmic_bxtwc.o
obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
obj-$(CONFIG_MFD_MT6397) += mt6397-core.o obj-$(CONFIG_MFD_MT6397) += mt6397-core.o
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/mfd/arizona/core.h> #include <linux/mfd/arizona/core.h>
#include <linux/mfd/arizona/registers.h> #include <linux/mfd/arizona/registers.h>
...@@ -69,8 +70,6 @@ EXPORT_SYMBOL_GPL(arizona_clk32k_enable); ...@@ -69,8 +70,6 @@ EXPORT_SYMBOL_GPL(arizona_clk32k_enable);
int arizona_clk32k_disable(struct arizona *arizona) int arizona_clk32k_disable(struct arizona *arizona)
{ {
int ret = 0;
mutex_lock(&arizona->clk_lock); mutex_lock(&arizona->clk_lock);
BUG_ON(arizona->clk32k_ref <= 0); BUG_ON(arizona->clk32k_ref <= 0);
...@@ -90,7 +89,7 @@ int arizona_clk32k_disable(struct arizona *arizona) ...@@ -90,7 +89,7 @@ int arizona_clk32k_disable(struct arizona *arizona)
mutex_unlock(&arizona->clk_lock); mutex_unlock(&arizona->clk_lock);
return ret; return 0;
} }
EXPORT_SYMBOL_GPL(arizona_clk32k_disable); EXPORT_SYMBOL_GPL(arizona_clk32k_disable);
...@@ -462,6 +461,50 @@ static int wm5102_clear_write_sequencer(struct arizona *arizona) ...@@ -462,6 +461,50 @@ static int wm5102_clear_write_sequencer(struct arizona *arizona)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int arizona_isolate_dcvdd(struct arizona *arizona)
{
int ret;
ret = regmap_update_bits(arizona->regmap,
ARIZONA_ISOLATION_CONTROL,
ARIZONA_ISOLATE_DCVDD1,
ARIZONA_ISOLATE_DCVDD1);
if (ret != 0)
dev_err(arizona->dev, "Failed to isolate DCVDD: %d\n", ret);
return ret;
}
static int arizona_connect_dcvdd(struct arizona *arizona)
{
int ret;
ret = regmap_update_bits(arizona->regmap,
ARIZONA_ISOLATION_CONTROL,
ARIZONA_ISOLATE_DCVDD1, 0);
if (ret != 0)
dev_err(arizona->dev, "Failed to connect DCVDD: %d\n", ret);
return ret;
}
static int arizona_is_jack_det_active(struct arizona *arizona)
{
unsigned int val;
int ret;
ret = regmap_read(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, &val);
if (ret) {
dev_err(arizona->dev,
"Failed to check jack det status: %d\n", ret);
return ret;
} else if (val & ARIZONA_JD1_ENA) {
return 1;
} else {
return 0;
}
}
static int arizona_runtime_resume(struct device *dev) static int arizona_runtime_resume(struct device *dev)
{ {
struct arizona *arizona = dev_get_drvdata(dev); struct arizona *arizona = dev_get_drvdata(dev);
...@@ -501,14 +544,9 @@ static int arizona_runtime_resume(struct device *dev) ...@@ -501,14 +544,9 @@ static int arizona_runtime_resume(struct device *dev)
switch (arizona->type) { switch (arizona->type) {
case WM5102: case WM5102:
if (arizona->external_dcvdd) { if (arizona->external_dcvdd) {
ret = regmap_update_bits(arizona->regmap, ret = arizona_connect_dcvdd(arizona);
ARIZONA_ISOLATION_CONTROL, if (ret != 0)
ARIZONA_ISOLATE_DCVDD1, 0);
if (ret != 0) {
dev_err(arizona->dev,
"Failed to connect DCVDD: %d\n", ret);
goto err; goto err;
}
} }
ret = wm5102_patch(arizona); ret = wm5102_patch(arizona);
...@@ -533,14 +571,9 @@ static int arizona_runtime_resume(struct device *dev) ...@@ -533,14 +571,9 @@ static int arizona_runtime_resume(struct device *dev)
goto err; goto err;
if (arizona->external_dcvdd) { if (arizona->external_dcvdd) {
ret = regmap_update_bits(arizona->regmap, ret = arizona_connect_dcvdd(arizona);
ARIZONA_ISOLATION_CONTROL, if (ret != 0)
ARIZONA_ISOLATE_DCVDD1, 0);
if (ret) {
dev_err(arizona->dev,
"Failed to connect DCVDD: %d\n", ret);
goto err; goto err;
}
} else { } else {
/* /*
* As this is only called for the internal regulator * As this is only called for the internal regulator
...@@ -571,14 +604,9 @@ static int arizona_runtime_resume(struct device *dev) ...@@ -571,14 +604,9 @@ static int arizona_runtime_resume(struct device *dev)
goto err; goto err;
if (arizona->external_dcvdd) { if (arizona->external_dcvdd) {
ret = regmap_update_bits(arizona->regmap, ret = arizona_connect_dcvdd(arizona);
ARIZONA_ISOLATION_CONTROL, if (ret != 0)
ARIZONA_ISOLATE_DCVDD1, 0);
if (ret != 0) {
dev_err(arizona->dev,
"Failed to connect DCVDD: %d\n", ret);
goto err; goto err;
}
} }
break; break;
} }
...@@ -600,49 +628,50 @@ static int arizona_runtime_resume(struct device *dev) ...@@ -600,49 +628,50 @@ static int arizona_runtime_resume(struct device *dev)
static int arizona_runtime_suspend(struct device *dev) static int arizona_runtime_suspend(struct device *dev)
{ {
struct arizona *arizona = dev_get_drvdata(dev); struct arizona *arizona = dev_get_drvdata(dev);
unsigned int val; int jd_active = 0;
int ret; int ret;
dev_dbg(arizona->dev, "Entering AoD mode\n"); dev_dbg(arizona->dev, "Entering AoD mode\n");
ret = regmap_read(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, &val);
if (ret) {
dev_err(dev, "Failed to check jack det status: %d\n", ret);
return ret;
}
if (arizona->external_dcvdd) {
ret = regmap_update_bits(arizona->regmap,
ARIZONA_ISOLATION_CONTROL,
ARIZONA_ISOLATE_DCVDD1,
ARIZONA_ISOLATE_DCVDD1);
if (ret != 0) {
dev_err(arizona->dev, "Failed to isolate DCVDD: %d\n",
ret);
return ret;
}
}
switch (arizona->type) { switch (arizona->type) {
case WM5110: case WM5110:
case WM8280: case WM8280:
if (arizona->external_dcvdd) jd_active = arizona_is_jack_det_active(arizona);
break; if (jd_active < 0)
return jd_active;
/* if (arizona->external_dcvdd) {
* As this is only called for the internal regulator ret = arizona_isolate_dcvdd(arizona);
* (where we know voltage ranges available) it is ok if (ret != 0)
* to request an exact range. return ret;
*/ } else {
ret = regulator_set_voltage(arizona->dcvdd, 1175000, 1175000); /*
if (ret < 0) { * As this is only called for the internal regulator
dev_err(arizona->dev, * (where we know voltage ranges available) it is ok
"Failed to set suspend voltage: %d\n", ret); * to request an exact range.
return ret; */
ret = regulator_set_voltage(arizona->dcvdd,
1175000, 1175000);
if (ret < 0) {
dev_err(arizona->dev,
"Failed to set suspend voltage: %d\n",
ret);
return ret;
}
} }
break; break;
case WM5102: case WM5102:
if (!(val & ARIZONA_JD1_ENA)) { jd_active = arizona_is_jack_det_active(arizona);
if (jd_active < 0)
return jd_active;
if (arizona->external_dcvdd) {
ret = arizona_isolate_dcvdd(arizona);
if (ret != 0)
return ret;
}
if (!jd_active) {
ret = regmap_write(arizona->regmap, ret = regmap_write(arizona->regmap,
ARIZONA_WRITE_SEQUENCER_CTRL_3, 0x0); ARIZONA_WRITE_SEQUENCER_CTRL_3, 0x0);
if (ret) { if (ret) {
...@@ -654,6 +683,15 @@ static int arizona_runtime_suspend(struct device *dev) ...@@ -654,6 +683,15 @@ static int arizona_runtime_suspend(struct device *dev)
} }
break; break;
default: default:
jd_active = arizona_is_jack_det_active(arizona);
if (jd_active < 0)
return jd_active;
if (arizona->external_dcvdd) {
ret = arizona_isolate_dcvdd(arizona);
if (ret != 0)
return ret;
}
break; break;
} }
...@@ -662,7 +700,7 @@ static int arizona_runtime_suspend(struct device *dev) ...@@ -662,7 +700,7 @@ static int arizona_runtime_suspend(struct device *dev)
regulator_disable(arizona->dcvdd); regulator_disable(arizona->dcvdd);
/* Allow us to completely power down if no jack detection */ /* Allow us to completely power down if no jack detection */
if (!(val & ARIZONA_JD1_ENA)) { if (!jd_active) {
dev_dbg(arizona->dev, "Fully powering off\n"); dev_dbg(arizona->dev, "Fully powering off\n");
arizona->has_fully_powered_off = true; arizona->has_fully_powered_off = true;
...@@ -928,7 +966,8 @@ int arizona_dev_init(struct arizona *arizona) ...@@ -928,7 +966,8 @@ int arizona_dev_init(struct arizona *arizona)
const char *type_name; const char *type_name;
unsigned int reg, val, mask; unsigned int reg, val, mask;
int (*apply_patch)(struct arizona *) = NULL; int (*apply_patch)(struct arizona *) = NULL;
int ret, i; const struct mfd_cell *subdevs = NULL;
int n_subdevs, ret, i;
dev_set_drvdata(arizona->dev, arizona); dev_set_drvdata(arizona->dev, arizona);
mutex_init(&arizona->clk_lock); mutex_init(&arizona->clk_lock);
...@@ -1089,74 +1128,95 @@ int arizona_dev_init(struct arizona *arizona) ...@@ -1089,74 +1128,95 @@ int arizona_dev_init(struct arizona *arizona)
arizona->rev &= ARIZONA_DEVICE_REVISION_MASK; arizona->rev &= ARIZONA_DEVICE_REVISION_MASK;
switch (reg) { switch (reg) {
#ifdef CONFIG_MFD_WM5102
case 0x5102: case 0x5102:
type_name = "WM5102"; if (IS_ENABLED(CONFIG_MFD_WM5102)) {
if (arizona->type != WM5102) { type_name = "WM5102";
dev_err(arizona->dev, "WM5102 registered as %d\n", if (arizona->type != WM5102) {
arizona->type); dev_warn(arizona->dev,
arizona->type = WM5102; "WM5102 registered as %d\n",
arizona->type);
arizona->type = WM5102;
}
apply_patch = wm5102_patch;
arizona->rev &= 0x7;
subdevs = wm5102_devs;
n_subdevs = ARRAY_SIZE(wm5102_devs);
} }
apply_patch = wm5102_patch;
arizona->rev &= 0x7;
break; break;
#endif
#ifdef CONFIG_MFD_WM5110
case 0x5110: case 0x5110:
switch (arizona->type) { if (IS_ENABLED(CONFIG_MFD_WM5110)) {
case WM5110: switch (arizona->type) {
type_name = "WM5110"; case WM5110:
break; type_name = "WM5110";
case WM8280: break;
type_name = "WM8280"; case WM8280:
break; type_name = "WM8280";
default: break;
type_name = "WM5110"; default:
dev_err(arizona->dev, "WM5110 registered as %d\n", type_name = "WM5110";
arizona->type); dev_warn(arizona->dev,
arizona->type = WM5110; "WM5110 registered as %d\n",
break; arizona->type);
arizona->type = WM5110;
break;
}
apply_patch = wm5110_patch;
subdevs = wm5110_devs;
n_subdevs = ARRAY_SIZE(wm5110_devs);
} }
apply_patch = wm5110_patch;
break; break;
#endif
#ifdef CONFIG_MFD_WM8997
case 0x8997: case 0x8997:
type_name = "WM8997"; if (IS_ENABLED(CONFIG_MFD_WM8997)) {
if (arizona->type != WM8997) { type_name = "WM8997";
dev_err(arizona->dev, "WM8997 registered as %d\n", if (arizona->type != WM8997) {
arizona->type); dev_warn(arizona->dev,
arizona->type = WM8997; "WM8997 registered as %d\n",
arizona->type);
arizona->type = WM8997;
}
apply_patch = wm8997_patch;
subdevs = wm8997_devs;
n_subdevs = ARRAY_SIZE(wm8997_devs);
} }
apply_patch = wm8997_patch;
break; break;
#endif
#ifdef CONFIG_MFD_WM8998
case 0x6349: case 0x6349:
switch (arizona->type) { if (IS_ENABLED(CONFIG_MFD_WM8998)) {
case WM8998: switch (arizona->type) {
type_name = "WM8998"; case WM8998:
break; type_name = "WM8998";
break;
case WM1814:
type_name = "WM1814"; case WM1814:
break; type_name = "WM1814";
break;
default:
type_name = "WM8998";
dev_warn(arizona->dev,
"WM8998 registered as %d\n",
arizona->type);
arizona->type = WM8998;
}
default: apply_patch = wm8998_patch;
type_name = "WM8998"; subdevs = wm8998_devs;
dev_err(arizona->dev, "WM8998 registered as %d\n", n_subdevs = ARRAY_SIZE(wm8998_devs);
arizona->type);
arizona->type = WM8998;
} }
apply_patch = wm8998_patch;
break; break;
#endif
default: default:
dev_err(arizona->dev, "Unknown device ID %x\n", reg); dev_err(arizona->dev, "Unknown device ID %x\n", reg);
goto err_reset; goto err_reset;
} }
if (!subdevs) {
dev_err(arizona->dev,
"No kernel support for device ID %x\n", reg);
goto err_reset;
}
dev_info(dev, "%s revision %c\n", type_name, arizona->rev + 'A'); dev_info(dev, "%s revision %c\n", type_name, arizona->rev + 'A');
if (apply_patch) { if (apply_patch) {
...@@ -1342,28 +1402,10 @@ int arizona_dev_init(struct arizona *arizona) ...@@ -1342,28 +1402,10 @@ int arizona_dev_init(struct arizona *arizona)
arizona_request_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, "Underclocked", arizona_request_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, "Underclocked",
arizona_underclocked, arizona); arizona_underclocked, arizona);
switch (arizona->type) { ret = mfd_add_devices(arizona->dev, PLATFORM_DEVID_NONE,
case WM5102: subdevs, n_subdevs, NULL, 0, NULL);
ret = mfd_add_devices(arizona->dev, -1, wm5102_devs,
ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
break;
case WM5110:
case WM8280:
ret = mfd_add_devices(arizona->dev, -1, wm5110_devs,
ARRAY_SIZE(wm5110_devs), NULL, 0, NULL);
break;
case WM8997:
ret = mfd_add_devices(arizona->dev, -1, wm8997_devs,
ARRAY_SIZE(wm8997_devs), NULL, 0, NULL);
break;
case WM8998:
case WM1814:
ret = mfd_add_devices(arizona->dev, -1, wm8998_devs,
ARRAY_SIZE(wm8998_devs), NULL, 0, NULL);
break;
}
if (ret != 0) { if (ret) {
dev_err(arizona->dev, "Failed to add subdevices: %d\n", ret); dev_err(arizona->dev, "Failed to add subdevices: %d\n", ret);
goto err_irq; goto err_irq;
} }
......
...@@ -27,7 +27,7 @@ static int arizona_i2c_probe(struct i2c_client *i2c, ...@@ -27,7 +27,7 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct arizona *arizona; struct arizona *arizona;
const struct regmap_config *regmap_config; const struct regmap_config *regmap_config = NULL;
unsigned long type; unsigned long type;
int ret; int ret;
...@@ -37,31 +37,32 @@ static int arizona_i2c_probe(struct i2c_client *i2c, ...@@ -37,31 +37,32 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
type = id->driver_data; type = id->driver_data;
switch (type) { switch (type) {
#ifdef CONFIG_MFD_WM5102
case WM5102: case WM5102:
regmap_config = &wm5102_i2c_regmap; if (IS_ENABLED(CONFIG_MFD_WM5102))
regmap_config = &wm5102_i2c_regmap;
break; break;
#endif
#ifdef CONFIG_MFD_WM5110
case WM5110: case WM5110:
case WM8280: case WM8280:
regmap_config = &wm5110_i2c_regmap; if (IS_ENABLED(CONFIG_MFD_WM5110))
regmap_config = &wm5110_i2c_regmap;
break; break;
#endif
#ifdef CONFIG_MFD_WM8997
case WM8997: case WM8997:
regmap_config = &wm8997_i2c_regmap; if (IS_ENABLED(CONFIG_MFD_WM8997))
regmap_config = &wm8997_i2c_regmap;
break; break;
#endif
#ifdef CONFIG_MFD_WM8998
case WM8998: case WM8998:
case WM1814: case WM1814:
regmap_config = &wm8998_i2c_regmap; if (IS_ENABLED(CONFIG_MFD_WM8998))
regmap_config = &wm8998_i2c_regmap;
break; break;
#endif
default: default:
dev_err(&i2c->dev, "Unknown device type %ld\n", dev_err(&i2c->dev, "Unknown device type %ld\n", type);
id->driver_data); return -EINVAL;
}
if (!regmap_config) {
dev_err(&i2c->dev,
"No kernel support for device type %ld\n", type);
return -EINVAL; return -EINVAL;
} }
...@@ -77,7 +78,7 @@ static int arizona_i2c_probe(struct i2c_client *i2c, ...@@ -77,7 +78,7 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
return ret; return ret;
} }
arizona->type = id->driver_data; arizona->type = type;
arizona->dev = &i2c->dev; arizona->dev = &i2c->dev;
arizona->irq = i2c->irq; arizona->irq = i2c->irq;
......
...@@ -169,7 +169,7 @@ static struct irq_chip arizona_irq_chip = { ...@@ -169,7 +169,7 @@ static struct irq_chip arizona_irq_chip = {
static int arizona_irq_map(struct irq_domain *h, unsigned int virq, static int arizona_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw) irq_hw_number_t hw)
{ {
struct regmap_irq_chip_data *data = h->host_data; struct arizona *data = h->host_data;
irq_set_chip_data(virq, data); irq_set_chip_data(virq, data);
irq_set_chip_and_handler(virq, &arizona_irq_chip, handle_simple_irq); irq_set_chip_and_handler(virq, &arizona_irq_chip, handle_simple_irq);
......
...@@ -27,7 +27,7 @@ static int arizona_spi_probe(struct spi_device *spi) ...@@ -27,7 +27,7 @@ static int arizona_spi_probe(struct spi_device *spi)
{ {
const struct spi_device_id *id = spi_get_device_id(spi); const struct spi_device_id *id = spi_get_device_id(spi);
struct arizona *arizona; struct arizona *arizona;
const struct regmap_config *regmap_config; const struct regmap_config *regmap_config = NULL;
unsigned long type; unsigned long type;
int ret; int ret;
...@@ -37,20 +37,23 @@ static int arizona_spi_probe(struct spi_device *spi) ...@@ -37,20 +37,23 @@ static int arizona_spi_probe(struct spi_device *spi)
type = id->driver_data; type = id->driver_data;
switch (type) { switch (type) {
#ifdef CONFIG_MFD_WM5102
case WM5102: case WM5102:
regmap_config = &wm5102_spi_regmap; if (IS_ENABLED(CONFIG_MFD_WM5102))
regmap_config = &wm5102_spi_regmap;
break; break;
#endif
#ifdef CONFIG_MFD_WM5110
case WM5110: case WM5110:
case WM8280: case WM8280:
regmap_config = &wm5110_spi_regmap; if (IS_ENABLED(CONFIG_MFD_WM5110))
regmap_config = &wm5110_spi_regmap;
break; break;
#endif
default: default:
dev_err(&spi->dev, "Unknown device type %ld\n", dev_err(&spi->dev, "Unknown device type %ld\n", type);
id->driver_data); return -EINVAL;
}
if (!regmap_config) {
dev_err(&spi->dev,
"No kernel support for device type %ld\n", type);
return -EINVAL; return -EINVAL;
} }
...@@ -66,7 +69,7 @@ static int arizona_spi_probe(struct spi_device *spi) ...@@ -66,7 +69,7 @@ static int arizona_spi_probe(struct spi_device *spi)
return ret; return ret;
} }
arizona->type = id->driver_data; arizona->type = type;
arizona->dev = &spi->dev; arizona->dev = &spi->dev;
arizona->irq = spi->irq; arizona->irq = spi->irq;
......
/*
* Driver for Atmel Flexcom
*
* Copyright (C) 2015 Atmel Corporation
*
* Author: Cyrille Pitchen <cyrille.pitchen@atmel.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <dt-bindings/mfd/atmel-flexcom.h>
/* I/O register offsets */
#define FLEX_MR 0x0 /* Mode Register */
#define FLEX_VERSION 0xfc /* Version Register */
/* Mode Register bit fields */
#define FLEX_MR_OPMODE_OFFSET (0) /* Operating Mode */
#define FLEX_MR_OPMODE_MASK (0x3 << FLEX_MR_OPMODE_OFFSET)
#define FLEX_MR_OPMODE(opmode) (((opmode) << FLEX_MR_OPMODE_OFFSET) & \
FLEX_MR_OPMODE_MASK)
static int atmel_flexcom_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct clk *clk;
struct resource *res;
void __iomem *base;
u32 opmode;
int err;
err = of_property_read_u32(np, "atmel,flexcom-mode", &opmode);
if (err)
return err;
if (opmode < ATMEL_FLEXCOM_MODE_USART ||
opmode > ATMEL_FLEXCOM_MODE_TWI)
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk))
return PTR_ERR(clk);
err = clk_prepare_enable(clk);
if (err)
return err;
/*
* Set the Operating Mode in the Mode Register: only the selected device
* is clocked. Hence, registers of the other serial devices remain
* inaccessible and are read as zero. Also the external I/O lines of the
* Flexcom are muxed to reach the selected device.
*/
writel(FLEX_MR_OPMODE(opmode), base + FLEX_MR);
clk_disable_unprepare(clk);
return of_platform_populate(np, NULL, NULL, &pdev->dev);
}
static const struct of_device_id atmel_flexcom_of_match[] = {
{ .compatible = "atmel,sama5d2-flexcom" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, atmel_flexcom_of_match);
static struct platform_driver atmel_flexcom_driver = {
.probe = atmel_flexcom_probe,
.driver = {
.name = "atmel_flexcom",
.of_match_table = atmel_flexcom_of_match,
},
};
module_platform_driver(atmel_flexcom_driver);
MODULE_AUTHOR("Cyrille Pitchen <cyrille.pitchen@atmel.com>");
MODULE_DESCRIPTION("Atmel Flexcom MFD driver");
MODULE_LICENSE("GPL v2");
...@@ -148,6 +148,7 @@ static const struct of_device_id atmel_hlcdc_match[] = { ...@@ -148,6 +148,7 @@ static const struct of_device_id atmel_hlcdc_match[] = {
{ .compatible = "atmel,sama5d4-hlcdc" }, { .compatible = "atmel,sama5d4-hlcdc" },
{ /* sentinel */ }, { /* sentinel */ },
}; };
MODULE_DEVICE_TABLE(of, atmel_hlcdc_match);
static struct platform_driver atmel_hlcdc_driver = { static struct platform_driver atmel_hlcdc_driver = {
.probe = atmel_hlcdc_probe, .probe = atmel_hlcdc_probe,
......
...@@ -161,6 +161,21 @@ static struct resource axp22x_pek_resources[] = { ...@@ -161,6 +161,21 @@ static struct resource axp22x_pek_resources[] = {
}, },
}; };
static struct resource axp288_power_button_resources[] = {
{
.name = "PEK_DBR",
.start = AXP288_IRQ_POKN,
.end = AXP288_IRQ_POKN,
.flags = IORESOURCE_IRQ,
},
{
.name = "PEK_DBF",
.start = AXP288_IRQ_POKP,
.end = AXP288_IRQ_POKP,
.flags = IORESOURCE_IRQ,
},
};
static struct resource axp288_fuel_gauge_resources[] = { static struct resource axp288_fuel_gauge_resources[] = {
{ {
.start = AXP288_IRQ_QWBTU, .start = AXP288_IRQ_QWBTU,
...@@ -571,6 +586,11 @@ static struct mfd_cell axp288_cells[] = { ...@@ -571,6 +586,11 @@ static struct mfd_cell axp288_cells[] = {
.num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources), .num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources),
.resources = axp288_fuel_gauge_resources, .resources = axp288_fuel_gauge_resources,
}, },
{
.name = "axp20x-pek",
.num_resources = ARRAY_SIZE(axp288_power_button_resources),
.resources = axp288_power_button_resources,
},
{ {
.name = "axp288_pmic_acpi", .name = "axp288_pmic_acpi",
}, },
......
...@@ -128,4 +128,3 @@ module_i2c_driver(bcm590xx_i2c_driver); ...@@ -128,4 +128,3 @@ module_i2c_driver(bcm590xx_i2c_driver);
MODULE_AUTHOR("Matt Porter <mporter@linaro.org>"); MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
MODULE_DESCRIPTION("BCM590xx multi-function driver"); MODULE_DESCRIPTION("BCM590xx multi-function driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("i2c:bcm590xx");
...@@ -344,6 +344,12 @@ static int cros_ec_i2c_resume(struct device *dev) ...@@ -344,6 +344,12 @@ static int cros_ec_i2c_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(cros_ec_i2c_pm_ops, cros_ec_i2c_suspend, static SIMPLE_DEV_PM_OPS(cros_ec_i2c_pm_ops, cros_ec_i2c_suspend,
cros_ec_i2c_resume); cros_ec_i2c_resume);
static const struct of_device_id cros_ec_i2c_of_match[] = {
{ .compatible = "google,cros-ec-i2c", },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, cros_ec_i2c_of_match);
static const struct i2c_device_id cros_ec_i2c_id[] = { static const struct i2c_device_id cros_ec_i2c_id[] = {
{ "cros-ec-i2c", 0 }, { "cros-ec-i2c", 0 },
{ } { }
...@@ -353,6 +359,7 @@ MODULE_DEVICE_TABLE(i2c, cros_ec_i2c_id); ...@@ -353,6 +359,7 @@ MODULE_DEVICE_TABLE(i2c, cros_ec_i2c_id);
static struct i2c_driver cros_ec_driver = { static struct i2c_driver cros_ec_driver = {
.driver = { .driver = {
.name = "cros-ec-i2c", .name = "cros-ec-i2c",
.of_match_table = of_match_ptr(cros_ec_i2c_of_match),
.pm = &cros_ec_i2c_pm_ops, .pm = &cros_ec_i2c_pm_ops,
}, },
.probe = cros_ec_i2c_probe, .probe = cros_ec_i2c_probe,
......
...@@ -532,11 +532,7 @@ static int da903x_probe(struct i2c_client *client, ...@@ -532,11 +532,7 @@ static int da903x_probe(struct i2c_client *client,
return ret; return ret;
} }
ret = da903x_add_subdevs(chip, pdata); return da903x_add_subdevs(chip, pdata);
if (ret)
return ret;
return 0;
} }
static int da903x_remove(struct i2c_client *client) static int da903x_remove(struct i2c_client *client)
......
...@@ -51,6 +51,9 @@ static bool da9052_reg_readable(struct device *dev, unsigned int reg) ...@@ -51,6 +51,9 @@ static bool da9052_reg_readable(struct device *dev, unsigned int reg)
case DA9052_GPIO_2_3_REG: case DA9052_GPIO_2_3_REG:
case DA9052_GPIO_4_5_REG: case DA9052_GPIO_4_5_REG:
case DA9052_GPIO_6_7_REG: case DA9052_GPIO_6_7_REG:
case DA9052_GPIO_8_9_REG:
case DA9052_GPIO_10_11_REG:
case DA9052_GPIO_12_13_REG:
case DA9052_GPIO_14_15_REG: case DA9052_GPIO_14_15_REG:
case DA9052_ID_0_1_REG: case DA9052_ID_0_1_REG:
case DA9052_ID_2_3_REG: case DA9052_ID_2_3_REG:
...@@ -178,6 +181,9 @@ static bool da9052_reg_writeable(struct device *dev, unsigned int reg) ...@@ -178,6 +181,9 @@ static bool da9052_reg_writeable(struct device *dev, unsigned int reg)
case DA9052_GPIO_2_3_REG: case DA9052_GPIO_2_3_REG:
case DA9052_GPIO_4_5_REG: case DA9052_GPIO_4_5_REG:
case DA9052_GPIO_6_7_REG: case DA9052_GPIO_6_7_REG:
case DA9052_GPIO_8_9_REG:
case DA9052_GPIO_10_11_REG:
case DA9052_GPIO_12_13_REG:
case DA9052_GPIO_14_15_REG: case DA9052_GPIO_14_15_REG:
case DA9052_ID_0_1_REG: case DA9052_ID_0_1_REG:
case DA9052_ID_2_3_REG: case DA9052_ID_2_3_REG:
......
...@@ -174,11 +174,7 @@ static int da9052_i2c_probe(struct i2c_client *client, ...@@ -174,11 +174,7 @@ static int da9052_i2c_probe(struct i2c_client *client,
return ret; return ret;
} }
ret = da9052_device_init(da9052, id->driver_data); return da9052_device_init(da9052, id->driver_data);
if (ret != 0)
return ret;
return 0;
} }
static int da9052_i2c_remove(struct i2c_client *client) static int da9052_i2c_remove(struct i2c_client *client)
......
...@@ -56,11 +56,7 @@ static int da9052_spi_probe(struct spi_device *spi) ...@@ -56,11 +56,7 @@ static int da9052_spi_probe(struct spi_device *spi)
return ret; return ret;
} }
ret = da9052_device_init(da9052, id->driver_data); return da9052_device_init(da9052, id->driver_data);
if (ret != 0)
return ret;
return 0;
} }
static int da9052_spi_remove(struct spi_device *spi) static int da9052_spi_remove(struct spi_device *spi)
......
...@@ -198,7 +198,7 @@ static int da9062_clear_fault_log(struct da9062 *chip) ...@@ -198,7 +198,7 @@ static int da9062_clear_fault_log(struct da9062 *chip)
return ret; return ret;
} }
int get_device_type(struct da9062 *chip) static int da9062_get_device_type(struct da9062 *chip)
{ {
int device_id, variant_id, variant_mrc; int device_id, variant_id, variant_mrc;
int ret; int ret;
...@@ -466,7 +466,7 @@ static int da9062_i2c_probe(struct i2c_client *i2c, ...@@ -466,7 +466,7 @@ static int da9062_i2c_probe(struct i2c_client *i2c,
if (ret < 0) if (ret < 0)
dev_warn(chip->dev, "Cannot clear fault log\n"); dev_warn(chip->dev, "Cannot clear fault log\n");
ret = get_device_type(chip); ret = da9062_get_device_type(chip);
if (ret) if (ret)
return ret; return ret;
......
...@@ -23,6 +23,77 @@ ...@@ -23,6 +23,77 @@
#include <linux/mfd/da9150/core.h> #include <linux/mfd/da9150/core.h>
#include <linux/mfd/da9150/registers.h> #include <linux/mfd/da9150/registers.h>
/* Raw device access, used for QIF */
static int da9150_i2c_read_device(struct i2c_client *client, u8 addr, int count,
u8 *buf)
{
struct i2c_msg xfer;
int ret;
/*
* Read is split into two transfers as device expects STOP/START rather
* than repeated start to carry out this kind of access.
*/
/* Write address */
xfer.addr = client->addr;
xfer.flags = 0;
xfer.len = 1;
xfer.buf = &addr;
ret = i2c_transfer(client->adapter, &xfer, 1);
if (ret != 1) {
if (ret < 0)
return ret;
else
return -EIO;
}
/* Read data */
xfer.addr = client->addr;
xfer.flags = I2C_M_RD;
xfer.len = count;
xfer.buf = buf;
ret = i2c_transfer(client->adapter, &xfer, 1);
if (ret == 1)
return 0;
else if (ret < 0)
return ret;
else
return -EIO;
}
static int da9150_i2c_write_device(struct i2c_client *client, u8 addr,
int count, const u8 *buf)
{
struct i2c_msg xfer;
u8 *reg_data;
int ret;
reg_data = kzalloc(1 + count, GFP_KERNEL);
if (!reg_data)
return -ENOMEM;
reg_data[0] = addr;
memcpy(&reg_data[1], buf, count);
/* Write address & data */
xfer.addr = client->addr;
xfer.flags = 0;
xfer.len = 1 + count;
xfer.buf = reg_data;
ret = i2c_transfer(client->adapter, &xfer, 1);
kfree(reg_data);
if (ret == 1)
return 0;
else if (ret < 0)
return ret;
else
return -EIO;
}
static bool da9150_volatile_reg(struct device *dev, unsigned int reg) static bool da9150_volatile_reg(struct device *dev, unsigned int reg)
{ {
switch (reg) { switch (reg) {
...@@ -107,6 +178,28 @@ static const struct regmap_config da9150_regmap_config = { ...@@ -107,6 +178,28 @@ static const struct regmap_config da9150_regmap_config = {
.volatile_reg = da9150_volatile_reg, .volatile_reg = da9150_volatile_reg,
}; };
void da9150_read_qif(struct da9150 *da9150, u8 addr, int count, u8 *buf)
{
int ret;
ret = da9150_i2c_read_device(da9150->core_qif, addr, count, buf);
if (ret < 0)
dev_err(da9150->dev, "Failed to read from QIF 0x%x: %d\n",
addr, ret);
}
EXPORT_SYMBOL_GPL(da9150_read_qif);
void da9150_write_qif(struct da9150 *da9150, u8 addr, int count, const u8 *buf)
{
int ret;
ret = da9150_i2c_write_device(da9150->core_qif, addr, count, buf);
if (ret < 0)
dev_err(da9150->dev, "Failed to write to QIF 0x%x: %d\n",
addr, ret);
}
EXPORT_SYMBOL_GPL(da9150_write_qif);
u8 da9150_reg_read(struct da9150 *da9150, u16 reg) u8 da9150_reg_read(struct da9150 *da9150, u16 reg)
{ {
int val, ret; int val, ret;
...@@ -262,54 +355,45 @@ static const struct regmap_irq_chip da9150_regmap_irq_chip = { ...@@ -262,54 +355,45 @@ static const struct regmap_irq_chip da9150_regmap_irq_chip = {
}; };
static struct resource da9150_gpadc_resources[] = { static struct resource da9150_gpadc_resources[] = {
{ DEFINE_RES_IRQ_NAMED(DA9150_IRQ_GPADC, "GPADC"),
.name = "GPADC",
.start = DA9150_IRQ_GPADC,
.end = DA9150_IRQ_GPADC,
.flags = IORESOURCE_IRQ,
},
}; };
static struct resource da9150_charger_resources[] = { static struct resource da9150_charger_resources[] = {
{ DEFINE_RES_IRQ_NAMED(DA9150_IRQ_CHG, "CHG_STATUS"),
.name = "CHG_STATUS", DEFINE_RES_IRQ_NAMED(DA9150_IRQ_TJUNC, "CHG_TJUNC"),
.start = DA9150_IRQ_CHG, DEFINE_RES_IRQ_NAMED(DA9150_IRQ_VFAULT, "CHG_VFAULT"),
.end = DA9150_IRQ_CHG, DEFINE_RES_IRQ_NAMED(DA9150_IRQ_VBUS, "CHG_VBUS"),
.flags = IORESOURCE_IRQ, };
},
{ static struct resource da9150_fg_resources[] = {
.name = "CHG_TJUNC", DEFINE_RES_IRQ_NAMED(DA9150_IRQ_FG, "FG"),
.start = DA9150_IRQ_TJUNC, };
.end = DA9150_IRQ_TJUNC,
.flags = IORESOURCE_IRQ, enum da9150_dev_idx {
}, DA9150_GPADC_IDX = 0,
{ DA9150_CHARGER_IDX,
.name = "CHG_VFAULT", DA9150_FG_IDX,
.start = DA9150_IRQ_VFAULT,
.end = DA9150_IRQ_VFAULT,
.flags = IORESOURCE_IRQ,
},
{
.name = "CHG_VBUS",
.start = DA9150_IRQ_VBUS,
.end = DA9150_IRQ_VBUS,
.flags = IORESOURCE_IRQ,
},
}; };
static struct mfd_cell da9150_devs[] = { static struct mfd_cell da9150_devs[] = {
{ [DA9150_GPADC_IDX] = {
.name = "da9150-gpadc", .name = "da9150-gpadc",
.of_compatible = "dlg,da9150-gpadc", .of_compatible = "dlg,da9150-gpadc",
.resources = da9150_gpadc_resources, .resources = da9150_gpadc_resources,
.num_resources = ARRAY_SIZE(da9150_gpadc_resources), .num_resources = ARRAY_SIZE(da9150_gpadc_resources),
}, },
{ [DA9150_CHARGER_IDX] = {
.name = "da9150-charger", .name = "da9150-charger",
.of_compatible = "dlg,da9150-charger", .of_compatible = "dlg,da9150-charger",
.resources = da9150_charger_resources, .resources = da9150_charger_resources,
.num_resources = ARRAY_SIZE(da9150_charger_resources), .num_resources = ARRAY_SIZE(da9150_charger_resources),
}, },
[DA9150_FG_IDX] = {
.name = "da9150-fuel-gauge",
.of_compatible = "dlg,da9150-fuel-gauge",
.resources = da9150_fg_resources,
.num_resources = ARRAY_SIZE(da9150_fg_resources),
},
}; };
static int da9150_probe(struct i2c_client *client, static int da9150_probe(struct i2c_client *client,
...@@ -317,6 +401,7 @@ static int da9150_probe(struct i2c_client *client, ...@@ -317,6 +401,7 @@ static int da9150_probe(struct i2c_client *client,
{ {
struct da9150 *da9150; struct da9150 *da9150;
struct da9150_pdata *pdata = dev_get_platdata(&client->dev); struct da9150_pdata *pdata = dev_get_platdata(&client->dev);
int qif_addr;
int ret; int ret;
da9150 = devm_kzalloc(&client->dev, sizeof(*da9150), GFP_KERNEL); da9150 = devm_kzalloc(&client->dev, sizeof(*da9150), GFP_KERNEL);
...@@ -335,16 +420,41 @@ static int da9150_probe(struct i2c_client *client, ...@@ -335,16 +420,41 @@ static int da9150_probe(struct i2c_client *client,
return ret; return ret;
} }
da9150->irq_base = pdata ? pdata->irq_base : -1; /* Setup secondary I2C interface for QIF access */
qif_addr = da9150_reg_read(da9150, DA9150_CORE2WIRE_CTRL_A);
qif_addr = (qif_addr & DA9150_CORE_BASE_ADDR_MASK) >> 1;
qif_addr |= DA9150_QIF_I2C_ADDR_LSB;
da9150->core_qif = i2c_new_dummy(client->adapter, qif_addr);
if (!da9150->core_qif) {
dev_err(da9150->dev, "Failed to attach QIF client\n");
return -ENODEV;
}
i2c_set_clientdata(da9150->core_qif, da9150);
if (pdata) {
da9150->irq_base = pdata->irq_base;
da9150_devs[DA9150_FG_IDX].platform_data = pdata->fg_pdata;
da9150_devs[DA9150_FG_IDX].pdata_size =
sizeof(struct da9150_fg_pdata);
} else {
da9150->irq_base = -1;
}
ret = regmap_add_irq_chip(da9150->regmap, da9150->irq, ret = regmap_add_irq_chip(da9150->regmap, da9150->irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
da9150->irq_base, &da9150_regmap_irq_chip, da9150->irq_base, &da9150_regmap_irq_chip,
&da9150->regmap_irq_data); &da9150->regmap_irq_data);
if (ret) if (ret) {
return ret; dev_err(da9150->dev, "Failed to add regmap irq chip: %d\n",
ret);
goto regmap_irq_fail;
}
da9150->irq_base = regmap_irq_chip_get_base(da9150->regmap_irq_data); da9150->irq_base = regmap_irq_chip_get_base(da9150->regmap_irq_data);
enable_irq_wake(da9150->irq); enable_irq_wake(da9150->irq);
ret = mfd_add_devices(da9150->dev, -1, da9150_devs, ret = mfd_add_devices(da9150->dev, -1, da9150_devs,
...@@ -352,11 +462,17 @@ static int da9150_probe(struct i2c_client *client, ...@@ -352,11 +462,17 @@ static int da9150_probe(struct i2c_client *client,
da9150->irq_base, NULL); da9150->irq_base, NULL);
if (ret) { if (ret) {
dev_err(da9150->dev, "Failed to add child devices: %d\n", ret); dev_err(da9150->dev, "Failed to add child devices: %d\n", ret);
regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data); goto mfd_fail;
return ret;
} }
return 0; return 0;
mfd_fail:
regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
regmap_irq_fail:
i2c_unregister_device(da9150->core_qif);
return ret;
} }
static int da9150_remove(struct i2c_client *client) static int da9150_remove(struct i2c_client *client)
...@@ -365,6 +481,7 @@ static int da9150_remove(struct i2c_client *client) ...@@ -365,6 +481,7 @@ static int da9150_remove(struct i2c_client *client)
regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data); regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
mfd_remove_devices(da9150->dev); mfd_remove_devices(da9150->dev);
i2c_unregister_device(da9150->core_qif);
return 0; return 0;
} }
......
...@@ -97,6 +97,7 @@ static const struct of_device_id of_hi6421_pmic_match_tbl[] = { ...@@ -97,6 +97,7 @@ static const struct of_device_id of_hi6421_pmic_match_tbl[] = {
{ .compatible = "hisilicon,hi6421-pmic", }, { .compatible = "hisilicon,hi6421-pmic", },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, of_hi6421_pmic_match_tbl);
static struct platform_driver hi6421_pmic_driver = { static struct platform_driver hi6421_pmic_driver = {
.driver = { .driver = {
......
...@@ -318,7 +318,6 @@ static int htcpld_setup_chip_irq( ...@@ -318,7 +318,6 @@ static int htcpld_setup_chip_irq(
struct htcpld_data *htcpld; struct htcpld_data *htcpld;
struct htcpld_chip *chip; struct htcpld_chip *chip;
unsigned int irq, irq_end; unsigned int irq, irq_end;
int ret = 0;
/* Get the platform and driver data */ /* Get the platform and driver data */
htcpld = platform_get_drvdata(pdev); htcpld = platform_get_drvdata(pdev);
...@@ -333,7 +332,7 @@ static int htcpld_setup_chip_irq( ...@@ -333,7 +332,7 @@ static int htcpld_setup_chip_irq(
irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
} }
return ret; return 0;
} }
static int htcpld_register_chip_i2c( static int htcpld_register_chip_i2c(
......
...@@ -25,10 +25,26 @@ static const struct intel_lpss_platform_info spt_info = { ...@@ -25,10 +25,26 @@ static const struct intel_lpss_platform_info spt_info = {
.clk_rate = 120000000, .clk_rate = 120000000,
}; };
static const struct intel_lpss_platform_info bxt_info = {
.clk_rate = 100000000,
};
static const struct intel_lpss_platform_info bxt_i2c_info = {
.clk_rate = 133000000,
};
static const struct acpi_device_id intel_lpss_acpi_ids[] = { static const struct acpi_device_id intel_lpss_acpi_ids[] = {
/* SPT */ /* SPT */
{ "INT3446", (kernel_ulong_t)&spt_info }, { "INT3446", (kernel_ulong_t)&spt_info },
{ "INT3447", (kernel_ulong_t)&spt_info }, { "INT3447", (kernel_ulong_t)&spt_info },
/* BXT */
{ "80860AAC", (kernel_ulong_t)&bxt_i2c_info },
{ "80860ABC", (kernel_ulong_t)&bxt_info },
{ "80860AC2", (kernel_ulong_t)&bxt_info },
/* APL */
{ "80865AAC", (kernel_ulong_t)&bxt_i2c_info },
{ "80865ABC", (kernel_ulong_t)&bxt_info },
{ "80865AC2", (kernel_ulong_t)&bxt_info },
{ } { }
}; };
MODULE_DEVICE_TABLE(acpi, intel_lpss_acpi_ids); MODULE_DEVICE_TABLE(acpi, intel_lpss_acpi_ids);
......
...@@ -70,7 +70,52 @@ static const struct intel_lpss_platform_info spt_uart_info = { ...@@ -70,7 +70,52 @@ static const struct intel_lpss_platform_info spt_uart_info = {
.clk_con_id = "baudclk", .clk_con_id = "baudclk",
}; };
static const struct intel_lpss_platform_info bxt_info = {
.clk_rate = 100000000,
};
static const struct intel_lpss_platform_info bxt_uart_info = {
.clk_rate = 100000000,
.clk_con_id = "baudclk",
};
static const struct intel_lpss_platform_info bxt_i2c_info = {
.clk_rate = 133000000,
};
static const struct pci_device_id intel_lpss_pci_ids[] = { static const struct pci_device_id intel_lpss_pci_ids[] = {
/* BXT */
{ PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x0aae), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x0ab0), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x0ab2), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x0ab4), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x0ab6), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x0ab8), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x0aba), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x0abc), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x0abe), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x0ac0), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x0ac2), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x0ac4), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x0ac6), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x0aee), (kernel_ulong_t)&bxt_uart_info },
/* APL */
{ PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x5ab0), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x5ab2), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x5ab4), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x5ab6), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x5ab8), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x5aba), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x5abc), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x5abe), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x5ac0), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x5ac2), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x5ac4), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x5ac6), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x5aee), (kernel_ulong_t)&bxt_uart_info },
/* SPT-LP */ /* SPT-LP */
{ PCI_VDEVICE(INTEL, 0x9d27), (kernel_ulong_t)&spt_uart_info }, { PCI_VDEVICE(INTEL, 0x9d27), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x9d28), (kernel_ulong_t)&spt_uart_info }, { PCI_VDEVICE(INTEL, 0x9d28), (kernel_ulong_t)&spt_uart_info },
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <asm-generic/io-64-nonatomic-lo-hi.h>
#include "intel-lpss.h" #include "intel-lpss.h"
#define LPSS_DEV_OFFSET 0x000 #define LPSS_DEV_OFFSET 0x000
...@@ -52,8 +54,7 @@ ...@@ -52,8 +54,7 @@
#define LPSS_PRIV_SSP_REG 0x20 #define LPSS_PRIV_SSP_REG 0x20
#define LPSS_PRIV_SSP_REG_DIS_DMA_FIN BIT(0) #define LPSS_PRIV_SSP_REG_DIS_DMA_FIN BIT(0)
#define LPSS_PRIV_REMAP_ADDR_LO 0x40 #define LPSS_PRIV_REMAP_ADDR 0x40
#define LPSS_PRIV_REMAP_ADDR_HI 0x44
#define LPSS_PRIV_CAPS 0xfc #define LPSS_PRIV_CAPS 0xfc
#define LPSS_PRIV_CAPS_NO_IDMA BIT(8) #define LPSS_PRIV_CAPS_NO_IDMA BIT(8)
...@@ -250,12 +251,7 @@ static void intel_lpss_set_remap_addr(const struct intel_lpss *lpss) ...@@ -250,12 +251,7 @@ static void intel_lpss_set_remap_addr(const struct intel_lpss *lpss)
{ {
resource_size_t addr = lpss->info->mem->start; resource_size_t addr = lpss->info->mem->start;
writel(addr, lpss->priv + LPSS_PRIV_REMAP_ADDR_LO); lo_hi_writeq(addr, lpss->priv + LPSS_PRIV_REMAP_ADDR);
#if BITS_PER_LONG > 32
writel(addr >> 32, lpss->priv + LPSS_PRIV_REMAP_ADDR_HI);
#else
writel(0, lpss->priv + LPSS_PRIV_REMAP_ADDR_HI);
#endif
} }
static void intel_lpss_deassert_reset(const struct intel_lpss *lpss) static void intel_lpss_deassert_reset(const struct intel_lpss *lpss)
......
...@@ -31,6 +31,10 @@ ...@@ -31,6 +31,10 @@
#define MFD_I2C_BAR 0 #define MFD_I2C_BAR 0
#define MFD_GPIO_BAR 1 #define MFD_GPIO_BAR 1
/* ACPI _ADR value to match the child node */
#define MFD_ACPI_MATCH_GPIO 0ULL
#define MFD_ACPI_MATCH_I2C 1ULL
/* The base GPIO number under GPIOLIB framework */ /* The base GPIO number under GPIOLIB framework */
#define INTEL_QUARK_MFD_GPIO_BASE 8 #define INTEL_QUARK_MFD_GPIO_BASE 8
...@@ -82,27 +86,37 @@ static struct resource intel_quark_i2c_res[] = { ...@@ -82,27 +86,37 @@ static struct resource intel_quark_i2c_res[] = {
}, },
}; };
static struct mfd_cell_acpi_match intel_quark_acpi_match_i2c = {
.adr = MFD_ACPI_MATCH_I2C,
};
static struct resource intel_quark_gpio_res[] = { static struct resource intel_quark_gpio_res[] = {
[INTEL_QUARK_IORES_MEM] = { [INTEL_QUARK_IORES_MEM] = {
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
}; };
static struct mfd_cell_acpi_match intel_quark_acpi_match_gpio = {
.adr = MFD_ACPI_MATCH_GPIO,
};
static struct mfd_cell intel_quark_mfd_cells[] = { static struct mfd_cell intel_quark_mfd_cells[] = {
{
.id = MFD_I2C_BAR,
.name = "i2c_designware",
.num_resources = ARRAY_SIZE(intel_quark_i2c_res),
.resources = intel_quark_i2c_res,
.ignore_resource_conflicts = true,
},
{ {
.id = MFD_GPIO_BAR, .id = MFD_GPIO_BAR,
.name = "gpio-dwapb", .name = "gpio-dwapb",
.acpi_match = &intel_quark_acpi_match_gpio,
.num_resources = ARRAY_SIZE(intel_quark_gpio_res), .num_resources = ARRAY_SIZE(intel_quark_gpio_res),
.resources = intel_quark_gpio_res, .resources = intel_quark_gpio_res,
.ignore_resource_conflicts = true, .ignore_resource_conflicts = true,
}, },
{
.id = MFD_I2C_BAR,
.name = "i2c_designware",
.acpi_match = &intel_quark_acpi_match_i2c,
.num_resources = ARRAY_SIZE(intel_quark_i2c_res),
.resources = intel_quark_i2c_res,
.ignore_resource_conflicts = true,
},
}; };
static const struct pci_device_id intel_quark_mfd_ids[] = { static const struct pci_device_id intel_quark_mfd_ids[] = {
...@@ -248,12 +262,11 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev, ...@@ -248,12 +262,11 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev,
dev_set_drvdata(&pdev->dev, quark_mfd); dev_set_drvdata(&pdev->dev, quark_mfd);
ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[MFD_I2C_BAR]); ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[1]);
if (ret) if (ret)
return ret; return ret;
ret = intel_quark_gpio_setup(pdev, ret = intel_quark_gpio_setup(pdev, &intel_quark_mfd_cells[0]);
&intel_quark_mfd_cells[MFD_GPIO_BAR]);
if (ret) if (ret)
return ret; return ret;
......
/*
* MFD core driver for Intel Broxton Whiskey Cove PMIC
*
* Copyright (C) 2015 Intel Corporation. All rights reserved.
*
* 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/module.h>
#include <linux/acpi.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h>
#include <linux/mfd/intel_bxtwc.h>
#include <asm/intel_pmc_ipc.h>
/* PMIC device registers */
#define REG_ADDR_MASK 0xFF00
#define REG_ADDR_SHIFT 8
#define REG_OFFSET_MASK 0xFF
/* Interrupt Status Registers */
#define BXTWC_IRQLVL1 0x4E02
#define BXTWC_PWRBTNIRQ 0x4E03
#define BXTWC_THRM0IRQ 0x4E04
#define BXTWC_THRM1IRQ 0x4E05
#define BXTWC_THRM2IRQ 0x4E06
#define BXTWC_BCUIRQ 0x4E07
#define BXTWC_ADCIRQ 0x4E08
#define BXTWC_CHGR0IRQ 0x4E09
#define BXTWC_CHGR1IRQ 0x4E0A
#define BXTWC_GPIOIRQ0 0x4E0B
#define BXTWC_GPIOIRQ1 0x4E0C
#define BXTWC_CRITIRQ 0x4E0D
/* Interrupt MASK Registers */
#define BXTWC_MIRQLVL1 0x4E0E
#define BXTWC_MPWRTNIRQ 0x4E0F
#define BXTWC_MTHRM0IRQ 0x4E12
#define BXTWC_MTHRM1IRQ 0x4E13
#define BXTWC_MTHRM2IRQ 0x4E14
#define BXTWC_MBCUIRQ 0x4E15
#define BXTWC_MADCIRQ 0x4E16
#define BXTWC_MCHGR0IRQ 0x4E17
#define BXTWC_MCHGR1IRQ 0x4E18
#define BXTWC_MGPIO0IRQ 0x4E19
#define BXTWC_MGPIO1IRQ 0x4E1A
#define BXTWC_MCRITIRQ 0x4E1B
/* Whiskey Cove PMIC share same ACPI ID between different platforms */
#define BROXTON_PMIC_WC_HRV 4
/* Manage in two IRQ chips since mask registers are not consecutive */
enum bxtwc_irqs {
/* Level 1 */
BXTWC_PWRBTN_LVL1_IRQ = 0,
BXTWC_TMU_LVL1_IRQ,
BXTWC_THRM_LVL1_IRQ,
BXTWC_BCU_LVL1_IRQ,
BXTWC_ADC_LVL1_IRQ,
BXTWC_CHGR_LVL1_IRQ,
BXTWC_GPIO_LVL1_IRQ,
BXTWC_CRIT_LVL1_IRQ,
/* Level 2 */
BXTWC_PWRBTN_IRQ,
};
enum bxtwc_irqs_level2 {
/* Level 2 */
BXTWC_THRM0_IRQ = 0,
BXTWC_THRM1_IRQ,
BXTWC_THRM2_IRQ,
BXTWC_BCU_IRQ,
BXTWC_ADC_IRQ,
BXTWC_CHGR0_IRQ,
BXTWC_CHGR1_IRQ,
BXTWC_GPIO0_IRQ,
BXTWC_GPIO1_IRQ,
BXTWC_CRIT_IRQ,
};
static const struct regmap_irq bxtwc_regmap_irqs[] = {
REGMAP_IRQ_REG(BXTWC_PWRBTN_LVL1_IRQ, 0, BIT(0)),
REGMAP_IRQ_REG(BXTWC_TMU_LVL1_IRQ, 0, BIT(1)),
REGMAP_IRQ_REG(BXTWC_THRM_LVL1_IRQ, 0, BIT(2)),
REGMAP_IRQ_REG(BXTWC_BCU_LVL1_IRQ, 0, BIT(3)),
REGMAP_IRQ_REG(BXTWC_ADC_LVL1_IRQ, 0, BIT(4)),
REGMAP_IRQ_REG(BXTWC_CHGR_LVL1_IRQ, 0, BIT(5)),
REGMAP_IRQ_REG(BXTWC_GPIO_LVL1_IRQ, 0, BIT(6)),
REGMAP_IRQ_REG(BXTWC_CRIT_LVL1_IRQ, 0, BIT(7)),
REGMAP_IRQ_REG(BXTWC_PWRBTN_IRQ, 1, 0x03),
};
static const struct regmap_irq bxtwc_regmap_irqs_level2[] = {
REGMAP_IRQ_REG(BXTWC_THRM0_IRQ, 0, 0xff),
REGMAP_IRQ_REG(BXTWC_THRM1_IRQ, 1, 0xbf),
REGMAP_IRQ_REG(BXTWC_THRM2_IRQ, 2, 0xff),
REGMAP_IRQ_REG(BXTWC_BCU_IRQ, 3, 0x1f),
REGMAP_IRQ_REG(BXTWC_ADC_IRQ, 4, 0xff),
REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 5, 0x1f),
REGMAP_IRQ_REG(BXTWC_CHGR1_IRQ, 6, 0x1f),
REGMAP_IRQ_REG(BXTWC_GPIO0_IRQ, 7, 0xff),
REGMAP_IRQ_REG(BXTWC_GPIO1_IRQ, 8, 0x3f),
REGMAP_IRQ_REG(BXTWC_CRIT_IRQ, 9, 0x03),
};
static struct regmap_irq_chip bxtwc_regmap_irq_chip = {
.name = "bxtwc_irq_chip",
.status_base = BXTWC_IRQLVL1,
.mask_base = BXTWC_MIRQLVL1,
.irqs = bxtwc_regmap_irqs,
.num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs),
.num_regs = 2,
};
static struct regmap_irq_chip bxtwc_regmap_irq_chip_level2 = {
.name = "bxtwc_irq_chip_level2",
.status_base = BXTWC_THRM0IRQ,
.mask_base = BXTWC_MTHRM0IRQ,
.irqs = bxtwc_regmap_irqs_level2,
.num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_level2),
.num_regs = 10,
};
static struct resource gpio_resources[] = {
DEFINE_RES_IRQ_NAMED(BXTWC_GPIO0_IRQ, "GPIO0"),
DEFINE_RES_IRQ_NAMED(BXTWC_GPIO1_IRQ, "GPIO1"),
};
static struct resource adc_resources[] = {
DEFINE_RES_IRQ_NAMED(BXTWC_ADC_IRQ, "ADC"),
};
static struct resource charger_resources[] = {
DEFINE_RES_IRQ_NAMED(BXTWC_CHGR0_IRQ, "CHARGER"),
DEFINE_RES_IRQ_NAMED(BXTWC_CHGR1_IRQ, "CHARGER1"),
};
static struct resource thermal_resources[] = {
DEFINE_RES_IRQ(BXTWC_THRM0_IRQ),
DEFINE_RES_IRQ(BXTWC_THRM1_IRQ),
DEFINE_RES_IRQ(BXTWC_THRM2_IRQ),
};
static struct resource bcu_resources[] = {
DEFINE_RES_IRQ_NAMED(BXTWC_BCU_IRQ, "BCU"),
};
static struct mfd_cell bxt_wc_dev[] = {
{
.name = "bxt_wcove_gpadc",
.num_resources = ARRAY_SIZE(adc_resources),
.resources = adc_resources,
},
{
.name = "bxt_wcove_thermal",
.num_resources = ARRAY_SIZE(thermal_resources),
.resources = thermal_resources,
},
{
.name = "bxt_wcove_ext_charger",
.num_resources = ARRAY_SIZE(charger_resources),
.resources = charger_resources,
},
{
.name = "bxt_wcove_bcu",
.num_resources = ARRAY_SIZE(bcu_resources),
.resources = bcu_resources,
},
{
.name = "bxt_wcove_gpio",
.num_resources = ARRAY_SIZE(gpio_resources),
.resources = gpio_resources,
},
{
.name = "bxt_wcove_region",
},
};
static int regmap_ipc_byte_reg_read(void *context, unsigned int reg,
unsigned int *val)
{
int ret;
int i2c_addr;
u8 ipc_in[2];
u8 ipc_out[4];
struct intel_soc_pmic *pmic = context;
if (reg & REG_ADDR_MASK)
i2c_addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
else {
i2c_addr = BXTWC_DEVICE1_ADDR;
if (!i2c_addr) {
dev_err(pmic->dev, "I2C address not set\n");
return -EINVAL;
}
}
reg &= REG_OFFSET_MASK;
ipc_in[0] = reg;
ipc_in[1] = i2c_addr;
ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS,
PMC_IPC_PMIC_ACCESS_READ,
ipc_in, sizeof(ipc_in), (u32 *)ipc_out, 1);
if (ret) {
dev_err(pmic->dev, "Failed to read from PMIC\n");
return ret;
}
*val = ipc_out[0];
return 0;
}
static int regmap_ipc_byte_reg_write(void *context, unsigned int reg,
unsigned int val)
{
int ret;
int i2c_addr;
u8 ipc_in[3];
struct intel_soc_pmic *pmic = context;
if (reg & REG_ADDR_MASK)
i2c_addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
else {
i2c_addr = BXTWC_DEVICE1_ADDR;
if (!i2c_addr) {
dev_err(pmic->dev, "I2C address not set\n");
return -EINVAL;
}
}
reg &= REG_OFFSET_MASK;
ipc_in[0] = reg;
ipc_in[1] = i2c_addr;
ipc_in[2] = val;
ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS,
PMC_IPC_PMIC_ACCESS_WRITE,
ipc_in, sizeof(ipc_in), NULL, 0);
if (ret) {
dev_err(pmic->dev, "Failed to write to PMIC\n");
return ret;
}
return 0;
}
/* sysfs interfaces to r/w PMIC registers, required by initial script */
static unsigned long bxtwc_reg_addr;
static ssize_t bxtwc_reg_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "0x%lx\n", bxtwc_reg_addr);
}
static ssize_t bxtwc_reg_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
if (kstrtoul(buf, 0, &bxtwc_reg_addr)) {
dev_err(dev, "Invalid register address\n");
return -EINVAL;
}
return (ssize_t)count;
}
static ssize_t bxtwc_val_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
unsigned int val;
struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
ret = regmap_read(pmic->regmap, bxtwc_reg_addr, &val);
if (ret < 0) {
dev_err(dev, "Failed to read 0x%lx\n", bxtwc_reg_addr);
return -EIO;
}
return sprintf(buf, "0x%02x\n", val);
}
static ssize_t bxtwc_val_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
unsigned int val;
struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
ret = kstrtouint(buf, 0, &val);
if (ret)
return ret;
ret = regmap_write(pmic->regmap, bxtwc_reg_addr, val);
if (ret) {
dev_err(dev, "Failed to write value 0x%02x to address 0x%lx",
val, bxtwc_reg_addr);
return -EIO;
}
return count;
}
static DEVICE_ATTR(addr, S_IWUSR | S_IRUSR, bxtwc_reg_show, bxtwc_reg_store);
static DEVICE_ATTR(val, S_IWUSR | S_IRUSR, bxtwc_val_show, bxtwc_val_store);
static struct attribute *bxtwc_attrs[] = {
&dev_attr_addr.attr,
&dev_attr_val.attr,
NULL
};
static const struct attribute_group bxtwc_group = {
.attrs = bxtwc_attrs,
};
static const struct regmap_config bxtwc_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.reg_write = regmap_ipc_byte_reg_write,
.reg_read = regmap_ipc_byte_reg_read,
};
static int bxtwc_probe(struct platform_device *pdev)
{
int ret;
acpi_handle handle;
acpi_status status;
unsigned long long hrv;
struct intel_soc_pmic *pmic;
handle = ACPI_HANDLE(&pdev->dev);
status = acpi_evaluate_integer(handle, "_HRV", NULL, &hrv);
if (ACPI_FAILURE(status)) {
dev_err(&pdev->dev, "Failed to get PMIC hardware revision\n");
return -ENODEV;
}
if (hrv != BROXTON_PMIC_WC_HRV) {
dev_err(&pdev->dev, "Invalid PMIC hardware revision: %llu\n",
hrv);
return -ENODEV;
}
pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
if (!pmic)
return -ENOMEM;
ret = platform_get_irq(pdev, 0);
if (ret < 0) {
dev_err(&pdev->dev, "Invalid IRQ\n");
return ret;
}
pmic->irq = ret;
dev_set_drvdata(&pdev->dev, pmic);
pmic->dev = &pdev->dev;
pmic->regmap = devm_regmap_init(&pdev->dev, NULL, pmic,
&bxtwc_regmap_config);
if (IS_ERR(pmic->regmap)) {
ret = PTR_ERR(pmic->regmap);
dev_err(&pdev->dev, "Failed to initialise regmap: %d\n", ret);
return ret;
}
ret = regmap_add_irq_chip(pmic->regmap, pmic->irq,
IRQF_ONESHOT | IRQF_SHARED,
0, &bxtwc_regmap_irq_chip,
&pmic->irq_chip_data);
if (ret) {
dev_err(&pdev->dev, "Failed to add IRQ chip\n");
return ret;
}
ret = regmap_add_irq_chip(pmic->regmap, pmic->irq,
IRQF_ONESHOT | IRQF_SHARED,
0, &bxtwc_regmap_irq_chip_level2,
&pmic->irq_chip_data_level2);
if (ret) {
dev_err(&pdev->dev, "Failed to add secondary IRQ chip\n");
goto err_irq_chip_level2;
}
ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, bxt_wc_dev,
ARRAY_SIZE(bxt_wc_dev), NULL, 0,
NULL);
if (ret) {
dev_err(&pdev->dev, "Failed to add devices\n");
goto err_mfd;
}
ret = sysfs_create_group(&pdev->dev.kobj, &bxtwc_group);
if (ret) {
dev_err(&pdev->dev, "Failed to create sysfs group %d\n", ret);
goto err_sysfs;
}
return 0;
err_sysfs:
mfd_remove_devices(&pdev->dev);
err_mfd:
regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_level2);
err_irq_chip_level2:
regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
return ret;
}
static int bxtwc_remove(struct platform_device *pdev)
{
struct intel_soc_pmic *pmic = dev_get_drvdata(&pdev->dev);
sysfs_remove_group(&pdev->dev.kobj, &bxtwc_group);
mfd_remove_devices(&pdev->dev);
regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_level2);
return 0;
}
static void bxtwc_shutdown(struct platform_device *pdev)
{
struct intel_soc_pmic *pmic = dev_get_drvdata(&pdev->dev);
disable_irq(pmic->irq);
}
#ifdef CONFIG_PM_SLEEP
static int bxtwc_suspend(struct device *dev)
{
struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
disable_irq(pmic->irq);
return 0;
}
static int bxtwc_resume(struct device *dev)
{
struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
enable_irq(pmic->irq);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(bxtwc_pm_ops, bxtwc_suspend, bxtwc_resume);
static const struct acpi_device_id bxtwc_acpi_ids[] = {
{ "INT34D3", },
{ }
};
MODULE_DEVICE_TABLE(acpi, pmic_acpi_ids);
static struct platform_driver bxtwc_driver = {
.probe = bxtwc_probe,
.remove = bxtwc_remove,
.shutdown = bxtwc_shutdown,
.driver = {
.name = "BXTWC PMIC",
.pm = &bxtwc_pm_ops,
.acpi_match_table = ACPI_PTR(bxtwc_acpi_ids),
},
};
module_platform_driver(bxtwc_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Qipeng Zha<qipeng.zha@intel.com>");
...@@ -448,7 +448,6 @@ static int kempld_probe(struct platform_device *pdev) ...@@ -448,7 +448,6 @@ static int kempld_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct kempld_device_data *pld; struct kempld_device_data *pld;
struct resource *ioport; struct resource *ioport;
int ret;
pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL); pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL);
if (!pld) if (!pld)
...@@ -471,11 +470,7 @@ static int kempld_probe(struct platform_device *pdev) ...@@ -471,11 +470,7 @@ static int kempld_probe(struct platform_device *pdev)
mutex_init(&pld->lock); mutex_init(&pld->lock);
platform_set_drvdata(pdev, pld); platform_set_drvdata(pdev, pld);
ret = kempld_detect_device(pld); return kempld_detect_device(pld);
if (ret)
return ret;
return 0;
} }
static int kempld_remove(struct platform_device *pdev) static int kempld_remove(struct platform_device *pdev)
...@@ -756,7 +751,6 @@ MODULE_DEVICE_TABLE(dmi, kempld_dmi_table); ...@@ -756,7 +751,6 @@ MODULE_DEVICE_TABLE(dmi, kempld_dmi_table);
static int __init kempld_init(void) static int __init kempld_init(void)
{ {
const struct dmi_system_id *id; const struct dmi_system_id *id;
int ret;
if (force_device_id[0]) { if (force_device_id[0]) {
for (id = kempld_dmi_table; for (id = kempld_dmi_table;
...@@ -771,11 +765,7 @@ static int __init kempld_init(void) ...@@ -771,11 +765,7 @@ static int __init kempld_init(void)
return -ENODEV; return -ENODEV;
} }
ret = platform_driver_register(&kempld_driver); return platform_driver_register(&kempld_driver);
if (ret)
return ret;
return 0;
} }
static void __exit kempld_exit(void) static void __exit kempld_exit(void)
......
...@@ -472,11 +472,7 @@ static int lm3533_device_setup(struct lm3533 *lm3533, ...@@ -472,11 +472,7 @@ static int lm3533_device_setup(struct lm3533 *lm3533,
if (ret) if (ret)
return ret; return ret;
ret = lm3533_set_boost_ovp(lm3533, pdata->boost_ovp); return lm3533_set_boost_ovp(lm3533, pdata->boost_ovp);
if (ret)
return ret;
return 0;
} }
static int lm3533_device_init(struct lm3533 *lm3533) static int lm3533_device_init(struct lm3533 *lm3533)
...@@ -596,7 +592,6 @@ static int lm3533_i2c_probe(struct i2c_client *i2c, ...@@ -596,7 +592,6 @@ static int lm3533_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct lm3533 *lm3533; struct lm3533 *lm3533;
int ret;
dev_dbg(&i2c->dev, "%s\n", __func__); dev_dbg(&i2c->dev, "%s\n", __func__);
...@@ -613,11 +608,7 @@ static int lm3533_i2c_probe(struct i2c_client *i2c, ...@@ -613,11 +608,7 @@ static int lm3533_i2c_probe(struct i2c_client *i2c,
lm3533->dev = &i2c->dev; lm3533->dev = &i2c->dev;
lm3533->irq = i2c->irq; lm3533->irq = i2c->irq;
ret = lm3533_device_init(lm3533); return lm3533_device_init(lm3533);
if (ret)
return ret;
return 0;
} }
static int lm3533_i2c_remove(struct i2c_client *i2c) static int lm3533_i2c_remove(struct i2c_client *i2c)
......
...@@ -132,24 +132,18 @@ static struct resource gpio_ich_res[] = { ...@@ -132,24 +132,18 @@ static struct resource gpio_ich_res[] = {
}, },
}; };
enum lpc_cells { static struct mfd_cell lpc_ich_wdt_cell = {
LPC_WDT = 0, .name = "iTCO_wdt",
LPC_GPIO, .num_resources = ARRAY_SIZE(wdt_ich_res),
.resources = wdt_ich_res,
.ignore_resource_conflicts = true,
}; };
static struct mfd_cell lpc_ich_cells[] = { static struct mfd_cell lpc_ich_gpio_cell = {
[LPC_WDT] = { .name = "gpio_ich",
.name = "iTCO_wdt", .num_resources = ARRAY_SIZE(gpio_ich_res),
.num_resources = ARRAY_SIZE(wdt_ich_res), .resources = gpio_ich_res,
.resources = wdt_ich_res, .ignore_resource_conflicts = true,
.ignore_resource_conflicts = true,
},
[LPC_GPIO] = {
.name = "gpio_ich",
.num_resources = ARRAY_SIZE(gpio_ich_res),
.resources = gpio_ich_res,
.ignore_resource_conflicts = true,
},
}; };
/* chipset related info */ /* chipset related info */
...@@ -841,7 +835,7 @@ static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev) ...@@ -841,7 +835,7 @@ static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev)
struct itco_wdt_platform_data *pdata; struct itco_wdt_platform_data *pdata;
struct lpc_ich_priv *priv = pci_get_drvdata(dev); struct lpc_ich_priv *priv = pci_get_drvdata(dev);
struct lpc_ich_info *info; struct lpc_ich_info *info;
struct mfd_cell *cell = &lpc_ich_cells[LPC_WDT]; struct mfd_cell *cell = &lpc_ich_wdt_cell;
pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) if (!pdata)
...@@ -860,7 +854,7 @@ static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev) ...@@ -860,7 +854,7 @@ static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev)
static void lpc_ich_finalize_gpio_cell(struct pci_dev *dev) static void lpc_ich_finalize_gpio_cell(struct pci_dev *dev)
{ {
struct lpc_ich_priv *priv = pci_get_drvdata(dev); struct lpc_ich_priv *priv = pci_get_drvdata(dev);
struct mfd_cell *cell = &lpc_ich_cells[LPC_GPIO]; struct mfd_cell *cell = &lpc_ich_gpio_cell;
cell->platform_data = &lpc_chipset_info[priv->chipset]; cell->platform_data = &lpc_chipset_info[priv->chipset];
cell->pdata_size = sizeof(struct lpc_ich_info); cell->pdata_size = sizeof(struct lpc_ich_info);
...@@ -904,7 +898,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev) ...@@ -904,7 +898,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev)
base_addr = base_addr_cfg & 0x0000ff80; base_addr = base_addr_cfg & 0x0000ff80;
if (!base_addr) { if (!base_addr) {
dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n");
lpc_ich_cells[LPC_GPIO].num_resources--; lpc_ich_gpio_cell.num_resources--;
goto gpe0_done; goto gpe0_done;
} }
...@@ -918,7 +912,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev) ...@@ -918,7 +912,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev)
* the platform_device subsystem doesn't see this resource * the platform_device subsystem doesn't see this resource
* or it will register an invalid region. * or it will register an invalid region.
*/ */
lpc_ich_cells[LPC_GPIO].num_resources--; lpc_ich_gpio_cell.num_resources--;
acpi_conflict = true; acpi_conflict = true;
} else { } else {
lpc_ich_enable_acpi_space(dev); lpc_ich_enable_acpi_space(dev);
...@@ -958,12 +952,12 @@ static int lpc_ich_init_gpio(struct pci_dev *dev) ...@@ -958,12 +952,12 @@ static int lpc_ich_init_gpio(struct pci_dev *dev)
lpc_ich_finalize_gpio_cell(dev); lpc_ich_finalize_gpio_cell(dev);
ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO, ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO,
&lpc_ich_cells[LPC_GPIO], 1, NULL, 0, NULL); &lpc_ich_gpio_cell, 1, NULL, 0, NULL);
gpio_done: gpio_done:
if (acpi_conflict) if (acpi_conflict)
pr_warn("Resource conflict(s) found affecting %s\n", pr_warn("Resource conflict(s) found affecting %s\n",
lpc_ich_cells[LPC_GPIO].name); lpc_ich_gpio_cell.name);
return ret; return ret;
} }
...@@ -1007,7 +1001,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev) ...@@ -1007,7 +1001,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
*/ */
if (lpc_chipset_info[priv->chipset].iTCO_version == 1) { if (lpc_chipset_info[priv->chipset].iTCO_version == 1) {
/* Don't register iomem for TCO ver 1 */ /* Don't register iomem for TCO ver 1 */
lpc_ich_cells[LPC_WDT].num_resources--; lpc_ich_wdt_cell.num_resources--;
} else if (lpc_chipset_info[priv->chipset].iTCO_version == 2) { } else if (lpc_chipset_info[priv->chipset].iTCO_version == 2) {
pci_read_config_dword(dev, RCBABASE, &base_addr_cfg); pci_read_config_dword(dev, RCBABASE, &base_addr_cfg);
base_addr = base_addr_cfg & 0xffffc000; base_addr = base_addr_cfg & 0xffffc000;
...@@ -1035,7 +1029,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev) ...@@ -1035,7 +1029,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
goto wdt_done; goto wdt_done;
ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO, ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO,
&lpc_ich_cells[LPC_WDT], 1, NULL, 0, NULL); &lpc_ich_wdt_cell, 1, NULL, 0, NULL);
wdt_done: wdt_done:
return ret; return ret;
......
...@@ -55,6 +55,7 @@ static const struct of_device_id max8997_pmic_dt_match[] = { ...@@ -55,6 +55,7 @@ static const struct of_device_id max8997_pmic_dt_match[] = {
{ .compatible = "maxim,max8997-pmic", .data = (void *)TYPE_MAX8997 }, { .compatible = "maxim,max8997-pmic", .data = (void *)TYPE_MAX8997 },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, max8997_pmic_dt_match);
#endif #endif
int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest) int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
......
...@@ -82,29 +82,49 @@ static int mfd_platform_add_cell(struct platform_device *pdev, ...@@ -82,29 +82,49 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
static void mfd_acpi_add_device(const struct mfd_cell *cell, static void mfd_acpi_add_device(const struct mfd_cell *cell,
struct platform_device *pdev) struct platform_device *pdev)
{ {
struct acpi_device *parent_adev; const struct mfd_cell_acpi_match *match = cell->acpi_match;
struct acpi_device *parent, *child;
struct acpi_device *adev; struct acpi_device *adev;
parent_adev = ACPI_COMPANION(pdev->dev.parent); parent = ACPI_COMPANION(pdev->dev.parent);
if (!parent_adev) if (!parent)
return; return;
/* /*
* MFD child device gets its ACPI handle either from the ACPI * MFD child device gets its ACPI handle either from the ACPI device
* device directly under the parent that matches the acpi_pnpid or * directly under the parent that matches the either _HID or _CID, or
* it will use the parent handle if is no acpi_pnpid is given. * _ADR or it will use the parent handle if is no ID is given.
*
* Note that use of _ADR is a grey area in the ACPI specification,
* though Intel Galileo Gen2 is using it to distinguish the children
* devices.
*/ */
adev = parent_adev; adev = parent;
if (cell->acpi_pnpid) { if (match) {
struct acpi_device_id ids[2] = {}; if (match->pnpid) {
struct acpi_device *child_adev; struct acpi_device_id ids[2] = {};
strlcpy(ids[0].id, cell->acpi_pnpid, sizeof(ids[0].id)); strlcpy(ids[0].id, match->pnpid, sizeof(ids[0].id));
list_for_each_entry(child_adev, &parent_adev->children, node) list_for_each_entry(child, &parent->children, node) {
if (acpi_match_device_ids(child_adev, ids)) { if (acpi_match_device_ids(child, ids)) {
adev = child_adev; adev = child;
break; break;
}
}
} else {
unsigned long long adr;
acpi_status status;
list_for_each_entry(child, &parent->children, node) {
status = acpi_evaluate_integer(child->handle,
"_ADR", NULL,
&adr);
if (ACPI_SUCCESS(status) && match->adr == adr) {
adev = child;
break;
}
} }
}
} }
ACPI_COMPANION_SET(&pdev->dev, adev); ACPI_COMPANION_SET(&pdev->dev, adev);
......
...@@ -55,7 +55,7 @@ EXPORT_SYMBOL_GPL(pcf50633_free_irq); ...@@ -55,7 +55,7 @@ EXPORT_SYMBOL_GPL(pcf50633_free_irq);
static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask) static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
{ {
u8 reg, bit; u8 reg, bit;
int ret = 0, idx; int idx;
idx = irq >> 3; idx = irq >> 3;
reg = PCF50633_REG_INT1M + idx; reg = PCF50633_REG_INT1M + idx;
...@@ -72,7 +72,7 @@ static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask) ...@@ -72,7 +72,7 @@ static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
mutex_unlock(&pcf->lock); mutex_unlock(&pcf->lock);
return ret; return 0;
} }
int pcf50633_irq_mask(struct pcf50633 *pcf, int irq) int pcf50633_irq_mask(struct pcf50633 *pcf, int irq)
......
...@@ -550,7 +550,7 @@ static int qcom_rpm_probe(struct platform_device *pdev) ...@@ -550,7 +550,7 @@ static int qcom_rpm_probe(struct platform_device *pdev)
ret = devm_request_irq(&pdev->dev, ret = devm_request_irq(&pdev->dev,
irq_ack, irq_ack,
qcom_rpm_ack_interrupt, qcom_rpm_ack_interrupt,
IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND, IRQF_TRIGGER_RISING,
"qcom_rpm_ack", "qcom_rpm_ack",
rpm); rpm);
if (ret) { if (ret) {
......
...@@ -47,6 +47,9 @@ static const struct mfd_cell rt5033_devs[] = { ...@@ -47,6 +47,9 @@ static const struct mfd_cell rt5033_devs[] = {
}, { }, {
.name = "rt5033-battery", .name = "rt5033-battery",
.of_compatible = "richtek,rt5033-battery", .of_compatible = "richtek,rt5033-battery",
}, {
.name = "rt5033-led",
.of_compatible = "richtek,rt5033-led",
}, },
}; };
...@@ -137,7 +140,6 @@ static struct i2c_driver rt5033_driver = { ...@@ -137,7 +140,6 @@ static struct i2c_driver rt5033_driver = {
}; };
module_i2c_driver(rt5033_driver); module_i2c_driver(rt5033_driver);
MODULE_ALIAS("i2c:rt5033");
MODULE_DESCRIPTION("Richtek RT5033 multi-function core driver"); MODULE_DESCRIPTION("Richtek RT5033 multi-function core driver");
MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>"); MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -138,11 +138,7 @@ static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card) ...@@ -138,11 +138,7 @@ static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask, pwr_on); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask, pwr_on);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0x00); LDO3318_PWR_MASK, 0x00);
err = rtsx_pci_send_cmd(pcr, 100); return rtsx_pci_send_cmd(pcr, 100);
if (err < 0)
return err;
return 0;
} }
static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card) static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
......
...@@ -26,6 +26,14 @@ ...@@ -26,6 +26,14 @@
#include "rtsx_pcr.h" #include "rtsx_pcr.h"
static u8 rts5227_get_ic_version(struct rtsx_pcr *pcr)
{
u8 val;
rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
return val & 0x0F;
}
static void rts5227_fill_driving(struct rtsx_pcr *pcr, u8 voltage) static void rts5227_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
{ {
u8 driving_3v3[4][3] = { u8 driving_3v3[4][3] = {
...@@ -88,7 +96,7 @@ static void rts5227_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) ...@@ -88,7 +96,7 @@ static void rts5227_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0); rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0);
if (pm_state == HOST_ENTER_S3) if (pm_state == HOST_ENTER_S3)
rtsx_pci_write_register(pcr, PM_CTRL3, 0x10, 0x10); rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x10);
rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03); rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
} }
...@@ -121,7 +129,7 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) ...@@ -121,7 +129,7 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0xB8); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0xB8);
else else
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0x88); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0x88);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, pcr->reg_pm_ctrl3, 0x10, 0x00);
return rtsx_pci_send_cmd(pcr, 100); return rtsx_pci_send_cmd(pcr, 100);
} }
...@@ -179,11 +187,7 @@ static int rts5227_card_power_on(struct rtsx_pcr *pcr, int card) ...@@ -179,11 +187,7 @@ static int rts5227_card_power_on(struct rtsx_pcr *pcr, int card)
SD_POWER_MASK, SD_POWER_ON); SD_POWER_MASK, SD_POWER_ON);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0x06); LDO3318_PWR_MASK, 0x06);
err = rtsx_pci_send_cmd(pcr, 100); return rtsx_pci_send_cmd(pcr, 100);
if (err < 0)
return err;
return 0;
} }
static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card) static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card)
...@@ -298,8 +302,73 @@ void rts5227_init_params(struct rtsx_pcr *pcr) ...@@ -298,8 +302,73 @@ void rts5227_init_params(struct rtsx_pcr *pcr)
pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15); pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15);
pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 7, 7); pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 7, 7);
pcr->ic_version = rts5227_get_ic_version(pcr);
pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl; pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl;
pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl; pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl;
pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl; pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl;
pcr->ms_pull_ctl_disable_tbl = rts5227_ms_pull_ctl_disable_tbl; pcr->ms_pull_ctl_disable_tbl = rts5227_ms_pull_ctl_disable_tbl;
pcr->reg_pm_ctrl3 = PM_CTRL3;
}
static int rts522a_optimize_phy(struct rtsx_pcr *pcr)
{
int err;
err = rtsx_pci_write_register(pcr, RTS522A_PM_CTRL3, D3_DELINK_MODE_EN,
0x00);
if (err < 0)
return err;
if (is_version(pcr, 0x522A, IC_VER_A)) {
err = rtsx_pci_write_phy_register(pcr, PHY_RCR2,
PHY_RCR2_INIT_27S);
if (err)
return err;
rtsx_pci_write_phy_register(pcr, PHY_RCR1, PHY_RCR1_INIT_27S);
rtsx_pci_write_phy_register(pcr, PHY_FLD0, PHY_FLD0_INIT_27S);
rtsx_pci_write_phy_register(pcr, PHY_FLD3, PHY_FLD3_INIT_27S);
rtsx_pci_write_phy_register(pcr, PHY_FLD4, PHY_FLD4_INIT_27S);
}
return 0;
}
static int rts522a_extra_init_hw(struct rtsx_pcr *pcr)
{
rts5227_extra_init_hw(pcr);
rtsx_pci_write_register(pcr, FUNC_FORCE_CTL, FUNC_FORCE_UPME_XMT_DBG,
FUNC_FORCE_UPME_XMT_DBG);
rtsx_pci_write_register(pcr, PCLK_CTL, 0x04, 0x04);
rtsx_pci_write_register(pcr, PM_EVENT_DEBUG, PME_DEBUG_0, PME_DEBUG_0);
rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 0xFF, 0x11);
return 0;
}
/* rts522a operations mainly derived from rts5227, except phy/hw init setting.
*/
static const struct pcr_ops rts522a_pcr_ops = {
.fetch_vendor_settings = rts5227_fetch_vendor_settings,
.extra_init_hw = rts522a_extra_init_hw,
.optimize_phy = rts522a_optimize_phy,
.turn_on_led = rts5227_turn_on_led,
.turn_off_led = rts5227_turn_off_led,
.enable_auto_blink = rts5227_enable_auto_blink,
.disable_auto_blink = rts5227_disable_auto_blink,
.card_power_on = rts5227_card_power_on,
.card_power_off = rts5227_card_power_off,
.switch_output_voltage = rts5227_switch_output_voltage,
.cd_deglitch = NULL,
.conv_clk_and_div_n = NULL,
.force_power_down = rts5227_force_power_down,
};
void rts522a_init_params(struct rtsx_pcr *pcr)
{
rts5227_init_params(pcr);
pcr->reg_pm_ctrl3 = RTS522A_PM_CTRL3;
} }
...@@ -129,11 +129,7 @@ static int rts5229_card_power_on(struct rtsx_pcr *pcr, int card) ...@@ -129,11 +129,7 @@ static int rts5229_card_power_on(struct rtsx_pcr *pcr, int card)
SD_POWER_MASK, SD_POWER_ON); SD_POWER_MASK, SD_POWER_ON);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0x06); LDO3318_PWR_MASK, 0x06);
err = rtsx_pci_send_cmd(pcr, 100); return rtsx_pci_send_cmd(pcr, 100);
if (err < 0)
return err;
return 0;
} }
static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card) static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card)
......
...@@ -234,11 +234,7 @@ static int rtsx_base_card_power_on(struct rtsx_pcr *pcr, int card) ...@@ -234,11 +234,7 @@ static int rtsx_base_card_power_on(struct rtsx_pcr *pcr, int card)
SD_POWER_MASK, SD_VCC_POWER_ON); SD_POWER_MASK, SD_VCC_POWER_ON);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
LDO3318_PWR_MASK, 0x06); LDO3318_PWR_MASK, 0x06);
err = rtsx_pci_send_cmd(pcr, 100); return rtsx_pci_send_cmd(pcr, 100);
if (err < 0)
return err;
return 0;
} }
static int rtsx_base_card_power_off(struct rtsx_pcr *pcr, int card) static int rtsx_base_card_power_off(struct rtsx_pcr *pcr, int card)
......
...@@ -55,6 +55,7 @@ static const struct pci_device_id rtsx_pci_ids[] = { ...@@ -55,6 +55,7 @@ static const struct pci_device_id rtsx_pci_ids[] = {
{ PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x522A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5286), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5286), PCI_CLASS_OTHERS << 16, 0xFF0000 },
...@@ -571,11 +572,7 @@ static int rtsx_pci_set_pull_ctl(struct rtsx_pcr *pcr, const u32 *tbl) ...@@ -571,11 +572,7 @@ static int rtsx_pci_set_pull_ctl(struct rtsx_pcr *pcr, const u32 *tbl)
tbl++; tbl++;
} }
err = rtsx_pci_send_cmd(pcr, 100); return rtsx_pci_send_cmd(pcr, 100);
if (err < 0)
return err;
return 0;
} }
int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card) int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card)
...@@ -1102,6 +1099,10 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr) ...@@ -1102,6 +1099,10 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
rts5227_init_params(pcr); rts5227_init_params(pcr);
break; break;
case 0x522A:
rts522a_init_params(pcr);
break;
case 0x5249: case 0x5249:
rts5249_init_params(pcr); rts5249_init_params(pcr);
break; break;
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#define MIN_DIV_N_PCR 80 #define MIN_DIV_N_PCR 80
#define MAX_DIV_N_PCR 208 #define MAX_DIV_N_PCR 208
#define RTS522A_PM_CTRL3 0xFF7E
#define RTS524A_PME_FORCE_CTL 0xFF78 #define RTS524A_PME_FORCE_CTL 0xFF78
#define RTS524A_PM_CTRL3 0xFF7E #define RTS524A_PM_CTRL3 0xFF7E
...@@ -38,6 +40,7 @@ void rts5229_init_params(struct rtsx_pcr *pcr); ...@@ -38,6 +40,7 @@ void rts5229_init_params(struct rtsx_pcr *pcr);
void rtl8411_init_params(struct rtsx_pcr *pcr); void rtl8411_init_params(struct rtsx_pcr *pcr);
void rtl8402_init_params(struct rtsx_pcr *pcr); void rtl8402_init_params(struct rtsx_pcr *pcr);
void rts5227_init_params(struct rtsx_pcr *pcr); void rts5227_init_params(struct rtsx_pcr *pcr);
void rts522a_init_params(struct rtsx_pcr *pcr);
void rts5249_init_params(struct rtsx_pcr *pcr); void rts5249_init_params(struct rtsx_pcr *pcr);
void rts524a_init_params(struct rtsx_pcr *pcr); void rts524a_init_params(struct rtsx_pcr *pcr);
void rts525a_init_params(struct rtsx_pcr *pcr); void rts525a_init_params(struct rtsx_pcr *pcr);
......
...@@ -103,12 +103,9 @@ static const struct mfd_cell s2mpa01_devs[] = { ...@@ -103,12 +103,9 @@ static const struct mfd_cell s2mpa01_devs[] = {
}; };
static const struct mfd_cell s2mpu02_devs[] = { static const struct mfd_cell s2mpu02_devs[] = {
{ .name = "s2mpu02-pmic", },
{ .name = "s2mpu02-rtc", },
{ {
.name = "s2mpu02-clk", .name = "s2mpu02-pmic",
.of_compatible = "samsung,s2mpu02-clk", },
}
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF
...@@ -253,6 +250,38 @@ static const struct regmap_config s5m8767_regmap_config = { ...@@ -253,6 +250,38 @@ static const struct regmap_config s5m8767_regmap_config = {
.cache_type = REGCACHE_FLAT, .cache_type = REGCACHE_FLAT,
}; };
static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic)
{
unsigned int val;
/* For each device type, the REG_ID is always the first register */
if (!regmap_read(sec_pmic->regmap_pmic, S2MPS11_REG_ID, &val))
dev_dbg(sec_pmic->dev, "Revision: 0x%x\n", val);
}
static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic)
{
int err;
if (sec_pmic->device_type != S2MPS13X)
return;
if (sec_pmic->pdata->disable_wrstbi) {
/*
* If WRSTBI pin is pulled down this feature must be disabled
* because each Suspend to RAM will trigger buck voltage reset
* to default values.
*/
err = regmap_update_bits(sec_pmic->regmap_pmic,
S2MPS13_REG_WRSTBI,
S2MPS13_REG_WRSTBI_MASK, 0x0);
if (err)
dev_warn(sec_pmic->dev,
"Cannot initialize WRSTBI config: %d\n",
err);
}
}
#ifdef CONFIG_OF #ifdef CONFIG_OF
/* /*
* Only the common platform data elements for s5m8767 are parsed here from the * Only the common platform data elements for s5m8767 are parsed here from the
...@@ -278,6 +307,10 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( ...@@ -278,6 +307,10 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
* not parsed here. * not parsed here.
*/ */
pd->manual_poweroff = of_property_read_bool(dev->of_node,
"samsung,s2mps11-acokb-ground");
pd->disable_wrstbi = of_property_read_bool(dev->of_node,
"samsung,s2mps11-wrstbi-ground");
return pd; return pd;
} }
#else #else
...@@ -423,6 +456,8 @@ static int sec_pmic_probe(struct i2c_client *i2c, ...@@ -423,6 +456,8 @@ static int sec_pmic_probe(struct i2c_client *i2c,
goto err_mfd; goto err_mfd;
device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup); device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup);
sec_pmic_configure(sec_pmic);
sec_pmic_dump_rev(sec_pmic);
return ret; return ret;
...@@ -440,6 +475,33 @@ static int sec_pmic_remove(struct i2c_client *i2c) ...@@ -440,6 +475,33 @@ static int sec_pmic_remove(struct i2c_client *i2c)
return 0; return 0;
} }
static void sec_pmic_shutdown(struct i2c_client *i2c)
{
struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
unsigned int reg, mask;
if (!sec_pmic->pdata->manual_poweroff)
return;
switch (sec_pmic->device_type) {
case S2MPS11X:
reg = S2MPS11_REG_CTRL1;
mask = S2MPS11_CTRL1_PWRHOLD_MASK;
break;
default:
/*
* Currently only one board with S2MPS11 needs this, so just
* ignore the rest.
*/
dev_warn(sec_pmic->dev,
"Unsupported device %lu for manual power off\n",
sec_pmic->device_type);
return;
}
regmap_update_bits(sec_pmic->regmap_pmic, reg, mask, 0);
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int sec_pmic_suspend(struct device *dev) static int sec_pmic_suspend(struct device *dev)
{ {
...@@ -491,6 +553,7 @@ static struct i2c_driver sec_pmic_driver = { ...@@ -491,6 +553,7 @@ static struct i2c_driver sec_pmic_driver = {
}, },
.probe = sec_pmic_probe, .probe = sec_pmic_probe,
.remove = sec_pmic_remove, .remove = sec_pmic_remove,
.shutdown = sec_pmic_shutdown,
.id_table = sec_pmic_id, .id_table = sec_pmic_id,
}; };
......
...@@ -1719,6 +1719,7 @@ static const struct of_device_id of_sm501_match_tbl[] = { ...@@ -1719,6 +1719,7 @@ static const struct of_device_id of_sm501_match_tbl[] = {
{ .compatible = "smi,sm501", }, { .compatible = "smi,sm501", },
{ /* end */ } { /* end */ }
}; };
MODULE_DEVICE_TABLE(of, of_sm501_match_tbl);
static struct platform_driver sm501_plat_driver = { static struct platform_driver sm501_plat_driver = {
.driver = { .driver = {
......
...@@ -795,6 +795,7 @@ static int stmpe24xx_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) ...@@ -795,6 +795,7 @@ static int stmpe24xx_get_altfunc(struct stmpe *stmpe, enum stmpe_block block)
return 2; return 2;
case STMPE_BLOCK_KEYPAD: case STMPE_BLOCK_KEYPAD:
case STMPE_BLOCK_PWM:
return 1; return 1;
case STMPE_BLOCK_GPIO: case STMPE_BLOCK_GPIO:
......
...@@ -64,27 +64,47 @@ static int tps6105x_startup(struct tps6105x *tps6105x) ...@@ -64,27 +64,47 @@ static int tps6105x_startup(struct tps6105x *tps6105x)
} }
/* /*
* MFD cells - we have one cell which is selected operation * MFD cells - we always have a GPIO cell and we have one cell
* mode, and we always have a GPIO cell. * which is selected operation mode.
*/ */
static struct mfd_cell tps6105x_cells[] = { static struct mfd_cell tps6105x_gpio_cell = {
{ .name = "tps6105x-gpio",
/* name will be runtime assigned */ };
.id = -1,
}, static struct mfd_cell tps6105x_leds_cell = {
{ .name = "tps6105x-leds",
.name = "tps6105x-gpio", };
.id = -1,
}, static struct mfd_cell tps6105x_flash_cell = {
.name = "tps6105x-flash",
}; };
static struct mfd_cell tps6105x_regulator_cell = {
.name = "tps6105x-regulator",
};
static int tps6105x_add_device(struct tps6105x *tps6105x,
struct mfd_cell *cell)
{
cell->platform_data = tps6105x;
cell->pdata_size = sizeof(*tps6105x);
return mfd_add_devices(&tps6105x->client->dev,
PLATFORM_DEVID_AUTO, cell, 1, NULL, 0, NULL);
}
static int tps6105x_probe(struct i2c_client *client, static int tps6105x_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct tps6105x *tps6105x; struct tps6105x *tps6105x;
struct tps6105x_platform_data *pdata; struct tps6105x_platform_data *pdata;
int ret; int ret;
int i;
pdata = dev_get_platdata(&client->dev);
if (!pdata) {
dev_err(&client->dev, "missing platform data\n");
return -ENODEV;
}
tps6105x = devm_kmalloc(&client->dev, sizeof(*tps6105x), GFP_KERNEL); tps6105x = devm_kmalloc(&client->dev, sizeof(*tps6105x), GFP_KERNEL);
if (!tps6105x) if (!tps6105x)
...@@ -96,7 +116,6 @@ static int tps6105x_probe(struct i2c_client *client, ...@@ -96,7 +116,6 @@ static int tps6105x_probe(struct i2c_client *client,
i2c_set_clientdata(client, tps6105x); i2c_set_clientdata(client, tps6105x);
tps6105x->client = client; tps6105x->client = client;
pdata = dev_get_platdata(&client->dev);
tps6105x->pdata = pdata; tps6105x->pdata = pdata;
ret = tps6105x_startup(tps6105x); ret = tps6105x_startup(tps6105x);
...@@ -105,38 +124,33 @@ static int tps6105x_probe(struct i2c_client *client, ...@@ -105,38 +124,33 @@ static int tps6105x_probe(struct i2c_client *client,
return ret; return ret;
} }
/* Remove warning texts when you implement new cell drivers */ ret = tps6105x_add_device(tps6105x, &tps6105x_gpio_cell);
if (ret)
return ret;
switch (pdata->mode) { switch (pdata->mode) {
case TPS6105X_MODE_SHUTDOWN: case TPS6105X_MODE_SHUTDOWN:
dev_info(&client->dev, dev_info(&client->dev,
"present, not used for anything, only GPIO\n"); "present, not used for anything, only GPIO\n");
break; break;
case TPS6105X_MODE_TORCH: case TPS6105X_MODE_TORCH:
tps6105x_cells[0].name = "tps6105x-leds"; ret = tps6105x_add_device(tps6105x, &tps6105x_leds_cell);
dev_warn(&client->dev,
"torch mode is unsupported\n");
break; break;
case TPS6105X_MODE_TORCH_FLASH: case TPS6105X_MODE_TORCH_FLASH:
tps6105x_cells[0].name = "tps6105x-flash"; ret = tps6105x_add_device(tps6105x, &tps6105x_flash_cell);
dev_warn(&client->dev,
"flash mode is unsupported\n");
break; break;
case TPS6105X_MODE_VOLTAGE: case TPS6105X_MODE_VOLTAGE:
tps6105x_cells[0].name ="tps6105x-regulator"; ret = tps6105x_add_device(tps6105x, &tps6105x_regulator_cell);
break; break;
default: default:
dev_warn(&client->dev, "invalid mode: %d\n", pdata->mode);
break; break;
} }
/* Set up and register the platform devices. */ if (ret)
for (i = 0; i < ARRAY_SIZE(tps6105x_cells); i++) { mfd_remove_devices(&client->dev);
/* One state holder for all drivers, this is simple */
tps6105x_cells[i].platform_data = tps6105x;
tps6105x_cells[i].pdata_size = sizeof(*tps6105x);
}
return mfd_add_devices(&client->dev, 0, tps6105x_cells, return ret;
ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL);
} }
static int tps6105x_remove(struct i2c_client *client) static int tps6105x_remove(struct i2c_client *client)
......
...@@ -39,6 +39,10 @@ static const struct mfd_cell tps65217s[] = { ...@@ -39,6 +39,10 @@ static const struct mfd_cell tps65217s[] = {
.name = "tps65217-bl", .name = "tps65217-bl",
.of_compatible = "ti,tps65217-bl", .of_compatible = "ti,tps65217-bl",
}, },
{
.name = "tps65217-charger",
.of_compatible = "ti,tps65217-charger",
},
}; };
/** /**
......
...@@ -647,6 +647,8 @@ static int twl6040_probe(struct i2c_client *client, ...@@ -647,6 +647,8 @@ static int twl6040_probe(struct i2c_client *client,
twl6040->clk32k = devm_clk_get(&client->dev, "clk32k"); twl6040->clk32k = devm_clk_get(&client->dev, "clk32k");
if (IS_ERR(twl6040->clk32k)) { if (IS_ERR(twl6040->clk32k)) {
if (PTR_ERR(twl6040->clk32k) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_info(&client->dev, "clk32k is not handled\n"); dev_info(&client->dev, "clk32k is not handled\n");
twl6040->clk32k = NULL; twl6040->clk32k = NULL;
} }
......
...@@ -250,7 +250,7 @@ static const struct reg_sequence wm5110_revd_patch[] = { ...@@ -250,7 +250,7 @@ static const struct reg_sequence wm5110_revd_patch[] = {
}; };
/* Add extra headphone write sequence locations */ /* Add extra headphone write sequence locations */
static const struct reg_default wm5110_reve_patch[] = { static const struct reg_sequence wm5110_reve_patch[] = {
{ 0x80, 0x3 }, { 0x80, 0x3 },
{ 0x80, 0x3 }, { 0x80, 0x3 },
{ 0x4b, 0x138 }, { 0x4b, 0x138 },
...@@ -1633,6 +1633,185 @@ static const struct reg_default wm5110_reg_default[] = { ...@@ -1633,6 +1633,185 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x00000EF8, 0x0000 }, /* R3832 - ISRC 3 CTRL 3 */ { 0x00000EF8, 0x0000 }, /* R3832 - ISRC 3 CTRL 3 */
{ 0x00000F00, 0x0000 }, /* R3840 - Clock Control */ { 0x00000F00, 0x0000 }, /* R3840 - Clock Control */
{ 0x00000F01, 0x0000 }, /* R3841 - ANC_SRC */ { 0x00000F01, 0x0000 }, /* R3841 - ANC_SRC */
{ 0x00000F08, 0x001c }, /* R3848 - ANC Coefficient */
{ 0x00000F09, 0x0000 }, /* R3849 - ANC Coefficient */
{ 0x00000F0A, 0x0000 }, /* R3850 - ANC Coefficient */
{ 0x00000F0B, 0x0000 }, /* R3851 - ANC Coefficient */
{ 0x00000F0C, 0x0000 }, /* R3852 - ANC Coefficient */
{ 0x00000F0D, 0x0000 }, /* R3853 - ANC Coefficient */
{ 0x00000F0E, 0x0000 }, /* R3854 - ANC Coefficient */
{ 0x00000F0F, 0x0000 }, /* R3855 - ANC Coefficient */
{ 0x00000F10, 0x0000 }, /* R3856 - ANC Coefficient */
{ 0x00000F11, 0x0000 }, /* R3857 - ANC Coefficient */
{ 0x00000F12, 0x0000 }, /* R3858 - ANC Coefficient */
{ 0x00000F15, 0x0000 }, /* R3861 - FCL Filter Control */
{ 0x00000F17, 0x0004 }, /* R3863 - FCL ADC Reformatter Control */
{ 0x00000F18, 0x0004 }, /* R3864 - ANC Coefficient */
{ 0x00000F19, 0x0002 }, /* R3865 - ANC Coefficient */
{ 0x00000F1A, 0x0000 }, /* R3866 - ANC Coefficient */
{ 0x00000F1B, 0x0010 }, /* R3867 - ANC Coefficient */
{ 0x00000F1C, 0x0000 }, /* R3868 - ANC Coefficient */
{ 0x00000F1D, 0x0000 }, /* R3869 - ANC Coefficient */
{ 0x00000F1E, 0x0000 }, /* R3870 - ANC Coefficient */
{ 0x00000F1F, 0x0000 }, /* R3871 - ANC Coefficient */
{ 0x00000F20, 0x0000 }, /* R3872 - ANC Coefficient */
{ 0x00000F21, 0x0000 }, /* R3873 - ANC Coefficient */
{ 0x00000F22, 0x0000 }, /* R3874 - ANC Coefficient */
{ 0x00000F23, 0x0000 }, /* R3875 - ANC Coefficient */
{ 0x00000F24, 0x0000 }, /* R3876 - ANC Coefficient */
{ 0x00000F25, 0x0000 }, /* R3877 - ANC Coefficient */
{ 0x00000F26, 0x0000 }, /* R3878 - ANC Coefficient */
{ 0x00000F27, 0x0000 }, /* R3879 - ANC Coefficient */
{ 0x00000F28, 0x0000 }, /* R3880 - ANC Coefficient */
{ 0x00000F29, 0x0000 }, /* R3881 - ANC Coefficient */
{ 0x00000F2A, 0x0000 }, /* R3882 - ANC Coefficient */
{ 0x00000F2B, 0x0000 }, /* R3883 - ANC Coefficient */
{ 0x00000F2C, 0x0000 }, /* R3884 - ANC Coefficient */
{ 0x00000F2D, 0x0000 }, /* R3885 - ANC Coefficient */
{ 0x00000F2E, 0x0000 }, /* R3886 - ANC Coefficient */
{ 0x00000F2F, 0x0000 }, /* R3887 - ANC Coefficient */
{ 0x00000F30, 0x0000 }, /* R3888 - ANC Coefficient */
{ 0x00000F31, 0x0000 }, /* R3889 - ANC Coefficient */
{ 0x00000F32, 0x0000 }, /* R3890 - ANC Coefficient */
{ 0x00000F33, 0x0000 }, /* R3891 - ANC Coefficient */
{ 0x00000F34, 0x0000 }, /* R3892 - ANC Coefficient */
{ 0x00000F35, 0x0000 }, /* R3893 - ANC Coefficient */
{ 0x00000F36, 0x0000 }, /* R3894 - ANC Coefficient */
{ 0x00000F37, 0x0000 }, /* R3895 - ANC Coefficient */
{ 0x00000F38, 0x0000 }, /* R3896 - ANC Coefficient */
{ 0x00000F39, 0x0000 }, /* R3897 - ANC Coefficient */
{ 0x00000F3A, 0x0000 }, /* R3898 - ANC Coefficient */
{ 0x00000F3B, 0x0000 }, /* R3899 - ANC Coefficient */
{ 0x00000F3C, 0x0000 }, /* R3900 - ANC Coefficient */
{ 0x00000F3D, 0x0000 }, /* R3901 - ANC Coefficient */
{ 0x00000F3E, 0x0000 }, /* R3902 - ANC Coefficient */
{ 0x00000F3F, 0x0000 }, /* R3903 - ANC Coefficient */
{ 0x00000F40, 0x0000 }, /* R3904 - ANC Coefficient */
{ 0x00000F41, 0x0000 }, /* R3905 - ANC Coefficient */
{ 0x00000F42, 0x0000 }, /* R3906 - ANC Coefficient */
{ 0x00000F43, 0x0000 }, /* R3907 - ANC Coefficient */
{ 0x00000F44, 0x0000 }, /* R3908 - ANC Coefficient */
{ 0x00000F45, 0x0000 }, /* R3909 - ANC Coefficient */
{ 0x00000F46, 0x0000 }, /* R3910 - ANC Coefficient */
{ 0x00000F47, 0x0000 }, /* R3911 - ANC Coefficient */
{ 0x00000F48, 0x0000 }, /* R3912 - ANC Coefficient */
{ 0x00000F49, 0x0000 }, /* R3913 - ANC Coefficient */
{ 0x00000F4A, 0x0000 }, /* R3914 - ANC Coefficient */
{ 0x00000F4B, 0x0000 }, /* R3915 - ANC Coefficient */
{ 0x00000F4C, 0x0000 }, /* R3916 - ANC Coefficient */
{ 0x00000F4D, 0x0000 }, /* R3917 - ANC Coefficient */
{ 0x00000F4E, 0x0000 }, /* R3918 - ANC Coefficient */
{ 0x00000F4F, 0x0000 }, /* R3919 - ANC Coefficient */
{ 0x00000F50, 0x0000 }, /* R3920 - ANC Coefficient */
{ 0x00000F51, 0x0000 }, /* R3921 - ANC Coefficient */
{ 0x00000F52, 0x0000 }, /* R3922 - ANC Coefficient */
{ 0x00000F53, 0x0000 }, /* R3923 - ANC Coefficient */
{ 0x00000F54, 0x0000 }, /* R3924 - ANC Coefficient */
{ 0x00000F55, 0x0000 }, /* R3925 - ANC Coefficient */
{ 0x00000F56, 0x0000 }, /* R3926 - ANC Coefficient */
{ 0x00000F57, 0x0000 }, /* R3927 - ANC Coefficient */
{ 0x00000F58, 0x0000 }, /* R3928 - ANC Coefficient */
{ 0x00000F59, 0x0000 }, /* R3929 - ANC Coefficient */
{ 0x00000F5A, 0x0000 }, /* R3930 - ANC Coefficient */
{ 0x00000F5B, 0x0000 }, /* R3931 - ANC Coefficient */
{ 0x00000F5C, 0x0000 }, /* R3932 - ANC Coefficient */
{ 0x00000F5D, 0x0000 }, /* R3933 - ANC Coefficient */
{ 0x00000F5E, 0x0000 }, /* R3934 - ANC Coefficient */
{ 0x00000F5F, 0x0000 }, /* R3935 - ANC Coefficient */
{ 0x00000F60, 0x0000 }, /* R3936 - ANC Coefficient */
{ 0x00000F61, 0x0000 }, /* R3937 - ANC Coefficient */
{ 0x00000F62, 0x0000 }, /* R3938 - ANC Coefficient */
{ 0x00000F63, 0x0000 }, /* R3939 - ANC Coefficient */
{ 0x00000F64, 0x0000 }, /* R3940 - ANC Coefficient */
{ 0x00000F65, 0x0000 }, /* R3941 - ANC Coefficient */
{ 0x00000F66, 0x0000 }, /* R3942 - ANC Coefficient */
{ 0x00000F67, 0x0000 }, /* R3943 - ANC Coefficient */
{ 0x00000F68, 0x0000 }, /* R3944 - ANC Coefficient */
{ 0x00000F69, 0x0000 }, /* R3945 - ANC Coefficient */
{ 0x00000F70, 0x0000 }, /* R3952 - FCR Filter Control */
{ 0x00000F72, 0x0004 }, /* R3954 - FCR ADC Reformatter Control */
{ 0x00000F73, 0x0004 }, /* R3955 - ANC Coefficient */
{ 0x00000F74, 0x0002 }, /* R3956 - ANC Coefficient */
{ 0x00000F75, 0x0000 }, /* R3957 - ANC Coefficient */
{ 0x00000F76, 0x0010 }, /* R3958 - ANC Coefficient */
{ 0x00000F77, 0x0000 }, /* R3959 - ANC Coefficient */
{ 0x00000F78, 0x0000 }, /* R3960 - ANC Coefficient */
{ 0x00000F79, 0x0000 }, /* R3961 - ANC Coefficient */
{ 0x00000F7A, 0x0000 }, /* R3962 - ANC Coefficient */
{ 0x00000F7B, 0x0000 }, /* R3963 - ANC Coefficient */
{ 0x00000F7C, 0x0000 }, /* R3964 - ANC Coefficient */
{ 0x00000F7D, 0x0000 }, /* R3965 - ANC Coefficient */
{ 0x00000F7E, 0x0000 }, /* R3966 - ANC Coefficient */
{ 0x00000F7F, 0x0000 }, /* R3967 - ANC Coefficient */
{ 0x00000F80, 0x0000 }, /* R3968 - ANC Coefficient */
{ 0x00000F81, 0x0000 }, /* R3969 - ANC Coefficient */
{ 0x00000F82, 0x0000 }, /* R3970 - ANC Coefficient */
{ 0x00000F83, 0x0000 }, /* R3971 - ANC Coefficient */
{ 0x00000F84, 0x0000 }, /* R3972 - ANC Coefficient */
{ 0x00000F85, 0x0000 }, /* R3973 - ANC Coefficient */
{ 0x00000F86, 0x0000 }, /* R3974 - ANC Coefficient */
{ 0x00000F87, 0x0000 }, /* R3975 - ANC Coefficient */
{ 0x00000F88, 0x0000 }, /* R3976 - ANC Coefficient */
{ 0x00000F89, 0x0000 }, /* R3977 - ANC Coefficient */
{ 0x00000F8A, 0x0000 }, /* R3978 - ANC Coefficient */
{ 0x00000F8B, 0x0000 }, /* R3979 - ANC Coefficient */
{ 0x00000F8C, 0x0000 }, /* R3980 - ANC Coefficient */
{ 0x00000F8D, 0x0000 }, /* R3981 - ANC Coefficient */
{ 0x00000F8E, 0x0000 }, /* R3982 - ANC Coefficient */
{ 0x00000F8F, 0x0000 }, /* R3983 - ANC Coefficient */
{ 0x00000F90, 0x0000 }, /* R3984 - ANC Coefficient */
{ 0x00000F91, 0x0000 }, /* R3985 - ANC Coefficient */
{ 0x00000F92, 0x0000 }, /* R3986 - ANC Coefficient */
{ 0x00000F93, 0x0000 }, /* R3987 - ANC Coefficient */
{ 0x00000F94, 0x0000 }, /* R3988 - ANC Coefficient */
{ 0x00000F95, 0x0000 }, /* R3989 - ANC Coefficient */
{ 0x00000F96, 0x0000 }, /* R3990 - ANC Coefficient */
{ 0x00000F97, 0x0000 }, /* R3991 - ANC Coefficient */
{ 0x00000F98, 0x0000 }, /* R3992 - ANC Coefficient */
{ 0x00000F99, 0x0000 }, /* R3993 - ANC Coefficient */
{ 0x00000F9A, 0x0000 }, /* R3994 - ANC Coefficient */
{ 0x00000F9B, 0x0000 }, /* R3995 - ANC Coefficient */
{ 0x00000F9C, 0x0000 }, /* R3996 - ANC Coefficient */
{ 0x00000F9D, 0x0000 }, /* R3997 - ANC Coefficient */
{ 0x00000F9E, 0x0000 }, /* R3998 - ANC Coefficient */
{ 0x00000F9F, 0x0000 }, /* R3999 - ANC Coefficient */
{ 0x00000FA0, 0x0000 }, /* R4000 - ANC Coefficient */
{ 0x00000FA1, 0x0000 }, /* R4001 - ANC Coefficient */
{ 0x00000FA2, 0x0000 }, /* R4002 - ANC Coefficient */
{ 0x00000FA3, 0x0000 }, /* R4003 - ANC Coefficient */
{ 0x00000FA4, 0x0000 }, /* R4004 - ANC Coefficient */
{ 0x00000FA5, 0x0000 }, /* R4005 - ANC Coefficient */
{ 0x00000FA6, 0x0000 }, /* R4006 - ANC Coefficient */
{ 0x00000FA7, 0x0000 }, /* R4007 - ANC Coefficient */
{ 0x00000FA8, 0x0000 }, /* R4008 - ANC Coefficient */
{ 0x00000FA9, 0x0000 }, /* R4009 - ANC Coefficient */
{ 0x00000FAA, 0x0000 }, /* R4010 - ANC Coefficient */
{ 0x00000FAB, 0x0000 }, /* R4011 - ANC Coefficient */
{ 0x00000FAC, 0x0000 }, /* R4012 - ANC Coefficient */
{ 0x00000FAD, 0x0000 }, /* R4013 - ANC Coefficient */
{ 0x00000FAE, 0x0000 }, /* R4014 - ANC Coefficient */
{ 0x00000FAF, 0x0000 }, /* R4015 - ANC Coefficient */
{ 0x00000FB0, 0x0000 }, /* R4016 - ANC Coefficient */
{ 0x00000FB1, 0x0000 }, /* R4017 - ANC Coefficient */
{ 0x00000FB2, 0x0000 }, /* R4018 - ANC Coefficient */
{ 0x00000FB3, 0x0000 }, /* R4019 - ANC Coefficient */
{ 0x00000FB4, 0x0000 }, /* R4020 - ANC Coefficient */
{ 0x00000FB5, 0x0000 }, /* R4021 - ANC Coefficient */
{ 0x00000FB6, 0x0000 }, /* R4022 - ANC Coefficient */
{ 0x00000FB7, 0x0000 }, /* R4023 - ANC Coefficient */
{ 0x00000FB8, 0x0000 }, /* R4024 - ANC Coefficient */
{ 0x00000FB9, 0x0000 }, /* R4025 - ANC Coefficient */
{ 0x00000FBA, 0x0000 }, /* R4026 - ANC Coefficient */
{ 0x00000FBB, 0x0000 }, /* R4027 - ANC Coefficient */
{ 0x00000FBC, 0x0000 }, /* R4028 - ANC Coefficient */
{ 0x00000FBD, 0x0000 }, /* R4029 - ANC Coefficient */
{ 0x00000FBE, 0x0000 }, /* R4030 - ANC Coefficient */
{ 0x00000FBF, 0x0000 }, /* R4031 - ANC Coefficient */
{ 0x00000FC0, 0x0000 }, /* R4032 - ANC Coefficient */
{ 0x00000FC1, 0x0000 }, /* R4033 - ANC Coefficient */
{ 0x00000FC2, 0x0000 }, /* R4034 - ANC Coefficient */
{ 0x00000FC3, 0x0000 }, /* R4035 - ANC Coefficient */
{ 0x00000FC4, 0x0000 }, /* R4036 - ANC Coefficient */
{ 0x00001100, 0x0010 }, /* R4352 - DSP1 Control 1 */ { 0x00001100, 0x0010 }, /* R4352 - DSP1 Control 1 */
{ 0x00001200, 0x0010 }, /* R4608 - DSP2 Control 1 */ { 0x00001200, 0x0010 }, /* R4608 - DSP2 Control 1 */
{ 0x00001300, 0x0010 }, /* R4864 - DSP3 Control 1 */ { 0x00001300, 0x0010 }, /* R4864 - DSP3 Control 1 */
...@@ -2710,6 +2889,13 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) ...@@ -2710,6 +2889,13 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_CLOCK_CONTROL: case ARIZONA_CLOCK_CONTROL:
case ARIZONA_ANC_SRC: case ARIZONA_ANC_SRC:
case ARIZONA_DSP_STATUS: case ARIZONA_DSP_STATUS:
case ARIZONA_ANC_COEFF_START ... ARIZONA_ANC_COEFF_END:
case ARIZONA_FCL_FILTER_CONTROL:
case ARIZONA_FCL_ADC_REFORMATTER_CONTROL:
case ARIZONA_FCL_COEFF_START ... ARIZONA_FCL_COEFF_END:
case ARIZONA_FCR_FILTER_CONTROL:
case ARIZONA_FCR_ADC_REFORMATTER_CONTROL:
case ARIZONA_FCR_COEFF_START ... ARIZONA_FCR_COEFF_END:
case ARIZONA_DSP1_CONTROL_1: case ARIZONA_DSP1_CONTROL_1:
case ARIZONA_DSP1_CLOCKING_1: case ARIZONA_DSP1_CLOCKING_1:
case ARIZONA_DSP1_STATUS_1: case ARIZONA_DSP1_STATUS_1:
......
...@@ -1626,7 +1626,9 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ...@@ -1626,7 +1626,9 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
mutex_init(&wm831x->io_lock); mutex_init(&wm831x->io_lock);
mutex_init(&wm831x->key_lock); mutex_init(&wm831x->key_lock);
dev_set_drvdata(wm831x->dev, wm831x); dev_set_drvdata(wm831x->dev, wm831x);
wm831x->soft_shutdown = pdata->soft_shutdown;
if (pdata)
wm831x->soft_shutdown = pdata->soft_shutdown;
ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID); ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
if (ret < 0) { if (ret < 0) {
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#define WM8998_NUM_AOD_ISR 2 #define WM8998_NUM_AOD_ISR 2
#define WM8998_NUM_ISR 5 #define WM8998_NUM_ISR 5
static const struct reg_default wm8998_rev_a_patch[] = { static const struct reg_sequence wm8998_rev_a_patch[] = {
{ 0x0212, 0x0000 }, { 0x0212, 0x0000 },
{ 0x0211, 0x0014 }, { 0x0211, 0x0014 },
{ 0x04E4, 0x0E0D }, { 0x04E4, 0x0E0D },
...@@ -199,8 +199,6 @@ static const struct reg_default wm8998_reg_default[] = { ...@@ -199,8 +199,6 @@ static const struct reg_default wm8998_reg_default[] = {
{ 0x00000069, 0x01FF }, /* R105 - Always On Triggers Sequence Select 4 */ { 0x00000069, 0x01FF }, /* R105 - Always On Triggers Sequence Select 4 */
{ 0x0000006A, 0x01FF }, /* R106 - Always On Triggers Sequence Select 5 */ { 0x0000006A, 0x01FF }, /* R106 - Always On Triggers Sequence Select 5 */
{ 0x0000006B, 0x01FF }, /* R107 - Always On Triggers Sequence Select 6 */ { 0x0000006B, 0x01FF }, /* R107 - Always On Triggers Sequence Select 6 */
{ 0x0000006E, 0x01FF }, /* R110 - Trigger Sequence Select 32 */
{ 0x0000006F, 0x01FF }, /* R111 - Trigger Sequence Select 33 */
{ 0x00000090, 0x0000 }, /* R144 - Haptics Control 1 */ { 0x00000090, 0x0000 }, /* R144 - Haptics Control 1 */
{ 0x00000091, 0x7FFF }, /* R145 - Haptics Control 2 */ { 0x00000091, 0x7FFF }, /* R145 - Haptics Control 2 */
{ 0x00000092, 0x0000 }, /* R146 - Haptics phase 1 intensity */ { 0x00000092, 0x0000 }, /* R146 - Haptics phase 1 intensity */
...@@ -270,16 +268,13 @@ static const struct reg_default wm8998_reg_default[] = { ...@@ -270,16 +268,13 @@ static const struct reg_default wm8998_reg_default[] = {
{ 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */ { 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */
{ 0x00000293, 0x0080 }, /* R659 - Accessory Detect Mode 1 */ { 0x00000293, 0x0080 }, /* R659 - Accessory Detect Mode 1 */
{ 0x0000029B, 0x0000 }, /* R667 - Headphone Detect 1 */ { 0x0000029B, 0x0000 }, /* R667 - Headphone Detect 1 */
{ 0x0000029C, 0x0000 }, /* R668 - Headphone Detect 2 */
{ 0x000002A2, 0x0000 }, /* R674 - Micd Clamp control */ { 0x000002A2, 0x0000 }, /* R674 - Micd Clamp control */
{ 0x000002A3, 0x1102 }, /* R675 - Mic Detect 1 */ { 0x000002A3, 0x1102 }, /* R675 - Mic Detect 1 */
{ 0x000002A4, 0x009F }, /* R676 - Mic Detect 2 */ { 0x000002A4, 0x009F }, /* R676 - Mic Detect 2 */
{ 0x000002A5, 0x0000 }, /* R677 - Mic Detect 3 */
{ 0x000002A6, 0x3737 }, /* R678 - Mic Detect Level 1 */ { 0x000002A6, 0x3737 }, /* R678 - Mic Detect Level 1 */
{ 0x000002A7, 0x2C37 }, /* R679 - Mic Detect Level 2 */ { 0x000002A7, 0x2C37 }, /* R679 - Mic Detect Level 2 */
{ 0x000002A8, 0x1422 }, /* R680 - Mic Detect Level 3 */ { 0x000002A8, 0x1422 }, /* R680 - Mic Detect Level 3 */
{ 0x000002A9, 0x030A }, /* R681 - Mic Detect Level 4 */ { 0x000002A9, 0x030A }, /* R681 - Mic Detect Level 4 */
{ 0x000002AB, 0x0000 }, /* R683 - Mic Detect 4 */
{ 0x000002CB, 0x0000 }, /* R715 - Isolation control */ { 0x000002CB, 0x0000 }, /* R715 - Isolation control */
{ 0x000002D3, 0x0000 }, /* R723 - Jack detect analogue */ { 0x000002D3, 0x0000 }, /* R723 - Jack detect analogue */
{ 0x00000300, 0x0000 }, /* R768 - Input Enables */ { 0x00000300, 0x0000 }, /* R768 - Input Enables */
...@@ -707,13 +702,11 @@ static const struct reg_default wm8998_reg_default[] = { ...@@ -707,13 +702,11 @@ static const struct reg_default wm8998_reg_default[] = {
{ 0x00000D1A, 0xFFFF }, /* R3354 - IRQ2 Status 3 Mask */ { 0x00000D1A, 0xFFFF }, /* R3354 - IRQ2 Status 3 Mask */
{ 0x00000D1B, 0xFFFF }, /* R3355 - IRQ2 Status 4 Mask */ { 0x00000D1B, 0xFFFF }, /* R3355 - IRQ2 Status 4 Mask */
{ 0x00000D1C, 0xFEFF }, /* R3356 - IRQ2 Status 5 Mask */ { 0x00000D1C, 0xFEFF }, /* R3356 - IRQ2 Status 5 Mask */
{ 0x00000D1D, 0xFFFF }, /* R3357 - IRQ2 Status 6 Mask */
{ 0x00000D1F, 0x0000 }, /* R3359 - IRQ2 Control */ { 0x00000D1F, 0x0000 }, /* R3359 - IRQ2 Control */
{ 0x00000D53, 0xFFFF }, /* R3411 - AOD IRQ Mask IRQ1 */ { 0x00000D53, 0xFFFF }, /* R3411 - AOD IRQ Mask IRQ1 */
{ 0x00000D54, 0xFFFF }, /* R3412 - AOD IRQ Mask IRQ2 */ { 0x00000D54, 0xFFFF }, /* R3412 - AOD IRQ Mask IRQ2 */
{ 0x00000D56, 0x0000 }, /* R3414 - Jack detect debounce */ { 0x00000D56, 0x0000 }, /* R3414 - Jack detect debounce */
{ 0x00000E00, 0x0000 }, /* R3584 - FX_Ctrl1 */ { 0x00000E00, 0x0000 }, /* R3584 - FX_Ctrl1 */
{ 0x00000E01, 0x0000 }, /* R3585 - FX_Ctrl2 */
{ 0x00000E10, 0x6318 }, /* R3600 - EQ1_1 */ { 0x00000E10, 0x6318 }, /* R3600 - EQ1_1 */
{ 0x00000E11, 0x6300 }, /* R3601 - EQ1_2 */ { 0x00000E11, 0x6300 }, /* R3601 - EQ1_2 */
{ 0x00000E12, 0x0FC8 }, /* R3602 - EQ1_3 */ { 0x00000E12, 0x0FC8 }, /* R3602 - EQ1_3 */
...@@ -833,7 +826,6 @@ static bool wm8998_readable_register(struct device *dev, unsigned int reg) ...@@ -833,7 +826,6 @@ static bool wm8998_readable_register(struct device *dev, unsigned int reg)
switch (reg) { switch (reg) {
case ARIZONA_SOFTWARE_RESET: case ARIZONA_SOFTWARE_RESET:
case ARIZONA_DEVICE_REVISION: case ARIZONA_DEVICE_REVISION:
case ARIZONA_CTRL_IF_SPI_CFG_1:
case ARIZONA_CTRL_IF_I2C1_CFG_1: case ARIZONA_CTRL_IF_I2C1_CFG_1:
case ARIZONA_CTRL_IF_I2C1_CFG_2: case ARIZONA_CTRL_IF_I2C1_CFG_2:
case ARIZONA_WRITE_SEQUENCER_CTRL_0: case ARIZONA_WRITE_SEQUENCER_CTRL_0:
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/acpi.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/platform_data/at24.h> #include <linux/platform_data/at24.h>
...@@ -131,6 +132,12 @@ static const struct i2c_device_id at24_ids[] = { ...@@ -131,6 +132,12 @@ static const struct i2c_device_id at24_ids[] = {
}; };
MODULE_DEVICE_TABLE(i2c, at24_ids); MODULE_DEVICE_TABLE(i2c, at24_ids);
static const struct acpi_device_id at24_acpi_ids[] = {
{ "INT3499", AT24_DEVICE_MAGIC(8192 / 8, 0) },
{ }
};
MODULE_DEVICE_TABLE(acpi, at24_acpi_ids);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* /*
...@@ -467,21 +474,29 @@ static void at24_get_ofdata(struct i2c_client *client, ...@@ -467,21 +474,29 @@ static void at24_get_ofdata(struct i2c_client *client,
static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
{ {
struct at24_platform_data chip; struct at24_platform_data chip;
kernel_ulong_t magic = 0;
bool writable; bool writable;
int use_smbus = 0; int use_smbus = 0;
int use_smbus_write = 0; int use_smbus_write = 0;
struct at24_data *at24; struct at24_data *at24;
int err; int err;
unsigned i, num_addresses; unsigned i, num_addresses;
kernel_ulong_t magic;
if (client->dev.platform_data) { if (client->dev.platform_data) {
chip = *(struct at24_platform_data *)client->dev.platform_data; chip = *(struct at24_platform_data *)client->dev.platform_data;
} else { } else {
if (!id->driver_data) if (id) {
magic = id->driver_data;
} else {
const struct acpi_device_id *aid;
aid = acpi_match_device(at24_acpi_ids, &client->dev);
if (aid)
magic = aid->driver_data;
}
if (!magic)
return -ENODEV; return -ENODEV;
magic = id->driver_data;
chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN));
magic >>= AT24_SIZE_BYTELEN; magic >>= AT24_SIZE_BYTELEN;
chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS); chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS);
...@@ -661,6 +676,7 @@ static int at24_remove(struct i2c_client *client) ...@@ -661,6 +676,7 @@ static int at24_remove(struct i2c_client *client)
static struct i2c_driver at24_driver = { static struct i2c_driver at24_driver = {
.driver = { .driver = {
.name = "at24", .name = "at24",
.acpi_match_table = ACPI_PTR(at24_acpi_ids),
}, },
.probe = at24_probe, .probe = at24_probe,
.remove = at24_remove, .remove = at24_remove,
......
...@@ -932,6 +932,7 @@ config PVPANIC ...@@ -932,6 +932,7 @@ config PVPANIC
config INTEL_PMC_IPC config INTEL_PMC_IPC
tristate "Intel PMC IPC Driver" tristate "Intel PMC IPC Driver"
depends on ACPI
---help--- ---help---
This driver provides support for PMC control on some Intel platforms. This driver provides support for PMC control on some Intel platforms.
The PMC is an ARC processor which defines IPC commands for communication The PMC is an ARC processor which defines IPC commands for communication
......
...@@ -203,6 +203,16 @@ config CHARGER_DA9150 ...@@ -203,6 +203,16 @@ config CHARGER_DA9150
This driver can also be built as a module. If so, the module will be This driver can also be built as a module. If so, the module will be
called da9150-charger. called da9150-charger.
config BATTERY_DA9150
tristate "Dialog Semiconductor DA9150 Fuel Gauge support"
depends on MFD_DA9150
help
Say Y here to enable support for the Fuel-Gauge unit of the DA9150
Integrated Charger & Fuel-Gauge IC
This driver can also be built as a module. If so, the module will be
called da9150-fg.
config AXP288_CHARGER config AXP288_CHARGER
tristate "X-Powers AXP288 Charger" tristate "X-Powers AXP288 Charger"
depends on MFD_AXP20X && EXTCON_AXP288 depends on MFD_AXP20X && EXTCON_AXP288
......
...@@ -34,6 +34,7 @@ obj-$(CONFIG_BATTERY_BQ27XXX) += bq27xxx_battery.o ...@@ -34,6 +34,7 @@ obj-$(CONFIG_BATTERY_BQ27XXX) += bq27xxx_battery.o
obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o
obj-$(CONFIG_CHARGER_DA9150) += da9150-charger.o obj-$(CONFIG_CHARGER_DA9150) += da9150-charger.o
obj-$(CONFIG_BATTERY_DA9150) += da9150-fg.o
obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o
obj-$(CONFIG_BATTERY_Z2) += z2_battery.o obj-$(CONFIG_BATTERY_Z2) += z2_battery.o
......
/*
* DA9150 Fuel-Gauge Driver
*
* Copyright (c) 2015 Dialog Semiconductor
*
* Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/power_supply.h>
#include <linux/list.h>
#include <asm/div64.h>
#include <linux/mfd/da9150/core.h>
#include <linux/mfd/da9150/registers.h>
/* Core2Wire */
#define DA9150_QIF_READ (0x0 << 7)
#define DA9150_QIF_WRITE (0x1 << 7)
#define DA9150_QIF_CODE_MASK 0x7F
#define DA9150_QIF_BYTE_SIZE 8
#define DA9150_QIF_BYTE_MASK 0xFF
#define DA9150_QIF_SHORT_SIZE 2
#define DA9150_QIF_LONG_SIZE 4
/* QIF Codes */
#define DA9150_QIF_UAVG 6
#define DA9150_QIF_UAVG_SIZE DA9150_QIF_LONG_SIZE
#define DA9150_QIF_IAVG 8
#define DA9150_QIF_IAVG_SIZE DA9150_QIF_LONG_SIZE
#define DA9150_QIF_NTCAVG 12
#define DA9150_QIF_NTCAVG_SIZE DA9150_QIF_LONG_SIZE
#define DA9150_QIF_SHUNT_VAL 36
#define DA9150_QIF_SHUNT_VAL_SIZE DA9150_QIF_SHORT_SIZE
#define DA9150_QIF_SD_GAIN 38
#define DA9150_QIF_SD_GAIN_SIZE DA9150_QIF_LONG_SIZE
#define DA9150_QIF_FCC_MAH 40
#define DA9150_QIF_FCC_MAH_SIZE DA9150_QIF_SHORT_SIZE
#define DA9150_QIF_SOC_PCT 43
#define DA9150_QIF_SOC_PCT_SIZE DA9150_QIF_SHORT_SIZE
#define DA9150_QIF_CHARGE_LIMIT 44
#define DA9150_QIF_CHARGE_LIMIT_SIZE DA9150_QIF_SHORT_SIZE
#define DA9150_QIF_DISCHARGE_LIMIT 45
#define DA9150_QIF_DISCHARGE_LIMIT_SIZE DA9150_QIF_SHORT_SIZE
#define DA9150_QIF_FW_MAIN_VER 118
#define DA9150_QIF_FW_MAIN_VER_SIZE DA9150_QIF_SHORT_SIZE
#define DA9150_QIF_E_FG_STATUS 126
#define DA9150_QIF_E_FG_STATUS_SIZE DA9150_QIF_SHORT_SIZE
#define DA9150_QIF_SYNC 127
#define DA9150_QIF_SYNC_SIZE DA9150_QIF_SHORT_SIZE
#define DA9150_QIF_MAX_CODES 128
/* QIF Sync Timeout */
#define DA9150_QIF_SYNC_TIMEOUT 1000
#define DA9150_QIF_SYNC_RETRIES 10
/* QIF E_FG_STATUS */
#define DA9150_FG_IRQ_LOW_SOC_MASK (1 << 0)
#define DA9150_FG_IRQ_HIGH_SOC_MASK (1 << 1)
#define DA9150_FG_IRQ_SOC_MASK \
(DA9150_FG_IRQ_LOW_SOC_MASK | DA9150_FG_IRQ_HIGH_SOC_MASK)
/* Private data */
struct da9150_fg {
struct da9150 *da9150;
struct device *dev;
struct mutex io_lock;
struct power_supply *battery;
struct delayed_work work;
u32 interval;
int warn_soc;
int crit_soc;
int soc;
};
/* Battery Properties */
static u32 da9150_fg_read_attr(struct da9150_fg *fg, u8 code, u8 size)
{
u8 buf[size];
u8 read_addr;
u32 res = 0;
int i;
/* Set QIF code (READ mode) */
read_addr = (code & DA9150_QIF_CODE_MASK) | DA9150_QIF_READ;
da9150_read_qif(fg->da9150, read_addr, size, buf);
for (i = 0; i < size; ++i)
res |= (buf[i] << (i * DA9150_QIF_BYTE_SIZE));
return res;
}
static void da9150_fg_write_attr(struct da9150_fg *fg, u8 code, u8 size,
u32 val)
{
u8 buf[size];
u8 write_addr;
int i;
/* Set QIF code (WRITE mode) */
write_addr = (code & DA9150_QIF_CODE_MASK) | DA9150_QIF_WRITE;
for (i = 0; i < size; ++i) {
buf[i] = (val >> (i * DA9150_QIF_BYTE_SIZE)) &
DA9150_QIF_BYTE_MASK;
}
da9150_write_qif(fg->da9150, write_addr, size, buf);
}
/* Trigger QIF Sync to update QIF readable data */
static void da9150_fg_read_sync_start(struct da9150_fg *fg)
{
int i = 0;
u32 res = 0;
mutex_lock(&fg->io_lock);
/* Check if QIF sync already requested, and write to sync if not */
res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
DA9150_QIF_SYNC_SIZE);
if (res > 0)
da9150_fg_write_attr(fg, DA9150_QIF_SYNC,
DA9150_QIF_SYNC_SIZE, 0);
/* Wait for sync to complete */
res = 0;
while ((res == 0) && (i++ < DA9150_QIF_SYNC_RETRIES)) {
usleep_range(DA9150_QIF_SYNC_TIMEOUT,
DA9150_QIF_SYNC_TIMEOUT * 2);
res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
DA9150_QIF_SYNC_SIZE);
}
/* Check if sync completed */
if (res == 0)
dev_err(fg->dev, "Failed to perform QIF read sync!\n");
}
/*
* Should always be called after QIF sync read has been performed, and all
* attributes required have been accessed.
*/
static inline void da9150_fg_read_sync_end(struct da9150_fg *fg)
{
mutex_unlock(&fg->io_lock);
}
/* Sync read of single QIF attribute */
static u32 da9150_fg_read_attr_sync(struct da9150_fg *fg, u8 code, u8 size)
{
u32 val;
da9150_fg_read_sync_start(fg);
val = da9150_fg_read_attr(fg, code, size);
da9150_fg_read_sync_end(fg);
return val;
}
/* Wait for QIF Sync, write QIF data and wait for ack */
static void da9150_fg_write_attr_sync(struct da9150_fg *fg, u8 code, u8 size,
u32 val)
{
int i = 0;
u32 res = 0, sync_val;
mutex_lock(&fg->io_lock);
/* Check if QIF sync already requested */
res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
DA9150_QIF_SYNC_SIZE);
/* Wait for an existing sync to complete */
while ((res == 0) && (i++ < DA9150_QIF_SYNC_RETRIES)) {
usleep_range(DA9150_QIF_SYNC_TIMEOUT,
DA9150_QIF_SYNC_TIMEOUT * 2);
res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
DA9150_QIF_SYNC_SIZE);
}
if (res == 0) {
dev_err(fg->dev, "Timeout waiting for existing QIF sync!\n");
mutex_unlock(&fg->io_lock);
return;
}
/* Write value for QIF code */
da9150_fg_write_attr(fg, code, size, val);
/* Wait for write acknowledgment */
i = 0;
sync_val = res;
while ((res == sync_val) && (i++ < DA9150_QIF_SYNC_RETRIES)) {
usleep_range(DA9150_QIF_SYNC_TIMEOUT,
DA9150_QIF_SYNC_TIMEOUT * 2);
res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
DA9150_QIF_SYNC_SIZE);
}
mutex_unlock(&fg->io_lock);
/* Check write was actually successful */
if (res != (sync_val + 1))
dev_err(fg->dev, "Error performing QIF sync write for code %d\n",
code);
}
/* Power Supply attributes */
static int da9150_fg_capacity(struct da9150_fg *fg,
union power_supply_propval *val)
{
val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_SOC_PCT,
DA9150_QIF_SOC_PCT_SIZE);
if (val->intval > 100)
val->intval = 100;
return 0;
}
static int da9150_fg_current_avg(struct da9150_fg *fg,
union power_supply_propval *val)
{
u32 iavg, sd_gain, shunt_val;
u64 div, res;
da9150_fg_read_sync_start(fg);
iavg = da9150_fg_read_attr(fg, DA9150_QIF_IAVG,
DA9150_QIF_IAVG_SIZE);
shunt_val = da9150_fg_read_attr(fg, DA9150_QIF_SHUNT_VAL,
DA9150_QIF_SHUNT_VAL_SIZE);
sd_gain = da9150_fg_read_attr(fg, DA9150_QIF_SD_GAIN,
DA9150_QIF_SD_GAIN_SIZE);
da9150_fg_read_sync_end(fg);
div = (u64) (sd_gain * shunt_val * 65536ULL);
do_div(div, 1000000);
res = (u64) (iavg * 1000000ULL);
do_div(res, div);
val->intval = (int) res;
return 0;
}
static int da9150_fg_voltage_avg(struct da9150_fg *fg,
union power_supply_propval *val)
{
u64 res;
val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_UAVG,
DA9150_QIF_UAVG_SIZE);
res = (u64) (val->intval * 186ULL);
do_div(res, 10000);
val->intval = (int) res;
return 0;
}
static int da9150_fg_charge_full(struct da9150_fg *fg,
union power_supply_propval *val)
{
val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_FCC_MAH,
DA9150_QIF_FCC_MAH_SIZE);
val->intval = val->intval * 1000;
return 0;
}
/*
* Temperature reading from device is only valid if battery/system provides
* valid NTC to associated pin of DA9150 chip.
*/
static int da9150_fg_temp(struct da9150_fg *fg,
union power_supply_propval *val)
{
val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_NTCAVG,
DA9150_QIF_NTCAVG_SIZE);
val->intval = (val->intval * 10) / 1048576;
return 0;
}
static enum power_supply_property da9150_fg_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CURRENT_AVG,
POWER_SUPPLY_PROP_VOLTAGE_AVG,
POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_TEMP,
};
static int da9150_fg_get_prop(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
struct da9150_fg *fg = dev_get_drvdata(psy->dev.parent);
int ret;
switch (psp) {
case POWER_SUPPLY_PROP_CAPACITY:
ret = da9150_fg_capacity(fg, val);
break;
case POWER_SUPPLY_PROP_CURRENT_AVG:
ret = da9150_fg_current_avg(fg, val);
break;
case POWER_SUPPLY_PROP_VOLTAGE_AVG:
ret = da9150_fg_voltage_avg(fg, val);
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
ret = da9150_fg_charge_full(fg, val);
break;
case POWER_SUPPLY_PROP_TEMP:
ret = da9150_fg_temp(fg, val);
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
/* Repeated SOC check */
static bool da9150_fg_soc_changed(struct da9150_fg *fg)
{
union power_supply_propval val;
da9150_fg_capacity(fg, &val);
if (val.intval != fg->soc) {
fg->soc = val.intval;
return true;
}
return false;
}
static void da9150_fg_work(struct work_struct *work)
{
struct da9150_fg *fg = container_of(work, struct da9150_fg, work.work);
/* Report if SOC has changed */
if (da9150_fg_soc_changed(fg))
power_supply_changed(fg->battery);
schedule_delayed_work(&fg->work, msecs_to_jiffies(fg->interval));
}
/* SOC level event configuration */
static void da9150_fg_soc_event_config(struct da9150_fg *fg)
{
int soc;
soc = da9150_fg_read_attr_sync(fg, DA9150_QIF_SOC_PCT,
DA9150_QIF_SOC_PCT_SIZE);
if (soc > fg->warn_soc) {
/* If SOC > warn level, set discharge warn level event */
da9150_fg_write_attr_sync(fg, DA9150_QIF_DISCHARGE_LIMIT,
DA9150_QIF_DISCHARGE_LIMIT_SIZE,
fg->warn_soc + 1);
} else if ((soc <= fg->warn_soc) && (soc > fg->crit_soc)) {
/*
* If SOC <= warn level, set discharge crit level event,
* and set charge warn level event.
*/
da9150_fg_write_attr_sync(fg, DA9150_QIF_DISCHARGE_LIMIT,
DA9150_QIF_DISCHARGE_LIMIT_SIZE,
fg->crit_soc + 1);
da9150_fg_write_attr_sync(fg, DA9150_QIF_CHARGE_LIMIT,
DA9150_QIF_CHARGE_LIMIT_SIZE,
fg->warn_soc);
} else if (soc <= fg->crit_soc) {
/* If SOC <= crit level, set charge crit level event */
da9150_fg_write_attr_sync(fg, DA9150_QIF_CHARGE_LIMIT,
DA9150_QIF_CHARGE_LIMIT_SIZE,
fg->crit_soc);
}
}
static irqreturn_t da9150_fg_irq(int irq, void *data)
{
struct da9150_fg *fg = data;
u32 e_fg_status;
/* Read FG IRQ status info */
e_fg_status = da9150_fg_read_attr(fg, DA9150_QIF_E_FG_STATUS,
DA9150_QIF_E_FG_STATUS_SIZE);
/* Handle warning/critical threhold events */
if (e_fg_status & DA9150_FG_IRQ_SOC_MASK)
da9150_fg_soc_event_config(fg);
/* Clear any FG IRQs */
da9150_fg_write_attr(fg, DA9150_QIF_E_FG_STATUS,
DA9150_QIF_E_FG_STATUS_SIZE, e_fg_status);
return IRQ_HANDLED;
}
static struct da9150_fg_pdata *da9150_fg_dt_pdata(struct device *dev)
{
struct device_node *fg_node = dev->of_node;
struct da9150_fg_pdata *pdata;
pdata = devm_kzalloc(dev, sizeof(struct da9150_fg_pdata), GFP_KERNEL);
if (!pdata)
return NULL;
of_property_read_u32(fg_node, "dlg,update-interval",
&pdata->update_interval);
of_property_read_u8(fg_node, "dlg,warn-soc-level",
&pdata->warn_soc_lvl);
of_property_read_u8(fg_node, "dlg,crit-soc-level",
&pdata->crit_soc_lvl);
return pdata;
}
static const struct power_supply_desc fg_desc = {
.name = "da9150-fg",
.type = POWER_SUPPLY_TYPE_BATTERY,
.properties = da9150_fg_props,
.num_properties = ARRAY_SIZE(da9150_fg_props),
.get_property = da9150_fg_get_prop,
};
static int da9150_fg_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct da9150 *da9150 = dev_get_drvdata(dev->parent);
struct da9150_fg_pdata *fg_pdata = dev_get_platdata(dev);
struct da9150_fg *fg;
int ver, irq, ret = 0;
fg = devm_kzalloc(dev, sizeof(*fg), GFP_KERNEL);
if (fg == NULL)
return -ENOMEM;
platform_set_drvdata(pdev, fg);
fg->da9150 = da9150;
fg->dev = dev;
mutex_init(&fg->io_lock);
/* Enable QIF */
da9150_set_bits(da9150, DA9150_CORE2WIRE_CTRL_A, DA9150_FG_QIF_EN_MASK,
DA9150_FG_QIF_EN_MASK);
fg->battery = devm_power_supply_register(dev, &fg_desc, NULL);
if (IS_ERR(fg->battery)) {
ret = PTR_ERR(fg->battery);
return ret;
}
ver = da9150_fg_read_attr(fg, DA9150_QIF_FW_MAIN_VER,
DA9150_QIF_FW_MAIN_VER_SIZE);
dev_info(dev, "Version: 0x%x\n", ver);
/* Handle DT data if provided */
if (dev->of_node) {
fg_pdata = da9150_fg_dt_pdata(dev);
dev->platform_data = fg_pdata;
}
/* Handle any pdata provided */
if (fg_pdata) {
fg->interval = fg_pdata->update_interval;
if (fg_pdata->warn_soc_lvl > 100)
dev_warn(dev, "Invalid SOC warning level provided, Ignoring");
else
fg->warn_soc = fg_pdata->warn_soc_lvl;
if ((fg_pdata->crit_soc_lvl > 100) ||
(fg_pdata->crit_soc_lvl >= fg_pdata->warn_soc_lvl))
dev_warn(dev, "Invalid SOC critical level provided, Ignoring");
else
fg->crit_soc = fg_pdata->crit_soc_lvl;
}
/* Configure initial SOC level events */
da9150_fg_soc_event_config(fg);
/*
* If an interval period has been provided then setup repeating
* work for reporting data updates.
*/
if (fg->interval) {
INIT_DELAYED_WORK(&fg->work, da9150_fg_work);
schedule_delayed_work(&fg->work,
msecs_to_jiffies(fg->interval));
}
/* Register IRQ */
irq = platform_get_irq_byname(pdev, "FG");
if (irq < 0) {
dev_err(dev, "Failed to get IRQ FG: %d\n", irq);
ret = irq;
goto irq_fail;
}
ret = devm_request_threaded_irq(dev, irq, NULL, da9150_fg_irq,
IRQF_ONESHOT, "FG", fg);
if (ret) {
dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
goto irq_fail;
}
return 0;
irq_fail:
if (fg->interval)
cancel_delayed_work(&fg->work);
return ret;
}
static int da9150_fg_remove(struct platform_device *pdev)
{
struct da9150_fg *fg = platform_get_drvdata(pdev);
if (fg->interval)
cancel_delayed_work(&fg->work);
return 0;
}
static int da9150_fg_resume(struct platform_device *pdev)
{
struct da9150_fg *fg = platform_get_drvdata(pdev);
/*
* Trigger SOC check to happen now so as to indicate any value change
* since last check before suspend.
*/
if (fg->interval)
flush_delayed_work(&fg->work);
return 0;
}
static struct platform_driver da9150_fg_driver = {
.driver = {
.name = "da9150-fuel-gauge",
},
.probe = da9150_fg_probe,
.remove = da9150_fg_remove,
.resume = da9150_fg_resume,
};
module_platform_driver(da9150_fg_driver);
MODULE_DESCRIPTION("Fuel-Gauge Driver for DA9150");
MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
MODULE_LICENSE("GPL");
/*
* This header provides macros for Atmel Flexcom DT bindings.
*
* Copyright (C) 2015 Cyrille Pitchen <cyrille.pitchen@atmel.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __DT_BINDINGS_ATMEL_FLEXCOM_H__
#define __DT_BINDINGS_ATMEL_FLEXCOM_H__
#define ATMEL_FLEXCOM_MODE_USART 1
#define ATMEL_FLEXCOM_MODE_SPI 2
#define ATMEL_FLEXCOM_MODE_TWI 3
#endif /* __DT_BINDINGS_ATMEL_FLEXCOM_H__ */
...@@ -21,6 +21,7 @@ enum { ...@@ -21,6 +21,7 @@ enum {
CHIP_INVALID = 0, CHIP_INVALID = 0,
CHIP_PM800, CHIP_PM800,
CHIP_PM805, CHIP_PM805,
CHIP_PM860,
CHIP_MAX, CHIP_MAX,
}; };
......
...@@ -1065,6 +1065,16 @@ ...@@ -1065,6 +1065,16 @@
#define ARIZONA_CLOCK_CONTROL 0xF00 #define ARIZONA_CLOCK_CONTROL 0xF00
#define ARIZONA_ANC_SRC 0xF01 #define ARIZONA_ANC_SRC 0xF01
#define ARIZONA_DSP_STATUS 0xF02 #define ARIZONA_DSP_STATUS 0xF02
#define ARIZONA_ANC_COEFF_START 0xF08
#define ARIZONA_ANC_COEFF_END 0xF12
#define ARIZONA_FCL_FILTER_CONTROL 0xF15
#define ARIZONA_FCL_ADC_REFORMATTER_CONTROL 0xF17
#define ARIZONA_FCL_COEFF_START 0xF18
#define ARIZONA_FCL_COEFF_END 0xF69
#define ARIZONA_FCR_FILTER_CONTROL 0xF70
#define ARIZONA_FCR_ADC_REFORMATTER_CONTROL 0xF72
#define ARIZONA_FCR_COEFF_START 0xF73
#define ARIZONA_FCR_COEFF_END 0xFC4
#define ARIZONA_DSP1_CONTROL_1 0x1100 #define ARIZONA_DSP1_CONTROL_1 0x1100
#define ARIZONA_DSP1_CLOCKING_1 0x1101 #define ARIZONA_DSP1_CLOCKING_1 0x1101
#define ARIZONA_DSP1_STATUS_1 0x1104 #define ARIZONA_DSP1_STATUS_1 0x1104
...@@ -8050,6 +8060,66 @@ ...@@ -8050,6 +8060,66 @@
#define ARIZONA_ISRC3_NOTCH_ENA_SHIFT 0 /* ISRC3_NOTCH_ENA */ #define ARIZONA_ISRC3_NOTCH_ENA_SHIFT 0 /* ISRC3_NOTCH_ENA */
#define ARIZONA_ISRC3_NOTCH_ENA_WIDTH 1 /* ISRC3_NOTCH_ENA */ #define ARIZONA_ISRC3_NOTCH_ENA_WIDTH 1 /* ISRC3_NOTCH_ENA */
/*
* R3840 (0xF00) - Clock Control
*/
#define ARIZONA_EXT_NG_SEL_CLR 0x0080 /* EXT_NG_SEL_CLR */
#define ARIZONA_EXT_NG_SEL_CLR_MASK 0x0080 /* EXT_NG_SEL_CLR */
#define ARIZONA_EXT_NG_SEL_CLR_SHIFT 7 /* EXT_NG_SEL_CLR */
#define ARIZONA_EXT_NG_SEL_CLR_WIDTH 1 /* EXT_NG_SEL_CLR */
#define ARIZONA_EXT_NG_SEL_SET 0x0040 /* EXT_NG_SEL_SET */
#define ARIZONA_EXT_NG_SEL_SET_MASK 0x0040 /* EXT_NG_SEL_SET */
#define ARIZONA_EXT_NG_SEL_SET_SHIFT 6 /* EXT_NG_SEL_SET */
#define ARIZONA_EXT_NG_SEL_SET_WIDTH 1 /* EXT_NG_SEL_SET */
#define ARIZONA_CLK_R_ENA_CLR 0x0020 /* CLK_R_ENA_CLR */
#define ARIZONA_CLK_R_ENA_CLR_MASK 0x0020 /* CLK_R_ENA_CLR */
#define ARIZONA_CLK_R_ENA_CLR_SHIFT 5 /* CLK_R_ENA_CLR */
#define ARIZONA_CLK_R_ENA_CLR_WIDTH 1 /* CLK_R_ENA_CLR */
#define ARIZONA_CLK_R_ENA_SET 0x0010 /* CLK_R_ENA_SET */
#define ARIZONA_CLK_R_ENA_SET_MASK 0x0010 /* CLK_R_ENA_SET */
#define ARIZONA_CLK_R_ENA_SET_SHIFT 4 /* CLK_R_ENA_SET */
#define ARIZONA_CLK_R_ENA_SET_WIDTH 1 /* CLK_R_ENA_SET */
#define ARIZONA_CLK_NG_ENA_CLR 0x0008 /* CLK_NG_ENA_CLR */
#define ARIZONA_CLK_NG_ENA_CLR_MASK 0x0008 /* CLK_NG_ENA_CLR */
#define ARIZONA_CLK_NG_ENA_CLR_SHIFT 3 /* CLK_NG_ENA_CLR */
#define ARIZONA_CLK_NG_ENA_CLR_WIDTH 1 /* CLK_NG_ENA_CLR */
#define ARIZONA_CLK_NG_ENA_SET 0x0004 /* CLK_NG_ENA_SET */
#define ARIZONA_CLK_NG_ENA_SET_MASK 0x0004 /* CLK_NG_ENA_SET */
#define ARIZONA_CLK_NG_ENA_SET_SHIFT 2 /* CLK_NG_ENA_SET */
#define ARIZONA_CLK_NG_ENA_SET_WIDTH 1 /* CLK_NG_ENA_SET */
#define ARIZONA_CLK_L_ENA_CLR 0x0002 /* CLK_L_ENA_CLR */
#define ARIZONA_CLK_L_ENA_CLR_MASK 0x0002 /* CLK_L_ENA_CLR */
#define ARIZONA_CLK_L_ENA_CLR_SHIFT 1 /* CLK_L_ENA_CLR */
#define ARIZONA_CLK_L_ENA_CLR_WIDTH 1 /* CLK_L_ENA_CLR */
#define ARIZONA_CLK_L_ENA_SET 0x0001 /* CLK_L_ENA_SET */
#define ARIZONA_CLK_L_ENA_SET_MASK 0x0001 /* CLK_L_ENA_SET */
#define ARIZONA_CLK_L_ENA_SET_SHIFT 0 /* CLK_L_ENA_SET */
#define ARIZONA_CLK_L_ENA_SET_WIDTH 1 /* CLK_L_ENA_SET */
/*
* R3841 (0xF01) - ANC SRC
*/
#define ARIZONA_IN_RXANCR_SEL_MASK 0x0070 /* IN_RXANCR_SEL - [4:6] */
#define ARIZONA_IN_RXANCR_SEL_SHIFT 4 /* IN_RXANCR_SEL - [4:6] */
#define ARIZONA_IN_RXANCR_SEL_WIDTH 3 /* IN_RXANCR_SEL - [4:6] */
#define ARIZONA_IN_RXANCL_SEL_MASK 0x0007 /* IN_RXANCL_SEL - [0:2] */
#define ARIZONA_IN_RXANCL_SEL_SHIFT 0 /* IN_RXANCL_SEL - [0:2] */
#define ARIZONA_IN_RXANCL_SEL_WIDTH 3 /* IN_RXANCL_SEL - [0:2] */
/*
* R3863 (0xF17) - FCL ADC Reformatter Control
*/
#define ARIZONA_FCL_MIC_MODE_SEL 0x000C /* FCL_MIC_MODE_SEL - [2:3] */
#define ARIZONA_FCL_MIC_MODE_SEL_SHIFT 2 /* FCL_MIC_MODE_SEL - [2:3] */
#define ARIZONA_FCL_MIC_MODE_SEL_WIDTH 2 /* FCL_MIC_MODE_SEL - [2:3] */
/*
* R3954 (0xF72) - FCR ADC Reformatter Control
*/
#define ARIZONA_FCR_MIC_MODE_SEL 0x000C /* FCR_MIC_MODE_SEL - [2:3] */
#define ARIZONA_FCR_MIC_MODE_SEL_SHIFT 2 /* FCR_MIC_MODE_SEL - [2:3] */
#define ARIZONA_FCR_MIC_MODE_SEL_WIDTH 2 /* FCR_MIC_MODE_SEL - [2:3] */
/* /*
* R4352 (0x1100) - DSP1 Control 1 * R4352 (0x1100) - DSP1 Control 1
*/ */
......
...@@ -18,6 +18,12 @@ ...@@ -18,6 +18,12 @@
struct irq_domain; struct irq_domain;
/* Matches ACPI PNP id, either _HID or _CID, or ACPI _ADR */
struct mfd_cell_acpi_match {
const char *pnpid;
const unsigned long long adr;
};
/* /*
* This struct describes the MFD part ("cell"). * This struct describes the MFD part ("cell").
* After registration the copy of this structure will become the platform data * After registration the copy of this structure will become the platform data
...@@ -44,8 +50,8 @@ struct mfd_cell { ...@@ -44,8 +50,8 @@ struct mfd_cell {
*/ */
const char *of_compatible; const char *of_compatible;
/* Matches ACPI PNP id, either _HID or _CID */ /* Matches ACPI */
const char *acpi_pnpid; const struct mfd_cell_acpi_match *acpi_match;
/* /*
* These resources can be specified relative to the parent device. * These resources can be specified relative to the parent device.
......
...@@ -65,6 +65,9 @@ ...@@ -65,6 +65,9 @@
#define DA9052_GPIO_2_3_REG 22 #define DA9052_GPIO_2_3_REG 22
#define DA9052_GPIO_4_5_REG 23 #define DA9052_GPIO_4_5_REG 23
#define DA9052_GPIO_6_7_REG 24 #define DA9052_GPIO_6_7_REG 24
#define DA9052_GPIO_8_9_REG 25
#define DA9052_GPIO_10_11_REG 26
#define DA9052_GPIO_12_13_REG 27
#define DA9052_GPIO_14_15_REG 28 #define DA9052_GPIO_14_15_REG 28
/* POWER SEQUENCER CONTROL REGISTERS */ /* POWER SEQUENCER CONTROL REGISTERS */
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#define __DA9150_CORE_H #define __DA9150_CORE_H
#include <linux/device.h> #include <linux/device.h>
#include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/regmap.h> #include <linux/regmap.h>
...@@ -46,23 +47,39 @@ ...@@ -46,23 +47,39 @@
#define DA9150_IRQ_GPADC 19 #define DA9150_IRQ_GPADC 19
#define DA9150_IRQ_WKUP 20 #define DA9150_IRQ_WKUP 20
/* I2C sub-device address */
#define DA9150_QIF_I2C_ADDR_LSB 0x5
struct da9150_fg_pdata {
u32 update_interval; /* msecs */
u8 warn_soc_lvl; /* % value */
u8 crit_soc_lvl; /* % value */
};
struct da9150_pdata { struct da9150_pdata {
int irq_base; int irq_base;
struct da9150_fg_pdata *fg_pdata;
}; };
struct da9150 { struct da9150 {
struct device *dev; struct device *dev;
struct regmap *regmap; struct regmap *regmap;
struct i2c_client *core_qif;
struct regmap_irq_chip_data *regmap_irq_data; struct regmap_irq_chip_data *regmap_irq_data;
int irq; int irq;
int irq_base; int irq_base;
}; };
/* Device I/O */ /* Device I/O - Query Interface for FG and standard register access */
void da9150_read_qif(struct da9150 *da9150, u8 addr, int count, u8 *buf);
void da9150_write_qif(struct da9150 *da9150, u8 addr, int count, const u8 *buf);
u8 da9150_reg_read(struct da9150 *da9150, u16 reg); u8 da9150_reg_read(struct da9150 *da9150, u16 reg);
void da9150_reg_write(struct da9150 *da9150, u16 reg, u8 val); void da9150_reg_write(struct da9150 *da9150, u16 reg, u8 val);
void da9150_set_bits(struct da9150 *da9150, u16 reg, u8 mask, u8 val); void da9150_set_bits(struct da9150 *da9150, u16 reg, u8 mask, u8 val);
void da9150_bulk_read(struct da9150 *da9150, u16 reg, int count, u8 *buf); void da9150_bulk_read(struct da9150 *da9150, u16 reg, int count, u8 *buf);
void da9150_bulk_write(struct da9150 *da9150, u16 reg, int count, const u8 *buf); void da9150_bulk_write(struct da9150 *da9150, u16 reg, int count, const u8 *buf);
#endif /* __DA9150_CORE_H */ #endif /* __DA9150_CORE_H */
/*
* intel_bxtwc.h - Header file for Intel Broxton Whiskey Cove PMIC
*
* Copyright (C) 2015 Intel Corporation. All rights reserved.
*
* 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/mfd/intel_soc_pmic.h>
#ifndef __INTEL_BXTWC_H__
#define __INTEL_BXTWC_H__
/* BXT WC devices */
#define BXTWC_DEVICE1_ADDR 0x4E
#define BXTWC_DEVICE2_ADDR 0x4F
#define BXTWC_DEVICE3_ADDR 0x5E
/* device1 Registers */
#define BXTWC_CHIPID 0x4E00
#define BXTWC_CHIPVER 0x4E01
#define BXTWC_SCHGRIRQ0_ADDR 0x5E1A
#define BXTWC_CHGRCTRL0_ADDR 0x5E16
#define BXTWC_CHGRCTRL1_ADDR 0x5E17
#define BXTWC_CHGRCTRL2_ADDR 0x5E18
#define BXTWC_CHGRSTATUS_ADDR 0x5E19
#define BXTWC_THRMBATZONE_ADDR 0x4F22
#define BXTWC_USBPATH_ADDR 0x5E19
#define BXTWC_USBPHYCTRL_ADDR 0x5E07
#define BXTWC_USBIDCTRL_ADDR 0x5E05
#define BXTWC_USBIDEN_MASK 0x01
#define BXTWC_USBIDSTAT_ADDR 0x00FF
#define BXTWC_USBSRCDETSTATUS_ADDR 0x5E29
#define BXTWC_DBGUSBBC1_ADDR 0x5FE0
#define BXTWC_DBGUSBBC2_ADDR 0x5FE1
#define BXTWC_DBGUSBBCSTAT_ADDR 0x5FE2
#define BXTWC_WAKESRC_ADDR 0x4E22
#define BXTWC_WAKESRC2_ADDR 0x4EE5
#define BXTWC_CHRTTADDR_ADDR 0x5E22
#define BXTWC_CHRTTDATA_ADDR 0x5E23
#define BXTWC_STHRMIRQ0_ADDR 0x4F19
#define WC_MTHRMIRQ1_ADDR 0x4E12
#define WC_STHRMIRQ1_ADDR 0x4F1A
#define WC_STHRMIRQ2_ADDR 0x4F1B
#define BXTWC_THRMZN0H_ADDR 0x4F44
#define BXTWC_THRMZN0L_ADDR 0x4F45
#define BXTWC_THRMZN1H_ADDR 0x4F46
#define BXTWC_THRMZN1L_ADDR 0x4F47
#define BXTWC_THRMZN2H_ADDR 0x4F48
#define BXTWC_THRMZN2L_ADDR 0x4F49
#define BXTWC_THRMZN3H_ADDR 0x4F4A
#define BXTWC_THRMZN3L_ADDR 0x4F4B
#define BXTWC_THRMZN4H_ADDR 0x4F4C
#define BXTWC_THRMZN4L_ADDR 0x4F4D
#endif
...@@ -25,6 +25,8 @@ struct intel_soc_pmic { ...@@ -25,6 +25,8 @@ struct intel_soc_pmic {
int irq; int irq;
struct regmap *regmap; struct regmap *regmap;
struct regmap_irq_chip_data *irq_chip_data; struct regmap_irq_chip_data *irq_chip_data;
struct regmap_irq_chip_data *irq_chip_data_level2;
struct device *dev;
}; };
#endif /* __INTEL_SOC_PMIC_H__ */ #endif /* __INTEL_SOC_PMIC_H__ */
...@@ -589,6 +589,7 @@ ...@@ -589,6 +589,7 @@
#define FORCE_ASPM_NO_ASPM 0x00 #define FORCE_ASPM_NO_ASPM 0x00
#define PM_CLK_FORCE_CTL 0xFE58 #define PM_CLK_FORCE_CTL 0xFE58
#define FUNC_FORCE_CTL 0xFE59 #define FUNC_FORCE_CTL 0xFE59
#define FUNC_FORCE_UPME_XMT_DBG 0x02
#define PERST_GLITCH_WIDTH 0xFE5C #define PERST_GLITCH_WIDTH 0xFE5C
#define CHANGE_LINK_STATE 0xFE5B #define CHANGE_LINK_STATE 0xFE5B
#define RESET_LOAD_REG 0xFE5E #define RESET_LOAD_REG 0xFE5E
...@@ -712,6 +713,7 @@ ...@@ -712,6 +713,7 @@
#define PHY_RCR1 0x02 #define PHY_RCR1 0x02
#define PHY_RCR1_ADP_TIME_4 0x0400 #define PHY_RCR1_ADP_TIME_4 0x0400
#define PHY_RCR1_VCO_COARSE 0x001F #define PHY_RCR1_VCO_COARSE 0x001F
#define PHY_RCR1_INIT_27S 0x0A1F
#define PHY_SSCCR2 0x02 #define PHY_SSCCR2 0x02
#define PHY_SSCCR2_PLL_NCODE 0x0A00 #define PHY_SSCCR2_PLL_NCODE 0x0A00
#define PHY_SSCCR2_TIME0 0x001C #define PHY_SSCCR2_TIME0 0x001C
...@@ -724,6 +726,7 @@ ...@@ -724,6 +726,7 @@
#define PHY_RCR2_FREQSEL_12 0x0040 #define PHY_RCR2_FREQSEL_12 0x0040
#define PHY_RCR2_CDR_SC_12P 0x0010 #define PHY_RCR2_CDR_SC_12P 0x0010
#define PHY_RCR2_CALIB_LATE 0x0002 #define PHY_RCR2_CALIB_LATE 0x0002
#define PHY_RCR2_INIT_27S 0xC152
#define PHY_SSCCR3 0x03 #define PHY_SSCCR3 0x03
#define PHY_SSCCR3_STEP_IN 0x2740 #define PHY_SSCCR3_STEP_IN 0x2740
#define PHY_SSCCR3_CHECK_DELAY 0x0008 #define PHY_SSCCR3_CHECK_DELAY 0x0008
...@@ -800,12 +803,14 @@ ...@@ -800,12 +803,14 @@
#define PHY_ANA1A_RXT_BIST 0x0500 #define PHY_ANA1A_RXT_BIST 0x0500
#define PHY_ANA1A_TXR_BIST 0x0040 #define PHY_ANA1A_TXR_BIST 0x0040
#define PHY_ANA1A_REV 0x0006 #define PHY_ANA1A_REV 0x0006
#define PHY_FLD0_INIT_27S 0x2546
#define PHY_FLD1 0x1B #define PHY_FLD1 0x1B
#define PHY_FLD2 0x1C #define PHY_FLD2 0x1C
#define PHY_FLD3 0x1D #define PHY_FLD3 0x1D
#define PHY_FLD3_TIMER_4 0x0800 #define PHY_FLD3_TIMER_4 0x0800
#define PHY_FLD3_TIMER_6 0x0020 #define PHY_FLD3_TIMER_6 0x0020
#define PHY_FLD3_RXDELINK 0x0004 #define PHY_FLD3_RXDELINK 0x0004
#define PHY_FLD3_INIT_27S 0x0004
#define PHY_ANA1D 0x1D #define PHY_ANA1D 0x1D
#define PHY_ANA1D_DEBUG_ADDR 0x0004 #define PHY_ANA1D_DEBUG_ADDR 0x0004
#define _PHY_FLD0 0x1D #define _PHY_FLD0 0x1D
...@@ -824,6 +829,7 @@ ...@@ -824,6 +829,7 @@
#define PHY_FLD4_BER_COUNT 0x00E0 #define PHY_FLD4_BER_COUNT 0x00E0
#define PHY_FLD4_BER_TIMER 0x000A #define PHY_FLD4_BER_TIMER 0x000A
#define PHY_FLD4_BER_CHK_EN 0x0001 #define PHY_FLD4_BER_CHK_EN 0x0001
#define PHY_FLD4_INIT_27S 0x5C7F
#define PHY_DIG1E 0x1E #define PHY_DIG1E 0x1E
#define PHY_DIG1E_REV 0x4000 #define PHY_DIG1E_REV 0x4000
#define PHY_DIG1E_D0_X_D1 0x1000 #define PHY_DIG1E_D0_X_D1 0x1000
......
...@@ -132,6 +132,10 @@ struct sec_platform_data { ...@@ -132,6 +132,10 @@ struct sec_platform_data {
int buck2_init; int buck2_init;
int buck3_init; int buck3_init;
int buck4_init; int buck4_init;
/* Whether or not manually set PWRHOLD to low during shutdown. */
bool manual_poweroff;
/* Disable the WRSTBI (buck voltage warm reset) when probing? */
bool disable_wrstbi;
}; };
/** /**
......
...@@ -179,6 +179,7 @@ enum s2mps11_regulators { ...@@ -179,6 +179,7 @@ enum s2mps11_regulators {
#define S2MPS11_BUCK_N_VOLTAGES (S2MPS11_BUCK_VSEL_MASK + 1) #define S2MPS11_BUCK_N_VOLTAGES (S2MPS11_BUCK_VSEL_MASK + 1)
#define S2MPS11_RAMP_DELAY 25000 /* uV/us */ #define S2MPS11_RAMP_DELAY 25000 /* uV/us */
#define S2MPS11_CTRL1_PWRHOLD_MASK BIT(4)
#define S2MPS11_BUCK2_RAMP_SHIFT 6 #define S2MPS11_BUCK2_RAMP_SHIFT 6
#define S2MPS11_BUCK34_RAMP_SHIFT 4 #define S2MPS11_BUCK34_RAMP_SHIFT 4
......
...@@ -184,5 +184,6 @@ enum s2mps13_regulators { ...@@ -184,5 +184,6 @@ enum s2mps13_regulators {
* Let's assume that default value will be set. * Let's assume that default value will be set.
*/ */
#define S2MPS13_BUCK_RAMP_DELAY 12500 #define S2MPS13_BUCK_RAMP_DELAY 12500
#define S2MPS13_REG_WRSTBI_MASK BIT(5)
#endif /* __LINUX_MFD_S2MPS13_H */ #endif /* __LINUX_MFD_S2MPS13_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment