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 0998d063.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIcBAABAgAGBQJR2zCaAAoJEIqAPN1PVmxK29EP/ieZf7Z7z7bg/0lEOvtOzACy
 WoCdSGFu5XcHOnlv0Fl1Rr/1AJFQoh4KugkGnVyrlztYVOFymj5VDdd8B43cxMLt
 7ymK/3crIH7uJuOoeDoDr3glLuo0TGB9f5Kv4ITdVD3/+AuqY4VIAisEDb0aWghW
 +v0I3fYeGdwRv+IqO5wacvddSoLa4rmOhnpbVMB2O1Y/LCm/yHI6tAFx1+AfH7y8
 zMHbGFc+gHg1xupJBCnRel0v8J+KNc02G/B1zNom/avL8b/mNXNI8JFxs3bMA0r8
 NpTHJ49OVPbhBQTA4U+BPoG4nzOiAOj0czf9dkGa5cyR8t4C9mmK+s8QHwepzrSG
 qbhCgTqp4bomB1m0RAO+z4F6BHTpmoChpho2btrwN9ZmhMHQeTWnGjjhEwZngpBq
 F22DC6k5ipV0k4962ZHfZ76v2Vot1gfd6zQ5r+2oHMMfWaKgS4L5efP2/wsU9H58
 BxMm84C7OWbgcTRmNn9jl4L9phBD31wvNANfUeMhLMyshnwPK5ZuUdX/+K2rq6h9
 w26Hg62HtKZFv/TEsCBQqpB6zSZa4u/KZzvwEahllQSQGKxIHaNYGtLGzJj9sCM+
 baT/82DFKuEvKfJpUKSBMznImp4WNGEz+8s2w4m/Ssuf30GN2GHjM9Q4gcHJu2mk
 7fTrsSHWYN+EHVzh1Zb8
 =RqMp
 -----END PGP SIGNATURE-----

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
commit 3aa78e0cb5
97 changed files with 4831 additions and 1013 deletions

View File

@ -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>;
};
}

View File

@ -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;
};
};
};

View File

@ -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;
};
};
};

View File

@ -18,20 +18,20 @@ For twl6030 regulators/LDOs
- "ti,twl6030-vdd1" for VDD1 SMPS
- "ti,twl6030-vdd2" for VDD2 SMPS
- "ti,twl6030-vdd3" for VDD3 SMPS
For twl6025 regulators/LDOs
For twl6032 regulators/LDOs
- compatible:
- "ti,twl6025-ldo1" for LDO1 LDO
- "ti,twl6025-ldo2" for LDO2 LDO
- "ti,twl6025-ldo3" for LDO3 LDO
- "ti,twl6025-ldo4" for LDO4 LDO
- "ti,twl6025-ldo5" for LDO5 LDO
- "ti,twl6025-ldo6" for LDO6 LDO
- "ti,twl6025-ldo7" for LDO7 LDO
- "ti,twl6025-ldoln" for LDOLN LDO
- "ti,twl6025-ldousb" for LDOUSB LDO
- "ti,twl6025-smps3" for SMPS3 SMPS
- "ti,twl6025-smps4" for SMPS4 SMPS
- "ti,twl6025-vio" for VIO SMPS
- "ti,twl6032-ldo1" for LDO1 LDO
- "ti,twl6032-ldo2" for LDO2 LDO
- "ti,twl6032-ldo3" for LDO3 LDO
- "ti,twl6032-ldo4" for LDO4 LDO
- "ti,twl6032-ldo5" for LDO5 LDO
- "ti,twl6032-ldo6" for LDO6 LDO
- "ti,twl6032-ldo7" for LDO7 LDO
- "ti,twl6032-ldoln" for LDOLN LDO
- "ti,twl6032-ldousb" for LDOUSB LDO
- "ti,twl6032-smps3" for SMPS3 SMPS
- "ti,twl6032-smps4" for SMPS4 SMPS
- "ti,twl6032-vio" for VIO SMPS
For twl4030 regulators/LDOs
- compatible:
- "ti,twl4030-vaux1" for VAUX1 LDO

View File

@ -8,7 +8,7 @@ TWL6030 USB COMPARATOR
usb interrupt number that raises VBUS interrupts when the controller has to
act as device
- 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 {
compatible = "ti,twl6030-usb";

View File

@ -5500,9 +5500,12 @@ F: include/media/mt9v032.h
MULTIFUNCTION DEVICES (MFD)
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
F: drivers/mfd/
F: include/linux/mfd/
MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
M: Chris Ball <cjb@laptop.org>

View File

@ -474,3 +474,17 @@
phy_id = <&davinci_mdio>, <1>;
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>;
};
};

View File

