Commit 3aa78e0c authored by Linus Torvalds's avatar Linus Torvalds

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 0998d063 ("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
  ...
parents dc5ef1f5 25f311fa
* 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>;
};
}
* 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;
};
};
};
Texas Instruments TWL family (twl4030) reset and power management module
The power management module inside the TWL family provides several facilities
to control the power resources, including power scripts. For now, the
binding only supports the complete shutdown of the system after poweroff.
Required properties:
- compatible : must be "ti,twl4030-power"
Optional properties:
- ti,use_poweroff: With this flag, the chip will initiates an ACTIVE-to-OFF or
SLEEP-to-OFF transition when the system poweroffs.
Example:
&i2c1 {
clock-frequency = <2600000>;
twl: twl@48 {
reg = <0x48>;
interrupts = <7>; /* SYS_NIRQ cascaded to intc */
interrupt-parent = <&intc>;
twl_power: power {
compatible = "ti,twl4030-power";
ti,use_poweroff;
};
};
};
......@@ -18,20 +18,20 @@ For twl6030 regulators/LDOs
- "ti,twl6030-vdd1" for VDD1 SMPS
- "ti,twl6030-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
......
......@@ -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";
......
......@@ -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>
......
......@@ -474,3 +474,17 @@ &cpsw_emac1 {
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>;
};
};
......@@ -502,6 +502,23 @@ elm: elm@48080000 {
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";
......
......@@ -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
......
......@@ -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
......
......@@ -52,8 +52,6 @@ source "drivers/i2c/Kconfig"
source "drivers/spi/Kconfig"
source "drivers/ssbi/Kconfig"
source "drivers/hsi/Kconfig"
source "drivers/pps/Kconfig"
......
......@@ -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
......
......@@ -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 @@ static int tiadc_probe(struct platform_device *pdev)
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");
......
This diff is collapsed.
......@@ -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 @@ static int device_gpadc_init(struct pm80x_chip *chip,
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");
/* 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");
if (!subchip || !subchip->power_page_addr || !subchip->gpadc_page_addr)
return -ENODEV;
/* 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,
},
......
......@@ -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,
},
......
......@@ -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);
/*
......
......@@ -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;
}
......
......@@ -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.
......@@ -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
......
......@@ -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)
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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 @@ static int ab8500_debug_probe(struct platform_device *plf)
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;
}
......
......@@ -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 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
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;
}
......
......@@ -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);
......
......@@ -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 @@ static int adp5520_probe(struct i2c_client *client,
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;
}
......
......@@ -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) {
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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)
......
......@@ -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;
}
......
......@@ -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 */
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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 @@ static int cmodio_pci_probe(struct pci_dev *dev,
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
......
......@@ -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;
}
......
This diff is collapsed.
......@@ -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");
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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,
......
......@@ -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,
......
......@@ -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);
......
......@@ -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",
......
......@@ -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;
}
}
......@@ -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",
......
......@@ -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
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
tsc_wires = pdata->tsc_init->wires;
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);
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,
......
......@@ -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>");
......
......@@ -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;
......
......@@ -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;
......
......@@ -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");
......
......@@ -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;
......
......@@ -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,
};
/*----------------------------------------------------------------------*/
......
......@@ -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);
......
......@@ -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");
......@@ -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);
......
......@@ -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);
......
......@@ -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;
......
This diff is collapsed.
This diff is collapsed.
......@@ -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 */ }
};
......
This diff is collapsed.
......@@ -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;
......
This diff is collapsed.
obj-$(CONFIG_SSBI) += ssbi.o
......@@ -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";
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment