Commit 4b781474 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mfd-3.5-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6

Pull MFD changes from Samuel Ortiz:
 "Besides the usual cleanups, this one brings:

   * Support for 5 new chipsets: Intel's ICH LPC and SCH Centerton,
     ST-E's STAX211, Samsung's MAX77693 and TI's LM3533.

   * Device tree support for the twl6040, tps65910, da9502 and ab8500
     drivers.

   * Fairly big tps56910, ab8500 and db8500 updates.

   * i2c support for mc13xxx.

   * Our regular update for the wm8xxx driver from Mark."

Fix up various conflicts with other trees, largely due to ab5500 removal
etc.

* tag 'mfd-3.5-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (106 commits)
  mfd: Fix build break of max77693 by adding REGMAP_I2C option
  mfd: Fix twl6040 build failure
  mfd: Fix max77693 build failure
  mfd: ab8500-core should depend on MFD_DB8500_PRCMU
  gpio: tps65910: dt: process gpio specific device node info
  mfd: Remove the parsing of dt info for tps65910 gpio
  mfd: Save device node parsed platform data for tps65910 sub devices
  mfd: Add r_select to lm3533 platform data
  gpio: Add Intel Centerton support to gpio-sch
  mfd: Emulate active low IRQs as well as active high IRQs for wm831x
  mfd: Mark two lm3533 zone registers as volatile
  mfd: Fix return type of lm533 attribute is_visible
  mfd: Enable Device Tree support in the ab8500-pwm driver
  mfd: Enable Device Tree support in the ab8500-sysctrl driver
  mfd: Add support for Device Tree to twl6040
  mfd: Register the twl6040 child for the ASoC codec unconditionally
  mfd: Allocate twl6040 IRQ numbers dynamically
  mfd: twl6040 code cleanup in interrupt initialization part
  mfd: Enable ab8500-gpadc driver for Device Tree
  mfd: Prevent unassigned pointer from being used in ab8500-gpadc driver
  ...