@ -502,6 +502,23 @@
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 {
compatible = "ti,am3352-gpmc";
ti,hwmods = "gpmc";

View File

@ -377,12 +377,8 @@ static struct max8998_platform_data aquila_max8998_pdata = {
.buck1_set1 = S5PV210_GPH0(3),
.buck1_set2 = S5PV210_GPH0(4),
.buck2_set3 = S5PV210_GPH0(5),
.buck1_voltage1 = 1200000,
.buck1_voltage2 = 1200000,
.buck1_voltage3 = 1200000,
.buck1_voltage4 = 1200000,
.buck2_voltage1 = 1200000,
.buck2_voltage2 = 1200000,
.buck1_voltage = { 1200000, 1200000, 1200000, 1200000 },
.buck2_voltage = { 1200000, 1200000 },
};
#endif

View File

@ -580,12 +580,8 @@ static struct max8998_platform_data goni_max8998_pdata = {
.buck1_set1 = S5PV210_GPH0(3),
.buck1_set2 = S5PV210_GPH0(4),
.buck2_set3 = S5PV210_GPH0(5),
.buck1_voltage1 = 1200000,
.buck1_voltage2 = 1200000,
.buck1_voltage3 = 1200000,
.buck1_voltage4 = 1200000,
.buck2_voltage1 = 1200000,
.buck2_voltage2 = 1200000,
.buck1_voltage = { 1200000, 1200000, 1200000, 1200000 },
.buck2_voltage = { 1200000, 1200000 },
};
#endif

View File

@ -52,8 +52,6 @@ source "drivers/i2c/Kconfig"
source "drivers/spi/Kconfig"
source "drivers/ssbi/Kconfig"
source "drivers/hsi/Kconfig"
source "drivers/pps/Kconfig"

View File

@ -117,7 +117,6 @@ obj-y += firmware/
obj-$(CONFIG_CRYPTO) += crypto/
obj-$(CONFIG_SUPERH) += sh/
obj-$(CONFIG_ARCH_SHMOBILE) += sh/
obj-$(CONFIG_SSBI) += ssbi/
ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
obj-y += clocksource/
endif

View File

@ -22,13 +22,18 @@
#include <linux/platform_device.h>
#include <linux/io.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/platform_data/ti_am335x_adc.h>
struct tiadc_device {
struct ti_tscadc_dev *mfd_tscadc;
int channels;
u8 channel_line[8];
u8 channel_step[8];
};
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);
}
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)
{
unsigned int stepconfig;
int i, channels = 0, steps;
int i, steps;
u32 step_en;
/*
* 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;
channels = TOTAL_CHANNELS - adc_dev->channels;
stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
for (i = (steps + 1); i <= TOTAL_STEPS; i++) {
tiadc_writel(adc_dev, REG_STEPCONFIG(i),
stepconfig | STEPCONFIG_INP(channels));
tiadc_writel(adc_dev, REG_STEPDELAY(i),
for (i = 0; i < adc_dev->channels; i++) {
int chan;
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);
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)
{
struct tiadc_device *adc_dev = iio_priv(indio_dev);
struct iio_chan_spec *chan_array;
struct iio_chan_spec *chan;
int i;
indio_dev->num_channels = channels;
chan_array = kcalloc(indio_dev->num_channels,
chan_array = kcalloc(channels,
sizeof(struct iio_chan_spec), GFP_KERNEL);
if (chan_array == NULL)
return -ENOMEM;
for (i = 0; i < (indio_dev->num_channels); i++) {
struct iio_chan_spec *chan = chan_array + i;
chan = chan_array;
for (i = 0; i < channels; i++, chan++) {
chan->type = IIO_VOLTAGE;
chan->indexed = 1;
chan->channel = i;
chan->channel = adc_dev->channel_line[i];
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;
return indio_dev->num_channels;
return 0;
}
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);
int i;
unsigned int fifo1count, readx1;
unsigned int fifo1count, read;
u32 step = UINT_MAX;
bool found = false;
/*
* 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.
*/
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);
for (i = 0; i < fifo1count; i++) {
readx1 = tiadc_readl(adc_dev, REG_FIFO1);
if (i == chan->channel)
*val = readx1 & 0xfff;
read = tiadc_readl(adc_dev, REG_FIFO1);
if (read >> 16 == step) {
*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;
}
@ -140,13 +189,15 @@ static int tiadc_probe(struct platform_device *pdev)
{
struct iio_dev *indio_dev;
struct tiadc_device *adc_dev;
struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
struct mfd_tscadc_board *pdata;
struct device_node *node = pdev->dev.of_node;
struct property *prop;
const __be32 *cur;
int err;
u32 val;
int channels = 0;
pdata = tscadc_dev->dev->platform_data;
if (!pdata || !pdata->adc_init) {
dev_err(&pdev->dev, "Could not find platform data\n");
if (!node) {
dev_err(&pdev->dev, "Could not find valid DT data.\n");
return -EINVAL;
}
@ -158,8 +209,13 @@ static int tiadc_probe(struct platform_device *pdev)
}
adc_dev = iio_priv(indio_dev);
adc_dev->mfd_tscadc = tscadc_dev;
adc_dev->channels = pdata->adc_init->adc_channels;
adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev);
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->name = dev_name(&pdev->dev);
@ -191,10 +247,15 @@ err_ret:
static int tiadc_remove(struct platform_device *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);
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);
return 0;
@ -205,9 +266,10 @@ static int tiadc_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(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;
tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
if (!device_may_wakeup(tscadc_dev->dev)) {
idle = tiadc_readl(adc_dev, REG_CTRL);
idle &= ~(CNTRLREG_TSCSSENB);
@ -243,16 +305,22 @@ static const struct dev_pm_ops tiadc_pm_ops = {
#define TIADC_PM_OPS NULL
#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 = {
.driver = {
.name = "tiadc",
.name = "TI-am335x-adc",
.owner = THIS_MODULE,
.pm = TIADC_PM_OPS,
.of_match_table = of_match_ptr(ti_adc_dt_ids),
},
.probe = tiadc_probe,
.remove = tiadc_remove,
};
module_platform_driver(tiadc_driver);
MODULE_DESCRIPTION("TI ADC controller driver");

View File

@ -24,8 +24,9 @@
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/input/ti_am335x_tsc.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/mfd/ti_am335x_tscadc.h>
@ -33,6 +34,13 @@
#define SEQ_SETTLE 275
#define MAX_12BIT ((1 << 12) - 1)
static const int config_pins[] = {
STEPCONFIG_XPP,
STEPCONFIG_XNN,
STEPCONFIG_YPP,
STEPCONFIG_YNN,
};
struct titsc {
struct input_dev *input;
struct ti_tscadc_dev *mfd_tscadc;
@ -40,7 +48,10 @@ struct titsc {
unsigned int wires;
unsigned int x_plate_resistance;
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)
@ -54,92 +65,153 @@ static void titsc_writel(struct titsc *tsc, unsigned int 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)
{
unsigned int config;
int i, total_steps;
/* Configure the Step registers */
total_steps = 2 * ts_dev->steps_to_configure;
int i;
int end_step;
u32 stepenable;
config = STEPCONFIG_MODE_HWSYNC |
STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
STEPCONFIG_AVG_16 | ts_dev->bit_xp;
switch (ts_dev->wires) {
case 4:
config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
break;
case 5:
config |= STEPCONFIG_YNN |
STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
STEPCONFIG_YPP;
config |= ts_dev->bit_yn |
STEPCONFIG_INP_AN4 | ts_dev->bit_xn |
ts_dev->bit_yp;
break;
case 8:
config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
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_STEPDELAY(i), STEPCONFIG_OPENDLY);
}
config = 0;
config = STEPCONFIG_MODE_HWSYNC |
STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
STEPCONFIG_AVG_16 | ts_dev->bit_yn |
STEPCONFIG_INM_ADCREFM;
switch (ts_dev->wires) {
case 4:
config |= STEPCONFIG_YPP;
config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
break;
case 5:
config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
STEPCONFIG_XNP | STEPCONFIG_YPN;
config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 |
ts_dev->bit_xn | ts_dev->bit_yp;
break;
case 8:
config |= STEPCONFIG_YPP;
config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
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_STEPDELAY(i), STEPCONFIG_OPENDLY);
}
config = 0;
/* Charge step configuration */
config = STEPCONFIG_XPP | STEPCONFIG_YNN |
config = ts_dev->bit_xp | ts_dev->bit_yn |
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_CHARGEDELAY, CHARGEDLY_OPENDLY);
config = 0;
/* Configure to calculate pressure */
/* coordinate_readouts * 2 … coordinate_readouts * 2 + 2 is for Z */
config = STEPCONFIG_MODE_HWSYNC |
STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
STEPCONFIG_AVG_16 | ts_dev->bit_yp |
ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM |
STEPCONFIG_INP(ts_dev->inp_xp);
titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
titsc_writel(ts_dev, REG_STEPDELAY(end_step),
STEPCONFIG_OPENDLY);
config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
end_step++;
config |= STEPCONFIG_INP(ts_dev->inp_yn);
titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
titsc_writel(ts_dev, REG_STEPDELAY(end_step),
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,
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 prev_val_x = ~0, prev_val_y = ~0;
unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
unsigned int read, diff;
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
* 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,
* 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);
channel = read & 0xf0000;
channel = channel >> 0x10;
if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) {
read &= 0xfff;
channel = (read & 0xf0000) >> 16;
read &= 0xfff;
if (channel < creads) {
diff = abs(read - prev_val_x);
if (diff < prev_diff_x) {
prev_diff_x = diff;
*x = read;
}
prev_val_x = read;
}
read = titsc_readl(ts_dev, REG_FIFO1);
channel = read & 0xf0000;
channel = channel >> 0x10;
if ((channel >= ts_dev->steps_to_configure) &&
(channel < (2 * ts_dev->steps_to_configure - 1))) {
read &= 0xfff;
} else if (channel < creads * 2) {
diff = abs(read - prev_val_y);
if (diff < prev_diff_y) {
prev_diff_y = diff;
*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 z1, z2, z;
unsigned int fsm;
unsigned int fifo1count, fifo0count;
int i;
status = titsc_readl(ts_dev, REG_IRQSTATUS);
if (status & IRQENB_FIFO0THRES) {
titsc_read_coordinates(ts_dev, &x, &y);
z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
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);
titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
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 *
* x postion/4096 * ((z2 / z1) - 1)
*/
z = z2 - z1;
z = z1 - z2;
z *= x;
z *= ts_dev->x_plate_resistance;
z /= z1;
z /= z2;
z = (z + 2047) >> 12;
if (z <= MAX_12BIT) {
@ -248,10 +308,53 @@ static irqreturn_t titsc_irq(int irq, void *dev)
irqclr |= IRQENB_PENUP;
}
titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
if (status & IRQENB_HW_PEN) {
titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
return IRQ_HANDLED;
titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00);
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 input_dev *input_dev;
struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
struct mfd_tscadc_board *pdata;
struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev);
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 */
ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
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->input = input_dev;
ts_dev->irq = tscadc_dev->irq;
ts_dev->wires = pdata->tsc_init->wires;
ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance;
ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure;
err = titsc_parse_dt(pdev, ts_dev);
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,
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);
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_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->dev.parent = &pdev->dev;
@ -329,11 +433,16 @@ err_free_mem:
static int titsc_remove(struct platform_device *pdev)
{
struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
struct titsc *ts_dev = tscadc_dev->tsc;
struct titsc *ts_dev = platform_get_drvdata(pdev);
u32 steps;
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);
kfree(ts_dev);
@ -343,10 +452,11 @@ static int titsc_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int titsc_suspend(struct device *dev)
{
struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
struct titsc *ts_dev = tscadc_dev->tsc;
struct titsc *ts_dev = dev_get_drvdata(dev);
struct ti_tscadc_dev *tscadc_dev;
unsigned int idle;
tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
if (device_may_wakeup(tscadc_dev->dev)) {
idle = titsc_readl(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)
{
struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
struct titsc *ts_dev = tscadc_dev->tsc;
struct titsc *ts_dev = dev_get_drvdata(dev);
struct ti_tscadc_dev *tscadc_dev;
tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
if (device_may_wakeup(tscadc_dev->dev)) {
titsc_writel(ts_dev, REG_IRQWAKEUP,
0x00);
@ -368,7 +479,7 @@ static int titsc_resume(struct device *dev)
}
titsc_step_config(ts_dev);
titsc_writel(ts_dev, REG_FIFO0THR,
ts_dev->steps_to_configure);
ts_dev->coordinate_readouts * 2 + 2 - 1);
return 0;
}
@ -381,13 +492,20 @@ static const struct dev_pm_ops titsc_pm_ops = {
#define TITSC_PM_OPS NULL
#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 = {
.probe = titsc_probe,
.remove = titsc_remove,
.driver = {
.name = "tsc",
.name = "TI-am335x-tsc",
.owner = THIS_MODULE,
.pm = TITSC_PM_OPS,
.of_match_table = of_match_ptr(ti_tsc_dt_ids),
},
};
module_platform_driver(ti_tsc_driver);

View File

@ -22,13 +22,12 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/mfd/core.h>
#include <linux/mfd/88pm80x.h>
#include <linux/slab.h>
#define PM800_CHIP_ID (0x00)
/* Interrupt Registers */
#define PM800_INT_STATUS1 (0x05)
#define PM800_ONKEY_INT_STS1 (1 << 0)
@ -113,20 +112,11 @@ enum {
PM800_MAX_IRQ,
};
enum {
/* Procida */
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
};
/* PM800: generation identification number */
#define PM800_CHIP_GEN_ID_NUM 0x3
static const struct i2c_device_id pm80x_id_table[] = {
{"88PM800", CHIP_PM800},
{"88PM800", 0},
{} /* NULL terminated */
};
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[] = {
/* INT0 */
[PM800_IRQ_ONKEY] = {
@ -315,10 +312,59 @@ out:
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)
{
struct regmap *map = chip->regmap;
unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
unsigned long flags = IRQF_ONESHOT;
int data, mask, ret = -EINVAL;
if (!map || !chip->irq) {
@ -362,6 +408,7 @@ static struct regmap_irq_chip pm800_irq_chip = {
.status_base = PM800_INT_STATUS1,
.mask_base = PM800_INT_ENA_1,
.ack_base = PM800_INT_STATUS1,
.mask_invert = 1,
};
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 i2c_client *client = chip->client;
int ret = 0;
subchip = chip->subchip;
/* PM800 block power: i2c addr 0x31 */
if (subchip->power_page_addr) {
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");
if (!subchip || !subchip->power_page_addr || !subchip->gpadc_page_addr)
return -ENODEV;
/* PM800 block GPADC: i2c addr 0x32 */
if (subchip->gpadc_page_addr) {
subchip->gpadc_page = i2c_new_dummy(client->adapter,
subchip->gpadc_page_addr);
subchip->regmap_gpadc =
devm_regmap_init_i2c(subchip->gpadc_page,
&pm80x_regmap_config);
i2c_set_clientdata(subchip->gpadc_page, chip);
} else
dev_info(chip->dev,
"PM800 block GPADC 0x32: No gpadc_page_addr\n");
/* PM800 block power page */
subchip->power_page = i2c_new_dummy(client->adapter,
subchip->power_page_addr);
if (subchip->power_page == NULL) {
ret = -ENODEV;
goto out;
}
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)
{
struct pm80x_subchip *subchip;
regmap_exit(chip->regmap);
i2c_unregister_device(chip->client);
subchip = chip->subchip;
if (subchip->power_page) {
regmap_exit(subchip->regmap_power);
if (subchip && subchip->power_page)
i2c_unregister_device(subchip->power_page);
}
if (subchip->gpadc_page) {
regmap_exit(subchip->regmap_gpadc);
if (subchip && subchip->gpadc_page)
i2c_unregister_device(subchip->gpadc_page);
}
}
static int device_800_init(struct pm80x_chip *chip,
struct pm80x_platform_data *pdata)
{
int ret, pmic_id;
int ret;
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(),
* read before that
@ -468,27 +510,22 @@ static int device_800_init(struct pm80x_chip *chip,
goto out;
}
ret =
mfd_add_devices(chip->dev, 0, &onkey_devs[0],
ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0,
NULL);
if (ret < 0) {
ret = device_onkey_init(chip, pdata);
if (ret) {
dev_err(chip->dev, "Failed to add onkey subdev\n");
goto out_dev;
} else
dev_info(chip->dev, "[%s]:Added mfd onkey_devs\n", __func__);
}
if (pdata && pdata->rtc) {
rtc_devs[0].platform_data = pdata->rtc;
rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata);
ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
ARRAY_SIZE(rtc_devs), NULL, 0, NULL);
if (ret < 0) {
dev_err(chip->dev, "Failed to add rtc subdev\n");
goto out_dev;
} else
dev_info(chip->dev,
"[%s]:Added mfd rtc_devs\n", __func__);
ret = device_rtc_init(chip, pdata);
if (ret) {
dev_err(chip->dev, "Failed to add rtc subdev\n");
goto out;
}
ret = device_regulator_init(chip, pdata);
if (ret) {
dev_err(chip->dev, "Failed to add regulators subdev\n");
goto out;
}
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_subchip *subchip;
ret = pm80x_init(client, id);
ret = pm80x_init(client);
if (ret) {
dev_err(&client->dev, "pm800_init fail\n");
goto out_init;
@ -524,28 +561,31 @@ static int pm800_probe(struct i2c_client *client,
goto err_subchip_alloc;
}
subchip->power_page_addr = pdata->power_page_addr;
subchip->gpadc_page_addr = pdata->gpadc_page_addr;
/* pm800 has 2 addtional pages to support power and gpadc. */
subchip->power_page_addr = client->addr + 1;
subchip->gpadc_page_addr = client->addr + 2;
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);
if (ret) {
dev_err(&client->dev, "pm800_pages_init failed!\n");
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)
pdata->plat_config(chip, pdata);
return 0;
err_device_init:
pm800_pages_exit(chip);
err_page_init:
mfd_remove_devices(chip->dev);
device_irq_exit_800(chip);
err_subchip_alloc:
pm80x_deinit();
out_init:
@ -567,7 +607,7 @@ static int pm800_remove(struct i2c_client *client)
static struct i2c_driver pm800_driver = {
.driver = {
.name = "88PM80X",
.name = "88PM800",
.owner = THIS_MODULE,
.pm = &pm80x_pm_ops,
},

View File

@ -29,10 +29,8 @@
#include <linux/slab.h>
#include <linux/delay.h>
#define PM805_CHIP_ID (0x00)
static const struct i2c_device_id pm80x_id_table[] = {
{"88PM805", CHIP_PM805},
{"88PM805", 0},
{} /* NULL terminated */
};
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)
{
struct regmap *map = chip->regmap;
unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
unsigned long flags = IRQF_ONESHOT;
int data, mask, ret = -EINVAL;
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)
{
int ret = 0;
unsigned int val;
struct regmap *map = chip->regmap;
if (!map) {
@ -200,13 +197,6 @@ static int device_805_init(struct pm80x_chip *chip)
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;
ret = device_irq_init_805(chip);
@ -239,7 +229,7 @@ static int pm805_probe(struct i2c_client *client,
struct pm80x_chip *chip;
struct pm80x_platform_data *pdata = client->dev.platform_data;
ret = pm80x_init(client, id);
ret = pm80x_init(client);
if (ret) {
dev_err(&client->dev, "pm805_init fail!\n");
goto out_init;
@ -249,7 +239,7 @@ static int pm805_probe(struct i2c_client *client,
ret = device_805_init(chip);
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;
}
@ -276,7 +266,7 @@ static int pm805_remove(struct i2c_client *client)
static struct i2c_driver pm805_driver = {
.driver = {
.name = "88PM80X",
.name = "88PM805",
.owner = THIS_MODULE,
.pm = &pm80x_pm_ops,
},

View File

@ -18,6 +18,23 @@
#include <linux/uaccess.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
* 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);
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 regmap *map;
int ret = 0;
unsigned int val;
int i, ret = 0;
chip =
devm_kzalloc(&client->dev, sizeof(struct pm80x_chip), GFP_KERNEL);
@ -51,10 +69,6 @@ int pm80x_init(struct i2c_client *client,
return ret;
}
chip->id = id->driver_data;
if (chip->id < CHIP_PM800 || chip->id > CHIP_PM805)
return -EINVAL;
chip->client = client;
chip->regmap = map;
@ -64,6 +78,25 @@ int pm80x_init(struct i2c_client *client,
dev_set_drvdata(chip->dev, 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);
/*

View File

@ -1150,17 +1150,17 @@ static int pm860x_probe(struct i2c_client *client,
return -EINVAL;
}
chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL);
chip = devm_kzalloc(&client->dev,
sizeof(struct pm860x_chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
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)) {
ret = PTR_ERR(chip->regmap);
dev_err(&client->dev, "Failed to allocate register map: %d\n",
ret);
kfree(chip);
return ret;
}
chip->client = client;
@ -1203,8 +1203,6 @@ static int pm860x_remove(struct i2c_client *client)
regmap_exit(chip->regmap_companion);
i2c_unregister_device(chip->companion);
}
regmap_exit(chip->regmap);
kfree(chip);
return 0;
}

View File

@ -53,7 +53,7 @@ config MFD_CROS_EC
help
If you say Y here you get support for the ChromeOS Embedded
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.
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.
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
tristate "Marvell 88PM800"
depends on I2C=y && GENERIC_HARDIRQS
@ -342,6 +363,7 @@ config MFD_MAX8998
bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support"
depends on I2C=y && GENERIC_HARDIRQS
select MFD_CORE
select IRQ_DOMAIN
help
Say yes here to support for Maxim Semiconductor MAX8998 and
National Semiconductor LP3974. This is a Power Management IC.
@ -419,7 +441,8 @@ config MFD_PM8XXX
config MFD_PM8921_CORE
tristate "Qualcomm PM8921 PMIC chip"
depends on SSBI && BROKEN
depends on (ARCH_MSM || HEXAGON)
depends on BROKEN
select MFD_CORE
select MFD_PM8XXX
help
@ -1046,6 +1069,12 @@ config MFD_WM5110
help
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
bool "Wolfson Microelectronics WM8400"
select MFD_CORE
@ -1144,7 +1173,8 @@ config MCP_UCB1200_TS
endmenu
config VEXPRESS_CONFIG
bool
bool "ARM Versatile Express platform infrastructure"
depends on ARM || ARM64
help
Platform configuration infrastructure for the ARM Ltd.
Versatile Express.

View File

@ -43,6 +43,9 @@ endif
ifneq ($(CONFIG_MFD_WM5110),n)
obj-$(CONFIG_MFD_ARIZONA) += wm5110-tables.o
endif
ifneq ($(CONFIG_MFD_WM8997),n)
obj-$(CONFIG_MFD_ARIZONA) += wm8997-tables.o
endif
obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.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_MFD_TIMBERDALE) += timberdale.o
obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
obj-$(CONFIG_MFD_KEMPLD) += kempld-core.o
obj-$(CONFIG_LPC_SCH) += lpc_sch.o
obj-$(CONFIG_LPC_ICH) += lpc_ich.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_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_TPS65911_COMPARATOR) += tps65911-comparator.o
obj-$(CONFIG_MFD_TPS65090) += tps65090.o

View File

@ -312,8 +312,9 @@ static ssize_t aat2870_reg_write_file(struct file *file,
while (*start == ' ')
start++;
if (strict_strtoul(start, 16, &val))
return -EINVAL;
ret = kstrtoul(start, 16, &val);
if (ret)
return ret;
ret = aat2870->write(aat2870, (u8)addr, (u8)val);
if (ret)

View File

@ -491,7 +491,7 @@ static ssize_t ab3100_get_set_reg(struct file *file,
char buf[32];
ssize_t buf_size;
int regp;
unsigned long user_reg;
u8 user_reg;
int err;
int i = 0;
@ -514,34 +514,29 @@ static ssize_t ab3100_get_set_reg(struct file *file,
/*
* Advance pointer to end of string then terminate
* the register string. This is needed to satisfy
* the strict_strtoul() function.
* the kstrtou8() function.
*/
while ((i < buf_size) && (buf[i] != ' '))
i++;
buf[i] = '\0';
err = strict_strtoul(&buf[regp], 16, &user_reg);
err = kstrtou8(&buf[regp], 16, &user_reg);
if (err)
return err;
if (user_reg > 0xff)
return -EINVAL;
/* Either we read or we write a register here */
if (!priv->mode) {
/* Reading */
u8 reg = (u8) user_reg;
u8 regvalue;
ab3100_get_register_interruptible(ab3100, reg, &regvalue);
ab3100_get_register_interruptible(ab3100, user_reg, &regvalue);
dev_info(ab3100->dev,
"debug read AB3100 reg[0x%02x]: 0x%02x\n",
reg, regvalue);
user_reg, regvalue);
} else {
int valp;
unsigned long user_value;
u8 reg = (u8) user_reg;
u8 value;
u8 user_value;
u8 regvalue;
/*
@ -557,20 +552,17 @@ static ssize_t ab3100_get_set_reg(struct file *file,
i++;
buf[i] = '\0';
err = strict_strtoul(&buf[valp], 16, &user_value);
err = kstrtou8(&buf[valp], 16, &user_value);
if (err)
return err;
if (user_reg > 0xff)
return -EINVAL;
value = (u8) user_value;
ab3100_set_register_interruptible(ab3100, reg, value);
ab3100_get_register_interruptible(ab3100, reg, &regvalue);
ab3100_set_register_interruptible(ab3100, user_reg, user_value);
ab3100_get_register_interruptible(ab3100, user_reg, &regvalue);
dev_info(ab3100->dev,
"debug write reg[0x%02x] with 0x%02x, "
"after readback: 0x%02x\n",
reg, value, regvalue);
user_reg, user_value, regvalue);
}
return buf_size;
}

View File

@ -187,7 +187,7 @@ static int __init ab3100_otp_probe(struct platform_device *pdev)
int err = 0;
int i;
otp = kzalloc(sizeof(struct ab3100_otp), GFP_KERNEL);
otp = devm_kzalloc(&pdev->dev, sizeof(struct ab3100_otp), GFP_KERNEL);
if (!otp) {
dev_err(&pdev->dev, "could not allocate AB3100 OTP device\n");
return -ENOMEM;
@ -199,7 +199,7 @@ static int __init ab3100_otp_probe(struct platform_device *pdev)
err = ab3100_otp_read(otp);
if (err)
goto err_otp_read;
return err;
dev_info(&pdev->dev, "AB3100 OTP readout registered\n");
@ -208,22 +208,19 @@ static int __init ab3100_otp_probe(struct platform_device *pdev)
err = device_create_file(&pdev->dev,
&ab3100_otp_attrs[i]);
if (err)
goto err_create_file;
goto err;
}
/* debugfs entries */
err = ab3100_otp_init_debugfs(&pdev->dev, otp);
if (err)
goto err_init_debugfs;
goto err;
return 0;
err_init_debugfs:
err_create_file:
err:
while (--i >= 0)
device_remove_file(&pdev->dev, &ab3100_otp_attrs[i]);
err_otp_read:
kfree(otp);
return err;
}
@ -236,7 +233,6 @@ static int __exit ab3100_otp_remove(struct platform_device *pdev)
device_remove_file(&pdev->dev,
&ab3100_otp_attrs[i]);
ab3100_otp_exit_debugfs(otp);
kfree(otp);
return 0;
}

View File

@ -650,6 +650,21 @@ static struct resource ab8500_rtc_resources[] = {
},
};
static struct resource ab8540_rtc_resources[] = {
{
.name = "1S",
.start = AB8540_INT_RTC_1S,
.end = AB8540_INT_RTC_1S,
.flags = IORESOURCE_IRQ,
},
{
.name = "ALARM",
.start = AB8500_INT_RTC_ALARM,
.end = AB8500_INT_RTC_ALARM,
.flags = IORESOURCE_IRQ,
},
};
static struct resource ab8500_poweronkey_db_resources[] = {
{
.name = "ONKEY_DBF",
@ -1050,6 +1065,10 @@ static struct mfd_cell ab8500_devs[] = {
.name = "ab8500-sysctrl",
.of_compatible = "stericsson,ab8500-sysctrl",
},
{
.name = "ab8500-ext-regulator",
.of_compatible = "stericsson,ab8500-ext-regulator",
},
{
.name = "ab8500-regulator",
.of_compatible = "stericsson,ab8500-regulator",
@ -1098,10 +1117,6 @@ static struct mfd_cell ab8500_devs[] = {
.of_compatible = "stericsson,ab8500-pwm",
.id = 3,
},
{
.name = "ab8500-leds",
.of_compatible = "stericsson,ab8500-leds",
},
{
.name = "ab8500-denc",
.of_compatible = "stericsson,ab8500-denc",
@ -1124,6 +1139,7 @@ static struct mfd_cell ab8500_devs[] = {
},
{
.name = "ab8500-codec",
.of_compatible = "stericsson,ab8500-codec",
},
};
@ -1138,6 +1154,9 @@ static struct mfd_cell ab9540_devs[] = {
{
.name = "ab8500-sysctrl",
},
{
.name = "ab8500-ext-regulator",
},
{
.name = "ab8500-regulator",
},
@ -1170,9 +1189,6 @@ static struct mfd_cell ab9540_devs[] = {
.name = "ab8500-pwm",
.id = 1,
},
{
.name = "ab8500-leds",
},
{
.name = "abx500-temp",
.num_resources = ARRAY_SIZE(ab8500_temp_resources),
@ -1241,9 +1257,6 @@ static struct mfd_cell ab8505_devs[] = {
.name = "ab8500-pwm",
.id = 1,
},
{
.name = "ab8500-leds",
},
{
.name = "pinctrl-ab8505",
},
@ -1273,6 +1286,9 @@ static struct mfd_cell ab8540_devs[] = {
{
.name = "ab8500-sysctrl",
},
{
.name = "ab8500-ext-regulator",
},
{
.name = "ab8500-regulator",
},
@ -1286,11 +1302,6 @@ static struct mfd_cell ab8540_devs[] = {
.num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
.resources = ab8505_gpadc_resources,
},
{
.name = "ab8500-rtc",
.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
.resources = ab8500_rtc_resources,
},
{
.name = "ab8500-acc-det",
.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
@ -1305,9 +1316,6 @@ static struct mfd_cell ab8540_devs[] = {
.name = "ab8500-pwm",
.id = 1,
},
{
.name = "ab8500-leds",
},
{
.name = "abx500-temp",
.num_resources = ARRAY_SIZE(ab8500_temp_resources),
@ -1331,6 +1339,24 @@ static struct mfd_cell ab8540_devs[] = {
},
};
static struct mfd_cell ab8540_cut1_devs[] = {
{
.name = "ab8500-rtc",
.of_compatible = "stericsson,ab8500-rtc",
.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
.resources = ab8500_rtc_resources,
},
};
static struct mfd_cell ab8540_cut2_devs[] = {
{
.name = "ab8540-rtc",
.of_compatible = "stericsson,ab8540-rtc",
.num_resources = ARRAY_SIZE(ab8540_rtc_resources),
.resources = ab8540_rtc_resources,
},
};
static ssize_t show_chip_id(struct device *dev,
struct device_attribute *attr, char *buf)
{
@ -1734,11 +1760,22 @@ static int ab8500_probe(struct platform_device *pdev)
ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
ARRAY_SIZE(ab9540_devs), NULL,
ab8500->irq_base, ab8500->domain);
else if (is_ab8540(ab8500))
else if (is_ab8540(ab8500)) {
ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs,
ARRAY_SIZE(ab8540_devs), NULL,
ab8500->irq_base, ab8500->domain);
else if (is_ab8505(ab8500))
ab8500->irq_base, NULL);
if (ret)
return ret;
if (is_ab8540_1p2_or_earlier(ab8500))
ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut1_devs,
ARRAY_SIZE(ab8540_cut1_devs), NULL,
ab8500->irq_base, NULL);
else /* ab8540 >= cut2 */
ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut2_devs,
ARRAY_SIZE(ab8540_cut2_devs), NULL,
ab8500->irq_base, NULL);
} else if (is_ab8505(ab8500))
ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs,
ARRAY_SIZE(ab8505_devs), NULL,
ab8500->irq_base, ab8500->domain);

View File

@ -2757,7 +2757,7 @@ static ssize_t show_irq(struct device *dev,
unsigned int irq_index;
int err;
err = strict_strtoul(attr->attr.name, 0, &name);
err = kstrtoul(attr->attr.name, 0, &name);
if (err)
return err;
@ -2937,7 +2937,6 @@ static struct dentry *ab8500_gpadc_dir;
static int ab8500_debug_probe(struct platform_device *plf)
{
struct dentry *file;
int ret = -ENOMEM;
struct ab8500 *ab8500;
struct resource *res;
debug_bank = AB8500_MISC;
@ -2946,24 +2945,26 @@ static int ab8500_debug_probe(struct platform_device *plf)
ab8500 = dev_get_drvdata(plf->dev.parent);
num_irqs = ab8500->mask_size;
irq_count = kzalloc(sizeof(*irq_count)*num_irqs, GFP_KERNEL);
irq_count = devm_kzalloc(&plf->dev,
sizeof(*irq_count)*num_irqs, GFP_KERNEL);
if (!irq_count)
return -ENOMEM;
dev_attr = kzalloc(sizeof(*dev_attr)*num_irqs,GFP_KERNEL);
dev_attr = devm_kzalloc(&plf->dev,
sizeof(*dev_attr)*num_irqs,GFP_KERNEL);
if (!dev_attr)
goto out_freeirq_count;
return -ENOMEM;
event_name = kzalloc(sizeof(*event_name)*num_irqs, GFP_KERNEL);
event_name = devm_kzalloc(&plf->dev,
sizeof(*event_name)*num_irqs, GFP_KERNEL);
if (!event_name)
goto out_freedev_attr;
return -ENOMEM;
res = platform_get_resource_byname(plf, 0, "IRQ_AB8500");
if (!res) {
dev_err(&plf->dev, "AB8500 irq not found, err %d\n",
irq_first);
ret = -ENXIO;
goto out_freeevent_name;
return ENXIO;
}
irq_ab8500 = res->start;
@ -2971,16 +2972,14 @@ static int ab8500_debug_probe(struct platform_device *plf)
if (irq_first < 0) {
dev_err(&plf->dev, "First irq not found, err %d\n",
irq_first);
ret = irq_first;
goto out_freeevent_name;
return irq_first;
}
irq_last = platform_get_irq_byname(plf, "IRQ_LAST");
if (irq_last < 0) {
dev_err(&plf->dev, "Last irq not found, err %d\n",
irq_last);
ret = irq_last;
goto out_freeevent_name;
return irq_last;
}
ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL);
@ -3189,22 +3188,13 @@ err:
if (ab8500_dir)
debugfs_remove_recursive(ab8500_dir);
dev_err(&plf->dev, "failed to create debugfs entries.\n");
out_freeevent_name:
kfree(event_name);
out_freedev_attr:
kfree(dev_attr);
out_freeirq_count:
kfree(irq_count);
return ret;
return -ENOMEM;
}
static int ab8500_debug_remove(struct platform_device *plf)
{
debugfs_remove_recursive(ab8500_dir);
kfree(event_name);
kfree(dev_attr);
kfree(irq_count);
return 0;
}

View File

@ -919,7 +919,7 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
int ret = 0;
struct ab8500_gpadc *gpadc;
gpadc = kzalloc(sizeof(struct ab8500_gpadc), GFP_KERNEL);
gpadc = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_gpadc), GFP_KERNEL);
if (!gpadc) {
dev_err(&pdev->dev, "Error: No memory\n");
return -ENOMEM;
@ -999,8 +999,6 @@ fail_irq:
free_irq(gpadc->irq_sw, gpadc);
free_irq(gpadc->irq_hw, gpadc);
fail:
kfree(gpadc);
gpadc = NULL;
return ret;
}
@ -1025,8 +1023,6 @@ static int ab8500_gpadc_remove(struct platform_device *pdev)
pm_runtime_put_noidle(gpadc->dev);
kfree(gpadc);
gpadc = NULL;
return 0;
}

View File

@ -36,7 +36,9 @@ int abx500_register_ops(struct device *dev, struct abx500_ops *ops)
{
struct abx500_device_entry *dev_entry;
dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL);
dev_entry = devm_kzalloc(dev,
sizeof(struct abx500_device_entry),
GFP_KERNEL);
if (!dev_entry) {
dev_err(dev, "register_ops kzalloc failed");
return -ENOMEM;
@ -54,12 +56,8 @@ void abx500_remove_ops(struct device *dev)
struct abx500_device_entry *dev_entry, *tmp;
list_for_each_entry_safe(dev_entry, tmp, &abx500_list, list)
{
if (dev_entry->dev == dev) {
if (dev_entry->dev == dev)
list_del(&dev_entry->list);
kfree(dev_entry);
}
}
}
EXPORT_SYMBOL(abx500_remove_ops);

View File

@ -223,7 +223,7 @@ static int adp5520_probe(struct i2c_client *client,
return -ENODEV;
}
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
@ -244,7 +244,7 @@ static int adp5520_probe(struct i2c_client *client,
if (ret) {
dev_err(&client->dev, "failed to request irq %d\n",
chip->irq);
goto out_free_chip;
return ret;
}
}
@ -302,9 +302,6 @@ out_free_irq:
if (chip->irq)
free_irq(chip->irq, chip);
out_free_chip:
kfree(chip);
return ret;
}
@ -317,7 +314,6 @@ static int adp5520_remove(struct i2c_client *client)
adp5520_remove_subdevs(chip);
adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0);
kfree(chip);
return 0;
}

View File

@ -554,6 +554,7 @@ static int arizona_of_get_core_pdata(struct arizona *arizona)
const struct of_device_id arizona_of_match[] = {
{ .compatible = "wlf,wm5102", .data = (void *)WM5102 },
{ .compatible = "wlf,wm5110", .data = (void *)WM5110 },
{ .compatible = "wlf,wm8997", .data = (void *)WM8997 },
{},
};
EXPORT_SYMBOL_GPL(arizona_of_match);
@ -586,6 +587,15 @@ static struct mfd_cell wm5110_devs[] = {
{ .name = "wm5110-codec" },
};
static struct mfd_cell wm8997_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-extcon" },
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
{ .name = "wm8997-codec" },
};
int arizona_dev_init(struct arizona *arizona)
{
struct device *dev = arizona->dev;
@ -608,6 +618,7 @@ int arizona_dev_init(struct arizona *arizona)
switch (arizona->type) {
case WM5102:
case WM5110:
case WM8997:
for (i = 0; i < ARRAY_SIZE(wm5102_core_supplies); i++)
arizona->core_supplies[i].supply
= wm5102_core_supplies[i];
@ -683,6 +694,7 @@ int arizona_dev_init(struct arizona *arizona)
switch (reg) {
case 0x5102:
case 0x5110:
case 0x8997:
break;
default:
dev_err(arizona->dev, "Unknown device ID: %x\n", reg);
@ -767,6 +779,17 @@ int arizona_dev_init(struct arizona *arizona)
}
apply_patch = wm5110_patch;
break;
#endif
#ifdef CONFIG_MFD_WM8997
case 0x8997:
type_name = "WM8997";
if (arizona->type != WM8997) {
dev_err(arizona->dev, "WM8997 registered as %d\n",
arizona->type);
arizona->type = WM8997;
}
apply_patch = wm8997_patch;
break;
#endif
default:
dev_err(arizona->dev, "Unknown device ID %x\n", reg);
@ -934,6 +957,10 @@ int arizona_dev_init(struct arizona *arizona)
ret = mfd_add_devices(arizona->dev, -1, wm5110_devs,
ARRAY_SIZE(wm5110_devs), NULL, 0, NULL);
break;
case WM8997:
ret = mfd_add_devices(arizona->dev, -1, wm8997_devs,
ARRAY_SIZE(wm8997_devs), NULL, 0, NULL);
break;
}
if (ret != 0) {

View File

@ -44,6 +44,11 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
case WM5110:
regmap_config = &wm5110_i2c_regmap;
break;
#endif
#ifdef CONFIG_MFD_WM8997
case WM8997:
regmap_config = &wm8997_i2c_regmap;
break;
#endif
default:
dev_err(&i2c->dev, "Unknown device type %ld\n",
@ -80,6 +85,7 @@ static int arizona_i2c_remove(struct i2c_client *i2c)
static const struct i2c_device_id arizona_i2c_id[] = {
{ "wm5102", WM5102 },
{ "wm5110", WM5110 },
{ "wm8997", WM8997 },
{ }
};
MODULE_DEVICE_TABLE(i2c, arizona_i2c_id);

View File

@ -208,6 +208,14 @@ int arizona_irq_init(struct arizona *arizona)
ctrlif_error = false;
break;
#endif
#ifdef CONFIG_MFD_WM8997
case WM8997:
aod = &wm8997_aod;
irq = &wm8997_irq;
ctrlif_error = false;
break;
#endif
default:
BUG_ON("Unknown Arizona class device" == NULL);
return -EINVAL;

View File

@ -25,6 +25,8 @@ extern const struct regmap_config wm5102_spi_regmap;
extern const struct regmap_config wm5110_i2c_regmap;
extern const struct regmap_config wm5110_spi_regmap;
extern const struct regmap_config wm8997_i2c_regmap;
extern const struct dev_pm_ops arizona_pm_ops;
extern const struct of_device_id arizona_of_match[];
@ -35,6 +37,9 @@ extern const struct regmap_irq_chip wm5102_irq;
extern const struct regmap_irq_chip wm5110_aod;
extern const struct regmap_irq_chip wm5110_irq;
extern const struct regmap_irq_chip wm8997_aod;
extern const struct regmap_irq_chip wm8997_irq;
int arizona_dev_init(struct arizona *arizona);
int arizona_dev_exit(struct arizona *arizona);
int arizona_irq_init(struct arizona *arizona);

View File

@ -958,7 +958,8 @@ static int __init asic3_probe(struct platform_device *pdev)
unsigned long clksel;
int ret = 0;
asic = kzalloc(sizeof(struct asic3), GFP_KERNEL);
asic = devm_kzalloc(&pdev->dev,
sizeof(struct asic3), GFP_KERNEL);
if (asic == NULL) {
printk(KERN_ERR "kzalloc failed\n");
return -ENOMEM;
@ -970,16 +971,14 @@ static int __init asic3_probe(struct platform_device *pdev)
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
ret = -ENOMEM;
dev_err(asic->dev, "no MEM resource\n");
goto out_free;
return -ENOMEM;
}
asic->mapping = ioremap(mem->start, resource_size(mem));
if (!asic->mapping) {
ret = -ENOMEM;
dev_err(asic->dev, "Couldn't ioremap\n");
goto out_free;
return -ENOMEM;
}
asic->irq_base = pdata->irq_base;
@ -1033,9 +1032,6 @@ static int __init asic3_probe(struct platform_device *pdev)
out_unmap:
iounmap(asic->mapping);
out_free:
kfree(asic);
return ret;
}
@ -1058,8 +1054,6 @@ static int asic3_remove(struct platform_device *pdev)
iounmap(asic->mapping);
kfree(asic);
return 0;
}

View File

@ -104,23 +104,19 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
ec_dev->command_sendrecv = cros_ec_command_sendrecv;
if (ec_dev->din_size) {
ec_dev->din = kmalloc(ec_dev->din_size, GFP_KERNEL);
if (!ec_dev->din) {
err = -ENOMEM;
goto fail_din;
}
ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
if (!ec_dev->din)
return -ENOMEM;
}
if (ec_dev->dout_size) {
ec_dev->dout = kmalloc(ec_dev->dout_size, GFP_KERNEL);
if (!ec_dev->dout) {
err = -ENOMEM;
goto fail_dout;
}
ec_dev->dout = devm_kzalloc(dev, ec_dev->dout_size, GFP_KERNEL);
if (!ec_dev->dout)
return -ENOMEM;
}
if (!ec_dev->irq) {
dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq);
goto fail_irq;
return err;
}
err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
@ -128,7 +124,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
"chromeos-ec", ec_dev);
if (err) {
dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err);
goto fail_irq;
return err;
}
err = mfd_add_devices(dev, 0, cros_devs,
@ -145,11 +141,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
fail_mfd:
free_irq(ec_dev->irq, ec_dev);
fail_irq:
kfree(ec_dev->dout);
fail_dout:
kfree(ec_dev->din);
fail_din:
return err;
}
EXPORT_SYMBOL(cros_ec_register);
@ -158,8 +150,6 @@ int cros_ec_remove(struct cros_ec_device *ec_dev)
{
mfd_remove_devices(ec_dev->dev);
free_irq(ec_dev->irq, ec_dev);
kfree(ec_dev->dout);
kfree(ec_dev->din);
return 0;
}

