You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'mfd-3.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next
Pull MFD update from Samuel Ortiz:
"For the 3.11 merge we only have one new MFD driver for the Kontron
PLD.
But we also have:
- Support for the TPS659038 PMIC from the palmas driver.
- Intel's Coleto Creek and Avoton SoCs support from the lpc_ich
driver.
- RTL8411B support from the rtsx driver.
- More DT support for the Arizona, max8998, twl4030-power and the
ti_am335x_tsadc drivers.
- The SSBI driver move under MFD.
- A conversion to the devm_* API for most of the MFD drivers.
- The twl4030-power got split from twl-core into its own module.
- A major ti_am335x_adc cleanup, leading to a proper DT support.
- Our regular arizona and wm* updates and cleanups from the Wolfson
folks.
- A better error handling and initialization, and a regulator
subdevice addition for the 88pm80x driver.
- A bulk platform_set_drvdata() call removal that's no longer need
since commit 0998d06310 ("device-core: Ensure drvdata = NULL when
no driver is bound")
* tag 'mfd-3.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next: (102 commits)
mfd: sec: Provide max_register to regmap
mfd: wm8994: Remove duplicate check for active JACKDET
MAINTAINERS: Add include directory to MFD file patterns
mfd: sec: Remove fields not used since regmap conversion
watchdog: Kontron PLD watchdog timer driver
mfd: max8998: Add support for Device Tree
regulator: max8998: Use arrays for specifying voltages in platform data
mfd: max8998: Add irq domain support
regulator: palmas: Add TPS659038 support
mfd: Kontron PLD mfd driver
mfd: palmas: Add TPS659038 PMIC support
mfd: palmas: Add SMPS10_BOOST feature
mfd: palmas: Check if irq is valid
mfd: lpc_ich: iTCO_wdt patch for Intel Coleto Creek DeviceIDs
mfd: twl-core: Change TWL6025 references to TWL6032
mfd: davinci_voicecodec: Fix build breakage
mfd: vexpress: Make the driver optional for arm and arm64
mfd: htc-egpio: Use devm_ioremap_nocache() instead of ioremap_nocache()
mfd: davinci_voicecodec: Convert to use devm_* APIs
mfd: twl4030-power: Fix relocking on error
...
This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
* TI - TSC ADC (Touschscreen and analog digital converter)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- child "tsc"
|
||||||
|
ti,wires: Wires refer to application modes i.e. 4/5/8 wire touchscreen
|
||||||
|
support on the platform.
|
||||||
|
ti,x-plate-resistance: X plate resistance
|
||||||
|
ti,coordiante-readouts: The sequencer supports a total of 16
|
||||||
|
programmable steps each step is used to
|
||||||
|
read a single coordinate. A single
|
||||||
|
readout is enough but multiple reads can
|
||||||
|
increase the quality.
|
||||||
|
A value of 5 means, 5 reads for X, 5 for
|
||||||
|
Y and 2 for Z (always). This utilises 12
|
||||||
|
of the 16 software steps available. The
|
||||||
|
remaining 4 can be used by the ADC.
|
||||||
|
ti,wire-config: Different boards could have a different order for
|
||||||
|
connecting wires on touchscreen. We need to provide an
|
||||||
|
8 bit number where in the 1st four bits represent the
|
||||||
|
analog lines and the next 4 bits represent positive/
|
||||||
|
negative terminal on that input line. Notations to
|
||||||
|
represent the input lines and terminals resoectively
|
||||||
|
is as follows:
|
||||||
|
AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
|
||||||
|
XP = 0, XN = 1, YP = 2, YN = 3.
|
||||||
|
- child "adc"
|
||||||
|
ti,adc-channels: List of analog inputs available for ADC.
|
||||||
|
AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
tscadc: tscadc@44e0d000 {
|
||||||
|
compatible = "ti,am3359-tscadc";
|
||||||
|
tsc {
|
||||||
|
ti,wires = <4>;
|
||||||
|
ti,x-plate-resistance = <200>;
|
||||||
|
ti,coordiante-readouts = <5>;
|
||||||
|
ti,wire-config = <0x00 0x11 0x22 0x33>;
|
||||||
|
};
|
||||||
|
|
||||||
|
adc {
|
||||||
|
ti,adc-channels = <4 5 6 7>;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
* Maxim MAX8998, National/TI LP3974 multi-function device
|
||||||
|
|
||||||
|
The Maxim MAX8998 is a multi-function device which includes voltage/current
|
||||||
|
regulators, real time clock, battery charging controller and several
|
||||||
|
other sub-blocks. It is interfaced using an I2C interface. Each sub-block
|
||||||
|
is addressed by the host system using different i2c slave address.
|
||||||
|
|
||||||
|
PMIC sub-block
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The PMIC sub-block contains a number of voltage and current regulators,
|
||||||
|
with controllable parameters and dynamic voltage scaling capability.
|
||||||
|
In addition, it includes a real time clock and battery charging controller
|
||||||
|
as well. It is accessible at I2C address 0x66.
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: Should be one of the following:
|
||||||
|
- "maxim,max8998" for Maxim MAX8998
|
||||||
|
- "national,lp3974" or "ti,lp3974" for National/TI LP3974.
|
||||||
|
- reg: Specifies the i2c slave address of the pmic block. It should be 0x66.
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- interrupt-parent: Specifies the phandle of the interrupt controller to which
|
||||||
|
the interrupts from MAX8998 are routed to.
|
||||||
|
- interrupts: Interrupt specifiers for two interrupt sources.
|
||||||
|
- First interrupt specifier is for main interrupt.
|
||||||
|
- Second interrupt specifier is for power-on/-off interrupt.
|
||||||
|
- max8998,pmic-buck1-dvs-gpios: GPIO specifiers for two host gpios used
|
||||||
|
for buck 1 dvs. The format of the gpio specifier depends on the gpio
|
||||||
|
controller.
|
||||||
|
- max8998,pmic-buck2-dvs-gpio: GPIO specifier for host gpio used
|
||||||
|
for buck 2 dvs. The format of the gpio specifier depends on the gpio
|
||||||
|
controller.
|
||||||
|
- max8998,pmic-buck1-default-dvs-idx: Default voltage setting selected from
|
||||||
|
the possible 4 options selectable by the dvs gpios. The value of this
|
||||||
|
property should be 0, 1, 2 or 3. If not specified or out of range,
|
||||||
|
a default value of 0 is taken.
|
||||||
|
- max8998,pmic-buck2-default-dvs-idx: Default voltage setting selected from
|
||||||
|
the possible 2 options selectable by the dvs gpios. The value of this
|
||||||
|
property should be 0 or 1. If not specified or out of range, a default
|
||||||
|
value of 0 is taken.
|
||||||
|
- max8998,pmic-buck-voltage-lock: If present, disallows changing of
|
||||||
|
preprogrammed buck dvfs voltages.
|
||||||
|
|
||||||
|
Additional properties required if max8998,pmic-buck1-dvs-gpios is defined:
|
||||||
|
- max8998,pmic-buck1-dvs-voltage: An array of 4 voltage values in microvolts
|
||||||
|
for buck1 regulator that can be selected using dvs gpio.
|
||||||
|
|
||||||
|
Additional properties required if max8998,pmic-buck2-dvs-gpio is defined:
|
||||||
|
- max8998,pmic-buck2-dvs-voltage: An array of 2 voltage values in microvolts
|
||||||
|
for buck2 regulator that can be selected using dvs gpio.
|
||||||
|
|
||||||
|
Regulators: All the regulators of MAX8998 to be instantiated shall be
|
||||||
|
listed in a child node named 'regulators'. Each regulator is represented
|
||||||
|
by a child node of the 'regulators' node.
|
||||||
|
|
||||||
|
regulator-name {
|
||||||
|
/* standard regulator bindings here */
|
||||||
|
};
|
||||||
|
|
||||||
|
Following regulators of the MAX8998 PMIC block are supported. Note that
|
||||||
|
the 'n' in regulator name, as in LDOn or BUCKn, represents the LDO or BUCK
|
||||||
|
number as described in MAX8998 datasheet.
|
||||||
|
|
||||||
|
- LDOn
|
||||||
|
- valid values for n are 2 to 17
|
||||||
|
- Example: LDO2, LDO10, LDO17
|
||||||
|
- BUCKn
|
||||||
|
- valid values for n are 1 to 4.
|
||||||
|
- Example: BUCK1, BUCK2, BUCK3, BUCK4
|
||||||
|
|
||||||
|
- ENVICHG: Battery Charging Current Monitor Output. This is a fixed
|
||||||
|
voltage type regulator
|
||||||
|
|
||||||
|
- ESAFEOUT1: (ldo19)
|
||||||
|
- ESAFEOUT2: (ld020)
|
||||||
|
|
||||||
|
Standard regulator bindings are used inside regulator subnodes. Check
|
||||||
|
Documentation/devicetree/bindings/regulator/regulator.txt
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
pmic@66 {
|
||||||
|
compatible = "maxim,max8998-pmic";
|
||||||
|
reg = <0x66>;
|
||||||
|
interrupt-parent = <&wakeup_eint>;
|
||||||
|
interrupts = <4 0>, <3 0>;
|
||||||
|
|
||||||
|
/* Buck 1 DVS settings */
|
||||||
|
max8998,pmic-buck1-default-dvs-idx = <0>;
|
||||||
|
max8998,pmic-buck1-dvs-gpios = <&gpx0 0 1 0 0>, /* SET1 */
|
||||||
|
<&gpx0 1 1 0 0>; /* SET2 */
|
||||||
|
max8998,pmic-buck1-dvs-voltage = <1350000>, <1300000>,
|
||||||
|
<1000000>, <950000>;
|
||||||
|
|
||||||
|
/* Buck 2 DVS settings */
|
||||||
|
max8998,pmic-buck2-default-dvs-idx = <0>;
|
||||||
|
max8998,pmic-buck2-dvs-gpio = <&gpx0 0 3 0 0>; /* SET3 */
|
||||||
|
max8998,pmic-buck2-dvs-voltage = <1350000>, <1300000>;
|
||||||
|
|
||||||
|
/* Regulators to instantiate */
|
||||||
|
regulators {
|
||||||
|
ldo2_reg: LDO2 {
|
||||||
|
regulator-name = "VDD_ALIVE_1.1V";
|
||||||
|
regulator-min-microvolt = <1100000>;
|
||||||
|
regulator-max-microvolt = <1100000>;
|
||||||
|
regulator-always-on;
|
||||||
|
};
|
||||||
|
|
||||||
|
buck1_reg: BUCK1 {
|
||||||
|
regulator-name = "VDD_ARM_1.2V";
|
||||||
|
regulator-min-microvolt = <950000>;
|
||||||
|
regulator-max-microvolt = <1350000>;
|
||||||
|
regulator-always-on;
|
||||||
|
regulator-boot-on;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
Texas Instruments TWL family (twl4030) reset and power management module
|
||||||
|
|
||||||
|
The power management module inside the TWL family provides several facilities
|
||||||
|
to control the power resources, including power scripts. For now, the
|
||||||
|
binding only supports the complete shutdown of the system after poweroff.
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible : must be "ti,twl4030-power"
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- ti,use_poweroff: With this flag, the chip will initiates an ACTIVE-to-OFF or
|
||||||
|
SLEEP-to-OFF transition when the system poweroffs.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
&i2c1 {
|
||||||
|
clock-frequency = <2600000>;
|
||||||
|
|
||||||
|
twl: twl@48 {
|
||||||
|
reg = <0x48>;
|
||||||
|
interrupts = <7>; /* SYS_NIRQ cascaded to intc */
|
||||||
|
interrupt-parent = <&intc>;
|
||||||
|
|
||||||
|
twl_power: power {
|
||||||
|
compatible = "ti,twl4030-power";
|
||||||
|
ti,use_poweroff;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -18,20 +18,20 @@ For twl6030 regulators/LDOs
|
|||||||
- "ti,twl6030-vdd1" for VDD1 SMPS
|
- "ti,twl6030-vdd1" for VDD1 SMPS
|
||||||
- "ti,twl6030-vdd2" for VDD2 SMPS
|
- "ti,twl6030-vdd2" for VDD2 SMPS
|
||||||
- "ti,twl6030-vdd3" for VDD3 SMPS
|
- "ti,twl6030-vdd3" for VDD3 SMPS
|
||||||
For twl6025 regulators/LDOs
|
For twl6032 regulators/LDOs
|
||||||
- compatible:
|
- compatible:
|
||||||
- "ti,twl6025-ldo1" for LDO1 LDO
|
- "ti,twl6032-ldo1" for LDO1 LDO
|
||||||
- "ti,twl6025-ldo2" for LDO2 LDO
|
- "ti,twl6032-ldo2" for LDO2 LDO
|
||||||
- "ti,twl6025-ldo3" for LDO3 LDO
|
- "ti,twl6032-ldo3" for LDO3 LDO
|
||||||
- "ti,twl6025-ldo4" for LDO4 LDO
|
- "ti,twl6032-ldo4" for LDO4 LDO
|
||||||
- "ti,twl6025-ldo5" for LDO5 LDO
|
- "ti,twl6032-ldo5" for LDO5 LDO
|
||||||
- "ti,twl6025-ldo6" for LDO6 LDO
|
- "ti,twl6032-ldo6" for LDO6 LDO
|
||||||
- "ti,twl6025-ldo7" for LDO7 LDO
|
- "ti,twl6032-ldo7" for LDO7 LDO
|
||||||
- "ti,twl6025-ldoln" for LDOLN LDO
|
- "ti,twl6032-ldoln" for LDOLN LDO
|
||||||
- "ti,twl6025-ldousb" for LDOUSB LDO
|
- "ti,twl6032-ldousb" for LDOUSB LDO
|
||||||
- "ti,twl6025-smps3" for SMPS3 SMPS
|
- "ti,twl6032-smps3" for SMPS3 SMPS
|
||||||
- "ti,twl6025-smps4" for SMPS4 SMPS
|
- "ti,twl6032-smps4" for SMPS4 SMPS
|
||||||
- "ti,twl6025-vio" for VIO SMPS
|
- "ti,twl6032-vio" for VIO SMPS
|
||||||
For twl4030 regulators/LDOs
|
For twl4030 regulators/LDOs
|
||||||
- compatible:
|
- compatible:
|
||||||
- "ti,twl4030-vaux1" for VAUX1 LDO
|
- "ti,twl4030-vaux1" for VAUX1 LDO
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ TWL6030 USB COMPARATOR
|
|||||||
usb interrupt number that raises VBUS interrupts when the controller has to
|
usb interrupt number that raises VBUS interrupts when the controller has to
|
||||||
act as device
|
act as device
|
||||||
- usb-supply : phandle to the regulator device tree node. It should be vusb
|
- usb-supply : phandle to the regulator device tree node. It should be vusb
|
||||||
if it is twl6030 or ldousb if it is twl6025 subclass.
|
if it is twl6030 or ldousb if it is twl6032 subclass.
|
||||||
|
|
||||||
twl6030-usb {
|
twl6030-usb {
|
||||||
compatible = "ti,twl6030-usb";
|
compatible = "ti,twl6030-usb";
|
||||||
|
|||||||
+4
-1
@@ -5500,9 +5500,12 @@ F: include/media/mt9v032.h
|
|||||||
|
|
||||||
MULTIFUNCTION DEVICES (MFD)
|
MULTIFUNCTION DEVICES (MFD)
|
||||||
M: Samuel Ortiz <sameo@linux.intel.com>
|
M: Samuel Ortiz <sameo@linux.intel.com>
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6.git
|
M: Lee Jones <lee.jones@linaro.org>
|
||||||
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next.git
|
||||||
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-fixes.git
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/mfd/
|
F: drivers/mfd/
|
||||||
|
F: include/linux/mfd/
|
||||||
|
|
||||||
MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
|
MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
|
||||||
M: Chris Ball <cjb@laptop.org>
|
M: Chris Ball <cjb@laptop.org>
|
||||||
|
|||||||
@@ -474,3 +474,17 @@
|
|||||||
phy_id = <&davinci_mdio>, <1>;
|
phy_id = <&davinci_mdio>, <1>;
|
||||||
phy-mode = "rgmii-txid";
|
phy-mode = "rgmii-txid";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&tscadc {
|
||||||
|
status = "okay";
|
||||||
|
tsc {
|
||||||
|
ti,wires = <4>;
|
||||||
|
ti,x-plate-resistance = <200>;
|
||||||
|
ti,coordiante-readouts = <5>;
|
||||||
|
ti,wire-config = <0x00 0x11 0x22 0x33>;
|
||||||
|
};
|
||||||
|
|
||||||
|
adc {
|
||||||
|
ti,adc-channels = <4 5 6 7>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|||||||
@@ -502,6 +502,23 @@
|
|||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
tscadc: tscadc@44e0d000 {
|
||||||
|
compatible = "ti,am3359-tscadc";
|
||||||
|
reg = <0x44e0d000 0x1000>;
|
||||||
|
interrupt-parent = <&intc>;
|
||||||
|
interrupts = <16>;
|
||||||
|
ti,hwmods = "adc_tsc";
|
||||||
|
status = "disabled";
|
||||||
|
|
||||||
|
tsc {
|
||||||
|
compatible = "ti,am3359-tsc";
|
||||||
|
};
|
||||||
|
am335x_adc: adc {
|
||||||
|
#io-channel-cells = <1>;
|
||||||
|
compatible = "ti,am3359-adc";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
gpmc: gpmc@50000000 {
|
gpmc: gpmc@50000000 {
|
||||||
compatible = "ti,am3352-gpmc";
|
compatible = "ti,am3352-gpmc";
|
||||||
ti,hwmods = "gpmc";
|
ti,hwmods = "gpmc";
|
||||||
|
|||||||
@@ -377,12 +377,8 @@ static struct max8998_platform_data aquila_max8998_pdata = {
|
|||||||
.buck1_set1 = S5PV210_GPH0(3),
|
.buck1_set1 = S5PV210_GPH0(3),
|
||||||
.buck1_set2 = S5PV210_GPH0(4),
|
.buck1_set2 = S5PV210_GPH0(4),
|
||||||
.buck2_set3 = S5PV210_GPH0(5),
|
.buck2_set3 = S5PV210_GPH0(5),
|
||||||
.buck1_voltage1 = 1200000,
|
.buck1_voltage = { 1200000, 1200000, 1200000, 1200000 },
|
||||||
.buck1_voltage2 = 1200000,
|
.buck2_voltage = { 1200000, 1200000 },
|
||||||
.buck1_voltage3 = 1200000,
|
|
||||||
.buck1_voltage4 = 1200000,
|
|
||||||
.buck2_voltage1 = 1200000,
|
|
||||||
.buck2_voltage2 = 1200000,
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -580,12 +580,8 @@ static struct max8998_platform_data goni_max8998_pdata = {
|
|||||||
.buck1_set1 = S5PV210_GPH0(3),
|
.buck1_set1 = S5PV210_GPH0(3),
|
||||||
.buck1_set2 = S5PV210_GPH0(4),
|
.buck1_set2 = S5PV210_GPH0(4),
|
||||||
.buck2_set3 = S5PV210_GPH0(5),
|
.buck2_set3 = S5PV210_GPH0(5),
|
||||||
.buck1_voltage1 = 1200000,
|
.buck1_voltage = { 1200000, 1200000, 1200000, 1200000 },
|
||||||
.buck1_voltage2 = 1200000,
|
.buck2_voltage = { 1200000, 1200000 },
|
||||||
.buck1_voltage3 = 1200000,
|
|
||||||
.buck1_voltage4 = 1200000,
|
|
||||||
.buck2_voltage1 = 1200000,
|
|
||||||
.buck2_voltage2 = 1200000,
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -52,8 +52,6 @@ source "drivers/i2c/Kconfig"
|
|||||||
|
|
||||||
source "drivers/spi/Kconfig"
|
source "drivers/spi/Kconfig"
|
||||||
|
|
||||||
source "drivers/ssbi/Kconfig"
|
|
||||||
|
|
||||||
source "drivers/hsi/Kconfig"
|
source "drivers/hsi/Kconfig"
|
||||||
|
|
||||||
source "drivers/pps/Kconfig"
|
source "drivers/pps/Kconfig"
|
||||||
|
|||||||
@@ -117,7 +117,6 @@ obj-y += firmware/
|
|||||||
obj-$(CONFIG_CRYPTO) += crypto/
|
obj-$(CONFIG_CRYPTO) += crypto/
|
||||||
obj-$(CONFIG_SUPERH) += sh/
|
obj-$(CONFIG_SUPERH) += sh/
|
||||||
obj-$(CONFIG_ARCH_SHMOBILE) += sh/
|
obj-$(CONFIG_ARCH_SHMOBILE) += sh/
|
||||||
obj-$(CONFIG_SSBI) += ssbi/
|
|
||||||
ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
|
ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
|
||||||
obj-y += clocksource/
|
obj-y += clocksource/
|
||||||
endif
|
endif
|
||||||
|
|||||||
+100
-32
@@ -22,13 +22,18 @@
|
|||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/iio/machine.h>
|
||||||
|
#include <linux/iio/driver.h>
|
||||||
|
|
||||||
#include <linux/mfd/ti_am335x_tscadc.h>
|
#include <linux/mfd/ti_am335x_tscadc.h>
|
||||||
#include <linux/platform_data/ti_am335x_adc.h>
|
|
||||||
|
|
||||||
struct tiadc_device {
|
struct tiadc_device {
|
||||||
struct ti_tscadc_dev *mfd_tscadc;
|
struct ti_tscadc_dev *mfd_tscadc;
|
||||||
int channels;
|
int channels;
|
||||||
|
u8 channel_line[8];
|
||||||
|
u8 channel_step[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
|
static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
|
||||||
@@ -42,10 +47,20 @@ static void tiadc_writel(struct tiadc_device *adc, unsigned int reg,
|
|||||||
writel(val, adc->mfd_tscadc->tscadc_base + reg);
|
writel(val, adc->mfd_tscadc->tscadc_base + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
|
||||||
|
{
|
||||||
|
u32 step_en;
|
||||||
|
|
||||||
|
step_en = ((1 << adc_dev->channels) - 1);
|
||||||
|
step_en <<= TOTAL_STEPS - adc_dev->channels + 1;
|
||||||
|
return step_en;
|
||||||
|
}
|
||||||
|
|
||||||
static void tiadc_step_config(struct tiadc_device *adc_dev)
|
static void tiadc_step_config(struct tiadc_device *adc_dev)
|
||||||
{
|
{
|
||||||
unsigned int stepconfig;
|
unsigned int stepconfig;
|
||||||
int i, channels = 0, steps;
|
int i, steps;
|
||||||
|
u32 step_en;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are 16 configurable steps and 8 analog input
|
* There are 16 configurable steps and 8 analog input
|
||||||
@@ -58,43 +73,63 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
steps = TOTAL_STEPS - adc_dev->channels;
|
steps = TOTAL_STEPS - adc_dev->channels;
|
||||||
channels = TOTAL_CHANNELS - adc_dev->channels;
|
|
||||||
|
|
||||||
stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
|
stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
|
||||||
|
|
||||||
for (i = (steps + 1); i <= TOTAL_STEPS; i++) {
|
for (i = 0; i < adc_dev->channels; i++) {
|
||||||
tiadc_writel(adc_dev, REG_STEPCONFIG(i),
|
int chan;
|
||||||
stepconfig | STEPCONFIG_INP(channels));
|
|
||||||
tiadc_writel(adc_dev, REG_STEPDELAY(i),
|
chan = adc_dev->channel_line[i];
|
||||||
|
tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
|
||||||
|
stepconfig | STEPCONFIG_INP(chan));
|
||||||
|
tiadc_writel(adc_dev, REG_STEPDELAY(steps),
|
||||||
STEPCONFIG_OPENDLY);
|
STEPCONFIG_OPENDLY);
|
||||||
channels++;
|
adc_dev->channel_step[i] = steps;
|
||||||
|
steps++;
|
||||||
}
|
}
|
||||||
tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
|
step_en = get_adc_step_mask(adc_dev);
|
||||||
|
am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char * const chan_name_ain[] = {
|
||||||
|
"AIN0",
|
||||||
|
"AIN1",
|
||||||
|
"AIN2",
|
||||||
|
"AIN3",
|
||||||
|
"AIN4",
|
||||||
|
"AIN5",
|
||||||
|
"AIN6",
|
||||||
|
"AIN7",
|
||||||
|
};
|
||||||
|
|
||||||
static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
|
static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
|
||||||
{
|
{
|
||||||
|
struct tiadc_device *adc_dev = iio_priv(indio_dev);
|
||||||
struct iio_chan_spec *chan_array;
|
struct iio_chan_spec *chan_array;
|
||||||
|
struct iio_chan_spec *chan;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
indio_dev->num_channels = channels;
|
indio_dev->num_channels = channels;
|
||||||
chan_array = kcalloc(indio_dev->num_channels,
|
chan_array = kcalloc(channels,
|
||||||
sizeof(struct iio_chan_spec), GFP_KERNEL);
|
sizeof(struct iio_chan_spec), GFP_KERNEL);
|
||||||
|
|
||||||
if (chan_array == NULL)
|
if (chan_array == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 0; i < (indio_dev->num_channels); i++) {
|
chan = chan_array;
|
||||||
struct iio_chan_spec *chan = chan_array + i;
|
for (i = 0; i < channels; i++, chan++) {
|
||||||
|
|
||||||
chan->type = IIO_VOLTAGE;
|
chan->type = IIO_VOLTAGE;
|
||||||
chan->indexed = 1;
|
chan->indexed = 1;
|
||||||
chan->channel = i;
|
chan->channel = adc_dev->channel_line[i];
|
||||||
chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
|
chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
|
||||||
|
chan->datasheet_name = chan_name_ain[chan->channel];
|
||||||
|
chan->scan_type.sign = 'u';
|
||||||
|
chan->scan_type.realbits = 12;
|
||||||
|
chan->scan_type.storagebits = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
indio_dev->channels = chan_array;
|
indio_dev->channels = chan_array;
|
||||||
|
|
||||||
return indio_dev->num_channels;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tiadc_channels_remove(struct iio_dev *indio_dev)
|
static void tiadc_channels_remove(struct iio_dev *indio_dev)
|
||||||
@@ -108,7 +143,9 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
|
|||||||
{
|
{
|
||||||
struct tiadc_device *adc_dev = iio_priv(indio_dev);
|
struct tiadc_device *adc_dev = iio_priv(indio_dev);
|
||||||
int i;
|
int i;
|
||||||
unsigned int fifo1count, readx1;
|
unsigned int fifo1count, read;
|
||||||
|
u32 step = UINT_MAX;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When the sub-system is first enabled,
|
* When the sub-system is first enabled,
|
||||||
@@ -121,14 +158,26 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
|
|||||||
* Hence we need to flush out this data.
|
* Hence we need to flush out this data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
|
||||||
|
if (chan->channel == adc_dev->channel_line[i]) {
|
||||||
|
step = adc_dev->channel_step[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (WARN_ON_ONCE(step == UINT_MAX))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
|
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
|
||||||
for (i = 0; i < fifo1count; i++) {
|
for (i = 0; i < fifo1count; i++) {
|
||||||
readx1 = tiadc_readl(adc_dev, REG_FIFO1);
|
read = tiadc_readl(adc_dev, REG_FIFO1);
|
||||||
if (i == chan->channel)
|
if (read >> 16 == step) {
|
||||||
*val = readx1 & 0xfff;
|
*val = read & 0xfff;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
|
am335x_tsc_se_update(adc_dev->mfd_tscadc);
|
||||||
|
if (found == false)
|
||||||
|
return -EBUSY;
|
||||||
return IIO_VAL_INT;
|
return IIO_VAL_INT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,13 +189,15 @@ static int tiadc_probe(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
struct tiadc_device *adc_dev;
|
struct tiadc_device *adc_dev;
|
||||||
struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
|
struct device_node *node = pdev->dev.of_node;
|
||||||
struct mfd_tscadc_board *pdata;
|
struct property *prop;
|
||||||
|
const __be32 *cur;
|
||||||
int err;
|
int err;
|
||||||
|
u32 val;
|
||||||
|
int channels = 0;
|
||||||
|
|
||||||
pdata = tscadc_dev->dev->platform_data;
|
if (!node) {
|
||||||
if (!pdata || !pdata->adc_init) {
|
dev_err(&pdev->dev, "Could not find valid DT data.\n");
|
||||||
dev_err(&pdev->dev, "Could not find platform data\n");
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,8 +209,13 @@ static int tiadc_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
adc_dev = iio_priv(indio_dev);
|
adc_dev = iio_priv(indio_dev);
|
||||||
|
|
||||||
adc_dev->mfd_tscadc = tscadc_dev;
|
adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev);
|
||||||
adc_dev->channels = pdata->adc_init->adc_channels;
|
|
||||||
|
of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
|
||||||
|
adc_dev->channel_line[channels] = val;
|
||||||
|
channels++;
|
||||||
|
}
|
||||||
|
adc_dev->channels = channels;
|
||||||
|
|
||||||
indio_dev->dev.parent = &pdev->dev;
|
indio_dev->dev.parent = &pdev->dev;
|
||||||
indio_dev->name = dev_name(&pdev->dev);
|
indio_dev->name = dev_name(&pdev->dev);
|
||||||
@@ -191,10 +247,15 @@ err_ret:
|
|||||||
static int tiadc_remove(struct platform_device *pdev)
|
static int tiadc_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
|
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
|
struct tiadc_device *adc_dev = iio_priv(indio_dev);
|
||||||
|
u32 step_en;
|
||||||
|
|
||||||
iio_device_unregister(indio_dev);
|
iio_device_unregister(indio_dev);
|
||||||
tiadc_channels_remove(indio_dev);
|
tiadc_channels_remove(indio_dev);
|
||||||
|
|
||||||
|
step_en = get_adc_step_mask(adc_dev);
|
||||||
|
am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
|
||||||
|
|
||||||
iio_device_free(indio_dev);
|
iio_device_free(indio_dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -205,9 +266,10 @@ static int tiadc_suspend(struct device *dev)
|
|||||||
{
|
{
|
||||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||||
struct tiadc_device *adc_dev = iio_priv(indio_dev);
|
struct tiadc_device *adc_dev = iio_priv(indio_dev);
|
||||||
struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
|
struct ti_tscadc_dev *tscadc_dev;
|
||||||
unsigned int idle;
|
unsigned int idle;
|
||||||
|
|
||||||
|
tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
|
||||||
if (!device_may_wakeup(tscadc_dev->dev)) {
|
if (!device_may_wakeup(tscadc_dev->dev)) {
|
||||||
idle = tiadc_readl(adc_dev, REG_CTRL);
|
idle = tiadc_readl(adc_dev, REG_CTRL);
|
||||||
idle &= ~(CNTRLREG_TSCSSENB);
|
idle &= ~(CNTRLREG_TSCSSENB);
|
||||||
@@ -243,16 +305,22 @@ static const struct dev_pm_ops tiadc_pm_ops = {
|
|||||||
#define TIADC_PM_OPS NULL
|
#define TIADC_PM_OPS NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static const struct of_device_id ti_adc_dt_ids[] = {
|
||||||
|
{ .compatible = "ti,am3359-adc", },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, ti_adc_dt_ids);
|
||||||
|
|
||||||
static struct platform_driver tiadc_driver = {
|
static struct platform_driver tiadc_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "tiadc",
|
.name = "TI-am335x-adc",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.pm = TIADC_PM_OPS,
|
.pm = TIADC_PM_OPS,
|
||||||
|
.of_match_table = of_match_ptr(ti_adc_dt_ids),
|
||||||
},
|
},
|
||||||
.probe = tiadc_probe,
|
.probe = tiadc_probe,
|
||||||
.remove = tiadc_remove,
|
.remove = tiadc_remove,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_platform_driver(tiadc_driver);
|
module_platform_driver(tiadc_driver);
|
||||||
|
|
||||||
MODULE_DESCRIPTION("TI ADC controller driver");
|
MODULE_DESCRIPTION("TI ADC controller driver");
|
||||||
|
|||||||
@@ -24,8 +24,9 @@
|
|||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/input/ti_am335x_tsc.h>
|
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
|
||||||
#include <linux/mfd/ti_am335x_tscadc.h>
|
#include <linux/mfd/ti_am335x_tscadc.h>
|
||||||
|
|
||||||
@@ -33,6 +34,13 @@
|
|||||||
#define SEQ_SETTLE 275
|
#define SEQ_SETTLE 275
|
||||||
#define MAX_12BIT ((1 << 12) - 1)
|
#define MAX_12BIT ((1 << 12) - 1)
|
||||||
|
|
||||||
|
static const int config_pins[] = {
|
||||||
|
STEPCONFIG_XPP,
|
||||||
|
STEPCONFIG_XNN,
|
||||||
|
STEPCONFIG_YPP,
|
||||||
|
STEPCONFIG_YNN,
|
||||||
|
};
|
||||||
|
|
||||||
struct titsc {
|
struct titsc {
|
||||||
struct input_dev *input;
|
struct input_dev *input;
|
||||||
struct ti_tscadc_dev *mfd_tscadc;
|
struct ti_tscadc_dev *mfd_tscadc;
|
||||||
@@ -40,7 +48,10 @@ struct titsc {
|
|||||||
unsigned int wires;
|
unsigned int wires;
|
||||||
unsigned int x_plate_resistance;
|
unsigned int x_plate_resistance;
|
||||||
bool pen_down;
|
bool pen_down;
|
||||||
int steps_to_configure;
|
int coordinate_readouts;
|
||||||
|
u32 config_inp[4];
|
||||||
|
u32 bit_xp, bit_xn, bit_yp, bit_yn;
|
||||||
|
u32 inp_xp, inp_xn, inp_yp, inp_yn;
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
|
static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
|
||||||
@@ -54,92 +65,153 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg,
|
|||||||
writel(val, tsc->mfd_tscadc->tscadc_base + reg);
|
writel(val, tsc->mfd_tscadc->tscadc_base + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int titsc_config_wires(struct titsc *ts_dev)
|
||||||
|
{
|
||||||
|
u32 analog_line[4];
|
||||||
|
u32 wire_order[4];
|
||||||
|
int i, bit_cfg;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
/*
|
||||||
|
* Get the order in which TSC wires are attached
|
||||||
|
* w.r.t. each of the analog input lines on the EVM.
|
||||||
|
*/
|
||||||
|
analog_line[i] = (ts_dev->config_inp[i] & 0xF0) >> 4;
|
||||||
|
wire_order[i] = ts_dev->config_inp[i] & 0x0F;
|
||||||
|
if (WARN_ON(analog_line[i] > 7))
|
||||||
|
return -EINVAL;
|
||||||
|
if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins)))
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
int an_line;
|
||||||
|
int wi_order;
|
||||||
|
|
||||||
|
an_line = analog_line[i];
|
||||||
|
wi_order = wire_order[i];
|
||||||
|
bit_cfg = config_pins[wi_order];
|
||||||
|
if (bit_cfg == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
switch (wi_order) {
|
||||||
|
case 0:
|
||||||
|
ts_dev->bit_xp = bit_cfg;
|
||||||
|
ts_dev->inp_xp = an_line;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
ts_dev->bit_xn = bit_cfg;
|
||||||
|
ts_dev->inp_xn = an_line;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
ts_dev->bit_yp = bit_cfg;
|
||||||
|
ts_dev->inp_yp = an_line;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
ts_dev->bit_yn = bit_cfg;
|
||||||
|
ts_dev->inp_yn = an_line;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void titsc_step_config(struct titsc *ts_dev)
|
static void titsc_step_config(struct titsc *ts_dev)
|
||||||
{
|
{
|
||||||
unsigned int config;
|
unsigned int config;
|
||||||
int i, total_steps;
|
int i;
|
||||||
|
int end_step;
|
||||||
/* Configure the Step registers */
|
u32 stepenable;
|
||||||
total_steps = 2 * ts_dev->steps_to_configure;
|
|
||||||
|
|
||||||
config = STEPCONFIG_MODE_HWSYNC |
|
config = STEPCONFIG_MODE_HWSYNC |
|
||||||
STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
|
STEPCONFIG_AVG_16 | ts_dev->bit_xp;
|
||||||
switch (ts_dev->wires) {
|
switch (ts_dev->wires) {
|
||||||
case 4:
|
case 4:
|
||||||
config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
|
config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
config |= STEPCONFIG_YNN |
|
config |= ts_dev->bit_yn |
|
||||||
STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
|
STEPCONFIG_INP_AN4 | ts_dev->bit_xn |
|
||||||
STEPCONFIG_YPP;
|
ts_dev->bit_yp;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
|
config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 1; i <= ts_dev->steps_to_configure; i++) {
|
/* 1 … coordinate_readouts is for X */
|
||||||
|
end_step = ts_dev->coordinate_readouts;
|
||||||
|
for (i = 0; i < end_step; i++) {
|
||||||
titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
|
titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
|
||||||
titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
|
titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
config = 0;
|
config = 0;
|
||||||
config = STEPCONFIG_MODE_HWSYNC |
|
config = STEPCONFIG_MODE_HWSYNC |
|
||||||
STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
|
STEPCONFIG_AVG_16 | ts_dev->bit_yn |
|
||||||
STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
|
STEPCONFIG_INM_ADCREFM;
|
||||||
switch (ts_dev->wires) {
|
switch (ts_dev->wires) {
|
||||||
case 4:
|
case 4:
|
||||||
config |= STEPCONFIG_YPP;
|
config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
|
config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 |
|
||||||
STEPCONFIG_XNP | STEPCONFIG_YPN;
|
ts_dev->bit_xn | ts_dev->bit_yp;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
config |= STEPCONFIG_YPP;
|
config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) {
|
/* coordinate_readouts … coordinate_readouts * 2 is for Y */
|
||||||
|
end_step = ts_dev->coordinate_readouts * 2;
|
||||||
|
for (i = ts_dev->coordinate_readouts; i < end_step; i++) {
|
||||||
titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
|
titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
|
||||||
titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
|
titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
config = 0;
|
|
||||||
/* Charge step configuration */
|
/* Charge step configuration */
|
||||||
config = STEPCONFIG_XPP | STEPCONFIG_YNN |
|
config = ts_dev->bit_xp | ts_dev->bit_yn |
|
||||||
STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
|
STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
|
||||||
STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
|
STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp);
|
||||||
|
|
||||||
titsc_writel(ts_dev, REG_CHARGECONFIG, config);
|
titsc_writel(ts_dev, REG_CHARGECONFIG, config);
|
||||||
titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
|
titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
|
||||||
|
|
||||||
config = 0;
|
/* coordinate_readouts * 2 … coordinate_readouts * 2 + 2 is for Z */
|
||||||
/* Configure to calculate pressure */
|
|
||||||
config = STEPCONFIG_MODE_HWSYNC |
|
config = STEPCONFIG_MODE_HWSYNC |
|
||||||
STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
|
STEPCONFIG_AVG_16 | ts_dev->bit_yp |
|
||||||
STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
|
ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM |
|
||||||
titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
|
STEPCONFIG_INP(ts_dev->inp_xp);
|
||||||
titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
|
titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
|
||||||
|
titsc_writel(ts_dev, REG_STEPDELAY(end_step),
|
||||||
STEPCONFIG_OPENDLY);
|
STEPCONFIG_OPENDLY);
|
||||||
|
|
||||||
config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
|
end_step++;
|
||||||
titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
|
config |= STEPCONFIG_INP(ts_dev->inp_yn);
|
||||||
titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
|
titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
|
||||||
|
titsc_writel(ts_dev, REG_STEPDELAY(end_step),
|
||||||
STEPCONFIG_OPENDLY);
|
STEPCONFIG_OPENDLY);
|
||||||
|
|
||||||
titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
|
/* The steps1 … end and bit 0 for TS_Charge */
|
||||||
|
stepenable = (1 << (end_step + 2)) - 1;
|
||||||
|
am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void titsc_read_coordinates(struct titsc *ts_dev,
|
static void titsc_read_coordinates(struct titsc *ts_dev,
|
||||||
unsigned int *x, unsigned int *y)
|
u32 *x, u32 *y, u32 *z1, u32 *z2)
|
||||||
{
|
{
|
||||||
unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT);
|
unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT);
|
||||||
unsigned int prev_val_x = ~0, prev_val_y = ~0;
|
unsigned int prev_val_x = ~0, prev_val_y = ~0;
|
||||||
unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
|
unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
|
||||||
unsigned int read, diff;
|
unsigned int read, diff;
|
||||||
unsigned int i, channel;
|
unsigned int i, channel;
|
||||||
|
unsigned int creads = ts_dev->coordinate_readouts;
|
||||||
|
|
||||||
|
*z1 = *z2 = 0;
|
||||||
|
if (fifocount % (creads * 2 + 2))
|
||||||
|
fifocount -= fifocount % (creads * 2 + 2);
|
||||||
/*
|
/*
|
||||||
* Delta filter is used to remove large variations in sampled
|
* Delta filter is used to remove large variations in sampled
|
||||||
* values from ADC. The filter tries to predict where the next
|
* values from ADC. The filter tries to predict where the next
|
||||||
@@ -148,32 +220,32 @@ static void titsc_read_coordinates(struct titsc *ts_dev,
|
|||||||
* algorithm compares the difference with that of a present value,
|
* algorithm compares the difference with that of a present value,
|
||||||
* if true the value is reported to the sub system.
|
* if true the value is reported to the sub system.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < fifocount - 1; i++) {
|
for (i = 0; i < fifocount; i++) {
|
||||||
read = titsc_readl(ts_dev, REG_FIFO0);
|
read = titsc_readl(ts_dev, REG_FIFO0);
|
||||||
channel = read & 0xf0000;
|
|
||||||
channel = channel >> 0x10;
|
channel = (read & 0xf0000) >> 16;
|
||||||
if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) {
|
read &= 0xfff;
|
||||||
read &= 0xfff;
|
if (channel < creads) {
|
||||||
diff = abs(read - prev_val_x);
|
diff = abs(read - prev_val_x);
|
||||||
if (diff < prev_diff_x) {
|
if (diff < prev_diff_x) {
|
||||||
prev_diff_x = diff;
|
prev_diff_x = diff;
|
||||||
*x = read;
|
*x = read;
|
||||||
}
|
}
|
||||||
prev_val_x = read;
|
prev_val_x = read;
|
||||||
}
|
|
||||||
|
|
||||||
read = titsc_readl(ts_dev, REG_FIFO1);
|
} else if (channel < creads * 2) {
|
||||||
channel = read & 0xf0000;
|
|
||||||
channel = channel >> 0x10;
|
|
||||||
if ((channel >= ts_dev->steps_to_configure) &&
|
|
||||||
(channel < (2 * ts_dev->steps_to_configure - 1))) {
|
|
||||||
read &= 0xfff;
|
|
||||||
diff = abs(read - prev_val_y);
|
diff = abs(read - prev_val_y);
|
||||||
if (diff < prev_diff_y) {
|
if (diff < prev_diff_y) {
|
||||||
prev_diff_y = diff;
|
prev_diff_y = diff;
|
||||||
*y = read;
|
*y = read;
|
||||||
}
|
}
|
||||||
prev_val_y = read;
|
prev_val_y = read;
|
||||||
|
|
||||||
|
} else if (channel < creads * 2 + 1) {
|
||||||
|
*z1 = read;
|
||||||
|
|
||||||
|
} else if (channel < creads * 2 + 2) {
|
||||||
|
*z2 = read;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,23 +258,11 @@ static irqreturn_t titsc_irq(int irq, void *dev)
|
|||||||
unsigned int x = 0, y = 0;
|
unsigned int x = 0, y = 0;
|
||||||
unsigned int z1, z2, z;
|
unsigned int z1, z2, z;
|
||||||
unsigned int fsm;
|
unsigned int fsm;
|
||||||
unsigned int fifo1count, fifo0count;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
status = titsc_readl(ts_dev, REG_IRQSTATUS);
|
status = titsc_readl(ts_dev, REG_IRQSTATUS);
|
||||||
if (status & IRQENB_FIFO0THRES) {
|
if (status & IRQENB_FIFO0THRES) {
|
||||||
titsc_read_coordinates(ts_dev, &x, &y);
|
|
||||||
|
|
||||||
z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
|
titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
|
||||||
z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
|
|
||||||
|
|
||||||
fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT);
|
|
||||||
for (i = 0; i < fifo1count; i++)
|
|
||||||
titsc_readl(ts_dev, REG_FIFO1);
|
|
||||||
|
|
||||||
fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT);
|
|
||||||
for (i = 0; i < fifo0count; i++)
|
|
||||||
titsc_readl(ts_dev, REG_FIFO0);
|
|
||||||
|
|
||||||
if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
|
if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
|
||||||
/*
|
/*
|
||||||
@@ -210,10 +270,10 @@ static irqreturn_t titsc_irq(int irq, void *dev)
|
|||||||
* Resistance(touch) = x plate resistance *
|
* Resistance(touch) = x plate resistance *
|
||||||
* x postion/4096 * ((z2 / z1) - 1)
|
* x postion/4096 * ((z2 / z1) - 1)
|
||||||
*/
|
*/
|
||||||
z = z2 - z1;
|
z = z1 - z2;
|
||||||
z *= x;
|
z *= x;
|
||||||
z *= ts_dev->x_plate_resistance;
|
z *= ts_dev->x_plate_resistance;
|
||||||
z /= z1;
|
z /= z2;
|
||||||
z = (z + 2047) >> 12;
|
z = (z + 2047) >> 12;
|
||||||
|
|
||||||
if (z <= MAX_12BIT) {
|
if (z <= MAX_12BIT) {
|
||||||
@@ -248,10 +308,53 @@ static irqreturn_t titsc_irq(int irq, void *dev)
|
|||||||
irqclr |= IRQENB_PENUP;
|
irqclr |= IRQENB_PENUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
|
if (status & IRQENB_HW_PEN) {
|
||||||
|
|
||||||
titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
|
titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00);
|
||||||
return IRQ_HANDLED;
|
titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (irqclr) {
|
||||||
|
titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
|
||||||
|
am335x_tsc_se_update(ts_dev->mfd_tscadc);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
return IRQ_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int titsc_parse_dt(struct platform_device *pdev,
|
||||||
|
struct titsc *ts_dev)
|
||||||
|
{
|
||||||
|
struct device_node *node = pdev->dev.of_node;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
err = of_property_read_u32(node, "ti,wires", &ts_dev->wires);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
switch (ts_dev->wires) {
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 8:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = of_property_read_u32(node, "ti,x-plate-resistance",
|
||||||
|
&ts_dev->x_plate_resistance);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = of_property_read_u32(node, "ti,coordiante-readouts",
|
||||||
|
&ts_dev->coordinate_readouts);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return of_property_read_u32_array(node, "ti,wire-config",
|
||||||
|
ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -262,17 +365,9 @@ static int titsc_probe(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct titsc *ts_dev;
|
struct titsc *ts_dev;
|
||||||
struct input_dev *input_dev;
|
struct input_dev *input_dev;
|
||||||
struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
|
struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev);
|
||||||
struct mfd_tscadc_board *pdata;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
pdata = tscadc_dev->dev->platform_data;
|
|
||||||
|
|
||||||
if (!pdata) {
|
|
||||||
dev_err(&pdev->dev, "Could not find platform data\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate memory for device */
|
/* Allocate memory for device */
|
||||||
ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
|
ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
|
||||||
input_dev = input_allocate_device();
|
input_dev = input_allocate_device();
|
||||||
@@ -286,9 +381,12 @@ static int titsc_probe(struct platform_device *pdev)
|
|||||||
ts_dev->mfd_tscadc = tscadc_dev;
|
ts_dev->mfd_tscadc = tscadc_dev;
|
||||||
ts_dev->input = input_dev;
|
ts_dev->input = input_dev;
|
||||||
ts_dev->irq = tscadc_dev->irq;
|
ts_dev->irq = tscadc_dev->irq;
|
||||||
ts_dev->wires = pdata->tsc_init->wires;
|
|
||||||
ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance;
|
err = titsc_parse_dt(pdev, ts_dev);
|
||||||
ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure;
|
if (err) {
|
||||||
|
dev_err(&pdev->dev, "Could not find valid DT data.\n");
|
||||||
|
goto err_free_mem;
|
||||||
|
}
|
||||||
|
|
||||||
err = request_irq(ts_dev->irq, titsc_irq,
|
err = request_irq(ts_dev->irq, titsc_irq,
|
||||||
0, pdev->dev.driver->name, ts_dev);
|
0, pdev->dev.driver->name, ts_dev);
|
||||||
@@ -298,8 +396,14 @@ static int titsc_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
|
titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
|
||||||
|
err = titsc_config_wires(ts_dev);
|
||||||
|
if (err) {
|
||||||
|
dev_err(&pdev->dev, "wrong i/p wire configuration\n");
|
||||||
|
goto err_free_irq;
|
||||||
|
}
|
||||||
titsc_step_config(ts_dev);
|
titsc_step_config(ts_dev);
|
||||||
titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
|
titsc_writel(ts_dev, REG_FIFO0THR,
|
||||||
|
ts_dev->coordinate_readouts * 2 + 2 - 1);
|
||||||
|
|
||||||
input_dev->name = "ti-tsc";
|
input_dev->name = "ti-tsc";
|
||||||
input_dev->dev.parent = &pdev->dev;
|
input_dev->dev.parent = &pdev->dev;
|
||||||
@@ -329,11 +433,16 @@ err_free_mem:
|
|||||||
|
|
||||||
static int titsc_remove(struct platform_device *pdev)
|
static int titsc_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
|
struct titsc *ts_dev = platform_get_drvdata(pdev);
|
||||||
struct titsc *ts_dev = tscadc_dev->tsc;
|
u32 steps;
|
||||||
|
|
||||||
free_irq(ts_dev->irq, ts_dev);
|
free_irq(ts_dev->irq, ts_dev);
|
||||||
|
|
||||||
|
/* total steps followed by the enable mask */
|
||||||
|
steps = 2 * ts_dev->coordinate_readouts + 2;
|
||||||
|
steps = (1 << steps) - 1;
|
||||||
|
am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps);
|
||||||
|
|
||||||
input_unregister_device(ts_dev->input);
|
input_unregister_device(ts_dev->input);
|
||||||
|
|
||||||
kfree(ts_dev);
|
kfree(ts_dev);
|
||||||
@@ -343,10 +452,11 @@ static int titsc_remove(struct platform_device *pdev)
|
|||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
static int titsc_suspend(struct device *dev)
|
static int titsc_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
|
struct titsc *ts_dev = dev_get_drvdata(dev);
|
||||||
struct titsc *ts_dev = tscadc_dev->tsc;
|
struct ti_tscadc_dev *tscadc_dev;
|
||||||
unsigned int idle;
|
unsigned int idle;
|
||||||
|
|
||||||
|
tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
|
||||||
if (device_may_wakeup(tscadc_dev->dev)) {
|
if (device_may_wakeup(tscadc_dev->dev)) {
|
||||||
idle = titsc_readl(ts_dev, REG_IRQENABLE);
|
idle = titsc_readl(ts_dev, REG_IRQENABLE);
|
||||||
titsc_writel(ts_dev, REG_IRQENABLE,
|
titsc_writel(ts_dev, REG_IRQENABLE,
|
||||||
@@ -358,9 +468,10 @@ static int titsc_suspend(struct device *dev)
|
|||||||
|
|
||||||
static int titsc_resume(struct device *dev)
|
static int titsc_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
|
struct titsc *ts_dev = dev_get_drvdata(dev);
|
||||||
struct titsc *ts_dev = tscadc_dev->tsc;
|
struct ti_tscadc_dev *tscadc_dev;
|
||||||
|
|
||||||
|
tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
|
||||||
if (device_may_wakeup(tscadc_dev->dev)) {
|
if (device_may_wakeup(tscadc_dev->dev)) {
|
||||||
titsc_writel(ts_dev, REG_IRQWAKEUP,
|
titsc_writel(ts_dev, REG_IRQWAKEUP,
|
||||||
0x00);
|
0x00);
|
||||||
@@ -368,7 +479,7 @@ static int titsc_resume(struct device *dev)
|
|||||||
}
|
}
|
||||||
titsc_step_config(ts_dev);
|
titsc_step_config(ts_dev);
|
||||||
titsc_writel(ts_dev, REG_FIFO0THR,
|
titsc_writel(ts_dev, REG_FIFO0THR,
|
||||||
ts_dev->steps_to_configure);
|
ts_dev->coordinate_readouts * 2 + 2 - 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,13 +492,20 @@ static const struct dev_pm_ops titsc_pm_ops = {
|
|||||||
#define TITSC_PM_OPS NULL
|
#define TITSC_PM_OPS NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static const struct of_device_id ti_tsc_dt_ids[] = {
|
||||||
|
{ .compatible = "ti,am3359-tsc", },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids);
|
||||||
|
|
||||||
static struct platform_driver ti_tsc_driver = {
|
static struct platform_driver ti_tsc_driver = {
|
||||||
.probe = titsc_probe,
|
.probe = titsc_probe,
|
||||||
.remove = titsc_remove,
|
.remove = titsc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "tsc",
|
.name = "TI-am335x-tsc",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.pm = TITSC_PM_OPS,
|
.pm = TITSC_PM_OPS,
|
||||||
|
.of_match_table = of_match_ptr(ti_tsc_dt_ids),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
module_platform_driver(ti_tsc_driver);
|
module_platform_driver(ti_tsc_driver);
|
||||||
|
|||||||
+137
-97
@@ -22,13 +22,12 @@
|
|||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/err.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/mfd/core.h>
|
#include <linux/mfd/core.h>
|
||||||
#include <linux/mfd/88pm80x.h>
|
#include <linux/mfd/88pm80x.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
#define PM800_CHIP_ID (0x00)
|
|
||||||
|
|
||||||
/* Interrupt Registers */
|
/* Interrupt Registers */
|
||||||
#define PM800_INT_STATUS1 (0x05)
|
#define PM800_INT_STATUS1 (0x05)
|
||||||
#define PM800_ONKEY_INT_STS1 (1 << 0)
|
#define PM800_ONKEY_INT_STS1 (1 << 0)
|
||||||
@@ -113,20 +112,11 @@ enum {
|
|||||||
PM800_MAX_IRQ,
|
PM800_MAX_IRQ,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
/* PM800: generation identification number */
|
||||||
/* Procida */
|
#define PM800_CHIP_GEN_ID_NUM 0x3
|
||||||
PM800_CHIP_A0 = 0x60,
|
|
||||||
PM800_CHIP_A1 = 0x61,
|
|
||||||
PM800_CHIP_B0 = 0x62,
|
|
||||||
PM800_CHIP_C0 = 0x63,
|
|
||||||
PM800_CHIP_END = PM800_CHIP_C0,
|
|
||||||
|
|
||||||
/* Make sure to update this to the last stepping */
|
|
||||||
PM8XXX_CHIP_END = PM800_CHIP_END
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct i2c_device_id pm80x_id_table[] = {
|
static const struct i2c_device_id pm80x_id_table[] = {
|
||||||
{"88PM800", CHIP_PM800},
|
{"88PM800", 0},
|
||||||
{} /* NULL terminated */
|
{} /* NULL terminated */
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, pm80x_id_table);
|
MODULE_DEVICE_TABLE(i2c, pm80x_id_table);
|
||||||
@@ -167,6 +157,13 @@ static struct mfd_cell onkey_devs[] = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct mfd_cell regulator_devs[] = {
|
||||||
|
{
|
||||||
|
.name = "88pm80x-regulator",
|
||||||
|
.id = -1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static const struct regmap_irq pm800_irqs[] = {
|
static const struct regmap_irq pm800_irqs[] = {
|
||||||
/* INT0 */
|
/* INT0 */
|
||||||
[PM800_IRQ_ONKEY] = {
|
[PM800_IRQ_ONKEY] = {
|
||||||
@@ -315,10 +312,59 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int device_onkey_init(struct pm80x_chip *chip,
|
||||||
|
struct pm80x_platform_data *pdata)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
|
||||||
|
ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0,
|
||||||
|
NULL);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(chip->dev, "Failed to add onkey subdev\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int device_rtc_init(struct pm80x_chip *chip,
|
||||||
|
struct pm80x_platform_data *pdata)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
rtc_devs[0].platform_data = pdata->rtc;
|
||||||
|
rtc_devs[0].pdata_size =
|
||||||
|
pdata->rtc ? sizeof(struct pm80x_rtc_pdata) : 0;
|
||||||
|
ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
|
||||||
|
ARRAY_SIZE(rtc_devs), NULL, 0, NULL);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(chip->dev, "Failed to add rtc subdev\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int device_regulator_init(struct pm80x_chip *chip,
|
||||||
|
struct pm80x_platform_data *pdata)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0],
|
||||||
|
ARRAY_SIZE(regulator_devs), NULL, 0, NULL);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(chip->dev, "Failed to add regulator subdev\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int device_irq_init_800(struct pm80x_chip *chip)
|
static int device_irq_init_800(struct pm80x_chip *chip)
|
||||||
{
|
{
|
||||||
struct regmap *map = chip->regmap;
|
struct regmap *map = chip->regmap;
|
||||||
unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
|
unsigned long flags = IRQF_ONESHOT;
|
||||||
int data, mask, ret = -EINVAL;
|
int data, mask, ret = -EINVAL;
|
||||||
|
|
||||||
if (!map || !chip->irq) {
|
if (!map || !chip->irq) {
|
||||||
@@ -362,6 +408,7 @@ static struct regmap_irq_chip pm800_irq_chip = {
|
|||||||
.status_base = PM800_INT_STATUS1,
|
.status_base = PM800_INT_STATUS1,
|
||||||
.mask_base = PM800_INT_ENA_1,
|
.mask_base = PM800_INT_ENA_1,
|
||||||
.ack_base = PM800_INT_STATUS1,
|
.ack_base = PM800_INT_STATUS1,
|
||||||
|
.mask_invert = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int pm800_pages_init(struct pm80x_chip *chip)
|
static int pm800_pages_init(struct pm80x_chip *chip)
|
||||||
@@ -369,77 +416,72 @@ static int pm800_pages_init(struct pm80x_chip *chip)
|
|||||||
struct pm80x_subchip *subchip;
|
struct pm80x_subchip *subchip;
|
||||||
struct i2c_client *client = chip->client;
|
struct i2c_client *client = chip->client;
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
subchip = chip->subchip;
|
subchip = chip->subchip;
|
||||||
/* PM800 block power: i2c addr 0x31 */
|
if (!subchip || !subchip->power_page_addr || !subchip->gpadc_page_addr)
|
||||||
if (subchip->power_page_addr) {
|
return -ENODEV;
|
||||||
subchip->power_page =
|
|
||||||
i2c_new_dummy(client->adapter, subchip->power_page_addr);
|
|
||||||
subchip->regmap_power =
|
|
||||||
devm_regmap_init_i2c(subchip->power_page,
|
|
||||||
&pm80x_regmap_config);
|
|
||||||
i2c_set_clientdata(subchip->power_page, chip);
|
|
||||||
} else
|
|
||||||
dev_info(chip->dev,
|
|
||||||
"PM800 block power 0x31: No power_page_addr\n");
|
|
||||||
|
|
||||||
/* PM800 block GPADC: i2c addr 0x32 */
|
/* PM800 block power page */
|
||||||
if (subchip->gpadc_page_addr) {
|
subchip->power_page = i2c_new_dummy(client->adapter,
|
||||||
subchip->gpadc_page = i2c_new_dummy(client->adapter,
|
subchip->power_page_addr);
|
||||||
subchip->gpadc_page_addr);
|
if (subchip->power_page == NULL) {
|
||||||
subchip->regmap_gpadc =
|
ret = -ENODEV;
|
||||||
devm_regmap_init_i2c(subchip->gpadc_page,
|
goto out;
|
||||||
&pm80x_regmap_config);
|
}
|
||||||
i2c_set_clientdata(subchip->gpadc_page, chip);
|
|
||||||
} else
|
|
||||||
dev_info(chip->dev,
|
|
||||||
"PM800 block GPADC 0x32: No gpadc_page_addr\n");
|
|
||||||
|
|
||||||
return 0;
|
subchip->regmap_power = devm_regmap_init_i2c(subchip->power_page,
|
||||||
|
&pm80x_regmap_config);
|
||||||
|
if (IS_ERR(subchip->regmap_power)) {
|
||||||
|
ret = PTR_ERR(subchip->regmap_power);
|
||||||
|
dev_err(chip->dev,
|
||||||
|
"Failed to allocate regmap_power: %d\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_set_clientdata(subchip->power_page, chip);
|
||||||
|
|
||||||
|
/* PM800 block GPADC */
|
||||||
|
subchip->gpadc_page = i2c_new_dummy(client->adapter,
|
||||||
|
subchip->gpadc_page_addr);
|
||||||
|
if (subchip->gpadc_page == NULL) {
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
subchip->regmap_gpadc = devm_regmap_init_i2c(subchip->gpadc_page,
|
||||||
|
&pm80x_regmap_config);
|
||||||
|
if (IS_ERR(subchip->regmap_gpadc)) {
|
||||||
|
ret = PTR_ERR(subchip->regmap_gpadc);
|
||||||
|
dev_err(chip->dev,
|
||||||
|
"Failed to allocate regmap_gpadc: %d\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
i2c_set_clientdata(subchip->gpadc_page, chip);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pm800_pages_exit(struct pm80x_chip *chip)
|
static void pm800_pages_exit(struct pm80x_chip *chip)
|
||||||
{
|
{
|
||||||
struct pm80x_subchip *subchip;
|
struct pm80x_subchip *subchip;
|
||||||
|
|
||||||
regmap_exit(chip->regmap);
|
|
||||||
i2c_unregister_device(chip->client);
|
|
||||||
|
|
||||||
subchip = chip->subchip;
|
subchip = chip->subchip;
|
||||||
if (subchip->power_page) {
|
|
||||||
regmap_exit(subchip->regmap_power);
|
if (subchip && subchip->power_page)
|
||||||
i2c_unregister_device(subchip->power_page);
|
i2c_unregister_device(subchip->power_page);
|
||||||
}
|
|
||||||
if (subchip->gpadc_page) {
|
if (subchip && subchip->gpadc_page)
|
||||||
regmap_exit(subchip->regmap_gpadc);
|
|
||||||
i2c_unregister_device(subchip->gpadc_page);
|
i2c_unregister_device(subchip->gpadc_page);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int device_800_init(struct pm80x_chip *chip,
|
static int device_800_init(struct pm80x_chip *chip,
|
||||||
struct pm80x_platform_data *pdata)
|
struct pm80x_platform_data *pdata)
|
||||||
{
|
{
|
||||||
int ret, pmic_id;
|
int ret;
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
|
|
||||||
ret = regmap_read(chip->regmap, PM800_CHIP_ID, &val);
|
|
||||||
if (ret < 0) {
|
|
||||||
dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
pmic_id = val & PM80X_VERSION_MASK;
|
|
||||||
|
|
||||||
if ((pmic_id >= PM800_CHIP_A0) && (pmic_id <= PM800_CHIP_END)) {
|
|
||||||
chip->version = val;
|
|
||||||
dev_info(chip->dev,
|
|
||||||
"88PM80x:Marvell 88PM800 (ID:0x%x) detected\n", val);
|
|
||||||
} else {
|
|
||||||
dev_err(chip->dev,
|
|
||||||
"Failed to detect Marvell 88PM800:ChipID[0x%x]\n", val);
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* alarm wake up bit will be clear in device_irq_init(),
|
* alarm wake up bit will be clear in device_irq_init(),
|
||||||
* read before that
|
* read before that
|
||||||
@@ -468,27 +510,22 @@ static int device_800_init(struct pm80x_chip *chip,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret =
|
ret = device_onkey_init(chip, pdata);
|
||||||
mfd_add_devices(chip->dev, 0, &onkey_devs[0],
|
if (ret) {
|
||||||
ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0,
|
|
||||||
NULL);
|
|
||||||
if (ret < 0) {
|
|
||||||
dev_err(chip->dev, "Failed to add onkey subdev\n");
|
dev_err(chip->dev, "Failed to add onkey subdev\n");
|
||||||
goto out_dev;
|
goto out_dev;
|
||||||
} else
|
}
|
||||||
dev_info(chip->dev, "[%s]:Added mfd onkey_devs\n", __func__);
|
|
||||||
|
|
||||||
if (pdata && pdata->rtc) {
|
ret = device_rtc_init(chip, pdata);
|
||||||
rtc_devs[0].platform_data = pdata->rtc;
|
if (ret) {
|
||||||
rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata);
|
dev_err(chip->dev, "Failed to add rtc subdev\n");
|
||||||
ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
|
goto out;
|
||||||
ARRAY_SIZE(rtc_devs), NULL, 0, NULL);
|
}
|
||||||
if (ret < 0) {
|
|
||||||
dev_err(chip->dev, "Failed to add rtc subdev\n");
|
ret = device_regulator_init(chip, pdata);
|
||||||
goto out_dev;
|
if (ret) {
|
||||||
} else
|
dev_err(chip->dev, "Failed to add regulators subdev\n");
|
||||||
dev_info(chip->dev,
|
goto out;
|
||||||
"[%s]:Added mfd rtc_devs\n", __func__);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -507,7 +544,7 @@ static int pm800_probe(struct i2c_client *client,
|
|||||||
struct pm80x_platform_data *pdata = client->dev.platform_data;
|
struct pm80x_platform_data *pdata = client->dev.platform_data;
|
||||||
struct pm80x_subchip *subchip;
|
struct pm80x_subchip *subchip;
|
||||||
|
|
||||||
ret = pm80x_init(client, id);
|
ret = pm80x_init(client);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&client->dev, "pm800_init fail\n");
|
dev_err(&client->dev, "pm800_init fail\n");
|
||||||
goto out_init;
|
goto out_init;
|
||||||
@@ -524,28 +561,31 @@ static int pm800_probe(struct i2c_client *client,
|
|||||||
goto err_subchip_alloc;
|
goto err_subchip_alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
subchip->power_page_addr = pdata->power_page_addr;
|
/* pm800 has 2 addtional pages to support power and gpadc. */
|
||||||
subchip->gpadc_page_addr = pdata->gpadc_page_addr;
|
subchip->power_page_addr = client->addr + 1;
|
||||||
|
subchip->gpadc_page_addr = client->addr + 2;
|
||||||
chip->subchip = subchip;
|
chip->subchip = subchip;
|
||||||
|
|
||||||
ret = device_800_init(chip, pdata);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id);
|
|
||||||
goto err_subchip_alloc;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = pm800_pages_init(chip);
|
ret = pm800_pages_init(chip);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&client->dev, "pm800_pages_init failed!\n");
|
dev_err(&client->dev, "pm800_pages_init failed!\n");
|
||||||
goto err_page_init;
|
goto err_page_init;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = device_800_init(chip, pdata);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(chip->dev, "Failed to initialize 88pm800 devices\n");
|
||||||
|
goto err_device_init;
|
||||||
|
}
|
||||||
|
|
||||||
if (pdata->plat_config)
|
if (pdata->plat_config)
|
||||||
pdata->plat_config(chip, pdata);
|
pdata->plat_config(chip, pdata);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_device_init:
|
||||||
|
pm800_pages_exit(chip);
|
||||||
err_page_init:
|
err_page_init:
|
||||||
mfd_remove_devices(chip->dev);
|
|
||||||
device_irq_exit_800(chip);
|
|
||||||
err_subchip_alloc:
|
err_subchip_alloc:
|
||||||
pm80x_deinit();
|
pm80x_deinit();
|
||||||
out_init:
|
out_init:
|
||||||
@@ -567,7 +607,7 @@ static int pm800_remove(struct i2c_client *client)
|
|||||||
|
|
||||||
static struct i2c_driver pm800_driver = {
|
static struct i2c_driver pm800_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "88PM80X",
|
.name = "88PM800",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.pm = &pm80x_pm_ops,
|
.pm = &pm80x_pm_ops,
|
||||||
},
|
},
|
||||||
|
|||||||
+5
-15
@@ -29,10 +29,8 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
|
||||||
#define PM805_CHIP_ID (0x00)
|
|
||||||
|
|
||||||
static const struct i2c_device_id pm80x_id_table[] = {
|
static const struct i2c_device_id pm80x_id_table[] = {
|
||||||
{"88PM805", CHIP_PM805},
|
{"88PM805", 0},
|
||||||
{} /* NULL terminated */
|
{} /* NULL terminated */
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, pm80x_id_table);
|
MODULE_DEVICE_TABLE(i2c, pm80x_id_table);
|
||||||
@@ -138,7 +136,7 @@ static struct regmap_irq pm805_irqs[] = {
|
|||||||
static int device_irq_init_805(struct pm80x_chip *chip)
|
static int device_irq_init_805(struct pm80x_chip *chip)
|
||||||
{
|
{
|
||||||
struct regmap *map = chip->regmap;
|
struct regmap *map = chip->regmap;
|
||||||
unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
|
unsigned long flags = IRQF_ONESHOT;
|
||||||
int data, mask, ret = -EINVAL;
|
int data, mask, ret = -EINVAL;
|
||||||
|
|
||||||
if (!map || !chip->irq) {
|
if (!map || !chip->irq) {
|
||||||
@@ -192,7 +190,6 @@ static struct regmap_irq_chip pm805_irq_chip = {
|
|||||||
static int device_805_init(struct pm80x_chip *chip)
|
static int device_805_init(struct pm80x_chip *chip)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned int val;
|
|
||||||
struct regmap *map = chip->regmap;
|
struct regmap *map = chip->regmap;
|
||||||
|
|
||||||
if (!map) {
|
if (!map) {
|
||||||
@@ -200,13 +197,6 @@ static int device_805_init(struct pm80x_chip *chip)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_read(map, PM805_CHIP_ID, &val);
|
|
||||||
if (ret < 0) {
|
|
||||||
dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
|
|
||||||
goto out_irq_init;
|
|
||||||
}
|
|
||||||
chip->version = val;
|
|
||||||
|
|
||||||
chip->regmap_irq_chip = &pm805_irq_chip;
|
chip->regmap_irq_chip = &pm805_irq_chip;
|
||||||
|
|
||||||
ret = device_irq_init_805(chip);
|
ret = device_irq_init_805(chip);
|
||||||
@@ -239,7 +229,7 @@ static int pm805_probe(struct i2c_client *client,
|
|||||||
struct pm80x_chip *chip;
|
struct pm80x_chip *chip;
|
||||||
struct pm80x_platform_data *pdata = client->dev.platform_data;
|
struct pm80x_platform_data *pdata = client->dev.platform_data;
|
||||||
|
|
||||||
ret = pm80x_init(client, id);
|
ret = pm80x_init(client);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&client->dev, "pm805_init fail!\n");
|
dev_err(&client->dev, "pm805_init fail!\n");
|
||||||
goto out_init;
|
goto out_init;
|
||||||
@@ -249,7 +239,7 @@ static int pm805_probe(struct i2c_client *client,
|
|||||||
|
|
||||||
ret = device_805_init(chip);
|
ret = device_805_init(chip);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id);
|
dev_err(chip->dev, "Failed to initialize 88pm805 devices\n");
|
||||||
goto err_805_init;
|
goto err_805_init;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,7 +266,7 @@ static int pm805_remove(struct i2c_client *client)
|
|||||||
|
|
||||||
static struct i2c_driver pm805_driver = {
|
static struct i2c_driver pm805_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "88PM80X",
|
.name = "88PM805",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.pm = &pm80x_pm_ops,
|
.pm = &pm80x_pm_ops,
|
||||||
},
|
},
|
||||||
|
|||||||
+40
-7
@@ -18,6 +18,23 @@
|
|||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
|
||||||
|
/* 88pm80x chips have same definition for chip id register. */
|
||||||
|
#define PM80X_CHIP_ID (0x00)
|
||||||
|
#define PM80X_CHIP_ID_NUM(x) (((x) >> 5) & 0x7)
|
||||||
|
#define PM80X_CHIP_ID_REVISION(x) ((x) & 0x1F)
|
||||||
|
|
||||||
|
struct pm80x_chip_mapping {
|
||||||
|
unsigned int id;
|
||||||
|
int type;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct pm80x_chip_mapping chip_mapping[] = {
|
||||||
|
/* 88PM800 chip id number */
|
||||||
|
{0x3, CHIP_PM800},
|
||||||
|
/* 88PM805 chip id number */
|
||||||
|
{0x0, CHIP_PM805},
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* workaround: some registers needed by pm805 are defined in pm800, so
|
* workaround: some registers needed by pm805 are defined in pm800, so
|
||||||
* need to use this global variable to maintain the relation between
|
* need to use this global variable to maintain the relation between
|
||||||
@@ -31,12 +48,13 @@ const struct regmap_config pm80x_regmap_config = {
|
|||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(pm80x_regmap_config);
|
EXPORT_SYMBOL_GPL(pm80x_regmap_config);
|
||||||
|
|
||||||
int pm80x_init(struct i2c_client *client,
|
|
||||||
const struct i2c_device_id *id)
|
int pm80x_init(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct pm80x_chip *chip;
|
struct pm80x_chip *chip;
|
||||||
struct regmap *map;
|
struct regmap *map;
|
||||||
int ret = 0;
|
unsigned int val;
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
chip =
|
chip =
|
||||||
devm_kzalloc(&client->dev, sizeof(struct pm80x_chip), GFP_KERNEL);
|
devm_kzalloc(&client->dev, sizeof(struct pm80x_chip), GFP_KERNEL);
|
||||||
@@ -51,10 +69,6 @@ int pm80x_init(struct i2c_client *client,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
chip->id = id->driver_data;
|
|
||||||
if (chip->id < CHIP_PM800 || chip->id > CHIP_PM805)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
chip->client = client;
|
chip->client = client;
|
||||||
chip->regmap = map;
|
chip->regmap = map;
|
||||||
|
|
||||||
@@ -64,6 +78,25 @@ int pm80x_init(struct i2c_client *client,
|
|||||||
dev_set_drvdata(chip->dev, chip);
|
dev_set_drvdata(chip->dev, chip);
|
||||||
i2c_set_clientdata(chip->client, chip);
|
i2c_set_clientdata(chip->client, chip);
|
||||||
|
|
||||||
|
ret = regmap_read(chip->regmap, PM80X_CHIP_ID, &val);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(chip_mapping); i++) {
|
||||||
|
if (chip_mapping[i].id == PM80X_CHIP_ID_NUM(val)) {
|
||||||
|
chip->type = chip_mapping[i].type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == ARRAY_SIZE(chip_mapping)) {
|
||||||
|
dev_err(chip->dev,
|
||||||
|
"Failed to detect Marvell 88PM800:ChipID[0x%x]\n", val);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
device_init_wakeup(&client->dev, 1);
|
device_init_wakeup(&client->dev, 1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1150,17 +1150,17 @@ static int pm860x_probe(struct i2c_client *client,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL);
|
chip = devm_kzalloc(&client->dev,
|
||||||
|
sizeof(struct pm860x_chip), GFP_KERNEL);
|
||||||
if (chip == NULL)
|
if (chip == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
chip->id = verify_addr(client);
|
chip->id = verify_addr(client);
|
||||||
chip->regmap = regmap_init_i2c(client, &pm860x_regmap_config);
|
chip->regmap = devm_regmap_init_i2c(client, &pm860x_regmap_config);
|
||||||
if (IS_ERR(chip->regmap)) {
|
if (IS_ERR(chip->regmap)) {
|
||||||
ret = PTR_ERR(chip->regmap);
|
ret = PTR_ERR(chip->regmap);
|
||||||
dev_err(&client->dev, "Failed to allocate register map: %d\n",
|
dev_err(&client->dev, "Failed to allocate register map: %d\n",
|
||||||
ret);
|
ret);
|
||||||
kfree(chip);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
chip->client = client;
|
chip->client = client;
|
||||||
@@ -1203,8 +1203,6 @@ static int pm860x_remove(struct i2c_client *client)
|
|||||||
regmap_exit(chip->regmap_companion);
|
regmap_exit(chip->regmap_companion);
|
||||||
i2c_unregister_device(chip->companion);
|
i2c_unregister_device(chip->companion);
|
||||||
}
|
}
|
||||||
regmap_exit(chip->regmap);
|
|
||||||
kfree(chip);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+33
-3
@@ -53,7 +53,7 @@ config MFD_CROS_EC
|
|||||||
help
|
help
|
||||||
If you say Y here you get support for the ChromeOS Embedded
|
If you say Y here you get support for the ChromeOS Embedded
|
||||||
Controller (EC) providing keyboard, battery and power services.
|
Controller (EC) providing keyboard, battery and power services.
|
||||||
You also ned to enable the driver for the bus you are using. The
|
You also need to enable the driver for the bus you are using. The
|
||||||
protocol for talking to the EC is defined by the bus driver.
|
protocol for talking to the EC is defined by the bus driver.
|
||||||
|
|
||||||
config MFD_CROS_EC_I2C
|
config MFD_CROS_EC_I2C
|
||||||
@@ -242,6 +242,27 @@ config MFD_JZ4740_ADC
|
|||||||
Say yes here if you want support for the ADC unit in the JZ4740 SoC.
|
Say yes here if you want support for the ADC unit in the JZ4740 SoC.
|
||||||
This driver is necessary for jz4740-battery and jz4740-hwmon driver.
|
This driver is necessary for jz4740-battery and jz4740-hwmon driver.
|
||||||
|
|
||||||
|
config MFD_KEMPLD
|
||||||
|
tristate "Kontron module PLD device"
|
||||||
|
select MFD_CORE
|
||||||
|
help
|
||||||
|
This is the core driver for the PLD (Programmable Logic Device) found
|
||||||
|
on some Kontron ETX and COMexpress (ETXexpress) modules. The PLD
|
||||||
|
device may provide functions like watchdog, GPIO, UART and I2C bus.
|
||||||
|
|
||||||
|
The following modules are supported:
|
||||||
|
* COMe-bIP#
|
||||||
|
* COMe-bPC2 (ETXexpress-PC)
|
||||||
|
* COMe-bSC# (ETXexpress-SC T#)
|
||||||
|
* COMe-cCT6
|
||||||
|
* COMe-cDC2 (microETXexpress-DC)
|
||||||
|
* COMe-cPC2 (microETXexpress-PC)
|
||||||
|
* COMe-mCT10
|
||||||
|
* ETX-OH
|
||||||
|
|
||||||
|
This driver can also be built as a module. If so, the module
|
||||||
|
will be called kempld-core.
|
||||||
|
|
||||||
config MFD_88PM800
|
config MFD_88PM800
|
||||||
tristate "Marvell 88PM800"
|
tristate "Marvell 88PM800"
|
||||||
depends on I2C=y && GENERIC_HARDIRQS
|
depends on I2C=y && GENERIC_HARDIRQS
|
||||||
@@ -342,6 +363,7 @@ config MFD_MAX8998
|
|||||||
bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support"
|
bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support"
|
||||||
depends on I2C=y && GENERIC_HARDIRQS
|
depends on I2C=y && GENERIC_HARDIRQS
|
||||||
select MFD_CORE
|
select MFD_CORE
|
||||||
|
select IRQ_DOMAIN
|
||||||
help
|
help
|
||||||
Say yes here to support for Maxim Semiconductor MAX8998 and
|
Say yes here to support for Maxim Semiconductor MAX8998 and
|
||||||
National Semiconductor LP3974. This is a Power Management IC.
|
National Semiconductor LP3974. This is a Power Management IC.
|
||||||
@@ -419,7 +441,8 @@ config MFD_PM8XXX
|
|||||||
|
|
||||||
config MFD_PM8921_CORE
|
config MFD_PM8921_CORE
|
||||||
tristate "Qualcomm PM8921 PMIC chip"
|
tristate "Qualcomm PM8921 PMIC chip"
|
||||||
depends on SSBI && BROKEN
|
depends on (ARCH_MSM || HEXAGON)
|
||||||
|
depends on BROKEN
|
||||||
select MFD_CORE
|
select MFD_CORE
|
||||||
select MFD_PM8XXX
|
select MFD_PM8XXX
|
||||||
help
|
help
|
||||||
@@ -1046,6 +1069,12 @@ config MFD_WM5110
|
|||||||
help
|
help
|
||||||
Support for Wolfson Microelectronics WM5110 low power audio SoC
|
Support for Wolfson Microelectronics WM5110 low power audio SoC
|
||||||
|
|
||||||
|
config MFD_WM8997
|
||||||
|
bool "Support Wolfson Microelectronics WM8997"
|
||||||
|
depends on MFD_ARIZONA
|
||||||
|
help
|
||||||
|
Support for Wolfson Microelectronics WM8997 low power audio SoC
|
||||||
|
|
||||||
config MFD_WM8400
|
config MFD_WM8400
|
||||||
bool "Wolfson Microelectronics WM8400"
|
bool "Wolfson Microelectronics WM8400"
|
||||||
select MFD_CORE
|
select MFD_CORE
|
||||||
@@ -1144,7 +1173,8 @@ config MCP_UCB1200_TS
|
|||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
config VEXPRESS_CONFIG
|
config VEXPRESS_CONFIG
|
||||||
bool
|
bool "ARM Versatile Express platform infrastructure"
|
||||||
|
depends on ARM || ARM64
|
||||||
help
|
help
|
||||||
Platform configuration infrastructure for the ARM Ltd.
|
Platform configuration infrastructure for the ARM Ltd.
|
||||||
Versatile Express.
|
Versatile Express.
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ endif
|
|||||||
ifneq ($(CONFIG_MFD_WM5110),n)
|
ifneq ($(CONFIG_MFD_WM5110),n)
|
||||||
obj-$(CONFIG_MFD_ARIZONA) += wm5110-tables.o
|
obj-$(CONFIG_MFD_ARIZONA) += wm5110-tables.o
|
||||||
endif
|
endif
|
||||||
|
ifneq ($(CONFIG_MFD_WM8997),n)
|
||||||
|
obj-$(CONFIG_MFD_ARIZONA) += wm8997-tables.o
|
||||||
|
endif
|
||||||
obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
|
obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
|
||||||
wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
|
wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
|
||||||
wm831x-objs += wm831x-auxadc.o
|
wm831x-objs += wm831x-auxadc.o
|
||||||
@@ -126,6 +129,7 @@ obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o
|
|||||||
obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o
|
obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o
|
||||||
obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
|
obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
|
||||||
obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
|
obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
|
||||||
|
obj-$(CONFIG_MFD_KEMPLD) += kempld-core.o
|
||||||
obj-$(CONFIG_LPC_SCH) += lpc_sch.o
|
obj-$(CONFIG_LPC_SCH) += lpc_sch.o
|
||||||
obj-$(CONFIG_LPC_ICH) += lpc_ich.o
|
obj-$(CONFIG_LPC_ICH) += lpc_ich.o
|
||||||
obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o
|
obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o
|
||||||
@@ -140,7 +144,7 @@ obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o
|
|||||||
|
|
||||||
obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o
|
obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o
|
||||||
obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o omap-usb-tll.o
|
obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o omap-usb-tll.o
|
||||||
obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o
|
obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o ssbi.o
|
||||||
obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o
|
obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.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
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user