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:
Linus Torvalds
2013-07-10 11:10:27 -07:00
97 changed files with 4831 additions and 1013 deletions
@@ -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
View File
@@ -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>
+14
View File
@@ -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>;
};
};
+17
View File
@@ -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";
+2 -6
View File
@@ -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
+2 -6
View File
@@ -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
-2
View File
@@ -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"
-1
View File
@@ -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
View File
@@ -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");
+203 -85
View File
@@ -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
View File
@@ -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, &regulator_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
View File
@@ -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
View File
@@ -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);
/* /*
+3 -5
View File
@@ -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
View File
@@ -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.
+5 -1
View File
@@ -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