View File

@ -46,56 +46,39 @@ void davinci_vc_write(struct davinci_vc *davinci_vc,
static int __init davinci_vc_probe(struct platform_device *pdev)
{
struct davinci_vc *davinci_vc;
struct resource *res, *mem;
struct resource *res;
struct mfd_cell *cell = NULL;
int ret;
davinci_vc = kzalloc(sizeof(struct davinci_vc), GFP_KERNEL);
davinci_vc = devm_kzalloc(&pdev->dev,
sizeof(struct davinci_vc), GFP_KERNEL);
if (!davinci_vc) {
dev_dbg(&pdev->dev,
"could not allocate memory for private data\n");
return -ENOMEM;
}
davinci_vc->clk = clk_get(&pdev->dev, NULL);
davinci_vc->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(davinci_vc->clk)) {
dev_dbg(&pdev->dev,
"could not get the clock for voice codec\n");
ret = -ENODEV;
goto fail1;
return -ENODEV;
}
clk_enable(davinci_vc->clk);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "no mem resource\n");
ret = -ENODEV;
goto fail2;
}
davinci_vc->pbase = res->start;
davinci_vc->base_size = resource_size(res);
mem = request_mem_region(davinci_vc->pbase, davinci_vc->base_size,
pdev->name);
if (!mem) {
dev_err(&pdev->dev, "VCIF region already claimed\n");
ret = -EBUSY;
goto fail2;
}
davinci_vc->base = ioremap(davinci_vc->pbase, davinci_vc->base_size);
if (!davinci_vc->base) {
dev_err(&pdev->dev, "can't ioremap mem resource.\n");
ret = -ENOMEM;
goto fail3;
davinci_vc->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(davinci_vc->base)) {
ret = PTR_ERR(davinci_vc->base);
goto fail;
}
res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (!res) {
dev_err(&pdev->dev, "no DMA resource\n");
ret = -ENXIO;
goto fail4;
goto fail;
}
davinci_vc->davinci_vcif.dma_tx_channel = res->start;
@ -106,7 +89,7 @@ static int __init davinci_vc_probe(struct platform_device *pdev)
if (!res) {
dev_err(&pdev->dev, "no DMA resource\n");
ret = -ENXIO;
goto fail4;
goto fail;
}
davinci_vc->davinci_vcif.dma_rx_channel = res->start;
@ -132,21 +115,13 @@ static int __init davinci_vc_probe(struct platform_device *pdev)
DAVINCI_VC_CELLS, NULL, 0, NULL);
if (ret != 0) {
dev_err(&pdev->dev, "fail to register client devices\n");
goto fail4;
goto fail;
}
return 0;
fail4:
iounmap(davinci_vc->base);
fail3:
release_mem_region(davinci_vc->pbase, davinci_vc->base_size);
fail2:
fail:
clk_disable(davinci_vc->clk);
clk_put(davinci_vc->clk);
davinci_vc->clk = NULL;
fail1:
kfree(davinci_vc);
return ret;
}
@ -157,14 +132,7 @@ static int davinci_vc_remove(struct platform_device *pdev)
mfd_remove_devices(&pdev->dev);
iounmap(davinci_vc->base);
release_mem_region(davinci_vc->pbase, davinci_vc->base_size);
clk_disable(davinci_vc->clk);
clk_put(davinci_vc->clk);
davinci_vc->clk = NULL;
kfree(davinci_vc);
return 0;
}

View File

@ -16,8 +16,8 @@
#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end))
#define PRCM_ACLK_MGT (0x004)
#define PRCM_SVACLK_MGT (0x008)
#define PRCM_SIACLK_MGT (0x00C)
#define PRCM_SVAMMCSPCLK_MGT (0x008)
#define PRCM_SIAMMDSPCLK_MGT (0x00C)
#define PRCM_SGACLK_MGT (0x014)
#define PRCM_UARTCLK_MGT (0x018)
#define PRCM_MSP02CLK_MGT (0x01C)

View File

@ -270,7 +270,7 @@ static int __init egpio_probe(struct platform_device *pdev)
int ret;
/* Initialize ei data structure. */
ei = kzalloc(sizeof(*ei), GFP_KERNEL);
ei = devm_kzalloc(&pdev->dev, sizeof(*ei), GFP_KERNEL);
if (!ei)
return -ENOMEM;
@ -286,7 +286,8 @@ static int __init egpio_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
goto fail;
ei->base_addr = ioremap_nocache(res->start, resource_size(res));
ei->base_addr = devm_ioremap_nocache(&pdev->dev, res->start,
resource_size(res));
if (!ei->base_addr)
goto fail;
pr_debug("EGPIO phys=%08x virt=%p\n", (u32)res->start, ei->base_addr);
@ -306,7 +307,9 @@ static int __init egpio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ei);
ei->nchips = pdata->num_chips;
ei->chip = kzalloc(sizeof(struct egpio_chip) * ei->nchips, GFP_KERNEL);
ei->chip = devm_kzalloc(&pdev->dev,
sizeof(struct egpio_chip) * ei->nchips,
GFP_KERNEL);
if (!ei->chip) {
ret = -ENOMEM;
goto fail;
@ -361,7 +364,6 @@ static int __init egpio_probe(struct platform_device *pdev)
fail:
printk(KERN_ERR "EGPIO failed to setup\n");
kfree(ei);
return ret;
}
@ -379,9 +381,6 @@ static int __exit egpio_remove(struct platform_device *pdev)
irq_set_chained_handler(ei->chained_irq, NULL);
device_init_wakeup(&pdev->dev, 0);
}
iounmap(ei->base_addr);
kfree(ei->chip);
kfree(ei);
return 0;
}

View File

@ -514,8 +514,8 @@ static int htcpld_setup_chips(struct platform_device *pdev)
/* Setup each chip's output GPIOs */
htcpld->nchips = pdata->num_chip;
htcpld->chip = kzalloc(sizeof(struct htcpld_chip) * htcpld->nchips,
GFP_KERNEL);
htcpld->chip = devm_kzalloc(dev, sizeof(struct htcpld_chip) * htcpld->nchips,
GFP_KERNEL);
if (!htcpld->chip) {
dev_warn(dev, "Unable to allocate memory for chips\n");
return -ENOMEM;
@ -580,12 +580,11 @@ static int htcpld_core_probe(struct platform_device *pdev)
return -ENXIO;
}
htcpld = kzalloc(sizeof(struct htcpld_data), GFP_KERNEL);
htcpld = devm_kzalloc(dev, sizeof(struct htcpld_data), GFP_KERNEL);
if (!htcpld)
return -ENOMEM;
/* Find chained irq */
ret = -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res) {
int flags;
@ -598,7 +597,7 @@ static int htcpld_core_probe(struct platform_device *pdev)
flags, pdev->name, htcpld);
if (ret) {
dev_warn(dev, "Unable to setup chained irq handler: %d\n", ret);
goto fail;
return ret;
} else
device_init_wakeup(dev, 0);
}
@ -609,7 +608,7 @@ static int htcpld_core_probe(struct platform_device *pdev)
/* Setup the htcpld chips */
ret = htcpld_setup_chips(pdev);
if (ret)
goto fail;
return ret;
/* Request the GPIO(s) for the int reset and set them up */
if (pdata->int_reset_gpio_hi) {
@ -644,10 +643,6 @@ static int htcpld_core_probe(struct platform_device *pdev)
dev_info(dev, "Initialized successfully\n");
return 0;
fail:
kfree(htcpld);
return ret;
}
/* The I2C Driver -- used internally */

View File

@ -147,7 +147,7 @@ static int __init pasic3_probe(struct platform_device *pdev)
if (!request_mem_region(r->start, resource_size(r), "pasic3"))
return -EBUSY;
asic = kzalloc(sizeof(struct pasic3_data), GFP_KERNEL);
asic = devm_kzalloc(dev, sizeof(struct pasic3_data), GFP_KERNEL);
if (!asic)
return -ENOMEM;
@ -156,7 +156,6 @@ static int __init pasic3_probe(struct platform_device *pdev)
asic->mapping = ioremap(r->start, resource_size(r));
if (!asic->mapping) {
dev_err(dev, "couldn't ioremap PASIC3\n");
kfree(asic);
return -ENOMEM;
}
@ -195,7 +194,6 @@ static int pasic3_remove(struct platform_device *pdev)
iounmap(asic->mapping);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(r->start, resource_size(r));
kfree(asic);
return 0;
}

View File

@ -438,7 +438,6 @@ static int intel_msic_remove(struct platform_device *pdev)
struct intel_msic *msic = platform_get_drvdata(pdev);
intel_msic_remove_devices(msic);
platform_set_drvdata(pdev, NULL);
return 0;
}

View File

@ -183,11 +183,10 @@ static int cmodio_pci_probe(struct pci_dev *dev,
struct cmodio_device *priv;
int ret;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(&dev->dev, "unable to allocate private data\n");
ret = -ENOMEM;
goto out_return;
return -ENOMEM;
}
pci_set_drvdata(dev, priv);
@ -197,7 +196,7 @@ static int cmodio_pci_probe(struct pci_dev *dev,
ret = pci_enable_device(dev);
if (ret) {
dev_err(&dev->dev, "unable to enable device\n");
goto out_free_priv;
return ret;
}
pci_set_master(dev);
@ -248,9 +247,7 @@ out_pci_release_regions:
pci_release_regions(dev);
out_pci_disable_device:
pci_disable_device(dev);
out_free_priv:
kfree(priv);
out_return:
return ret;
}
@ -263,7 +260,6 @@ static void cmodio_pci_remove(struct pci_dev *dev)
iounmap(priv->ctrl);
pci_release_regions(dev);
pci_disable_device(dev);
kfree(priv);
}
#define PCI_VENDOR_ID_JANZ 0x13c3

View File

@ -86,13 +86,13 @@ static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc)
static inline void jz4740_adc_clk_enable(struct jz4740_adc *adc)
{
if (atomic_inc_return(&adc->clk_ref) == 1)
clk_enable(adc->clk);
clk_prepare_enable(adc->clk);
}
static inline void jz4740_adc_clk_disable(struct jz4740_adc *adc)
{
if (atomic_dec_return(&adc->clk_ref) == 0)
clk_disable(adc->clk);
clk_disable_unprepare(adc->clk);
}
static inline void jz4740_adc_set_enabled(struct jz4740_adc *adc, int engine,
@ -294,7 +294,6 @@ static int jz4740_adc_probe(struct platform_device *pdev)
err_clk_put:
clk_put(adc->clk);
err_iounmap:
platform_set_drvdata(pdev, NULL);
iounmap(adc->base);
err_release_mem_region:
release_mem_region(adc->mem->start, resource_size(adc->mem));
@ -317,8 +316,6 @@ static int jz4740_adc_remove(struct platform_device *pdev)
clk_put(adc->clk);
platform_set_drvdata(pdev, NULL);
return 0;
}

641
drivers/mfd/kempld-core.c Normal file
View File

@ -0,0 +1,641 @@
/*
* Kontron PLD MFD core driver
*
* Copyright (c) 2010-2013 Kontron Europe GmbH
* Author: Michael Brunner <michael.brunner@kontron.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 2 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/kempld.h>
#include <linux/module.h>
#include <linux/dmi.h>
#include <linux/io.h>
#include <linux/delay.h>
#define MAX_ID_LEN 4
static char force_device_id[MAX_ID_LEN + 1] = "";
module_param_string(force_device_id, force_device_id, sizeof(force_device_id), 0);
MODULE_PARM_DESC(force_device_id, "Override detected product");
/*
* Get hardware mutex to block firmware from accessing the pld.
* It is possible for the firmware may hold the mutex for an extended length of
* time. This function will block until access has been granted.
*/
static void kempld_get_hardware_mutex(struct kempld_device_data *pld)
{
/* The mutex bit will read 1 until access has been granted */
while (ioread8(pld->io_index) & KEMPLD_MUTEX_KEY)
msleep(1);
}
static void kempld_release_hardware_mutex(struct kempld_device_data *pld)
{
/* The harware mutex is released when 1 is written to the mutex bit. */
iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
}
static int kempld_get_info_generic(struct kempld_device_data *pld)
{
u16 version;
u8 spec;
kempld_get_mutex(pld);
version = kempld_read16(pld, KEMPLD_VERSION);
spec = kempld_read8(pld, KEMPLD_SPEC);
pld->info.buildnr = kempld_read16(pld, KEMPLD_BUILDNR);
pld->info.minor = KEMPLD_VERSION_GET_MINOR(version);
pld->info.major = KEMPLD_VERSION_GET_MAJOR(version);
pld->info.number = KEMPLD_VERSION_GET_NUMBER(version);
pld->info.type = KEMPLD_VERSION_GET_TYPE(version);
if (spec == 0xff) {
pld->info.spec_minor = 0;
pld->info.spec_major = 1;
} else {
pld->info.spec_minor = KEMPLD_SPEC_GET_MINOR(spec);
pld->info.spec_major = KEMPLD_SPEC_GET_MAJOR(spec);
}
if (pld->info.spec_major > 0)
pld->feature_mask = kempld_read16(pld, KEMPLD_FEATURE);
else
pld->feature_mask = 0;
kempld_release_mutex(pld);
return 0;
}
enum kempld_cells {
KEMPLD_I2C = 0,
KEMPLD_WDT,
KEMPLD_GPIO,
KEMPLD_UART,
};
static struct mfd_cell kempld_devs[] = {
[KEMPLD_I2C] = {
.name = "kempld-i2c",
},
[KEMPLD_WDT] = {
.name = "kempld-wdt",
},
[KEMPLD_GPIO] = {
.name = "kempld-gpio",
},
[KEMPLD_UART] = {
.name = "kempld-uart",
},
};
#define KEMPLD_MAX_DEVS ARRAY_SIZE(kempld_devs)
static int kempld_register_cells_generic(struct kempld_device_data *pld)
{
struct mfd_cell devs[KEMPLD_MAX_DEVS];
int i = 0;
if (pld->feature_mask & KEMPLD_FEATURE_BIT_I2C)
devs[i++] = kempld_devs[KEMPLD_I2C];
if (pld->feature_mask & KEMPLD_FEATURE_BIT_WATCHDOG)
devs[i++] = kempld_devs[KEMPLD_WDT];
if (pld->feature_mask & KEMPLD_FEATURE_BIT_GPIO)
devs[i++] = kempld_devs[KEMPLD_GPIO];
if (pld->feature_mask & KEMPLD_FEATURE_MASK_UART)
devs[i++] = kempld_devs[KEMPLD_UART];
return mfd_add_devices(pld->dev, -1, devs, i, NULL, 0, NULL);
}
static struct resource kempld_ioresource = {
.start = KEMPLD_IOINDEX,
.end = KEMPLD_IODATA,
.flags = IORESOURCE_IO,
};
static const struct kempld_platform_data kempld_platform_data_generic = {
.pld_clock = KEMPLD_CLK,
.ioresource = &kempld_ioresource,
.get_hardware_mutex = kempld_get_hardware_mutex,
.release_hardware_mutex = kempld_release_hardware_mutex,
.get_info = kempld_get_info_generic,
.register_cells = kempld_register_cells_generic,
};
static struct platform_device *kempld_pdev;
static int kempld_create_platform_device(const struct dmi_system_id *id)
{
struct kempld_platform_data *pdata = id->driver_data;
int ret;
kempld_pdev = platform_device_alloc("kempld", -1);
if (!kempld_pdev)
return -ENOMEM;
ret = platform_device_add_data(kempld_pdev, pdata, sizeof(*pdata));
if (ret)
goto err;
ret = platform_device_add_resources(kempld_pdev, pdata->ioresource, 1);
if (ret)
goto err;
ret = platform_device_add(kempld_pdev);
if (ret)
goto err;
return 0;
err:
platform_device_put(kempld_pdev);
return ret;
}
/**
* kempld_read8 - read 8 bit register
* @pld: kempld_device_data structure describing the PLD
* @index: register index on the chip
*
* kempld_get_mutex must be called prior to calling this function.
*/
u8 kempld_read8(struct kempld_device_data *pld, u8 index)
{
iowrite8(index, pld->io_index);
return ioread8(pld->io_data);
}
EXPORT_SYMBOL_GPL(kempld_read8);
/**
* kempld_write8 - write 8 bit register
* @pld: kempld_device_data structure describing the PLD
* @index: register index on the chip
* @data: new register value
*
* kempld_get_mutex must be called prior to calling this function.
*/
void kempld_write8(struct kempld_device_data *pld, u8 index, u8 data)
{
iowrite8(index, pld->io_index);
iowrite8(data, pld->io_data);
}
EXPORT_SYMBOL_GPL(kempld_write8);
/**
* kempld_read16 - read 16 bit register
* @pld: kempld_device_data structure describing the PLD
* @index: register index on the chip
*
* kempld_get_mutex must be called prior to calling this function.
*/
u16 kempld_read16(struct kempld_device_data *pld, u8 index)
{
return kempld_read8(pld, index) | kempld_read8(pld, index + 1) << 8;
}
EXPORT_SYMBOL_GPL(kempld_read16);
/**
* kempld_write16 - write 16 bit register
* @pld: kempld_device_data structure describing the PLD
* @index: register index on the chip
* @data: new register value
*
* kempld_get_mutex must be called prior to calling this function.
*/
void kempld_write16(struct kempld_device_data *pld, u8 index, u16 data)
{
kempld_write8(pld, index, (u8)data);
kempld_write8(pld, index + 1, (u8)(data >> 8));
}
EXPORT_SYMBOL_GPL(kempld_write16);
/**
* kempld_read32 - read 32 bit register
* @pld: kempld_device_data structure describing the PLD
* @index: register index on the chip
*
* kempld_get_mutex must be called prior to calling this function.
*/
u32 kempld_read32(struct kempld_device_data *pld, u8 index)
{
return kempld_read16(pld, index) | kempld_read16(pld, index + 2) << 16;
}
EXPORT_SYMBOL_GPL(kempld_read32);
/**
* kempld_write32 - write 32 bit register
* @pld: kempld_device_data structure describing the PLD
* @index: register index on the chip
* @data: new register value
*
* kempld_get_mutex must be called prior to calling this function.
*/
void kempld_write32(struct kempld_device_data *pld, u8 index, u32 data)
{
kempld_write16(pld, index, (u16)data);
kempld_write16(pld, index + 2, (u16)(data >> 16));
}
EXPORT_SYMBOL_GPL(kempld_write32);
/**
* kempld_get_mutex - acquire PLD mutex
* @pld: kempld_device_data structure describing the PLD
*/
void kempld_get_mutex(struct kempld_device_data *pld)
{
struct kempld_platform_data *pdata = pld->dev->platform_data;
mutex_lock(&pld->lock);
pdata->get_hardware_mutex(pld);
}
EXPORT_SYMBOL_GPL(kempld_get_mutex);
/**
* kempld_release_mutex - release PLD mutex
* @pld: kempld_device_data structure describing the PLD
*/
void kempld_release_mutex(struct kempld_device_data *pld)
{
struct kempld_platform_data *pdata = pld->dev->platform_data;
pdata->release_hardware_mutex(pld);
mutex_unlock(&pld->lock);
}
EXPORT_SYMBOL_GPL(kempld_release_mutex);
/**
* kempld_get_info - update device specific information
* @pld: kempld_device_data structure describing the PLD
*
* This function calls the configured board specific kempld_get_info_XXXX
* function which is responsible for gathering information about the specific
* hardware. The information is then stored within the pld structure.
*/
static int kempld_get_info(struct kempld_device_data *pld)
{
struct kempld_platform_data *pdata = pld->dev->platform_data;
return pdata->get_info(pld);
}
/*
* kempld_register_cells - register cell drivers
*
* This function registers cell drivers for the detected hardware by calling
* the configured kempld_register_cells_XXXX function which is responsible
* to detect and register the needed cell drivers.
*/
static int kempld_register_cells(struct kempld_device_data *pld)
{
struct kempld_platform_data *pdata = pld->dev->platform_data;
return pdata->register_cells(pld);
}
static int kempld_detect_device(struct kempld_device_data *pld)
{
char *version_type;
u8 index_reg;
int ret;
mutex_lock(&pld->lock);
/* Check for empty IO space */
index_reg = ioread8(pld->io_index);
if (index_reg == 0xff && ioread8(pld->io_data) == 0xff) {
mutex_unlock(&pld->lock);
return -ENODEV;
}
/* Release hardware mutex if aquired */
if (!(index_reg & KEMPLD_MUTEX_KEY))
iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
mutex_unlock(&pld->lock);
ret = kempld_get_info(pld);
if (ret)
return ret;
switch (pld->info.type) {
case 0:
version_type = "release";
break;
case 1:
version_type = "debug";
break;
case 2:
version_type = "custom";
break;
default:
version_type = "unspecified";
}
dev_info(pld->dev, "Found Kontron PLD %d\n", pld->info.number);
dev_info(pld->dev, "%s version %d.%d build %d, specification %d.%d\n",
version_type, pld->info.major, pld->info.minor,
pld->info.buildnr, pld->info.spec_major,
pld->info.spec_minor);
return kempld_register_cells(pld);
}
static int kempld_probe(struct platform_device *pdev)
{
struct kempld_platform_data *pdata = pdev->dev.platform_data;
struct device *dev = &pdev->dev;
struct kempld_device_data *pld;
struct resource *ioport;
int ret;
pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL);
if (!pld)
return -ENOMEM;
ioport = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!ioport)
return -EINVAL;
pld->io_base = devm_ioport_map(dev, ioport->start,
ioport->end - ioport->start);
if (!pld->io_base)
return -ENOMEM;
pld->io_index = pld->io_base;
pld->io_data = pld->io_base + 1;
pld->pld_clock = pdata->pld_clock;
pld->dev = dev;
mutex_init(&pld->lock);
platform_set_drvdata(pdev, pld);
ret = kempld_detect_device(pld);
if (ret)
return ret;
return 0;
}
static int kempld_remove(struct platform_device *pdev)
{
struct kempld_device_data *pld = platform_get_drvdata(pdev);
struct kempld_platform_data *pdata = pld->dev->platform_data;
mfd_remove_devices(&pdev->dev);
pdata->release_hardware_mutex(pld);
return 0;
}
static struct platform_driver kempld_driver = {
.driver = {
.name = "kempld",
.owner = THIS_MODULE,
},
.probe = kempld_probe,
.remove = kempld_remove,
};
static struct dmi_system_id __initdata kempld_dmi_table[] = {
{
.ident = "CCR2",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP2"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CCR6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP6"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CHR2",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T2"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CHR2",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T2"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CHR2",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC2"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CHR6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T6"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CHR6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T6"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CHR6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC6"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CNTG",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-PC"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CNTG",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bPC2"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CNTX",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "PXT"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "FRI2",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BIOS_VERSION, "FRI2"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "FRI2",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "Fish River Island II"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "MBR1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "ETX-OH"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "NTC1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "nanoETXexpress-TT"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "NTC1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "nETXe-TT"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "NTC1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-mTT"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "NUP1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-mCT"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "UNP1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-DC"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "UNP1",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cDC2"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "UNTG",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-PC"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "UNTG",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cPC2"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "UUP6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cCT6"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
},
{}
};
MODULE_DEVICE_TABLE(dmi, kempld_dmi_table);
static int __init kempld_init(void)
{
const struct dmi_system_id *id;
int ret;
if (force_device_id[0]) {
for (id = kempld_dmi_table; id->matches[0].slot != DMI_NONE; id++)
if (strstr(id->ident, force_device_id))
if (id->callback && id->callback(id))
break;
if (id->matches[0].slot == DMI_NONE)
return -ENODEV;
} else {
if (!dmi_check_system(kempld_dmi_table))
return -ENODEV;
}
ret = platform_driver_register(&kempld_driver);
if (ret)
return ret;
return 0;
}
static void __exit kempld_exit(void)
{
if (kempld_pdev)
platform_device_unregister(kempld_pdev);
platform_driver_unregister(&kempld_driver);
}
module_init(kempld_init);
module_exit(kempld_exit);
MODULE_DESCRIPTION("KEM PLD Core Driver");
MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:kempld-core");