parents 53f2c4a8 29f772d4
What: /sys/bus/i2c/devices/.../output_hvled[n]
Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Set the controlling backlight device for high-voltage current
sink HVLED[n] (n = 1, 2) (0, 1).
What: /sys/bus/i2c/devices/.../output_lvled[n]
Date: April 2012
KernelVersion: 3.5
Contact: Johan Hovold <jhovold@gmail.com>
Description:
Set the controlling led device for low-voltage current sink
LVLED[n] (n = 1..5) (0..3).
* Dialog DA9052/53 Power Management Integrated Circuit (PMIC)
Required properties:
- compatible : Should be "dlg,da9052", "dlg,da9053-aa",
"dlg,da9053-ab", or "dlg,da9053-bb"
Sub-nodes:
- regulators : Contain the regulator nodes. The DA9052/53 regulators are
bound using their names as listed below:
buck0 : regulator BUCK0
buck1 : regulator BUCK1
buck2 : regulator BUCK2
buck3 : regulator BUCK3
ldo4 : regulator LDO4
ldo5 : regulator LDO5
ldo6 : regulator LDO6
ldo7 : regulator LDO7
ldo8 : regulator LDO8
ldo9 : regulator LDO9
ldo10 : regulator LDO10
ldo11 : regulator LDO11
ldo12 : regulator LDO12
ldo13 : regulator LDO13
The bindings details of individual regulator device can be found in:
Documentation/devicetree/bindings/regulator/regulator.txt
Examples:
i2c@63fc8000 { /* I2C1 */
status = "okay";
pmic: dialog@48 {
compatible = "dlg,da9053-aa";
reg = <0x48>;
regulators {
buck0 {
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <2075000>;
};
buck1 {
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <2075000>;
};
buck2 {
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <2500000>;
};
buck3 {
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <2500000>;
};
};
};
};
TPS65910 Power Management Integrated Circuit
Required properties:
- compatible: "ti,tps65910" or "ti,tps65911"
- reg: I2C slave address
- interrupts: the interrupt outputs of the controller
- #gpio-cells: number of cells to describe a GPIO, this should be 2.
The first cell is the GPIO number.
The second cell is used to specify additional options <unused>.
- gpio-controller: mark the device as a GPIO controller
- #interrupt-cells: the number of cells to describe an IRQ, this should be 2.
The first cell is the IRQ number.
The second cell is the flags, encoded as the trigger masks from
Documentation/devicetree/bindings/interrupts.txt
- regulators: This is the list of child nodes that specify the regulator
initialization data for defined regulators. Not all regulators for the given
device need to be present. The definition for each of these nodes is defined
using the standard binding for regulators found at
Documentation/devicetree/bindings/regulator/regulator.txt.
The valid names for regulators are:
tps65910: vrtc, vio, vdd1, vdd2, vdd3, vdig1, vdig2, vpll, vdac, vaux1,
vaux2, vaux33, vmmc
tps65911: vrtc, vio, vdd1, vdd3, vddctrl, ldo1, ldo2, ldo3, ldo4, ldo5,
ldo6, ldo7, ldo8
Optional properties:
- ti,vmbch-threshold: (tps65911) main battery charged threshold
comparator. (see VMBCH_VSEL in TPS65910 datasheet)
- ti,vmbch2-threshold: (tps65911) main battery discharged threshold
comparator. (see VMBCH_VSEL in TPS65910 datasheet)
- ti,en-gpio-sleep: enable sleep control for gpios
There should be 9 entries here, one for each gpio.
Regulator Optional properties:
- ti,regulator-ext-sleep-control: enable external sleep
control through external inputs [0 (not enabled), 1 (EN1), 2 (EN2) or 4(EN3)]
If this property is not defined, it defaults to 0 (not enabled).
Example:
pmu: tps65910@d2 {
compatible = "ti,tps65910";
reg = <0xd2>;
interrupt-parent = <&intc>;
interrupts = < 0 118 0x04 >;
#gpio-cells = <2>;
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
ti,vmbch-threshold = 0;
ti,vmbch2-threshold = 0;
ti,en-gpio-sleep = <0 0 1 0 0 0 0 0 0>;
regulators {
vdd1_reg: vdd1 {
regulator-min-microvolt = < 600000>;
regulator-max-microvolt = <1500000>;
regulator-always-on;
regulator-boot-on;
ti,regulator-ext-sleep-control = <0>;
};
vdd2_reg: vdd2 {
regulator-min-microvolt = < 600000>;
regulator-max-microvolt = <1500000>;
regulator-always-on;
regulator-boot-on;
ti,regulator-ext-sleep-control = <4>;
};
vddctrl_reg: vddctrl {
regulator-min-microvolt = < 600000>;
regulator-max-microvolt = <1400000>;
regulator-always-on;
regulator-boot-on;
ti,regulator-ext-sleep-control = <0>;
};
vio_reg: vio {
regulator-min-microvolt = <1500000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
regulator-boot-on;
ti,regulator-ext-sleep-control = <1>;
};
ldo1_reg: ldo1 {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <3300000>;
ti,regulator-ext-sleep-control = <0>;
};
ldo2_reg: ldo2 {
regulator-min-microvolt = <1050000>;
regulator-max-microvolt = <1050000>;
ti,regulator-ext-sleep-control = <0>;
};
ldo3_reg: ldo3 {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <3300000>;
ti,regulator-ext-sleep-control = <0>;
};
ldo4_reg: ldo4 {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
ti,regulator-ext-sleep-control = <0>;
};
ldo5_reg: ldo5 {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <3300000>;
ti,regulator-ext-sleep-control = <0>;
};
ldo6_reg: ldo6 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
ti,regulator-ext-sleep-control = <0>;
};
ldo7_reg: ldo7 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-always-on;
regulator-boot-on;
ti,regulator-ext-sleep-control = <1>;
};
ldo8_reg: ldo8 {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
ti,regulator-ext-sleep-control = <1>;
};
};
};
Texas Instruments TWL6040 family
The TWL6040s are 8-channel high quality low-power audio codecs providing audio
and vibra functionality on OMAP4+ platforms.
They are connected ot the host processor via i2c for commands, McPDM for audio
data and commands.
Required properties:
- compatible : Must be "ti,twl6040";
- reg: must be 0x4b for i2c address
- interrupts: twl6040 has one interrupt line connecteded to the main SoC
- interrupt-parent: The parent interrupt controller
- twl6040,audpwron-gpio: Power on GPIO line for the twl6040
- vio-supply: Regulator for the twl6040 VIO supply
- v2v1-supply: Regulator for the twl6040 V2V1 supply
Optional properties, nodes:
- enable-active-high: To power on the twl6040 during boot.
Vibra functionality
Required properties:
- vddvibl-supply: Regulator for the left vibra motor
- vddvibr-supply: Regulator for the right vibra motor
- vibra { }: Configuration section for vibra parameters containing the following
properties:
- ti,vibldrv-res: Resistance parameter for left driver
- ti,vibrdrv-res: Resistance parameter for right driver
- ti,viblmotor-res: Resistance parameter for left motor
- ti,viblmotor-res: Resistance parameter for right motor
Optional properties within vibra { } section:
- vddvibl_uV: If the vddvibl default voltage need to be changed
- vddvibr_uV: If the vddvibr default voltage need to be changed
Example:
&i2c1 {
twl6040: twl@4b {
compatible = "ti,twl6040";
reg = <0x4b>;
interrupts = <0 119 4>;
interrupt-parent = <&gic>;
twl6040,audpwron-gpio = <&gpio4 31 0>;
vio-supply = <&v1v8>;
v2v1-supply = <&v2v1>;
enable-active-high;
/* regulators for vibra motor */
vddvibl-supply = <&vbat>;
vddvibr-supply = <&vbat>;
vibra {
/* Vibra driver, motor resistance parameters */
ti,vibldrv-res = <8>;
ti,vibrdrv-res = <3>;
ti,viblmotor-res = <10>;
ti,vibrmotor-res = <10>;
};
};
};
...@@ -3382,6 +3382,12 @@ W: http://www.developer.ibm.com/welcome/netfinity/serveraid.html ...@@ -3382,6 +3382,12 @@ W: http://www.developer.ibm.com/welcome/netfinity/serveraid.html
S: Supported S: Supported
F: drivers/scsi/ips.* F: drivers/scsi/ips.*
ICH LPC AND GPIO DRIVER
M: Peter Tyser <ptyser@xes-inc.com>
S: Maintained
F: drivers/mfd/lpc_ich.c
F: drivers/gpio/gpio-ich.c
IDE SUBSYSTEM IDE SUBSYSTEM
M: "David S. Miller" <davem@davemloft.net> M: "David S. Miller" <davem@davemloft.net>
L: linux-ide@vger.kernel.org L: linux-ide@vger.kernel.org
......
...@@ -206,7 +206,7 @@ static struct resource ab8500_resources[] = { ...@@ -206,7 +206,7 @@ static struct resource ab8500_resources[] = {
}; };
struct platform_device ab8500_device = { struct platform_device ab8500_device = {
.name = "ab8500-i2c", .name = "ab8500-core",
.id = 0, .id = 0,
.dev = { .dev = {
.platform_data = &ab8500_platdata, .platform_data = &ab8500_platdata,
......
/*
* Header file for STMicroelectronics ConneXt (STA2X11) IOHub
*/
#ifndef __ASM_STA2X11_H
#define __ASM_STA2X11_H
#include <linux/pci.h>
/* This needs to be called from the MFD to configure its sub-devices */
struct sta2x11_instance *sta2x11_get_instance(struct pci_dev *pdev);
#endif /* __ASM_STA2X11_H */
...@@ -167,6 +167,14 @@ config GPIO_PXA ...@@ -167,6 +167,14 @@ config GPIO_PXA
help help
Say yes here to support the PXA GPIO device Say yes here to support the PXA GPIO device
config GPIO_STA2X11
bool "STA2x11/ConneXt GPIO support"
depends on MFD_STA2X11
select GENERIC_IRQ_CHIP
help
Say yes here to support the STA2x11/ConneXt GPIO device.
The GPIO module has 128 GPIO pins with alternate functions.
config GPIO_XILINX config GPIO_XILINX
bool "Xilinx GPIO support" bool "Xilinx GPIO support"
depends on PPC_OF || MICROBLAZE depends on PPC_OF || MICROBLAZE
...@@ -180,13 +188,13 @@ config GPIO_VR41XX ...@@ -180,13 +188,13 @@ config GPIO_VR41XX
Say yes here to support the NEC VR4100 series General-purpose I/O Uint Say yes here to support the NEC VR4100 series General-purpose I/O Uint
config GPIO_SCH config GPIO_SCH
tristate "Intel SCH/TunnelCreek GPIO" tristate "Intel SCH/TunnelCreek/Centerton GPIO"
depends on PCI && X86 depends on PCI && X86
select MFD_CORE select MFD_CORE
select LPC_SCH select LPC_SCH
help help
Say yes here to support GPIO interface on Intel Poulsbo SCH Say yes here to support GPIO interface on Intel Poulsbo SCH,
or Intel Tunnel Creek processor. Intel Tunnel Creek processor or Intel Centerton processor.
The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are
powered by the core power rail and are turned off during sleep powered by the core power rail and are turned off during sleep
modes (S3 and higher). The remaining four GPIOs are powered by modes (S3 and higher). The remaining four GPIOs are powered by
...@@ -195,6 +203,22 @@ config GPIO_SCH ...@@ -195,6 +203,22 @@ config GPIO_SCH
system from the Suspend-to-RAM state. system from the Suspend-to-RAM state.
The Intel Tunnel Creek processor has 5 GPIOs powered by the The Intel Tunnel Creek processor has 5 GPIOs powered by the
core power rail and 9 from suspend power supply. core power rail and 9 from suspend power supply.
The Intel Centerton processor has a total of 30 GPIO pins.
Twenty-one are powered by the core power rail and 9 from the
suspend power supply.
config GPIO_ICH
tristate "Intel ICH GPIO"
depends on PCI && X86
select MFD_CORE
select LPC_ICH
help
Say yes here to support the GPIO functionality of a number of Intel
ICH-based chipsets. Currently supported devices: ICH6, ICH7, ICH8
ICH9, ICH10, Series 5/3400 (eg Ibex Peak), Series 6/C200 (eg
Cougar Point), NM10 (Tiger Point), and 3100 (Whitmore Lake).
If unsure, say N.
config GPIO_VX855 config GPIO_VX855
tristate "VIA VX855/VX875 GPIO" tristate "VIA VX855/VX875 GPIO"
......
...@@ -19,6 +19,7 @@ obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o ...@@ -19,6 +19,7 @@ obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o
obj-$(CONFIG_GPIO_EM) += gpio-em.o obj-$(CONFIG_GPIO_EM) += gpio-em.o
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o
...@@ -51,6 +52,7 @@ obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o ...@@ -51,6 +52,7 @@ obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o
obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
obj-$(CONFIG_GPIO_SCH) += gpio-sch.o obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o
obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o
obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o
......
This diff is collapsed.
...@@ -232,6 +232,14 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev) ...@@ -232,6 +232,14 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev)
sch_gpio_resume.ngpio = 9; sch_gpio_resume.ngpio = 9;
break; break;
case PCI_DEVICE_ID_INTEL_CENTERTON_ILB:
sch_gpio_core.base = 0;
sch_gpio_core.ngpio = 21;
sch_gpio_resume.base = 21;
sch_gpio_resume.ngpio = 9;
break;
default: default:
return -ENODEV; return -ENODEV;
} }
......
This diff is collapsed.
...@@ -18,14 +18,27 @@ ...@@ -18,14 +18,27 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/mfd/tps65910.h> #include <linux/mfd/tps65910.h>
#include <linux/of_device.h>
struct tps65910_gpio {
struct gpio_chip gpio_chip;
struct tps65910 *tps65910;
};
static inline struct tps65910_gpio *to_tps65910_gpio(struct gpio_chip *chip)
{
return container_of(chip, struct tps65910_gpio, gpio_chip);
}
static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset) static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset)
{ {
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
uint8_t val; struct tps65910 *tps65910 = tps65910_gpio->tps65910;
unsigned int val;
tps65910->read(tps65910, TPS65910_GPIO0 + offset, 1, &val); tps65910_reg_read(tps65910, TPS65910_GPIO0 + offset, &val);
if (val & GPIO_STS_MASK) if (val & GPIO_STS_MASK)
return 1; return 1;
...@@ -36,83 +49,170 @@ static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset) ...@@ -36,83 +49,170 @@ static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset)
static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset, static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset,
int value) int value)
{ {
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
struct tps65910 *tps65910 = tps65910_gpio->tps65910;
if (value) if (value)
tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset, tps65910_reg_set_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_SET_MASK); GPIO_SET_MASK);
else else
tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset, tps65910_reg_clear_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_SET_MASK); GPIO_SET_MASK);
} }
static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset, static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset,
int value) int value)
{ {
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
struct tps65910 *tps65910 = tps65910_gpio->tps65910;
/* Set the initial value */ /* Set the initial value */
tps65910_gpio_set(gc, offset, value); tps65910_gpio_set(gc, offset, value);
return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset, return tps65910_reg_set_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_CFG_MASK); GPIO_CFG_MASK);
} }
static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset) static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset)
{ {
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
struct tps65910 *tps65910 = tps65910_gpio->tps65910;
return tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset, return tps65910_reg_clear_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_CFG_MASK); GPIO_CFG_MASK);
} }
void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base) #ifdef CONFIG_OF
static struct tps65910_board *tps65910_parse_dt_for_gpio(struct device *dev,
struct tps65910 *tps65910, int chip_ngpio)
{ {
struct tps65910_board *tps65910_board = tps65910->of_plat_data;
unsigned int prop_array[TPS6591X_MAX_NUM_GPIO];
int ngpio = min(chip_ngpio, TPS6591X_MAX_NUM_GPIO);
int ret; int ret;
struct tps65910_board *board_data; int idx;
tps65910_board->gpio_base = -1;
ret = of_property_read_u32_array(tps65910->dev->of_node,
"ti,en-gpio-sleep", prop_array, ngpio);
if (ret < 0) {
dev_dbg(dev, "ti,en-gpio-sleep not specified\n");
return tps65910_board;
}
if (!gpio_base) for (idx = 0; idx < ngpio; idx++)
return; tps65910_board->en_gpio_sleep[idx] = (prop_array[idx] != 0);
tps65910->gpio.owner = THIS_MODULE; return tps65910_board;
tps65910->gpio.label = tps65910->i2c_client->name; }
tps65910->gpio.dev = tps65910->dev; #else
tps65910->gpio.base = gpio_base; static struct tps65910_board *tps65910_parse_dt_for_gpio(struct device *dev,
struct tps65910 *tps65910, int chip_ngpio)
{
return NULL;
}
#endif
static int __devinit tps65910_gpio_probe(struct platform_device *pdev)
{
struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
struct tps65910_board *pdata = dev_get_platdata(tps65910->dev);
struct tps65910_gpio *tps65910_gpio;
int ret;
int i;
tps65910_gpio = devm_kzalloc(&pdev->dev,
sizeof(*tps65910_gpio), GFP_KERNEL);
if (!tps65910_gpio) {
dev_err(&pdev->dev, "Could not allocate tps65910_gpio\n");
return -ENOMEM;
}
tps65910_gpio->tps65910 = tps65910;
tps65910_gpio->gpio_chip.owner = THIS_MODULE;
tps65910_gpio->gpio_chip.label = tps65910->i2c_client->name;
switch(tps65910_chip_id(tps65910)) { switch(tps65910_chip_id(tps65910)) {
case TPS65910: case TPS65910:
tps65910->gpio.ngpio = TPS65910_NUM_GPIO; tps65910_gpio->gpio_chip.ngpio = TPS65910_NUM_GPIO;
break; break;
case TPS65911: case TPS65911:
tps65910->gpio.ngpio = TPS65911_NUM_GPIO; tps65910_gpio->gpio_chip.ngpio = TPS65911_NUM_GPIO;
break; break;
default: default:
return; return -EINVAL;
} }
tps65910->gpio.can_sleep = 1; tps65910_gpio->gpio_chip.can_sleep = 1;
tps65910_gpio->gpio_chip.direction_input = tps65910_gpio_input;
tps65910_gpio->gpio_chip.direction_output = tps65910_gpio_output;
tps65910_gpio->gpio_chip.set = tps65910_gpio_set;
tps65910_gpio->gpio_chip.get = tps65910_gpio_get;
tps65910_gpio->gpio_chip.dev = &pdev->dev;
if (pdata && pdata->gpio_base)
tps65910_gpio->gpio_chip.base = pdata->gpio_base;
else
tps65910_gpio->gpio_chip.base = -1;
tps65910->gpio.direction_input = tps65910_gpio_input; if (!pdata && tps65910->dev->of_node)
tps65910->gpio.direction_output = tps65910_gpio_output; pdata = tps65910_parse_dt_for_gpio(&pdev->dev, tps65910,
tps65910->gpio.set = tps65910_gpio_set; tps65910_gpio->gpio_chip.ngpio);
tps65910->gpio.get = tps65910_gpio_get;
/* Configure sleep control for gpios */ if (!pdata)
board_data = dev_get_platdata(tps65910->dev); goto skip_init;
if (board_data) {
int i; /* Configure sleep control for gpios if provided */
for (i = 0; i < tps65910->gpio.ngpio; ++i) { for (i = 0; i < tps65910_gpio->gpio_chip.ngpio; ++i) {
if (board_data->en_gpio_sleep[i]) { if (!pdata->en_gpio_sleep[i])
ret = tps65910_set_bits(tps65910, continue;
ret = tps65910_reg_set_bits(tps65910,
TPS65910_GPIO0 + i, GPIO_SLEEP_MASK); TPS65910_GPIO0 + i, GPIO_SLEEP_MASK);
if (ret < 0) if (ret < 0)
dev_warn(tps65910->dev, dev_warn(tps65910->dev,
"GPIO Sleep setting failed\n"); "GPIO Sleep setting failed with err %d\n", ret);
}
} }
skip_init:
ret = gpiochip_add(&tps65910_gpio->gpio_chip);
if (ret < 0) {
dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
return ret;
} }
ret = gpiochip_add(&tps65910->gpio); platform_set_drvdata(pdev, tps65910_gpio);
return ret;
}
static int __devexit tps65910_gpio_remove(struct platform_device *pdev)
{
struct tps65910_gpio *tps65910_gpio = platform_get_drvdata(pdev);
if (ret) return gpiochip_remove(&tps65910_gpio->gpio_chip);
dev_warn(tps65910->dev, "GPIO registration failed: %d\n", ret);
} }
static struct platform_driver tps65910_gpio_driver = {
.driver.name = "tps65910-gpio",
.driver.owner = THIS_MODULE,
.probe = tps65910_gpio_probe,
.remove = __devexit_p(tps65910_gpio_remove),
};
static int __init tps65910_gpio_init(void)
{
return platform_driver_register(&tps65910_gpio_driver);
}
subsys_initcall(tps65910_gpio_init);
static void __exit tps65910_gpio_exit(void)
{
platform_driver_unregister(&tps65910_gpio_driver);
}
module_exit(tps65910_gpio_exit);
MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
MODULE_AUTHOR("Jorge Eduardo Candelaria jedu@slimlogic.co.uk>");
MODULE_DESCRIPTION("GPIO interface for TPS65910/TPS6511 PMICs");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:tps65910-gpio");
...@@ -102,10 +102,8 @@ static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) ...@@ -102,10 +102,8 @@ static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
struct wm831x *wm831x = wm831x_gpio->wm831x; struct wm831x *wm831x = wm831x_gpio->wm831x;
if (!wm831x->irq_base) return irq_create_mapping(wm831x->irq_domain,
return -EINVAL; WM831X_IRQ_GPIO_1 + offset);
return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset;
} }
static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
......
...@@ -73,7 +73,7 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev) ...@@ -73,7 +73,7 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev)
{ {
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_on *wm831x_on; struct wm831x_on *wm831x_on;
int irq = platform_get_irq(pdev, 0); int irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0));
int ret; int ret;
wm831x_on = kzalloc(sizeof(struct wm831x_on), GFP_KERNEL); wm831x_on = kzalloc(sizeof(struct wm831x_on), GFP_KERNEL);
......
...@@ -260,15 +260,16 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev) ...@@ -260,15 +260,16 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
* If we have a direct IRQ use it, otherwise use the interrupt * If we have a direct IRQ use it, otherwise use the interrupt
* from the WM831x IRQ controller. * from the WM831x IRQ controller.
*/ */
wm831x_ts->data_irq = wm831x_irq(wm831x,
platform_get_irq_byname(pdev,
"TCHDATA"));
if (pdata && pdata->data_irq) if (pdata && pdata->data_irq)
wm831x_ts->data_irq = pdata->data_irq; wm831x_ts->data_irq = pdata->data_irq;
else
wm831x_ts->data_irq = platform_get_irq_byname(pdev, "TCHDATA");
wm831x_ts->pd_irq = wm831x_irq(wm831x,
platform_get_irq_byname(pdev, "TCHPD"));
if (pdata && pdata->pd_irq) if (pdata && pdata->pd_irq)
wm831x_ts->pd_irq = pdata->pd_irq; wm831x_ts->pd_irq = pdata->pd_irq;
else
wm831x_ts->pd_irq = platform_get_irq_byname(pdev, "TCHPD");
if (pdata) if (pdata)
wm831x_ts->pressure = pdata->pressure; wm831x_ts->pressure = pdata->pressure;
......
...@@ -106,6 +106,19 @@ config UCB1400_CORE ...@@ -106,6 +106,19 @@ config UCB1400_CORE
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called ucb1400_core. module will be called ucb1400_core.
config MFD_LM3533
tristate "LM3533 Lighting Power chip"
depends on I2C
select MFD_CORE
select REGMAP_I2C
help
Say yes here to enable support for National Semiconductor / TI
LM3533 Lighting Power chips.
This driver provides common support for accessing the device;
additional drivers must be enabled in order to use the LED,
backlight or ambient-light-sensor functionality of the device.
config TPS6105X config TPS6105X
tristate "TPS61050/61052 Boost Converters" tristate "TPS61050/61052 Boost Converters"
depends on I2C depends on I2C
...@@ -177,8 +190,8 @@ config MFD_TPS65910 ...@@ -177,8 +190,8 @@ config MFD_TPS65910
bool "TPS65910 Power Management chip" bool "TPS65910 Power Management chip"
depends on I2C=y && GPIOLIB depends on I2C=y && GPIOLIB
select MFD_CORE select MFD_CORE
select GPIO_TPS65910
select REGMAP_I2C select REGMAP_I2C
select IRQ_DOMAIN
help help
if you say yes here you get support for the TPS65910 series of if you say yes here you get support for the TPS65910 series of
Power Management chips. Power Management chips.
...@@ -409,6 +422,19 @@ config PMIC_ADP5520 ...@@ -409,6 +422,19 @@ config PMIC_ADP5520
individual components like LCD backlight, LEDs, GPIOs and Kepad individual components like LCD backlight, LEDs, GPIOs and Kepad
under the corresponding menus. under the corresponding menus.
config MFD_MAX77693
bool "Maxim Semiconductor MAX77693 PMIC Support"
depends on I2C=y && GENERIC_HARDIRQS
select MFD_CORE
select REGMAP_I2C
help
Say yes here to support for Maxim Semiconductor MAX77693.
This is a companion Power Management IC with Flash, Haptic, Charger,
and MUIC(Micro USB Interface Controller) controls on chip.
This driver provides common support for accessing the device;
additional drivers must be enabled in order to use the functionality
of the device.
config MFD_MAX8925 config MFD_MAX8925
bool "Maxim Semiconductor MAX8925 PMIC Support" bool "Maxim Semiconductor MAX8925 PMIC Support"
depends on I2C=y && GENERIC_HARDIRQS depends on I2C=y && GENERIC_HARDIRQS
...@@ -454,9 +480,9 @@ config MFD_S5M_CORE ...@@ -454,9 +480,9 @@ config MFD_S5M_CORE
of the device of the device
config MFD_WM8400 config MFD_WM8400
tristate "Support Wolfson Microelectronics WM8400" bool "Support Wolfson Microelectronics WM8400"
select MFD_CORE select MFD_CORE
depends on I2C depends on I2C=y
select REGMAP_I2C select REGMAP_I2C
help help
Support for the Wolfson Microelecronics WM8400 PMIC and audio Support for the Wolfson Microelecronics WM8400 PMIC and audio
...@@ -473,6 +499,7 @@ config MFD_WM831X_I2C ...@@ -473,6 +499,7 @@ config MFD_WM831X_I2C
select MFD_CORE select MFD_CORE
select MFD_WM831X select MFD_WM831X
select REGMAP_I2C select REGMAP_I2C
select IRQ_DOMAIN
depends on I2C=y && GENERIC_HARDIRQS depends on I2C=y && GENERIC_HARDIRQS
help help
Support for the Wolfson Microelecronics WM831x and WM832x PMICs Support for the Wolfson Microelecronics WM831x and WM832x PMICs
...@@ -485,6 +512,7 @@ config MFD_WM831X_SPI ...@@ -485,6 +512,7 @@ config MFD_WM831X_SPI
select MFD_CORE select MFD_CORE
select MFD_WM831X select MFD_WM831X
select REGMAP_SPI select REGMAP_SPI
select IRQ_DOMAIN
depends on SPI_MASTER && GENERIC_HARDIRQS depends on SPI_MASTER && GENERIC_HARDIRQS
help help
Support for the Wolfson Microelecronics WM831x and WM832x PMICs Support for the Wolfson Microelecronics WM831x and WM832x PMICs
...@@ -597,17 +625,32 @@ config MFD_MC13783 ...@@ -597,17 +625,32 @@ config MFD_MC13783
tristate tristate
config MFD_MC13XXX config MFD_MC13XXX
tristate "Support Freescale MC13783 and MC13892" tristate
depends on SPI_MASTER depends on SPI_MASTER || I2C
select MFD_CORE select MFD_CORE
select MFD_MC13783 select MFD_MC13783
help help
Support for the Freescale (Atlas) PMIC and audio CODECs Enable support for the Freescale MC13783 and MC13892 PMICs.
MC13783 and MC13892.
This driver provides common support for accessing the device, This driver provides common support for accessing the device,
additional drivers must be enabled in order to use the additional drivers must be enabled in order to use the
functionality of the device. functionality of the device.
config MFD_MC13XXX_SPI
tristate "Freescale MC13783 and MC13892 SPI interface"
depends on SPI_MASTER
select REGMAP_SPI
select MFD_MC13XXX
help
Select this if your MC13xxx is connected via an SPI bus.
config MFD_MC13XXX_I2C
tristate "Freescale MC13892 I2C interface"
depends on I2C
select REGMAP_I2C
select MFD_MC13XXX
help
Select this if your MC13xxx is connected via an I2C bus.
config ABX500_CORE config ABX500_CORE
bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions" bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions"
default y if ARCH_U300 || ARCH_U8500 default y if ARCH_U300 || ARCH_U8500
...@@ -651,7 +694,7 @@ config EZX_PCAP ...@@ -651,7 +694,7 @@ config EZX_PCAP
config AB8500_CORE config AB8500_CORE
bool "ST-Ericsson AB8500 Mixed Signal Power Management chip" bool "ST-Ericsson AB8500 Mixed Signal Power Management chip"
depends on GENERIC_HARDIRQS && ABX500_CORE depends on GENERIC_HARDIRQS && ABX500_CORE && MFD_DB8500_PRCMU
select MFD_CORE select MFD_CORE
help help
Select this option to enable access to AB8500 power management Select this option to enable access to AB8500 power management
...@@ -722,6 +765,16 @@ config LPC_SCH ...@@ -722,6 +765,16 @@ config LPC_SCH
LPC bridge function of the Intel SCH provides support for LPC bridge function of the Intel SCH provides support for
System Management Bus and General Purpose I/O. System Management Bus and General Purpose I/O.
config LPC_ICH
tristate "Intel ICH LPC"
depends on PCI
select MFD_CORE
help
The LPC bridge function of the Intel ICH provides support for
many functional units. This driver provides needed support for
other drivers to control these functions, currently GPIO and
watchdog.
config MFD_RDC321X config MFD_RDC321X
tristate "Support for RDC-R321x southbridge" tristate "Support for RDC-R321x southbridge"
select MFD_CORE select MFD_CORE
...@@ -854,6 +907,11 @@ config MFD_RC5T583 ...@@ -854,6 +907,11 @@ config MFD_RC5T583
Additional drivers must be enabled in order to use the Additional drivers must be enabled in order to use the
different functionality of the device. different functionality of the device.
config MFD_STA2X11
bool "STA2X11 multi function device support"
depends on STA2X11
select MFD_CORE
config MFD_ANATOP config MFD_ANATOP
bool "Support for Freescale i.MX on-chip ANATOP controller" bool "Support for Freescale i.MX on-chip ANATOP controller"
depends on SOC_IMX6Q depends on SOC_IMX6Q
......
...@@ -15,6 +15,7 @@ obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o ...@@ -15,6 +15,7 @@ obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o
obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
obj-$(CONFIG_MFD_TI_SSP) += ti-ssp.o obj-$(CONFIG_MFD_TI_SSP) += ti-ssp.o
obj-$(CONFIG_MFD_STA2X11) += sta2x11-mfd.o
obj-$(CONFIG_MFD_STMPE) += stmpe.o obj-$(CONFIG_MFD_STMPE) += stmpe.o
obj-$(CONFIG_STMPE_I2C) += stmpe-i2c.o obj-$(CONFIG_STMPE_I2C) += stmpe-i2c.o
obj-$(CONFIG_STMPE_SPI) += stmpe-spi.o obj-$(CONFIG_STMPE_SPI) += stmpe-spi.o
...@@ -54,6 +55,8 @@ obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o ...@@ -54,6 +55,8 @@ obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o
obj-$(CONFIG_TWL6040_CORE) += twl6040-core.o twl6040-irq.o obj-$(CONFIG_TWL6040_CORE) += twl6040-core.o twl6040-irq.o
obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
obj-$(CONFIG_MFD_MC13XXX_SPI) += mc13xxx-spi.o
obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o
obj-$(CONFIG_MFD_CORE) += mfd-core.o obj-$(CONFIG_MFD_CORE) += mfd-core.o
...@@ -75,6 +78,7 @@ obj-$(CONFIG_PMIC_DA9052) += da9052-core.o ...@@ -75,6 +78,7 @@ obj-$(CONFIG_PMIC_DA9052) += da9052-core.o
obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o
obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o
obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o
max8925-objs := max8925-core.o max8925-i2c.o max8925-objs := max8925-core.o max8925-i2c.o
obj-$(CONFIG_MFD_MAX8925) += max8925.o obj-$(CONFIG_MFD_MAX8925) += max8925.o
obj-$(CONFIG_MFD_MAX8997) += max8997.o max8997-irq.o obj-$(CONFIG_MFD_MAX8997) += max8997.o max8997-irq.o
...@@ -87,15 +91,15 @@ obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o ...@@ -87,15 +91,15 @@ obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o
obj-$(CONFIG_ABX500_CORE) += abx500-core.o obj-$(CONFIG_ABX500_CORE) += abx500-core.o
obj-$(CONFIG_AB3100_CORE) += ab3100-core.o obj-$(CONFIG_AB3100_CORE) += ab3100-core.o
obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o
obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o
obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o
obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o
# ab8500-i2c need to come after db8500-prcmu (which provides the channel) # ab8500-core need to come after db8500-prcmu (which provides the channel)
obj-$(CONFIG_AB8500_I2C_CORE) += ab8500-i2c.o obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o
obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
obj-$(CONFIG_PMIC_ADP5520) += adp5520.o obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
obj-$(CONFIG_LPC_SCH) += lpc_sch.o obj-$(CONFIG_LPC_SCH) += lpc_sch.o
obj-$(CONFIG_LPC_ICH) += lpc_ich.o
obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o
obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o
obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o
......
This diff is collapsed.
...@@ -608,10 +608,16 @@ static int __devexit ab8500_debug_remove(struct platform_device *plf) ...@@ -608,10 +608,16 @@ static int __devexit ab8500_debug_remove(struct platform_device *plf)
return 0; return 0;
} }
static const struct of_device_id ab8500_debug_match[] = {
{ .compatible = "stericsson,ab8500-debug", },
{}
};
static struct platform_driver ab8500_debug_driver = { static struct platform_driver ab8500_debug_driver = {
.driver = { .driver = {
.name = "ab8500-debug", .name = "ab8500-debug",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = ab8500_debug_match,
}, },
.probe = ab8500_debug_probe, .probe = ab8500_debug_probe,
.remove = __devexit_p(ab8500_debug_remove) .remove = __devexit_p(ab8500_debug_remove)
......
...@@ -584,7 +584,7 @@ static int __devinit ab8500_gpadc_probe(struct platform_device *pdev) ...@@ -584,7 +584,7 @@ static int __devinit ab8500_gpadc_probe(struct platform_device *pdev)
gpadc->irq = platform_get_irq_byname(pdev, "SW_CONV_END"); gpadc->irq = platform_get_irq_byname(pdev, "SW_CONV_END");
if (gpadc->irq < 0) { if (gpadc->irq < 0) {
dev_err(gpadc->dev, "failed to get platform irq-%d\n", dev_err(&pdev->dev, "failed to get platform irq-%d\n",
gpadc->irq); gpadc->irq);
ret = gpadc->irq; ret = gpadc->irq;
goto fail; goto fail;
...@@ -648,12 +648,18 @@ static int __devexit ab8500_gpadc_remove(struct platform_device *pdev) ...@@ -648,12 +648,18 @@ static int __devexit ab8500_gpadc_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct of_device_id ab8500_gpadc_match[] = {
{ .compatible = "stericsson,ab8500-gpadc", },
{}
};
static struct platform_driver ab8500_gpadc_driver = { static struct platform_driver ab8500_gpadc_driver = {
.probe = ab8500_gpadc_probe, .probe = ab8500_gpadc_probe,
.remove = __devexit_p(ab8500_gpadc_remove), .remove = __devexit_p(ab8500_gpadc_remove),
.driver = { .driver = {
.name = "ab8500-gpadc", .name = "ab8500-gpadc",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = ab8500_gpadc_match,
}, },
}; };
......
/*
* Copyright (C) ST-Ericsson SA 2010
* Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson.
* License Terms: GNU General Public License v2
* This file was based on drivers/mfd/ab8500-spi.c
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/dbx500-prcmu.h>
static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data)
{
int ret;
ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
if (ret < 0)
dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
return ret;
}
static int ab8500_i2c_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask,
u8 data)
{
int ret;
ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data,
&mask, 1);
if (ret < 0)
dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
return ret;
}
static int ab8500_i2c_read(struct ab8500 *ab8500, u16 addr)
{
int ret;
u8 data;
ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
if (ret < 0) {
dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
return ret;
}
return (int)data;
}
static int __devinit ab8500_i2c_probe(struct platform_device *plf)
{
const struct platform_device_id *platid = platform_get_device_id(plf);
struct ab8500 *ab8500;
struct resource *resource;
int ret;
ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL);
if (!ab8500)
return -ENOMEM;
ab8500->dev = &plf->dev;
resource = platform_get_resource(plf, IORESOURCE_IRQ, 0);
if (!resource) {
kfree(ab8500);
return -ENODEV;
}
ab8500->irq = resource->start;
ab8500->read = ab8500_i2c_read;
ab8500->write = ab8500_i2c_write;
ab8500->write_masked = ab8500_i2c_write_masked;
platform_set_drvdata(plf, ab8500);
ret = ab8500_init(ab8500, platid->driver_data);
if (ret)
kfree(ab8500);
return ret;
}
static int __devexit ab8500_i2c_remove(struct platform_device *plf)
{
struct ab8500 *ab8500 = platform_get_drvdata(plf);
ab8500_exit(ab8500);
kfree(ab8500);
return 0;
}
static const struct platform_device_id ab8500_id[] = {
{ "ab8500-i2c", AB8500_VERSION_AB8500 },
{ "ab8505-i2c", AB8500_VERSION_AB8505 },
{ "ab9540-i2c", AB8500_VERSION_AB9540 },
{ "ab8540-i2c", AB8500_VERSION_AB8540 },
{ }
};
static struct platform_driver ab8500_i2c_driver = {
.driver = {
.name = "ab8500-i2c",
.owner = THIS_MODULE,
},
.probe = ab8500_i2c_probe,
.remove = __devexit_p(ab8500_i2c_remove),
.id_table = ab8500_id,
};
static int __init ab8500_i2c_init(void)
{
return platform_driver_register(&ab8500_i2c_driver);
}
static void __exit ab8500_i2c_exit(void)
{
platform_driver_unregister(&ab8500_i2c_driver);
}
arch_initcall(ab8500_i2c_init);
module_exit(ab8500_i2c_exit);
MODULE_AUTHOR("Mattias WALLIN <mattias.wallin@stericsson.com");
MODULE_DESCRIPTION("AB8500 Core access via PRCMU I2C");
MODULE_LICENSE("GPL v2");
...@@ -61,10 +61,16 @@ static int __devexit ab8500_sysctrl_remove(struct platform_device *pdev) ...@@ -61,10 +61,16 @@ static int __devexit ab8500_sysctrl_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct of_device_id ab8500_sysctrl_match[] = {
{ .compatible = "stericsson,ab8500-sysctrl", },
{}
};
static struct platform_driver ab8500_sysctrl_driver = { static struct platform_driver ab8500_sysctrl_driver = {
.driver = { .driver = {
.name = "ab8500-sysctrl", .name = "ab8500-sysctrl",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = ab8500_sysctrl_match,
}, },
.probe = ab8500_sysctrl_probe, .probe = ab8500_sysctrl_probe,
.remove = __devexit_p(ab8500_sysctrl_remove), .remove = __devexit_p(ab8500_sysctrl_remove),
......
...@@ -41,39 +41,26 @@ ...@@ -41,39 +41,26 @@
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/mfd/anatop.h> #include <linux/mfd/anatop.h>
u32 anatop_get_bits(struct anatop *adata, u32 addr, int bit_shift, u32 anatop_read_reg(struct anatop *adata, u32 addr)
int bit_width)
{ {
u32 val, mask; return readl(adata->ioreg + addr);
if (bit_width == 32)
mask = ~0;
else
mask = (1 << bit_width) - 1;
val = readl(adata->ioreg + addr);
val = (val >> bit_shift) & mask;
return val;
} }
EXPORT_SYMBOL_GPL(anatop_get_bits); EXPORT_SYMBOL_GPL(anatop_read_reg);
void anatop_set_bits(struct anatop *adata, u32 addr, int bit_shift, void anatop_write_reg(struct anatop *adata, u32 addr, u32 data, u32 mask)
int bit_width, u32 data)
{ {
u32 val, mask; u32 val;
if (bit_width == 32) data &= mask;
mask = ~0;
else
mask = (1 << bit_width) - 1;
spin_lock(&adata->reglock); spin_lock(&adata->reglock);
val = readl(adata->ioreg + addr) & ~(mask << bit_shift); val = readl(adata->ioreg + addr);
writel((data << bit_shift) | val, adata->ioreg + addr); val &= ~mask;
val |= data;
writel(val, adata->ioreg + addr);
spin_unlock(&adata->reglock); spin_unlock(&adata->reglock);
} }
EXPORT_SYMBOL_GPL(anatop_set_bits); EXPORT_SYMBOL_GPL(anatop_write_reg);
static const struct of_device_id of_anatop_match[] = { static const struct of_device_id of_anatop_match[] = {
{ .compatible = "fsl,imx6q-anatop", }, { .compatible = "fsl,imx6q-anatop", },
......
...@@ -353,12 +353,28 @@ static int asic3_gpio_irq_type(struct irq_data *data, unsigned int type) ...@@ -353,12 +353,28 @@ static int asic3_gpio_irq_type(struct irq_data *data, unsigned int type)
return 0; return 0;
} }
static int asic3_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
{
struct asic3 *asic = irq_data_get_irq_chip_data(data);
u32 bank, index;
u16 bit;
bank = asic3_irq_to_bank(asic, data->irq);
index = asic3_irq_to_index(asic, data->irq);
bit = 1<<index;
asic3_set_register(asic, bank + ASIC3_GPIO_SLEEP_MASK, bit, !on);
return 0;
}
static struct irq_chip asic3_gpio_irq_chip = { static struct irq_chip asic3_gpio_irq_chip = {
.name = "ASIC3-GPIO", .name = "ASIC3-GPIO",
.irq_ack = asic3_mask_gpio_irq, .irq_ack = asic3_mask_gpio_irq,
.irq_mask = asic3_mask_gpio_irq, .irq_mask = asic3_mask_gpio_irq,
.irq_unmask = asic3_unmask_gpio_irq, .irq_unmask = asic3_unmask_gpio_irq,
.irq_set_type = asic3_gpio_irq_type, .irq_set_type = asic3_gpio_irq_type,
.irq_set_wake = asic3_gpio_irq_set_wake,
}; };
static struct irq_chip asic3_irq_chip = { static struct irq_chip asic3_irq_chip = {
...@@ -529,7 +545,7 @@ static int asic3_gpio_to_irq(struct gpio_chip *chip, unsigned offset) ...@@ -529,7 +545,7 @@ static int asic3_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{ {
struct asic3 *asic = container_of(chip, struct asic3, gpio); struct asic3 *asic = container_of(chip, struct asic3, gpio);
return (offset < ASIC3_NUM_GPIOS) ? asic->irq_base + offset : -ENXIO; return asic->irq_base + offset;
} }
static __init int asic3_gpio_probe(struct platform_device *pdev, static __init int asic3_gpio_probe(struct platform_device *pdev,
...@@ -894,10 +910,13 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, ...@@ -894,10 +910,13 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
asic3_mmc_resources[0].start >>= asic->bus_shift; asic3_mmc_resources[0].start >>= asic->bus_shift;
asic3_mmc_resources[0].end >>= asic->bus_shift; asic3_mmc_resources[0].end >>= asic->bus_shift;
if (pdata->clock_rate) {
ds1wm_pdata.clock_rate = pdata->clock_rate;
ret = mfd_add_devices(&pdev->dev, pdev->id, ret = mfd_add_devices(&pdev->dev, pdev->id,
&asic3_cell_ds1wm, 1, mem, asic->irq_base); &asic3_cell_ds1wm, 1, mem, asic->irq_base);
if (ret < 0) if (ret < 0)
goto out; goto out;
}
if (mem_sdio && (irq >= 0)) { if (mem_sdio && (irq >= 0)) {
ret = mfd_add_devices(&pdev->dev, pdev->id, ret = mfd_add_devices(&pdev->dev, pdev->id,
...@@ -1000,6 +1019,9 @@ static int __init asic3_probe(struct platform_device *pdev) ...@@ -1000,6 +1019,9 @@ static int __init asic3_probe(struct platform_device *pdev)
asic3_mfd_probe(pdev, pdata, mem); asic3_mfd_probe(pdev, pdata, mem);
asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
(ASIC3_EXTCF_CF0_BUF_EN|ASIC3_EXTCF_CF0_PWAIT_EN), 1);
dev_info(asic->dev, "ASIC3 Core driver\n"); dev_info(asic->dev, "ASIC3 Core driver\n");
return 0; return 0;
...@@ -1021,6 +1043,9 @@ static int __devexit asic3_remove(struct platform_device *pdev) ...@@ -1021,6 +1043,9 @@ static int __devexit asic3_remove(struct platform_device *pdev)
int ret; int ret;
struct asic3 *asic = platform_get_drvdata(pdev); struct asic3 *asic = platform_get_drvdata(pdev);
asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
(ASIC3_EXTCF_CF0_BUF_EN|ASIC3_EXTCF_CF0_PWAIT_EN), 0);
asic3_mfd_remove(pdev); asic3_mfd_remove(pdev);
ret = asic3_gpio_remove(pdev); ret = asic3_gpio_remove(pdev);
......
...@@ -186,18 +186,7 @@ static struct pci_driver cs5535_mfd_driver = { ...@@ -186,18 +186,7 @@ static struct pci_driver cs5535_mfd_driver = {
.remove = __devexit_p(cs5535_mfd_remove), .remove = __devexit_p(cs5535_mfd_remove),
}; };
static int __init cs5535_mfd_init(void) module_pci_driver(cs5535_mfd_driver);
{
return pci_register_driver(&cs5535_mfd_driver);
}
static void __exit cs5535_mfd_exit(void)
{
pci_unregister_driver(&cs5535_mfd_driver);
}
module_init(cs5535_mfd_init);
module_exit(cs5535_mfd_exit);
MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>"); MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
MODULE_DESCRIPTION("MFD driver for CS5535/CS5536 southbridge's ISA PCI device"); MODULE_DESCRIPTION("MFD driver for CS5535/CS5536 southbridge's ISA PCI device");
......
...@@ -318,6 +318,135 @@ static bool da9052_reg_volatile(struct device *dev, unsigned int reg) ...@@ -318,6 +318,135 @@ static bool da9052_reg_volatile(struct device *dev, unsigned int reg)
} }
} }
/*
* TBAT look-up table is computed from the R90 reg (8 bit register)
* reading as below. The battery temperature is in milliCentigrade
* TBAT = (1/(t1+1/298) - 273) * 1000 mC
* where t1 = (1/B)* ln(( ADCval * 2.5)/(R25*ITBAT*255))
* Default values are R25 = 10e3, B = 3380, ITBAT = 50e-6
* Example:
* R25=10E3, B=3380, ITBAT=50e-6, ADCVAL=62d calculates
* TBAT = 20015 mili degrees Centrigrade
*
*/
static const int32_t tbat_lookup[255] = {
183258, 144221, 124334, 111336, 101826, 94397, 88343, 83257,
78889, 75071, 71688, 68656, 65914, 63414, 61120, 59001,
570366, 55204, 53490, 51881, 50364, 48931, 47574, 46285,
45059, 43889, 42772, 41703, 40678, 39694, 38748, 37838,
36961, 36115, 35297, 34507, 33743, 33002, 32284, 31588,
30911, 30254, 29615, 28994, 28389, 27799, 27225, 26664,
26117, 25584, 25062, 24553, 24054, 23567, 23091, 22624,
22167, 21719, 21281, 20851, 20429, 20015, 19610, 19211,
18820, 18436, 18058, 17688, 17323, 16965, 16612, 16266,
15925, 15589, 15259, 14933, 14613, 14298, 13987, 13681,
13379, 13082, 12788, 12499, 12214, 11933, 11655, 11382,
11112, 10845, 10582, 10322, 10066, 9812, 9562, 9315,
9071, 8830, 8591, 8356, 8123, 7893, 7665, 7440,
7218, 6998, 6780, 6565, 6352, 6141, 5933, 5726,
5522, 5320, 5120, 4922, 4726, 4532, 4340, 4149,
3961, 3774, 3589, 3406, 3225, 3045, 2867, 2690,
2516, 2342, 2170, 2000, 1831, 1664, 1498, 1334,
1171, 1009, 849, 690, 532, 376, 221, 67,
-84, -236, -386, -535, -683, -830, -975, -1119,
-1263, -1405, -1546, -1686, -1825, -1964, -2101, -2237,
-2372, -2506, -2639, -2771, -2902, -3033, -3162, -3291,
-3418, -3545, -3671, -3796, -3920, -4044, -4166, -4288,
-4409, -4529, -4649, -4767, -4885, -5002, -5119, -5235,
-5349, -5464, -5577, -5690, -5802, -5913, -6024, -6134,
-6244, -6352, -6461, -6568, -6675, -6781, -6887, -6992,
-7096, -7200, -7303, -7406, -7508, -7609, -7710, -7810,
-7910, -8009, -8108, -8206, -8304, -8401, -8497, -8593,
-8689, -8784, -8878, -8972, -9066, -9159, -9251, -9343,
-9435, -9526, -9617, -9707, -9796, -9886, -9975, -10063,
-10151, -10238, -10325, -10412, -10839, -10923, -11007, -11090,
-11173, -11256, -11338, -11420, -11501, -11583, -11663, -11744,
-11823, -11903, -11982
};
static const u8 chan_mux[DA9052_ADC_VBBAT + 1] = {
[DA9052_ADC_VDDOUT] = DA9052_ADC_MAN_MUXSEL_VDDOUT,
[DA9052_ADC_ICH] = DA9052_ADC_MAN_MUXSEL_ICH,
[DA9052_ADC_TBAT] = DA9052_ADC_MAN_MUXSEL_TBAT,
[DA9052_ADC_VBAT] = DA9052_ADC_MAN_MUXSEL_VBAT,
[DA9052_ADC_IN4] = DA9052_ADC_MAN_MUXSEL_AD4,
[DA9052_ADC_IN5] = DA9052_ADC_MAN_MUXSEL_AD5,
[DA9052_ADC_IN6] = DA9052_ADC_MAN_MUXSEL_AD6,
[DA9052_ADC_VBBAT] = DA9052_ADC_MAN_MUXSEL_VBBAT
};
int da9052_adc_manual_read(struct da9052 *da9052, unsigned char channel)
{
int ret;
unsigned short calc_data;
unsigned short data;
unsigned char mux_sel;
if (channel > DA9052_ADC_VBBAT)
return -EINVAL;
mutex_lock(&da9052->auxadc_lock);
/* Channel gets activated on enabling the Conversion bit */
mux_sel = chan_mux[channel] | DA9052_ADC_MAN_MAN_CONV;
ret = da9052_reg_write(da9052, DA9052_ADC_MAN_REG, mux_sel);
if (ret < 0)
goto err;
/* Wait for an interrupt */
if (!wait_for_completion_timeout(&da9052->done,
msecs_to_jiffies(500))) {
dev_err(da9052->dev,
"timeout waiting for ADC conversion interrupt\n");
ret = -ETIMEDOUT;
goto err;
}
ret = da9052_reg_read(da9052, DA9052_ADC_RES_H_REG);
if (ret < 0)
goto err;
calc_data = (unsigned short)ret;
data = calc_data << 2;
ret = da9052_reg_read(da9052, DA9052_ADC_RES_L_REG);
if (ret < 0)
goto err;
calc_data = (unsigned short)(ret & DA9052_ADC_RES_LSB);
data |= calc_data;
ret = data;
err:
mutex_unlock(&da9052->auxadc_lock);
return ret;
}
EXPORT_SYMBOL_GPL(da9052_adc_manual_read);
static irqreturn_t da9052_auxadc_irq(int irq, void *irq_data)
{
struct da9052 *da9052 = irq_data;
complete(&da9052->done);
return IRQ_HANDLED;
}
int da9052_adc_read_temp(struct da9052 *da9052)
{
int tbat;
tbat = da9052_reg_read(da9052, DA9052_TBAT_RES_REG);
if (tbat <= 0)
return tbat;
/* ARRAY_SIZE check is not needed since TBAT is a 8-bit register */
return tbat_lookup[tbat - 1];
}
EXPORT_SYMBOL_GPL(da9052_adc_read_temp);
static struct resource da9052_rtc_resource = { static struct resource da9052_rtc_resource = {
.name = "ALM", .name = "ALM",
.start = DA9052_IRQ_ALARM, .start = DA9052_IRQ_ALARM,
...@@ -646,6 +775,9 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id) ...@@ -646,6 +775,9 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
struct irq_desc *desc; struct irq_desc *desc;
int ret; int ret;
mutex_init(&da9052->auxadc_lock);
init_completion(&da9052->done);
if (pdata && pdata->init != NULL) if (pdata && pdata->init != NULL)
pdata->init(da9052); pdata->init(da9052);
...@@ -665,6 +797,12 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id) ...@@ -665,6 +797,12 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
da9052->irq_base = regmap_irq_chip_get_base(da9052->irq_data); da9052->irq_base = regmap_irq_chip_get_base(da9052->irq_data);
ret = request_threaded_irq(DA9052_IRQ_ADC_EOM, NULL, da9052_auxadc_irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"adc irq", da9052);
if (ret != 0)
dev_err(da9052->dev, "DA9052 ADC IRQ failed ret=%d\n", ret);
ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info, ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info,
ARRAY_SIZE(da9052_subdev_info), NULL, 0); ARRAY_SIZE(da9052_subdev_info), NULL, 0);
if (ret) if (ret)
...@@ -673,6 +811,7 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id) ...@@ -673,6 +811,7 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
return 0; return 0;
err: err:
free_irq(DA9052_IRQ_ADC_EOM, da9052);
mfd_remove_devices(da9052->dev); mfd_remove_devices(da9052->dev);
regmap_err: regmap_err:
return ret; return ret;
...@@ -680,6 +819,7 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id) ...@@ -680,6 +819,7 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
void da9052_device_exit(struct da9052 *da9052) void da9052_device_exit(struct da9052 *da9052)
{ {
free_irq(DA9052_IRQ_ADC_EOM, da9052);
regmap_del_irq_chip(da9052->chip_irq, da9052->irq_data); regmap_del_irq_chip(da9052->chip_irq, da9052->irq_data);
mfd_remove_devices(da9052->dev); mfd_remove_devices(da9052->dev);
} }
......
...@@ -22,6 +22,11 @@ ...@@ -22,6 +22,11 @@
#include <linux/mfd/da9052/da9052.h> #include <linux/mfd/da9052/da9052.h>
#include <linux/mfd/da9052/reg.h> #include <linux/mfd/da9052/reg.h>
#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_device.h>
#endif
static int da9052_i2c_enable_multiwrite(struct da9052 *da9052) static int da9052_i2c_enable_multiwrite(struct da9052 *da9052)
{ {
int reg_val, ret; int reg_val, ret;
...@@ -41,13 +46,31 @@ static int da9052_i2c_enable_multiwrite(struct da9052 *da9052) ...@@ -41,13 +46,31 @@ static int da9052_i2c_enable_multiwrite(struct da9052 *da9052)
return 0; return 0;
} }
static struct i2c_device_id da9052_i2c_id[] = {
{"da9052", DA9052},
{"da9053-aa", DA9053_AA},
{"da9053-ba", DA9053_BA},
{"da9053-bb", DA9053_BB},
{}
};
#ifdef CONFIG_OF
static const struct of_device_id dialog_dt_ids[] = {
{ .compatible = "dlg,da9052", .data = &da9052_i2c_id[0] },
{ .compatible = "dlg,da9053-aa", .data = &da9052_i2c_id[1] },
{ .compatible = "dlg,da9053-ab", .data = &da9052_i2c_id[2] },
{ .compatible = "dlg,da9053-bb", .data = &da9052_i2c_id[3] },
{ /* sentinel */ }
};
#endif
static int __devinit da9052_i2c_probe(struct i2c_client *client, static int __devinit da9052_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct da9052 *da9052; struct da9052 *da9052;
int ret; int ret;
da9052 = kzalloc(sizeof(struct da9052), GFP_KERNEL); da9052 = devm_kzalloc(&client->dev, sizeof(struct da9052), GFP_KERNEL);
if (!da9052) if (!da9052)
return -ENOMEM; return -ENOMEM;
...@@ -55,8 +78,7 @@ static int __devinit da9052_i2c_probe(struct i2c_client *client, ...@@ -55,8 +78,7 @@ static int __devinit da9052_i2c_probe(struct i2c_client *client,
I2C_FUNC_SMBUS_BYTE_DATA)) { I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_info(&client->dev, "Error in %s:i2c_check_functionality\n", dev_info(&client->dev, "Error in %s:i2c_check_functionality\n",
__func__); __func__);
ret = -ENODEV; return -ENODEV;
goto err;
} }
da9052->dev = &client->dev; da9052->dev = &client->dev;
...@@ -64,29 +86,39 @@ static int __devinit da9052_i2c_probe(struct i2c_client *client, ...@@ -64,29 +86,39 @@ static int __devinit da9052_i2c_probe(struct i2c_client *client,
i2c_set_clientdata(client, da9052); i2c_set_clientdata(client, da9052);
da9052->regmap = regmap_init_i2c(client, &da9052_regmap_config); da9052->regmap = devm_regmap_init_i2c(client, &da9052_regmap_config);
if (IS_ERR(da9052->regmap)) { if (IS_ERR(da9052->regmap)) {
ret = PTR_ERR(da9052->regmap); ret = PTR_ERR(da9052->regmap);
dev_err(&client->dev, "Failed to allocate register map: %d\n", dev_err(&client->dev, "Failed to allocate register map: %d\n",
ret); ret);
goto err; return ret;
} }
ret = da9052_i2c_enable_multiwrite(da9052); ret = da9052_i2c_enable_multiwrite(da9052);
if (ret < 0) if (ret < 0)
goto err_regmap; return ret;
#ifdef CONFIG_OF
if (!id) {
struct device_node *np = client->dev.of_node;
const struct of_device_id *deviceid;
deviceid = of_match_node(dialog_dt_ids, np);
id = (const struct i2c_device_id *)deviceid->data;
}
#endif
if (!id) {
ret = -ENODEV;
dev_err(&client->dev, "id is null.\n");
return ret;
}
ret = da9052_device_init(da9052, id->driver_data); ret = da9052_device_init(da9052, id->driver_data);
if (ret != 0) if (ret != 0)
goto err_regmap; return ret;
return 0; return 0;
err_regmap:
regmap_exit(da9052->regmap);
err:
kfree(da9052);
return ret;
} }
static int __devexit da9052_i2c_remove(struct i2c_client *client) static int __devexit da9052_i2c_remove(struct i2c_client *client)
...@@ -94,20 +126,9 @@ static int __devexit da9052_i2c_remove(struct i2c_client *client) ...@@ -94,20 +126,9 @@ static int __devexit da9052_i2c_remove(struct i2c_client *client)
struct da9052 *da9052 = i2c_get_clientdata(client); struct da9052 *da9052 = i2c_get_clientdata(client);
da9052_device_exit(da9052); da9052_device_exit(da9052);
regmap_exit(da9052->regmap);
kfree(da9052);
return 0; return 0;
} }
static struct i2c_device_id da9052_i2c_id[] = {
{"da9052", DA9052},
{"da9053-aa", DA9053_AA},
{"da9053-ba", DA9053_BA},
{"da9053-bb", DA9053_BB},
{}
};
static struct i2c_driver da9052_i2c_driver = { static struct i2c_driver da9052_i2c_driver = {
.probe = da9052_i2c_probe, .probe = da9052_i2c_probe,
.remove = __devexit_p(da9052_i2c_remove), .remove = __devexit_p(da9052_i2c_remove),
...@@ -115,6 +136,9 @@ static struct i2c_driver da9052_i2c_driver = { ...@@ -115,6 +136,9 @@ static struct i2c_driver da9052_i2c_driver = {
.driver = { .driver = {
.name = "da9052", .name = "da9052",
.owner = THIS_MODULE, .owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = dialog_dt_ids,
#endif
}, },
}; };
......
...@@ -25,8 +25,9 @@ static int __devinit da9052_spi_probe(struct spi_device *spi) ...@@ -25,8 +25,9 @@ static int __devinit da9052_spi_probe(struct spi_device *spi)
{ {
int ret; int ret;
const struct spi_device_id *id = spi_get_device_id(spi); const struct spi_device_id *id = spi_get_device_id(spi);
struct da9052 *da9052 = kzalloc(sizeof(struct da9052), GFP_KERNEL); struct da9052 *da9052;
da9052 = devm_kzalloc(&spi->dev, sizeof(struct da9052), GFP_KERNEL);
if (!da9052) if (!da9052)
return -ENOMEM; return -ENOMEM;
...@@ -42,25 +43,19 @@ static int __devinit da9052_spi_probe(struct spi_device *spi) ...@@ -42,25 +43,19 @@ static int __devinit da9052_spi_probe(struct spi_device *spi)
da9052_regmap_config.read_flag_mask = 1; da9052_regmap_config.read_flag_mask = 1;
da9052_regmap_config.write_flag_mask = 0; da9052_regmap_config.write_flag_mask = 0;
da9052->regmap = regmap_init_spi(spi, &da9052_regmap_config); da9052->regmap = devm_regmap_init_spi(spi, &da9052_regmap_config);
if (IS_ERR(da9052->regmap)) { if (IS_ERR(da9052->regmap)) {
ret = PTR_ERR(da9052->regmap); ret = PTR_ERR(da9052->regmap);
dev_err(&spi->dev, "Failed to allocate register map: %d\n", dev_err(&spi->dev, "Failed to allocate register map: %d\n",
ret); ret);
goto err; return ret;
} }
ret = da9052_device_init(da9052, id->driver_data); ret = da9052_device_init(da9052, id->driver_data);
if (ret != 0) if (ret != 0)
goto err_regmap; return ret;
return 0; return 0;
err_regmap:
regmap_exit(da9052->regmap);
err:
kfree(da9052);
return ret;
} }
static int __devexit da9052_spi_remove(struct spi_device *spi) static int __devexit da9052_spi_remove(struct spi_device *spi)
...@@ -68,9 +63,6 @@ static int __devexit da9052_spi_remove(struct spi_device *spi) ...@@ -68,9 +63,6 @@ static int __devexit da9052_spi_remove(struct spi_device *spi)
struct da9052 *da9052 = dev_get_drvdata(&spi->dev); struct da9052 *da9052 = dev_get_drvdata(&spi->dev);
da9052_device_exit(da9052); da9052_device_exit(da9052);
regmap_exit(da9052->regmap);
kfree(da9052);
return 0; return 0;
} }
...@@ -88,7 +80,6 @@ static struct spi_driver da9052_spi_driver = { ...@@ -88,7 +80,6 @@ static struct spi_driver da9052_spi_driver = {
.id_table = da9052_spi_id, .id_table = da9052_spi_id,
.driver = { .driver = {
.name = "da9052", .name = "da9052",
.bus = &spi_bus_type,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
}; };
......
...@@ -2720,6 +2720,7 @@ static struct regulator_consumer_supply db8500_vape_consumers[] = { ...@@ -2720,6 +2720,7 @@ static struct regulator_consumer_supply db8500_vape_consumers[] = {
REGULATOR_SUPPLY("v-i2c", "nmk-i2c.1"), REGULATOR_SUPPLY("v-i2c", "nmk-i2c.1"),
REGULATOR_SUPPLY("v-i2c", "nmk-i2c.2"), REGULATOR_SUPPLY("v-i2c", "nmk-i2c.2"),
REGULATOR_SUPPLY("v-i2c", "nmk-i2c.3"), REGULATOR_SUPPLY("v-i2c", "nmk-i2c.3"),
REGULATOR_SUPPLY("v-i2c", "nmk-i2c.4"),
/* "v-mmc" changed to "vcore" in the mainline kernel */ /* "v-mmc" changed to "vcore" in the mainline kernel */
REGULATOR_SUPPLY("vcore", "sdi0"), REGULATOR_SUPPLY("vcore", "sdi0"),
REGULATOR_SUPPLY("vcore", "sdi1"), REGULATOR_SUPPLY("vcore", "sdi1"),
...@@ -2958,9 +2959,10 @@ static struct mfd_cell db8500_prcmu_devs[] = { ...@@ -2958,9 +2959,10 @@ static struct mfd_cell db8500_prcmu_devs[] = {
* prcmu_fw_init - arch init call for the Linux PRCMU fw init logic * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic
* *
*/ */
static int __init db8500_prcmu_probe(struct platform_device *pdev) static int __devinit db8500_prcmu_probe(struct platform_device *pdev)
{ {
int err = 0; struct device_node *np = pdev->dev.of_node;
int irq = 0, err = 0;
if (ux500_is_svp()) if (ux500_is_svp())
return -ENODEV; return -ENODEV;
...@@ -2970,7 +2972,13 @@ static int __init db8500_prcmu_probe(struct platform_device *pdev) ...@@ -2970,7 +2972,13 @@ static int __init db8500_prcmu_probe(struct platform_device *pdev)
/* Clean up the mailbox interrupts after pre-kernel code. */ /* Clean up the mailbox interrupts after pre-kernel code. */
writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR); writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
err = request_threaded_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, if (np)
irq = platform_get_irq(pdev, 0);
if (!np || irq <= 0)
irq = IRQ_DB8500_PRCMU1;
err = request_threaded_irq(irq, prcmu_irq_handler,
prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL); prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL);
if (err < 0) { if (err < 0) {
pr_err("prcmu: Failed to allocate IRQ_DB8500_PRCMU1.\n"); pr_err("prcmu: Failed to allocate IRQ_DB8500_PRCMU1.\n");
...@@ -2981,13 +2989,15 @@ static int __init db8500_prcmu_probe(struct platform_device *pdev) ...@@ -2981,13 +2989,15 @@ static int __init db8500_prcmu_probe(struct platform_device *pdev)
if (cpu_is_u8500v20_or_later()) if (cpu_is_u8500v20_or_later())
prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
if (!np) {
err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs, err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs,
ARRAY_SIZE(db8500_prcmu_devs), NULL, ARRAY_SIZE(db8500_prcmu_devs), NULL, 0);
0); if (err) {
if (err)
pr_err("prcmu: Failed to add subdevices\n"); pr_err("prcmu: Failed to add subdevices\n");
else return err;
}
}
pr_info("DB8500 PRCMU initialized\n"); pr_info("DB8500 PRCMU initialized\n");
no_irq_return: no_irq_return:
...@@ -2999,11 +3009,12 @@ static struct platform_driver db8500_prcmu_driver = { ...@@ -2999,11 +3009,12 @@ static struct platform_driver db8500_prcmu_driver = {
.name = "db8500-prcmu", .name = "db8500-prcmu",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = db8500_prcmu_probe,
}; };
static int __init db8500_prcmu_init(void) static int __init db8500_prcmu_init(void)
{ {
return platform_driver_probe(&db8500_prcmu_driver, db8500_prcmu_probe); return platform_driver_register(&db8500_prcmu_driver);
} }
arch_initcall(db8500_prcmu_init); arch_initcall(db8500_prcmu_init);
......
...@@ -406,7 +406,7 @@ static int __devinit intel_msic_probe(struct platform_device *pdev) ...@@ -406,7 +406,7 @@ static int __devinit intel_msic_probe(struct platform_device *pdev)
return -ENXIO; return -ENXIO;
} }
msic = kzalloc(sizeof(*msic), GFP_KERNEL); msic = devm_kzalloc(&pdev->dev, sizeof(*msic), GFP_KERNEL);
if (!msic) if (!msic)
return -ENOMEM; return -ENOMEM;
...@@ -421,21 +421,13 @@ static int __devinit intel_msic_probe(struct platform_device *pdev) ...@@ -421,21 +421,13 @@ static int __devinit intel_msic_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res) {
dev_err(&pdev->dev, "failed to get SRAM iomem resource\n"); dev_err(&pdev->dev, "failed to get SRAM iomem resource\n");
ret = -ENODEV; return -ENODEV;
goto fail_free_msic;
} }
res = request_mem_region(res->start, resource_size(res), pdev->name); msic->irq_base = devm_request_and_ioremap(&pdev->dev, res);
if (!res) {
ret = -EBUSY;
goto fail_free_msic;
}
msic->irq_base = ioremap_nocache(res->start, resource_size(res));
if (!msic->irq_base) { if (!msic->irq_base) {
dev_err(&pdev->dev, "failed to map SRAM memory\n"); dev_err(&pdev->dev, "failed to map SRAM memory\n");
ret = -ENOMEM; return -ENOMEM;
goto fail_release_region;
} }
platform_set_drvdata(pdev, msic); platform_set_drvdata(pdev, msic);
...@@ -443,7 +435,7 @@ static int __devinit intel_msic_probe(struct platform_device *pdev) ...@@ -443,7 +435,7 @@ static int __devinit intel_msic_probe(struct platform_device *pdev)
ret = intel_msic_init_devices(msic); ret = intel_msic_init_devices(msic);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to initialize MSIC devices\n"); dev_err(&pdev->dev, "failed to initialize MSIC devices\n");
goto fail_unmap_mem; return ret;
} }
dev_info(&pdev->dev, "Intel MSIC version %c%d (vendor %#x)\n", dev_info(&pdev->dev, "Intel MSIC version %c%d (vendor %#x)\n",
...@@ -451,27 +443,14 @@ static int __devinit intel_msic_probe(struct platform_device *pdev) ...@@ -451,27 +443,14 @@ static int __devinit intel_msic_probe(struct platform_device *pdev)
msic->vendor); msic->vendor);
return 0; return 0;
fail_unmap_mem:
iounmap(msic->irq_base);
fail_release_region:
release_mem_region(res->start, resource_size(res));
fail_free_msic:
kfree(msic);
return ret;
} }
static int __devexit intel_msic_remove(struct platform_device *pdev) static int __devexit intel_msic_remove(struct platform_device *pdev)
{ {
struct intel_msic *msic = platform_get_drvdata(pdev); struct intel_msic *msic = platform_get_drvdata(pdev);
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
intel_msic_remove_devices(msic); intel_msic_remove_devices(msic);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
iounmap(msic->irq_base);
release_mem_region(res->start, resource_size(res));
kfree(msic);
return 0; return 0;
} }
......
...@@ -283,23 +283,8 @@ static struct pci_driver cmodio_pci_driver = { ...@@ -283,23 +283,8 @@ static struct pci_driver cmodio_pci_driver = {
.remove = __devexit_p(cmodio_pci_remove), .remove = __devexit_p(cmodio_pci_remove),
}; };
/* module_pci_driver(cmodio_pci_driver);
* Module Init / Exit
*/
static int __init cmodio_init(void)
{
return pci_register_driver(&cmodio_pci_driver);
}
static void __exit cmodio_exit(void)
{
pci_unregister_driver(&cmodio_pci_driver);
}
MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>"); MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
MODULE_DESCRIPTION("Janz CMOD-IO PCI MODULbus Carrier Board Driver"); MODULE_DESCRIPTION("Janz CMOD-IO PCI MODULbus Carrier Board Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_init(cmodio_init);
module_exit(cmodio_exit);
This diff is collapsed.
/*
* lm3533-ctrlbank.c -- LM3533 Generic Control Bank interface
*
* Copyright (C) 2011-2012 Texas Instruments
*
* Author: Johan Hovold <jhovold@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/mfd/lm3533.h>
#define LM3533_MAX_CURRENT_MIN 5000
#define LM3533_MAX_CURRENT_MAX 29800
#define LM3533_MAX_CURRENT_STEP 800
#define LM3533_BRIGHTNESS_MAX 255
#define LM3533_PWM_MAX 0x3f
#define LM3533_REG_PWM_BASE 0x14
#define LM3533_REG_MAX_CURRENT_BASE 0x1f
#define LM3533_REG_CTRLBANK_ENABLE 0x27
#define LM3533_REG_BRIGHTNESS_BASE 0x40
static inline u8 lm3533_ctrlbank_get_reg(struct lm3533_ctrlbank *cb, u8 base)
{
return base + cb->id;
}
int lm3533_ctrlbank_enable(struct lm3533_ctrlbank *cb)
{
u8 mask;
int ret;
dev_dbg(cb->dev, "%s - %d\n", __func__, cb->id);
mask = 1 << cb->id;
ret = lm3533_update(cb->lm3533, LM3533_REG_CTRLBANK_ENABLE,
mask, mask);
if (ret)
dev_err(cb->dev, "failed to enable ctrlbank %d\n", cb->id);
return ret;
}
EXPORT_SYMBOL_GPL(lm3533_ctrlbank_enable);
int lm3533_ctrlbank_disable(struct lm3533_ctrlbank *cb)
{
u8 mask;
int ret;
dev_dbg(cb->dev, "%s - %d\n", __func__, cb->id);
mask = 1 << cb->id;
ret = lm3533_update(cb->lm3533, LM3533_REG_CTRLBANK_ENABLE, 0, mask);
if (ret)
dev_err(cb->dev, "failed to disable ctrlbank %d\n", cb->id);
return ret;
}
EXPORT_SYMBOL_GPL(lm3533_ctrlbank_disable);
/*
* Full-scale current.
*
* imax 5000 - 29800 uA (800 uA step)
*/
int lm3533_ctrlbank_set_max_current(struct lm3533_ctrlbank *cb, u16 imax)
{
u8 reg;
u8 val;
int ret;
if (imax < LM3533_MAX_CURRENT_MIN || imax > LM3533_MAX_CURRENT_MAX)
return -EINVAL;
val = (imax - LM3533_MAX_CURRENT_MIN) / LM3533_MAX_CURRENT_STEP;
reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_MAX_CURRENT_BASE);
ret = lm3533_write(cb->lm3533, reg, val);
if (ret)
dev_err(cb->dev, "failed to set max current\n");
return ret;
}
EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_max_current);
#define lm3533_ctrlbank_set(_name, _NAME) \
int lm3533_ctrlbank_set_##_name(struct lm3533_ctrlbank *cb, u8 val) \
{ \
u8 reg; \
int ret; \
\
if (val > LM3533_##_NAME##_MAX) \
return -EINVAL; \
\
reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_##_NAME##_BASE); \
ret = lm3533_write(cb->lm3533, reg, val); \
if (ret) \
dev_err(cb->dev, "failed to set " #_name "\n"); \
\
return ret; \
} \
EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_##_name);
#define lm3533_ctrlbank_get(_name, _NAME) \
int lm3533_ctrlbank_get_##_name(struct lm3533_ctrlbank *cb, u8 *val) \
{ \
u8 reg; \
int ret; \
\
reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_##_NAME##_BASE); \
ret = lm3533_read(cb->lm3533, reg, val); \
if (ret) \
dev_err(cb->dev, "failed to get " #_name "\n"); \
\
return ret; \
} \
EXPORT_SYMBOL_GPL(lm3533_ctrlbank_get_##_name);
lm3533_ctrlbank_set(brightness, BRIGHTNESS);
lm3533_ctrlbank_get(brightness, BRIGHTNESS);
/*
* PWM-input control mask:
*
* bit 5 - PWM-input enabled in Zone 4
* bit 4 - PWM-input enabled in Zone 3
* bit 3 - PWM-input enabled in Zone 2
* bit 2 - PWM-input enabled in Zone 1
* bit 1 - PWM-input enabled in Zone 0
* bit 0 - PWM-input enabled
*/
lm3533_ctrlbank_set(pwm, PWM);
lm3533_ctrlbank_get(pwm, PWM);
MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
MODULE_DESCRIPTION("LM3533 Control Bank interface");
MODULE_LICENSE("GPL");
This diff is collapsed.
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#define GPIOBASE 0x44 #define GPIOBASE 0x44
#define GPIO_IO_SIZE 64 #define GPIO_IO_SIZE 64
#define GPIO_IO_SIZE_CENTERTON 128
#define WDTBASE 0x84 #define WDTBASE 0x84
#define WDT_IO_SIZE 64 #define WDT_IO_SIZE 64
...@@ -68,7 +69,7 @@ static struct resource wdt_sch_resource = { ...@@ -68,7 +69,7 @@ static struct resource wdt_sch_resource = {
static struct mfd_cell tunnelcreek_cells[] = { static struct mfd_cell tunnelcreek_cells[] = {
{ {
.name = "tunnelcreek_wdt", .name = "ie6xx_wdt",
.num_resources = 1, .num_resources = 1,
.resources = &wdt_sch_resource, .resources = &wdt_sch_resource,
}, },
...@@ -77,6 +78,7 @@ static struct mfd_cell tunnelcreek_cells[] = { ...@@ -77,6 +78,7 @@ static struct mfd_cell tunnelcreek_cells[] = {
static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = { static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CENTERTON_ILB) },
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE(pci, lpc_sch_ids); MODULE_DEVICE_TABLE(pci, lpc_sch_ids);
...@@ -115,6 +117,10 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev, ...@@ -115,6 +117,10 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,
} }
gpio_sch_resource.start = base_addr; gpio_sch_resource.start = base_addr;
if (id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB)
gpio_sch_resource.end = base_addr + GPIO_IO_SIZE_CENTERTON - 1;
else
gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1; gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1;
for (i=0; i < ARRAY_SIZE(lpc_sch_cells); i++) for (i=0; i < ARRAY_SIZE(lpc_sch_cells); i++)
...@@ -125,7 +131,8 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev, ...@@ -125,7 +131,8 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,
if (ret) if (ret)
goto out_dev; goto out_dev;
if (id->device == PCI_DEVICE_ID_INTEL_ITC_LPC) { if (id->device == PCI_DEVICE_ID_INTEL_ITC_LPC
|| id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) {
pci_read_config_dword(dev, WDTBASE, &base_addr_cfg); pci_read_config_dword(dev, WDTBASE, &base_addr_cfg);
if (!(base_addr_cfg & (1 << 31))) { if (!(base_addr_cfg & (1 << 31))) {
dev_err(&dev->dev, "Decode of the WDT I/O range disabled\n"); dev_err(&dev->dev, "Decode of the WDT I/O range disabled\n");
...@@ -167,18 +174,7 @@ static struct pci_driver lpc_sch_driver = { ...@@ -167,18 +174,7 @@ static struct pci_driver lpc_sch_driver = {
.remove = __devexit_p(lpc_sch_remove), .remove = __devexit_p(lpc_sch_remove),
}; };
static int __init lpc_sch_init(void) module_pci_driver(lpc_sch_driver);
{
return pci_register_driver(&lpc_sch_driver);
}
static void __exit lpc_sch_exit(void)
{
pci_unregister_driver(&lpc_sch_driver);
}
module_init(lpc_sch_init);
module_exit(lpc_sch_exit);
MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>"); MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
MODULE_DESCRIPTION("LPC interface for Intel Poulsbo SCH"); MODULE_DESCRIPTION("LPC interface for Intel Poulsbo SCH");
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright 2009-2010 Creative Product Design
* Marc Reilly marc@cpdesign.com.au
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/mfd/core.h>
#include <linux/mfd/mc13xxx.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include "mc13xxx.h"
static const struct i2c_device_id mc13xxx_i2c_device_id[] = {
{
.name = "mc13892",
.driver_data = MC13XXX_ID_MC13892,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(i2c, mc13xxx_i2c_device_id);
static const struct of_device_id mc13xxx_dt_ids[] = {
{
.compatible = "fsl,mc13892",
.data = (void *) &mc13xxx_i2c_device_id[0],
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, mc13xxx_dt_ids);
static struct regmap_config mc13xxx_regmap_i2c_config = {
.reg_bits = 8,
.val_bits = 24,
.max_register = MC13XXX_NUMREGS,
.cache_type = REGCACHE_NONE,
};
static int mc13xxx_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
const struct of_device_id *of_id;
struct i2c_driver *idrv = to_i2c_driver(client->dev.driver);
struct mc13xxx *mc13xxx;
struct mc13xxx_platform_data *pdata = dev_get_platdata(&client->dev);
int ret;
of_id = of_match_device(mc13xxx_dt_ids, &client->dev);
if (of_id)
idrv->id_table = (const struct i2c_device_id*) of_id->data;
mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL);
if (!mc13xxx)
return -ENOMEM;
dev_set_drvdata(&client->dev, mc13xxx);
mc13xxx->dev = &client->dev;
mutex_init(&mc13xxx->lock);
mc13xxx->regmap = regmap_init_i2c(client, &mc13xxx_regmap_i2c_config);
if (IS_ERR(mc13xxx->regmap)) {
ret = PTR_ERR(mc13xxx->regmap);
dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",
ret);
dev_set_drvdata(&client->dev, NULL);
kfree(mc13xxx);
return ret;
}
ret = mc13xxx_common_init(mc13xxx, pdata, client->irq);
if (ret == 0 && (id->driver_data != mc13xxx->ictype))
dev_warn(mc13xxx->dev,
"device id doesn't match auto detection!\n");
return ret;
}
static int __devexit mc13xxx_i2c_remove(struct i2c_client *client)
{
struct mc13xxx *mc13xxx = dev_get_drvdata(&client->dev);
mc13xxx_common_cleanup(mc13xxx);
return 0;
}
static struct i2c_driver mc13xxx_i2c_driver = {
.id_table = mc13xxx_i2c_device_id,
.driver = {
.owner = THIS_MODULE,
.name = "mc13xxx",
.of_match_table = mc13xxx_dt_ids,
},
.probe = mc13xxx_i2c_probe,
.remove = __devexit_p(mc13xxx_i2c_remove),
};
static int __init mc13xxx_i2c_init(void)
{
return i2c_add_driver(&mc13xxx_i2c_driver);
}
subsys_initcall(mc13xxx_i2c_init);
static void __exit mc13xxx_i2c_exit(void)
{
i2c_del_driver(&mc13xxx_i2c_driver);
}
module_exit(mc13xxx_i2c_exit);
MODULE_DESCRIPTION("i2c driver for Freescale MC13XXX PMIC");
MODULE_AUTHOR("Marc Reilly <marc@cpdesign.com.au");
MODULE_LICENSE("GPL v2");
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.
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.
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