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[] = {
};
/* MC13783 */
static struct mc13xxx_platform_data mc13783_pdata __initdata = {
.regulators = mx27_3ds_regulators,
.num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
.flags = MC13XXX_USE_REGULATOR,
static struct mc13xxx_platform_data mc13783_pdata = {
.regulators = {
.regulators = mx27_3ds_regulators,
.num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
},
.flags = MC13783_USE_REGULATOR,
};
/* SPI */
......
......@@ -263,10 +263,12 @@ static struct mc13xxx_regulator_init_data pcm038_regulators[] = {
};
static struct mc13xxx_platform_data pcm038_pmic = {
.regulators = pcm038_regulators,
.num_regulators = ARRAY_SIZE(pcm038_regulators),
.flags = MC13XXX_USE_ADC | MC13XXX_USE_REGULATOR |
MC13XXX_USE_TOUCHSCREEN,
.regulators = {
.regulators = pcm038_regulators,
.num_regulators = ARRAY_SIZE(pcm038_regulators),
},
.flags = MC13783_USE_ADC | MC13783_USE_REGULATOR |
MC13783_USE_TOUCHSCREEN,
};
static struct spi_board_info pcm038_spi_board_info[] __initdata = {
......
......@@ -488,10 +488,12 @@ static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = {
};
/* MC13783 */
static struct mc13xxx_platform_data mc13783_pdata __initdata = {
.regulators = mx31_3ds_regulators,
.num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
.flags = MC13XXX_USE_REGULATOR | MC13XXX_USE_TOUCHSCREEN
static struct mc13xxx_platform_data mc13783_pdata = {
.regulators = {
.regulators = mx31_3ds_regulators,
.num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
},
.flags = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN,
};
/* SPI */
......
......@@ -268,8 +268,10 @@ static struct mc13783_leds_platform_data moboard_leds = {
};
static struct mc13xxx_platform_data moboard_pmic = {
.regulators = moboard_regulators,
.num_regulators = ARRAY_SIZE(moboard_regulators),
.regulators = {
.regulators = moboard_regulators,
.num_regulators = ARRAY_SIZE(moboard_regulators),
},
.leds = &moboard_leds,
.flags = MC13XXX_USE_REGULATOR | MC13XXX_USE_RTC |
MC13XXX_USE_ADC | MC13XXX_USE_LED,
......
......@@ -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 = {
.irq_base = TWL6030_IRQ_BASE,
.irq_end = TWL6030_IRQ_END,
......@@ -565,6 +571,7 @@ static struct twl4030_platform_data sdp4430_twldata = {
.vaux1 = &sdp4430_vaux1,
.vaux2 = &sdp4430_vaux2,
.vaux3 = &sdp4430_vaux3,
.clk32kg = &sdp4430_clk32kg,
.usb = &omap4_usbphy_data
};
......
......@@ -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 = {
.irq_base = TWL6030_IRQ_BASE,
.irq_end = TWL6030_IRQ_END,
......@@ -426,6 +432,7 @@ static struct twl4030_platform_data omap4_panda_twldata = {
.vaux1 = &omap4_panda_vaux1,
.vaux2 = &omap4_panda_vaux2,
.vaux3 = &omap4_panda_vaux3,
.clk32kg = &omap4_panda_clk32kg,
.usb = &omap4_usbphy_data,
};
......
......@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/mfd/core.h>
#include <asm/io.h>
#include <asm/olpc.h>
......@@ -56,25 +57,24 @@ static void xo1_power_off(void)
static int __devinit olpc_xo1_probe(struct platform_device *pdev)
{
struct resource *res;
int err;
/* don't run on non-XOs */
if (!machine_is_olpc())
return -ENODEV;
err = mfd_cell_enable(pdev);
if (err)
return err;
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;
}
if (strcmp(pdev->name, "cs5535-pms") == 0)
if (strcmp(pdev->name, "olpc-xo1-pms") == 0)
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;
/* 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)
static int __devexit olpc_xo1_remove(struct platform_device *pdev)
{
struct resource *r;
r = platform_get_resource(pdev, IORESOURCE_IO, 0);
release_region(r->start, resource_size(r));
mfd_cell_disable(pdev);
if (strcmp(pdev->name, "cs5535-pms") == 0)
if (strcmp(pdev->name, "olpc-xo1-pms") == 0)
pms_base = 0;
else if (strcmp(pdev->name, "cs5535-acpi") == 0)
else if (strcmp(pdev->name, "olpc-xo1-acpi") == 0)
acpi_base = 0;
pm_power_off = NULL;
......@@ -104,7 +101,7 @@ static int __devexit olpc_xo1_remove(struct platform_device *pdev)
static struct platform_driver cs5535_pms_drv = {
.driver = {
.name = "cs5535-pms",
.name = "olpc-xo1-pms",
.owner = THIS_MODULE,
},
.probe = olpc_xo1_probe,
......@@ -113,7 +110,7 @@ static struct platform_driver cs5535_pms_drv = {
static struct platform_driver cs5535_acpi_drv = {
.driver = {
.name = "cs5535-acpi",
.name = "olpc-xo1-acpi",
.owner = THIS_MODULE,
},
.probe = olpc_xo1_probe,
......@@ -124,26 +121,27 @@ static int __init olpc_xo1_init(void)
{
int r;
r = platform_driver_register(&cs5535_pms_drv);
r = mfd_shared_platform_driver_register(&cs5535_pms_drv, "cs5535-pms");
if (r)
return r;
r = platform_driver_register(&cs5535_acpi_drv);
r = mfd_shared_platform_driver_register(&cs5535_acpi_drv,
"cs5535-acpi");
if (r)
platform_driver_unregister(&cs5535_pms_drv);
mfd_shared_platform_driver_unregister(&cs5535_pms_drv);
return r;
}
static void __exit olpc_xo1_exit(void)
{
platform_driver_unregister(&cs5535_acpi_drv);
platform_driver_unregister(&cs5535_pms_drv);
mfd_shared_platform_driver_unregister(&cs5535_acpi_drv);
mfd_shared_platform_driver_unregister(&cs5535_pms_drv);
}
MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:olpc-xo1");
MODULE_ALIAS("platform:cs5535-pms");
module_init(olpc_xo1_init);
module_exit(olpc_xo1_exit);
......@@ -27,6 +27,7 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/slab.h>
#include <linux/timb_dma.h>
......@@ -684,7 +685,7 @@ static irqreturn_t td_irq(int irq, void *devid)
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 resource *iomem;
int irq;
......
......@@ -100,18 +100,21 @@ config GPIO_VR41XX
Say yes here to support the NEC VR4100 series General-purpose I/O Uint
config GPIO_SCH
tristate "Intel SCH GPIO"
tristate "Intel SCH/TunnelCreek GPIO"
depends on GPIOLIB && PCI && X86
select MFD_CORE
select LPC_SCH
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
powered by the core power rail and are turned off during sleep
modes (S3 and higher). The remaining four GPIOs are powered by
the Intel SCH suspend power supply. These GPIOs remain
active during S3. The suspend powered GPIOs can be used to wake the
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
will be called sch-gpio.
......
......@@ -15,6 +15,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/slab.h>
......@@ -149,7 +150,7 @@ static int __devinit ttl_probe(struct platform_device *pdev)
struct resource *res;
int ret;
pdata = pdev->dev.platform_data;
pdata = mfd_get_data(pdev);
if (!pdata) {
dev_err(dev, "no platform data\n");
ret = -ENXIO;
......
......@@ -27,6 +27,7 @@
#include <linux/pci.h>
#include <linux/gpio.h>
#include <linux/mfd/rdc321x.h>
#include <linux/mfd/core.h>
#include <linux/slab.h>
struct rdc321x_gpio {
......@@ -135,7 +136,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
struct rdc321x_gpio *rdc321x_gpio_dev;
struct rdc321x_gpio_pdata *pdata;
pdata = platform_get_drvdata(pdev);
pdata = mfd_get_data(pdev);
if (!pdata) {
dev_err(&pdev->dev, "no platform data supplied\n");
return -ENODEV;
......
......@@ -25,6 +25,7 @@
#include <linux/errno.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
#include <linux/pci_ids.h>
#include <linux/gpio.h>
......@@ -187,7 +188,11 @@ static struct gpio_chip sch_gpio_resume = {
static int __devinit sch_gpio_probe(struct platform_device *pdev)
{
struct resource *res;
int err;
int err, id;
id = pdev->id;
if (!id)
return -ENODEV;
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!res)
......@@ -198,12 +203,40 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev)
gpio_ba = res->start;
sch_gpio_core.base = 0;
sch_gpio_core.ngpio = 10;
sch_gpio_core.dev = &pdev->dev;
switch (id) {
case PCI_DEVICE_ID_INTEL_SCH_LPC:
sch_gpio_core.base = 0;
sch_gpio_core.ngpio = 10;
sch_gpio_resume.base = 10;
sch_gpio_resume.ngpio = 4;
/*
* GPIO[6:0] enabled by default
* GPIO7 is configured by the CMC as SLPIOVR
* Enable GPIO[9:8] core powered gpios explicitly
*/
outb(0x3, gpio_ba + CGEN + 1);
/*
* SUS_GPIO[2:0] enabled by default
* Enable SUS_GPIO3 resume powered gpio explicitly
*/
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_resume.base = 10;
sch_gpio_resume.ngpio = 4;
sch_gpio_core.dev = &pdev->dev;
sch_gpio_resume.dev = &pdev->dev;
err = gpiochip_add(&sch_gpio_core);
......@@ -214,18 +247,6 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev)
if (err < 0)
goto err_sch_gpio_resume;
/*
* GPIO[6:0] enabled by default
* GPIO7 is configured by the CMC as SLPIOVR
* Enable GPIO[9:8] core powered gpios explicitly
*/
outb(0x3, gpio_ba + CGEN + 1);
/*
* SUS_GPIO[2:0] enabled by default
* Enable SUS_GPIO3 resume powered gpio explicitly
*/
outb(0x8, gpio_ba + RGEN);
return 0;
err_sch_gpio_resume:
......
......@@ -23,6 +23,7 @@
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/timb_gpio.h>
......@@ -228,7 +229,7 @@ static int __devinit timbgpio_probe(struct platform_device *pdev)
struct gpio_chip *gc;
struct timbgpio *tgpio;
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);
if (!pdata || pdata->nr_pins > 32) {
......@@ -319,14 +320,13 @@ static int __devinit timbgpio_probe(struct platform_device *pdev)
static int __devexit timbgpio_remove(struct platform_device *pdev)
{
int err;
struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
struct timbgpio *tgpio = platform_get_drvdata(pdev);
struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
int irq = platform_get_irq(pdev, 0);
if (irq >= 0 && tgpio->irq_base > 0) {
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_data(tgpio->irq_base + i, NULL);
}
......
......@@ -1047,6 +1047,16 @@ config SENSORS_TMP421
This driver can also be built as a module. If so, the module
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
tristate "VIA CPU temperature sensor"
depends on X86
......
......@@ -104,6 +104,7 @@ obj-$(CONFIG_SENSORS_THMC50) += thmc50.o
obj-$(CONFIG_SENSORS_TMP102) += tmp102.o
obj-$(CONFIG_SENSORS_TMP401) += tmp401.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_VIA686A) += via686a.o
obj-$(CONFIG_SENSORS_VT1211) += vt1211.o
......
......@@ -32,7 +32,7 @@ struct jz4740_hwmon {
int irq;
struct mfd_cell *cell;
const struct mfd_cell *cell;
struct device *hwmon;
struct completion read_completion;
......@@ -112,7 +112,7 @@ static int __devinit jz4740_hwmon_probe(struct platform_device *pdev)
return -ENOMEM;
}
hwmon->cell = pdev->dev.platform_data;
hwmon->cell = mfd_get_cell(pdev);
hwmon->irq = platform_get_irq(pdev, 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 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
......@@ -305,7 +306,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
return -EIO;
}
pdata = pdev->dev.platform_data;
pdata = mfd_get_data(pdev);
if (pdata) {
i2c->regstep = pdata->regstep;
i2c->clock_khz = pdata->clock_khz;
......
......@@ -34,6 +34,7 @@
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
......@@ -704,7 +705,7 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev)
if (irq < 0)
goto resource_missing;
pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data;
pdata = mfd_get_data(pdev);
if (!pdata)
return -EINVAL;
......
......@@ -74,7 +74,7 @@ static int __devinit pm860x_onkey_probe(struct platform_device *pdev)
info->chip = chip;
info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
info->dev = &pdev->dev;
info->irq = irq + chip->irq_base;
info->irq = irq;
info->idev = input_allocate_device();
if (!info->idev) {
......
......@@ -29,6 +29,7 @@
#include <linux/workqueue.h>
#include <linux/i2c/twl.h>
#include <linux/mfd/twl4030-codec.h>
#include <linux/mfd/core.h>
#include <linux/input.h>
#include <linux/slab.h>
......@@ -196,7 +197,7 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
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;
int ret;
......
......@@ -17,6 +17,7 @@
#include <linux/leds.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/mfd/core.h>
#include <linux/mfd/88pm860x.h>
#define LED_PWM_SHIFT (3)
......@@ -118,7 +119,8 @@ static void pm860x_led_work(struct work_struct *work)
struct pm860x_led *led;
struct pm860x_chip *chip;
int mask;
unsigned char buf[3];
int mask, ret;
led = container_of(work, struct pm860x_led, work);
chip = led->chip;
......@@ -128,16 +130,27 @@ static void pm860x_led_work(struct work_struct *work)
pm860x_set_bits(led->i2c, __led_off(led->port),
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);
pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask);
} else if (led->brightness == 0) {
pm860x_set_bits(led->i2c, __led_off(led->port),
LED_CURRENT_MASK, 0);
mask = __blink_ctl_mask(led->port);
pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 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),
LED_CURRENT_MASK, 0);
mask = __blink_ctl_mask(led->port);
pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0);
}
}
led->current_brightness = led->brightness;
dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n",
__led_off(led->port), led->brightness);
......@@ -153,31 +166,12 @@ static void pm860x_led_set(struct led_classdev *cdev,
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)
{
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm860x_platform_data *pm860x_pdata;
struct pm860x_led_pdata *pdata;
struct pm860x_led *data;
struct mfd_cell *cell;
struct resource *res;
int ret;
......@@ -187,10 +181,11 @@ static int pm860x_led_probe(struct platform_device *pdev)
return -EINVAL;
}
if (pdev->dev.parent->platform_data) {
pm860x_pdata = pdev->dev.parent->platform_data;
pdata = pm860x_pdata->led;
} else {
cell = pdev->dev.platform_data;
if (cell == NULL)
return -ENODEV;
pdata = cell->mfd_data;
if (pdata == NULL) {
dev_err(&pdev->dev, "No platform data!\n");
return -EINVAL;
}
......@@ -198,12 +193,12 @@ static int pm860x_led_probe(struct platform_device *pdev)
data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL);
if (data == NULL)
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);
data->chip = chip;
data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
data->iset = pdata->iset;
data->port = __check_device(pdata, data->name);
data->port = pdata->flags;
if (data->port < 0) {
dev_err(&pdev->dev, "check device failed\n");
kfree(data);
......@@ -221,6 +216,7 @@ static int pm860x_led_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
goto out;
}
pm860x_led_set(&data->cdev, 0);
return 0;
out:
kfree(data);
......
......@@ -22,6 +22,7 @@
#include <linux/leds.h>
#include <linux/workqueue.h>
#include <linux/mfd/mc13783.h>
#include <linux/mfd/core.h>
#include <linux/slab.h>
struct mc13783_led {
......@@ -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)
{
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);
int ret = 0;
int reg = 0;
......@@ -264,7 +265,7 @@ static int __devinit mc13783_leds_prepare(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 *led, *led_dat;
int ret, i;
......@@ -351,7 +352,7 @@ static int __devinit mc13783_led_probe(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 *dev = dev_get_drvdata(pdev->dev.parent);
int i;
......
......@@ -21,6 +21,7 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/i2c.h>
......@@ -148,7 +149,7 @@ static const struct v4l2_file_operations timbradio_fops = {
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;
int err;
......
......@@ -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)
{
struct wl1273_core **core = pdev->dev.platform_data;
struct wl1273_core **core = mfd_get_data(pdev);
struct wl1273_device *radio;
struct v4l2_ctrl *ctrl;
int r = 0;
......
......@@ -24,6 +24,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dmaengine.h>
#include <linux/mfd/core.h>
#include <linux/scatterlist.h>
#include <linux/interrupt.h>
#include <linux/list.h>
......@@ -790,7 +791,7 @@ static int __devinit timblogiw_probe(struct platform_device *pdev)
{
int err;
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) {
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,
}
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[] = {
{ "88PM860x", 0 },
......
......@@ -129,6 +129,17 @@ config UCB1400_CORE
To compile this driver as a module, choose M here: the
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
tristate "TPS6501x Power Management chips"
depends on I2C && GPIOLIB
......@@ -178,6 +189,16 @@ config TWL4030_CORE
high speed USB OTG transceiver, an audio codec (on most
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
bool "Support power resources on TWL4030 family chips"
depends on TWL4030_CORE && ARM
......@@ -304,6 +325,18 @@ config MFD_MAX8925
accessing the device, additional drivers must be enabled in order
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
bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support"
depends on I2C=y && GENERIC_HARDIRQS
......@@ -534,6 +567,13 @@ config AB8500_DEBUG
Select this option if you want debug information using the debug
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
bool "ST-Ericsson AB3550 Mixed Signal Circuit core functions"
select MFD_CORE
......
......@@ -33,11 +33,13 @@ obj-$(CONFIG_MFD_WM8350) += wm8350.o
obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o
obj-$(CONFIG_TPS6105X) += tps6105x.o
obj-$(CONFIG_TPS65010) += tps65010.o
obj-$(CONFIG_TPS6507X) += tps6507x.o
obj-$(CONFIG_MENELAUS) += menelaus.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_CODEC) += twl4030-codec.o
obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o
......@@ -61,6 +63,7 @@ obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o
obj-$(CONFIG_PMIC_DA903X) += da903x.o
max8925-objs := max8925-core.o max8925-i2c.o
obj-$(CONFIG_MFD_MAX8925) += max8925.o
obj-$(CONFIG_MFD_MAX8997) += max8997.o
obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o
pcf50633-objs := pcf50633-core.o pcf50633-irq.o
......@@ -71,9 +74,10 @@ obj-$(CONFIG_ABX500_CORE) += abx500-core.o
obj-$(CONFIG_AB3100_CORE) += ab3100-core.o
obj-$(CONFIG_AB3100_OTP) += ab3100-otp.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_DEBUG) += ab8500-debugfs.o
obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
obj-$(CONFIG_LPC_SCH) += lpc_sch.o
......
......@@ -613,7 +613,7 @@ static void ab3100_setup_debugfs(struct ab3100 *ab3100)
ab3100_get_priv.ab3100 = ab3100;
ab3100_get_priv.mode = false;
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);
if (!ab3100_get_reg_file) {
err = -ENOMEM;
......@@ -623,7 +623,7 @@ static void ab3100_setup_debugfs(struct ab3100 *ab3100)
ab3100_set_priv.ab3100 = ab3100;
ab3100_set_priv.mode = true;
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);
if (!ab3100_set_reg_file) {
err = -ENOMEM;
......@@ -949,10 +949,8 @@ static int __devinit ab3100_probe(struct i2c_client *client,
goto exit_no_ops;
/* Set up and register the platform devices. */
for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++) {
ab3100_devs[i].platform_data = ab3100_plf_data;
ab3100_devs[i].data_size = sizeof(struct ab3100_platform_data);
}
for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++)
ab3100_devs[i].mfd_data = ab3100_plf_data;
err = mfd_add_devices(&client->dev, 0, ab3100_devs,
ARRAY_SIZE(ab3100_devs), NULL, 0);
......
......@@ -1053,17 +1053,17 @@ static inline void ab3550_setup_debugfs(struct ab3550 *ab)
goto exit_destroy_dir;
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)
goto exit_destroy_reg;
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)
goto exit_destroy_bank;
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)
goto exit_destroy_address;
......@@ -1320,10 +1320,8 @@ static int __init ab3550_probe(struct i2c_client *client,
goto exit_no_ops;
/* Set up and register the platform devices. */
for (i = 0; i < AB3550_NUM_DEVICES; i++) {
ab3550_devs[i].platform_data = ab3550_plf_data->dev_data[i];
ab3550_devs[i].data_size = ab3550_plf_data->dev_data_sz[i];
}
for (i = 0; i < AB3550_NUM_DEVICES; i++)
ab3550_devs[i].mfd_data = ab3550_plf_data->dev_data[i];
err = mfd_add_devices(&client->dev, 0, ab3550_devs,
ARRAY_SIZE(ab3550_devs), NULL,
......
......@@ -4,7 +4,7 @@
* License Terms: GNU General Public License v2
* Author: Srinidhi Kasagar <srinidhi.kasagar@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>
......@@ -90,6 +90,7 @@
#define AB8500_IT_MASK24_REG 0x57
#define AB8500_REV_REG 0x80
#define AB8500_SWITCH_OFF_STATUS 0x00
/*
* Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
......@@ -652,10 +653,38 @@ static ssize_t show_chip_id(struct device *dev,
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(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
static struct attribute *ab8500_sysfs_entries[] = {
&dev_attr_chip_id.attr,
&dev_attr_switch_off_status.attr,
NULL,
};
......@@ -686,9 +715,10 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
* 0x10 - Cut 1.0
* 0x11 - Cut 1.1
* 0x20 - Cut 2.0
* 0x30 - Cut 3.0
*/
if (value == 0x0 || value == 0x10 || value == 0x11 || value == 0x20) {
ab8500->revision = value;
if (value == 0x0 || value == 0x10 || value == 0x11 || value == 0x20 ||
value == 0x30) {
dev_info(ab8500->dev, "detected chip, revision: %#x\n", value);
} else {
dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value);
......@@ -696,6 +726,24 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
}
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)
plat->init(ab8500);
......@@ -764,6 +812,6 @@ int __devexit ab8500_exit(struct ab8500 *ab8500)
return 0;
}
MODULE_AUTHOR("Srinidhi Kasagar, Rabin Vincent");
MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
MODULE_DESCRIPTION("AB8500 MFD core");
MODULE_LICENSE("GPL v2");
......@@ -585,18 +585,18 @@ static int __devinit ab8500_debug_probe(struct platform_device *plf)
goto exit_destroy_dir;
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)
goto exit_destroy_reg;
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);
if (!ab8500_address_file)
goto exit_destroy_bank;
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)
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)
}
#ifdef CONFIG_PM
static int adp5520_suspend(struct i2c_client *client,
pm_message_t state)
static int adp5520_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct adp5520_chip *chip = dev_get_drvdata(&client->dev);
adp5520_clr_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY);
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);
adp5520_set_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY);
return 0;
}
#else
#define adp5520_suspend NULL
#define adp5520_resume NULL
#endif
static SIMPLE_DEV_PM_OPS(adp5520_pm, adp5520_suspend, adp5520_resume);
static const struct i2c_device_id adp5520_id[] = {
{ "pmic-adp5520", ID_ADP5520 },
{ "pmic-adp5501", ID_ADP5501 },
......@@ -353,11 +353,10 @@ static struct i2c_driver adp5520_driver = {
.driver = {
.name = "adp5520",
.owner = THIS_MODULE,
.pm = &adp5520_pm,
},
.probe = adp5520_probe,
.remove = __devexit_p(adp5520_remove),
.suspend = adp5520_suspend,
.resume = adp5520_resume,
.id_table = adp5520_id,
};
......
......@@ -682,7 +682,7 @@ static struct mfd_cell asic3_cell_ds1wm = {
.name = "ds1wm",
.enable = ds1wm_enable,
.disable = ds1wm_disable,
.driver_data = &ds1wm_pdata,
.mfd_data = &ds1wm_pdata,
.num_resources = ARRAY_SIZE(ds1wm_resources),
.resources = ds1wm_resources,
};
......@@ -783,7 +783,7 @@ static struct mfd_cell asic3_cell_mmc = {
.name = "tmio-mmc",
.enable = asic3_mmc_enable,
.disable = asic3_mmc_disable,
.driver_data = &asic3_mmc_data,
.mfd_data = &asic3_mmc_data,
.num_resources = ARRAY_SIZE(asic3_mmc_resources),
.resources = asic3_mmc_resources,
};
......@@ -810,9 +810,6 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
ds1wm_resources[0].start >>= 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 */
asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
mem_sdio->start, 0x400 >> asic->bus_shift);
......@@ -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].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,
&asic3_cell_ds1wm, 1, mem, asic->irq_base);
if (ret < 0)
......
......@@ -39,6 +39,37 @@ enum cs5535_mfd_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 mfd_cell cs5535_mfd_cells[] = {
......@@ -65,12 +96,18 @@ static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
.name = "cs5535-pms",
.num_resources = 1,
.resources = &cs5535_mfd_resources[PMS_BAR],
.enable = cs5535_mfd_res_enable,
.disable = cs5535_mfd_res_disable,
},
{
.id = ACPI_BAR,
.name = "cs5535-acpi",
.num_resources = 1,
.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)
/* Voice codec interface client */
cell = &davinci_vc->cells[DAVINCI_VC_VCIF_CELL];
cell->name = "davinci-vcif";
cell->driver_data = davinci_vc;
cell->mfd_data = davinci_vc;
/* Voice codec CQ93VC client */
cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL];
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,
DAVINCI_VC_CELLS, NULL, 0);
......
......@@ -117,7 +117,7 @@ static struct mfd_cell ds1wm_cell __initdata = {
.name = "ds1wm",
.enable = ds1wm_enable,
.disable = ds1wm_disable,
.driver_data = &ds1wm_pdata,
.mfd_data = &ds1wm_pdata,
.num_resources = 2,
.resources = ds1wm_resources,
};
......@@ -165,8 +165,6 @@ static int __init pasic3_probe(struct platform_device *pdev)
ds1wm_pdata.clock_rate = pdata->clock_rate;
/* the first 5 PASIC3 registers control the DS1WM */
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,
&ds1wm_cell, 1, r, irq);
if (ret < 0)
......@@ -174,9 +172,6 @@ static int __init pasic3_probe(struct platform_device *pdev)
}
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);
if (ret < 0)
dev_warn(dev, "failed to register LED device\n");
......
......@@ -86,8 +86,7 @@ static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv,
/* Add platform data */
pdata->modno = modno;
cell->platform_data = pdata;
cell->data_size = sizeof(*pdata);
cell->mfd_data = pdata;
/* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */
res->flags = IORESOURCE_MEM;
......
......@@ -232,8 +232,6 @@ const struct mfd_cell jz4740_adc_cells[] = {
.name = "jz4740-hwmon",
.num_resources = ARRAY_SIZE(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,
.disable = jz4740_adc_cell_disable,
......@@ -243,8 +241,6 @@ const struct mfd_cell jz4740_adc_cells[] = {
.name = "jz4740-battery",
.num_resources = ARRAY_SIZE(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,
.disable = jz4740_adc_cell_disable,
......
......@@ -61,6 +61,7 @@ static struct mfd_cell lpc_sch_cells[] = {
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_ITC_LPC) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, lpc_sch_ids);
......@@ -70,6 +71,7 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,
{
unsigned int base_addr_cfg;
unsigned short base_addr;
int i;
pci_read_config_dword(dev, SMBASE, &base_addr_cfg);
if (!(base_addr_cfg & (1 << 31))) {
......@@ -99,7 +101,10 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,
gpio_sch_resource.start = base_addr;
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);
}
......
This diff is collapsed.
......@@ -233,7 +233,7 @@ struct max8998_reg_dump {
u8 val;
};
#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_IRQM2),
SAVE_ITEM(MAX8998_REG_IRQM3),
......@@ -298,7 +298,7 @@ static int max8998_restore(struct device *dev)
return 0;
}
const struct dev_pm_ops max8998_pm = {
static const struct dev_pm_ops max8998_pm = {
.suspend = max8998_suspend,
.resume = max8998_resume,
.freeze = max8998_freeze,
......
......@@ -683,14 +683,13 @@ int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode,
EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion);
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];
const char *name = mc13xxx_get_chipname(mc13xxx);
struct mfd_cell cell = {
.platform_data = pdata,
.data_size = pdata_size,
.mfd_data = pdata,
};
/* there is no asnprintf in the kernel :-( */
......@@ -706,7 +705,7 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx,
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)
......@@ -764,13 +763,8 @@ static int mc13xxx_probe(struct spi_device *spi)
mc13xxx_add_subdevice(mc13xxx, "%s-codec");
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",
&regulator_pdata, sizeof(regulator_pdata));
&pdata->regulators);
}
if (pdata->flags & MC13XXX_USE_RTC)
......@@ -779,10 +773,8 @@ static int mc13xxx_probe(struct spi_device *spi)
if (pdata->flags & MC13XXX_USE_TOUCHSCREEN)
mc13xxx_add_subdevice(mc13xxx, "%s-ts");
if (pdata->flags & MC13XXX_USE_LED) {
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led",
pdata->leds, sizeof(*pdata->leds));
}
if (pdata->flags & MC13XXX_USE_LED)
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", pdata->leds);
return 0;
}
......@@ -811,6 +803,7 @@ static const struct spi_device_id mc13xxx_device_id[] = {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(spi, mc13xxx_device_id);
static struct spi_driver mc13xxx_driver = {
.id_table = mc13xxx_device_id,
......
......@@ -18,6 +18,43 @@
#include <linux/pm_runtime.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,
const struct mfd_cell *cell,
struct resource *mem_base,
......@@ -37,14 +74,10 @@ static int mfd_add_device(struct device *parent, int id,
goto fail_device;
pdev->dev.parent = parent;
platform_set_drvdata(pdev, cell->driver_data);
if (cell->data_size) {
ret = platform_device_add_data(pdev,
cell->platform_data, cell->data_size);
if (ret)
goto fail_res;
}
ret = platform_device_add_data(pdev, cell, sizeof(*cell));
if (ret)
goto fail_res;
for (r = 0; r < cell->num_resources; r++) {
res[r].name = cell->resources[r].name;
......@@ -100,14 +133,22 @@ static int mfd_add_device(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,
int irq_base)
{
int i;
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++) {
atomic_set(&cnts[i], 0);
cells[i].usage_count = &cnts[i];
ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base);
if (ret)
break;
......@@ -120,17 +161,89 @@ int mfd_add_devices(struct device *parent, int id,
}
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;
}
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);
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_AUTHOR("Ian Molton, Dmitry Baryshkov");
......@@ -21,6 +21,7 @@
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/mfd/pcf50633/core.h>
......@@ -230,27 +231,26 @@ pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name,
}
}
#ifdef CONFIG_PM
static int pcf50633_suspend(struct i2c_client *client, pm_message_t state)
#ifdef CONFIG_PM_SLEEP
static int pcf50633_suspend(struct device *dev)
{
struct pcf50633 *pcf;
pcf = i2c_get_clientdata(client);
struct i2c_client *client = to_i2c_client(dev);
struct pcf50633 *pcf = i2c_get_clientdata(client);
return pcf50633_irq_suspend(pcf);
}
static int pcf50633_resume(struct i2c_client *client)
static int pcf50633_resume(struct device *dev)
{
struct pcf50633 *pcf;
pcf = i2c_get_clientdata(client);
struct i2c_client *client = to_i2c_client(dev);
struct pcf50633 *pcf = i2c_get_clientdata(client);
return pcf50633_irq_resume(pcf);
}
#else
#define pcf50633_suspend NULL
#define pcf50633_resume NULL
#endif
static SIMPLE_DEV_PM_OPS(pcf50633_pm, pcf50633_suspend, pcf50633_resume);
static int __devinit pcf50633_probe(struct i2c_client *client,
const struct i2c_device_id *ids)
{
......@@ -360,16 +360,16 @@ static struct i2c_device_id pcf50633_id_table[] = {
{"pcf50633", 0x73},
{/* end of list */}
};
MODULE_DEVICE_TABLE(i2c, pcf50633_id_table);
static struct i2c_driver pcf50633_driver = {
.driver = {
.name = "pcf50633",
.pm = &pcf50633_pm,
},
.id_table = pcf50633_id_table,
.probe = pcf50633_probe,
.remove = __devexit_p(pcf50633_remove),
.suspend = pcf50633_suspend,
.resume = pcf50633_resume,
};
static int __init pcf50633_init(void)
......
......@@ -61,12 +61,12 @@ static struct mfd_cell rdc321x_sb_cells[] = {
.name = "rdc321x-wdt",
.resources = rdc321x_wdt_resource,
.num_resources = ARRAY_SIZE(rdc321x_wdt_resource),
.driver_data = &rdc321x_wdt_pdata,
.mfd_data = &rdc321x_wdt_pdata,
}, {
.name = "rdc321x-gpio",
.resources = 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)
}
memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc));
priv->cell_mmc.driver_data = mmc_data;
priv->cell_mmc.platform_data = &priv->cell_mmc;
priv->cell_mmc.data_size = sizeof(priv->cell_mmc);
priv->cell_mmc.mfd_data = mmc_data;
platform_set_drvdata(pdev, priv);
......
......@@ -170,7 +170,7 @@ static struct mfd_cell t7l66xb_cells[] = {
.name = "tmio-mmc",
.enable = t7l66xb_mmc_enable,
.disable = t7l66xb_mmc_disable,
.driver_data = &t7166xb_mmc_data,
.mfd_data = &t7166xb_mmc_data,
.num_resources = ARRAY_SIZE(t7l66xb_mmc_resources),
.resources = t7l66xb_mmc_resources,
},
......@@ -383,16 +383,7 @@ static int t7l66xb_probe(struct platform_device *dev)
t7l66xb_attach_irq(dev);
t7l66xb_cells[T7L66XB_CELL_NAND].driver_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]);
t7l66xb_cells[T7L66XB_CELL_NAND].mfd_data = pdata->nand_data;
ret = mfd_add_devices(&dev->dev, dev->id,
t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells),
......
......@@ -131,7 +131,7 @@ static struct mfd_cell tc6387xb_cells[] = {
.name = "tmio-mmc",
.enable = tc6387xb_mmc_enable,
.disable = tc6387xb_mmc_disable,
.driver_data = &tc6387xb_mmc_data,
.mfd_data = &tc6387xb_mmc_data,
.num_resources = ARRAY_SIZE(tc6387xb_mmc_resources),
.resources = tc6387xb_mmc_resources,
},
......@@ -190,11 +190,6 @@ static int __devinit tc6387xb_probe(struct platform_device *dev)
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,
ARRAY_SIZE(tc6387xb_cells), iomem, irq);
......
......@@ -393,7 +393,7 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = {
.name = "tmio-mmc",
.enable = tc6393xb_mmc_enable,
.resume = tc6393xb_mmc_resume,
.driver_data = &tc6393xb_mmc_data,
.mfd_data = &tc6393xb_mmc_data,
.num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
.resources = tc6393xb_mmc_resources,
},
......@@ -693,27 +693,8 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
goto err_setup;
}
tc6393xb_cells[TC6393XB_CELL_NAND].driver_data = tcpd->nand_data;
tc6393xb_cells[TC6393XB_CELL_NAND].platform_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]);
tc6393xb_cells[TC6393XB_CELL_NAND].mfd_data = tcpd->nand_data;
tc6393xb_cells[TC6393XB_CELL_FB].mfd_data = tcpd->fb_data;
ret = mfd_add_devices(&dev->dev, dev->id,
tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
......
......@@ -384,8 +384,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
.platform_data = &timb_dma_platform_data,
.data_size = sizeof(timb_dma_platform_data),
.mfd_data = &timb_dma_platform_data,
},
{
.name = "timb-uart",
......@@ -396,43 +395,37 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
.name = "xiic-i2c",
.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
.resources = timberdale_xiic_resources,
.platform_data = &timberdale_xiic_platform_data,
.data_size = sizeof(timberdale_xiic_platform_data),
.mfd_data = &timberdale_xiic_platform_data,
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
.platform_data = &timberdale_gpio_platform_data,
.data_size = sizeof(timberdale_gpio_platform_data),
.mfd_data = &timberdale_gpio_platform_data,
},
{
.name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
.platform_data = &timberdale_video_platform_data,
.data_size = sizeof(timberdale_video_platform_data),
.mfd_data = &timberdale_video_platform_data,
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
.platform_data = &timberdale_radio_platform_data,
.data_size = sizeof(timberdale_radio_platform_data),
.mfd_data = &timberdale_radio_platform_data,
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
.platform_data = &timberdale_xspi_platform_data,
.data_size = sizeof(timberdale_xspi_platform_data),
.mfd_data = &timberdale_xspi_platform_data,
},
{
.name = "ks8842",
.num_resources = ARRAY_SIZE(timberdale_eth_resources),
.resources = timberdale_eth_resources,
.platform_data = &timberdale_ks8842_platform_data,
.data_size = sizeof(timberdale_ks8842_platform_data)
.mfd_data = &timberdale_ks8842_platform_data,
},
};
......@@ -441,8 +434,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
.platform_data = &timb_dma_platform_data,
.data_size = sizeof(timb_dma_platform_data),
.mfd_data = &timb_dma_platform_data,
},
{
.name = "timb-uart",
......@@ -458,15 +450,13 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
.name = "xiic-i2c",
.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
.resources = timberdale_xiic_resources,
.platform_data = &timberdale_xiic_platform_data,
.data_size = sizeof(timberdale_xiic_platform_data),
.mfd_data = &timberdale_xiic_platform_data,
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
.platform_data = &timberdale_gpio_platform_data,
.data_size = sizeof(timberdale_gpio_platform_data),
.mfd_data = &timberdale_gpio_platform_data,
},
{
.name = "timb-mlogicore",
......@@ -477,29 +467,25 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
.name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
.platform_data = &timberdale_video_platform_data,
.data_size = sizeof(timberdale_video_platform_data),
.mfd_data = &timberdale_video_platform_data,
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
.platform_data = &timberdale_radio_platform_data,
.data_size = sizeof(timberdale_radio_platform_data),
.mfd_data = &timberdale_radio_platform_data,
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
.platform_data = &timberdale_xspi_platform_data,
.data_size = sizeof(timberdale_xspi_platform_data),
.mfd_data = &timberdale_xspi_platform_data,
},
{
.name = "ks8842",
.num_resources = ARRAY_SIZE(timberdale_eth_resources),
.resources = timberdale_eth_resources,
.platform_data = &timberdale_ks8842_platform_data,
.data_size = sizeof(timberdale_ks8842_platform_data)
.mfd_data = &timberdale_ks8842_platform_data,
},
};
......@@ -508,8 +494,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
.platform_data = &timb_dma_platform_data,
.data_size = sizeof(timb_dma_platform_data),
.mfd_data = &timb_dma_platform_data,
},
{
.name = "timb-uart",
......@@ -520,36 +505,31 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
.name = "xiic-i2c",
.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
.resources = timberdale_xiic_resources,
.platform_data = &timberdale_xiic_platform_data,
.data_size = sizeof(timberdale_xiic_platform_data),
.mfd_data = &timberdale_xiic_platform_data,
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
.platform_data = &timberdale_gpio_platform_data,
.data_size = sizeof(timberdale_gpio_platform_data),
.mfd_data = &timberdale_gpio_platform_data,
},
{
.name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
.platform_data = &timberdale_video_platform_data,
.data_size = sizeof(timberdale_video_platform_data),
.mfd_data = &timberdale_video_platform_data,
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
.platform_data = &timberdale_radio_platform_data,
.data_size = sizeof(timberdale_radio_platform_data),
.mfd_data = &timberdale_radio_platform_data,
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
.platform_data = &timberdale_xspi_platform_data,
.data_size = sizeof(timberdale_xspi_platform_data),
.mfd_data = &timberdale_xspi_platform_data,
},
};
......@@ -558,8 +538,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
.platform_data = &timb_dma_platform_data,
.data_size = sizeof(timb_dma_platform_data),
.mfd_data = &timb_dma_platform_data,
},
{
.name = "timb-uart",
......@@ -570,43 +549,37 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
.name = "ocores-i2c",
.num_resources = ARRAY_SIZE(timberdale_ocores_resources),
.resources = timberdale_ocores_resources,
.platform_data = &timberdale_ocores_platform_data,
.data_size = sizeof(timberdale_ocores_platform_data),
.mfd_data = &timberdale_ocores_platform_data,
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
.platform_data = &timberdale_gpio_platform_data,
.data_size = sizeof(timberdale_gpio_platform_data),
.mfd_data = &timberdale_gpio_platform_data,
},
{
.name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
.platform_data = &timberdale_video_platform_data,
.data_size = sizeof(timberdale_video_platform_data),
.mfd_data = &timberdale_video_platform_data,
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
.platform_data = &timberdale_radio_platform_data,
.data_size = sizeof(timberdale_radio_platform_data),
.mfd_data = &timberdale_radio_platform_data,
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
.platform_data = &timberdale_xspi_platform_data,
.data_size = sizeof(timberdale_xspi_platform_data),
.mfd_data = &timberdale_xspi_platform_data,
},
{
.name = "ks8842",
.num_resources = ARRAY_SIZE(timberdale_eth_resources),
.resources = timberdale_eth_resources,
.platform_data = &timberdale_ks8842_platform_data,
.data_size = sizeof(timberdale_ks8842_platform_data)
.mfd_data = &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,
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)
return;
return 0;
tps6586x->gpio.owner = THIS_MODULE;
tps6586x->gpio.label = tps6586x->client->name;
......@@ -307,9 +305,7 @@ static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base)
tps6586x->gpio.set = tps6586x_gpio_set;
tps6586x->gpio.get = tps6586x_gpio_get;
ret = gpiochip_add(&tps6586x->gpio);
if (ret)
dev_warn(tps6586x->dev, "GPIO registration failed: %d\n", ret);
return gpiochip_add(&tps6586x->gpio);
}
static int __remove_subdev(struct device *dev, void *unused)
......@@ -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);
if (ret) {
dev_err(&client->dev, "add devices failed: %d\n", ret);
goto err_add_devs;
}
tps6586x_gpio_init(tps6586x, pdata->gpio_base);
return 0;
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)
free_irq(client->irq, tps6586x);
err_irq_init:
......@@ -587,4 +594,3 @@ module_exit(tps6586x_exit);
MODULE_DESCRIPTION("TPS6586X core driver");
MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
MODULE_LICENSE("GPL");
......@@ -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);
if (IS_ERR(child))
return PTR_ERR(child);
}
if (twl_has_pwrbutton()) {
if (twl_has_pwrbutton() && twl_class_is_4030()) {
child = add_child(1, "twl4030_pwrbutton",
NULL, 0, true, pdata->irq_base + 8 + 0, 0);
if (IS_ERR(child))
......@@ -864,6 +864,10 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3);
if (IS_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 &&
......
......@@ -208,15 +208,13 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
if (pdata->audio) {
cell = &codec->cells[childs];
cell->name = "twl4030-codec";
cell->platform_data = pdata->audio;
cell->data_size = sizeof(*pdata->audio);
cell->mfd_data = pdata->audio;
childs++;
}
if (pdata->vibra) {
cell = &codec->cells[childs];
cell->name = "twl4030-vibra";
cell->platform_data = pdata->vibra;
cell->data_size = sizeof(*pdata->vibra);
cell->mfd_data = pdata->vibra;
childs++;
}
......
This diff is collapsed.
......@@ -60,6 +60,7 @@ static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x
input_report_abs(idev, ABS_X, x);
input_report_abs(idev, ABS_Y, y);
input_report_abs(idev, ABS_PRESSURE, pressure);
input_report_key(idev, BTN_TOUCH, 1);
input_sync(idev);
}
......@@ -68,6 +69,7 @@ static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
struct input_dev *idev = ts->idev;
input_report_abs(idev, ABS_PRESSURE, 0);
input_report_key(idev, BTN_TOUCH, 0);
input_sync(idev);
}
......@@ -384,7 +386,8 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
idev->open = ucb1x00_ts_open;
idev->close = ucb1x00_ts_close;
__set_bit(EV_ABS, idev->evbit);
idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_drvdata(idev, ts);
......
......@@ -122,6 +122,7 @@ static struct pci_device_id vx855_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, vx855_pci_tbl);
static struct pci_driver vx855_pci_driver = {
.name = "vx855",
......
......@@ -38,7 +38,6 @@ static int wl1273_core_remove(struct i2c_client *client)
dev_dbg(&client->dev, "%s\n", __func__);
mfd_remove_devices(&client->dev);
i2c_set_clientdata(client, NULL);
kfree(core);
return 0;
......@@ -79,8 +78,7 @@ static int __devinit wl1273_core_probe(struct i2c_client *client,
cell = &core->cells[children];
cell->name = "wl1273_fm_radio";
cell->platform_data = &core;
cell->data_size = sizeof(core);
cell->mfd_data = &core;
children++;
if (pdata->children & WL1273_CODEC_CHILD) {
......@@ -88,8 +86,7 @@ static int __devinit wl1273_core_probe(struct i2c_client *client,
dev_dbg(&client->dev, "%s: Have codec.\n", __func__);
cell->name = "wl1273-codec";
cell->platform_data = &core;
cell->data_size = sizeof(core);
cell->mfd_data = &core;
children++;
}
......@@ -104,7 +101,6 @@ static int __devinit wl1273_core_probe(struct i2c_client *client,
return 0;
err:
i2c_set_clientdata(client, NULL);
pdata->free_resources();
kfree(core);
......
......@@ -51,17 +51,25 @@ static int wm831x_i2c_write_device(struct wm831x *wm831x, unsigned short reg,
int bytes, void *src)
{
struct i2c_client *i2c = wm831x->control_data;
unsigned char msg[bytes + 2];
struct i2c_msg xfer[2];
int ret;
reg = cpu_to_be16(reg);
memcpy(&msg[0], &reg, 2);
memcpy(&msg[2], src, bytes);
ret = i2c_master_send(i2c, msg, bytes + 2);
xfer[0].addr = i2c->addr;
xfer[0].flags = 0;
xfer[0].len = 2;
xfer[0].buf = (char *)&reg;
xfer[1].addr = i2c->addr;
xfer[1].flags = I2C_M_NOSTART;
xfer[1].len = bytes;
xfer[1].buf = (char *)src;
ret = i2c_transfer(i2c->adapter, xfer, 2);
if (ret < 0)
return ret;
if (ret < bytes + 2)
if (ret != 2)
return -EIO;
return 0;
......
......@@ -26,15 +26,6 @@
#include <linux/delay.h>
/*
* Since generic IRQs don't currently support interrupt controllers on
* interrupt driven buses we don't use genirq but instead provide an
* interface that looks very much like the standard ones. This leads
* to some bodges, including storing interrupt handler information in
* the static irq_data table we use to look up the data for individual
* interrupts, but hopefully won't last too long.
*/
struct wm831x_irq_data {
int primary;
int reg;
......@@ -361,6 +352,10 @@ static void wm831x_irq_sync_unlock(struct irq_data *data)
/* If there's been a change in the mask write it back
* to the hardware. */
if (wm831x->irq_masks_cur[i] != wm831x->irq_masks_cache[i]) {
dev_dbg(wm831x->dev, "IRQ mask sync: %x = %x\n",
WM831X_INTERRUPT_STATUS_1_MASK + i,
wm831x->irq_masks_cur[i]);
wm831x->irq_masks_cache[i] = wm831x->irq_masks_cur[i];
wm831x_reg_write(wm831x,
WM831X_INTERRUPT_STATUS_1_MASK + i,
......@@ -371,7 +366,7 @@ static void wm831x_irq_sync_unlock(struct irq_data *data)
mutex_unlock(&wm831x->irq_lock);
}
static void wm831x_irq_unmask(struct irq_data *data)
static void wm831x_irq_enable(struct irq_data *data)
{
struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x,
......@@ -380,7 +375,7 @@ static void wm831x_irq_unmask(struct irq_data *data)
wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
}
static void wm831x_irq_mask(struct irq_data *data)
static void wm831x_irq_disable(struct irq_data *data)
{
struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x,
......@@ -426,8 +421,8 @@ static struct irq_chip wm831x_irq_chip = {
.name = "wm831x",
.irq_bus_lock = wm831x_irq_lock,
.irq_bus_sync_unlock = wm831x_irq_sync_unlock,
.irq_mask = wm831x_irq_mask,
.irq_unmask = wm831x_irq_unmask,
.irq_disable = wm831x_irq_disable,
.irq_enable = wm831x_irq_enable,
.irq_set_type = wm831x_irq_set_type,
};
......@@ -449,6 +444,18 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
goto out;
}
/* The touch interrupts are visible in the primary register as
* an optimisation; open code this to avoid complicating the
* main handling loop and so we can also skip iterating the
* descriptors.
*/
if (primary & WM831X_TCHPD_INT)
handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHPD);
if (primary & WM831X_TCHDATA_INT)
handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHDATA);
if (primary & (WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT))
goto out;
for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) {
int offset = wm831x_irqs[i].reg - 1;
......@@ -481,6 +488,9 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
}
out:
/* Touchscreen interrupts are handled specially in the driver */
status_regs[0] &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT);
for (i = 0; i < ARRAY_SIZE(status_regs); i++) {
if (status_regs[i])
wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i,
......@@ -517,6 +527,14 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
return 0;
}
if (pdata->irq_cmos)
i = 0;
else
i = WM831X_IRQ_OD;
wm831x_set_bits(wm831x, WM831X_IRQ_CONFIG,
WM831X_IRQ_OD, i);
/* Try to flag /IRQ as a wake source; there are a number of
* unconditional wake sources in the PMIC so this isn't
* conditional but we don't actually care *too* much if it
......
......@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pm.h>
#include <linux/spi/spi.h>
#include <linux/mfd/wm831x/core.h>
......@@ -113,22 +114,27 @@ static int __devexit wm831x_spi_remove(struct spi_device *spi)
return 0;
}
static int wm831x_spi_suspend(struct spi_device *spi, pm_message_t m)
static int wm831x_spi_suspend(struct device *dev)
{
struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
struct wm831x *wm831x = dev_get_drvdata(dev);
return wm831x_device_suspend(wm831x);
}
static const struct dev_pm_ops wm831x_spi_pm = {
.freeze = wm831x_spi_suspend,
.suspend = wm831x_spi_suspend,
};
static struct spi_driver wm8310_spi_driver = {
.driver = {
.name = "wm8310",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.pm = &wm831x_spi_pm,
},
.probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove),
.suspend = wm831x_spi_suspend,
};
static struct spi_driver wm8311_spi_driver = {
......@@ -136,10 +142,10 @@ static struct spi_driver wm8311_spi_driver = {
.name = "wm8311",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.pm = &wm831x_spi_pm,
},
.probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove),
.suspend = wm831x_spi_suspend,
};
static struct spi_driver wm8312_spi_driver = {
......@@ -147,10 +153,10 @@ static struct spi_driver wm8312_spi_driver = {
.name = "wm8312",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.pm = &wm831x_spi_pm,
},
.probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove),
.suspend = wm831x_spi_suspend,
};
static struct spi_driver wm8320_spi_driver = {
......@@ -158,10 +164,10 @@ static struct spi_driver wm8320_spi_driver = {
.name = "wm8320",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.pm = &wm831x_spi_pm,
},
.probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove),
.suspend = wm831x_spi_suspend,
};
static struct spi_driver wm8321_spi_driver = {
......@@ -169,10 +175,10 @@ static struct spi_driver wm8321_spi_driver = {
.name = "wm8321",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.pm = &wm831x_spi_pm,
},
.probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove),
.suspend = wm831x_spi_suspend,
};
static struct spi_driver wm8325_spi_driver = {
......@@ -180,10 +186,10 @@ static struct spi_driver wm8325_spi_driver = {
.name = "wm8325",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.pm = &wm831x_spi_pm,
},
.probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove),
.suspend = wm831x_spi_suspend,
};
static struct spi_driver wm8326_spi_driver = {
......@@ -191,10 +197,10 @@ static struct spi_driver wm8326_spi_driver = {
.name = "wm8326",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.pm = &wm831x_spi_pm,
},
.probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove),
.suspend = wm831x_spi_suspend,
};
static int __init wm831x_spi_init(void)
......
......@@ -245,7 +245,7 @@ static int wm8400_register_codec(struct wm8400 *wm8400)
{
struct mfd_cell cell = {
.name = "wm8400-codec",
.driver_data = wm8400,
.mfd_data = wm8400,
};
return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0);
......
......@@ -40,10 +40,8 @@ static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
return ret;
for (i = 0; i < bytes / 2; i++) {
buf[i] = be16_to_cpu(buf[i]);
dev_vdbg(wm8994->dev, "Read %04x from R%d(0x%x)\n",
buf[i], reg + i, reg + i);
be16_to_cpu(buf[i]), reg + i, reg + i);
}
return 0;
......@@ -69,7 +67,7 @@ int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg)
if (ret < 0)
return ret;
else
return val;
return be16_to_cpu(val);
}
EXPORT_SYMBOL_GPL(wm8994_reg_read);
......@@ -79,7 +77,7 @@ EXPORT_SYMBOL_GPL(wm8994_reg_read);
* @wm8994: Device to read from
* @reg: First register
* @count: Number of registers
* @buf: Buffer to fill.
* @buf: Buffer to fill. The data will be returned big endian.
*/
int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
int count, u16 *buf)
......@@ -97,9 +95,9 @@ int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
EXPORT_SYMBOL_GPL(wm8994_bulk_read);
static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
int bytes, void *src)
int bytes, const void *src)
{
u16 *buf = src;
const u16 *buf = src;
int i;
BUG_ON(bytes % 2);
......@@ -107,9 +105,7 @@ static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
for (i = 0; i < bytes / 2; i++) {
dev_vdbg(wm8994->dev, "Write %04x to R%d(0x%x)\n",
buf[i], reg + i, reg + i);
buf[i] = cpu_to_be16(buf[i]);
be16_to_cpu(buf[i]), reg + i, reg + i);
}
return wm8994->write_dev(wm8994, reg, bytes, src);
......@@ -127,6 +123,8 @@ int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
{
int ret;
val = cpu_to_be16(val);
mutex_lock(&wm8994->io_lock);
ret = wm8994_write(wm8994, reg, 2, &val);
......@@ -137,6 +135,29 @@ int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
}
EXPORT_SYMBOL_GPL(wm8994_reg_write);
/**
* wm8994_bulk_write: Write multiple WM8994 registers
*
* @wm8994: Device to write to
* @reg: First register
* @count: Number of registers
* @buf: Buffer to write from. Data must be big-endian formatted.
*/
int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg,
int count, const u16 *buf)
{
int ret;
mutex_lock(&wm8994->io_lock);
ret = wm8994_write(wm8994, reg, count * 2, buf);
mutex_unlock(&wm8994->io_lock);
return ret;
}
EXPORT_SYMBOL_GPL(wm8994_bulk_write);
/**
* wm8994_set_bits: Set the value of a bitfield in a WM8994 register
*
......@@ -157,9 +178,13 @@ int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
if (ret < 0)
goto out;
r = be16_to_cpu(r);
r &= ~mask;
r |= val;
r = cpu_to_be16(r);
ret = wm8994_write(wm8994, reg, 2, &r);
out:
......@@ -271,6 +296,11 @@ static int wm8994_suspend(struct device *dev)
if (ret < 0)
dev_err(dev, "Failed to save LDO registers: %d\n", ret);
/* Explicitly put the device into reset in case regulators
* don't get disabled in order to ensure consistent restart.
*/
wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET, 0x8994);
wm8994->suspended = true;
ret = regulator_bulk_disable(wm8994->num_supplies,
......@@ -552,25 +582,29 @@ static int wm8994_i2c_read_device(struct wm8994 *wm8994, unsigned short reg,
return 0;
}
/* Currently we allocate the write buffer on the stack; this is OK for
* small writes - if we need to do large writes this will need to be
* revised.
*/
static int wm8994_i2c_write_device(struct wm8994 *wm8994, unsigned short reg,
int bytes, void *src)
int bytes, const void *src)
{
struct i2c_client *i2c = wm8994->control_data;
unsigned char msg[bytes + 2];
struct i2c_msg xfer[2];
int ret;
reg = cpu_to_be16(reg);
memcpy(&msg[0], &reg, 2);
memcpy(&msg[2], src, bytes);
ret = i2c_master_send(i2c, msg, bytes + 2);
xfer[0].addr = i2c->addr;
xfer[0].flags = 0;
xfer[0].len = 2;
xfer[0].buf = (char *)&reg;
xfer[1].addr = i2c->addr;
xfer[1].flags = I2C_M_NOSTART;
xfer[1].len = bytes;
xfer[1].buf = (char *)src;
ret = i2c_transfer(i2c->adapter, xfer, 2);
if (ret < 0)
return ret;
if (ret < bytes + 2)
if (ret != 2)
return -EIO;
return 0;
......@@ -612,7 +646,8 @@ static const struct i2c_device_id wm8994_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
UNIVERSAL_DEV_PM_OPS(wm8994_pm_ops, wm8994_suspend, wm8994_resume, NULL);
static UNIVERSAL_DEV_PM_OPS(wm8994_pm_ops, wm8994_suspend, wm8994_resume,
NULL);
static struct i2c_driver wm8994_i2c_driver = {
.driver = {
......
......@@ -182,7 +182,7 @@ static void wm8994_irq_sync_unlock(struct irq_data *data)
mutex_unlock(&wm8994->irq_lock);
}
static void wm8994_irq_unmask(struct irq_data *data)
static void wm8994_irq_enable(struct irq_data *data)
{
struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994,
......@@ -191,7 +191,7 @@ static void wm8994_irq_unmask(struct irq_data *data)
wm8994->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
}
static void wm8994_irq_mask(struct irq_data *data)
static void wm8994_irq_disable(struct irq_data *data)
{
struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994,
......@@ -204,8 +204,8 @@ static struct irq_chip wm8994_irq_chip = {
.name = "wm8994",
.irq_bus_lock = wm8994_irq_lock,
.irq_bus_sync_unlock = wm8994_irq_sync_unlock,
.irq_mask = wm8994_irq_mask,
.irq_unmask = wm8994_irq_unmask,
.irq_disable = wm8994_irq_disable,
.irq_enable = wm8994_irq_enable,
};
/* The processing of the primary interrupt occurs in a thread so that
......@@ -225,9 +225,11 @@ static irqreturn_t wm8994_irq_thread(int irq, void *data)
return IRQ_NONE;
}
/* Apply masking */
for (i = 0; i < WM8994_NUM_IRQ_REGS; i++)
/* Bit swap and apply masking */
for (i = 0; i < WM8994_NUM_IRQ_REGS; i++) {
status[i] = be16_to_cpu(status[i]);
status[i] &= ~wm8994->irq_masks_cur[i];
}
/* Report */
for (i = 0; i < ARRAY_SIZE(wm8994_irqs); i++) {
......
......@@ -303,8 +303,7 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
{
struct mfd_cell *cell = host->pdev->dev.platform_data;
struct tmio_mmc_data *pdata = cell->driver_data;
struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
/*
* Testing on sh-mobile showed that SDIO IRQs are unmasked when
......@@ -327,8 +326,7 @@ static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
static void tmio_mmc_clk_start(struct tmio_mmc_host *host)
{
struct mfd_cell *cell = host->pdev->dev.platform_data;
struct tmio_mmc_data *pdata = cell->driver_data;
struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 |
sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
......@@ -669,8 +667,7 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
static irqreturn_t tmio_mmc_irq(int irq, void *devid)
{
struct tmio_mmc_host *host = devid;
struct mfd_cell *cell = host->pdev->dev.platform_data;
struct tmio_mmc_data *pdata = cell->driver_data;
struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
unsigned int ireg, irq_mask, status;
unsigned int sdio_ireg, sdio_irq_mask, sdio_status;
......@@ -799,8 +796,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
struct scatterlist *sg = host->sg_ptr, *sg_tmp;
struct dma_async_tx_descriptor *desc = NULL;
struct dma_chan *chan = host->chan_rx;
struct mfd_cell *cell = host->pdev->dev.platform_data;
struct tmio_mmc_data *pdata = cell->driver_data;
struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
dma_cookie_t cookie;
int ret, i;
bool aligned = true, multiple = true;
......@@ -869,8 +865,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
struct scatterlist *sg = host->sg_ptr, *sg_tmp;
struct dma_async_tx_descriptor *desc = NULL;
struct dma_chan *chan = host->chan_tx;
struct mfd_cell *cell = host->pdev->dev.platform_data;
struct tmio_mmc_data *pdata = cell->driver_data;
struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
dma_cookie_t cookie;
int ret, i;
bool aligned = true, multiple = true;
......@@ -1063,8 +1058,7 @@ static void tmio_mmc_release_dma(struct tmio_mmc_host *host)
static int tmio_mmc_start_data(struct tmio_mmc_host *host,
struct mmc_data *data)
{
struct mfd_cell *cell = host->pdev->dev.platform_data;
struct tmio_mmc_data *pdata = cell->driver_data;
struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
pr_debug("setup data transfer: blocksize %08x nr_blocks %d\n",
data->blksz, data->blocks);
......@@ -1169,8 +1163,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
static int tmio_mmc_get_ro(struct mmc_host *mmc)
{
struct tmio_mmc_host *host = mmc_priv(mmc);
struct mfd_cell *cell = host->pdev->dev.platform_data;
struct tmio_mmc_data *pdata = cell->driver_data;
struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
return ((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||
(sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)) ? 0 : 1;
......@@ -1179,8 +1172,7 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc)
static int tmio_mmc_get_cd(struct mmc_host *mmc)
{
struct tmio_mmc_host *host = mmc_priv(mmc);
struct mfd_cell *cell = host->pdev->dev.platform_data;
struct tmio_mmc_data *pdata = cell->driver_data;
struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
if (!pdata->get_cd)
return -ENOSYS;
......@@ -1199,7 +1191,7 @@ static const struct mmc_host_ops tmio_mmc_ops = {
#ifdef CONFIG_PM
static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state)
{
struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
const struct mfd_cell *cell = mfd_get_cell(dev);
struct mmc_host *mmc = platform_get_drvdata(dev);
int ret;
......@@ -1214,7 +1206,7 @@ static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state)
static int tmio_mmc_resume(struct platform_device *dev)
{
struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
const struct mfd_cell *cell = mfd_get_cell(dev);
struct mmc_host *mmc = platform_get_drvdata(dev);
int ret = 0;
......@@ -1237,7 +1229,7 @@ static int tmio_mmc_resume(struct platform_device *dev)
static int __devinit tmio_mmc_probe(struct platform_device *dev)
{
struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
const struct mfd_cell *cell = mfd_get_cell(dev);
struct tmio_mmc_data *pdata;
struct resource *res_ctl;
struct tmio_mmc_host *host;
......@@ -1252,7 +1244,7 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
if (!res_ctl)
goto out;
pdata = cell->driver_data;
pdata = mfd_get_data(dev);
if (!pdata || !pdata->hclk)
goto out;
......@@ -1352,7 +1344,7 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
static int __devexit tmio_mmc_remove(struct platform_device *dev)
{
struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
const struct mfd_cell *cell = mfd_get_cell(dev);
struct mmc_host *mmc = platform_get_drvdata(dev);
platform_set_drvdata(dev, NULL);
......
......@@ -319,7 +319,7 @@ static int tmio_nand_correct_data(struct mtd_info *mtd, unsigned char *buf,
static int tmio_hw_init(struct platform_device *dev, struct tmio_nand *tmio)
{
struct mfd_cell *cell = dev_get_platdata(&dev->dev);
const struct mfd_cell *cell = mfd_get_cell(dev);
int ret;
if (cell->enable) {
......@@ -363,7 +363,7 @@ static int tmio_hw_init(struct platform_device *dev, struct tmio_nand *tmio)
static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio)
{
struct mfd_cell *cell = dev_get_platdata(&dev->dev);
const struct mfd_cell *cell = mfd_get_cell(dev);
tmio_iowrite8(FCR_MODE_POWER_OFF, tmio->fcr + FCR_MODE);
if (cell->disable)
......@@ -372,8 +372,7 @@ static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio)
static int tmio_probe(struct platform_device *dev)
{
struct mfd_cell *cell = dev_get_platdata(&dev->dev);
struct tmio_nand_data *data = cell->driver_data;
struct tmio_nand_data *data = mfd_get_data(dev);
struct resource *fcr = platform_get_resource(dev,
IORESOURCE_MEM, 0);
struct resource *ccr = platform_get_resource(dev,
......@@ -516,7 +515,7 @@ static int tmio_remove(struct platform_device *dev)
#ifdef CONFIG_PM
static int tmio_suspend(struct platform_device *dev, pm_message_t state)
{
struct mfd_cell *cell = dev_get_platdata(&dev->dev);
const struct mfd_cell *cell = mfd_get_cell(dev);
if (cell->suspend)
cell->suspend(dev);
......@@ -527,7 +526,7 @@ static int tmio_suspend(struct platform_device *dev, pm_message_t state)
static int tmio_resume(struct platform_device *dev)
{
struct mfd_cell *cell = dev_get_platdata(&dev->dev);
const struct mfd_cell *cell = mfd_get_cell(dev);
/* FIXME - is this required or merely another attack of the broken
* SHARP platform? Looks suspicious.
......
......@@ -15,6 +15,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/netdevice.h>
#include <linux/can.h>
......@@ -1643,7 +1644,7 @@ static int __devinit ican3_probe(struct platform_device *pdev)
struct device *dev;
int ret;
pdata = pdev->dev.platform_data;
pdata = mfd_get_data(pdev);
if (!pdata)
return -ENXIO;
......
......@@ -26,6 +26,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
......@@ -1145,7 +1146,7 @@ static int __devinit ks8842_probe(struct platform_device *pdev)
struct resource *iomem;
struct net_device *netdev;
struct ks8842_adapter *adapter;
struct ks8842_platform_data *pdata = pdev->dev.platform_data;
struct ks8842_platform_data *pdata = mfd_get_data(pdev);
u16 id;
unsigned i;
......
......@@ -39,7 +39,7 @@ struct jz_battery {
int irq;
int charge_irq;
struct mfd_cell *cell;
const struct mfd_cell *cell;
int status;
long voltage;
......@@ -258,7 +258,7 @@ static int __devinit jz_battery_probe(struct platform_device *pdev)
return -ENOMEM;
}
jz_battery->cell = pdev->dev.platform_data;
jz_battery->cell = mfd_get_cell(pdev);
jz_battery->irq = platform_get_irq(pdev, 0);
if (jz_battery->irq < 0) {
......
......@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/mfd/core.h>
#include <linux/mfd/88pm860x.h>
struct pm8607_regulator_info {
......@@ -394,47 +395,48 @@ static struct pm8607_regulator_info pm8607_regulator_info[] = {
PM8607_LDO(14, LDO14, 0, 4, SUPPLIES_EN12, 6),
};
static inline struct pm8607_regulator_info *find_regulator_info(int id)
static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
{
struct pm8607_regulator_info *info;
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm8607_regulator_info *info = NULL;
struct regulator_init_data *pdata;
struct mfd_cell *cell;
int i;
cell = pdev->dev.platform_data;
if (cell == NULL)
return -ENODEV;
pdata = cell->mfd_data;
if (pdata == NULL)
return -EINVAL;
for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
info = &pm8607_regulator_info[i];
if (info->desc.id == id)
return info;
if (!strcmp(info->desc.name, pdata->constraints.name))
break;
}
return NULL;
}
static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
{
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm860x_platform_data *pdata = chip->dev->platform_data;
struct pm8607_regulator_info *info = NULL;
info = find_regulator_info(pdev->id);
if (info == NULL) {
dev_err(&pdev->dev, "invalid regulator ID specified\n");
if (i > ARRAY_SIZE(pm8607_regulator_info)) {
dev_err(&pdev->dev, "Failed to find regulator %s\n",
pdata->constraints.name);
return -EINVAL;
}
info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
info->chip = chip;
/* check DVC ramp slope double */
if (!strcmp(info->desc.name, "BUCK3"))
if (info->chip->buck3_double)
info->slope_double = 1;
info->regulator = regulator_register(&info->desc, &pdev->dev,
pdata->regulator[pdev->id], info);
pdata, info);
if (IS_ERR(info->regulator)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
info->desc.name);
return PTR_ERR(info->regulator);
}
/* check DVC ramp slope double */
if (info->desc.id == PM8607_ID_BUCK3)
if (info->chip->buck3_double)
info->slope_double = 1;
platform_set_drvdata(pdev, info);
return 0;
}
......
This diff is collapsed.
......@@ -18,6 +18,7 @@ obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
......@@ -33,7 +34,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
......
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