View File

@ -51,6 +51,8 @@
* document number TBD : Lynx Point
* document number TBD : Lynx Point-LP
* document number TBD : Wellsburg
* document number TBD : Avoton SoC
* document number TBD : Coleto Creek
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@ -207,6 +209,8 @@ enum lpc_chipsets {
LPC_LPT, /* Lynx Point */
LPC_LPT_LP, /* Lynx Point-LP */
LPC_WBG, /* Wellsburg */
LPC_AVN, /* Avoton SoC */
LPC_COLETO, /* Coleto Creek */
};
struct lpc_ich_info lpc_chipset_info[] = {
@ -491,6 +495,14 @@ struct lpc_ich_info lpc_chipset_info[] = {
.name = "Wellsburg",
.iTCO_version = 2,
},
[LPC_AVN] = {
.name = "Avoton SoC",
.iTCO_version = 1,
},
[LPC_COLETO] = {
.name = "Coleto Creek",
.iTCO_version = 2,
},
};
/*
@ -704,6 +716,11 @@ static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = {
{ PCI_VDEVICE(INTEL, 0x8d5d), LPC_WBG},
{ PCI_VDEVICE(INTEL, 0x8d5e), LPC_WBG},
{ PCI_VDEVICE(INTEL, 0x8d5f), LPC_WBG},
{ PCI_VDEVICE(INTEL, 0x1f38), LPC_AVN},
{ PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN},
{ PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN},
{ PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN},
{ PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO},
{ 0, }, /* End of list */
};
MODULE_DEVICE_TABLE(pci, lpc_ich_ids);
@ -973,18 +990,7 @@ static struct pci_driver lpc_ich_driver = {
.remove = lpc_ich_remove,
};
static int __init lpc_ich_init(void)
{
return pci_register_driver(&lpc_ich_driver);
}
static void __exit lpc_ich_exit(void)
{
pci_unregister_driver(&lpc_ich_driver);
}
module_init(lpc_ich_init);
module_exit(lpc_ich_exit);
module_pci_driver(lpc_ich_driver);
MODULE_AUTHOR("Aaron Sierra <asierra@xes-inc.com>");
MODULE_DESCRIPTION("LPC interface for Intel ICH");

View File

@ -37,6 +37,7 @@
static struct mfd_cell max77686_devs[] = {
{ .name = "max77686-pmic", },
{ .name = "max77686-rtc", },
{ .name = "max77686-clk", },
};
static struct regmap_config max77686_regmap_config = {
@ -84,12 +85,12 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
pdata = max77686_i2c_parse_dt_pdata(&i2c->dev);
if (!pdata) {
ret = -EIO;
dev_err(&i2c->dev, "No platform data found.\n");
goto err;
return -EIO;
}
max77686 = kzalloc(sizeof(struct max77686_dev), GFP_KERNEL);
max77686 = devm_kzalloc(&i2c->dev,
sizeof(struct max77686_dev), GFP_KERNEL);
if (max77686 == NULL)
return -ENOMEM;
@ -107,7 +108,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
ret = PTR_ERR(max77686->regmap);
dev_err(max77686->dev, "Failed to allocate register map: %d\n",
ret);
kfree(max77686);
return ret;
}
@ -115,8 +115,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
MAX77686_REG_DEVICE_ID, &data) < 0) {
dev_err(max77686->dev,
"device not found on this channel (this is not an error)\n");
ret = -ENODEV;
goto err;
return -ENODEV;
} else
dev_info(max77686->dev, "device found\n");
@ -127,17 +126,11 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
ret = mfd_add_devices(max77686->dev, -1, max77686_devs,
ARRAY_SIZE(max77686_devs), NULL, 0, NULL);
if (ret < 0) {
mfd_remove_devices(max77686->dev);
i2c_unregister_device(max77686->rtc);
}
if (ret < 0)
goto err_mfd;
return ret;
err_mfd:
mfd_remove_devices(max77686->dev);
i2c_unregister_device(max77686->rtc);
err:
kfree(max77686);
return ret;
}
@ -147,7 +140,6 @@ static int max77686_i2c_remove(struct i2c_client *i2c)
mfd_remove_devices(max77686->dev);
i2c_unregister_device(max77686->rtc);
kfree(max77686);
return 0;
}

View File

