Commit a6a1d648 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6

* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (90 commits)
  mfd: Push byte swaps out of wm8994 bulk read path
  mfd: Rename ab8500 gpadc header
  mfd: Constify WM8994 write path
  mfd: Push byte swap out of WM8994 bulk I/O
  mfd: Avoid copying data in WM8994 I2C write
  mfd: Remove copy from WM831x I2C write function
  mfd: Staticise WM8994 PM ops
  regulator: Add a subdriver for TI TPS6105x regulator portions v2
  mfd: Add a core driver for TI TPS61050/TPS61052 chips v2
  gpio: Add Tunnel Creek support to sch_gpio
  mfd: Add Tunnel Creek support to lpc_sch
  pci_ids: Add Intel Tunnel Creek LPC Bridge device ID.
  regulator: MAX8997/8966 support
  mfd: Add WM8994 bulk register write operation
  mfd: Append additional read write on 88pm860x
  mfd: Adopt mfd_data in 88pm860x input driver
  mfd: Adopt mfd_data in 88pm860x regulator
  mfd: Adopt mfd_data in 88pm860x led
  mfd: Adopt mfd_data in 88pm860x backlight
  mfd: Fix MAX8997 Kconfig entry typos
  ...
parents 1b506cfb 316b6cc0
Kernel driver twl4030-madc
=========================
Supported chips:
* Texas Instruments TWL4030
Prefix: 'twl4030-madc'
Authors:
J Keerthy <j-keerthy@ti.com>
Description
-----------
The Texas Instruments TWL4030 is a Power Management and Audio Circuit. Among
other things it contains a 10-bit A/D converter MADC. The converter has 16
channels which can be used in different modes.
See this table for the meaning of the different channels
Channel Signal
------------------------------------------
0 Battery type(BTYPE)
1 BCI: Battery temperature (BTEMP)
2 GP analog input
3 GP analog input
4 GP analog input
5 GP analog input
6 GP analog input
7 GP analog input
8 BCI: VBUS voltage(VBUS)
9 Backup Battery voltage (VBKP)
10 BCI: Battery charger current (ICHG)
11 BCI: Battery charger voltage (VCHG)
12 BCI: Main battery voltage (VBAT)
13 Reserved
14 Reserved
15 VRUSB Supply/Speaker left/Speaker right polarization level
The Sysfs nodes will represent the voltage in the units of mV,
the temperature channel shows the converted temperature in
degree celcius. The Battery charging current channel represents
battery charging current in mA.
...@@ -232,10 +232,13 @@ static struct mc13xxx_regulator_init_data mx27_3ds_regulators[] = { ...@@ -232,10 +232,13 @@ static struct mc13xxx_regulator_init_data mx27_3ds_regulators[] = {
}; };
/* MC13783 */ /* MC13783 */
static struct mc13xxx_platform_data mc13783_pdata __initdata = { static struct mc13xxx_platform_data mc13783_pdata = {
.regulators = {
.regulators = mx27_3ds_regulators, .regulators = mx27_3ds_regulators,
.num_regulators = ARRAY_SIZE(mx27_3ds_regulators), .num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
.flags = MC13XXX_USE_REGULATOR,
},
.flags = MC13783_USE_REGULATOR,
}; };
/* SPI */ /* SPI */
......
...@@ -263,10 +263,12 @@ static struct mc13xxx_regulator_init_data pcm038_regulators[] = { ...@@ -263,10 +263,12 @@ static struct mc13xxx_regulator_init_data pcm038_regulators[] = {
}; };
static struct mc13xxx_platform_data pcm038_pmic = { static struct mc13xxx_platform_data pcm038_pmic = {
.regulators = {
.regulators = pcm038_regulators, .regulators = pcm038_regulators,
.num_regulators = ARRAY_SIZE(pcm038_regulators), .num_regulators = ARRAY_SIZE(pcm038_regulators),
.flags = MC13XXX_USE_ADC | MC13XXX_USE_REGULATOR | },
MC13XXX_USE_TOUCHSCREEN, .flags = MC13783_USE_ADC | MC13783_USE_REGULATOR |
MC13783_USE_TOUCHSCREEN,
}; };
static struct spi_board_info pcm038_spi_board_info[] __initdata = { static struct spi_board_info pcm038_spi_board_info[] __initdata = {
......
...@@ -488,10 +488,12 @@ static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = { ...@@ -488,10 +488,12 @@ static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = {
}; };
/* MC13783 */ /* MC13783 */
static struct mc13xxx_platform_data mc13783_pdata __initdata = { static struct mc13xxx_platform_data mc13783_pdata = {
.regulators = {
.regulators = mx31_3ds_regulators, .regulators = mx31_3ds_regulators,
.num_regulators = ARRAY_SIZE(mx31_3ds_regulators), .num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
.flags = MC13XXX_USE_REGULATOR | MC13XXX_USE_TOUCHSCREEN },
.flags = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN,
}; };
/* SPI */ /* SPI */
......
...@@ -268,8 +268,10 @@ static struct mc13783_leds_platform_data moboard_leds = { ...@@ -268,8 +268,10 @@ static struct mc13783_leds_platform_data moboard_leds = {
}; };
static struct mc13xxx_platform_data moboard_pmic = { static struct mc13xxx_platform_data moboard_pmic = {
.regulators = {
.regulators = moboard_regulators, .regulators = moboard_regulators,
.num_regulators = ARRAY_SIZE(moboard_regulators), .num_regulators = ARRAY_SIZE(moboard_regulators),
},
.leds = &moboard_leds, .leds = &moboard_leds,
.flags = MC13XXX_USE_REGULATOR | MC13XXX_USE_RTC | .flags = MC13XXX_USE_REGULATOR | MC13XXX_USE_RTC |
MC13XXX_USE_ADC | MC13XXX_USE_LED, MC13XXX_USE_ADC | MC13XXX_USE_LED,
......
...@@ -550,6 +550,12 @@ static struct regulator_init_data sdp4430_vusb = { ...@@ -550,6 +550,12 @@ static struct regulator_init_data sdp4430_vusb = {
}, },
}; };
static struct regulator_init_data sdp4430_clk32kg = {
.constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
};
static struct twl4030_platform_data sdp4430_twldata = { static struct twl4030_platform_data sdp4430_twldata = {
.irq_base = TWL6030_IRQ_BASE, .irq_base = TWL6030_IRQ_BASE,
.irq_end = TWL6030_IRQ_END, .irq_end = TWL6030_IRQ_END,
...@@ -565,6 +571,7 @@ static struct twl4030_platform_data sdp4430_twldata = { ...@@ -565,6 +571,7 @@ static struct twl4030_platform_data sdp4430_twldata = {
.vaux1 = &sdp4430_vaux1, .vaux1 = &sdp4430_vaux1,
.vaux2 = &sdp4430_vaux2, .vaux2 = &sdp4430_vaux2,
.vaux3 = &sdp4430_vaux3, .vaux3 = &sdp4430_vaux3,
.clk32kg = &sdp4430_clk32kg,
.usb = &omap4_usbphy_data .usb = &omap4_usbphy_data
}; };
......
...@@ -411,6 +411,12 @@ static struct regulator_init_data omap4_panda_vusb = { ...@@ -411,6 +411,12 @@ static struct regulator_init_data omap4_panda_vusb = {
}, },
}; };
static struct regulator_init_data omap4_panda_clk32kg = {
.constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
};
static struct twl4030_platform_data omap4_panda_twldata = { static struct twl4030_platform_data omap4_panda_twldata = {
.irq_base = TWL6030_IRQ_BASE, .irq_base = TWL6030_IRQ_BASE,
.irq_end = TWL6030_IRQ_END, .irq_end = TWL6030_IRQ_END,
...@@ -426,6 +432,7 @@ static struct twl4030_platform_data omap4_panda_twldata = { ...@@ -426,6 +432,7 @@ static struct twl4030_platform_data omap4_panda_twldata = {
.vaux1 = &omap4_panda_vaux1, .vaux1 = &omap4_panda_vaux1,
.vaux2 = &omap4_panda_vaux2, .vaux2 = &omap4_panda_vaux2,
.vaux3 = &omap4_panda_vaux3, .vaux3 = &omap4_panda_vaux3,
.clk32kg = &omap4_panda_clk32kg,
.usb = &omap4_usbphy_data, .usb = &omap4_usbphy_data,
}; };
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/mfd/core.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/olpc.h> #include <asm/olpc.h>
...@@ -56,25 +57,24 @@ static void xo1_power_off(void) ...@@ -56,25 +57,24 @@ static void xo1_power_off(void)
static int __devinit olpc_xo1_probe(struct platform_device *pdev) static int __devinit olpc_xo1_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
int err;
/* don't run on non-XOs */ /* don't run on non-XOs */
if (!machine_is_olpc()) if (!machine_is_olpc())
return -ENODEV; return -ENODEV;
err = mfd_cell_enable(pdev);
if (err)
return err;
res = platform_get_resource(pdev, IORESOURCE_IO, 0); res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!res) { if (!res) {
dev_err(&pdev->dev, "can't fetch device resource info\n"); dev_err(&pdev->dev, "can't fetch device resource info\n");
return -EIO; return -EIO;
} }
if (strcmp(pdev->name, "olpc-xo1-pms") == 0)
if (!request_region(res->start, resource_size(res), DRV_NAME)) {
dev_err(&pdev->dev, "can't request region\n");
return -EIO;
}
if (strcmp(pdev->name, "cs5535-pms") == 0)
pms_base = res->start; pms_base = res->start;
else if (strcmp(pdev->name, "cs5535-acpi") == 0) else if (strcmp(pdev->name, "olpc-xo1-ac-acpi") == 0)
acpi_base = res->start; acpi_base = res->start;
/* If we have both addresses, we can override the poweroff hook */ /* If we have both addresses, we can override the poweroff hook */
...@@ -88,14 +88,11 @@ static int __devinit olpc_xo1_probe(struct platform_device *pdev) ...@@ -88,14 +88,11 @@ static int __devinit olpc_xo1_probe(struct platform_device *pdev)
static int __devexit olpc_xo1_remove(struct platform_device *pdev) static int __devexit olpc_xo1_remove(struct platform_device *pdev)
{ {
struct resource *r; mfd_cell_disable(pdev);
r = platform_get_resource(pdev, IORESOURCE_IO, 0);
release_region(r->start, resource_size(r));
if (strcmp(pdev->name, "cs5535-pms") == 0) if (strcmp(pdev->name, "olpc-xo1-pms") == 0)
pms_base = 0; pms_base = 0;
else if (strcmp(pdev->name, "cs5535-acpi") == 0) else if (strcmp(pdev->name, "olpc-xo1-acpi") == 0)
acpi_base = 0; acpi_base = 0;
pm_power_off = NULL; pm_power_off = NULL;
...@@ -104,7 +101,7 @@ static int __devexit olpc_xo1_remove(struct platform_device *pdev) ...@@ -104,7 +101,7 @@ static int __devexit olpc_xo1_remove(struct platform_device *pdev)
static struct platform_driver cs5535_pms_drv = { static struct platform_driver cs5535_pms_drv = {
.driver = { .driver = {
.name = "cs5535-pms", .name = "olpc-xo1-pms",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = olpc_xo1_probe, .probe = olpc_xo1_probe,
...@@ -113,7 +110,7 @@ static struct platform_driver cs5535_pms_drv = { ...@@ -113,7 +110,7 @@ static struct platform_driver cs5535_pms_drv = {
static struct platform_driver cs5535_acpi_drv = { static struct platform_driver cs5535_acpi_drv = {
.driver = { .driver = {
.name = "cs5535-acpi", .name = "olpc-xo1-acpi",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = olpc_xo1_probe, .probe = olpc_xo1_probe,
...@@ -124,26 +121,27 @@ static int __init olpc_xo1_init(void) ...@@ -124,26 +121,27 @@ static int __init olpc_xo1_init(void)
{ {
int r; int r;
r = platform_driver_register(&cs5535_pms_drv); r = mfd_shared_platform_driver_register(&cs5535_pms_drv, "cs5535-pms");
if (r) if (r)
return r; return r;
r = platform_driver_register(&cs5535_acpi_drv); r = mfd_shared_platform_driver_register(&cs5535_acpi_drv,
"cs5535-acpi");
if (r) if (r)
platform_driver_unregister(&cs5535_pms_drv); mfd_shared_platform_driver_unregister(&cs5535_pms_drv);
return r; return r;
} }
static void __exit olpc_xo1_exit(void) static void __exit olpc_xo1_exit(void)
{ {
platform_driver_unregister(&cs5535_acpi_drv); mfd_shared_platform_driver_unregister(&cs5535_acpi_drv);
platform_driver_unregister(&cs5535_pms_drv); mfd_shared_platform_driver_unregister(&cs5535_pms_drv);
} }
MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>"); MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:olpc-xo1"); MODULE_ALIAS("platform:cs5535-pms");
module_init(olpc_xo1_init); module_init(olpc_xo1_init);
module_exit(olpc_xo1_exit); module_exit(olpc_xo1_exit);
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/timb_dma.h> #include <linux/timb_dma.h>
...@@ -684,7 +685,7 @@ static irqreturn_t td_irq(int irq, void *devid) ...@@ -684,7 +685,7 @@ static irqreturn_t td_irq(int irq, void *devid)
static int __devinit td_probe(struct platform_device *pdev) static int __devinit td_probe(struct platform_device *pdev)
{ {
struct timb_dma_platform_data *pdata = pdev->dev.platform_data; struct timb_dma_platform_data *pdata = mfd_get_data(pdev);
struct timb_dma *td; struct timb_dma *td;
struct resource *iomem; struct resource *iomem;
int irq; int irq;
......
...@@ -100,18 +100,21 @@ config GPIO_VR41XX ...@@ -100,18 +100,21 @@ 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 GPIO" tristate "Intel SCH/TunnelCreek GPIO"
depends on GPIOLIB && PCI && X86 depends on GPIOLIB && 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.
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
the Intel SCH suspend power supply. These GPIOs remain the Intel SCH suspend power supply. These GPIOs remain
active during S3. The suspend powered GPIOs can be used to wake the active during S3. The suspend powered GPIOs can be used to wake the
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
core power rail and 9 from suspend power supply.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called sch-gpio. will be called sch-gpio.
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -149,7 +150,7 @@ static int __devinit ttl_probe(struct platform_device *pdev) ...@@ -149,7 +150,7 @@ static int __devinit ttl_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
int ret; int ret;
pdata = pdev->dev.platform_data; pdata = mfd_get_data(pdev);
if (!pdata) { if (!pdata) {
dev_err(dev, "no platform data\n"); dev_err(dev, "no platform data\n");
ret = -ENXIO; ret = -ENXIO;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/mfd/rdc321x.h> #include <linux/mfd/rdc321x.h>
#include <linux/mfd/core.h>
#include <linux/slab.h> #include <linux/slab.h>
struct rdc321x_gpio { struct rdc321x_gpio {
...@@ -135,7 +136,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev) ...@@ -135,7 +136,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
struct rdc321x_gpio *rdc321x_gpio_dev; struct rdc321x_gpio *rdc321x_gpio_dev;
struct rdc321x_gpio_pdata *pdata; struct rdc321x_gpio_pdata *pdata;
pdata = platform_get_drvdata(pdev); pdata = mfd_get_data(pdev);
if (!pdata) { if (!pdata) {
dev_err(&pdev->dev, "no platform data supplied\n"); dev_err(&pdev->dev, "no platform data supplied\n");
return -ENODEV; return -ENODEV;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pci_ids.h>
#include <linux/gpio.h> #include <linux/gpio.h>
...@@ -187,7 +188,11 @@ static struct gpio_chip sch_gpio_resume = { ...@@ -187,7 +188,11 @@ static struct gpio_chip sch_gpio_resume = {
static int __devinit sch_gpio_probe(struct platform_device *pdev) static int __devinit sch_gpio_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
int err; int err, id;
id = pdev->id;
if (!id)
return -ENODEV;
res = platform_get_resource(pdev, IORESOURCE_IO, 0); res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!res) if (!res)
...@@ -198,21 +203,13 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev) ...@@ -198,21 +203,13 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev)
gpio_ba = res->start; gpio_ba = res->start;
switch (id) {
case PCI_DEVICE_ID_INTEL_SCH_LPC:
sch_gpio_core.base = 0; sch_gpio_core.base = 0;
sch_gpio_core.ngpio = 10; sch_gpio_core.ngpio = 10;
sch_gpio_core.dev = &pdev->dev;
sch_gpio_resume.base = 10; sch_gpio_resume.base = 10;
sch_gpio_resume.ngpio = 4; sch_gpio_resume.ngpio = 4;
sch_gpio_resume.dev = &pdev->dev;
err = gpiochip_add(&sch_gpio_core);
if (err < 0)
goto err_sch_gpio_core;
err = gpiochip_add(&sch_gpio_resume);
if (err < 0)
goto err_sch_gpio_resume;
/* /*
* GPIO[6:0] enabled by default * GPIO[6:0] enabled by default
...@@ -225,6 +222,30 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev) ...@@ -225,6 +222,30 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev)
* Enable SUS_GPIO3 resume powered gpio explicitly * Enable SUS_GPIO3 resume powered gpio explicitly
*/ */
outb(0x8, gpio_ba + RGEN); outb(0x8, gpio_ba + RGEN);
break;
case PCI_DEVICE_ID_INTEL_ITC_LPC:
sch_gpio_core.base = 0;
sch_gpio_core.ngpio = 5;
sch_gpio_resume.base = 5;
sch_gpio_resume.ngpio = 9;
break;
default:
return -ENODEV;
}
sch_gpio_core.dev = &pdev->dev;
sch_gpio_resume.dev = &pdev->dev;
err = gpiochip_add(&sch_gpio_core);
if (err < 0)
goto err_sch_gpio_core;
err = gpiochip_add(&sch_gpio_resume);
if (err < 0)
goto err_sch_gpio_resume;
return 0; return 0;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/timb_gpio.h> #include <linux/timb_gpio.h>
...@@ -228,7 +229,7 @@ static int __devinit timbgpio_probe(struct platform_device *pdev) ...@@ -228,7 +229,7 @@ static int __devinit timbgpio_probe(struct platform_device *pdev)
struct gpio_chip *gc; struct gpio_chip *gc;
struct timbgpio *tgpio; struct timbgpio *tgpio;
struct resource *iomem; struct resource *iomem;
struct timbgpio_platform_data *pdata = pdev->dev.platform_data; struct timbgpio_platform_data *pdata = mfd_get_data(pdev);
int irq = platform_get_irq(pdev, 0); int irq = platform_get_irq(pdev, 0);
if (!pdata || pdata->nr_pins > 32) { if (!pdata || pdata->nr_pins > 32) {
...@@ -319,14 +320,13 @@ static int __devinit timbgpio_probe(struct platform_device *pdev) ...@@ -319,14 +320,13 @@ static int __devinit timbgpio_probe(struct platform_device *pdev)
static int __devexit timbgpio_remove(struct platform_device *pdev) static int __devexit timbgpio_remove(struct platform_device *pdev)
{ {
int err; int err;
struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
struct timbgpio *tgpio = platform_get_drvdata(pdev); struct timbgpio *tgpio = platform_get_drvdata(pdev);
struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
int irq = platform_get_irq(pdev, 0); int irq = platform_get_irq(pdev, 0);
if (irq >= 0 && tgpio->irq_base > 0) { if (irq >= 0 && tgpio->irq_base > 0) {
int i; int i;
for (i = 0; i < pdata->nr_pins; i++) { for (i = 0; i < tgpio->gpio.ngpio; i++) {
set_irq_chip(tgpio->irq_base + i, NULL); set_irq_chip(tgpio->irq_base + i, NULL);
set_irq_chip_data(tgpio->irq_base + i, NULL); set_irq_chip_data(tgpio->irq_base + i, NULL);
} }
......
...@@ -1047,6 +1047,16 @@ config SENSORS_TMP421 ...@@ -1047,6 +1047,16 @@ config SENSORS_TMP421
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called tmp421. will be called tmp421.
config SENSORS_TWL4030_MADC
tristate "Texas Instruments TWL4030 MADC Hwmon"
depends on TWL4030_MADC
help
If you say yes here you get hwmon support for triton
TWL4030-MADC.
This driver can also be built as a module. If so it will be called
twl4030-madc-hwmon.
config SENSORS_VIA_CPUTEMP config SENSORS_VIA_CPUTEMP
tristate "VIA CPU temperature sensor" tristate "VIA CPU temperature sensor"
depends on X86 depends on X86
......
...@@ -104,6 +104,7 @@ obj-$(CONFIG_SENSORS_THMC50) += thmc50.o ...@@ -104,6 +104,7 @@ obj-$(CONFIG_SENSORS_THMC50) += thmc50.o
obj-$(CONFIG_SENSORS_TMP102) += tmp102.o obj-$(CONFIG_SENSORS_TMP102) += tmp102.o
obj-$(CONFIG_SENSORS_TMP401) += tmp401.o obj-$(CONFIG_SENSORS_TMP401) += tmp401.o
obj-$(CONFIG_SENSORS_TMP421) += tmp421.o obj-$(CONFIG_SENSORS_TMP421) += tmp421.o
obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o
obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
obj-$(CONFIG_SENSORS_VT1211) += vt1211.o obj-$(CONFIG_SENSORS_VT1211) += vt1211.o
......
...@@ -32,7 +32,7 @@ struct jz4740_hwmon { ...@@ -32,7 +32,7 @@ struct jz4740_hwmon {
int irq; int irq;
struct mfd_cell *cell; const struct mfd_cell *cell;
struct device *hwmon; struct device *hwmon;
struct completion read_completion; struct completion read_completion;
...@@ -112,7 +112,7 @@ static int __devinit jz4740_hwmon_probe(struct platform_device *pdev) ...@@ -112,7 +112,7 @@ static int __devinit jz4740_hwmon_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
hwmon->cell = pdev->dev.platform_data; hwmon->cell = mfd_get_cell(pdev);
hwmon->irq = platform_get_irq(pdev, 0); hwmon->irq = platform_get_irq(pdev, 0);
if (hwmon->irq < 0) { if (hwmon->irq < 0) {
......
/*
*
* TWL4030 MADC Hwmon driver-This driver monitors the real time
* conversion of analog signals like battery temperature,
* battery type, battery level etc. User can ask for the conversion on a
* particular channel using the sysfs nodes.
*
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
* J Keerthy <j-keerthy@ti.com>
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c/twl.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/i2c/twl4030-madc.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/stddef.h>
#include <linux/sysfs.h>
#include <linux/err.h>
#include <linux/types.h>
/*
* sysfs hook function
*/
static ssize_t madc_read(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct twl4030_madc_request req;
long val;
req.channels = (1 << attr->index);
req.method = TWL4030_MADC_SW2;
req.func_cb = NULL;
val = twl4030_madc_conversion(&req);
if (val < 0)
return val;
return sprintf(buf, "%d\n", req.rbuf[attr->index]);
}
/* sysfs nodes to read individual channels from user side */
static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, madc_read, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, madc_read, NULL, 1);
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, madc_read, NULL, 2);
static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, madc_read, NULL, 3);
static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, madc_read, NULL, 4);
static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, madc_read, NULL, 5);
static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, madc_read, NULL, 6);
static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, madc_read, NULL, 7);
static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, madc_read, NULL, 8);
static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, madc_read, NULL, 9);
static SENSOR_DEVICE_ATTR(curr10_input, S_IRUGO, madc_read, NULL, 10);
static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, madc_read, NULL, 11);
static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, madc_read, NULL, 12);
static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, madc_read, NULL, 15);
static struct attribute *twl4030_madc_attributes[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_in2_input.dev_attr.attr,
&sensor_dev_attr_in3_input.dev_attr.attr,
&sensor_dev_attr_in4_input.dev_attr.attr,
&sensor_dev_attr_in5_input.dev_attr.attr,
&sensor_dev_attr_in6_input.dev_attr.attr,
&sensor_dev_attr_in7_input.dev_attr.attr,
&sensor_dev_attr_in8_input.dev_attr.attr,
&sensor_dev_attr_in9_input.dev_attr.attr,
&sensor_dev_attr_curr10_input.dev_attr.attr,
&sensor_dev_attr_in11_input.dev_attr.attr,
&sensor_dev_attr_in12_input.dev_attr.attr,
&sensor_dev_attr_in15_input.dev_attr.attr,
NULL
};
static const struct attribute_group twl4030_madc_group = {
.attrs = twl4030_madc_attributes,
};
static int __devinit twl4030_madc_hwmon_probe(struct platform_device *pdev)
{
int ret;
int status;
struct device *hwmon;
ret = sysfs_create_group(&pdev->dev.kobj, &twl4030_madc_group);
if (ret)
goto err_sysfs;
hwmon = hwmon_device_register(&pdev->dev);
if (IS_ERR(hwmon)) {
dev_err(&pdev->dev, "hwmon_device_register failed.\n");
status = PTR_ERR(hwmon);
goto err_reg;
}
return 0;
err_reg:
sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group);
err_sysfs:
return ret;
}
static int __devexit twl4030_madc_hwmon_remove(struct platform_device *pdev)
{
hwmon_device_unregister(&pdev->dev);
sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group);
return 0;
}
static struct platform_driver twl4030_madc_hwmon_driver = {
.probe = twl4030_madc_hwmon_probe,
.remove = __exit_p(twl4030_madc_hwmon_remove),
.driver = {
.name = "twl4030_madc_hwmon",
.owner = THIS_MODULE,
},
};
static int __init twl4030_madc_hwmon_init(void)
{
return platform_driver_register(&twl4030_madc_hwmon_driver);
}
module_init(twl4030_madc_hwmon_init);
static void __exit twl4030_madc_hwmon_exit(void)
{
platform_driver_unregister(&twl4030_madc_hwmon_driver);
}
module_exit(twl4030_madc_hwmon_exit);
MODULE_DESCRIPTION("TWL4030 ADC Hwmon driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("J Keerthy");
MODULE_ALIAS("twl4030_madc_hwmon");
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/wait.h> #include <linux/wait.h>
...@@ -305,7 +306,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) ...@@ -305,7 +306,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
return -EIO; return -EIO;
} }
pdata = pdev->dev.platform_data; pdata = mfd_get_data(pdev);
if (pdata) { if (pdata) {
i2c->regstep = pdata->regstep; i2c->regstep = pdata->regstep;
i2c->clock_khz = pdata->clock_khz; i2c->clock_khz = pdata->clock_khz;
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/wait.h> #include <linux/wait.h>
...@@ -704,7 +705,7 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev) ...@@ -704,7 +705,7 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev)
if (irq < 0) if (irq < 0)
goto resource_missing; goto resource_missing;
pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data; pdata = mfd_get_data(pdev);
if (!pdata) if (!pdata)
return -EINVAL; return -EINVAL;
......
...@@ -74,7 +74,7 @@ static int __devinit pm860x_onkey_probe(struct platform_device *pdev) ...@@ -74,7 +74,7 @@ static int __devinit pm860x_onkey_probe(struct platform_device *pdev)
info->chip = chip; info->chip = chip;
info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
info->dev = &pdev->dev; info->dev = &pdev->dev;
info->irq = irq + chip->irq_base; info->irq = irq;
info->idev = input_allocate_device(); info->idev = input_allocate_device();
if (!info->idev) { if (!info->idev) {
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/i2c/twl.h> #include <linux/i2c/twl.h>
#include <linux/mfd/twl4030-codec.h> #include <linux/mfd/twl4030-codec.h>
#include <linux/mfd/core.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -196,7 +197,7 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops, ...@@ -196,7 +197,7 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
static int __devinit twl4030_vibra_probe(struct platform_device *pdev) static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
{ {
struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data; struct twl4030_codec_vibra_data *pdata = mfd_get_data(pdev);
struct vibra_info *info; struct vibra_info *info;
int ret; int ret;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/mfd/core.h>
#include <linux/mfd/88pm860x.h> #include <linux/mfd/88pm860x.h>
#define LED_PWM_SHIFT (3) #define LED_PWM_SHIFT (3)
...@@ -118,7 +119,8 @@ static void pm860x_led_work(struct work_struct *work) ...@@ -118,7 +119,8 @@ static void pm860x_led_work(struct work_struct *work)
struct pm860x_led *led; struct pm860x_led *led;
struct pm860x_chip *chip; struct pm860x_chip *chip;
int mask; unsigned char buf[3];
int mask, ret;
led = container_of(work, struct pm860x_led, work); led = container_of(work, struct pm860x_led, work);
chip = led->chip; chip = led->chip;
...@@ -128,16 +130,27 @@ static void pm860x_led_work(struct work_struct *work) ...@@ -128,16 +130,27 @@ static void pm860x_led_work(struct work_struct *work)
pm860x_set_bits(led->i2c, __led_off(led->port), pm860x_set_bits(led->i2c, __led_off(led->port),
LED_CURRENT_MASK, led->iset); LED_CURRENT_MASK, led->iset);
} }
pm860x_set_bits(led->i2c, __blink_off(led->port),
LED_BLINK_MASK, LED_ON_CONTINUOUS);
mask = __blink_ctl_mask(led->port); mask = __blink_ctl_mask(led->port);
pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask); pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask);
} else if (led->brightness == 0) { }
pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK,
led->brightness);
if (led->brightness == 0) {
pm860x_bulk_read(led->i2c, __led_off(led->port), 3, buf);
ret = buf[0] & LED_PWM_MASK;
ret |= buf[1] & LED_PWM_MASK;
ret |= buf[2] & LED_PWM_MASK;
if (ret == 0) {
/* unset current since no led is lighting */
pm860x_set_bits(led->i2c, __led_off(led->port), pm860x_set_bits(led->i2c, __led_off(led->port),
LED_CURRENT_MASK, 0); LED_CURRENT_MASK, 0);
mask = __blink_ctl_mask(led->port); mask = __blink_ctl_mask(led->port);
pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0); pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0);
} }
pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK, }
led->brightness);
led->current_brightness = led->brightness; led->current_brightness = led->brightness;
dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n", dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n",
__led_off(led->port), led->brightness); __led_off(led->port), led->brightness);
...@@ -153,31 +166,12 @@ static void pm860x_led_set(struct led_classdev *cdev, ...@@ -153,31 +166,12 @@ static void pm860x_led_set(struct led_classdev *cdev,
schedule_work(&data->work); schedule_work(&data->work);
} }
static int __check_device(struct pm860x_led_pdata *pdata, char *name)
{
struct pm860x_led_pdata *p = pdata;
int ret = -EINVAL;
while (p && p->id) {
if ((p->id != PM8606_ID_LED) || (p->flags < 0))
break;
if (!strncmp(name, pm860x_led_name[p->flags],
MFD_NAME_SIZE)) {
ret = (int)p->flags;
break;
}
p++;
}
return ret;
}
static int pm860x_led_probe(struct platform_device *pdev) static int pm860x_led_probe(struct platform_device *pdev)
{ {
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm860x_platform_data *pm860x_pdata;
struct pm860x_led_pdata *pdata; struct pm860x_led_pdata *pdata;
struct pm860x_led *data; struct pm860x_led *data;
struct mfd_cell *cell;
struct resource *res; struct resource *res;
int ret; int ret;
...@@ -187,10 +181,11 @@ static int pm860x_led_probe(struct platform_device *pdev) ...@@ -187,10 +181,11 @@ static int pm860x_led_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
if (pdev->dev.parent->platform_data) { cell = pdev->dev.platform_data;
pm860x_pdata = pdev->dev.parent->platform_data; if (cell == NULL)
pdata = pm860x_pdata->led; return -ENODEV;
} else { pdata = cell->mfd_data;
if (pdata == NULL) {
dev_err(&pdev->dev, "No platform data!\n"); dev_err(&pdev->dev, "No platform data!\n");
return -EINVAL; return -EINVAL;
} }
...@@ -198,12 +193,12 @@ static int pm860x_led_probe(struct platform_device *pdev) ...@@ -198,12 +193,12 @@ static int pm860x_led_probe(struct platform_device *pdev)
data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL); data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL);
if (data == NULL) if (data == NULL)
return -ENOMEM; return -ENOMEM;
strncpy(data->name, res->name, MFD_NAME_SIZE); strncpy(data->name, res->name, MFD_NAME_SIZE - 1);
dev_set_drvdata(&pdev->dev, data); dev_set_drvdata(&pdev->dev, data);
data->chip = chip; data->chip = chip;
data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
data->iset = pdata->iset; data->iset = pdata->iset;
data->port = __check_device(pdata, data->name); data->port = pdata->flags;
if (data->port < 0) { if (data->port < 0) {
dev_err(&pdev->dev, "check device failed\n"); dev_err(&pdev->dev, "check device failed\n");
kfree(data); kfree(data);
...@@ -221,6 +216,7 @@ static int pm860x_led_probe(struct platform_device *pdev) ...@@ -221,6 +216,7 @@ static int pm860x_led_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Failed to register LED: %d\n", ret); dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
goto out; goto out;
} }
pm860x_led_set(&data->cdev, 0);
return 0; return 0;
out: out:
kfree(data); kfree(data);
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/mfd/mc13783.h> #include <linux/mfd/mc13783.h>
#include <linux/mfd/core.h>
#include <linux/slab.h> #include <linux/slab.h>
struct mc13783_led { struct mc13783_led {
...@@ -183,7 +184,7 @@ static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current) ...@@ -183,7 +184,7 @@ static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current)
static int __devinit mc13783_leds_prepare(struct platform_device *pdev) static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
{ {
struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev);
struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
int ret = 0; int ret = 0;
int reg = 0; int reg = 0;
...@@ -264,7 +265,7 @@ static int __devinit mc13783_leds_prepare(struct platform_device *pdev) ...@@ -264,7 +265,7 @@ static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
static int __devinit mc13783_led_probe(struct platform_device *pdev) static int __devinit mc13783_led_probe(struct platform_device *pdev)
{ {
struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev);
struct mc13783_led_platform_data *led_cur; struct mc13783_led_platform_data *led_cur;
struct mc13783_led *led, *led_dat; struct mc13783_led *led, *led_dat;
int ret, i; int ret, i;
...@@ -351,7 +352,7 @@ static int __devinit mc13783_led_probe(struct platform_device *pdev) ...@@ -351,7 +352,7 @@ static int __devinit mc13783_led_probe(struct platform_device *pdev)
static int __devexit mc13783_led_remove(struct platform_device *pdev) static int __devexit mc13783_led_remove(struct platform_device *pdev)
{ {
struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev);
struct mc13783_led *led = platform_get_drvdata(pdev); struct mc13783_led *led = platform_get_drvdata(pdev);
struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
int i; int i;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <media/v4l2-ioctl.h> #include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
...@@ -148,7 +149,7 @@ static const struct v4l2_file_operations timbradio_fops = { ...@@ -148,7 +149,7 @@ static const struct v4l2_file_operations timbradio_fops = {
static int __devinit timbradio_probe(struct platform_device *pdev) static int __devinit timbradio_probe(struct platform_device *pdev)
{ {
struct timb_radio_platform_data *pdata = pdev->dev.platform_data; struct timb_radio_platform_data *pdata = mfd_get_data(pdev);
struct timbradio *tr; struct timbradio *tr;
int err; int err;
......
...@@ -2138,7 +2138,7 @@ static int wl1273_fm_radio_remove(struct platform_device *pdev) ...@@ -2138,7 +2138,7 @@ static int wl1273_fm_radio_remove(struct platform_device *pdev)
static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev)
{ {
struct wl1273_core **core = pdev->dev.platform_data; struct wl1273_core **core = mfd_get_data(pdev);
struct wl1273_device *radio; struct wl1273_device *radio;
struct v4l2_ctrl *ctrl; struct v4l2_ctrl *ctrl;
int r = 0; int r = 0;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/mfd/core.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/list.h> #include <linux/list.h>
...@@ -790,7 +791,7 @@ static int __devinit timblogiw_probe(struct platform_device *pdev) ...@@ -790,7 +791,7 @@ static int __devinit timblogiw_probe(struct platform_device *pdev)
{ {
int err; int err;
struct timblogiw *lw = NULL; struct timblogiw *lw = NULL;
struct timb_video_platform_data *pdata = pdev->dev.platform_data; struct timb_video_platform_data *pdata = mfd_get_data(pdev);
if (!pdata) { if (!pdata) {
dev_err(&pdev->dev, "No platform data\n"); dev_err(&pdev->dev, "No platform data\n");
......
This diff is collapsed.
...@@ -126,6 +126,109 @@ int pm860x_set_bits(struct i2c_client *i2c, int reg, ...@@ -126,6 +126,109 @@ int pm860x_set_bits(struct i2c_client *i2c, int reg,
} }
EXPORT_SYMBOL(pm860x_set_bits); EXPORT_SYMBOL(pm860x_set_bits);
int pm860x_page_reg_read(struct i2c_client *i2c, int reg)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char zero = 0;
unsigned char data;
int ret;
mutex_lock(&chip->io_lock);
pm860x_write_device(i2c, 0xFA, 0, &zero);
pm860x_write_device(i2c, 0xFB, 0, &zero);
pm860x_write_device(i2c, 0xFF, 0, &zero);
ret = pm860x_read_device(i2c, reg, 1, &data);
if (ret >= 0)
ret = (int)data;
pm860x_write_device(i2c, 0xFE, 0, &zero);
pm860x_write_device(i2c, 0xFC, 0, &zero);
mutex_unlock(&chip->io_lock);
return ret;
}
EXPORT_SYMBOL(pm860x_page_reg_read);
int pm860x_page_reg_write(struct i2c_client *i2c, int reg,
unsigned char data)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char zero;
int ret;
mutex_lock(&chip->io_lock);
pm860x_write_device(i2c, 0xFA, 0, &zero);
pm860x_write_device(i2c, 0xFB, 0, &zero);
pm860x_write_device(i2c, 0xFF, 0, &zero);
ret = pm860x_write_device(i2c, reg, 1, &data);
pm860x_write_device(i2c, 0xFE, 0, &zero);
pm860x_write_device(i2c, 0xFC, 0, &zero);
mutex_unlock(&chip->io_lock);
return ret;
}
EXPORT_SYMBOL(pm860x_page_reg_write);
int pm860x_page_bulk_read(struct i2c_client *i2c, int reg,
int count, unsigned char *buf)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char zero = 0;
int ret;
mutex_lock(&chip->io_lock);
pm860x_write_device(i2c, 0xFA, 0, &zero);
pm860x_write_device(i2c, 0xFB, 0, &zero);
pm860x_write_device(i2c, 0xFF, 0, &zero);
ret = pm860x_read_device(i2c, reg, count, buf);
pm860x_write_device(i2c, 0xFE, 0, &zero);
pm860x_write_device(i2c, 0xFC, 0, &zero);
mutex_unlock(&chip->io_lock);
return ret;
}
EXPORT_SYMBOL(pm860x_page_bulk_read);
int pm860x_page_bulk_write(struct i2c_client *i2c, int reg,
int count, unsigned char *buf)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char zero = 0;
int ret;
mutex_lock(&chip->io_lock);
pm860x_write_device(i2c, 0xFA, 0, &zero);
pm860x_write_device(i2c, 0xFB, 0, &zero);
pm860x_write_device(i2c, 0xFF, 0, &zero);
ret = pm860x_write_device(i2c, reg, count, buf);
pm860x_write_device(i2c, 0xFE, 0, &zero);
pm860x_write_device(i2c, 0xFC, 0, &zero);
mutex_unlock(&chip->io_lock);
return ret;
}
EXPORT_SYMBOL(pm860x_page_bulk_write);
int pm860x_page_set_bits(struct i2c_client *i2c, int reg,
unsigned char mask, unsigned char data)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char zero;
unsigned char value;
int ret;
mutex_lock(&chip->io_lock);
pm860x_write_device(i2c, 0xFA, 0, &zero);
pm860x_write_device(i2c, 0xFB, 0, &zero);
pm860x_write_device(i2c, 0xFF, 0, &zero);
ret = pm860x_read_device(i2c, reg, 1, &value);
if (ret < 0)
goto out;
value &= ~mask;
value |= data;
ret = pm860x_write_device(i2c, reg, 1, &value);
out:
pm860x_write_device(i2c, 0xFE, 0, &zero);
pm860x_write_device(i2c, 0xFC, 0, &zero);
mutex_unlock(&chip->io_lock);
return ret;
}
EXPORT_SYMBOL(pm860x_page_set_bits);
static const struct i2c_device_id pm860x_id_table[] = { static const struct i2c_device_id pm860x_id_table[] = {
{ "88PM860x", 0 }, { "88PM860x", 0 },
......
...@@ -129,6 +129,17 @@ config UCB1400_CORE ...@@ -129,6 +129,17 @@ 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 TPS6105X
tristate "TPS61050/61052 Boost Converters"
depends on I2C
select REGULATOR
select REGULATOR_FIXED_VOLTAGE
help
This option enables a driver for the TP61050/TPS61052
high-power "white LED driver". This boost converter is
sometimes used for other things than white LEDs, and
also contains a GPIO pin.
config TPS65010 config TPS65010
tristate "TPS6501x Power Management chips" tristate "TPS6501x Power Management chips"
depends on I2C && GPIOLIB depends on I2C && GPIOLIB
...@@ -178,6 +189,16 @@ config TWL4030_CORE ...@@ -178,6 +189,16 @@ config TWL4030_CORE
high speed USB OTG transceiver, an audio codec (on most high speed USB OTG transceiver, an audio codec (on most
versions) and many other features. versions) and many other features.
config TWL4030_MADC
tristate "Texas Instruments TWL4030 MADC"
depends on TWL4030_CORE
help
This driver provides support for triton TWL4030-MADC. The
driver supports both RT and SW conversion methods.
This driver can be built as a module. If so it will be
named twl4030-madc
config TWL4030_POWER config TWL4030_POWER
bool "Support power resources on TWL4030 family chips" bool "Support power resources on TWL4030 family chips"
depends on TWL4030_CORE && ARM depends on TWL4030_CORE && ARM
...@@ -304,6 +325,18 @@ config MFD_MAX8925 ...@@ -304,6 +325,18 @@ config MFD_MAX8925
accessing the device, additional drivers must be enabled in order accessing the device, additional drivers must be enabled in order
to use the functionality of the device. to use the functionality of the device.
config MFD_MAX8997
bool "Maxim Semiconductor MAX8997/8966 PMIC Support"
depends on I2C=y && GENERIC_HARDIRQS
select MFD_CORE
help
Say yes here to support for Maxim Semiconductor MAX8998/8966.
This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic,
MUIC 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_MAX8998 config MFD_MAX8998
bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support" bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support"
depends on I2C=y && GENERIC_HARDIRQS depends on I2C=y && GENERIC_HARDIRQS
...@@ -534,6 +567,13 @@ config AB8500_DEBUG ...@@ -534,6 +567,13 @@ config AB8500_DEBUG
Select this option if you want debug information using the debug Select this option if you want debug information using the debug
filesystem, debugfs. filesystem, debugfs.
config AB8500_GPADC
bool "AB8500 GPADC driver"
depends on AB8500_CORE && REGULATOR_AB8500
default y
help
AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage
config AB3550_CORE config AB3550_CORE
bool "ST-Ericsson AB3550 Mixed Signal Circuit core functions" bool "ST-Ericsson AB3550 Mixed Signal Circuit core functions"
select MFD_CORE select MFD_CORE
......
...@@ -33,11 +33,13 @@ obj-$(CONFIG_MFD_WM8350) += wm8350.o ...@@ -33,11 +33,13 @@ obj-$(CONFIG_MFD_WM8350) += wm8350.o
obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o
obj-$(CONFIG_TPS6105X) += tps6105x.o
obj-$(CONFIG_TPS65010) += tps65010.o obj-$(CONFIG_TPS65010) += tps65010.o
obj-$(CONFIG_TPS6507X) += tps6507x.o obj-$(CONFIG_TPS6507X) += tps6507x.o
obj-$(CONFIG_MENELAUS) += menelaus.o obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o
obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o
obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o
obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o
...@@ -61,6 +63,7 @@ obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o ...@@ -61,6 +63,7 @@ obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o
obj-$(CONFIG_PMIC_DA903X) += da903x.o obj-$(CONFIG_PMIC_DA903X) += da903x.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
obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o
pcf50633-objs := pcf50633-core.o pcf50633-irq.o pcf50633-objs := pcf50633-core.o pcf50633-irq.o
...@@ -71,9 +74,10 @@ obj-$(CONFIG_ABX500_CORE) += abx500-core.o ...@@ -71,9 +74,10 @@ 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_AB3550_CORE) += ab3550-core.o obj-$(CONFIG_AB3550_CORE) += ab3550-core.o
obj-$(CONFIG_AB8500_CORE) += ab8500-core.o obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o
obj-$(CONFIG_AB8500_I2C_CORE) += ab8500-i2c.o obj-$(CONFIG_AB8500_I2C_CORE) += ab8500-i2c.o
obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o
obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.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
......
...@@ -613,7 +613,7 @@ static void ab3100_setup_debugfs(struct ab3100 *ab3100) ...@@ -613,7 +613,7 @@ static void ab3100_setup_debugfs(struct ab3100 *ab3100)
ab3100_get_priv.ab3100 = ab3100; ab3100_get_priv.ab3100 = ab3100;
ab3100_get_priv.mode = false; ab3100_get_priv.mode = false;
ab3100_get_reg_file = debugfs_create_file("get_reg", ab3100_get_reg_file = debugfs_create_file("get_reg",
S_IWUGO, ab3100_dir, &ab3100_get_priv, S_IWUSR, ab3100_dir, &ab3100_get_priv,
&ab3100_get_set_reg_fops); &ab3100_get_set_reg_fops);
if (!ab3100_get_reg_file) { if (!ab3100_get_reg_file) {
err = -ENOMEM; err = -ENOMEM;
...@@ -623,7 +623,7 @@ static void ab3100_setup_debugfs(struct ab3100 *ab3100) ...@@ -623,7 +623,7 @@ static void ab3100_setup_debugfs(struct ab3100 *ab3100)
ab3100_set_priv.ab3100 = ab3100; ab3100_set_priv.ab3100 = ab3100;
ab3100_set_priv.mode = true; ab3100_set_priv.mode = true;
ab3100_set_reg_file = debugfs_create_file("set_reg", ab3100_set_reg_file = debugfs_create_file("set_reg",
S_IWUGO, ab3100_dir, &ab3100_set_priv, S_IWUSR, ab3100_dir, &ab3100_set_priv,
&ab3100_get_set_reg_fops); &ab3100_get_set_reg_fops);
if (!ab3100_set_reg_file) { if (!ab3100_set_reg_file) {
err = -ENOMEM; err = -ENOMEM;
...@@ -949,10 +949,8 @@ static int __devinit ab3100_probe(struct i2c_client *client, ...@@ -949,10 +949,8 @@ static int __devinit ab3100_probe(struct i2c_client *client,
goto exit_no_ops; goto exit_no_ops;
/* Set up and register the platform devices. */ /* Set up and register the platform devices. */
for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++) { for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++)
ab3100_devs[i].platform_data = ab3100_plf_data; ab3100_devs[i].mfd_data = ab3100_plf_data;
ab3100_devs[i].data_size = sizeof(struct ab3100_platform_data);
}
err = mfd_add_devices(&client->dev, 0, ab3100_devs, err = mfd_add_devices(&client->dev, 0, ab3100_devs,
ARRAY_SIZE(ab3100_devs), NULL, 0); ARRAY_SIZE(ab3100_devs), NULL, 0);
......
...@@ -1053,17 +1053,17 @@ static inline void ab3550_setup_debugfs(struct ab3550 *ab) ...@@ -1053,17 +1053,17 @@ static inline void ab3550_setup_debugfs(struct ab3550 *ab)
goto exit_destroy_dir; goto exit_destroy_dir;
ab3550_bank_file = debugfs_create_file("register-bank", ab3550_bank_file = debugfs_create_file("register-bank",
(S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_bank_fops); (S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_bank_fops);
if (!ab3550_bank_file) if (!ab3550_bank_file)
goto exit_destroy_reg; goto exit_destroy_reg;
ab3550_address_file = debugfs_create_file("register-address", ab3550_address_file = debugfs_create_file("register-address",
(S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_address_fops); (S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_address_fops);
if (!ab3550_address_file) if (!ab3550_address_file)
goto exit_destroy_bank; goto exit_destroy_bank;
ab3550_val_file = debugfs_create_file("register-value", ab3550_val_file = debugfs_create_file("register-value",
(S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_val_fops); (S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_val_fops);
if (!ab3550_val_file) if (!ab3550_val_file)
goto exit_destroy_address; goto exit_destroy_address;
...@@ -1320,10 +1320,8 @@ static int __init ab3550_probe(struct i2c_client *client, ...@@ -1320,10 +1320,8 @@ static int __init ab3550_probe(struct i2c_client *client,
goto exit_no_ops; goto exit_no_ops;
/* Set up and register the platform devices. */ /* Set up and register the platform devices. */
for (i = 0; i < AB3550_NUM_DEVICES; i++) { for (i = 0; i < AB3550_NUM_DEVICES; i++)
ab3550_devs[i].platform_data = ab3550_plf_data->dev_data[i]; ab3550_devs[i].mfd_data = ab3550_plf_data->dev_data[i];
ab3550_devs[i].data_size = ab3550_plf_data->dev_data_sz[i];
}
err = mfd_add_devices(&client->dev, 0, ab3550_devs, err = mfd_add_devices(&client->dev, 0, ab3550_devs,
ARRAY_SIZE(ab3550_devs), NULL, ARRAY_SIZE(ab3550_devs), NULL,
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* License Terms: GNU General Public License v2 * License Terms: GNU General Public License v2
* Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
* Author: Rabin Vincent <rabin.vincent@stericsson.com> * Author: Rabin Vincent <rabin.vincent@stericsson.com>
* Changes: Mattias Wallin <mattias.wallin@stericsson.com> * Author: Mattias Wallin <mattias.wallin@stericsson.com>
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -90,6 +90,7 @@ ...@@ -90,6 +90,7 @@
#define AB8500_IT_MASK24_REG 0x57 #define AB8500_IT_MASK24_REG 0x57
#define AB8500_REV_REG 0x80 #define AB8500_REV_REG 0x80
#define AB8500_SWITCH_OFF_STATUS 0x00
/* /*
* Map interrupt numbers to the LATCH and MASK register offsets, Interrupt * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
...@@ -652,10 +653,38 @@ static ssize_t show_chip_id(struct device *dev, ...@@ -652,10 +653,38 @@ static ssize_t show_chip_id(struct device *dev,
return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL); return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
} }
/*
* ab8500 has switched off due to (SWITCH_OFF_STATUS):
* 0x01 Swoff bit programming
* 0x02 Thermal protection activation
* 0x04 Vbat lower then BattOk falling threshold
* 0x08 Watchdog expired
* 0x10 Non presence of 32kHz clock
* 0x20 Battery level lower than power on reset threshold
* 0x40 Power on key 1 pressed longer than 10 seconds
* 0x80 DB8500 thermal shutdown
*/
static ssize_t show_switch_off_status(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
u8 value;
struct ab8500 *ab8500;
ab8500 = dev_get_drvdata(dev);
ret = get_register_interruptible(ab8500, AB8500_RTC,
AB8500_SWITCH_OFF_STATUS, &value);
if (ret < 0)
return ret;
return sprintf(buf, "%#x\n", value);
}
static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
static struct attribute *ab8500_sysfs_entries[] = { static struct attribute *ab8500_sysfs_entries[] = {
&dev_attr_chip_id.attr, &dev_attr_chip_id.attr,
&dev_attr_switch_off_status.attr,
NULL, NULL,
}; };
...@@ -686,9 +715,10 @@ int __devinit ab8500_init(struct ab8500 *ab8500) ...@@ -686,9 +715,10 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
* 0x10 - Cut 1.0 * 0x10 - Cut 1.0
* 0x11 - Cut 1.1 * 0x11 - Cut 1.1
* 0x20 - Cut 2.0 * 0x20 - Cut 2.0
* 0x30 - Cut 3.0
*/ */
if (value == 0x0 || value == 0x10 || value == 0x11 || value == 0x20) { if (value == 0x0 || value == 0x10 || value == 0x11 || value == 0x20 ||
ab8500->revision = value; value == 0x30) {
dev_info(ab8500->dev, "detected chip, revision: %#x\n", value); dev_info(ab8500->dev, "detected chip, revision: %#x\n", value);
} else { } else {
dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value); dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value);
...@@ -696,6 +726,24 @@ int __devinit ab8500_init(struct ab8500 *ab8500) ...@@ -696,6 +726,24 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
} }
ab8500->chip_id = value; ab8500->chip_id = value;
/*
* ab8500 has switched off due to (SWITCH_OFF_STATUS):
* 0x01 Swoff bit programming
* 0x02 Thermal protection activation
* 0x04 Vbat lower then BattOk falling threshold
* 0x08 Watchdog expired
* 0x10 Non presence of 32kHz clock
* 0x20 Battery level lower than power on reset threshold
* 0x40 Power on key 1 pressed longer than 10 seconds
* 0x80 DB8500 thermal shutdown
*/
ret = get_register_interruptible(ab8500, AB8500_RTC,
AB8500_SWITCH_OFF_STATUS, &value);
if (ret < 0)
return ret;
dev_info(ab8500->dev, "switch off status: %#x", value);
if (plat && plat->init) if (plat && plat->init)
plat->init(ab8500); plat->init(ab8500);
...@@ -764,6 +812,6 @@ int __devexit ab8500_exit(struct ab8500 *ab8500) ...@@ -764,6 +812,6 @@ int __devexit ab8500_exit(struct ab8500 *ab8500)
return 0; return 0;
} }
MODULE_AUTHOR("Srinidhi Kasagar, Rabin Vincent"); MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
MODULE_DESCRIPTION("AB8500 MFD core"); MODULE_DESCRIPTION("AB8500 MFD core");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -585,18 +585,18 @@ static int __devinit ab8500_debug_probe(struct platform_device *plf) ...@@ -585,18 +585,18 @@ static int __devinit ab8500_debug_probe(struct platform_device *plf)
goto exit_destroy_dir; goto exit_destroy_dir;
ab8500_bank_file = debugfs_create_file("register-bank", ab8500_bank_file = debugfs_create_file("register-bank",
(S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_bank_fops); (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_bank_fops);
if (!ab8500_bank_file) if (!ab8500_bank_file)
goto exit_destroy_reg; goto exit_destroy_reg;
ab8500_address_file = debugfs_create_file("register-address", ab8500_address_file = debugfs_create_file("register-address",
(S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev,
&ab8500_address_fops); &ab8500_address_fops);
if (!ab8500_address_file) if (!ab8500_address_file)
goto exit_destroy_bank; goto exit_destroy_bank;
ab8500_val_file = debugfs_create_file("register-value", ab8500_val_file = debugfs_create_file("register-value",
(S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_val_fops); (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_val_fops);
if (!ab8500_val_file) if (!ab8500_val_file)
goto exit_destroy_address; goto exit_destroy_address;
......
This diff is collapsed.
/*
* Copyright (C) ST-Ericsson SA 2010
* Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> for ST Ericsson.
* License terms: GNU General Public License (GPL) version 2
*/
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/mfd/ab8500.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/ab8500/sysctrl.h>
static struct device *sysctrl_dev;
static inline bool valid_bank(u8 bank)
{
return ((bank == AB8500_SYS_CTRL1_BLOCK) ||
(bank == AB8500_SYS_CTRL2_BLOCK));
}
int ab8500_sysctrl_read(u16 reg, u8 *value)
{
u8 bank;
if (sysctrl_dev == NULL)
return -EAGAIN;
bank = (reg >> 8);
if (!valid_bank(bank))
return -EINVAL;
return abx500_get_register_interruptible(sysctrl_dev, bank,
(u8)(reg & 0xFF), value);
}
int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value)
{
u8 bank;
if (sysctrl_dev == NULL)
return -EAGAIN;
bank = (reg >> 8);
if (!valid_bank(bank))
return -EINVAL;
return abx500_mask_and_set_register_interruptible(sysctrl_dev, bank,
(u8)(reg & 0xFF), mask, value);
}
static int __devinit ab8500_sysctrl_probe(struct platform_device *pdev)
{
sysctrl_dev = &pdev->dev;
return 0;
}
static int __devexit ab8500_sysctrl_remove(struct platform_device *pdev)
{
sysctrl_dev = NULL;
return 0;
}
static struct platform_driver ab8500_sysctrl_driver = {
.driver = {
.name = "ab8500-sysctrl",
.owner = THIS_MODULE,
},
.probe = ab8500_sysctrl_probe,
.remove = __devexit_p(ab8500_sysctrl_remove),
};
static int __init ab8500_sysctrl_init(void)
{
return platform_driver_register(&ab8500_sysctrl_driver);
}
subsys_initcall(ab8500_sysctrl_init);
MODULE_AUTHOR("Mattias Nilsson <mattias.i.nilsson@stericsson.com");
MODULE_DESCRIPTION("AB8500 system control driver");
MODULE_LICENSE("GPL v2");
...@@ -321,27 +321,27 @@ static int __devexit adp5520_remove(struct i2c_client *client) ...@@ -321,27 +321,27 @@ static int __devexit adp5520_remove(struct i2c_client *client)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int adp5520_suspend(struct i2c_client *client, static int adp5520_suspend(struct device *dev)
pm_message_t state)
{ {
struct i2c_client *client = to_i2c_client(dev);
struct adp5520_chip *chip = dev_get_drvdata(&client->dev); struct adp5520_chip *chip = dev_get_drvdata(&client->dev);
adp5520_clr_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY); adp5520_clr_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY);
return 0; return 0;
} }
static int adp5520_resume(struct i2c_client *client) static int adp5520_resume(struct device *dev)
{ {
struct i2c_client *client = to_i2c_client(dev);
struct adp5520_chip *chip = dev_get_drvdata(&client->dev); struct adp5520_chip *chip = dev_get_drvdata(&client->dev);
adp5520_set_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY); adp5520_set_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY);
return 0; return 0;
} }
#else
#define adp5520_suspend NULL
#define adp5520_resume NULL
#endif #endif
static SIMPLE_DEV_PM_OPS(adp5520_pm, adp5520_suspend, adp5520_resume);
static const struct i2c_device_id adp5520_id[] = { static const struct i2c_device_id adp5520_id[] = {
{ "pmic-adp5520", ID_ADP5520 }, { "pmic-adp5520", ID_ADP5520 },
{ "pmic-adp5501", ID_ADP5501 }, { "pmic-adp5501", ID_ADP5501 },
...@@ -353,11 +353,10 @@ static struct i2c_driver adp5520_driver = { ...@@ -353,11 +353,10 @@ static struct i2c_driver adp5520_driver = {
.driver = { .driver = {
.name = "adp5520", .name = "adp5520",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &adp5520_pm,
}, },
.probe = adp5520_probe, .probe = adp5520_probe,
.remove = __devexit_p(adp5520_remove), .remove = __devexit_p(adp5520_remove),
.suspend = adp5520_suspend,
.resume = adp5520_resume,
.id_table = adp5520_id, .id_table = adp5520_id,
}; };
......
...@@ -682,7 +682,7 @@ static struct mfd_cell asic3_cell_ds1wm = { ...@@ -682,7 +682,7 @@ static struct mfd_cell asic3_cell_ds1wm = {
.name = "ds1wm", .name = "ds1wm",
.enable = ds1wm_enable, .enable = ds1wm_enable,
.disable = ds1wm_disable, .disable = ds1wm_disable,
.driver_data = &ds1wm_pdata, .mfd_data = &ds1wm_pdata,
.num_resources = ARRAY_SIZE(ds1wm_resources), .num_resources = ARRAY_SIZE(ds1wm_resources),
.resources = ds1wm_resources, .resources = ds1wm_resources,
}; };
...@@ -783,7 +783,7 @@ static struct mfd_cell asic3_cell_mmc = { ...@@ -783,7 +783,7 @@ static struct mfd_cell asic3_cell_mmc = {
.name = "tmio-mmc", .name = "tmio-mmc",
.enable = asic3_mmc_enable, .enable = asic3_mmc_enable,
.disable = asic3_mmc_disable, .disable = asic3_mmc_disable,
.driver_data = &asic3_mmc_data, .mfd_data = &asic3_mmc_data,
.num_resources = ARRAY_SIZE(asic3_mmc_resources), .num_resources = ARRAY_SIZE(asic3_mmc_resources),
.resources = asic3_mmc_resources, .resources = asic3_mmc_resources,
}; };
...@@ -810,9 +810,6 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, ...@@ -810,9 +810,6 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
ds1wm_resources[0].start >>= asic->bus_shift; ds1wm_resources[0].start >>= asic->bus_shift;
ds1wm_resources[0].end >>= asic->bus_shift; ds1wm_resources[0].end >>= asic->bus_shift;
asic3_cell_ds1wm.platform_data = &asic3_cell_ds1wm;
asic3_cell_ds1wm.data_size = sizeof(asic3_cell_ds1wm);
/* MMC */ /* MMC */
asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) + asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
mem_sdio->start, 0x400 >> asic->bus_shift); mem_sdio->start, 0x400 >> asic->bus_shift);
...@@ -824,9 +821,6 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, ...@@ -824,9 +821,6 @@ 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;
asic3_cell_mmc.platform_data = &asic3_cell_mmc;
asic3_cell_mmc.data_size = sizeof(asic3_cell_mmc);
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)
......
...@@ -39,6 +39,37 @@ enum cs5535_mfd_bars { ...@@ -39,6 +39,37 @@ enum cs5535_mfd_bars {
NR_BARS, NR_BARS,
}; };
static int cs5535_mfd_res_enable(struct platform_device *pdev)
{
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!res) {
dev_err(&pdev->dev, "can't fetch device resource info\n");
return -EIO;
}
if (!request_region(res->start, resource_size(res), DRV_NAME)) {
dev_err(&pdev->dev, "can't request region\n");
return -EIO;
}
return 0;
}
static int cs5535_mfd_res_disable(struct platform_device *pdev)
{
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!res) {
dev_err(&pdev->dev, "can't fetch device resource info\n");
return -EIO;
}
release_region(res->start, resource_size(res));
return 0;
}
static __devinitdata struct resource cs5535_mfd_resources[NR_BARS]; static __devinitdata struct resource cs5535_mfd_resources[NR_BARS];
static __devinitdata struct mfd_cell cs5535_mfd_cells[] = { static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
...@@ -65,12 +96,18 @@ static __devinitdata struct mfd_cell cs5535_mfd_cells[] = { ...@@ -65,12 +96,18 @@ static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
.name = "cs5535-pms", .name = "cs5535-pms",
.num_resources = 1, .num_resources = 1,
.resources = &cs5535_mfd_resources[PMS_BAR], .resources = &cs5535_mfd_resources[PMS_BAR],
.enable = cs5535_mfd_res_enable,
.disable = cs5535_mfd_res_disable,
}, },
{ {
.id = ACPI_BAR, .id = ACPI_BAR,
.name = "cs5535-acpi", .name = "cs5535-acpi",
.num_resources = 1, .num_resources = 1,
.resources = &cs5535_mfd_resources[ACPI_BAR], .resources = &cs5535_mfd_resources[ACPI_BAR],
.enable = cs5535_mfd_res_enable,
.disable = cs5535_mfd_res_disable,
}, },
}; };
......
...@@ -119,12 +119,12 @@ static int __init davinci_vc_probe(struct platform_device *pdev) ...@@ -119,12 +119,12 @@ static int __init davinci_vc_probe(struct platform_device *pdev)
/* Voice codec interface client */ /* Voice codec interface client */
cell = &davinci_vc->cells[DAVINCI_VC_VCIF_CELL]; cell = &davinci_vc->cells[DAVINCI_VC_VCIF_CELL];
cell->name = "davinci-vcif"; cell->name = "davinci-vcif";
cell->driver_data = davinci_vc; cell->mfd_data = davinci_vc;
/* Voice codec CQ93VC client */ /* Voice codec CQ93VC client */
cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL]; cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL];
cell->name = "cq93vc-codec"; cell->name = "cq93vc-codec";
cell->driver_data = davinci_vc; cell->mfd_data = davinci_vc;
ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells, ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells,
DAVINCI_VC_CELLS, NULL, 0); DAVINCI_VC_CELLS, NULL, 0);
......
...@@ -117,7 +117,7 @@ static struct mfd_cell ds1wm_cell __initdata = { ...@@ -117,7 +117,7 @@ static struct mfd_cell ds1wm_cell __initdata = {
.name = "ds1wm", .name = "ds1wm",
.enable = ds1wm_enable, .enable = ds1wm_enable,
.disable = ds1wm_disable, .disable = ds1wm_disable,
.driver_data = &ds1wm_pdata, .mfd_data = &ds1wm_pdata,
.num_resources = 2, .num_resources = 2,
.resources = ds1wm_resources, .resources = ds1wm_resources,
}; };
...@@ -165,8 +165,6 @@ static int __init pasic3_probe(struct platform_device *pdev) ...@@ -165,8 +165,6 @@ static int __init pasic3_probe(struct platform_device *pdev)
ds1wm_pdata.clock_rate = pdata->clock_rate; ds1wm_pdata.clock_rate = pdata->clock_rate;
/* the first 5 PASIC3 registers control the DS1WM */ /* the first 5 PASIC3 registers control the DS1WM */
ds1wm_resources[0].end = (5 << asic->bus_shift) - 1; ds1wm_resources[0].end = (5 << asic->bus_shift) - 1;
ds1wm_cell.platform_data = &ds1wm_cell;
ds1wm_cell.data_size = sizeof(ds1wm_cell);
ret = mfd_add_devices(&pdev->dev, pdev->id, ret = mfd_add_devices(&pdev->dev, pdev->id,
&ds1wm_cell, 1, r, irq); &ds1wm_cell, 1, r, irq);
if (ret < 0) if (ret < 0)
...@@ -174,9 +172,6 @@ static int __init pasic3_probe(struct platform_device *pdev) ...@@ -174,9 +172,6 @@ static int __init pasic3_probe(struct platform_device *pdev)
} }
if (pdata && pdata->led_pdata) { if (pdata && pdata->led_pdata) {
led_cell.driver_data = pdata->led_pdata;
led_cell.platform_data = &led_cell;
led_cell.data_size = sizeof(ds1wm_cell);
ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0); ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0);
if (ret < 0) if (ret < 0)
dev_warn(dev, "failed to register LED device\n"); dev_warn(dev, "failed to register LED device\n");
......
...@@ -86,8 +86,7 @@ static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv, ...@@ -86,8 +86,7 @@ static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv,
/* Add platform data */ /* Add platform data */
pdata->modno = modno; pdata->modno = modno;
cell->platform_data = pdata; cell->mfd_data = pdata;
cell->data_size = sizeof(*pdata);
/* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */ /* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */
res->flags = IORESOURCE_MEM; res->flags = IORESOURCE_MEM;
......
...@@ -232,8 +232,6 @@ const struct mfd_cell jz4740_adc_cells[] = { ...@@ -232,8 +232,6 @@ const struct mfd_cell jz4740_adc_cells[] = {
.name = "jz4740-hwmon", .name = "jz4740-hwmon",
.num_resources = ARRAY_SIZE(jz4740_hwmon_resources), .num_resources = ARRAY_SIZE(jz4740_hwmon_resources),
.resources = jz4740_hwmon_resources, .resources = jz4740_hwmon_resources,
.platform_data = (void *)&jz4740_adc_cells[0],
.data_size = sizeof(struct mfd_cell),
.enable = jz4740_adc_cell_enable, .enable = jz4740_adc_cell_enable,
.disable = jz4740_adc_cell_disable, .disable = jz4740_adc_cell_disable,
...@@ -243,8 +241,6 @@ const struct mfd_cell jz4740_adc_cells[] = { ...@@ -243,8 +241,6 @@ const struct mfd_cell jz4740_adc_cells[] = {
.name = "jz4740-battery", .name = "jz4740-battery",
.num_resources = ARRAY_SIZE(jz4740_battery_resources), .num_resources = ARRAY_SIZE(jz4740_battery_resources),
.resources = jz4740_battery_resources, .resources = jz4740_battery_resources,
.platform_data = (void *)&jz4740_adc_cells[1],
.data_size = sizeof(struct mfd_cell),
.enable = jz4740_adc_cell_enable, .enable = jz4740_adc_cell_enable,
.disable = jz4740_adc_cell_disable, .disable = jz4740_adc_cell_disable,
......
...@@ -61,6 +61,7 @@ static struct mfd_cell lpc_sch_cells[] = { ...@@ -61,6 +61,7 @@ static struct mfd_cell lpc_sch_cells[] = {
static struct pci_device_id lpc_sch_ids[] = { static struct pci_device_id 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) },
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE(pci, lpc_sch_ids); MODULE_DEVICE_TABLE(pci, lpc_sch_ids);
...@@ -70,6 +71,7 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev, ...@@ -70,6 +71,7 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,
{ {
unsigned int base_addr_cfg; unsigned int base_addr_cfg;
unsigned short base_addr; unsigned short base_addr;
int i;
pci_read_config_dword(dev, SMBASE, &base_addr_cfg); pci_read_config_dword(dev, SMBASE, &base_addr_cfg);
if (!(base_addr_cfg & (1 << 31))) { if (!(base_addr_cfg & (1 << 31))) {
...@@ -99,7 +101,10 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev, ...@@ -99,7 +101,10 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,
gpio_sch_resource.start = base_addr; gpio_sch_resource.start = base_addr;
gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1; gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1;
return mfd_add_devices(&dev->dev, -1, for (i=0; i < ARRAY_SIZE(lpc_sch_cells); i++)
lpc_sch_cells[i].id = id->device;
return mfd_add_devices(&dev->dev, 0,
lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0); lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0);
} }
......
This diff is collapsed.
...@@ -233,7 +233,7 @@ struct max8998_reg_dump { ...@@ -233,7 +233,7 @@ struct max8998_reg_dump {
u8 val; u8 val;
}; };
#define SAVE_ITEM(x) { .addr = (x), .val = 0x0, } #define SAVE_ITEM(x) { .addr = (x), .val = 0x0, }
struct max8998_reg_dump max8998_dump[] = { static struct max8998_reg_dump max8998_dump[] = {
SAVE_ITEM(MAX8998_REG_IRQM1), SAVE_ITEM(MAX8998_REG_IRQM1),
SAVE_ITEM(MAX8998_REG_IRQM2), SAVE_ITEM(MAX8998_REG_IRQM2),
SAVE_ITEM(MAX8998_REG_IRQM3), SAVE_ITEM(MAX8998_REG_IRQM3),
...@@ -298,7 +298,7 @@ static int max8998_restore(struct device *dev) ...@@ -298,7 +298,7 @@ static int max8998_restore(struct device *dev)
return 0; return 0;
} }
const struct dev_pm_ops max8998_pm = { static const struct dev_pm_ops max8998_pm = {
.suspend = max8998_suspend, .suspend = max8998_suspend,
.resume = max8998_resume, .resume = max8998_resume,
.freeze = max8998_freeze, .freeze = max8998_freeze,
......
...@@ -683,14 +683,13 @@ int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, ...@@ -683,14 +683,13 @@ int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode,
EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion); EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion);
static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx, static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx,
const char *format, void *pdata, size_t pdata_size) const char *format, void *pdata)
{ {
char buf[30]; char buf[30];
const char *name = mc13xxx_get_chipname(mc13xxx); const char *name = mc13xxx_get_chipname(mc13xxx);
struct mfd_cell cell = { struct mfd_cell cell = {
.platform_data = pdata, .mfd_data = pdata,
.data_size = pdata_size,
}; };
/* there is no asnprintf in the kernel :-( */ /* there is no asnprintf in the kernel :-( */
...@@ -706,7 +705,7 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx, ...@@ -706,7 +705,7 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx,
static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format) static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format)
{ {
return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL, 0); return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL);
} }
static int mc13xxx_probe(struct spi_device *spi) static int mc13xxx_probe(struct spi_device *spi)
...@@ -764,13 +763,8 @@ static int mc13xxx_probe(struct spi_device *spi) ...@@ -764,13 +763,8 @@ static int mc13xxx_probe(struct spi_device *spi)
mc13xxx_add_subdevice(mc13xxx, "%s-codec"); mc13xxx_add_subdevice(mc13xxx, "%s-codec");
if (pdata->flags & MC13XXX_USE_REGULATOR) { if (pdata->flags & MC13XXX_USE_REGULATOR) {
struct mc13xxx_regulator_platform_data regulator_pdata = {
.num_regulators = pdata->num_regulators,
.regulators = pdata->regulators,
};
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator", mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
&regulator_pdata, sizeof(regulator_pdata)); &pdata->regulators);
} }
if (pdata->flags & MC13XXX_USE_RTC) if (pdata->flags & MC13XXX_USE_RTC)
...@@ -779,10 +773,8 @@ static int mc13xxx_probe(struct spi_device *spi) ...@@ -779,10 +773,8 @@ static int mc13xxx_probe(struct spi_device *spi)
if (pdata->flags & MC13XXX_USE_TOUCHSCREEN) if (pdata->flags & MC13XXX_USE_TOUCHSCREEN)
mc13xxx_add_subdevice(mc13xxx, "%s-ts"); mc13xxx_add_subdevice(mc13xxx, "%s-ts");
if (pdata->flags & MC13XXX_USE_LED) { if (pdata->flags & MC13XXX_USE_LED)
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", pdata->leds);
pdata->leds, sizeof(*pdata->leds));
}
return 0; return 0;
} }
...@@ -811,6 +803,7 @@ static const struct spi_device_id mc13xxx_device_id[] = { ...@@ -811,6 +803,7 @@ static const struct spi_device_id mc13xxx_device_id[] = {
/* sentinel */ /* sentinel */
} }
}; };
MODULE_DEVICE_TABLE(spi, mc13xxx_device_id);
static struct spi_driver mc13xxx_driver = { static struct spi_driver mc13xxx_driver = {
.id_table = mc13xxx_device_id, .id_table = mc13xxx_device_id,
......
...@@ -18,6 +18,43 @@ ...@@ -18,6 +18,43 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/slab.h> #include <linux/slab.h>
int mfd_cell_enable(struct platform_device *pdev)
{
const struct mfd_cell *cell = mfd_get_cell(pdev);
int err = 0;
/* only call enable hook if the cell wasn't previously enabled */
if (atomic_inc_return(cell->usage_count) == 1)
err = cell->enable(pdev);
/* if the enable hook failed, decrement counter to allow retries */
if (err)
atomic_dec(cell->usage_count);
return err;
}
EXPORT_SYMBOL(mfd_cell_enable);
int mfd_cell_disable(struct platform_device *pdev)
{
const struct mfd_cell *cell = mfd_get_cell(pdev);
int err = 0;
/* only disable if no other clients are using it */
if (atomic_dec_return(cell->usage_count) == 0)
err = cell->disable(pdev);
/* if the disable hook failed, increment to allow retries */
if (err)
atomic_inc(cell->usage_count);
/* sanity check; did someone call disable too many times? */
WARN_ON(atomic_read(cell->usage_count) < 0);
return err;
}
EXPORT_SYMBOL(mfd_cell_disable);
static int mfd_add_device(struct device *parent, int id, static int mfd_add_device(struct device *parent, int id,
const struct mfd_cell *cell, const struct mfd_cell *cell,
struct resource *mem_base, struct resource *mem_base,
...@@ -37,14 +74,10 @@ static int mfd_add_device(struct device *parent, int id, ...@@ -37,14 +74,10 @@ static int mfd_add_device(struct device *parent, int id,
goto fail_device; goto fail_device;
pdev->dev.parent = parent; pdev->dev.parent = parent;
platform_set_drvdata(pdev, cell->driver_data);
if (cell->data_size) { ret = platform_device_add_data(pdev, cell, sizeof(*cell));
ret = platform_device_add_data(pdev,
cell->platform_data, cell->data_size);
if (ret) if (ret)
goto fail_res; goto fail_res;
}
for (r = 0; r < cell->num_resources; r++) { for (r = 0; r < cell->num_resources; r++) {
res[r].name = cell->resources[r].name; res[r].name = cell->resources[r].name;
...@@ -100,14 +133,22 @@ static int mfd_add_device(struct device *parent, int id, ...@@ -100,14 +133,22 @@ static int mfd_add_device(struct device *parent, int id,
} }
int mfd_add_devices(struct device *parent, int id, int mfd_add_devices(struct device *parent, int id,
const struct mfd_cell *cells, int n_devs, struct mfd_cell *cells, int n_devs,
struct resource *mem_base, struct resource *mem_base,
int irq_base) int irq_base)
{ {
int i; int i;
int ret = 0; int ret = 0;
atomic_t *cnts;
/* initialize reference counting for all cells */
cnts = kcalloc(sizeof(*cnts), n_devs, GFP_KERNEL);
if (!cnts)
return -ENOMEM;
for (i = 0; i < n_devs; i++) { for (i = 0; i < n_devs; i++) {
atomic_set(&cnts[i], 0);
cells[i].usage_count = &cnts[i];
ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base); ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base);
if (ret) if (ret)
break; break;
...@@ -120,17 +161,89 @@ int mfd_add_devices(struct device *parent, int id, ...@@ -120,17 +161,89 @@ int mfd_add_devices(struct device *parent, int id,
} }
EXPORT_SYMBOL(mfd_add_devices); EXPORT_SYMBOL(mfd_add_devices);
static int mfd_remove_devices_fn(struct device *dev, void *unused) static int mfd_remove_devices_fn(struct device *dev, void *c)
{ {
platform_device_unregister(to_platform_device(dev)); struct platform_device *pdev = to_platform_device(dev);
const struct mfd_cell *cell = mfd_get_cell(pdev);
atomic_t **usage_count = c;
/* find the base address of usage_count pointers (for freeing) */
if (!*usage_count || (cell->usage_count < *usage_count))
*usage_count = cell->usage_count;
platform_device_unregister(pdev);
return 0; return 0;
} }
void mfd_remove_devices(struct device *parent) void mfd_remove_devices(struct device *parent)
{ {
device_for_each_child(parent, NULL, mfd_remove_devices_fn); atomic_t *cnts = NULL;
device_for_each_child(parent, &cnts, mfd_remove_devices_fn);
kfree(cnts);
} }
EXPORT_SYMBOL(mfd_remove_devices); EXPORT_SYMBOL(mfd_remove_devices);
static int add_shared_platform_device(const char *cell, const char *name)
{
struct mfd_cell cell_entry;
struct device *dev;
struct platform_device *pdev;
int err;
/* check if we've already registered a device (don't fail if we have) */
if (bus_find_device_by_name(&platform_bus_type, NULL, name))
return 0;
/* fetch the parent cell's device (should already be registered!) */
dev = bus_find_device_by_name(&platform_bus_type, NULL, cell);
if (!dev) {
printk(KERN_ERR "failed to find device for cell %s\n", cell);
return -ENODEV;
}
pdev = to_platform_device(dev);
memcpy(&cell_entry, mfd_get_cell(pdev), sizeof(cell_entry));
WARN_ON(!cell_entry.enable);
cell_entry.name = name;
err = mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0);
if (err)
dev_err(dev, "MFD add devices failed: %d\n", err);
return err;
}
int mfd_shared_platform_driver_register(struct platform_driver *drv,
const char *cellname)
{
int err;
err = add_shared_platform_device(cellname, drv->driver.name);
if (err)
printk(KERN_ERR "failed to add platform device %s\n",
drv->driver.name);
err = platform_driver_register(drv);
if (err)
printk(KERN_ERR "failed to add platform driver %s\n",
drv->driver.name);
return err;
}
EXPORT_SYMBOL(mfd_shared_platform_driver_register);
void mfd_shared_platform_driver_unregister(struct platform_driver *drv)
{
struct device *dev;
dev = bus_find_device_by_name(&platform_bus_type, NULL,
drv->driver.name);
if (dev)
platform_device_unregister(to_platform_device(dev));
platform_driver_unregister(drv);
}
EXPORT_SYMBOL(mfd_shared_platform_driver_unregister);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov"); MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov");
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/pm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mfd/pcf50633/core.h> #include <linux/mfd/pcf50633/core.h>
...@@ -230,27 +231,26 @@ pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name, ...@@ -230,27 +231,26 @@ pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name,
} }
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
static int pcf50633_suspend(struct i2c_client *client, pm_message_t state) static int pcf50633_suspend(struct device *dev)
{ {
struct pcf50633 *pcf; struct i2c_client *client = to_i2c_client(dev);
pcf = i2c_get_clientdata(client); struct pcf50633 *pcf = i2c_get_clientdata(client);
return pcf50633_irq_suspend(pcf); return pcf50633_irq_suspend(pcf);
} }
static int pcf50633_resume(struct i2c_client *client) static int pcf50633_resume(struct device *dev)
{ {
struct pcf50633 *pcf; struct i2c_client *client = to_i2c_client(dev);
pcf = i2c_get_clientdata(client); struct pcf50633 *pcf = i2c_get_clientdata(client);
return pcf50633_irq_resume(pcf); return pcf50633_irq_resume(pcf);
} }
#else
#define pcf50633_suspend NULL
#define pcf50633_resume NULL
#endif #endif
static SIMPLE_DEV_PM_OPS(pcf50633_pm, pcf50633_suspend, pcf50633_resume);
static int __devinit pcf50633_probe(struct i2c_client *client, static int __devinit pcf50633_probe(struct i2c_client *client,
const struct i2c_device_id *ids) const struct i2c_device_id *ids)
{ {
...@@ -360,16 +360,16 @@ static struct i2c_device_id pcf50633_id_table[] = { ...@@ -360,16 +360,16 @@ static struct i2c_device_id pcf50633_id_table[] = {
{"pcf50633", 0x73}, {"pcf50633", 0x73},
{/* end of list */} {/* end of list */}
}; };
MODULE_DEVICE_TABLE(i2c, pcf50633_id_table);
static struct i2c_driver pcf50633_driver = { static struct i2c_driver pcf50633_driver = {
.driver = { .driver = {
.name = "pcf50633", .name = "pcf50633",
.pm = &pcf50633_pm,
}, },
.id_table = pcf50633_id_table, .id_table = pcf50633_id_table,
.probe = pcf50633_probe, .probe = pcf50633_probe,
.remove = __devexit_p(pcf50633_remove), .remove = __devexit_p(pcf50633_remove),
.suspend = pcf50633_suspend,
.resume = pcf50633_resume,
}; };
static int __init pcf50633_init(void) static int __init pcf50633_init(void)
......
...@@ -61,12 +61,12 @@ static struct mfd_cell rdc321x_sb_cells[] = { ...@@ -61,12 +61,12 @@ static struct mfd_cell rdc321x_sb_cells[] = {
.name = "rdc321x-wdt", .name = "rdc321x-wdt",
.resources = rdc321x_wdt_resource, .resources = rdc321x_wdt_resource,
.num_resources = ARRAY_SIZE(rdc321x_wdt_resource), .num_resources = ARRAY_SIZE(rdc321x_wdt_resource),
.driver_data = &rdc321x_wdt_pdata, .mfd_data = &rdc321x_wdt_pdata,
}, { }, {
.name = "rdc321x-gpio", .name = "rdc321x-gpio",
.resources = rdc321x_gpio_resources, .resources = rdc321x_gpio_resources,
.num_resources = ARRAY_SIZE(rdc321x_gpio_resources), .num_resources = ARRAY_SIZE(rdc321x_gpio_resources),
.driver_data = &rdc321x_gpio_pdata, .mfd_data = &rdc321x_gpio_pdata,
}, },
}; };
......
...@@ -146,9 +146,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) ...@@ -146,9 +146,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
} }
memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc)); memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc));
priv->cell_mmc.driver_data = mmc_data; priv->cell_mmc.mfd_data = mmc_data;
priv->cell_mmc.platform_data = &priv->cell_mmc;
priv->cell_mmc.data_size = sizeof(priv->cell_mmc);
platform_set_drvdata(pdev, priv); platform_set_drvdata(pdev, priv);
......
...@@ -170,7 +170,7 @@ static struct mfd_cell t7l66xb_cells[] = { ...@@ -170,7 +170,7 @@ static struct mfd_cell t7l66xb_cells[] = {
.name = "tmio-mmc", .name = "tmio-mmc",
.enable = t7l66xb_mmc_enable, .enable = t7l66xb_mmc_enable,
.disable = t7l66xb_mmc_disable, .disable = t7l66xb_mmc_disable,
.driver_data = &t7166xb_mmc_data, .mfd_data = &t7166xb_mmc_data,
.num_resources = ARRAY_SIZE(t7l66xb_mmc_resources), .num_resources = ARRAY_SIZE(t7l66xb_mmc_resources),
.resources = t7l66xb_mmc_resources, .resources = t7l66xb_mmc_resources,
}, },
...@@ -383,16 +383,7 @@ static int t7l66xb_probe(struct platform_device *dev) ...@@ -383,16 +383,7 @@ static int t7l66xb_probe(struct platform_device *dev)
t7l66xb_attach_irq(dev); t7l66xb_attach_irq(dev);
t7l66xb_cells[T7L66XB_CELL_NAND].driver_data = pdata->nand_data; t7l66xb_cells[T7L66XB_CELL_NAND].mfd_data = pdata->nand_data;
t7l66xb_cells[T7L66XB_CELL_NAND].platform_data =
&t7l66xb_cells[T7L66XB_CELL_NAND];
t7l66xb_cells[T7L66XB_CELL_NAND].data_size =
sizeof(t7l66xb_cells[T7L66XB_CELL_NAND]);
t7l66xb_cells[T7L66XB_CELL_MMC].platform_data =
&t7l66xb_cells[T7L66XB_CELL_MMC];
t7l66xb_cells[T7L66XB_CELL_MMC].data_size =
sizeof(t7l66xb_cells[T7L66XB_CELL_MMC]);
ret = mfd_add_devices(&dev->dev, dev->id, ret = mfd_add_devices(&dev->dev, dev->id,
t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells), t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells),
......
...@@ -131,7 +131,7 @@ static struct mfd_cell tc6387xb_cells[] = { ...@@ -131,7 +131,7 @@ static struct mfd_cell tc6387xb_cells[] = {
.name = "tmio-mmc", .name = "tmio-mmc",
.enable = tc6387xb_mmc_enable, .enable = tc6387xb_mmc_enable,
.disable = tc6387xb_mmc_disable, .disable = tc6387xb_mmc_disable,
.driver_data = &tc6387xb_mmc_data, .mfd_data = &tc6387xb_mmc_data,
.num_resources = ARRAY_SIZE(tc6387xb_mmc_resources), .num_resources = ARRAY_SIZE(tc6387xb_mmc_resources),
.resources = tc6387xb_mmc_resources, .resources = tc6387xb_mmc_resources,
}, },
...@@ -190,11 +190,6 @@ static int __devinit tc6387xb_probe(struct platform_device *dev) ...@@ -190,11 +190,6 @@ static int __devinit tc6387xb_probe(struct platform_device *dev)
printk(KERN_INFO "Toshiba tc6387xb initialised\n"); printk(KERN_INFO "Toshiba tc6387xb initialised\n");
tc6387xb_cells[TC6387XB_CELL_MMC].platform_data =
&tc6387xb_cells[TC6387XB_CELL_MMC];
tc6387xb_cells[TC6387XB_CELL_MMC].data_size =
sizeof(tc6387xb_cells[TC6387XB_CELL_MMC]);
ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells, ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells,
ARRAY_SIZE(tc6387xb_cells), iomem, irq); ARRAY_SIZE(tc6387xb_cells), iomem, irq);
......
...@@ -393,7 +393,7 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = { ...@@ -393,7 +393,7 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = {
.name = "tmio-mmc", .name = "tmio-mmc",
.enable = tc6393xb_mmc_enable, .enable = tc6393xb_mmc_enable,
.resume = tc6393xb_mmc_resume, .resume = tc6393xb_mmc_resume,
.driver_data = &tc6393xb_mmc_data, .mfd_data = &tc6393xb_mmc_data,
.num_resources = ARRAY_SIZE(tc6393xb_mmc_resources), .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
.resources = tc6393xb_mmc_resources, .resources = tc6393xb_mmc_resources,
}, },
...@@ -693,27 +693,8 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) ...@@ -693,27 +693,8 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
goto err_setup; goto err_setup;
} }
tc6393xb_cells[TC6393XB_CELL_NAND].driver_data = tcpd->nand_data; tc6393xb_cells[TC6393XB_CELL_NAND].mfd_data = tcpd->nand_data;
tc6393xb_cells[TC6393XB_CELL_NAND].platform_data = tc6393xb_cells[TC6393XB_CELL_FB].mfd_data = tcpd->fb_data;
&tc6393xb_cells[TC6393XB_CELL_NAND];
tc6393xb_cells[TC6393XB_CELL_NAND].data_size =
sizeof(tc6393xb_cells[TC6393XB_CELL_NAND]);
tc6393xb_cells[TC6393XB_CELL_MMC].platform_data =
&tc6393xb_cells[TC6393XB_CELL_MMC];
tc6393xb_cells[TC6393XB_CELL_MMC].data_size =
sizeof(tc6393xb_cells[TC6393XB_CELL_MMC]);
tc6393xb_cells[TC6393XB_CELL_OHCI].platform_data =
&tc6393xb_cells[TC6393XB_CELL_OHCI];
tc6393xb_cells[TC6393XB_CELL_OHCI].data_size =
sizeof(tc6393xb_cells[TC6393XB_CELL_OHCI]);
tc6393xb_cells[TC6393XB_CELL_FB].driver_data = tcpd->fb_data;
tc6393xb_cells[TC6393XB_CELL_FB].platform_data =
&tc6393xb_cells[TC6393XB_CELL_FB];
tc6393xb_cells[TC6393XB_CELL_FB].data_size =
sizeof(tc6393xb_cells[TC6393XB_CELL_FB]);
ret = mfd_add_devices(&dev->dev, dev->id, ret = mfd_add_devices(&dev->dev, dev->id,
tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
......
...@@ -384,8 +384,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = { ...@@ -384,8 +384,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
.name = "timb-dma", .name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources), .num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources, .resources = timberdale_dma_resources,
.platform_data = &timb_dma_platform_data, .mfd_data = &timb_dma_platform_data,
.data_size = sizeof(timb_dma_platform_data),
}, },
{ {
.name = "timb-uart", .name = "timb-uart",
...@@ -396,43 +395,37 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = { ...@@ -396,43 +395,37 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
.name = "xiic-i2c", .name = "xiic-i2c",
.num_resources = ARRAY_SIZE(timberdale_xiic_resources), .num_resources = ARRAY_SIZE(timberdale_xiic_resources),
.resources = timberdale_xiic_resources, .resources = timberdale_xiic_resources,
.platform_data = &timberdale_xiic_platform_data, .mfd_data = &timberdale_xiic_platform_data,
.data_size = sizeof(timberdale_xiic_platform_data),
}, },
{ {
.name = "timb-gpio", .name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources), .num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources, .resources = timberdale_gpio_resources,
.platform_data = &timberdale_gpio_platform_data, .mfd_data = &timberdale_gpio_platform_data,
.data_size = sizeof(timberdale_gpio_platform_data),
}, },
{ {
.name = "timb-video", .name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources), .num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources, .resources = timberdale_video_resources,
.platform_data = &timberdale_video_platform_data, .mfd_data = &timberdale_video_platform_data,
.data_size = sizeof(timberdale_video_platform_data),
}, },
{ {
.name = "timb-radio", .name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources), .num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources, .resources = timberdale_radio_resources,
.platform_data = &timberdale_radio_platform_data, .mfd_data = &timberdale_radio_platform_data,
.data_size = sizeof(timberdale_radio_platform_data),
}, },
{ {
.name = "xilinx_spi", .name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources), .num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources, .resources = timberdale_spi_resources,
.platform_data = &timberdale_xspi_platform_data, .mfd_data = &timberdale_xspi_platform_data,
.data_size = sizeof(timberdale_xspi_platform_data),
}, },
{ {
.name = "ks8842", .name = "ks8842",
.num_resources = ARRAY_SIZE(timberdale_eth_resources), .num_resources = ARRAY_SIZE(timberdale_eth_resources),
.resources = timberdale_eth_resources, .resources = timberdale_eth_resources,
.platform_data = &timberdale_ks8842_platform_data, .mfd_data = &timberdale_ks8842_platform_data,
.data_size = sizeof(timberdale_ks8842_platform_data)
}, },
}; };
...@@ -441,8 +434,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { ...@@ -441,8 +434,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
.name = "timb-dma", .name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources), .num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources, .resources = timberdale_dma_resources,
.platform_data = &timb_dma_platform_data, .mfd_data = &timb_dma_platform_data,
.data_size = sizeof(timb_dma_platform_data),
}, },
{ {
.name = "timb-uart", .name = "timb-uart",
...@@ -458,15 +450,13 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { ...@@ -458,15 +450,13 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
.name = "xiic-i2c", .name = "xiic-i2c",
.num_resources = ARRAY_SIZE(timberdale_xiic_resources), .num_resources = ARRAY_SIZE(timberdale_xiic_resources),
.resources = timberdale_xiic_resources, .resources = timberdale_xiic_resources,
.platform_data = &timberdale_xiic_platform_data, .mfd_data = &timberdale_xiic_platform_data,
.data_size = sizeof(timberdale_xiic_platform_data),
}, },
{ {
.name = "timb-gpio", .name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources), .num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources, .resources = timberdale_gpio_resources,
.platform_data = &timberdale_gpio_platform_data, .mfd_data = &timberdale_gpio_platform_data,
.data_size = sizeof(timberdale_gpio_platform_data),
}, },
{ {
.name = "timb-mlogicore", .name = "timb-mlogicore",
...@@ -477,29 +467,25 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { ...@@ -477,29 +467,25 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
.name = "timb-video", .name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources), .num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources, .resources = timberdale_video_resources,
.platform_data = &timberdale_video_platform_data, .mfd_data = &timberdale_video_platform_data,
.data_size = sizeof(timberdale_video_platform_data),
}, },
{ {
.name = "timb-radio", .name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources), .num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources, .resources = timberdale_radio_resources,
.platform_data = &timberdale_radio_platform_data, .mfd_data = &timberdale_radio_platform_data,
.data_size = sizeof(timberdale_radio_platform_data),
}, },
{ {
.name = "xilinx_spi", .name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources), .num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources, .resources = timberdale_spi_resources,
.platform_data = &timberdale_xspi_platform_data, .mfd_data = &timberdale_xspi_platform_data,
.data_size = sizeof(timberdale_xspi_platform_data),
}, },
{ {
.name = "ks8842", .name = "ks8842",
.num_resources = ARRAY_SIZE(timberdale_eth_resources), .num_resources = ARRAY_SIZE(timberdale_eth_resources),
.resources = timberdale_eth_resources, .resources = timberdale_eth_resources,
.platform_data = &timberdale_ks8842_platform_data, .mfd_data = &timberdale_ks8842_platform_data,
.data_size = sizeof(timberdale_ks8842_platform_data)
}, },
}; };
...@@ -508,8 +494,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = { ...@@ -508,8 +494,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
.name = "timb-dma", .name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources), .num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources, .resources = timberdale_dma_resources,
.platform_data = &timb_dma_platform_data, .mfd_data = &timb_dma_platform_data,
.data_size = sizeof(timb_dma_platform_data),
}, },
{ {
.name = "timb-uart", .name = "timb-uart",
...@@ -520,36 +505,31 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = { ...@@ -520,36 +505,31 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
.name = "xiic-i2c", .name = "xiic-i2c",
.num_resources = ARRAY_SIZE(timberdale_xiic_resources), .num_resources = ARRAY_SIZE(timberdale_xiic_resources),
.resources = timberdale_xiic_resources, .resources = timberdale_xiic_resources,
.platform_data = &timberdale_xiic_platform_data, .mfd_data = &timberdale_xiic_platform_data,
.data_size = sizeof(timberdale_xiic_platform_data),
}, },
{ {
.name = "timb-gpio", .name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources), .num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources, .resources = timberdale_gpio_resources,
.platform_data = &timberdale_gpio_platform_data, .mfd_data = &timberdale_gpio_platform_data,
.data_size = sizeof(timberdale_gpio_platform_data),
}, },
{ {
.name = "timb-video", .name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources), .num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources, .resources = timberdale_video_resources,
.platform_data = &timberdale_video_platform_data, .mfd_data = &timberdale_video_platform_data,
.data_size = sizeof(timberdale_video_platform_data),
}, },
{ {
.name = "timb-radio", .name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources), .num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources, .resources = timberdale_radio_resources,
.platform_data = &timberdale_radio_platform_data, .mfd_data = &timberdale_radio_platform_data,
.data_size = sizeof(timberdale_radio_platform_data),
}, },
{ {
.name = "xilinx_spi", .name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources), .num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources, .resources = timberdale_spi_resources,
.platform_data = &timberdale_xspi_platform_data, .mfd_data = &timberdale_xspi_platform_data,
.data_size = sizeof(timberdale_xspi_platform_data),
}, },
}; };
...@@ -558,8 +538,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = { ...@@ -558,8 +538,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
.name = "timb-dma", .name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources), .num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources, .resources = timberdale_dma_resources,
.platform_data = &timb_dma_platform_data, .mfd_data = &timb_dma_platform_data,
.data_size = sizeof(timb_dma_platform_data),
}, },
{ {
.name = "timb-uart", .name = "timb-uart",
...@@ -570,43 +549,37 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = { ...@@ -570,43 +549,37 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
.name = "ocores-i2c", .name = "ocores-i2c",
.num_resources = ARRAY_SIZE(timberdale_ocores_resources), .num_resources = ARRAY_SIZE(timberdale_ocores_resources),
.resources = timberdale_ocores_resources, .resources = timberdale_ocores_resources,
.platform_data = &timberdale_ocores_platform_data, .mfd_data = &timberdale_ocores_platform_data,
.data_size = sizeof(timberdale_ocores_platform_data),
}, },
{ {
.name = "timb-gpio", .name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources), .num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources, .resources = timberdale_gpio_resources,
.platform_data = &timberdale_gpio_platform_data, .mfd_data = &timberdale_gpio_platform_data,
.data_size = sizeof(timberdale_gpio_platform_data),
}, },
{ {
.name = "timb-video", .name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources), .num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources, .resources = timberdale_video_resources,
.platform_data = &timberdale_video_platform_data, .mfd_data = &timberdale_video_platform_data,
.data_size = sizeof(timberdale_video_platform_data),
}, },
{ {
.name = "timb-radio", .name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources), .num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources, .resources = timberdale_radio_resources,
.platform_data = &timberdale_radio_platform_data, .mfd_data = &timberdale_radio_platform_data,
.data_size = sizeof(timberdale_radio_platform_data),
}, },
{ {
.name = "xilinx_spi", .name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources), .num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources, .resources = timberdale_spi_resources,
.platform_data = &timberdale_xspi_platform_data, .mfd_data = &timberdale_xspi_platform_data,
.data_size = sizeof(timberdale_xspi_platform_data),
}, },
{ {
.name = "ks8842", .name = "ks8842",
.num_resources = ARRAY_SIZE(timberdale_eth_resources), .num_resources = ARRAY_SIZE(timberdale_eth_resources),
.resources = timberdale_eth_resources, .resources = timberdale_eth_resources,
.platform_data = &timberdale_ks8842_platform_data, .mfd_data = &timberdale_ks8842_platform_data,
.data_size = sizeof(timberdale_ks8842_platform_data)
}, },
}; };
......
/*
* Core driver for TPS61050/61052 boost converters, used for while LED
* driving, audio power amplification, white LED flash, and generic
* boost conversion. Additionally it provides a 1-bit GPIO pin (out or in)
* and a flash synchronization pin to synchronize flash events when used as
* flashgun.
*
* Copyright (C) 2011 ST-Ericsson SA
* Written on behalf of Linaro for ST-Ericsson
*
* Author: Linus Walleij <linus.walleij@linaro.org>
*
* License terms: GNU General Public License (GPL) version 2
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/gpio.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/regulator/driver.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps6105x.h>
int tps6105x_set(struct tps6105x *tps6105x, u8 reg, u8 value)
{
int ret;
ret = mutex_lock_interruptible(&tps6105x->lock);
if (ret)
return ret;
ret = i2c_smbus_write_byte_data(tps6105x->client, reg, value);
mutex_unlock(&tps6105x->lock);
if (ret < 0)
return ret;
return 0;
}
EXPORT_SYMBOL(tps6105x_set);
int tps6105x_get(struct tps6105x *tps6105x, u8 reg, u8 *buf)
{
int ret;
ret = mutex_lock_interruptible(&tps6105x->lock);
if (ret)
return ret;
ret = i2c_smbus_read_byte_data(tps6105x->client, reg);
mutex_unlock(&tps6105x->lock);
if (ret < 0)
return ret;
*buf = ret;
return 0;
}
EXPORT_SYMBOL(tps6105x_get);
/*
* Masks off the bits in the mask and sets the bits in the bitvalues
* parameter in one atomic operation
*/
int tps6105x_mask_and_set(struct tps6105x *tps6105x, u8 reg,
u8 bitmask, u8 bitvalues)
{
int ret;
u8 regval;
ret = mutex_lock_interruptible(&tps6105x->lock);
if (ret)
return ret;
ret = i2c_smbus_read_byte_data(tps6105x->client, reg);
if (ret < 0)
goto fail;
regval = ret;
regval = (~bitmask & regval) | (bitmask & bitvalues);
ret = i2c_smbus_write_byte_data(tps6105x->client, reg, regval);
fail:
mutex_unlock(&tps6105x->lock);
if (ret < 0)
return ret;
return 0;
}
EXPORT_SYMBOL(tps6105x_mask_and_set);
static int __devinit tps6105x_startup(struct tps6105x *tps6105x)
{
int ret;
u8 regval;
ret = tps6105x_get(tps6105x, TPS6105X_REG_0, &regval);
if (ret)
return ret;
switch (regval >> TPS6105X_REG0_MODE_SHIFT) {
case TPS6105X_REG0_MODE_SHUTDOWN:
dev_info(&tps6105x->client->dev,
"TPS6105x found in SHUTDOWN mode\n");
break;
case TPS6105X_REG0_MODE_TORCH:
dev_info(&tps6105x->client->dev,
"TPS6105x found in TORCH mode\n");
break;
case TPS6105X_REG0_MODE_TORCH_FLASH:
dev_info(&tps6105x->client->dev,
"TPS6105x found in FLASH mode\n");
break;
case TPS6105X_REG0_MODE_VOLTAGE:
dev_info(&tps6105x->client->dev,
"TPS6105x found in VOLTAGE mode\n");
break;
default:
break;
}
return ret;
}
/*
* MFD cells - we have one cell which is selected operation
* mode, and we always have a GPIO cell.
*/
static struct mfd_cell tps6105x_cells[] = {
{
/* name will be runtime assigned */
.id = -1,
},
{
.name = "tps6105x-gpio",
.id = -1,
},
};
static int __devinit tps6105x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct tps6105x *tps6105x;
struct tps6105x_platform_data *pdata;
int ret;
int i;
tps6105x = kmalloc(sizeof(*tps6105x), GFP_KERNEL);
if (!tps6105x)
return -ENOMEM;
i2c_set_clientdata(client, tps6105x);
tps6105x->client = client;
pdata = client->dev.platform_data;
tps6105x->pdata = pdata;
mutex_init(&tps6105x->lock);
ret = tps6105x_startup(tps6105x);
if (ret) {
dev_err(&client->dev, "chip initialization failed\n");
goto fail;
}
/* Remove warning texts when you implement new cell drivers */
switch (pdata->mode) {
case TPS6105X_MODE_SHUTDOWN:
dev_info(&client->dev,
"present, not used for anything, only GPIO\n");
break;
case TPS6105X_MODE_TORCH:
tps6105x_cells[0].name = "tps6105x-leds";
dev_warn(&client->dev,
"torch mode is unsupported\n");
break;
case TPS6105X_MODE_TORCH_FLASH:
tps6105x_cells[0].name = "tps6105x-flash";
dev_warn(&client->dev,
"flash mode is unsupported\n");
break;
case TPS6105X_MODE_VOLTAGE:
tps6105x_cells[0].name ="tps6105x-regulator";
break;
default:
break;
}
/* Set up and register the platform devices. */
for (i = 0; i < ARRAY_SIZE(tps6105x_cells); i++) {
/* One state holder for all drivers, this is simple */
tps6105x_cells[i].mfd_data = tps6105x;
}
ret = mfd_add_devices(&client->dev, 0, tps6105x_cells,
ARRAY_SIZE(tps6105x_cells), NULL, 0);
if (ret)
goto fail;
return 0;
fail:
kfree(tps6105x);
return ret;
}
static int __devexit tps6105x_remove(struct i2c_client *client)
{
struct tps6105x *tps6105x = i2c_get_clientdata(client);
mfd_remove_devices(&client->dev);
/* Put chip in shutdown mode */
tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0,
TPS6105X_REG0_MODE_MASK,
TPS6105X_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT);
kfree(tps6105x);
return 0;
}
static const struct i2c_device_id tps6105x_id[] = {
{ "tps61050", 0 },
{ "tps61052", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tps6105x_id);
static struct i2c_driver tps6105x_driver = {
.driver = {
.name = "tps6105x",
},
.probe = tps6105x_probe,
.remove = __devexit_p(tps6105x_remove),
.id_table = tps6105x_id,
};
static int __init tps6105x_init(void)
{
return i2c_add_driver(&tps6105x_driver);
}
subsys_initcall(tps6105x_init);
static void __exit tps6105x_exit(void)
{
i2c_del_driver(&tps6105x_driver);
}
module_exit(tps6105x_exit);
MODULE_AUTHOR("Linus Walleij");
MODULE_DESCRIPTION("TPS6105x White LED Boost Converter Driver");
MODULE_LICENSE("GPL v2");
...@@ -288,12 +288,10 @@ static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, ...@@ -288,12 +288,10 @@ static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset,
return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask); return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask);
} }
static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base) static int tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base)
{ {
int ret;
if (!gpio_base) if (!gpio_base)
return; return 0;
tps6586x->gpio.owner = THIS_MODULE; tps6586x->gpio.owner = THIS_MODULE;
tps6586x->gpio.label = tps6586x->client->name; tps6586x->gpio.label = tps6586x->client->name;
...@@ -307,9 +305,7 @@ static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base) ...@@ -307,9 +305,7 @@ static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base)
tps6586x->gpio.set = tps6586x_gpio_set; tps6586x->gpio.set = tps6586x_gpio_set;
tps6586x->gpio.get = tps6586x_gpio_get; tps6586x->gpio.get = tps6586x_gpio_get;
ret = gpiochip_add(&tps6586x->gpio); return gpiochip_add(&tps6586x->gpio);
if (ret)
dev_warn(tps6586x->dev, "GPIO registration failed: %d\n", ret);
} }
static int __remove_subdev(struct device *dev, void *unused) static int __remove_subdev(struct device *dev, void *unused)
...@@ -517,17 +513,28 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client, ...@@ -517,17 +513,28 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
} }
} }
ret = tps6586x_gpio_init(tps6586x, pdata->gpio_base);
if (ret) {
dev_err(&client->dev, "GPIO registration failed: %d\n", ret);
goto err_gpio_init;
}
ret = tps6586x_add_subdevs(tps6586x, pdata); ret = tps6586x_add_subdevs(tps6586x, pdata);
if (ret) { if (ret) {
dev_err(&client->dev, "add devices failed: %d\n", ret); dev_err(&client->dev, "add devices failed: %d\n", ret);
goto err_add_devs; goto err_add_devs;
} }
tps6586x_gpio_init(tps6586x, pdata->gpio_base);
return 0; return 0;
err_add_devs: err_add_devs:
if (pdata->gpio_base) {
ret = gpiochip_remove(&tps6586x->gpio);
if (ret)
dev_err(&client->dev, "Can't remove gpio chip: %d\n",
ret);
}
err_gpio_init:
if (client->irq) if (client->irq)
free_irq(client->irq, tps6586x); free_irq(client->irq, tps6586x);
err_irq_init: err_irq_init:
...@@ -587,4 +594,3 @@ module_exit(tps6586x_exit); ...@@ -587,4 +594,3 @@ module_exit(tps6586x_exit);
MODULE_DESCRIPTION("TPS6586X core driver"); MODULE_DESCRIPTION("TPS6586X core driver");
MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -721,13 +721,13 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) ...@@ -721,13 +721,13 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
} }
if (twl_has_watchdog()) { if (twl_has_watchdog() && twl_class_is_4030()) {
child = add_child(0, "twl4030_wdt", NULL, 0, false, 0, 0); child = add_child(0, "twl4030_wdt", NULL, 0, false, 0, 0);
if (IS_ERR(child)) if (IS_ERR(child))
return PTR_ERR(child); return PTR_ERR(child);
} }
if (twl_has_pwrbutton()) { if (twl_has_pwrbutton() && twl_class_is_4030()) {
child = add_child(1, "twl4030_pwrbutton", child = add_child(1, "twl4030_pwrbutton",
NULL, 0, true, pdata->irq_base + 8 + 0, 0); NULL, 0, true, pdata->irq_base + 8 + 0, 0);
if (IS_ERR(child)) if (IS_ERR(child))
...@@ -864,6 +864,10 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) ...@@ -864,6 +864,10 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3); child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3);
if (IS_ERR(child)) if (IS_ERR(child))
return PTR_ERR(child); return PTR_ERR(child);
child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg);
if (IS_ERR(child))
return PTR_ERR(child);
} }
if (twl_has_bci() && pdata->bci && if (twl_has_bci() && pdata->bci &&
......
...@@ -208,15 +208,13 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev) ...@@ -208,15 +208,13 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
if (pdata->audio) { if (pdata->audio) {
cell = &codec->cells[childs]; cell = &codec->cells[childs];
cell->name = "twl4030-codec"; cell->name = "twl4030-codec";
cell->platform_data = pdata->audio; cell->mfd_data = pdata->audio;
cell->data_size = sizeof(*pdata->audio);
childs++; childs++;
} }
if (pdata->vibra) { if (pdata->vibra) {
cell = &codec->cells[childs]; cell = &codec->cells[childs];
cell->name = "twl4030-vibra"; cell->name = "twl4030-vibra";
cell->platform_data = pdata->vibra; cell->mfd_data = pdata->vibra;
cell->data_size = sizeof(*pdata->vibra);
childs++; childs++;
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -122,6 +122,7 @@ static struct pci_device_id vx855_pci_tbl[] = { ...@@ -122,6 +122,7 @@ static struct pci_device_id vx855_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE(pci, vx855_pci_tbl);
static struct pci_driver vx855_pci_driver = { static struct pci_driver vx855_pci_driver = {
.name = "vx855", .name = "vx855",
......
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