@ -170,7 +170,8 @@ static int max8925_probe(struct i2c_client *client,
return -EINVAL;
}
chip = kzalloc(sizeof(struct max8925_chip), GFP_KERNEL);
chip = devm_kzalloc(&client->dev,
sizeof(struct max8925_chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
chip->i2c = client;
@ -199,7 +200,6 @@ static int max8925_remove(struct i2c_client *client)
max8925_device_exit(chip);
i2c_unregister_device(chip->adc);
i2c_unregister_device(chip->rtc);
kfree(chip);
return 0;
}

View File

@ -14,6 +14,7 @@
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/mfd/max8998-private.h>
struct max8998_irq_data {
@ -99,7 +100,8 @@ static struct max8998_irq_data max8998_irqs[] = {
static inline struct max8998_irq_data *
irq_to_max8998_irq(struct max8998_dev *max8998, int irq)
{
return &max8998_irqs[irq - max8998->irq_base];
struct irq_data *data = irq_get_irq_data(irq);
return &max8998_irqs[data->hwirq];
}
static void max8998_irq_lock(struct irq_data *data)
@ -176,8 +178,14 @@ static irqreturn_t max8998_irq_thread(int irq, void *data)
/* Report */
for (i = 0; i < MAX8998_IRQ_NR; i++) {
if (irq_reg[max8998_irqs[i].reg - 1] & max8998_irqs[i].mask)
handle_nested_irq(max8998->irq_base + i);
if (irq_reg[max8998_irqs[i].reg - 1] & max8998_irqs[i].mask) {
irq = irq_find_mapping(max8998->irq_domain, i);
if (WARN_ON(!irq)) {
disable_irq_nosync(max8998->irq);
return IRQ_NONE;
}
handle_nested_irq(irq);
}
}
return IRQ_HANDLED;
@ -185,27 +193,40 @@ static irqreturn_t max8998_irq_thread(int irq, void *data)
int max8998_irq_resume(struct max8998_dev *max8998)
{
if (max8998->irq && max8998->irq_base)
max8998_irq_thread(max8998->irq_base, max8998);
if (max8998->irq && max8998->irq_domain)
max8998_irq_thread(max8998->irq, max8998);
return 0;
}
static int max8998_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hw)
{
struct max8997_dev *max8998 = d->host_data;
irq_set_chip_data(irq, max8998);
irq_set_chip_and_handler(irq, &max8998_irq_chip, handle_edge_irq);
irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq);
#endif
return 0;
}
static struct irq_domain_ops max8998_irq_domain_ops = {
.map = max8998_irq_domain_map,
};
int max8998_irq_init(struct max8998_dev *max8998)
{
int i;
int cur_irq;
int ret;
struct irq_domain *domain;
if (!max8998->irq) {
dev_warn(max8998->dev,
"No interrupt specified, no interrupts\n");
max8998->irq_base = 0;
return 0;
}
if (!max8998->irq_base) {
dev_err(max8998->dev,
"No interrupt base specified, no interrupts\n");
return 0;
}
@ -221,19 +242,13 @@ int max8998_irq_init(struct max8998_dev *max8998)
max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM1, 0xff);
max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM2, 0xff);
/* register with genirq */
for (i = 0; i < MAX8998_IRQ_NR; i++) {
cur_irq = i + max8998->irq_base;
irq_set_chip_data(cur_irq, max8998);
irq_set_chip_and_handler(cur_irq, &max8998_irq_chip,
handle_edge_irq);
irq_set_nested_thread(cur_irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(cur_irq, IRQF_VALID);
#else
irq_set_noprobe(cur_irq);
#endif
domain = irq_domain_add_simple(NULL, MAX8998_IRQ_NR,
max8998->irq_base, &max8998_irq_domain_ops, max8998);
if (!domain) {
dev_err(max8998->dev, "could not create irq domain\n");
return -ENODEV;
}
max8998->irq_domain = domain;
ret = request_threaded_irq(max8998->irq, NULL, max8998_irq_thread,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,

View File

@ -20,12 +20,15 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/err.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/pm_runtime.h>
#include <linux/mutex.h>
#include <linux/mfd/core.h>
@ -128,6 +131,56 @@ int max8998_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
}
EXPORT_SYMBOL(max8998_update_reg);
#ifdef CONFIG_OF
static struct of_device_id max8998_dt_match[] = {
{ .compatible = "maxim,max8998", .data = (void *)TYPE_MAX8998 },
{ .compatible = "national,lp3974", .data = (void *)TYPE_LP3974 },
{ .compatible = "ti,lp3974", .data = (void *)TYPE_LP3974 },
{},
};
MODULE_DEVICE_TABLE(of, max8998_dt_match);
#endif
/*
* Only the common platform data elements for max8998 are parsed here from the
* device tree. Other sub-modules of max8998 such as pmic, rtc and others have
* to parse their own platform data elements from device tree.
*
* The max8998 platform data structure is instantiated here and the drivers for
* the sub-modules need not instantiate another instance while parsing their
* platform data.
*/
static struct max8998_platform_data *max8998_i2c_parse_dt_pdata(
struct device *dev)
{
struct max8998_platform_data *pd;
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
if (!pd)
return ERR_PTR(-ENOMEM);
pd->ono = irq_of_parse_and_map(dev->of_node, 1);
/*
* ToDo: the 'wakeup' member in the platform data is more of a linux
* specfic information. Hence, there is no binding for that yet and
* not parsed here.
*/
return pd;
}
static inline int max8998_i2c_get_driver_data(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) {
const struct of_device_id *match;
match = of_match_node(max8998_dt_match, i2c->dev.of_node);
return (int)match->data;
}
return (int)id->driver_data;
}
static int max8998_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@ -139,11 +192,20 @@ static int max8998_i2c_probe(struct i2c_client *i2c,
if (max8998 == NULL)
return -ENOMEM;
if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) {
pdata = max8998_i2c_parse_dt_pdata(&i2c->dev);
if (IS_ERR(pdata)) {
ret = PTR_ERR(pdata);
goto err;
}
}
i2c_set_clientdata(i2c, max8998);
max8998->dev = &i2c->dev;
max8998->i2c = i2c;
max8998->irq = i2c->irq;
max8998->type = id->driver_data;
max8998->type = max8998_i2c_get_driver_data(i2c, id);
max8998->pdata = pdata;
if (pdata) {
max8998->ono = pdata->ono;
max8998->irq_base = pdata->irq_base;
@ -158,7 +220,7 @@ static int max8998_i2c_probe(struct i2c_client *i2c,
pm_runtime_set_active(max8998->dev);
switch (id->driver_data) {
switch (max8998->type) {
case TYPE_LP3974:
ret = mfd_add_devices(max8998->dev, -1,
lp3974_devs, ARRAY_SIZE(lp3974_devs),
@ -314,6 +376,7 @@ static struct i2c_driver max8998_i2c_driver = {
.name = "max8998",
.owner = THIS_MODULE,
.pm = &max8998_pm,
.of_match_table = of_match_ptr(max8998_dt_match),
},
.probe = max8998_i2c_probe,
.remove = max8998_i2c_remove,

View File

@ -225,8 +225,6 @@ static int mcp_sa11x0_probe(struct platform_device *dev)
if (ret == 0)
return 0;
platform_set_drvdata(dev, NULL);
err_ioremap:
iounmap(m->base1);
iounmap(m->base0);
@ -252,7 +250,6 @@ static int mcp_sa11x0_remove(struct platform_device *dev)
mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1);
platform_set_drvdata(dev, NULL);
mcp_host_del(mcp);
iounmap(m->base1);
iounmap(m->base0);

View File

@ -23,78 +23,7 @@
#include <linux/err.h>
#include <linux/mfd/core.h>
#include <linux/mfd/palmas.h>
#include <linux/of_platform.h>
enum palmas_ids {
PALMAS_PMIC_ID,
PALMAS_GPIO_ID,
PALMAS_LEDS_ID,
PALMAS_WDT_ID,
PALMAS_RTC_ID,
PALMAS_PWRBUTTON_ID,
PALMAS_GPADC_ID,
PALMAS_RESOURCE_ID,
PALMAS_CLK_ID,
PALMAS_PWM_ID,
PALMAS_USB_ID,
};
static struct resource palmas_rtc_resources[] = {
{
.start = PALMAS_RTC_ALARM_IRQ,
.end = PALMAS_RTC_ALARM_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static const struct mfd_cell palmas_children[] = {
{
.name = "palmas-pmic",
.id = PALMAS_PMIC_ID,
},
{
.name = "palmas-gpio",
.id = PALMAS_GPIO_ID,
},
{
.name = "palmas-leds",
.id = PALMAS_LEDS_ID,
},
{
.name = "palmas-wdt",
.id = PALMAS_WDT_ID,
},
{
.name = "palmas-rtc",
.id = PALMAS_RTC_ID,
.resources = &palmas_rtc_resources[0],
.num_resources = ARRAY_SIZE(palmas_rtc_resources),
},
{
.name = "palmas-pwrbutton",
.id = PALMAS_PWRBUTTON_ID,
},
{
.name = "palmas-gpadc",
.id = PALMAS_GPADC_ID,
},
{
.name = "palmas-resource",
.id = PALMAS_RESOURCE_ID,
},
{
.name = "palmas-clk",
.id = PALMAS_CLK_ID,
},
{
.name = "palmas-pwm",
.id = PALMAS_PWM_ID,
},
{
.name = "palmas-usb",
.id = PALMAS_USB_ID,
}
};
#include <linux/of_device.h>
static const struct regmap_config palmas_regmap_config[PALMAS_NUM_CLIENTS] = {
{
@ -302,6 +231,21 @@ static void palmas_dt_to_pdata(struct i2c_client *i2c,
palmas_set_pdata_irq_flag(i2c, pdata);
}
static unsigned int palmas_features = PALMAS_PMIC_FEATURE_SMPS10_BOOST;
static unsigned int tps659038_features;
static const struct of_device_id of_palmas_match_tbl[] = {
{
.compatible = "ti,palmas",
.data = &palmas_features,
},
{
.compatible = "ti,tps659038",
.data = &tps659038_features,
},
{ },
};
static int palmas_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@ -309,9 +253,9 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
struct palmas_platform_data *pdata;
struct device_node *node = i2c->dev.of_node;
int ret = 0, i;
unsigned int reg, addr;
unsigned int reg, addr, *features;
int slave;
struct mfd_cell *children;
const struct of_device_id *match;
pdata = dev_get_platdata(&i2c->dev);
@ -333,9 +277,16 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, palmas);
palmas->dev = &i2c->dev;
palmas->id = id->driver_data;
palmas->irq = i2c->irq;
match = of_match_device(of_match_ptr(of_palmas_match_tbl), &i2c->dev);
if (!match)
return -ENODATA;
features = (unsigned int *)match->data;
palmas->features = *features;
for (i = 0; i < PALMAS_NUM_CLIENTS; i++) {
if (i == 0)
palmas->i2c_clients[i] = i2c;
@ -362,6 +313,11 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
}
}
if (!palmas->irq) {
dev_warn(palmas->dev, "IRQ missing: skipping irq request\n");
goto no_irq;
}
/* Change interrupt line output polarity */
if (pdata->irq_flags & IRQ_TYPE_LEVEL_HIGH)
reg = PALMAS_POLARITY_CTRL_INT_POLARITY;
@ -388,6 +344,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
if (ret < 0)
goto err;
no_irq:
slave = PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE);
addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE,
PALMAS_PRIMARY_SECONDARY_PAD1);
@ -472,42 +429,8 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
return ret;
}
children = kmemdup(palmas_children, sizeof(palmas_children),
GFP_KERNEL);
if (!children) {
ret = -ENOMEM;
goto err_irq;
}
children[PALMAS_PMIC_ID].platform_data = pdata->pmic_pdata;
children[PALMAS_PMIC_ID].pdata_size = sizeof(*pdata->pmic_pdata);
children[PALMAS_GPADC_ID].platform_data = pdata->gpadc_pdata;
children[PALMAS_GPADC_ID].pdata_size = sizeof(*pdata->gpadc_pdata);
children[PALMAS_RESOURCE_ID].platform_data = pdata->resource_pdata;
children[PALMAS_RESOURCE_ID].pdata_size =
sizeof(*pdata->resource_pdata);
children[PALMAS_USB_ID].platform_data = pdata->usb_pdata;
children[PALMAS_USB_ID].pdata_size = sizeof(*pdata->usb_pdata);
children[PALMAS_CLK_ID].platform_data = pdata->clk_pdata;
children[PALMAS_CLK_ID].pdata_size = sizeof(*pdata->clk_pdata);
ret = mfd_add_devices(palmas->dev, -1,
children, ARRAY_SIZE(palmas_children),
NULL, 0,
regmap_irq_get_domain(palmas->irq_data));
kfree(children);
if (ret < 0)
goto err_devices;
return ret;
err_devices:
mfd_remove_devices(palmas->dev);
err_irq:
regmap_del_irq_chip(palmas->irq, palmas->irq_data);
err:
@ -533,11 +456,6 @@ static const struct i2c_device_id palmas_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, palmas_i2c_id);
static struct of_device_id of_palmas_match_tbl[] = {
{ .compatible = "ti,palmas", },
{ /* end */ }
};
static struct i2c_driver palmas_i2c_driver = {
.driver = {
.name = "palmas",

View File

@ -35,12 +35,33 @@ static u8 rtl8411_get_ic_version(struct rtsx_pcr *pcr)
return val & 0x0F;
}
static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr)
{
u8 val = 0;
rtsx_pci_read_register(pcr, RTL8411B_PACKAGE_MODE, &val);
if (val & 0x2)
return 1;
else
return 0;
}
static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_register(pcr, CD_PAD_CTL,
CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
}
static int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr)
{
if (rtl8411b_is_qfn48(pcr))
rtsx_pci_write_register(pcr, CARD_PULL_CTL3, 0xFF, 0xF5);
return rtsx_pci_write_register(pcr, CD_PAD_CTL,
CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
}
static int rtl8411_turn_on_led(struct rtsx_pcr *pcr)
{
return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00);
@ -214,6 +235,20 @@ static const struct pcr_ops rtl8411_pcr_ops = {
.conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
};
static const struct pcr_ops rtl8411b_pcr_ops = {
.extra_init_hw = rtl8411b_extra_init_hw,
.optimize_phy = NULL,
.turn_on_led = rtl8411_turn_on_led,
.turn_off_led = rtl8411_turn_off_led,
.enable_auto_blink = rtl8411_enable_auto_blink,
.disable_auto_blink = rtl8411_disable_auto_blink,
.card_power_on = rtl8411_card_power_on,
.card_power_off = rtl8411_card_power_off,
.switch_output_voltage = rtl8411_switch_output_voltage,
.cd_deglitch = rtl8411_cd_deglitch,
.conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
};
/* SD Pull Control Enable:
* SD_DAT[3:0] ==> pull up
* SD_CD ==> pull up
@ -276,6 +311,74 @@ static const u32 rtl8411_ms_pull_ctl_disable_tbl[] = {
0,
};
static const u32 rtl8411b_qfn64_sd_pull_ctl_enable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0x09 | 0xD0),
RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50),
RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
0,
};
static const u32 rtl8411b_qfn48_sd_pull_ctl_enable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0x69 | 0x90),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x08 | 0x11),
0,
};
static const u32 rtl8411b_qfn64_sd_pull_ctl_disable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0),
RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50),
RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
0,
};
static const u32 rtl8411b_qfn48_sd_pull_ctl_disable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
0,
};
static const u32 rtl8411b_qfn64_ms_pull_ctl_enable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0),
RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05 | 0x50),
RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
0,
};
static const u32 rtl8411b_qfn48_ms_pull_ctl_enable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
0,
};
static const u32 rtl8411b_qfn64_ms_pull_ctl_disable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0),
RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50),
RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
0,
};
static const u32 rtl8411b_qfn48_ms_pull_ctl_disable_tbl[] = {
RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90),
RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
0,
};
void rtl8411_init_params(struct rtsx_pcr *pcr)
{
pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
@ -288,3 +391,32 @@ void rtl8411_init_params(struct rtsx_pcr *pcr)
pcr->ms_pull_ctl_enable_tbl = rtl8411_ms_pull_ctl_enable_tbl;
pcr->ms_pull_ctl_disable_tbl = rtl8411_ms_pull_ctl_disable_tbl;
}
void rtl8411b_init_params(struct rtsx_pcr *pcr)
{
pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
pcr->num_slots = 2;
pcr->ops = &rtl8411b_pcr_ops;
pcr->ic_version = rtl8411_get_ic_version(pcr);
if (rtl8411b_is_qfn48(pcr)) {
pcr->sd_pull_ctl_enable_tbl =
rtl8411b_qfn48_sd_pull_ctl_enable_tbl;
pcr->sd_pull_ctl_disable_tbl =
rtl8411b_qfn48_sd_pull_ctl_disable_tbl;
pcr->ms_pull_ctl_enable_tbl =
rtl8411b_qfn48_ms_pull_ctl_enable_tbl;
pcr->ms_pull_ctl_disable_tbl =
rtl8411b_qfn48_ms_pull_ctl_disable_tbl;
} else {
pcr->sd_pull_ctl_enable_tbl =
rtl8411b_qfn64_sd_pull_ctl_enable_tbl;
pcr->sd_pull_ctl_disable_tbl =
rtl8411b_qfn64_sd_pull_ctl_disable_tbl;
pcr->ms_pull_ctl_enable_tbl =
rtl8411b_qfn64_ms_pull_ctl_enable_tbl;
pcr->ms_pull_ctl_disable_tbl =
rtl8411b_qfn64_ms_pull_ctl_disable_tbl;
}
}

View File

@ -57,6 +57,7 @@ static DEFINE_PCI_DEVICE_TABLE(rtsx_pci_ids) = {
{ PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ 0, }
};
@ -1038,6 +1039,10 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
case 0x5249:
rts5249_init_params(pcr);
break;
case 0x5287:
rtl8411b_init_params(pcr);
break;
}
dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n",

View File

@ -33,5 +33,6 @@ void rts5229_init_params(struct rtsx_pcr *pcr);
void rtl8411_init_params(struct rtsx_pcr *pcr);
void rts5227_init_params(struct rtsx_pcr *pcr);
void rts5249_init_params(struct rtsx_pcr *pcr);
void rtl8411b_init_params(struct rtsx_pcr *pcr);
#endif

View File

@ -25,6 +25,9 @@
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/irq.h>
#include <linux/mfd/samsung/rtc.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h>
#include <linux/regmap.h>
static struct mfd_cell s5m8751_devs[] = {
@ -105,6 +108,26 @@ static struct regmap_config sec_regmap_config = {
.val_bits = 8,
};
static struct regmap_config s2mps11_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPS11_REG_L38CTRL,
};
static struct regmap_config s5m8763_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S5M8763_REG_LBCNFG2,
};
static struct regmap_config s5m8767_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S5M8767_REG_LDO28CTRL,
};
#ifdef CONFIG_OF
/*
@ -160,6 +183,7 @@ static int sec_pmic_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct sec_platform_data *pdata = i2c->dev.platform_data;
const struct regmap_config *regmap;
struct sec_pmic_dev *sec_pmic;
int ret;
@ -190,7 +214,22 @@ static int sec_pmic_probe(struct i2c_client *i2c,
sec_pmic->pdata = pdata;
}
sec_pmic->regmap = devm_regmap_init_i2c(i2c, &sec_regmap_config);
switch (sec_pmic->device_type) {
case S2MPS11X:
regmap = &s2mps11_regmap_config;
break;
case S5M8763X:
regmap = &s5m8763_regmap_config;
break;
case S5M8767X:
regmap = &s5m8767_regmap_config;
break;
default:
regmap = &sec_regmap_config;
break;
}
sec_pmic->regmap = devm_regmap_init_i2c(i2c, regmap);
if (IS_ERR(sec_pmic->regmap)) {
ret = PTR_ERR(sec_pmic->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@ -230,13 +269,12 @@ static int sec_pmic_probe(struct i2c_client *i2c,
BUG();
}
if (ret < 0)
if (ret)
goto err;
return ret;
err:
mfd_remove_devices(sec_pmic->dev);
sec_irq_exit(sec_pmic);
i2c_unregister_device(sec_pmic->rtc);
return ret;

View File

@ -422,7 +422,6 @@ static int t7l66xb_remove(struct platform_device *dev)
iounmap(t7l66xb->scr);
release_resource(&t7l66xb->rscr);
mfd_remove_devices(&dev->dev);
platform_set_drvdata(dev, NULL);
kfree(t7l66xb);
return ret;

View File

@ -217,7 +217,6 @@ static int tc6387xb_remove(struct platform_device *dev)
release_resource(&tc6387xb->rscr);
clk_disable(tc6387xb->clk32k);
clk_put(tc6387xb->clk32k);
platform_set_drvdata(dev, NULL);
kfree(tc6387xb);
return 0;

View File

@ -756,7 +756,6 @@ static int tc6393xb_remove(struct platform_device *dev)
clk_disable(tc6393xb->clk);
iounmap(tc6393xb->scr);
release_resource(&tc6393xb->rscr);
platform_set_drvdata(dev, NULL);
clk_put(tc6393xb->clk);
kfree(tc6393xb);

View File

@ -22,10 +22,10 @@
#include <linux/regmap.h>
#include <linux/mfd/core.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/mfd/ti_am335x_tscadc.h>
#include <linux/input/ti_am335x_tsc.h>
#include <linux/platform_data/ti_am335x_adc.h>
static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg)
{
@ -48,6 +48,32 @@ static const struct regmap_config tscadc_regmap_config = {
.val_bits = 32,
};
void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc)
{
tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
}
EXPORT_SYMBOL_GPL(am335x_tsc_se_update);
void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val)
{
spin_lock(&tsadc->reg_lock);
tsadc->reg_se_cache |= val;
spin_unlock(&tsadc->reg_lock);
am335x_tsc_se_update(tsadc);
}
EXPORT_SYMBOL_GPL(am335x_tsc_se_set);
void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val)
{
spin_lock(&tsadc->reg_lock);
tsadc->reg_se_cache &= ~val;
spin_unlock(&tsadc->reg_lock);
am335x_tsc_se_update(tsadc);
}
EXPORT_SYMBOL_GPL(am335x_tsc_se_clr);
static void tscadc_idle_config(struct ti_tscadc_dev *config)
{
unsigned int idleconfig;
@ -63,27 +89,48 @@ static int ti_tscadc_probe(struct platform_device *pdev)
struct ti_tscadc_dev *tscadc;
struct resource *res;
struct clk *clk;
struct mfd_tscadc_board *pdata = pdev->dev.platform_data;
struct device_node *node = pdev->dev.of_node;
struct mfd_cell *cell;
struct property *prop;
const __be32 *cur;
u32 val;
int err, ctrl;
int clk_value, clock_rate;
int tsc_wires, adc_channels = 0, total_channels;
int tsc_wires = 0, adc_channels = 0, total_channels;
int readouts = 0;
if (!pdata) {
dev_err(&pdev->dev, "Could not find platform data\n");
if (!pdev->dev.of_node) {
dev_err(&pdev->dev, "Could not find valid DT data.\n");
return -EINVAL;
}
if (pdata->adc_init)
adc_channels = pdata->adc_init->adc_channels;
node = of_get_child_by_name(pdev->dev.of_node, "tsc");
of_property_read_u32(node, "ti,wires", &tsc_wires);
of_property_read_u32(node, "ti,coordiante-readouts", &readouts);
tsc_wires = pdata->tsc_init->wires;
node = of_get_child_by_name(pdev->dev.of_node, "adc");
of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
adc_channels++;
if (val > 7) {
dev_err(&pdev->dev, " PIN numbers are 0..7 (not %d)\n",
val);
return -EINVAL;
}
}
total_channels = tsc_wires + adc_channels;
if (total_channels > 8) {
dev_err(&pdev->dev, "Number of i/p channels more than 8\n");
return -EINVAL;
}
if (total_channels == 0) {
dev_err(&pdev->dev, "Need atleast one channel.\n");
return -EINVAL;
}
if (readouts * 2 + 2 + adc_channels > 16) {
dev_err(&pdev->dev, "Too many step configurations requested\n");
return -EINVAL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@ -129,6 +176,7 @@ static int ti_tscadc_probe(struct platform_device *pdev)
goto ret;
}
spin_lock_init(&tscadc->reg_lock);
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
@ -173,26 +221,37 @@ static int ti_tscadc_probe(struct platform_device *pdev)
ctrl |= CNTRLREG_TSCSSENB;
tscadc_writel(tscadc, REG_CTRL, ctrl);
tscadc->used_cells = 0;
tscadc->tsc_cell = -1;
tscadc->adc_cell = -1;
/* TSC Cell */
cell = &tscadc->cells[TSC_CELL];
cell->name = "tsc";
cell->platform_data = tscadc;
cell->pdata_size = sizeof(*tscadc);
if (tsc_wires > 0) {
tscadc->tsc_cell = tscadc->used_cells;
cell = &tscadc->cells[tscadc->used_cells++];
cell->name = "TI-am335x-tsc";
cell->of_compatible = "ti,am3359-tsc";
cell->platform_data = &tscadc;
cell->pdata_size = sizeof(tscadc);
}
/* ADC Cell */
cell = &tscadc->cells[ADC_CELL];
cell->name = "tiadc";
cell->platform_data = tscadc;
cell->pdata_size = sizeof(*tscadc);
if (adc_channels > 0) {
tscadc->adc_cell = tscadc->used_cells;
cell = &tscadc->cells[tscadc->used_cells++];
cell->name = "TI-am335x-adc";
cell->of_compatible = "ti,am3359-adc";
cell->platform_data = &tscadc;
cell->pdata_size = sizeof(tscadc);
}
err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
TSCADC_CELLS, NULL, 0, NULL);
tscadc->used_cells, NULL, 0, NULL);
if (err < 0)
goto err_disable_clk;
device_init_wakeup(&pdev->dev, true);
platform_set_drvdata(pdev, tscadc);
return 0;
err_disable_clk:
@ -239,7 +298,7 @@ static int tscadc_resume(struct device *dev)
CNTRLREG_STEPID | CNTRLREG_4WIRE;
tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
tscadc_idle_config(tscadc_dev);
tscadc_writel(tscadc_dev, REG_SE, STPENB_STEPENB);
am335x_tsc_se_update(tscadc_dev);
restore = tscadc_readl(tscadc_dev, REG_CTRL);
tscadc_writel(tscadc_dev, REG_CTRL,
(restore | CNTRLREG_TSCSSENB));
@ -256,11 +315,18 @@ static const struct dev_pm_ops tscadc_pm_ops = {
#define TSCADC_PM_OPS NULL
#endif
static const struct of_device_id ti_tscadc_dt_ids[] = {
{ .compatible = "ti,am3359-tscadc", },
{ }
};
MODULE_DEVICE_TABLE(of, ti_tscadc_dt_ids);
static struct platform_driver ti_tscadc_driver = {
.driver = {
.name = "ti_tscadc",
.name = "ti_am3359-tscadc",
.owner = THIS_MODULE,
.pm = TSCADC_PM_OPS,
.of_match_table = of_match_ptr(ti_tscadc_dt_ids),
},
.probe = ti_tscadc_probe,
.remove = ti_tscadc_remove,

View File

@ -162,7 +162,6 @@ int tps65912_device_init(struct tps65912 *tps65912)
err:
kfree(init_data);
mfd_remove_devices(tps65912->dev);
kfree(tps65912);
return ret;
}
@ -170,7 +169,6 @@ void tps65912_device_exit(struct tps65912 *tps65912)
{
mfd_remove_devices(tps65912->dev);
tps65912_irq_exit(tps65912);
kfree(tps65912);
}
MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>");

View File

@ -77,7 +77,8 @@ static int tps65912_i2c_probe(struct i2c_client *i2c,
{
struct tps65912 *tps65912;
tps65912 = kzalloc(sizeof(struct tps65912), GFP_KERNEL);
tps65912 = devm_kzalloc(&i2c->dev,
sizeof(struct tps65912), GFP_KERNEL);
if (tps65912 == NULL)
return -ENOMEM;

View File

@ -85,7 +85,8 @@ static int tps65912_spi_probe(struct spi_device *spi)
{
struct tps65912 *tps65912;
tps65912 = kzalloc(sizeof(struct tps65912), GFP_KERNEL);
tps65912 = devm_kzalloc(&spi->dev,
sizeof(struct tps65912), GFP_KERNEL);
if (tps65912 == NULL)
return -ENOMEM;

View File

@ -118,7 +118,7 @@
#define TWL6030_BASEADD_GASGAUGE 0x00C0
#define TWL6030_BASEADD_PIH 0x00D0
#define TWL6030_BASEADD_CHARGER 0x00E0
#define TWL6025_BASEADD_CHARGER 0x00DA
#define TWL6032_BASEADD_CHARGER 0x00DA
#define TWL6030_BASEADD_LED 0x00F4
/* subchip/slave 2 0x4A - DFT */
@ -718,9 +718,9 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
| REGULATOR_CHANGE_STATUS,
};
if (features & TWL6025_SUBCLASS) {
if (features & TWL6032_SUBCLASS) {
usb3v3.supply = "ldousb";
regulator = TWL6025_REG_LDOUSB;
regulator = TWL6032_REG_LDOUSB;
} else {
usb3v3.supply = "vusb";
regulator = TWL6030_REG_VUSB;
@ -747,8 +747,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
usb3v3.dev_name = dev_name(child);
} else if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) &&
twl_class_is_6030()) {
if (features & TWL6025_SUBCLASS)
child = add_regulator(TWL6025_REG_LDOUSB,
if (features & TWL6032_SUBCLASS)
child = add_regulator(TWL6032_REG_LDOUSB,
pdata->ldousb, features);
else
child = add_regulator(TWL6030_REG_VUSB,
@ -872,7 +872,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
/* twl6030 regulators */
if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
!(features & TWL6025_SUBCLASS)) {
!(features & TWL6032_SUBCLASS)) {
child = add_regulator(TWL6030_REG_VDD1, pdata->vdd1,
features);
if (IS_ERR(child))
@ -952,60 +952,60 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
return PTR_ERR(child);
}
/* twl6025 regulators */
/* twl6032 regulators */
if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
(features & TWL6025_SUBCLASS)) {
child = add_regulator(TWL6025_REG_LDO5, pdata->ldo5,
(features & TWL6032_SUBCLASS)) {
child = add_regulator(TWL6032_REG_LDO5, pdata->ldo5,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6025_REG_LDO1, pdata->ldo1,
child = add_regulator(TWL6032_REG_LDO1, pdata->ldo1,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6025_REG_LDO7, pdata->ldo7,
child = add_regulator(TWL6032_REG_LDO7, pdata->ldo7,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6025_REG_LDO6, pdata->ldo6,
child = add_regulator(TWL6032_REG_LDO6, pdata->ldo6,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6025_REG_LDOLN, pdata->ldoln,
child = add_regulator(TWL6032_REG_LDOLN, pdata->ldoln,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6025_REG_LDO2, pdata->ldo2,
child = add_regulator(TWL6032_REG_LDO2, pdata->ldo2,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6025_REG_LDO4, pdata->ldo4,
child = add_regulator(TWL6032_REG_LDO4, pdata->ldo4,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6025_REG_LDO3, pdata->ldo3,
child = add_regulator(TWL6032_REG_LDO3, pdata->ldo3,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6025_REG_SMPS3, pdata->smps3,
child = add_regulator(TWL6032_REG_SMPS3, pdata->smps3,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6025_REG_SMPS4, pdata->smps4,
child = add_regulator(TWL6032_REG_SMPS4, pdata->smps4,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6025_REG_VIO, pdata->vio6025,
child = add_regulator(TWL6032_REG_VIO, pdata->vio6025,
features);
if (IS_ERR(child))
return PTR_ERR(child);
@ -1023,6 +1023,14 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
return PTR_ERR(child);
}
if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata->power) {
child = add_child(TWL_MODULE_PM_MASTER, "twl4030_power",
pdata->power, sizeof(*pdata->power), false,
0, 0);
if (IS_ERR(child))
return PTR_ERR(child);
}
return 0;
}
@ -1176,10 +1184,10 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
if ((id->driver_data) & TWL6030_CLASS) {
twl_priv->twl_id = TWL6030_CLASS_ID;
twl_priv->twl_map = &twl6030_map[0];
/* The charger base address is different in twl6025 */
if ((id->driver_data) & TWL6025_SUBCLASS)
/* The charger base address is different in twl6032 */
if ((id->driver_data) & TWL6032_SUBCLASS)
twl_priv->twl_map[TWL_MODULE_MAIN_CHARGE].base =
TWL6025_BASEADD_CHARGER;
TWL6032_BASEADD_CHARGER;
twl_regmap_config = twl6030_regmap_config;
} else {
twl_priv->twl_id = TWL4030_CLASS_ID;
@ -1234,10 +1242,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
WARN(status < 0, "Error: reading twl_idcode register value\n");
}
/* load power event scripts */
if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata && pdata->power)
twl4030_power_init(pdata->power);
/* Maybe init the T2 Interrupt subsystem */
if (client->irq) {
if (twl_class_is_4030()) {
@ -1292,7 +1296,7 @@ static const struct i2c_device_id twl_ids[] = {
{ "tps65921", TPS_SUBSET }, /* fewer LDOs; no codec, no LED
and vibrator. Charger in USB module*/
{ "twl6030", TWL6030_CLASS }, /* "Phoenix power chip" */
{ "twl6025", TWL6030_CLASS | TWL6025_SUBCLASS }, /* "Phoenix lite" */
{ "twl6032", TWL6030_CLASS | TWL6032_SUBCLASS }, /* "Phoenix lite" */
{ /* end of list */ },
};
MODULE_DEVICE_TABLE(i2c, twl_ids);
@ -1305,17 +1309,7 @@ static struct i2c_driver twl_driver = {
.remove = twl_remove,
};
static int __init twl_init(void)
{
return i2c_add_driver(&twl_driver);
}
subsys_initcall(twl_init);
static void __exit twl_exit(void)
{
i2c_del_driver(&twl_driver);
}
module_exit(twl_exit);
module_i2c_driver(twl_driver);
MODULE_AUTHOR("Texas Instruments, Inc.");
MODULE_DESCRIPTION("I2C Core interface for TWL");

View File

@ -261,10 +261,8 @@ static int twl4030_audio_probe(struct platform_device *pdev)
ret = -ENODEV;
}
if (ret) {
platform_set_drvdata(pdev, NULL);
if (ret)
twl4030_audio_dev = NULL;
}
return ret;
}
@ -272,7 +270,6 @@ static int twl4030_audio_probe(struct platform_device *pdev)
static int twl4030_audio_remove(struct platform_device *pdev)
{
mfd_remove_devices(&pdev->dev);
platform_set_drvdata(pdev, NULL);
twl4030_audio_dev = NULL;
return 0;

View File

@ -570,6 +570,7 @@ static struct irq_chip twl4030_sih_irq_chip = {
.irq_set_type = twl4030_sih_set_type,
.irq_bus_lock = twl4030_sih_bus_lock,
.irq_bus_sync_unlock = twl4030_sih_bus_sync_unlock,
.flags = IRQCHIP_SKIP_SET_WAKE,
};
/*----------------------------------------------------------------------*/

View File

@ -775,12 +775,10 @@ static int twl4030_madc_probe(struct platform_device *pdev)
IRQF_TRIGGER_RISING, "twl4030_madc", madc);
if (ret) {
dev_dbg(&pdev->dev, "could not request irq\n");
goto err_irq;
goto err_i2c;
}
twl4030_madc = madc;
return 0;
err_irq:
platform_set_drvdata(pdev, NULL);
err_i2c:
twl4030_madc_set_current_generator(madc, 0, 0);
err_current_generator:
@ -796,7 +794,6 @@ static int twl4030_madc_remove(struct platform_device *pdev)
struct twl4030_madc_data *madc = platform_get_drvdata(pdev);
free_irq(platform_get_irq(pdev, 0), madc);
platform_set_drvdata(pdev, NULL);
twl4030_madc_set_current_generator(madc, 0, 0);
twl4030_madc_set_power(madc, 0);
kfree(madc);

View File

@ -28,6 +28,7 @@
#include <linux/pm.h>
#include <linux/i2c/twl.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <asm/mach-types.h>
@ -492,6 +493,39 @@ int twl4030_remove_script(u8 flags)
return err;
}
int twl4030_power_configure_scripts(struct twl4030_power_data *pdata)
{
int err;
int i;
u8 address = twl4030_start_script_address;
for (i = 0; i < pdata->num; i++) {
err = load_twl4030_script(pdata->scripts[i], address);
if (err)
return err;
address += pdata->scripts[i]->size;
}
return 0;
}
int twl4030_power_configure_resources(struct twl4030_power_data *pdata)
{
struct twl4030_resconfig *resconfig = pdata->resource_config;
int err;
if (resconfig) {
while (resconfig->resource) {
err = twl4030_configure_resource(resconfig);
if (err)
return err;
resconfig++;
}
}
return 0;
}
/*
* In master mode, start the power off sequence.
* After a successful execution, TWL shuts down the power to the SoC
@ -507,43 +541,58 @@ void twl4030_power_off(void)
pr_err("TWL4030 Unable to power off\n");
}
void twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
static bool twl4030_power_use_poweroff(struct twl4030_power_data *pdata,
struct device_node *node)
{
if (pdata && pdata->use_poweroff)
return true;
if (of_property_read_bool(node, "ti,use_poweroff"))
return true;
return false;
}
int twl4030_power_probe(struct platform_device *pdev)
{
struct twl4030_power_data *pdata = pdev->dev.platform_data;
struct device_node *node = pdev->dev.of_node;
int err = 0;
int i;
struct twl4030_resconfig *resconfig;
u8 val, address = twl4030_start_script_address;
int err2 = 0;
u8 val;
if (!pdata && !node) {
dev_err(&pdev->dev, "Platform data is missing\n");
return -EINVAL;
}
err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
TWL4030_PM_MASTER_PROTECT_KEY);
if (err)
goto unlock;
err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
err |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER,
TWL4030_PM_MASTER_KEY_CFG2,
TWL4030_PM_MASTER_PROTECT_KEY);
if (err)
goto unlock;
for (i = 0; i < twl4030_scripts->num; i++) {
err = load_twl4030_script(twl4030_scripts->scripts[i], address);
if (err)
goto load;
address += twl4030_scripts->scripts[i]->size;
if (err) {
pr_err("TWL4030 Unable to unlock registers\n");
return err;
}
resconfig = twl4030_scripts->resource_config;
if (resconfig) {
while (resconfig->resource) {
err = twl4030_configure_resource(resconfig);
if (err)
goto resource;
resconfig++;
if (pdata) {
/* TODO: convert to device tree */
err = twl4030_power_configure_scripts(pdata);
if (err) {
pr_err("TWL4030 failed to load scripts\n");
goto relock;
}
err = twl4030_power_configure_resources(pdata);
if (err) {
pr_err("TWL4030 failed to configure resource\n");
goto relock;
}
}
/* Board has to be wired properly to use this feature */
if (twl4030_scripts->use_poweroff && !pm_power_off) {
if (twl4030_power_use_poweroff(pdata, node) && !pm_power_off) {
/* Default for SEQ_OFFSYNC is set, lets ensure this */
err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val,
TWL4030_PM_MASTER_CFG_P123_TRANSITION);
@ -564,22 +613,43 @@ void twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
}
relock:
err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
err2 = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
TWL4030_PM_MASTER_PROTECT_KEY);
if (err)
if (err2) {
pr_err("TWL4030 Unable to relock registers\n");
return;
return err2;
}
unlock:
if (err)
pr_err("TWL4030 Unable to unlock registers\n");
return;
load:
if (err)
pr_err("TWL4030 failed to load scripts\n");
return;
resource:
if (err)
pr_err("TWL4030 failed to configure resource\n");
return;
return err;
}
static int twl4030_power_remove(struct platform_device *pdev)
{
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id twl4030_power_of_match[] = {
{.compatible = "ti,twl4030-power", },
{ },
};
MODULE_DEVICE_TABLE(of, twl4030_power_of_match);
#endif
static struct platform_driver twl4030_power_driver = {
.driver = {
.name = "twl4030_power",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(twl4030_power_of_match),
},
.probe = twl4030_power_probe,
.remove = twl4030_power_remove,
};
module_platform_driver(twl4030_power_driver);
MODULE_AUTHOR("Nokia Corporation");
MODULE_AUTHOR("Texas Instruments, Inc.");
MODULE_DESCRIPTION("Power management for TWL4030");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:twl4030_power");

View File

@ -351,6 +351,8 @@ void __init vexpress_sysreg_of_early_init(void)
}
#ifdef CONFIG_GPIOLIB
#define VEXPRESS_SYSREG_GPIO(_name, _reg, _value) \
[VEXPRESS_GPIO_##_name] = { \
.reg = _reg, \
@ -445,6 +447,8 @@ struct gpio_led_platform_data vexpress_sysreg_leds_pdata = {
.leds = vexpress_sysreg_leds,
};
#endif
static ssize_t vexpress_sysreg_sys_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
@ -480,6 +484,9 @@ static int vexpress_sysreg_probe(struct platform_device *pdev)
setup_timer(&vexpress_sysreg_config_timer,
vexpress_sysreg_config_complete, 0);
vexpress_sysreg_dev = &pdev->dev;
#ifdef CONFIG_GPIOLIB
vexpress_sysreg_gpio_chip.dev = &pdev->dev;
err = gpiochip_add(&vexpress_sysreg_gpio_chip);
if (err) {
@ -490,11 +497,10 @@ static int vexpress_sysreg_probe(struct platform_device *pdev)
return err;
}
vexpress_sysreg_dev = &pdev->dev;
platform_device_register_data(vexpress_sysreg_dev, "leds-gpio",
PLATFORM_DEVID_AUTO, &vexpress_sysreg_leds_pdata,
sizeof(vexpress_sysreg_leds_pdata));
#endif
device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id);

View File

@ -259,20 +259,6 @@ static int wm8994_suspend(struct device *dev)
break;
}
switch (wm8994->type) {
case WM1811:
ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2);
if (ret < 0) {
dev_err(dev, "Failed to read jackdet: %d\n", ret);
} else if (ret & WM1811_JACKDET_MODE_MASK) {
dev_dbg(dev, "CODEC still active, ignoring suspend\n");
return 0;
}
break;
default:
break;
}
/* Disable LDO pulldowns while the device is suspended if we
* don't know that something will be driving them. */
if (!wm8994->ldo_ena_always_driven)
@ -652,6 +638,17 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
return ret;
}
/* Explicitly put the device into reset in case regulators
* don't get disabled in order to ensure we know the device
* state.
*/
ret = wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET,
wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET));
if (ret != 0) {
dev_err(wm8994->dev, "Failed to reset device: %d\n", ret);
return ret;
}
if (regmap_patch) {
ret = regmap_register_patch(wm8994->regmap, regmap_patch,
patch_regs);

View File

@ -14,10 +14,12 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/mfd/core.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/regmap.h>
#include <linux/mfd/wm8994/core.h>
@ -138,6 +140,55 @@ static struct regmap_irq_chip wm8994_irq_chip = {
.runtime_pm = true,
};
static void wm8994_edge_irq_enable(struct irq_data *data)
{
}
static void wm8994_edge_irq_disable(struct irq_data *data)
{
}
static struct irq_chip wm8994_edge_irq_chip = {
.name = "wm8994_edge",
.irq_disable = wm8994_edge_irq_disable,
.irq_enable = wm8994_edge_irq_enable,
};
static irqreturn_t wm8994_edge_irq(int irq, void *data)
{
struct wm8994 *wm8994 = data;
while (gpio_get_value_cansleep(wm8994->pdata.irq_gpio))
handle_nested_irq(irq_create_mapping(wm8994->edge_irq, 0));
return IRQ_HANDLED;
}
static int wm8994_edge_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
struct wm8994 *wm8994 = h->host_data;
irq_set_chip_data(virq, wm8994);
irq_set_chip_and_handler(virq, &wm8994_edge_irq_chip, handle_edge_irq);
irq_set_nested_thread(virq, 1);
/* ARM needs us to explicitly flag the IRQ as valid
* and will set them noprobe when we do so. */
#ifdef CONFIG_ARM
set_irq_flags(virq, IRQF_VALID);
#else
irq_set_noprobe(virq);
#endif
return 0;
}
static struct irq_domain_ops wm8994_edge_irq_ops = {
.map = wm8994_edge_irq_map,
.xlate = irq_domain_xlate_twocell,
};
int wm8994_irq_init(struct wm8994 *wm8994)
{
int ret;
@ -156,10 +207,51 @@ int wm8994_irq_init(struct wm8994 *wm8994)
if (pdata->irq_flags)
irqflags = pdata->irq_flags;
ret = regmap_add_irq_chip(wm8994->regmap, wm8994->irq,
irqflags,
wm8994->irq_base, &wm8994_irq_chip,
&wm8994->irq_data);
/* use a GPIO for edge triggered controllers */
if (irqflags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
if (gpio_to_irq(pdata->irq_gpio) != wm8994->irq) {
dev_warn(wm8994->dev, "IRQ %d is not GPIO %d (%d)\n",
wm8994->irq, pdata->irq_gpio,
gpio_to_irq(pdata->irq_gpio));
wm8994->irq = gpio_to_irq(pdata->irq_gpio);
}
ret = devm_gpio_request_one(wm8994->dev, pdata->irq_gpio,
GPIOF_IN, "WM8994 IRQ");
if (ret != 0) {
dev_err(wm8994->dev, "Failed to get IRQ GPIO: %d\n",
ret);
return ret;
}
wm8994->edge_irq = irq_domain_add_linear(NULL, 1,
&wm8994_edge_irq_ops,
wm8994);
ret = regmap_add_irq_chip(wm8994->regmap,
irq_create_mapping(wm8994->edge_irq,
0),
IRQF_ONESHOT,
wm8994->irq_base, &wm8994_irq_chip,
&wm8994->irq_data);
if (ret != 0) {
dev_err(wm8994->dev, "Failed to get IRQ: %d\n",
ret);
return ret;
}
ret = request_threaded_irq(wm8994->irq,
NULL, wm8994_edge_irq,
irqflags,
"WM8994 edge", wm8994);
} else {
ret = regmap_add_irq_chip(wm8994->regmap, wm8994->irq,
irqflags,
wm8994->irq_base, &wm8994_irq_chip,
&wm8994->irq_data);
}
if (ret != 0) {
dev_err(wm8994->dev, "Failed to register IRQ chip: %d\n", ret);
return ret;

1525
drivers/mfd/wm8997-tables.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -28,8 +28,11 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#include <linux/mfd/max8998.h>
#include <linux/mfd/max8998-private.h>
@ -589,13 +592,13 @@ static struct regulator_desc regulators[] = {
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
}, {
.name = "EN32KHz AP",
.name = "EN32KHz-AP",
.id = MAX8998_EN32KHZ_AP,
.ops = &max8998_others_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
}, {
.name = "EN32KHz CP",
.name = "EN32KHz-CP",
.id = MAX8998_EN32KHZ_CP,
.ops = &max8998_others_ops,
.type = REGULATOR_VOLTAGE,
@ -621,21 +624,140 @@ static struct regulator_desc regulators[] = {
}
};
static int max8998_pmic_dt_parse_dvs_gpio(struct max8998_dev *iodev,
struct max8998_platform_data *pdata,
struct device_node *pmic_np)
{
int gpio;
gpio = of_get_named_gpio(pmic_np, "max8998,pmic-buck1-dvs-gpios", 0);
if (!gpio_is_valid(gpio)) {
dev_err(iodev->dev, "invalid buck1 gpio[0]: %d\n", gpio);
return -EINVAL;
}
pdata->buck1_set1 = gpio;
gpio = of_get_named_gpio(pmic_np, "max8998,pmic-buck1-dvs-gpios", 1);
if (!gpio_is_valid(gpio)) {
dev_err(iodev->dev, "invalid buck1 gpio[1]: %d\n", gpio);
return -EINVAL;
}
pdata->buck1_set2 = gpio;
gpio = of_get_named_gpio(pmic_np, "max8998,pmic-buck2-dvs-gpio", 0);
if (!gpio_is_valid(gpio)) {
dev_err(iodev->dev, "invalid buck 2 gpio: %d\n", gpio);
return -EINVAL;
}
pdata->buck2_set3 = gpio;
return 0;
}
static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev,
struct max8998_platform_data *pdata)
{
struct device_node *pmic_np = iodev->dev->of_node;
struct device_node *regulators_np, *reg_np;
struct max8998_regulator_data *rdata;
unsigned int i;
int ret;
regulators_np = of_get_child_by_name(pmic_np, "regulators");
if (!regulators_np) {
dev_err(iodev->dev, "could not find regulators sub-node\n");
return -EINVAL;
}
/* count the number of regulators to be supported in pmic */
pdata->num_regulators = of_get_child_count(regulators_np);
rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
pdata->num_regulators, GFP_KERNEL);
if (!rdata)
return -ENOMEM;
pdata->regulators = rdata;
for (i = 0; i < ARRAY_SIZE(regulators); ++i) {
reg_np = of_get_child_by_name(regulators_np,
regulators[i].name);
if (!reg_np)
continue;
rdata->id = regulators[i].id;
rdata->initdata = of_get_regulator_init_data(
iodev->dev, reg_np);
rdata->reg_node = reg_np;
++rdata;
}
pdata->num_regulators = rdata - pdata->regulators;
ret = max8998_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
if (ret)
return -EINVAL;
if (of_find_property(pmic_np, "max8998,pmic-buck-voltage-lock", NULL))
pdata->buck_voltage_lock = true;
ret = of_property_read_u32(pmic_np,
"max8998,pmic-buck1-default-dvs-idx",
&pdata->buck1_default_idx);
if (!ret && pdata->buck1_default_idx >= 4) {
pdata->buck1_default_idx = 0;
dev_warn(iodev->dev, "invalid value for default dvs index, using 0 instead\n");
}
ret = of_property_read_u32(pmic_np,
"max8998,pmic-buck2-default-dvs-idx",
&pdata->buck2_default_idx);
if (!ret && pdata->buck2_default_idx >= 2) {
pdata->buck2_default_idx = 0;
dev_warn(iodev->dev, "invalid value for default dvs index, using 0 instead\n");
}
ret = of_property_read_u32_array(pmic_np,
"max8998,pmic-buck1-dvs-voltage",
pdata->buck1_voltage,
ARRAY_SIZE(pdata->buck1_voltage));
if (ret) {
dev_err(iodev->dev, "buck1 voltages not specified\n");
return -EINVAL;
}
ret = of_property_read_u32_array(pmic_np,
"max8998,pmic-buck2-dvs-voltage",
pdata->buck2_voltage,
ARRAY_SIZE(pdata->buck2_voltage));
if (ret) {
dev_err(iodev->dev, "buck2 voltages not specified\n");
return -EINVAL;
}
return 0;
}
static int max8998_pmic_probe(struct platform_device *pdev)
{
struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
struct max8998_platform_data *pdata = iodev->pdata;
struct regulator_config config = { };
struct regulator_dev **rdev;
struct max8998_data *max8998;
struct i2c_client *i2c;
int i, ret, size;
unsigned int v;
if (!pdata) {
dev_err(pdev->dev.parent, "No platform init data supplied\n");
return -ENODEV;
}
if (IS_ENABLED(CONFIG_OF) && iodev->dev->of_node) {
ret = max8998_pmic_dt_parse_pdata(iodev, pdata);
if (ret)
return ret;
}
max8998 = devm_kzalloc(&pdev->dev, sizeof(struct max8998_data),
GFP_KERNEL);
if (!max8998)
@ -688,53 +810,21 @@ static int max8998_pmic_probe(struct platform_device *pdev)
gpio_request(pdata->buck1_set2, "MAX8998 BUCK1_SET2");
gpio_direction_output(pdata->buck1_set2,
(max8998->buck1_idx >> 1) & 0x1);
/* Set predefined value for BUCK1 register 1 */
i = 0;
while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i
< pdata->buck1_voltage1)
i++;
max8998->buck1_vol[0] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i);
if (ret)
goto err_out;
/* Set predefined value for BUCK1 register 2 */
i = 0;
while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i
< pdata->buck1_voltage2)
i++;
max8998->buck1_vol[1] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i);
if (ret)
goto err_out;
/* Set predefined value for BUCK1 register 3 */
i = 0;
while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i
< pdata->buck1_voltage3)
i++;
max8998->buck1_vol[2] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE3, i);
if (ret)
goto err_out;
/* Set predefined value for BUCK1 register 4 */
i = 0;
while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i
< pdata->buck1_voltage4)
i++;
max8998->buck1_vol[3] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE4, i);
if (ret)
goto err_out;
/* Set predefined values for BUCK1 registers */
for (v = 0; v < ARRAY_SIZE(pdata->buck1_voltage); ++v) {
i = 0;
while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i
< pdata->buck1_voltage[v])
i++;
max8998->buck1_vol[v] = i;
ret = max8998_write_reg(i2c,
MAX8998_REG_BUCK1_VOLTAGE1 + v, i);
if (ret)
goto err_out;
}
}
if (gpio_is_valid(pdata->buck2_set3)) {
@ -750,27 +840,20 @@ static int max8998_pmic_probe(struct platform_device *pdev)
gpio_direction_output(pdata->buck2_set3,
max8998->buck2_idx & 0x1);
/* BUCK2 register 1 */
i = 0;
while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i
< pdata->buck2_voltage1)
i++;
max8998->buck2_vol[0] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i);
if (ret)
goto err_out;
/* Set predefined values for BUCK2 registers */
for (v = 0; v < ARRAY_SIZE(pdata->buck2_voltage); ++v) {
i = 0;
while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i
< pdata->buck2_voltage[v])
i++;
/* BUCK2 register 2 */
i = 0;
while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i
< pdata->buck2_voltage2)
i++;
max8998->buck2_vol[1] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i);
if (ret)
goto err_out;
max8998->buck2_vol[v] = i;
ret = max8998_write_reg(i2c,
MAX8998_REG_BUCK2_VOLTAGE1 + v, i);
if (ret)
goto err_out;
}
}
for (i = 0; i < pdata->num_regulators; i++) {
@ -788,13 +871,15 @@ static int max8998_pmic_probe(struct platform_device *pdev)
}
config.dev = max8998->dev;
config.of_node = pdata->regulators[i].reg_node;
config.init_data = pdata->regulators[i].initdata;
config.driver_data = max8998;
rdev[i] = regulator_register(&regulators[index], &config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
dev_err(max8998->dev, "regulator init failed\n");
dev_err(max8998->dev, "regulator %s init failed (%d)\n",
regulators[index].name, ret);
rdev[i] = NULL;
goto err;
}

View File

@ -838,6 +838,9 @@ static int palmas_regulators_probe(struct platform_device *pdev)
continue;
ramp_delay_support = true;
break;
case PALMAS_REG_SMPS10:
if (!PALMAS_PMIC_HAS(palmas, SMPS10_BOOST))
continue;
}
if ((id == PALMAS_REG_SMPS6) || (id == PALMAS_REG_SMPS8))
@ -1051,6 +1054,7 @@ static struct of_device_id of_palmas_match_tbl[] = {
{ .compatible = "ti,tps65913-pmic", },
{ .compatible = "ti,tps65914-pmic", },
{ .compatible = "ti,tps80036-pmic", },
{ .compatible = "ti,tps659038-pmic", },
{ /* end */ }
};

View File

@ -109,7 +109,7 @@ struct twlreg_info {
#define SMPS_OFFSET_EN BIT(0)
#define SMPS_EXTENDED_EN BIT(1)
/* twl6025 SMPS EPROM values */
/* twl6032 SMPS EPROM values */
#define TWL6030_SMPS_OFFSET 0xB0
#define TWL6030_SMPS_MULT 0xB3
#define SMPS_MULTOFFSET_SMPS4 BIT(0)
@ -173,7 +173,7 @@ static int twl6030reg_is_enabled(struct regulator_dev *rdev)
struct twlreg_info *info = rdev_get_drvdata(rdev);
int grp = 0, val;
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) {
if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS))) {
grp = twlreg_grp(rdev);
if (grp < 0)
return grp;
@ -211,7 +211,7 @@ static int twl6030reg_enable(struct regulator_dev *rdev)
int grp = 0;
int ret;
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
grp = twlreg_grp(rdev);
if (grp < 0)
return grp;
@ -245,7 +245,7 @@ static int twl6030reg_disable(struct regulator_dev *rdev)
int grp = 0;
int ret;
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
grp = P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030;
/* For 6030, set the off state for all grps enabled */
@ -339,7 +339,7 @@ static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
int grp = 0;
int val;
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
grp = twlreg_grp(rdev);
if (grp < 0)
@ -899,14 +899,14 @@ static const struct twlreg_info TWL6030_INFO_##label = { \
}, \
}
#define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \
static const struct twlreg_info TWL6025_INFO_##label = { \
#define TWL6032_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \
static const struct twlreg_info TWL6032_INFO_##label = { \
.base = offset, \
.min_mV = min_mVolts, \
.max_mV = max_mVolts, \
.desc = { \
.name = #label, \
.id = TWL6025_REG_##label, \
.id = TWL6032_REG_##label, \
.n_voltages = 32, \
.ops = &twl6030ldo_ops, \
.type = REGULATOR_VOLTAGE, \
@ -933,14 +933,14 @@ static const struct twlreg_info TWLFIXED_INFO_##label = { \
}, \
}
#define TWL6025_ADJUSTABLE_SMPS(label, offset) \
#define TWL6032_ADJUSTABLE_SMPS(label, offset) \
static const struct twlreg_info TWLSMPS_INFO_##label = { \
.base = offset, \
.min_mV = 600, \
.max_mV = 2100, \
.desc = { \
.name = #label, \
.id = TWL6025_REG_##label, \
.id = TWL6032_REG_##label, \
.n_voltages = 63, \
.ops = &twlsmps_ops, \
.type = REGULATOR_VOLTAGE, \
@ -981,15 +981,15 @@ TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300);
TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300);
TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300);
/* 6025 are renamed compared to 6030 versions */
TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300);
TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300);
TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300);
TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300);
TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300);
TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300);
TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300);
TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300);
TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300);
TWL6032_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300);
TWL6032_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300);
TWL6032_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300);
TWL6032_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300);
TWL6032_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300);
TWL6032_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300);
TWL6032_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300);
TWL6032_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300);
TWL6032_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300);
TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08);
TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08);
TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08);
@ -1001,9 +1001,9 @@ TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0);
TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0);
TWL6030_FIXED_LDO(V1V8, 0x16, 1800, 0);
TWL6030_FIXED_LDO(V2V1, 0x1c, 2100, 0);
TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34);
TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10);
TWL6025_ADJUSTABLE_SMPS(VIO, 0x16);
TWL6032_ADJUSTABLE_SMPS(SMPS3, 0x34);
TWL6032_ADJUSTABLE_SMPS(SMPS4, 0x10);
TWL6032_ADJUSTABLE_SMPS(VIO, 0x16);
static u8 twl_get_smps_offset(void)
{
@ -1031,7 +1031,7 @@ static u8 twl_get_smps_mult(void)
#define TWL4030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL4030, label)
#define TWL6030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6030, label)
#define TWL6025_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6025, label)
#define TWL6032_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6032, label)
#define TWLFIXED_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLFIXED, label)
#define TWLSMPS_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLSMPS, label)
@ -1060,15 +1060,15 @@ static const struct of_device_id twl_of_match[] = {
TWL6030_OF_MATCH("ti,twl6030-vmmc", VMMC),
TWL6030_OF_MATCH("ti,twl6030-vpp", VPP),
TWL6030_OF_MATCH("ti,twl6030-vusim", VUSIM),
TWL6025_OF_MATCH("ti,twl6025-ldo2", LDO2),
TWL6025_OF_MATCH("ti,twl6025-ldo4", LDO4),
TWL6025_OF_MATCH("ti,twl6025-ldo3", LDO3),
TWL6025_OF_MATCH("ti,twl6025-ldo5", LDO5),
TWL6025_OF_MATCH("ti,twl6025-ldo1", LDO1),
TWL6025_OF_MATCH("ti,twl6025-ldo7", LDO7),
TWL6025_OF_MATCH("ti,twl6025-ldo6", LDO6),
TWL6025_OF_MATCH("ti,twl6025-ldoln", LDOLN),
TWL6025_OF_MATCH("ti,twl6025-ldousb", LDOUSB),
TWL6032_OF_MATCH("ti,twl6032-ldo2", LDO2),
TWL6032_OF_MATCH("ti,twl6032-ldo4", LDO4),
TWL6032_OF_MATCH("ti,twl6032-ldo3", LDO3),
TWL6032_OF_MATCH("ti,twl6032-ldo5", LDO5),
TWL6032_OF_MATCH("ti,twl6032-ldo1", LDO1),
TWL6032_OF_MATCH("ti,twl6032-ldo7", LDO7),
TWL6032_OF_MATCH("ti,twl6032-ldo6", LDO6),
TWL6032_OF_MATCH("ti,twl6032-ldoln", LDOLN),
TWL6032_OF_MATCH("ti,twl6032-ldousb", LDOUSB),
TWLFIXED_OF_MATCH("ti,twl4030-vintana1", VINTANA1),
TWLFIXED_OF_MATCH("ti,twl4030-vintdig", VINTDIG),
TWLFIXED_OF_MATCH("ti,twl4030-vusb1v5", VUSB1V5),
@ -1080,9 +1080,9 @@ static const struct of_device_id twl_of_match[] = {
TWLFIXED_OF_MATCH("ti,twl6030-vusb", VUSB),
TWLFIXED_OF_MATCH("ti,twl6030-v1v8", V1V8),
TWLFIXED_OF_MATCH("ti,twl6030-v2v1", V2V1),
TWLSMPS_OF_MATCH("ti,twl6025-smps3", SMPS3),
TWLSMPS_OF_MATCH("ti,twl6025-smps4", SMPS4),
TWLSMPS_OF_MATCH("ti,twl6025-vio", VIO),
TWLSMPS_OF_MATCH("ti,twl6032-smps3", SMPS3),
TWLSMPS_OF_MATCH("ti,twl6032-smps4", SMPS4),
TWLSMPS_OF_MATCH("ti,twl6032-vio", VIO),
{},
};
MODULE_DEVICE_TABLE(of, twl_of_match);
@ -1163,19 +1163,19 @@ static int twlreg_probe(struct platform_device *pdev)
}
switch (id) {
case TWL6025_REG_SMPS3:
case TWL6032_REG_SMPS3:
if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3)
info->flags |= SMPS_EXTENDED_EN;
if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3)
info->flags |= SMPS_OFFSET_EN;
break;
case TWL6025_REG_SMPS4:
case TWL6032_REG_SMPS4:
if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4)
info->flags |= SMPS_EXTENDED_EN;
if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4)
info->flags |= SMPS_OFFSET_EN;
break;
case TWL6025_REG_VIO:
case TWL6032_REG_VIO:
if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO)
info->flags |= SMPS_EXTENDED_EN;
if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO)

View File

@ -16,6 +16,7 @@
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/bcd.h>
#include <linux/irqdomain.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
#include <linux/mfd/max8998.h>
@ -252,7 +253,7 @@ static const struct rtc_class_ops max8998_rtc_ops = {
static int max8998_rtc_probe(struct platform_device *pdev)
{
struct max8998_dev *max8998 = dev_get_drvdata(pdev->dev.parent);
struct max8998_platform_data *pdata = dev_get_platdata(max8998->dev);
struct max8998_platform_data *pdata = max8998->pdata;
struct max8998_rtc_info *info;
int ret;
@ -264,7 +265,6 @@ static int max8998_rtc_probe(struct platform_device *pdev)
info->dev = &pdev->dev;
info->max8998 = max8998;
info->rtc = max8998->rtc;
info->irq = max8998->irq_base + MAX8998_IRQ_ALARM0;
platform_set_drvdata(pdev, info);
@ -277,6 +277,15 @@ static int max8998_rtc_probe(struct platform_device *pdev)
return ret;
}
if (!max8998->irq_domain)
goto no_irq;
info->irq = irq_create_mapping(max8998->irq_domain, MAX8998_IRQ_ALARM0);
if (!info->irq) {
dev_warn(&pdev->dev, "Failed to map alarm IRQ\n");
goto no_irq;
}
ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
max8998_rtc_alarm_irq, 0, "rtc-alarm0", info);
@ -284,6 +293,7 @@ static int max8998_rtc_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
info->irq, ret);
no_irq:
dev_info(&pdev->dev, "RTC CHIP NAME: %s\n", pdev->id_entry->name);
if (pdata && pdata->rtc_delay) {
info->lp3974_bug_workaround = true;

View File

@ -1,16 +0,0 @@
#
# SSBI bus support
#
menu "Qualcomm MSM SSBI bus support"
config SSBI
tristate "Qualcomm Single-wire Serial Bus Interface (SSBI)"
help
If you say yes to this option, support will be included for the
built-in SSBI interface on Qualcomm MSM family processors.
This is required for communicating with Qualcomm PMICs and
other devices that have the SSBI interface.
endmenu

View File

@ -1 +0,0 @@
obj-$(CONFIG_SSBI) += ssbi.o

View File

@ -347,7 +347,7 @@ static int twl6030_usb_probe(struct platform_device *pdev)
if (np) {
twl->regulator = "usb";
} else if (pdata) {
if (pdata->features & TWL6025_SUBCLASS)
if (pdata->features & TWL6032_SUBCLASS)
twl->regulator = "ldousb";
else
twl->regulator = "vusb";

View File

@ -687,6 +687,17 @@ config HP_WATCHDOG
To compile this driver as a module, choose M here: the module will be
called hpwdt.
config KEMPLD_WDT
tristate "Kontron COM Watchdog Timer"
depends on MFD_KEMPLD
select WATCHDOG_CORE
help
Support for the PLD watchdog on some Kontron ETX and COMexpress
(ETXexpress) modules
This driver can also be built as a module. If so, the module will be
called kempld_wdt.
config HPWDT_NMI_DECODING
bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer"
depends on HP_WATCHDOG

View File

@ -90,6 +90,7 @@ endif
obj-$(CONFIG_IT8712F_WDT) += it8712f_wdt.o
obj-$(CONFIG_IT87_WDT) += it87_wdt.o
obj-$(CONFIG_HP_WATCHDOG) += hpwdt.o
obj-$(CONFIG_KEMPLD_WDT) += kempld_wdt.o
obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o

View File

@ -0,0 +1,581 @@
/*
* Kontron PLD watchdog driver
*
* Copyright (c) 2010-2013 Kontron Europe GmbH
* Author: Michael Brunner <michael.brunner@kontron.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 2 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Note: From the PLD watchdog point of view timeout and pretimeout are
* defined differently than in the kernel.
* First the pretimeout stage runs out before the timeout stage gets
* active.
*
* Kernel/API: P-----| pretimeout
* |-----------------------T timeout
* Watchdog: |-----------------P pretimeout_stage
* |-----T timeout_stage
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/watchdog.h>
#include <linux/platform_device.h>
#include <linux/mfd/kempld.h>
#define KEMPLD_WDT_STAGE_TIMEOUT(x) (0x1b + (x) * 4)
#define KEMPLD_WDT_STAGE_CFG(x) (0x18 + (x))
#define STAGE_CFG_GET_PRESCALER(x) (((x) & 0x30) >> 4)
#define STAGE_CFG_SET_PRESCALER(x) (((x) & 0x30) << 4)
#define STAGE_CFG_PRESCALER_MASK 0x30
#define STAGE_CFG_ACTION_MASK 0x7
#define STAGE_CFG_ASSERT (1 << 3)
#define KEMPLD_WDT_MAX_STAGES 2
#define KEMPLD_WDT_KICK 0x16
#define KEMPLD_WDT_CFG 0x17
#define KEMPLD_WDT_CFG_ENABLE 0x10
#define KEMPLD_WDT_CFG_ENABLE_LOCK 0x8
#define KEMPLD_WDT_CFG_GLOBAL_LOCK 0x80
enum {
ACTION_NONE = 0,
ACTION_RESET,
ACTION_NMI,
ACTION_SMI,
ACTION_SCI,
ACTION_DELAY,
};
enum {
STAGE_TIMEOUT = 0,
STAGE_PRETIMEOUT,
};
enum {
PRESCALER_21 = 0,
PRESCALER_17,
PRESCALER_12,
};
const u32 kempld_prescaler[] = {
[PRESCALER_21] = (1 << 21) - 1,
[PRESCALER_17] = (1 << 17) - 1,
[PRESCALER_12] = (1 << 12) - 1,
0,
};
struct kempld_wdt_stage {
unsigned int id;
u32 mask;
};
struct kempld_wdt_data {
struct kempld_device_data *pld;
struct watchdog_device wdd;
unsigned int pretimeout;
struct kempld_wdt_stage stage[KEMPLD_WDT_MAX_STAGES];
#ifdef CONFIG_PM
u8 pm_status_store;
#endif
};
#define DEFAULT_TIMEOUT 30 /* seconds */
#define DEFAULT_PRETIMEOUT 0
static unsigned int timeout = DEFAULT_TIMEOUT;
module_param(timeout, uint, 0);
MODULE_PARM_DESC(timeout,
"Watchdog timeout in seconds. (>=0, default="
__MODULE_STRING(DEFAULT_TIMEOUT) ")");
static unsigned int pretimeout = DEFAULT_PRETIMEOUT;
module_param(pretimeout, uint, 0);
MODULE_PARM_DESC(pretimeout,
"Watchdog pretimeout in seconds. (>=0, default="
__MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
static int kempld_wdt_set_stage_action(struct kempld_wdt_data *wdt_data,
struct kempld_wdt_stage *stage,
u8 action)
{
struct kempld_device_data *pld = wdt_data->pld;
u8 stage_cfg;
if (!stage || !stage->mask)
return -EINVAL;
kempld_get_mutex(pld);
stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id));
stage_cfg &= ~STAGE_CFG_ACTION_MASK;
stage_cfg |= (action & STAGE_CFG_ACTION_MASK);
if (action == ACTION_RESET)
stage_cfg |= STAGE_CFG_ASSERT;
else
stage_cfg &= ~STAGE_CFG_ASSERT;
kempld_write8(pld, KEMPLD_WDT_STAGE_CFG(stage->id), stage_cfg);
kempld_release_mutex(pld);
return 0;
}
static int kempld_wdt_set_stage_timeout(struct kempld_wdt_data *wdt_data,
struct kempld_wdt_stage *stage,
unsigned int timeout)
{
struct kempld_device_data *pld = wdt_data->pld;
u32 prescaler = kempld_prescaler[PRESCALER_21];
u64 stage_timeout64;
u32 stage_timeout;
u32 remainder;
u8 stage_cfg;
if (!stage)
return -EINVAL;
stage_timeout64 = (u64)timeout * pld->pld_clock;
remainder = do_div(stage_timeout64, prescaler);
if (remainder)
stage_timeout64++;
if (stage_timeout64 > stage->mask)
return -EINVAL;
stage_timeout = stage_timeout64 & stage->mask;
kempld_get_mutex(pld);
stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id));
stage_cfg &= ~STAGE_CFG_PRESCALER_MASK;
stage_cfg |= STAGE_CFG_SET_PRESCALER(prescaler);
kempld_write8(pld, KEMPLD_WDT_STAGE_CFG(stage->id), stage_cfg);
kempld_write32(pld, KEMPLD_WDT_STAGE_TIMEOUT(stage->id),
stage_timeout);
kempld_release_mutex(pld);
return 0;
}
/*
* kempld_get_mutex must be called prior to calling this function.
*/
static unsigned int kempld_wdt_get_timeout(struct kempld_wdt_data *wdt_data,
struct kempld_wdt_stage *stage)
{
struct kempld_device_data *pld = wdt_data->pld;
unsigned int timeout;
u64 stage_timeout;
u32 prescaler;
u32 remainder;
u8 stage_cfg;
if (!stage->mask)
return 0;
stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id));
stage_timeout = kempld_read32(pld, KEMPLD_WDT_STAGE_TIMEOUT(stage->id));
prescaler = kempld_prescaler[STAGE_CFG_GET_PRESCALER(stage_cfg)];
stage_timeout = (stage_timeout & stage->mask) * prescaler;
remainder = do_div(stage_timeout, pld->pld_clock);
if (remainder)
stage_timeout++;
timeout = stage_timeout;
WARN_ON_ONCE(timeout != stage_timeout);
return timeout;
}
static int kempld_wdt_set_timeout(struct watchdog_device *wdd,
unsigned int timeout)
{
struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
struct kempld_wdt_stage *pretimeout_stage;
struct kempld_wdt_stage *timeout_stage;
int ret;
timeout_stage = &wdt_data->stage[STAGE_TIMEOUT];
pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT];
if (pretimeout_stage->mask && wdt_data->pretimeout > 0)
timeout = wdt_data->pretimeout;
ret = kempld_wdt_set_stage_action(wdt_data, timeout_stage,
ACTION_RESET);
if (ret)
return ret;
ret = kempld_wdt_set_stage_timeout(wdt_data, timeout_stage,
timeout);
if (ret)
return ret;
wdd->timeout = timeout;
return 0;
}
static int kempld_wdt_set_pretimeout(struct watchdog_device *wdd,
unsigned int pretimeout)
{
struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
struct kempld_wdt_stage *pretimeout_stage;
u8 action = ACTION_NONE;
int ret;
pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT];
if (!pretimeout_stage->mask)
return -ENXIO;
if (pretimeout > wdd->timeout)
return -EINVAL;
if (pretimeout > 0)
action = ACTION_NMI;
ret = kempld_wdt_set_stage_action(wdt_data, pretimeout_stage,
action);
if (ret)
return ret;
ret = kempld_wdt_set_stage_timeout(wdt_data, pretimeout_stage,
wdd->timeout - pretimeout);
if (ret)
return ret;
wdt_data->pretimeout = pretimeout;
return 0;
}
static void kempld_wdt_update_timeouts(struct kempld_wdt_data *wdt_data)
{
struct kempld_device_data *pld = wdt_data->pld;
struct kempld_wdt_stage *pretimeout_stage;
struct kempld_wdt_stage *timeout_stage;
unsigned int pretimeout, timeout;
pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT];
timeout_stage = &wdt_data->stage[STAGE_TIMEOUT];
kempld_get_mutex(pld);
pretimeout = kempld_wdt_get_timeout(wdt_data, pretimeout_stage);
timeout = kempld_wdt_get_timeout(wdt_data, timeout_stage);
kempld_release_mutex(pld);
if (pretimeout)
wdt_data->pretimeout = timeout;
else
wdt_data->pretimeout = 0;
wdt_data->wdd.timeout = pretimeout + timeout;
}
static int kempld_wdt_start(struct watchdog_device *wdd)
{
struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
struct kempld_device_data *pld = wdt_data->pld;
u8 status;
int ret;
ret = kempld_wdt_set_timeout(wdd, wdd->timeout);
if (ret)
return ret;
kempld_get_mutex(pld);
status = kempld_read8(pld, KEMPLD_WDT_CFG);
status |= KEMPLD_WDT_CFG_ENABLE;
kempld_write8(pld, KEMPLD_WDT_CFG, status);
status = kempld_read8(pld, KEMPLD_WDT_CFG);
kempld_release_mutex(pld);
/* Check if the watchdog was enabled */
if (!(status & KEMPLD_WDT_CFG_ENABLE))
return -EACCES;
return 0;
}
static int kempld_wdt_stop(struct watchdog_device *wdd)
{
struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
struct kempld_device_data *pld = wdt_data->pld;
u8 status;
kempld_get_mutex(pld);
status = kempld_read8(pld, KEMPLD_WDT_CFG);
status &= ~KEMPLD_WDT_CFG_ENABLE;
kempld_write8(pld, KEMPLD_WDT_CFG, status);
status = kempld_read8(pld, KEMPLD_WDT_CFG);
kempld_release_mutex(pld);
/* Check if the watchdog was disabled */
if (status & KEMPLD_WDT_CFG_ENABLE)
return -EACCES;
return 0;
}
static int kempld_wdt_keepalive(struct watchdog_device *wdd)
{
struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
struct kempld_device_data *pld = wdt_data->pld;
kempld_get_mutex(pld);
kempld_write8(pld, KEMPLD_WDT_KICK, 'K');
kempld_release_mutex(pld);
return 0;
}
static long kempld_wdt_ioctl(struct watchdog_device *wdd, unsigned int cmd,
unsigned long arg)
{
struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
void __user *argp = (void __user *)arg;
int ret = -ENOIOCTLCMD;
int __user *p = argp;
int new_value;
switch (cmd) {
case WDIOC_SETPRETIMEOUT:
if (get_user(new_value, p))
return -EFAULT;
ret = kempld_wdt_set_pretimeout(wdd, new_value);
if (ret)
return ret;
ret = kempld_wdt_keepalive(wdd);
break;
case WDIOC_GETPRETIMEOUT:
ret = put_user(wdt_data->pretimeout, (int *)arg);
break;
}
return ret;
}
static int kempld_wdt_probe_stages(struct watchdog_device *wdd)
{
struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
struct kempld_device_data *pld = wdt_data->pld;
struct kempld_wdt_stage *pretimeout_stage;
struct kempld_wdt_stage *timeout_stage;
u8 index, data, data_orig;
u32 mask;
int i, j;
pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT];
timeout_stage = &wdt_data->stage[STAGE_TIMEOUT];
pretimeout_stage->mask = 0;
timeout_stage->mask = 0;
for (i = 0; i < 3; i++) {
index = KEMPLD_WDT_STAGE_TIMEOUT(i);
mask = 0;
kempld_get_mutex(pld);
/* Probe each byte individually. */
for (j = 0; j < 4; j++) {
data_orig = kempld_read8(pld, index + j);
kempld_write8(pld, index + j, 0x00);
data = kempld_read8(pld, index + j);
/* A failed write means this byte is reserved */
if (data != 0x00)
break;
kempld_write8(pld, index + j, data_orig);
mask |= 0xff << (j * 8);
}
kempld_release_mutex(pld);
/* Assign available stages to timeout and pretimeout */
if (!timeout_stage->mask) {
timeout_stage->mask = mask;
timeout_stage->id = i;
} else {
if (pld->feature_mask & KEMPLD_FEATURE_BIT_NMI) {
pretimeout_stage->mask = timeout_stage->mask;
timeout_stage->mask = mask;
pretimeout_stage->id = timeout_stage->id;
timeout_stage->id = i;
}
break;
}
}
if (!timeout_stage->mask)
return -ENODEV;
return 0;
}
static struct watchdog_info kempld_wdt_info = {
.identity = "KEMPLD Watchdog",
.options = WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING |
WDIOF_MAGICCLOSE |
WDIOF_PRETIMEOUT
};
static struct watchdog_ops kempld_wdt_ops = {
.owner = THIS_MODULE,
.start = kempld_wdt_start,
.stop = kempld_wdt_stop,
.ping = kempld_wdt_keepalive,
.set_timeout = kempld_wdt_set_timeout,
.ioctl = kempld_wdt_ioctl,
};
static int kempld_wdt_probe(struct platform_device *pdev)
{
struct kempld_device_data *pld = dev_get_drvdata(pdev->dev.parent);
struct kempld_wdt_data *wdt_data;
struct device *dev = &pdev->dev;
struct watchdog_device *wdd;
u8 status;
int ret = 0;
wdt_data = devm_kzalloc(dev, sizeof(*wdt_data), GFP_KERNEL);
if (!wdt_data)
return -ENOMEM;
wdt_data->pld = pld;
wdd = &wdt_data->wdd;
wdd->parent = dev;
kempld_get_mutex(pld);
status = kempld_read8(pld, KEMPLD_WDT_CFG);
kempld_release_mutex(pld);
/* Enable nowayout if watchdog is already locked */
if (status & (KEMPLD_WDT_CFG_ENABLE_LOCK |
KEMPLD_WDT_CFG_GLOBAL_LOCK)) {
if (!nowayout)
dev_warn(dev,
"Forcing nowayout - watchdog lock enabled!\n");
nowayout = true;
}
wdd->info = &kempld_wdt_info;
wdd->ops = &kempld_wdt_ops;
watchdog_set_drvdata(wdd, wdt_data);
watchdog_set_nowayout(wdd, nowayout);
ret = kempld_wdt_probe_stages(wdd);
if (ret)
return ret;
kempld_wdt_set_timeout(wdd, timeout);
kempld_wdt_set_pretimeout(wdd, pretimeout);
/* Check if watchdog is already enabled */
if (status & KEMPLD_WDT_CFG_ENABLE) {
/* Get current watchdog settings */
kempld_wdt_update_timeouts(wdt_data);
dev_info(dev, "Watchdog was already enabled\n");
}
platform_set_drvdata(pdev, wdt_data);
ret = watchdog_register_device(wdd);
if (ret)
return ret;
dev_info(dev, "Watchdog registered with %ds timeout\n", wdd->timeout);
return 0;
}
static void kempld_wdt_shutdown(struct platform_device *pdev)
{
struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev);
kempld_wdt_stop(&wdt_data->wdd);
}
static int kempld_wdt_remove(struct platform_device *pdev)
{
struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev);
struct watchdog_device *wdd = &wdt_data->wdd;
int ret = 0;
if (!nowayout)
ret = kempld_wdt_stop(wdd);
watchdog_unregister_device(wdd);
return ret;
}
#ifdef CONFIG_PM
/* Disable watchdog if it is active during suspend */
static int kempld_wdt_suspend(struct platform_device *pdev,
pm_message_t message)
{
struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev);
struct kempld_device_data *pld = wdt_data->pld;
struct watchdog_device *wdd = &wdt_data->wdd;
kempld_get_mutex(pld);
wdt_data->pm_status_store = kempld_read8(pld, KEMPLD_WDT_CFG);
kempld_release_mutex(pld);
kempld_wdt_update_timeouts(wdt_data);
if (wdt_data->pm_status_store & KEMPLD_WDT_CFG_ENABLE)
return kempld_wdt_stop(wdd);
return 0;
}
/* Enable watchdog and configure it if necessary */
static int kempld_wdt_resume(struct platform_device *pdev)
{
struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev);
struct watchdog_device *wdd = &wdt_data->wdd;
/*
* If watchdog was stopped before suspend be sure it gets disabled
* again, for the case BIOS has enabled it during resume
*/
if (wdt_data->pm_status_store & KEMPLD_WDT_CFG_ENABLE)
return kempld_wdt_start(wdd);
else
return kempld_wdt_stop(wdd);
}
#else
#define kempld_wdt_suspend NULL
#define kempld_wdt_resume NULL
#endif
static struct platform_driver kempld_wdt_driver = {
.driver = {
.name = "kempld-wdt",
.owner = THIS_MODULE,
},
.probe = kempld_wdt_probe,
.remove = kempld_wdt_remove,
.shutdown = kempld_wdt_shutdown,
.suspend = kempld_wdt_suspend,
.resume = kempld_wdt_resume,
};
module_platform_driver(kempld_wdt_driver);
MODULE_DESCRIPTION("KEM PLD Watchdog Driver");
MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);

View File

@ -658,7 +658,6 @@ struct twl4030_power_data {
bool use_poweroff; /* Board is wired for TWL poweroff */
};
extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
extern int twl4030_remove_script(u8 flags);
extern void twl4030_power_off(void);
@ -726,7 +725,7 @@ struct twl4030_platform_data {
struct regulator_init_data *clk32kg;
struct regulator_init_data *v1v8;
struct regulator_init_data *v2v1;
/* TWL6025 LDO regulators */
/* TWL6032 LDO regulators */
struct regulator_init_data *ldo1;
struct regulator_init_data *ldo2;
struct regulator_init_data *ldo3;
@ -736,7 +735,7 @@ struct twl4030_platform_data {
struct regulator_init_data *ldo7;
struct regulator_init_data *ldoln;
struct regulator_init_data *ldousb;
/* TWL6025 DCDC regulators */
/* TWL6032 DCDC regulators */
struct regulator_init_data *smps3;
struct regulator_init_data *smps4;
struct regulator_init_data *vio6025;
@ -753,7 +752,7 @@ struct twl_regulator_driver_data {
#define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */
#define TWL5031 BIT(2) /* twl5031 has different registers */
#define TWL6030_CLASS BIT(3) /* TWL6030 class */
#define TWL6025_SUBCLASS BIT(4) /* TWL6025 has changed registers */
#define TWL6032_SUBCLASS BIT(4) /* TWL6032 has changed registers */
#define TWL4030_ALLOW_UNSUPPORTED BIT(5) /* Some voltages are possible
* but not officially supported.
* This flag is necessary to
@ -840,20 +839,20 @@ static inline int twl4030charger_usb_en(int enable) { return 0; }
#define TWL6030_REG_CLK32KG 48
/* LDOs on 6025 have different names */
#define TWL6025_REG_LDO2 49
#define TWL6025_REG_LDO4 50
#define TWL6025_REG_LDO3 51
#define TWL6025_REG_LDO5 52
#define TWL6025_REG_LDO1 53
#define TWL6025_REG_LDO7 54
#define TWL6025_REG_LDO6 55
#define TWL6025_REG_LDOLN 56
#define TWL6025_REG_LDOUSB 57
#define TWL6032_REG_LDO2 49
#define TWL6032_REG_LDO4 50
#define TWL6032_REG_LDO3 51
#define TWL6032_REG_LDO5 52
#define TWL6032_REG_LDO1 53
#define TWL6032_REG_LDO7 54
#define TWL6032_REG_LDO6 55
#define TWL6032_REG_LDOLN 56
#define TWL6032_REG_LDOUSB 57
/* 6025 DCDC supplies */
#define TWL6025_REG_SMPS3 58
#define TWL6025_REG_SMPS4 59
#define TWL6025_REG_VIO 60
#define TWL6032_REG_SMPS3 58
#define TWL6032_REG_SMPS4 59
#define TWL6032_REG_VIO 60
#endif /* End of __TWL4030_H */

View File

@ -1,23 +0,0 @@
#ifndef __LINUX_TI_AM335X_TSC_H
#define __LINUX_TI_AM335X_TSC_H
/**
* struct tsc_data Touchscreen wire configuration
* @wires: Wires refer to application modes
* i.e. 4/5/8 wire touchscreen support
* on the platform.
* @x_plate_resistance: X plate resistance.
* @steps_to_configure: The sequencer supports a total of
* 16 programmable steps.
* A step configured to read a single
* co-ordinate value, can be applied
* more number of times for better results.
*/
struct tsc_data {
int wires;
int x_plate_resistance;
int steps_to_configure;
};
#endif

View File

@ -17,7 +17,6 @@
#include <linux/regmap.h>
#include <linux/atomic.h>
#define PM80X_VERSION_MASK (0xFF) /* 80X chip ID mask */
enum {
CHIP_INVALID = 0,
CHIP_PM800,
@ -299,8 +298,7 @@ struct pm80x_chip {
struct regmap *regmap;
struct regmap_irq_chip *regmap_irq_chip;
struct regmap_irq_chip_data *irq_data;
unsigned char version;
int id;
int type;
int irq;
int irq_mode;
unsigned long wu_flag;
@ -309,8 +307,14 @@ struct pm80x_chip {
struct pm80x_platform_data {
struct pm80x_rtc_pdata *rtc;
unsigned short power_page_addr; /* power page I2C address */
unsigned short gpadc_page_addr; /* gpadc page I2C address */
/*
* For the regulator not defined, set regulators[not_defined] to be
* NULL. num_regulators are the number of regulators supposed to be
* initialized. If all regulators are not defined, set num_regulators
* to be 0.
*/
struct regulator_init_data *regulators[PM800_ID_RG_MAX];
unsigned int num_regulators;
int irq_mode; /* Clear interrupt by read/write(0/1) */
int batt_det; /* enable/disable */
int (*plat_config)(struct pm80x_chip *chip,
@ -363,7 +367,6 @@ static inline int pm80x_dev_resume(struct device *dev)
}
#endif
extern int pm80x_init(struct i2c_client *client,
const struct i2c_device_id *id);
extern int pm80x_init(struct i2c_client *client);
extern int pm80x_deinit(void);
#endif /* __LINUX_MFD_88PM80X_H */

View File

@ -291,6 +291,8 @@ enum ab8500_version {
#define AB8540_INT_FSYNC2R 213
#define AB8540_INT_BITCLK2F 214
#define AB8540_INT_BITCLK2R 215
/* ab8540_irq_regoffset[27] -> IT[Source|Latch|Mask]33 */
#define AB8540_INT_RTC_1S 216
/*
* AB8500_AB9540_NR_IRQS is used when configuring the IRQ numbers for the

View File

@ -23,6 +23,7 @@
enum arizona_type {
WM5102 = 1,
WM5110 = 2,
WM8997 = 3,
};
#define ARIZONA_IRQ_GP1 0
@ -121,5 +122,6 @@ int arizona_set_irq_wake(struct arizona *arizona, int irq, int on);
int wm5102_patch(struct arizona *arizona);
int wm5110_patch(struct arizona *arizona);
int wm8997_patch(struct arizona *arizona);
#endif

View File

@ -28,6 +28,8 @@
#include <linux/mfd/core.h>
#include <linux/platform_data/edma.h>
#include <mach/hardware.h>
/*
* Register values.
*/
@ -111,8 +113,6 @@ struct davinci_vc {
/* Memory resources */
void __iomem *base;
resource_size_t pbase;
size_t base_size;
/* MFD cells */
struct mfd_cell cells[DAVINCI_VC_CELLS];

125
include/linux/mfd/kempld.h Normal file
View File

@ -0,0 +1,125 @@
/*
* Kontron PLD driver definitions
*
* Copyright (c) 2010-2012 Kontron Europe GmbH
* Author: Michael Brunner <michael.brunner@kontron.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 2 as published
* by the Free Software Foundation.
*/
#ifndef _LINUX_MFD_KEMPLD_H_
#define _LINUX_MFD_KEMPLD_H_
/* kempld register definitions */
#define KEMPLD_IOINDEX 0xa80
#define KEMPLD_IODATA 0xa81
#define KEMPLD_MUTEX_KEY 0x80
#define KEMPLD_VERSION 0x00
#define KEMPLD_VERSION_LSB 0x00
#define KEMPLD_VERSION_MSB 0x01
#define KEMPLD_VERSION_GET_MINOR(x) (x & 0x1f)
#define KEMPLD_VERSION_GET_MAJOR(x) ((x >> 5) & 0x1f)
#define KEMPLD_VERSION_GET_NUMBER(x) ((x >> 10) & 0xf)
#define KEMPLD_VERSION_GET_TYPE(x) ((x >> 14) & 0x3)
#define KEMPLD_BUILDNR 0x02
#define KEMPLD_BUILDNR_LSB 0x02
#define KEMPLD_BUILDNR_MSB 0x03
#define KEMPLD_FEATURE 0x04
#define KEMPLD_FEATURE_LSB 0x04
#define KEMPLD_FEATURE_MSB 0x05
#define KEMPLD_FEATURE_BIT_I2C (1 << 0)
#define KEMPLD_FEATURE_BIT_WATCHDOG (1 << 1)
#define KEMPLD_FEATURE_BIT_GPIO (1 << 2)
#define KEMPLD_FEATURE_MASK_UART (7 << 3)
#define KEMPLD_FEATURE_BIT_NMI (1 << 8)
#define KEMPLD_FEATURE_BIT_SMI (1 << 9)
#define KEMPLD_FEATURE_BIT_SCI (1 << 10)
#define KEMPLD_SPEC 0x06
#define KEMPLD_SPEC_GET_MINOR(x) (x & 0x0f)
#define KEMPLD_SPEC_GET_MAJOR(x) ((x >> 4) & 0x0f)
#define KEMPLD_IRQ_GPIO 0x35
#define KEMPLD_IRQ_I2C 0x36
#define KEMPLD_CFG 0x37
#define KEMPLD_CFG_GPIO_I2C_MUX (1 << 0)
#define KEMPLD_CFG_BIOS_WP (1 << 7)
#define KEMPLD_CLK 33333333
#define KEMPLD_TYPE_RELEASE 0x0
#define KEMPLD_TYPE_DEBUG 0x1
#define KEMPLD_TYPE_CUSTOM 0x2
/**
* struct kempld_info - PLD device information structure
* @major: PLD major revision
* @minor: PLD minor revision
* @buildnr: PLD build number
* @number: PLD board specific index
* @type: PLD type
* @spec_major: PLD FW specification major revision
* @spec_minor: PLD FW specification minor revision
*/
struct kempld_info {
unsigned int major;
unsigned int minor;
unsigned int buildnr;
unsigned int number;
unsigned int type;
unsigned int spec_major;
unsigned int spec_minor;
};
/**
* struct kempld_device_data - Internal representation of the PLD device
* @io_base: Pointer to the IO memory
* @io_index: Pointer to the IO index register
* @io_data: Pointer to the IO data register
* @pld_clock: PLD clock frequency
* @feature_mask: PLD feature mask
* @dev: Pointer to kernel device structure
* @info: KEMPLD info structure
* @lock: PLD mutex
*/
struct kempld_device_data {
void __iomem *io_base;
void __iomem *io_index;
void __iomem *io_data;
u32 pld_clock;
u32 feature_mask;
struct device *dev;
struct kempld_info info;
struct mutex lock;
};
/**
* struct kempld_platform_data - PLD hardware configuration structure
* @pld_clock: PLD clock frequency
* @gpio_base GPIO base pin number
* @ioresource: IO addresses of the PLD
* @get_mutex: PLD specific get_mutex callback
* @release_mutex: PLD specific release_mutex callback
* @get_info: PLD specific get_info callback
* @register_cells: PLD specific register_cells callback
*/
struct kempld_platform_data {
u32 pld_clock;
int gpio_base;
struct resource *ioresource;
void (*get_hardware_mutex) (struct kempld_device_data *);
void (*release_hardware_mutex) (struct kempld_device_data *);
int (*get_info) (struct kempld_device_data *);
int (*register_cells) (struct kempld_device_data *);
};
extern void kempld_get_mutex(struct kempld_device_data *pld);
extern void kempld_release_mutex(struct kempld_device_data *pld);
extern u8 kempld_read8(struct kempld_device_data *pld, u8 index);
extern void kempld_write8(struct kempld_device_data *pld, u8 index, u8 data);
extern u16 kempld_read16(struct kempld_device_data *pld, u8 index);
extern void kempld_write16(struct kempld_device_data *pld, u8 index, u16 data);
extern u32 kempld_read32(struct kempld_device_data *pld, u8 index);
extern void kempld_write32(struct kempld_device_data *pld, u8 index, u32 data);
#endif /* _LINUX_MFD_KEMPLD_H_ */

View File

@ -132,9 +132,12 @@ enum {
#define MAX8998_ENRAMP (1 << 4)
struct irq_domain;
/**
* struct max8998_dev - max8998 master device for sub-drivers
* @dev: master device of the chip (can be used to access platform data)
* @pdata: platform data for the driver and subdrivers
* @i2c: i2c client private data for regulator
* @rtc: i2c client private data for rtc
* @iolock: mutex for serializing io access
@ -148,12 +151,14 @@ enum {
*/
struct max8998_dev {
struct device *dev;
struct max8998_platform_data *pdata;
struct i2c_client *i2c;
struct i2c_client *rtc;
struct mutex iolock;
struct mutex irqlock;
int irq_base;
unsigned int irq_base;
struct irq_domain *irq_domain;
int irq;
int ono;
u8 irq_masks_cur[MAX8998_NUM_IRQ_REGS];

View File

@ -58,10 +58,12 @@ enum {
* max8998_regulator_data - regulator data
* @id: regulator id
* @initdata: regulator init data (contraints, supplies, ...)
* @reg_node: DT node of regulator (unused on non-DT platforms)
*/
struct max8998_regulator_data {
int id;
struct regulator_init_data *initdata;
struct device_node *reg_node;
};
/**
@ -73,12 +75,8 @@ struct max8998_regulator_data {
* @buck_voltage_lock: Do NOT change the values of the following six
* registers set by buck?_voltage?. The voltage of BUCK1/2 cannot
* be other than the preset values.
* @buck1_voltage1: BUCK1 DVS mode 1 voltage register
* @buck1_voltage2: BUCK1 DVS mode 2 voltage register
* @buck1_voltage3: BUCK1 DVS mode 3 voltage register
* @buck1_voltage4: BUCK1 DVS mode 4 voltage register
* @buck2_voltage1: BUCK2 DVS mode 1 voltage register
* @buck2_voltage2: BUCK2 DVS mode 2 voltage register
* @buck1_voltage: BUCK1 DVS mode 1 voltage registers
* @buck2_voltage: BUCK2 DVS mode 2 voltage registers
* @buck1_set1: BUCK1 gpio pin 1 to set output voltage
* @buck1_set2: BUCK1 gpio pin 2 to set output voltage
* @buck1_default_idx: Default for BUCK1 gpio pin 1, 2
@ -100,15 +98,11 @@ struct max8998_regulator_data {
struct max8998_platform_data {
struct max8998_regulator_data *regulators;
int num_regulators;
int irq_base;
unsigned int irq_base;
int ono;
bool buck_voltage_lock;
int buck1_voltage1;
int buck1_voltage2;
int buck1_voltage3;
int buck1_voltage4;
int buck2_voltage1;
int buck2_voltage2;
int buck1_voltage[4];
int buck2_voltage[2];
int buck1_set1;
int buck1_set2;
int buck1_default_idx;

View File

@ -34,6 +34,19 @@
((a) == PALMAS_CHIP_ID))
#define is_palmas_charger(a) ((a) == PALMAS_CHIP_CHARGER_ID)
/**
* Palmas PMIC feature types
*
* PALMAS_PMIC_FEATURE_SMPS10_BOOST - used when the PMIC provides SMPS10_BOOST
* regulator.
*
* PALMAS_PMIC_HAS(b, f) - macro to check if a bandgap device is capable of a
* specific feature (above) or not. Return non-zero, if yes.
*/
#define PALMAS_PMIC_FEATURE_SMPS10_BOOST BIT(0)
#define PALMAS_PMIC_HAS(b, f) \
((b)->features & PALMAS_PMIC_FEATURE_ ## f)
struct palmas_pmic;
struct palmas_gpadc;
struct palmas_resource;
@ -54,6 +67,7 @@ struct palmas {
/* Stored chip id */
int id;
unsigned int features;
/* IRQ Data */
int irq;
u32 irq_mask;

View File

@ -575,6 +575,7 @@
#define CARD_PWR_CTL 0xFD50
#define CARD_CLK_SWITCH 0xFD51
#define RTL8411B_PACKAGE_MODE 0xFD51
#define CARD_SHARE_MODE 0xFD52
#define CARD_DRIVE_SEL 0xFD53
#define CARD_STOP 0xFD54

View File

@ -14,8 +14,6 @@
#ifndef __LINUX_MFD_SEC_CORE_H
#define __LINUX_MFD_SEC_CORE_H
#define NUM_IRQ_REGS 4
enum sec_device_type {
S5M8751X,
S5M8763X,
@ -44,8 +42,6 @@ struct sec_pmic_dev {
struct regmap *regmap;
struct i2c_client *i2c;
struct i2c_client *rtc;
struct mutex iolock;
struct mutex irqlock;
int device_type;
int irq_base;
@ -53,8 +49,6 @@ struct sec_pmic_dev {
struct regmap_irq_chip_data *irq_data;
int ono;
u8 irq_masks_cur[NUM_IRQ_REGS];
u8 irq_masks_cache[NUM_IRQ_REGS];
int type;
bool wakeup;
};

View File

@ -30,8 +30,8 @@
#define REG_IDLECONFIG 0x058
#define REG_CHARGECONFIG 0x05C
#define REG_CHARGEDELAY 0x060
#define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
#define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
#define REG_STEPCONFIG(n) (0x64 + ((n) * 8))
#define REG_STEPDELAY(n) (0x68 + ((n) * 8))
#define REG_FIFO0CNT 0xE4
#define REG_FIFO0THR 0xE8
#define REG_FIFO1CNT 0xF0
@ -46,8 +46,6 @@
/* Step Enable */
#define STEPENB_MASK (0x1FFFF << 0)
#define STEPENB(val) ((val) << 0)
#define STPENB_STEPENB STEPENB(0x1FFFF)
#define STPENB_STEPENB_TC STEPENB(0x1FFF)
/* IRQ enable */
#define IRQENB_HW_PEN BIT(0)
@ -73,8 +71,6 @@
#define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
#define STEPCONFIG_INP_MASK (0xF << 19)
#define STEPCONFIG_INP(val) ((val) << 19)
#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2)
#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3)
#define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4)
#define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
#define STEPCONFIG_FIFO1 BIT(26)
@ -96,7 +92,6 @@
#define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1)
#define STEPCHARGE_INP_MASK (0xF << 19)
#define STEPCHARGE_INP(val) ((val) << 19)
#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1)
#define STEPCHARGE_RFM_MASK (3 << 23)
#define STEPCHARGE_RFM(val) ((val) << 23)
#define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1)
@ -125,22 +120,17 @@
#define TSCADC_CELLS 2
enum tscadc_cells {
TSC_CELL,
ADC_CELL,
};
struct mfd_tscadc_board {
struct tsc_data *tsc_init;
struct adc_data *adc_init;
};
struct ti_tscadc_dev {
struct device *dev;
struct regmap *regmap_tscadc;
void __iomem *tscadc_base;
int irq;
int used_cells; /* 1-2 */
int tsc_cell; /* -1 if not used */
int adc_cell; /* -1 if not used */
struct mfd_cell cells[TSCADC_CELLS];
u32 reg_se_cache;
spinlock_t reg_lock;
/* tsc device */
struct titsc *tsc;
@ -149,4 +139,15 @@ struct ti_tscadc_dev {
struct adc_device *adc;
};
static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
{
struct ti_tscadc_dev **tscadc_dev = p->dev.platform_data;
return *tscadc_dev;
}
void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc);
void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val);
void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val);
#endif

View File

@ -29,6 +29,7 @@ enum wm8994_type {
struct regulator_dev;
struct regulator_bulk_data;
struct irq_domain;
#define WM8994_NUM_GPIO_REGS 11
#define WM8994_NUM_LDO_REGS 2
@ -73,6 +74,7 @@ struct wm8994 {
int irq;
struct regmap_irq_chip_data *irq_data;
struct irq_domain *edge_irq;
/* Used over suspend/resume */
bool suspended;

View File

@ -228,6 +228,11 @@ struct wm8994_pdata {
* lines is mastered.
*/
int max_channels_clocked[WM8994_NUM_AIF];
/**
* GPIO for the IRQ pin if host only supports edge triggering
*/
int irq_gpio;
};
#endif

View File

@ -1,14 +0,0 @@
#ifndef __LINUX_TI_AM335X_ADC_H
#define __LINUX_TI_AM335X_ADC_H
/**
* struct adc_data ADC Input information
* @adc_channels: Number of analog inputs
* available for ADC.
*/
struct adc_data {
unsigned int adc_channels;
};
#endif