提交 9f1912c4 编写于 作者: L 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: (57 commits)
  regulator: Fix 88pm8607.c printk format warning
  input: Add support for Qualcomm PMIC8XXX power key
  input: Add Qualcomm pm8xxx keypad controller driver
  mfd: Add omap-usbhs runtime PM support
  mfd: Fix ASIC3 SD Host Controller Configuration size
  mfd: Fix omap_usbhs_alloc_children error handling
  mfd: Fix omap usbhs crash when rmmoding ehci or ohci
  mfd: Add ASIC3 LED support
  leds: Add ASIC3 LED support
  mfd: Update twl4030-code maintainer e-mail address
  mfd: Correct the name and bitmask for ab8500-gpadc BTempPullUp
  mfd: Add manual ab8500-gpadc batt temp activation for AB8500 3.0
  mfd: Provide ab8500-core enumerators for chip cuts
  mfd: Check twl4030-power remove script error condition after i2cwrite
  mfd: Fix twl6030 irq definitions
  mfd: Add phoenix lite (twl6025) support to twl6030
  mfd: Avoid to use constraint name in 88pm860x regulator driver
  mfd: Remove checking on max8925 regulator[0]
  mfd: Remove unused parameter from 88pm860x API
  mfd: Avoid to allocate 88pm860x static platform data
  ...
......@@ -931,6 +931,8 @@ F: drivers/mmc/host/msm_sdcc.h
F: drivers/tty/serial/msm_serial.h
F: drivers/tty/serial/msm_serial.c
F: drivers/platform/msm/
F: drivers/*/pm8???-*
F: include/linux/mfd/pm8xxx/
T: git git://codeaurora.org/quic/kernel/davidb/linux-msm.git
S: Maintained
......
......@@ -729,7 +729,7 @@ static struct twl4030_resconfig twl4030_rconfig[] __initdata = {
{ .resource = RES_RESET, .devgroup = -1,
.type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1
},
{ .resource = RES_Main_Ref, .devgroup = -1,
{ .resource = RES_MAIN_REF, .devgroup = -1,
.type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1
},
{ 0, 0},
......
......@@ -27,7 +27,6 @@
#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>
......@@ -685,7 +684,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 = mfd_get_data(pdev);
struct timb_dma_platform_data *pdata = pdev->dev.platform_data;
struct timb_dma *td;
struct resource *iomem;
int irq;
......
......@@ -15,7 +15,6 @@
#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>
......@@ -150,7 +149,7 @@ static int __devinit ttl_probe(struct platform_device *pdev)
struct resource *res;
int ret;
pdata = mfd_get_data(pdev);
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(dev, "no platform data\n");
ret = -ENXIO;
......
......@@ -27,7 +27,6 @@
#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 {
......@@ -136,7 +135,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
struct rdc321x_gpio *rdc321x_gpio_dev;
struct rdc321x_gpio_pdata *pdata;
pdata = mfd_get_data(pdev);
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "no platform data supplied\n");
return -ENODEV;
......
......@@ -23,7 +23,6 @@
#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>
......@@ -229,7 +228,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 = mfd_get_data(pdev);
struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
int irq = platform_get_irq(pdev, 0);
if (!pdata || pdata->nr_pins > 32) {
......@@ -320,13 +319,14 @@ 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 < tgpio->gpio.ngpio; i++) {
for (i = 0; i < pdata->nr_pins; i++) {
irq_set_chip(tgpio->irq_base + i, NULL);
irq_set_chip_data(tgpio->irq_base + i, NULL);
}
......
......@@ -49,7 +49,6 @@
#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>
......@@ -306,7 +305,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
return -EIO;
}
pdata = mfd_get_data(pdev);
pdata = pdev->dev.platform_data;
if (pdata) {
i2c->regstep = pdata->regstep;
i2c->clock_khz = pdata->clock_khz;
......
......@@ -34,7 +34,6 @@
#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>
......@@ -705,7 +704,7 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev)
if (irq < 0)
goto resource_missing;
pdata = mfd_get_data(pdev);
pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data;
if (!pdata)
return -EINVAL;
......
......@@ -412,6 +412,17 @@ config KEYBOARD_PXA930_ROTARY
To compile this driver as a module, choose M here: the
module will be called pxa930_rotary.
config KEYBOARD_PMIC8XXX
tristate "Qualcomm PMIC8XXX keypad support"
depends on MFD_PM8XXX
help
Say Y here if you want to enable the driver for the PMIC8XXX
keypad provided as a reference design from Qualcomm. This is intended
to support upto 18x8 matrix based keypad design.
To compile this driver as a module, choose M here: the module will
be called pmic8xxx-keypad.
config KEYBOARD_SAMSUNG
tristate "Samsung keypad support"
depends on SAMSUNG_DEV_KEYPAD
......
......@@ -34,6 +34,7 @@ obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o
obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o
obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o
obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o
obj-$(CONFIG_KEYBOARD_PMIC8XXX) += pmic8xxx-keypad.o
obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o
obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o
obj-$(CONFIG_KEYBOARD_QT1070) += qt1070.o
......
此差异已折叠。
......@@ -330,6 +330,17 @@ config INPUT_PWM_BEEPER
To compile this driver as a module, choose M here: the module will be
called pwm-beeper.
config INPUT_PMIC8XXX_PWRKEY
tristate "PMIC8XXX power key support"
depends on MFD_PM8XXX
help
Say Y here if you want support for the PMIC8XXX power key.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called pmic8xxx-pwrkey.
config INPUT_GPIO_ROTARY_ENCODER
tristate "Rotary encoders connected to GPIO pins"
depends on GPIOLIB && GENERIC_GPIO
......
......@@ -33,6 +33,7 @@ obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o
obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o
obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
......
/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only 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.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/log2.h>
#include <linux/mfd/pm8xxx/core.h>
#include <linux/input/pmic8xxx-pwrkey.h>
#define PON_CNTL_1 0x1C
#define PON_CNTL_PULL_UP BIT(7)
#define PON_CNTL_TRIG_DELAY_MASK (0x7)
/**
* struct pmic8xxx_pwrkey - pmic8xxx pwrkey information
* @key_press_irq: key press irq number
*/
struct pmic8xxx_pwrkey {
struct input_dev *pwr;
int key_press_irq;
};
static irqreturn_t pwrkey_press_irq(int irq, void *_pwrkey)
{
struct pmic8xxx_pwrkey *pwrkey = _pwrkey;
input_report_key(pwrkey->pwr, KEY_POWER, 1);
input_sync(pwrkey->pwr);
return IRQ_HANDLED;
}
static irqreturn_t pwrkey_release_irq(int irq, void *_pwrkey)
{
struct pmic8xxx_pwrkey *pwrkey = _pwrkey;
input_report_key(pwrkey->pwr, KEY_POWER, 0);
input_sync(pwrkey->pwr);
return IRQ_HANDLED;
}
#ifdef CONFIG_PM_SLEEP
static int pmic8xxx_pwrkey_suspend(struct device *dev)
{
struct pmic8xxx_pwrkey *pwrkey = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
enable_irq_wake(pwrkey->key_press_irq);
return 0;
}
static int pmic8xxx_pwrkey_resume(struct device *dev)
{
struct pmic8xxx_pwrkey *pwrkey = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
disable_irq_wake(pwrkey->key_press_irq);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(pm8xxx_pwr_key_pm_ops,
pmic8xxx_pwrkey_suspend, pmic8xxx_pwrkey_resume);
static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev)
{
struct input_dev *pwr;
int key_release_irq = platform_get_irq(pdev, 0);
int key_press_irq = platform_get_irq(pdev, 1);
int err;
unsigned int delay;
u8 pon_cntl;
struct pmic8xxx_pwrkey *pwrkey;
const struct pm8xxx_pwrkey_platform_data *pdata = mfd_get_data(pdev);
if (!pdata) {
dev_err(&pdev->dev, "power key platform data not supplied\n");
return -EINVAL;
}
if (pdata->kpd_trigger_delay_us > 62500) {
dev_err(&pdev->dev, "invalid power key trigger delay\n");
return -EINVAL;
}
pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL);
if (!pwrkey)
return -ENOMEM;
pwr = input_allocate_device();
if (!pwr) {
dev_dbg(&pdev->dev, "Can't allocate power button\n");
err = -ENOMEM;
goto free_pwrkey;
}
input_set_capability(pwr, EV_KEY, KEY_POWER);
pwr->name = "pmic8xxx_pwrkey";
pwr->phys = "pmic8xxx_pwrkey/input0";
pwr->dev.parent = &pdev->dev;
delay = (pdata->kpd_trigger_delay_us << 10) / USEC_PER_SEC;
delay = 1 + ilog2(delay);
err = pm8xxx_readb(pdev->dev.parent, PON_CNTL_1, &pon_cntl);
if (err < 0) {
dev_err(&pdev->dev, "failed reading PON_CNTL_1 err=%d\n", err);
goto free_input_dev;
}
pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK;
pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK);
if (pdata->pull_up)
pon_cntl |= PON_CNTL_PULL_UP;
else
pon_cntl &= ~PON_CNTL_PULL_UP;
err = pm8xxx_writeb(pdev->dev.parent, PON_CNTL_1, pon_cntl);
if (err < 0) {
dev_err(&pdev->dev, "failed writing PON_CNTL_1 err=%d\n", err);
goto free_input_dev;
}
err = input_register_device(pwr);
if (err) {
dev_dbg(&pdev->dev, "Can't register power key: %d\n", err);
goto free_input_dev;
}
pwrkey->key_press_irq = key_press_irq;
pwrkey->pwr = pwr;
platform_set_drvdata(pdev, pwrkey);
err = request_irq(key_press_irq, pwrkey_press_irq,
IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwrkey);
if (err < 0) {
dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n",
key_press_irq, err);
goto unreg_input_dev;
}
err = request_irq(key_release_irq, pwrkey_release_irq,
IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_release", pwrkey);
if (err < 0) {
dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n",
key_release_irq, err);
goto free_press_irq;
}
device_init_wakeup(&pdev->dev, pdata->wakeup);
return 0;
free_press_irq:
free_irq(key_press_irq, NULL);
unreg_input_dev:
platform_set_drvdata(pdev, NULL);
input_unregister_device(pwr);
pwr = NULL;
free_input_dev:
input_free_device(pwr);
free_pwrkey:
kfree(pwrkey);
return err;
}
static int __devexit pmic8xxx_pwrkey_remove(struct platform_device *pdev)
{
struct pmic8xxx_pwrkey *pwrkey = platform_get_drvdata(pdev);
int key_release_irq = platform_get_irq(pdev, 0);
int key_press_irq = platform_get_irq(pdev, 1);
device_init_wakeup(&pdev->dev, 0);
free_irq(key_press_irq, pwrkey);
free_irq(key_release_irq, pwrkey);
input_unregister_device(pwrkey->pwr);
platform_set_drvdata(pdev, NULL);
kfree(pwrkey);
return 0;
}
static struct platform_driver pmic8xxx_pwrkey_driver = {
.probe = pmic8xxx_pwrkey_probe,
.remove = __devexit_p(pmic8xxx_pwrkey_remove),
.driver = {
.name = PM8XXX_PWRKEY_DEV_NAME,
.owner = THIS_MODULE,
.pm = &pm8xxx_pwr_key_pm_ops,
},
};
static int __init pmic8xxx_pwrkey_init(void)
{
return platform_driver_register(&pmic8xxx_pwrkey_driver);
}
module_init(pmic8xxx_pwrkey_init);
static void __exit pmic8xxx_pwrkey_exit(void)
{
platform_driver_unregister(&pmic8xxx_pwrkey_driver);
}
module_exit(pmic8xxx_pwrkey_exit);
MODULE_ALIAS("platform:pmic8xxx_pwrkey");
MODULE_DESCRIPTION("PMIC8XXX Power Key driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Trilok Soni <tsoni@codeaurora.org>");
......@@ -29,7 +29,6 @@
#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>
......@@ -197,7 +196,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 = mfd_get_data(pdev);
struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data;
struct vibra_info *info;
int ret;
......
......@@ -389,6 +389,16 @@ config LEDS_NETXBIG
and 5Big Network v2 boards. The LEDs are wired to a CPLD and are
controlled through a GPIO extension bus.
config LEDS_ASIC3
bool "LED support for the HTC ASIC3"
depends on MFD_ASIC3
default y
help
This option enables support for the LEDs on the HTC ASIC3. The HTC
ASIC3 LED GPIOs are inputs, not outputs, thus the leds-gpio driver
cannot be used. This driver supports hardware blinking with an on+off
period from 62ms to 125s. Say Y to enable LEDs on the HP iPAQ hx4700.
config LEDS_TRIGGERS
bool "LED Trigger support"
depends on LEDS_CLASS
......
......@@ -42,6 +42,7 @@ obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o
obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o
obj-$(CONFIG_LEDS_NS2) += leds-ns2.o
obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o
obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o
# LED SPI Drivers
obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
......
......@@ -17,7 +17,6 @@
#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)
......@@ -171,7 +170,6 @@ static int pm860x_led_probe(struct platform_device *pdev)
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm860x_led_pdata *pdata;
struct pm860x_led *data;
struct mfd_cell *cell;
struct resource *res;
int ret;
......@@ -181,10 +179,7 @@ static int pm860x_led_probe(struct platform_device *pdev)
return -EINVAL;
}
cell = pdev->dev.platform_data;
if (cell == NULL)
return -ENODEV;
pdata = cell->mfd_data;
pdata = pdev->dev.platform_data;
if (pdata == NULL) {
dev_err(&pdev->dev, "No platform data!\n");
return -EINVAL;
......
/*
* Copyright (C) 2011 Paul Parsons <lost.distance@yahoo.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.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/slab.h>
#include <linux/mfd/asic3.h>
#include <linux/mfd/core.h>
/*
* The HTC ASIC3 LED GPIOs are inputs, not outputs.
* Hence we turn the LEDs on/off via the TimeBase register.
*/
/*
* When TimeBase is 4 the clock resolution is about 32Hz.
* This driver supports hardware blinking with an on+off
* period from 62ms (2 clocks) to 125s (4000 clocks).
*/
#define MS_TO_CLK(ms) DIV_ROUND_CLOSEST(((ms)*1024), 32000)
#define CLK_TO_MS(clk) (((clk)*32000)/1024)
#define MAX_CLK 4000 /* Fits into 12-bit Time registers */
#define MAX_MS CLK_TO_MS(MAX_CLK)
static const unsigned int led_n_base[ASIC3_NUM_LEDS] = {
[0] = ASIC3_LED_0_Base,
[1] = ASIC3_LED_1_Base,
[2] = ASIC3_LED_2_Base,
};
static void brightness_set(struct led_classdev *cdev,
enum led_brightness value)
{
struct platform_device *pdev = to_platform_device(cdev->dev->parent);
const struct mfd_cell *cell = mfd_get_cell(pdev);
struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
u32 timebase;
unsigned int base;
timebase = (value == LED_OFF) ? 0 : (LED_EN|0x4);
base = led_n_base[cell->id];
asic3_write_register(asic, (base + ASIC3_LED_PeriodTime), 32);
asic3_write_register(asic, (base + ASIC3_LED_DutyTime), 32);
asic3_write_register(asic, (base + ASIC3_LED_AutoStopCount), 0);
asic3_write_register(asic, (base + ASIC3_LED_TimeBase), timebase);
}
static int blink_set(struct led_classdev *cdev,
unsigned long *delay_on,
unsigned long *delay_off)
{
struct platform_device *pdev = to_platform_device(cdev->dev->parent);
const struct mfd_cell *cell = mfd_get_cell(pdev);
struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
u32 on;
u32 off;
unsigned int base;
if (*delay_on > MAX_MS || *delay_off > MAX_MS)
return -EINVAL;
if (*delay_on == 0 && *delay_off == 0) {
/* If both are zero then a sensible default should be chosen */
on = MS_TO_CLK(500);
off = MS_TO_CLK(500);
} else {
on = MS_TO_CLK(*delay_on);
off = MS_TO_CLK(*delay_off);
if ((on + off) > MAX_CLK)
return -EINVAL;
}
base = led_n_base[cell->id];
asic3_write_register(asic, (base + ASIC3_LED_PeriodTime), (on + off));
asic3_write_register(asic, (base + ASIC3_LED_DutyTime), on);
asic3_write_register(asic, (base + ASIC3_LED_AutoStopCount), 0);
asic3_write_register(asic, (base + ASIC3_LED_TimeBase), (LED_EN|0x4));
*delay_on = CLK_TO_MS(on);
*delay_off = CLK_TO_MS(off);
return 0;
}
static int __devinit asic3_led_probe(struct platform_device *pdev)
{
struct asic3_led *led = pdev->dev.platform_data;
int ret;
ret = mfd_cell_enable(pdev);
if (ret < 0)
goto ret0;
led->cdev = kzalloc(sizeof(struct led_classdev), GFP_KERNEL);
if (!led->cdev) {
ret = -ENOMEM;
goto ret1;
}
led->cdev->name = led->name;
led->cdev->default_trigger = led->default_trigger;
led->cdev->brightness_set = brightness_set;
led->cdev->blink_set = blink_set;
ret = led_classdev_register(&pdev->dev, led->cdev);
if (ret < 0)
goto ret2;
return 0;
ret2:
kfree(led->cdev);
ret1:
(void) mfd_cell_disable(pdev);
ret0:
return ret;
}
static int __devexit asic3_led_remove(struct platform_device *pdev)
{
struct asic3_led *led = pdev->dev.platform_data;
led_classdev_unregister(led->cdev);
kfree(led->cdev);
return mfd_cell_disable(pdev);
}
static struct platform_driver asic3_led_driver = {
.probe = asic3_led_probe,
.remove = __devexit_p(asic3_led_remove),
.driver = {
.name = "leds-asic3",
.owner = THIS_MODULE,
},
};
MODULE_ALIAS("platform:leds-asic3");
static int __init asic3_led_init(void)
{
return platform_driver_register(&asic3_led_driver);
}
static void __exit asic3_led_exit(void)
{
platform_driver_unregister(&asic3_led_driver);
}
module_init(asic3_led_init);
module_exit(asic3_led_exit);
MODULE_AUTHOR("Paul Parsons <lost.distance@yahoo.com>");
MODULE_DESCRIPTION("HTC ASIC3 LED driver");
MODULE_LICENSE("GPL");
......@@ -22,7 +22,6 @@
#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 {
......@@ -184,7 +183,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 = mfd_get_data(pdev);
struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
int ret = 0;
int reg = 0;
......@@ -265,7 +264,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 = mfd_get_data(pdev);
struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct mc13783_led_platform_data *led_cur;
struct mc13783_led *led, *led_dat;
int ret, i;
......@@ -352,7 +351,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 = mfd_get_data(pdev);
struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct mc13783_led *led = platform_get_drvdata(pdev);
struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
int i;
......
......@@ -21,7 +21,6 @@
#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>
......@@ -149,7 +148,7 @@ static const struct v4l2_file_operations timbradio_fops = {
static int __devinit timbradio_probe(struct platform_device *pdev)
{
struct timb_radio_platform_data *pdata = mfd_get_data(pdev);
struct timb_radio_platform_data *pdata = pdev->dev.platform_data;
struct timbradio *tr;
int err;
......
......@@ -1990,7 +1990,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 = mfd_get_data(pdev);
struct wl1273_core **core = pdev->dev.platform_data;
struct wl1273_device *radio;
struct v4l2_ctrl *ctrl;
int r = 0;
......
......@@ -24,7 +24,6 @@
#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>
......@@ -791,7 +790,7 @@ static int __devinit timblogiw_probe(struct platform_device *pdev)
{
int err;
struct timblogiw *lw = NULL;
struct timb_video_platform_data *pdata = mfd_get_data(pdev);
struct timb_video_platform_data *pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "No platform data\n");
......
......@@ -21,13 +21,13 @@
#define INT_STATUS_NUM 3
static struct resource bk_resources[] __initdata = {
static struct resource bk_resources[] __devinitdata = {
{PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,},
{PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,},
{PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,},
};
static struct resource led_resources[] __initdata = {
static struct resource led_resources[] __devinitdata = {
{PM8606_LED1_RED, PM8606_LED1_RED, "led0-red", IORESOURCE_IO,},
{PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,},
{PM8606_LED1_BLUE, PM8606_LED1_BLUE, "led0-blue", IORESOURCE_IO,},
......@@ -36,7 +36,7 @@ static struct resource led_resources[] __initdata = {
{PM8606_LED2_BLUE, PM8606_LED2_BLUE, "led1-blue", IORESOURCE_IO,},
};
static struct resource regulator_resources[] __initdata = {
static struct resource regulator_resources[] __devinitdata = {
{PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,},
{PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,},
{PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,},
......@@ -57,15 +57,15 @@ static struct resource regulator_resources[] __initdata = {
{PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,},
};
static struct resource touch_resources[] __initdata = {
static struct resource touch_resources[] __devinitdata = {
{PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,},
};
static struct resource onkey_resources[] __initdata = {
static struct resource onkey_resources[] __devinitdata = {
{PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,},
};
static struct resource codec_resources[] __initdata = {
static struct resource codec_resources[] __devinitdata = {
/* Headset microphone insertion or removal */
{PM8607_IRQ_MICIN, PM8607_IRQ_MICIN, "micin", IORESOURCE_IRQ,},
/* Hook-switch press or release */
......@@ -76,12 +76,12 @@ static struct resource codec_resources[] __initdata = {
{PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,},
};
static struct resource battery_resources[] __initdata = {
static struct resource battery_resources[] __devinitdata = {
{PM8607_IRQ_CC, PM8607_IRQ_CC, "columb counter", IORESOURCE_IRQ,},
{PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery", IORESOURCE_IRQ,},
};
static struct resource charger_resources[] __initdata = {
static struct resource charger_resources[] __devinitdata = {
{PM8607_IRQ_CHG, PM8607_IRQ_CHG, "charger detect", IORESOURCE_IRQ,},
{PM8607_IRQ_CHG_DONE, PM8607_IRQ_CHG_DONE, "charging done", IORESOURCE_IRQ,},
{PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging timeout", IORESOURCE_IRQ,},
......@@ -90,13 +90,17 @@ static struct resource charger_resources[] __initdata = {
{PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,},
};
static struct mfd_cell bk_devs[] __initdata = {
static struct resource rtc_resources[] __devinitdata = {
{PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,},
};
static struct mfd_cell bk_devs[] = {
{"88pm860x-backlight", 0,},
{"88pm860x-backlight", 1,},
{"88pm860x-backlight", 2,},
};
static struct mfd_cell led_devs[] __initdata = {
static struct mfd_cell led_devs[] = {
{"88pm860x-led", 0,},
{"88pm860x-led", 1,},
{"88pm860x-led", 2,},
......@@ -105,7 +109,7 @@ static struct mfd_cell led_devs[] __initdata = {
{"88pm860x-led", 5,},
};
static struct mfd_cell regulator_devs[] __initdata = {
static struct mfd_cell regulator_devs[] = {
{"88pm860x-regulator", 0,},
{"88pm860x-regulator", 1,},
{"88pm860x-regulator", 2,},
......@@ -126,15 +130,15 @@ static struct mfd_cell regulator_devs[] __initdata = {
{"88pm860x-regulator", 17,},
};
static struct mfd_cell touch_devs[] __initdata = {
static struct mfd_cell touch_devs[] = {
{"88pm860x-touch", -1,},
};
static struct mfd_cell onkey_devs[] __initdata = {
static struct mfd_cell onkey_devs[] = {
{"88pm860x-onkey", -1,},
};
static struct mfd_cell codec_devs[] __initdata = {
static struct mfd_cell codec_devs[] = {
{"88pm860x-codec", -1,},
};
......@@ -143,11 +147,10 @@ static struct mfd_cell power_devs[] = {
{"88pm860x-charger", -1,},
};
static struct pm860x_backlight_pdata bk_pdata[ARRAY_SIZE(bk_devs)];
static struct pm860x_led_pdata led_pdata[ARRAY_SIZE(led_devs)];
static struct regulator_init_data regulator_pdata[ARRAY_SIZE(regulator_devs)];
static struct pm860x_touch_pdata touch_pdata;
static struct pm860x_power_pdata power_pdata;
static struct mfd_cell rtc_devs[] = {
{"88pm860x-rtc", -1,},
};
struct pm860x_irq_data {
int reg;
......@@ -501,7 +504,6 @@ static void device_irq_exit(struct pm860x_chip *chip)
}
static void __devinit device_bk_init(struct pm860x_chip *chip,
struct i2c_client *i2c,
struct pm860x_platform_data *pdata)
{
int ret;
......@@ -514,13 +516,12 @@ static void __devinit device_bk_init(struct pm860x_chip *chip,
pdata->num_backlights = ARRAY_SIZE(bk_devs);
for (i = 0; i < pdata->num_backlights; i++) {
memcpy(&bk_pdata[i], &pdata->backlight[i],
sizeof(struct pm860x_backlight_pdata));
bk_devs[i].mfd_data = &bk_pdata[i];
bk_devs[i].platform_data = &pdata->backlight[i];
bk_devs[i].pdata_size = sizeof(struct pm860x_backlight_pdata);
for (j = 0; j < ARRAY_SIZE(bk_devs); j++) {
id = bk_resources[j].start;
if (bk_pdata[i].flags != id)
if (pdata->backlight[i].flags != id)
continue;
bk_devs[i].num_resources = 1;
......@@ -538,7 +539,6 @@ static void __devinit device_bk_init(struct pm860x_chip *chip,
}
static void __devinit device_led_init(struct pm860x_chip *chip,
struct i2c_client *i2c,
struct pm860x_platform_data *pdata)
{
int ret;
......@@ -551,13 +551,12 @@ static void __devinit device_led_init(struct pm860x_chip *chip,
pdata->num_leds = ARRAY_SIZE(led_devs);
for (i = 0; i < pdata->num_leds; i++) {
memcpy(&led_pdata[i], &pdata->led[i],
sizeof(struct pm860x_led_pdata));
led_devs[i].mfd_data = &led_pdata[i];
led_devs[i].platform_data = &pdata->led[i];
led_devs[i].pdata_size = sizeof(struct pm860x_led_pdata);
for (j = 0; j < ARRAY_SIZE(led_devs); j++) {
id = led_resources[j].start;
if (led_pdata[i].flags != id)
if (pdata->led[i].flags != id)
continue;
led_devs[i].num_resources = 1;
......@@ -575,12 +574,11 @@ static void __devinit device_led_init(struct pm860x_chip *chip,
}
static void __devinit device_regulator_init(struct pm860x_chip *chip,
struct i2c_client *i2c,
struct pm860x_platform_data *pdata)
{
struct regulator_init_data *initdata;
int ret;
int i, j;
int i, seq;
if ((pdata == NULL) || (pdata->regulator == NULL))
return;
......@@ -588,41 +586,21 @@ static void __devinit device_regulator_init(struct pm860x_chip *chip,
if (pdata->num_regulators > ARRAY_SIZE(regulator_devs))
pdata->num_regulators = ARRAY_SIZE(regulator_devs);
for (i = 0, j = -1; i < pdata->num_regulators; i++) {
for (i = 0, seq = -1; i < pdata->num_regulators; i++) {
initdata = &pdata->regulator[i];
if (strstr(initdata->constraints.name, "BUCK")) {
sscanf(initdata->constraints.name, "BUCK%d", &j);
/* BUCK1 ~ BUCK3 */
if ((j < 1) || (j > 3)) {
dev_err(chip->dev, "Failed to add constraint "
"(%s)\n", initdata->constraints.name);
goto out;
}
j = (j - 1) + PM8607_ID_BUCK1;
}
if (strstr(initdata->constraints.name, "LDO")) {
sscanf(initdata->constraints.name, "LDO%d", &j);
/* LDO1 ~ LDO15 */
if ((j < 1) || (j > 15)) {
dev_err(chip->dev, "Failed to add constraint "
"(%s)\n", initdata->constraints.name);
goto out;
}
j = (j - 1) + PM8607_ID_LDO1;
}
if (j == -1) {
dev_err(chip->dev, "Failed to add constraint (%s)\n",
initdata->constraints.name);
seq = *(unsigned int *)initdata->driver_data;
if ((seq < 0) || (seq > PM8607_ID_RG_MAX)) {
dev_err(chip->dev, "Wrong ID(%d) on regulator(%s)\n",
seq, initdata->constraints.name);
goto out;
}
memcpy(&regulator_pdata[i], &pdata->regulator[i],
sizeof(struct regulator_init_data));
regulator_devs[i].mfd_data = &regulator_pdata[i];
regulator_devs[i].platform_data = &pdata->regulator[i];
regulator_devs[i].pdata_size = sizeof(struct regulator_init_data);
regulator_devs[i].num_resources = 1;
regulator_devs[i].resources = &regulator_resources[j];
regulator_devs[i].resources = &regulator_resources[seq];
ret = mfd_add_devices(chip->dev, 0, &regulator_devs[i], 1,
&regulator_resources[j], 0);
&regulator_resources[seq], 0);
if (ret < 0) {
dev_err(chip->dev, "Failed to add regulator subdev\n");
goto out;
......@@ -632,17 +610,35 @@ static void __devinit device_regulator_init(struct pm860x_chip *chip,
return;
}
static void __devinit device_rtc_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
int ret;
if ((pdata == NULL))
return;
rtc_devs[0].platform_data = pdata->rtc;
rtc_devs[0].pdata_size = sizeof(struct pm860x_rtc_pdata);
rtc_devs[0].num_resources = ARRAY_SIZE(rtc_resources);
rtc_devs[0].resources = &rtc_resources[0];
ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
ARRAY_SIZE(rtc_devs), &rtc_resources[0],
chip->irq_base);
if (ret < 0)
dev_err(chip->dev, "Failed to add rtc subdev\n");
}
static void __devinit device_touch_init(struct pm860x_chip *chip,
struct i2c_client *i2c,
struct pm860x_platform_data *pdata)
{
int ret;
if ((pdata == NULL) || (pdata->touch == NULL))
if (pdata == NULL)
return;
memcpy(&touch_pdata, pdata->touch, sizeof(struct pm860x_touch_pdata));
touch_devs[0].mfd_data = &touch_pdata;
touch_devs[0].platform_data = pdata->touch;
touch_devs[0].pdata_size = sizeof(struct pm860x_touch_pdata);
touch_devs[0].num_resources = ARRAY_SIZE(touch_resources);
touch_devs[0].resources = &touch_resources[0];
ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
......@@ -653,16 +649,15 @@ static void __devinit device_touch_init(struct pm860x_chip *chip,
}
static void __devinit device_power_init(struct pm860x_chip *chip,
struct i2c_client *i2c,
struct pm860x_platform_data *pdata)
{
int ret;
if ((pdata == NULL) || (pdata->power == NULL))
if (pdata == NULL)
return;
memcpy(&power_pdata, pdata->power, sizeof(struct pm860x_power_pdata));
power_devs[0].mfd_data = &power_pdata;
power_devs[0].platform_data = pdata->power;
power_devs[0].pdata_size = sizeof(struct pm860x_power_pdata);
power_devs[0].num_resources = ARRAY_SIZE(battery_resources);
power_devs[0].resources = &battery_resources[0],
ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1,
......@@ -670,7 +665,8 @@ static void __devinit device_power_init(struct pm860x_chip *chip,
if (ret < 0)
dev_err(chip->dev, "Failed to add battery subdev\n");
power_devs[1].mfd_data = &power_pdata;
power_devs[1].platform_data = pdata->power;
power_devs[1].pdata_size = sizeof(struct pm860x_power_pdata);
power_devs[1].num_resources = ARRAY_SIZE(charger_resources);
power_devs[1].resources = &charger_resources[0],
ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1,
......@@ -680,7 +676,6 @@ static void __devinit device_power_init(struct pm860x_chip *chip,
}
static void __devinit device_onkey_init(struct pm860x_chip *chip,
struct i2c_client *i2c,
struct pm860x_platform_data *pdata)
{
int ret;
......@@ -695,7 +690,6 @@ static void __devinit device_onkey_init(struct pm860x_chip *chip,
}
static void __devinit device_codec_init(struct pm860x_chip *chip,
struct i2c_client *i2c,
struct pm860x_platform_data *pdata)
{
int ret;
......@@ -763,11 +757,12 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
if (ret < 0)
goto out;
device_regulator_init(chip, i2c, pdata);
device_onkey_init(chip, i2c, pdata);
device_touch_init(chip, i2c, pdata);
device_power_init(chip, i2c, pdata);
device_codec_init(chip, i2c, pdata);
device_regulator_init(chip, pdata);
device_rtc_init(chip, pdata);
device_onkey_init(chip, pdata);
device_touch_init(chip, pdata);
device_power_init(chip, pdata);
device_codec_init(chip, pdata);
out:
return;
}
......@@ -779,8 +774,8 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
switch (chip->id) {
case CHIP_PM8606:
device_bk_init(chip, chip->client, pdata);
device_led_init(chip, chip->client, pdata);
device_bk_init(chip, pdata);
device_led_init(chip, pdata);
break;
case CHIP_PM8607:
device_8607_init(chip, chip->client, pdata);
......@@ -790,8 +785,8 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
if (chip->companion) {
switch (chip->id) {
case CHIP_PM8607:
device_bk_init(chip, chip->companion, pdata);
device_led_init(chip, chip->companion, pdata);
device_bk_init(chip, pdata);
device_led_init(chip, pdata);
break;
case CHIP_PM8606:
device_8607_init(chip, chip->companion, pdata);
......
......@@ -157,6 +157,20 @@ config TPS6507X
This driver can also be built as a module. If so, the module
will be called tps6507x.
config MFD_TPS6586X
bool "TPS6586x Power Management chips"
depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS
select MFD_CORE
help
If you say yes here you get support for the TPS6586X series of
Power Management chips.
This driver provides common support for accessing the device,
additional drivers must be enabled in order to use the
functionality of the device.
This driver can also be built as a module. If so, the module
will be called tps6586x.
config MENELAUS
bool "Texas Instruments TWL92330/Menelaus PM chip"
depends on I2C=y && ARCH_OMAP2
......@@ -455,6 +469,20 @@ config MFD_PCF50633
facilities, and registers devices for the various functions
so that function-specific drivers can bind to them.
config PCF50633_ADC
tristate "Support for NXP PCF50633 ADC"
depends on MFD_PCF50633
help
Say yes here if you want to include support for ADC in the
NXP PCF50633 chip.
config PCF50633_GPIO
tristate "Support for NXP PCF50633 GPIO"
depends on MFD_PCF50633
help
Say yes here if you want to include support GPIO for pins on
the PCF50633 chip.
config MFD_MC13783
tristate
......@@ -470,20 +498,6 @@ config MFD_MC13XXX
additional drivers must be enabled in order to use the
functionality of the device.
config PCF50633_ADC
tristate "Support for NXP PCF50633 ADC"
depends on MFD_PCF50633
help
Say yes here if you want to include support for ADC in the
NXP PCF50633 chip.
config PCF50633_GPIO
tristate "Support for NXP PCF50633 GPIO"
depends on MFD_PCF50633
help
Say yes here if you want to include support GPIO for pins on
the PCF50633 chip.
config ABX500_CORE
bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions"
default y if ARCH_U300 || ARCH_U8500
......@@ -649,20 +663,6 @@ config MFD_JZ4740_ADC
Say yes here if you want support for the ADC unit in the JZ4740 SoC.
This driver is necessary for jz4740-battery and jz4740-hwmon driver.
config MFD_TPS6586X
bool "TPS6586x Power Management chips"
depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS
select MFD_CORE
help
If you say yes here you get support for the TPS6586X series of
Power Management chips.
This driver provides common support for accessing the device,
additional drivers must be enabled in order to use the
functionality of the device.
This driver can also be built as a module. If so, the module
will be called tps6586x.
config MFD_VX855
tristate "Support for VIA VX855/VX875 integrated south bridge"
depends on PCI
......@@ -691,6 +691,34 @@ config MFD_OMAP_USB_HOST
This MFD driver does the required setup functionalities for
OMAP USB Host drivers.
config MFD_PM8XXX
tristate
config MFD_PM8921_CORE
tristate "Qualcomm PM8921 PMIC chip"
depends on MSM_SSBI
select MFD_CORE
select MFD_PM8XXX
help
If you say yes to this option, support will be included for the
built-in PM8921 PMIC chip.
This is required if your board has a PM8921 and uses its features,
such as: MPPs, GPIOs, regulators, interrupts, and PWM.
Say M here if you want to include support for PM8921 chip as a module.
This will build a module called "pm8921-core".
config MFD_PM8XXX_IRQ
bool "Support for Qualcomm PM8xxx IRQ features"
depends on MFD_PM8XXX
default y if MFD_PM8XXX
help
This is the IRQ driver for Qualcomm PM 8xxx PMIC chips.
This is required to use certain other PM 8xxx features, such as GPIO
and MPP.
endif # MFD_SUPPORT
menu "Multimedia Capabilities Port drivers"
......
......@@ -91,3 +91,5 @@ obj-$(CONFIG_MFD_VX855) += vx855.o
obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o
obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o
obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o
obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o
obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o
......@@ -949,8 +949,10 @@ 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].mfd_data = ab3100_plf_data;
for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++) {
ab3100_devs[i].platform_data = ab3100_plf_data;
ab3100_devs[i].pdata_size = sizeof(struct ab3100_platform_data);
}
err = mfd_add_devices(&client->dev, 0, ab3100_devs,
ARRAY_SIZE(ab3100_devs), NULL, 0);
......
......@@ -1320,8 +1320,10 @@ 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].mfd_data = ab3550_plf_data->dev_data[i];
for (i = 0; i < AB3550_NUM_DEVICES; i++) {
ab3550_devs[i].platform_data = ab3550_plf_data->dev_data[i];
ab3550_devs[i].pdata_size = ab3550_plf_data->dev_data_sz[i];
}
err = mfd_add_devices(&client->dev, 0, ab3550_devs,
ARRAY_SIZE(ab3550_devs), NULL,
......
......@@ -254,8 +254,9 @@ static void ab8500_irq_sync_unlock(struct irq_data *data)
if (new == old)
continue;
/* Interrupt register 12 does'nt exist prior to version 0x20 */
if (ab8500_irq_regoffset[i] == 11 && ab8500->chip_id < 0x20)
/* Interrupt register 12 doesn't exist prior to version 2.0 */
if (ab8500_irq_regoffset[i] == 11 &&
ab8500->chip_id < AB8500_CUT2P0)
continue;
ab8500->oldmask[i] = new;
......@@ -307,8 +308,8 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
int status;
u8 value;
/* Interrupt register 12 does'nt exist prior to version 0x20 */
if (regoffset == 11 && ab8500->chip_id < 0x20)
/* Interrupt register 12 doesn't exist prior to version 2.0 */
if (regoffset == 11 && ab8500->chip_id < AB8500_CUT2P0)
continue;
status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
......@@ -724,17 +725,15 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
if (ret < 0)
return ret;
/*
* 0x0 - Early Drop
* 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 ||
value == 0x30) {
switch (value) {
case AB8500_CUTEARLY:
case AB8500_CUT1P0:
case AB8500_CUT1P1:
case AB8500_CUT2P0:
case AB8500_CUT3P0:
dev_info(ab8500->dev, "detected chip, revision: %#x\n", value);
} else {
break;
default:
dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value);
return -EINVAL;
}
......@@ -763,8 +762,9 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
/* Clear and mask all interrupts */
for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
/* Interrupt register 12 does'nt exist prior to version 0x20 */
if (ab8500_irq_regoffset[i] == 11 && ab8500->chip_id < 0x20)
/* Interrupt register 12 doesn't exist prior to version 2.0 */
if (ab8500_irq_regoffset[i] == 11 &&
ab8500->chip_id < AB8500_CUT2P0)
continue;
get_register_interruptible(ab8500, AB8500_INTERRUPT,
......
......@@ -57,6 +57,7 @@
#define SW_AVG_16 0x60
#define ADC_SW_CONV 0x04
#define EN_ICHAR 0x80
#define BTEMP_PULL_UP 0x08
#define EN_BUF 0x40
#define DIS_ZERO 0x00
#define GPADC_BUSY 0x01
......@@ -101,6 +102,7 @@ struct adc_cal_data {
/**
* struct ab8500_gpadc - AB8500 GPADC device information
* @chip_id ABB chip id
* @dev: pointer to the struct device
* @node: a list of AB8500 GPADCs, hence prepared for
reentrance
......@@ -112,6 +114,7 @@ struct adc_cal_data {
* @cal_data array of ADC calibration data structs
*/
struct ab8500_gpadc {
u8 chip_id;
struct device *dev;
struct list_head node;
struct completion ab8500_gpadc_complete;
......@@ -274,6 +277,7 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input)
dev_err(gpadc->dev, "gpadc_conversion: enable gpadc failed\n");
goto out;
}
/* Select the input source and set average samples to 16 */
ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
AB8500_GPADC_CTRL2_REG, (input | SW_AVG_16));
......@@ -282,9 +286,11 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input)
"gpadc_conversion: set avg samples failed\n");
goto out;
}
/*
* Enable ADC, buffering, select rising edge and enable ADC path
* charging current sense if it needed
* charging current sense if it needed, ABB 3.0 needs some special
* treatment too.
*/
switch (input) {
case MAIN_CHARGER_C:
......@@ -294,6 +300,23 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input)
EN_BUF | EN_ICHAR,
EN_BUF | EN_ICHAR);
break;
case BTEMP_BALL:
if (gpadc->chip_id >= AB8500_CUT3P0) {
/* Turn on btemp pull-up on ABB 3.0 */
ret = abx500_mask_and_set_register_interruptible(
gpadc->dev,
AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
EN_BUF | BTEMP_PULL_UP,
EN_BUF | BTEMP_PULL_UP);
/*
* Delay might be needed for ABB8500 cut 3.0, if not, remove
* when hardware will be availible
*/
msleep(1);
break;
}
/* Intentional fallthrough */
default:
ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
AB8500_GPADC, AB8500_GPADC_CTRL1_REG, EN_BUF, EN_BUF);
......@@ -304,6 +327,7 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input)
"gpadc_conversion: select falling edge failed\n");
goto out;
}
ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
AB8500_GPADC, AB8500_GPADC_CTRL1_REG, ADC_SW_CONV, ADC_SW_CONV);
if (ret < 0) {
......@@ -552,6 +576,14 @@ static int __devinit ab8500_gpadc_probe(struct platform_device *pdev)
goto fail;
}
/* Get Chip ID of the ABB ASIC */
ret = abx500_get_chip_id(gpadc->dev);
if (ret < 0) {
dev_err(gpadc->dev, "failed to get chip ID\n");
goto fail_irq;
}
gpadc->chip_id = (u8) ret;
/* VTVout LDO used to power up ab8500-GPADC */
gpadc->regu = regulator_get(&pdev->dev, "vddadc");
if (IS_ERR(gpadc->regu)) {
......
......@@ -88,19 +88,19 @@ struct asic3 {
static int asic3_gpio_get(struct gpio_chip *chip, unsigned offset);
static inline void asic3_write_register(struct asic3 *asic,
unsigned int reg, u32 value)
void asic3_write_register(struct asic3 *asic, unsigned int reg, u32 value)
{
iowrite16(value, asic->mapping +
(reg >> asic->bus_shift));
}
EXPORT_SYMBOL_GPL(asic3_write_register);
static inline u32 asic3_read_register(struct asic3 *asic,
unsigned int reg)
u32 asic3_read_register(struct asic3 *asic, unsigned int reg)
{
return ioread16(asic->mapping +
(reg >> asic->bus_shift));
}
EXPORT_SYMBOL_GPL(asic3_read_register);
static void asic3_set_register(struct asic3 *asic, u32 reg, u32 bits, bool set)
{
......@@ -676,7 +676,8 @@ static struct mfd_cell asic3_cell_ds1wm = {
.name = "ds1wm",
.enable = ds1wm_enable,
.disable = ds1wm_disable,
.mfd_data = &ds1wm_pdata,
.platform_data = &ds1wm_pdata,
.pdata_size = sizeof(ds1wm_pdata),
.num_resources = ARRAY_SIZE(ds1wm_resources),
.resources = ds1wm_resources,
};
......@@ -777,12 +778,61 @@ static struct mfd_cell asic3_cell_mmc = {
.name = "tmio-mmc",
.enable = asic3_mmc_enable,
.disable = asic3_mmc_disable,
.mfd_data = &asic3_mmc_data,
.platform_data = &asic3_mmc_data,
.pdata_size = sizeof(asic3_mmc_data),
.num_resources = ARRAY_SIZE(asic3_mmc_resources),
.resources = asic3_mmc_resources,
};
static const int clock_ledn[ASIC3_NUM_LEDS] = {
[0] = ASIC3_CLOCK_LED0,
[1] = ASIC3_CLOCK_LED1,
[2] = ASIC3_CLOCK_LED2,
};
static int asic3_leds_enable(struct platform_device *pdev)
{
const struct mfd_cell *cell = mfd_get_cell(pdev);
struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
asic3_clk_enable(asic, &asic->clocks[clock_ledn[cell->id]]);
return 0;
}
static int asic3_leds_disable(struct platform_device *pdev)
{
const struct mfd_cell *cell = mfd_get_cell(pdev);
struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
asic3_clk_disable(asic, &asic->clocks[clock_ledn[cell->id]]);
return 0;
}
static struct mfd_cell asic3_cell_leds[ASIC3_NUM_LEDS] = {
[0] = {
.name = "leds-asic3",
.id = 0,
.enable = asic3_leds_enable,
.disable = asic3_leds_disable,
},
[1] = {
.name = "leds-asic3",
.id = 1,
.enable = asic3_leds_enable,
.disable = asic3_leds_disable,
},
[2] = {
.name = "leds-asic3",
.id = 2,
.enable = asic3_leds_enable,
.disable = asic3_leds_disable,
},
};
static int __init asic3_mfd_probe(struct platform_device *pdev,
struct asic3_platform_data *pdata,
struct resource *mem)
{
struct asic3 *asic = platform_get_drvdata(pdev);
......@@ -806,7 +856,8 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
/* MMC */
asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
mem_sdio->start, 0x400 >> asic->bus_shift);
mem_sdio->start,
ASIC3_SD_CONFIG_SIZE >> asic->bus_shift);
if (!asic->tmio_cnf) {
ret = -ENOMEM;
dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n");
......@@ -820,9 +871,23 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
if (ret < 0)
goto out;
if (mem_sdio && (irq >= 0))
if (mem_sdio && (irq >= 0)) {
ret = mfd_add_devices(&pdev->dev, pdev->id,
&asic3_cell_mmc, 1, mem_sdio, irq);
if (ret < 0)
goto out;
}
if (pdata->leds) {
int i;
for (i = 0; i < ASIC3_NUM_LEDS; ++i) {
asic3_cell_leds[i].platform_data = &pdata->leds[i];
asic3_cell_leds[i].pdata_size = sizeof(pdata->leds[i]);
}
ret = mfd_add_devices(&pdev->dev, 0,
asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0);
}
out:
return ret;
......@@ -903,7 +968,7 @@ static int __init asic3_probe(struct platform_device *pdev)
*/
memcpy(asic->clocks, asic3_clk_init, sizeof(asic3_clk_init));
asic3_mfd_probe(pdev, mem);
asic3_mfd_probe(pdev, pdata, mem);
dev_info(asic->dev, "ASIC3 Core driver\n");
......
......@@ -119,12 +119,14 @@ 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->mfd_data = davinci_vc;
cell->platform_data = davinci_vc;
cell->pdata_size = sizeof(*davinci_vc);
/* Voice codec CQ93VC client */
cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL];
cell->name = "cq93vc-codec";
cell->mfd_data = davinci_vc;
cell->platform_data = davinci_vc;
cell->pdata_size = sizeof(*davinci_vc);
ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells,
DAVINCI_VC_CELLS, NULL, 0);
......
......@@ -117,7 +117,8 @@ static struct mfd_cell ds1wm_cell __initdata = {
.name = "ds1wm",
.enable = ds1wm_enable,
.disable = ds1wm_disable,
.mfd_data = &ds1wm_pdata,
.platform_data = &ds1wm_pdata,
.pdata_size = sizeof(ds1wm_pdata),
.num_resources = 2,
.resources = ds1wm_resources,
};
......@@ -172,6 +173,8 @@ static int __init pasic3_probe(struct platform_device *pdev)
}
if (pdata && pdata->led_pdata) {
led_cell.platform_data = pdata->led_pdata;
led_cell.pdata_size = sizeof(struct pasic3_leds_machinfo);
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,7 +86,8 @@ static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv,
/* Add platform data */
pdata->modno = modno;
cell->mfd_data = pdata;
cell->platform_data = pdata;
cell->pdata_size = sizeof(*pdata);
/* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */
res->flags = IORESOURCE_MEM;
......
......@@ -627,7 +627,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
goto out_dev;
}
if (pdata && pdata->regulator[0]) {
if (pdata) {
ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
ARRAY_SIZE(regulator_devs),
&regulator_resources[0], 0);
......
......@@ -683,13 +683,14 @@ 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)
const char *format, void *pdata, size_t pdata_size)
{
char buf[30];
const char *name = mc13xxx_get_chipname(mc13xxx);
struct mfd_cell cell = {
.mfd_data = pdata,
.platform_data = pdata,
.pdata_size = pdata_size,
};
/* there is no asnprintf in the kernel :-( */
......@@ -705,7 +706,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);
return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL, 0);
}
static int mc13xxx_probe(struct spi_device *spi)
......@@ -764,7 +765,7 @@ static int mc13xxx_probe(struct spi_device *spi)
if (pdata->flags & MC13XXX_USE_REGULATOR) {
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
&pdata->regulators);
&pdata->regulators, sizeof(pdata->regulators));
}
if (pdata->flags & MC13XXX_USE_RTC)
......@@ -774,7 +775,8 @@ static int mc13xxx_probe(struct spi_device *spi)
mc13xxx_add_subdevice(mc13xxx, "%s-ts");
if (pdata->flags & MC13XXX_USE_LED)
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", pdata->leds);
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led",
pdata->leds, sizeof(*pdata->leds));
return 0;
}
......
......@@ -88,6 +88,13 @@ static int mfd_add_device(struct device *parent, int id,
pdev->dev.parent = parent;
if (cell->pdata_size) {
ret = platform_device_add_data(pdev,
cell->platform_data, cell->pdata_size);
if (ret)
goto fail_res;
}
ret = mfd_platform_add_cell(pdev, cell);
if (ret)
goto fail_res;
......
......@@ -26,6 +26,7 @@
#include <linux/spinlock.h>
#include <linux/gpio.h>
#include <plat/usb.h>
#include <linux/pm_runtime.h>
#define USBHS_DRIVER_NAME "usbhs-omap"
#define OMAP_EHCI_DEVICE "ehci-omap"
......@@ -146,9 +147,6 @@
struct usbhs_hcd_omap {
struct clk *usbhost_ick;
struct clk *usbhost_hs_fck;
struct clk *usbhost_fs_fck;
struct clk *xclk60mhsp1_ck;
struct clk *xclk60mhsp2_ck;
struct clk *utmi_p1_fck;
......@@ -158,8 +156,6 @@ struct usbhs_hcd_omap {
struct clk *usbhost_p2_fck;
struct clk *usbtll_p2_fck;
struct clk *init_60m_fclk;
struct clk *usbtll_fck;
struct clk *usbtll_ick;
void __iomem *uhh_base;
void __iomem *tll_base;
......@@ -281,6 +277,7 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
if (!ehci) {
dev_err(dev, "omap_usbhs_alloc_child failed\n");
ret = -ENOMEM;
goto err_end;
}
......@@ -304,13 +301,14 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
sizeof(*ohci_data), dev);
if (!ohci) {
dev_err(dev, "omap_usbhs_alloc_child failed\n");
ret = -ENOMEM;
goto err_ehci;
}
return 0;
err_ehci:
platform_device_put(ehci);
platform_device_unregister(ehci);
err_end:
return ret;
......@@ -351,46 +349,13 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
omap->platdata.ehci_data = pdata->ehci_data;
omap->platdata.ohci_data = pdata->ohci_data;
omap->usbhost_ick = clk_get(dev, "usbhost_ick");
if (IS_ERR(omap->usbhost_ick)) {
ret = PTR_ERR(omap->usbhost_ick);
dev_err(dev, "usbhost_ick failed error:%d\n", ret);
goto err_end;
}
omap->usbhost_hs_fck = clk_get(dev, "hs_fck");
if (IS_ERR(omap->usbhost_hs_fck)) {
ret = PTR_ERR(omap->usbhost_hs_fck);
dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret);
goto err_usbhost_ick;
}
omap->usbhost_fs_fck = clk_get(dev, "fs_fck");
if (IS_ERR(omap->usbhost_fs_fck)) {
ret = PTR_ERR(omap->usbhost_fs_fck);
dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret);
goto err_usbhost_hs_fck;
}
omap->usbtll_fck = clk_get(dev, "usbtll_fck");
if (IS_ERR(omap->usbtll_fck)) {
ret = PTR_ERR(omap->usbtll_fck);
dev_err(dev, "usbtll_fck failed error:%d\n", ret);
goto err_usbhost_fs_fck;
}
omap->usbtll_ick = clk_get(dev, "usbtll_ick");
if (IS_ERR(omap->usbtll_ick)) {
ret = PTR_ERR(omap->usbtll_ick);
dev_err(dev, "usbtll_ick failed error:%d\n", ret);
goto err_usbtll_fck;
}
pm_runtime_enable(&pdev->dev);
omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
if (IS_ERR(omap->utmi_p1_fck)) {
ret = PTR_ERR(omap->utmi_p1_fck);
dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret);
goto err_usbtll_ick;
goto err_end;
}
omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
......@@ -520,22 +485,8 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
err_utmi_p1_fck:
clk_put(omap->utmi_p1_fck);
err_usbtll_ick:
clk_put(omap->usbtll_ick);
err_usbtll_fck:
clk_put(omap->usbtll_fck);
err_usbhost_fs_fck:
clk_put(omap->usbhost_fs_fck);
err_usbhost_hs_fck:
clk_put(omap->usbhost_hs_fck);
err_usbhost_ick:
clk_put(omap->usbhost_ick);
err_end:
pm_runtime_disable(&pdev->dev);
kfree(omap);
end_probe:
......@@ -569,11 +520,7 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev)
clk_put(omap->utmi_p2_fck);
clk_put(omap->xclk60mhsp1_ck);
clk_put(omap->utmi_p1_fck);
clk_put(omap->usbtll_ick);
clk_put(omap->usbtll_fck);
clk_put(omap->usbhost_fs_fck);
clk_put(omap->usbhost_hs_fck);
clk_put(omap->usbhost_ick);
pm_runtime_disable(&pdev->dev);
kfree(omap);
return 0;
......@@ -693,7 +640,6 @@ static int usbhs_enable(struct device *dev)
struct usbhs_omap_platform_data *pdata = &omap->platdata;
unsigned long flags = 0;
int ret = 0;
unsigned long timeout;
unsigned reg;
dev_dbg(dev, "starting TI HSUSB Controller\n");
......@@ -706,11 +652,7 @@ static int usbhs_enable(struct device *dev)
if (omap->count > 0)
goto end_count;
clk_enable(omap->usbhost_ick);
clk_enable(omap->usbhost_hs_fck);
clk_enable(omap->usbhost_fs_fck);
clk_enable(omap->usbtll_fck);
clk_enable(omap->usbtll_ick);
pm_runtime_get_sync(dev);
if (pdata->ehci_data->phy_reset) {
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) {
......@@ -734,50 +676,6 @@ static int usbhs_enable(struct device *dev)
omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
/* perform TLL soft reset, and wait until reset is complete */
usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
OMAP_USBTLL_SYSCONFIG_SOFTRESET);
/* Wait for TLL reset to complete */
timeout = jiffies + msecs_to_jiffies(1000);
while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
& OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
cpu_relax();
if (time_after(jiffies, timeout)) {
dev_dbg(dev, "operation timed out\n");
ret = -EINVAL;
goto err_tll;
}
}
dev_dbg(dev, "TLL RESET DONE\n");
/* (1<<3) = no idle mode only for initial debugging */
usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
OMAP_USBTLL_SYSCONFIG_AUTOIDLE);
/* Put UHH in NoIdle/NoStandby mode */
reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG);
if (is_omap_usbhs_rev1(omap)) {
reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
| OMAP_UHH_SYSCONFIG_SIDLEMODE
| OMAP_UHH_SYSCONFIG_CACTIVITY
| OMAP_UHH_SYSCONFIG_MIDLEMODE);
reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
} else if (is_omap_usbhs_rev2(omap)) {
reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR;
reg |= OMAP4_UHH_SYSCONFIG_NOIDLE;
reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR;
reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY;
}
usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
/* setup ULPI bypass and burst configurations */
reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
......@@ -917,6 +815,8 @@ static int usbhs_enable(struct device *dev)
return 0;
err_tll:
pm_runtime_put_sync(dev);
spin_unlock_irqrestore(&omap->lock, flags);
if (pdata->ehci_data->phy_reset) {
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
gpio_free(pdata->ehci_data->reset_gpio_port[0]);
......@@ -924,13 +824,6 @@ static int usbhs_enable(struct device *dev)
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
gpio_free(pdata->ehci_data->reset_gpio_port[1]);
}
clk_disable(omap->usbtll_ick);
clk_disable(omap->usbtll_fck);
clk_disable(omap->usbhost_fs_fck);
clk_disable(omap->usbhost_hs_fck);
clk_disable(omap->usbhost_ick);
spin_unlock_irqrestore(&omap->lock, flags);
return ret;
}
......@@ -994,6 +887,20 @@ static void usbhs_disable(struct device *dev)
dev_dbg(dev, "operation timed out\n");
}
if (is_omap_usbhs_rev2(omap)) {
if (is_ehci_tll_mode(pdata->port_mode[0]))
clk_enable(omap->usbtll_p1_fck);
if (is_ehci_tll_mode(pdata->port_mode[1]))
clk_enable(omap->usbtll_p2_fck);
clk_disable(omap->utmi_p2_fck);
clk_disable(omap->utmi_p1_fck);
}
pm_runtime_put_sync(dev);
/* The gpio_free migh sleep; so unlock the spinlock */
spin_unlock_irqrestore(&omap->lock, flags);
if (pdata->ehci_data->phy_reset) {
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
gpio_free(pdata->ehci_data->reset_gpio_port[0]);
......@@ -1001,14 +908,7 @@ static void usbhs_disable(struct device *dev)
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
gpio_free(pdata->ehci_data->reset_gpio_port[1]);
}
clk_disable(omap->utmi_p2_fck);
clk_disable(omap->utmi_p1_fck);
clk_disable(omap->usbtll_ick);
clk_disable(omap->usbtll_fck);
clk_disable(omap->usbhost_fs_fck);
clk_disable(omap->usbhost_hs_fck);
clk_disable(omap->usbhost_ick);
return;
end_disble:
spin_unlock_irqrestore(&omap->lock, flags);
......
/*
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only 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.
*/
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/msm_ssbi.h>
#include <linux/mfd/core.h>
#include <linux/mfd/pm8xxx/pm8921.h>
#include <linux/mfd/pm8xxx/core.h>
#define REG_HWREV 0x002 /* PMIC4 revision */
#define REG_HWREV_2 0x0E8 /* PMIC4 revision 2 */
struct pm8921 {
struct device *dev;
struct pm_irq_chip *irq_chip;
};
static int pm8921_readb(const struct device *dev, u16 addr, u8 *val)
{
const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
return msm_ssbi_read(pmic->dev->parent, addr, val, 1);
}
static int pm8921_writeb(const struct device *dev, u16 addr, u8 val)
{
const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
return msm_ssbi_write(pmic->dev->parent, addr, &val, 1);
}
static int pm8921_read_buf(const struct device *dev, u16 addr, u8 *buf,
int cnt)
{
const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
return msm_ssbi_read(pmic->dev->parent, addr, buf, cnt);
}
static int pm8921_write_buf(const struct device *dev, u16 addr, u8 *buf,
int cnt)
{
const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
return msm_ssbi_write(pmic->dev->parent, addr, buf, cnt);
}
static int pm8921_read_irq_stat(const struct device *dev, int irq)
{
const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
return pm8xxx_get_irq_stat(pmic->irq_chip, irq);
}
static struct pm8xxx_drvdata pm8921_drvdata = {
.pmic_readb = pm8921_readb,
.pmic_writeb = pm8921_writeb,
.pmic_read_buf = pm8921_read_buf,
.pmic_write_buf = pm8921_write_buf,
.pmic_read_irq_stat = pm8921_read_irq_stat,
};
static int __devinit pm8921_add_subdevices(const struct pm8921_platform_data
*pdata,
struct pm8921 *pmic,
u32 rev)
{
int ret = 0, irq_base = 0;
struct pm_irq_chip *irq_chip;
if (pdata->irq_pdata) {
pdata->irq_pdata->irq_cdata.nirqs = PM8921_NR_IRQS;
pdata->irq_pdata->irq_cdata.rev = rev;
irq_base = pdata->irq_pdata->irq_base;
irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata);
if (IS_ERR(irq_chip)) {
pr_err("Failed to init interrupts ret=%ld\n",
PTR_ERR(irq_chip));
return PTR_ERR(irq_chip);
}
pmic->irq_chip = irq_chip;
}
return ret;
}
static int __devinit pm8921_probe(struct platform_device *pdev)
{
const struct pm8921_platform_data *pdata = pdev->dev.platform_data;
struct pm8921 *pmic;
int rc;
u8 val;
u32 rev;
if (!pdata) {
pr_err("missing platform data\n");
return -EINVAL;
}
pmic = kzalloc(sizeof(struct pm8921), GFP_KERNEL);
if (!pmic) {
pr_err("Cannot alloc pm8921 struct\n");
return -ENOMEM;
}
/* Read PMIC chip revision */
rc = msm_ssbi_read(pdev->dev.parent, REG_HWREV, &val, sizeof(val));
if (rc) {
pr_err("Failed to read hw rev reg %d:rc=%d\n", REG_HWREV, rc);
goto err_read_rev;
}
pr_info("PMIC revision 1: %02X\n", val);
rev = val;
/* Read PMIC chip revision 2 */
rc = msm_ssbi_read(pdev->dev.parent, REG_HWREV_2, &val, sizeof(val));
if (rc) {
pr_err("Failed to read hw rev 2 reg %d:rc=%d\n",
REG_HWREV_2, rc);
goto err_read_rev;
}
pr_info("PMIC revision 2: %02X\n", val);
rev |= val << BITS_PER_BYTE;
pmic->dev = &pdev->dev;
pm8921_drvdata.pm_chip_data = pmic;
platform_set_drvdata(pdev, &pm8921_drvdata);
rc = pm8921_add_subdevices(pdata, pmic, rev);
if (rc) {
pr_err("Cannot add subdevices rc=%d\n", rc);
goto err;
}
/* gpio might not work if no irq device is found */
WARN_ON(pmic->irq_chip == NULL);
return 0;
err:
mfd_remove_devices(pmic->dev);
platform_set_drvdata(pdev, NULL);
err_read_rev:
kfree(pmic);
return rc;
}
static int __devexit pm8921_remove(struct platform_device *pdev)
{
struct pm8xxx_drvdata *drvdata;
struct pm8921 *pmic = NULL;
drvdata = platform_get_drvdata(pdev);
if (drvdata)
pmic = drvdata->pm_chip_data;
if (pmic)
mfd_remove_devices(pmic->dev);
if (pmic->irq_chip) {
pm8xxx_irq_exit(pmic->irq_chip);
pmic->irq_chip = NULL;
}
platform_set_drvdata(pdev, NULL);
kfree(pmic);
return 0;
}
static struct platform_driver pm8921_driver = {
.probe = pm8921_probe,
.remove = __devexit_p(pm8921_remove),
.driver = {
.name = "pm8921-core",
.owner = THIS_MODULE,
},
};
static int __init pm8921_init(void)
{
return platform_driver_register(&pm8921_driver);
}
subsys_initcall(pm8921_init);
static void __exit pm8921_exit(void)
{
platform_driver_unregister(&pm8921_driver);
}
module_exit(pm8921_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("PMIC 8921 core driver");
MODULE_VERSION("1.0");
MODULE_ALIAS("platform:pm8921-core");
/*
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only 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.
*/
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/mfd/pm8xxx/core.h>
#include <linux/mfd/pm8xxx/irq.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
/* PMIC8xxx IRQ */
#define SSBI_REG_ADDR_IRQ_BASE 0x1BB
#define SSBI_REG_ADDR_IRQ_ROOT (SSBI_REG_ADDR_IRQ_BASE + 0)
#define SSBI_REG_ADDR_IRQ_M_STATUS1 (SSBI_REG_ADDR_IRQ_BASE + 1)
#define SSBI_REG_ADDR_IRQ_M_STATUS2 (SSBI_REG_ADDR_IRQ_BASE + 2)
#define SSBI_REG_ADDR_IRQ_M_STATUS3 (SSBI_REG_ADDR_IRQ_BASE + 3)
#define SSBI_REG_ADDR_IRQ_M_STATUS4 (SSBI_REG_ADDR_IRQ_BASE + 4)
#define SSBI_REG_ADDR_IRQ_BLK_SEL (SSBI_REG_ADDR_IRQ_BASE + 5)
#define SSBI_REG_ADDR_IRQ_IT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 6)
#define SSBI_REG_ADDR_IRQ_CONFIG (SSBI_REG_ADDR_IRQ_BASE + 7)
#define SSBI_REG_ADDR_IRQ_RT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 8)
#define PM_IRQF_LVL_SEL 0x01 /* level select */
#define PM_IRQF_MASK_FE 0x02 /* mask falling edge */
#define PM_IRQF_MASK_RE 0x04 /* mask rising edge */
#define PM_IRQF_CLR 0x08 /* clear interrupt */
#define PM_IRQF_BITS_MASK 0x70
#define PM_IRQF_BITS_SHIFT 4
#define PM_IRQF_WRITE 0x80
#define PM_IRQF_MASK_ALL (PM_IRQF_MASK_FE | \
PM_IRQF_MASK_RE)
struct pm_irq_chip {
struct device *dev;
spinlock_t pm_irq_lock;
unsigned int devirq;
unsigned int irq_base;
unsigned int num_irqs;
unsigned int num_blocks;
unsigned int num_masters;
u8 config[0];
};
static int pm8xxx_read_root_irq(const struct pm_irq_chip *chip, u8 *rp)
{
return pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_ROOT, rp);
}
static int pm8xxx_read_master_irq(const struct pm_irq_chip *chip, u8 m, u8 *bp)
{
return pm8xxx_readb(chip->dev,
SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp);
}
static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, u8 bp, u8 *ip)
{
int rc;
spin_lock(&chip->pm_irq_lock);
rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
if (rc) {
pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
goto bail;
}
rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
if (rc)
pr_err("Failed Reading Status rc=%d\n", rc);
bail:
spin_unlock(&chip->pm_irq_lock);
return rc;
}
static int pm8xxx_config_irq(struct pm_irq_chip *chip, u8 bp, u8 cp)
{
int rc;
spin_lock(&chip->pm_irq_lock);
rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
if (rc) {
pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
goto bail;
}
cp |= PM_IRQF_WRITE;
rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp);
if (rc)
pr_err("Failed Configuring IRQ rc=%d\n", rc);
bail:
spin_unlock(&chip->pm_irq_lock);
return rc;
}
static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
{
int pmirq, irq, i, ret = 0;
u8 bits;
ret = pm8xxx_read_block_irq(chip, block, &bits);
if (ret) {
pr_err("Failed reading %d block ret=%d", block, ret);
return ret;
}
if (!bits) {
pr_err("block bit set in master but no irqs: %d", block);
return 0;
}
/* Check IRQ bits */
for (i = 0; i < 8; i++) {
if (bits & (1 << i)) {
pmirq = block * 8 + i;
irq = pmirq + chip->irq_base;
generic_handle_irq(irq);
}
}
return 0;
}
static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
{
u8 blockbits;
int block_number, i, ret = 0;
ret = pm8xxx_read_master_irq(chip, master, &blockbits);
if (ret) {
pr_err("Failed to read master %d ret=%d\n", master, ret);
return ret;
}
if (!blockbits) {
pr_err("master bit set in root but no blocks: %d", master);
return 0;
}
for (i = 0; i < 8; i++)
if (blockbits & (1 << i)) {
block_number = master * 8 + i; /* block # */
ret |= pm8xxx_irq_block_handler(chip, block_number);
}
return ret;
}
static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc)
{
struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
struct irq_chip *irq_chip = irq_desc_get_chip(desc);
u8 root;
int i, ret, masters = 0;
ret = pm8xxx_read_root_irq(chip, &root);
if (ret) {
pr_err("Can't read root status ret=%d\n", ret);
return;
}
/* on pm8xxx series masters start from bit 1 of the root */
masters = root >> 1;
/* Read allowed masters for blocks. */
for (i = 0; i < chip->num_masters; i++)
if (masters & (1 << i))
pm8xxx_irq_master_handler(chip, i);
irq_chip->irq_ack(&desc->irq_data);
}
static void pm8xxx_irq_mask_ack(struct irq_data *d)
{
struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
unsigned int pmirq = d->irq - chip->irq_base;
int master, irq_bit;
u8 block, config;
block = pmirq / 8;
master = block / 8;
irq_bit = pmirq % 8;
config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
pm8xxx_config_irq(chip, block, config);
}
static void pm8xxx_irq_unmask(struct irq_data *d)
{
struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
unsigned int pmirq = d->irq - chip->irq_base;
int master, irq_bit;
u8 block, config;
block = pmirq / 8;
master = block / 8;
irq_bit = pmirq % 8;
config = chip->config[pmirq];
pm8xxx_config_irq(chip, block, config);
}
static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
{
struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
unsigned int pmirq = d->irq - chip->irq_base;
int master, irq_bit;
u8 block, config;
block = pmirq / 8;
master = block / 8;
irq_bit = pmirq % 8;
chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT)
| PM_IRQF_MASK_ALL;
if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
if (flow_type & IRQF_TRIGGER_RISING)
chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
if (flow_type & IRQF_TRIGGER_FALLING)
chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
} else {
chip->config[pmirq] |= PM_IRQF_LVL_SEL;
if (flow_type & IRQF_TRIGGER_HIGH)
chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
else
chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
}
config = chip->config[pmirq] | PM_IRQF_CLR;
return pm8xxx_config_irq(chip, block, config);
}
static int pm8xxx_irq_set_wake(struct irq_data *d, unsigned int on)
{
return 0;
}
static struct irq_chip pm8xxx_irq_chip = {
.name = "pm8xxx",
.irq_mask_ack = pm8xxx_irq_mask_ack,
.irq_unmask = pm8xxx_irq_unmask,
.irq_set_type = pm8xxx_irq_set_type,
.irq_set_wake = pm8xxx_irq_set_wake,
.flags = IRQCHIP_MASK_ON_SUSPEND,
};
/**
* pm8xxx_get_irq_stat - get the status of the irq line
* @chip: pointer to identify a pmic irq controller
* @irq: the irq number
*
* The pm8xxx gpio and mpp rely on the interrupt block to read
* the values on their pins. This function is to facilitate reading
* the status of a gpio or an mpp line. The caller has to convert the
* gpio number to irq number.
*
* RETURNS:
* an int indicating the value read on that line
*/
int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
{
int pmirq, rc;
u8 block, bits, bit;
unsigned long flags;
if (chip == NULL || irq < chip->irq_base ||
irq >= chip->irq_base + chip->num_irqs)
return -EINVAL;
pmirq = irq - chip->irq_base;
block = pmirq / 8;
bit = pmirq % 8;
spin_lock_irqsave(&chip->pm_irq_lock, flags);
rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
if (rc) {
pr_err("Failed Selecting block irq=%d pmirq=%d blk=%d rc=%d\n",
irq, pmirq, block, rc);
goto bail_out;
}
rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
if (rc) {
pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n",
irq, pmirq, block, rc);
goto bail_out;
}
rc = (bits & (1 << bit)) ? 1 : 0;
bail_out:
spin_unlock_irqrestore(&chip->pm_irq_lock, flags);
return rc;
}
EXPORT_SYMBOL_GPL(pm8xxx_get_irq_stat);
struct pm_irq_chip * __devinit pm8xxx_irq_init(struct device *dev,
const struct pm8xxx_irq_platform_data *pdata)
{
struct pm_irq_chip *chip;
int devirq, rc;
unsigned int pmirq;
if (!pdata) {
pr_err("No platform data\n");
return ERR_PTR(-EINVAL);
}
devirq = pdata->devirq;
if (devirq < 0) {
pr_err("missing devirq\n");
rc = devirq;
return ERR_PTR(-EINVAL);
}
chip = kzalloc(sizeof(struct pm_irq_chip)
+ sizeof(u8) * pdata->irq_cdata.nirqs, GFP_KERNEL);
if (!chip) {
pr_err("Cannot alloc pm_irq_chip struct\n");
return ERR_PTR(-EINVAL);
}
chip->dev = dev;
chip->devirq = devirq;
chip->irq_base = pdata->irq_base;
chip->num_irqs = pdata->irq_cdata.nirqs;
chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
spin_lock_init(&chip->pm_irq_lock);
for (pmirq = 0; pmirq < chip->num_irqs; pmirq++) {
irq_set_chip_and_handler(chip->irq_base + pmirq,
&pm8xxx_irq_chip,
handle_level_irq);
irq_set_chip_data(chip->irq_base + pmirq, chip);
#ifdef CONFIG_ARM
set_irq_flags(chip->irq_base + pmirq, IRQF_VALID);
#else
irq_set_noprobe(chip->irq_base + pmirq);
#endif
}
irq_set_irq_type(devirq, pdata->irq_trigger_flag);
irq_set_handler_data(devirq, chip);
irq_set_chained_handler(devirq, pm8xxx_irq_handler);
set_irq_wake(devirq, 1);
return chip;
}
int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip)
{
irq_set_chained_handler(chip->devirq, NULL);
kfree(chip);
return 0;
}
......@@ -61,12 +61,14 @@ static struct mfd_cell rdc321x_sb_cells[] = {
.name = "rdc321x-wdt",
.resources = rdc321x_wdt_resource,
.num_resources = ARRAY_SIZE(rdc321x_wdt_resource),
.mfd_data = &rdc321x_wdt_pdata,
.platform_data = &rdc321x_wdt_pdata,
.pdata_size = sizeof(rdc321x_wdt_pdata),
}, {
.name = "rdc321x-gpio",
.resources = rdc321x_gpio_resources,
.num_resources = ARRAY_SIZE(rdc321x_gpio_resources),
.mfd_data = &rdc321x_gpio_pdata,
.platform_data = &rdc321x_gpio_pdata,
.pdata_size = sizeof(rdc321x_gpio_pdata),
},
};
......
......@@ -170,7 +170,8 @@ static struct mfd_cell t7l66xb_cells[] = {
.name = "tmio-mmc",
.enable = t7l66xb_mmc_enable,
.disable = t7l66xb_mmc_disable,
.mfd_data = &t7166xb_mmc_data,
.platform_data = &t7166xb_mmc_data,
.pdata_size = sizeof(t7166xb_mmc_data),
.num_resources = ARRAY_SIZE(t7l66xb_mmc_resources),
.resources = t7l66xb_mmc_resources,
},
......@@ -382,7 +383,8 @@ static int t7l66xb_probe(struct platform_device *dev)
t7l66xb_attach_irq(dev);
t7l66xb_cells[T7L66XB_CELL_NAND].mfd_data = pdata->nand_data;
t7l66xb_cells[T7L66XB_CELL_NAND].platform_data = pdata->nand_data;
t7l66xb_cells[T7L66XB_CELL_NAND].pdata_size = sizeof(*pdata->nand_data);
ret = mfd_add_devices(&dev->dev, dev->id,
t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells),
......
......@@ -131,7 +131,8 @@ static struct mfd_cell tc6387xb_cells[] = {
.name = "tmio-mmc",
.enable = tc6387xb_mmc_enable,
.disable = tc6387xb_mmc_disable,
.mfd_data = &tc6387xb_mmc_data,
.platform_data = &tc6387xb_mmc_data,
.pdata_size = sizeof(tc6387xb_mmc_data),
.num_resources = ARRAY_SIZE(tc6387xb_mmc_resources),
.resources = tc6387xb_mmc_resources,
},
......
......@@ -393,7 +393,8 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = {
.name = "tmio-mmc",
.enable = tc6393xb_mmc_enable,
.resume = tc6393xb_mmc_resume,
.mfd_data = &tc6393xb_mmc_data,
.platform_data = &tc6393xb_mmc_data,
.pdata_size = sizeof(tc6393xb_mmc_data),
.num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
.resources = tc6393xb_mmc_resources,
},
......@@ -692,8 +693,11 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
goto err_setup;
}
tc6393xb_cells[TC6393XB_CELL_NAND].mfd_data = tcpd->nand_data;
tc6393xb_cells[TC6393XB_CELL_FB].mfd_data = tcpd->fb_data;
tc6393xb_cells[TC6393XB_CELL_NAND].platform_data = tcpd->nand_data;
tc6393xb_cells[TC6393XB_CELL_NAND].pdata_size =
sizeof(*tcpd->nand_data);
tc6393xb_cells[TC6393XB_CELL_FB].platform_data = tcpd->fb_data;
tc6393xb_cells[TC6393XB_CELL_FB].pdata_size = sizeof(*tcpd->fb_data);
ret = mfd_add_devices(&dev->dev, dev->id,
tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
......
......@@ -384,7 +384,8 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
.mfd_data = &timb_dma_platform_data,
.platform_data = &timb_dma_platform_data,
.pdata_size = sizeof(timb_dma_platform_data),
},
{
.name = "timb-uart",
......@@ -395,37 +396,43 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
.name = "xiic-i2c",
.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
.resources = timberdale_xiic_resources,
.mfd_data = &timberdale_xiic_platform_data,
.platform_data = &timberdale_xiic_platform_data,
.pdata_size = sizeof(timberdale_xiic_platform_data),
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
.mfd_data = &timberdale_gpio_platform_data,
.platform_data = &timberdale_gpio_platform_data,
.pdata_size = sizeof(timberdale_gpio_platform_data),
},
{
.name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
.mfd_data = &timberdale_video_platform_data,
.platform_data = &timberdale_video_platform_data,
.pdata_size = sizeof(timberdale_video_platform_data),
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
.mfd_data = &timberdale_radio_platform_data,
.platform_data = &timberdale_radio_platform_data,
.pdata_size = sizeof(timberdale_radio_platform_data),
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
.mfd_data = &timberdale_xspi_platform_data,
.platform_data = &timberdale_xspi_platform_data,
.pdata_size = sizeof(timberdale_xspi_platform_data),
},
{
.name = "ks8842",
.num_resources = ARRAY_SIZE(timberdale_eth_resources),
.resources = timberdale_eth_resources,
.mfd_data = &timberdale_ks8842_platform_data,
.platform_data = &timberdale_ks8842_platform_data,
.pdata_size = sizeof(timberdale_ks8842_platform_data),
},
};
......@@ -434,7 +441,8 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
.mfd_data = &timb_dma_platform_data,
.platform_data = &timb_dma_platform_data,
.pdata_size = sizeof(timb_dma_platform_data),
},
{
.name = "timb-uart",
......@@ -450,13 +458,15 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
.name = "xiic-i2c",
.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
.resources = timberdale_xiic_resources,
.mfd_data = &timberdale_xiic_platform_data,
.platform_data = &timberdale_xiic_platform_data,
.pdata_size = sizeof(timberdale_xiic_platform_data),
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
.mfd_data = &timberdale_gpio_platform_data,
.platform_data = &timberdale_gpio_platform_data,
.pdata_size = sizeof(timberdale_gpio_platform_data),
},
{
.name = "timb-mlogicore",
......@@ -467,25 +477,29 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
.name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
.mfd_data = &timberdale_video_platform_data,
.platform_data = &timberdale_video_platform_data,
.pdata_size = sizeof(timberdale_video_platform_data),
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
.mfd_data = &timberdale_radio_platform_data,
.platform_data = &timberdale_radio_platform_data,
.pdata_size = sizeof(timberdale_radio_platform_data),
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
.mfd_data = &timberdale_xspi_platform_data,
.platform_data = &timberdale_xspi_platform_data,
.pdata_size = sizeof(timberdale_xspi_platform_data),
},
{
.name = "ks8842",
.num_resources = ARRAY_SIZE(timberdale_eth_resources),
.resources = timberdale_eth_resources,
.mfd_data = &timberdale_ks8842_platform_data,
.platform_data = &timberdale_ks8842_platform_data,
.pdata_size = sizeof(timberdale_ks8842_platform_data),
},
};
......@@ -494,7 +508,8 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
.mfd_data = &timb_dma_platform_data,
.platform_data = &timb_dma_platform_data,
.pdata_size = sizeof(timb_dma_platform_data),
},
{
.name = "timb-uart",
......@@ -505,31 +520,36 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
.name = "xiic-i2c",
.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
.resources = timberdale_xiic_resources,
.mfd_data = &timberdale_xiic_platform_data,
.platform_data = &timberdale_xiic_platform_data,
.pdata_size = sizeof(timberdale_xiic_platform_data),
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
.mfd_data = &timberdale_gpio_platform_data,
.platform_data = &timberdale_gpio_platform_data,
.pdata_size = sizeof(timberdale_gpio_platform_data),
},
{
.name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
.mfd_data = &timberdale_video_platform_data,
.platform_data = &timberdale_video_platform_data,
.pdata_size = sizeof(timberdale_video_platform_data),
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
.mfd_data = &timberdale_radio_platform_data,
.platform_data = &timberdale_radio_platform_data,
.pdata_size = sizeof(timberdale_radio_platform_data),
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
.mfd_data = &timberdale_xspi_platform_data,
.platform_data = &timberdale_xspi_platform_data,
.pdata_size = sizeof(timberdale_xspi_platform_data),
},
};
......@@ -538,7 +558,8 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
.mfd_data = &timb_dma_platform_data,
.platform_data = &timb_dma_platform_data,
.pdata_size = sizeof(timb_dma_platform_data),
},
{
.name = "timb-uart",
......@@ -549,37 +570,43 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
.name = "ocores-i2c",
.num_resources = ARRAY_SIZE(timberdale_ocores_resources),
.resources = timberdale_ocores_resources,
.mfd_data = &timberdale_ocores_platform_data,
.platform_data = &timberdale_ocores_platform_data,
.pdata_size = sizeof(timberdale_ocores_platform_data),
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
.mfd_data = &timberdale_gpio_platform_data,
.platform_data = &timberdale_gpio_platform_data,
.pdata_size = sizeof(timberdale_gpio_platform_data),
},
{
.name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
.mfd_data = &timberdale_video_platform_data,
.platform_data = &timberdale_video_platform_data,
.pdata_size = sizeof(timberdale_video_platform_data),
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
.mfd_data = &timberdale_radio_platform_data,
.platform_data = &timberdale_radio_platform_data,
.pdata_size = sizeof(timberdale_radio_platform_data),
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
.mfd_data = &timberdale_xspi_platform_data,
.platform_data = &timberdale_xspi_platform_data,
.pdata_size = sizeof(timberdale_xspi_platform_data),
},
{
.name = "ks8842",
.num_resources = ARRAY_SIZE(timberdale_eth_resources),
.resources = timberdale_eth_resources,
.mfd_data = &timberdale_ks8842_platform_data,
.platform_data = &timberdale_ks8842_platform_data,
.pdata_size = sizeof(timberdale_ks8842_platform_data),
},
};
......
......@@ -183,7 +183,8 @@ static int __devinit tps6105x_probe(struct i2c_client *client,
/* 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;
tps6105x_cells[i].platform_data = tps6105x;
tps6105x_cells[i].pdata_size = sizeof(*tps6105x);
}
ret = mfd_add_devices(&client->dev, 0, tps6105x_cells,
......
......@@ -270,8 +270,8 @@ static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset,
{
struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio);
__tps6586x_write(tps6586x->client, TPS6586X_GPIOSET2,
value << offset);
tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET2,
value << offset, 1 << offset);
}
static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset,
......
......@@ -198,6 +198,7 @@
#define TWL6030_BASEADD_GASGAUGE 0x00C0
#define TWL6030_BASEADD_PIH 0x00D0
#define TWL6030_BASEADD_CHARGER 0x00E0
#define TWL6025_BASEADD_CHARGER 0x00DA
/* subchip/slave 2 0x4A - DFT */
#define TWL6030_BASEADD_DIEID 0x00C0
......@@ -229,6 +230,9 @@
/* is driver active, bound to a chip? */
static bool inuse;
/* TWL IDCODE Register value */
static u32 twl_idcode;
static unsigned int twl_id;
unsigned int twl_rev(void)
{
......@@ -328,6 +332,7 @@ static struct twl_mapping twl6030_map[] = {
{ SUB_CHIP_ID0, TWL6030_BASEADD_RTC },
{ SUB_CHIP_ID0, TWL6030_BASEADD_MEM },
{ SUB_CHIP_ID1, TWL6025_BASEADD_CHARGER },
};
/*----------------------------------------------------------------------*/
......@@ -487,6 +492,58 @@ EXPORT_SYMBOL(twl_i2c_read_u8);
/*----------------------------------------------------------------------*/
/**
* twl_read_idcode_register - API to read the IDCODE register.
*
* Unlocks the IDCODE register and read the 32 bit value.
*/
static int twl_read_idcode_register(void)
{
int err;
err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, TWL_EEPROM_R_UNLOCK,
REG_UNLOCK_TEST_REG);
if (err) {
pr_err("TWL4030 Unable to unlock IDCODE registers -%d\n", err);
goto fail;
}
err = twl_i2c_read(TWL4030_MODULE_INTBR, (u8 *)(&twl_idcode),
REG_IDCODE_7_0, 4);
if (err) {
pr_err("TWL4030: unable to read IDCODE -%d\n", err);
goto fail;
}
err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, 0x0, REG_UNLOCK_TEST_REG);
if (err)
pr_err("TWL4030 Unable to relock IDCODE registers -%d\n", err);
fail:
return err;
}
/**
* twl_get_type - API to get TWL Si type.
*
* Api to get the TWL Si type from IDCODE value.
*/
int twl_get_type(void)
{
return TWL_SIL_TYPE(twl_idcode);
}
EXPORT_SYMBOL_GPL(twl_get_type);
/**
* twl_get_version - API to get TWL Si version.
*
* Api to get the TWL Si version from IDCODE value.
*/
int twl_get_version(void)
{
return TWL_SIL_REV(twl_idcode);
}
EXPORT_SYMBOL_GPL(twl_get_version);
static struct device *
add_numbered_child(unsigned chip, const char *name, int num,
void *pdata, unsigned pdata_len,
......@@ -549,7 +606,7 @@ static inline struct device *add_child(unsigned chip, const char *name,
static struct device *
add_regulator_linked(int num, struct regulator_init_data *pdata,
struct regulator_consumer_supply *consumers,
unsigned num_consumers)
unsigned num_consumers, unsigned long features)
{
unsigned sub_chip_id;
/* regulator framework demands init_data ... */
......@@ -561,6 +618,8 @@ add_regulator_linked(int num, struct regulator_init_data *pdata,
pdata->num_consumer_supplies = num_consumers;
}
pdata->driver_data = (void *)features;
/* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */
sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid;
return add_numbered_child(sub_chip_id, "twl_reg", num,
......@@ -568,9 +627,10 @@ add_regulator_linked(int num, struct regulator_init_data *pdata,
}
static struct device *
add_regulator(int num, struct regulator_init_data *pdata)
add_regulator(int num, struct regulator_init_data *pdata,
unsigned long features)
{
return add_regulator_linked(num, pdata, NULL, 0);
return add_regulator_linked(num, pdata, NULL, 0, features);
}
/*
......@@ -650,17 +710,20 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
};
child = add_regulator_linked(TWL4030_REG_VUSB1V5,
&usb_fixed, &usb1v5, 1);
&usb_fixed, &usb1v5, 1,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator_linked(TWL4030_REG_VUSB1V8,
&usb_fixed, &usb1v8, 1);
&usb_fixed, &usb1v8, 1,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator_linked(TWL4030_REG_VUSB3V1,
&usb_fixed, &usb3v1, 1);
&usb_fixed, &usb3v1, 1,
features);
if (IS_ERR(child))
return PTR_ERR(child);
......@@ -685,9 +748,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
}
if (twl_has_usb() && pdata->usb && twl_class_is_6030()) {
static struct regulator_consumer_supply usb3v3 = {
.supply = "vusb",
};
static struct regulator_consumer_supply usb3v3;
int regulator;
if (twl_has_regulator()) {
/* this is a template that gets copied */
......@@ -700,12 +762,22 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
| REGULATOR_CHANGE_STATUS,
};
child = add_regulator_linked(TWL6030_REG_VUSB,
&usb_fixed, &usb3v3, 1);
if (features & TWL6025_SUBCLASS) {
usb3v3.supply = "ldousb";
regulator = TWL6025_REG_LDOUSB;
} else {
usb3v3.supply = "vusb";
regulator = TWL6030_REG_VUSB;
}
child = add_regulator_linked(regulator, &usb_fixed,
&usb3v3, 1,
features);
if (IS_ERR(child))
return PTR_ERR(child);
}
pdata->usb->features = features;
child = add_child(0, "twl6030_usb",
pdata->usb, sizeof(*pdata->usb),
true,
......@@ -718,7 +790,16 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
/* we need to connect regulators to this transceiver */
if (twl_has_regulator() && child)
usb3v3.dev = child;
} else if (twl_has_regulator() && twl_class_is_6030()) {
if (features & TWL6025_SUBCLASS)
child = add_regulator(TWL6025_REG_LDOUSB,
pdata->ldousb, features);
else
child = add_regulator(TWL6030_REG_VUSB,
pdata->vusb, features);
if (IS_ERR(child))
return PTR_ERR(child);
}
if (twl_has_watchdog() && twl_class_is_4030()) {
......@@ -755,46 +836,55 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
/* twl4030 regulators */
if (twl_has_regulator() && twl_class_is_4030()) {
child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1);
child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VIO, pdata->vio);
child = add_regulator(TWL4030_REG_VIO, pdata->vio,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1);
child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2);
child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1);
child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VDAC, pdata->vdac);
child = add_regulator(TWL4030_REG_VDAC, pdata->vdac,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator((features & TWL4030_VAUX2)
? TWL4030_REG_VAUX2_4030
: TWL4030_REG_VAUX2,
pdata->vaux2);
pdata->vaux2, features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1);
child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2);
child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig);
child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig,
features);
if (IS_ERR(child))
return PTR_ERR(child);
}
......@@ -802,72 +892,152 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
/* maybe add LDOs that are omitted on cost-reduced parts */
if (twl_has_regulator() && !(features & TPS_SUBSET)
&& twl_class_is_4030()) {
child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2);
child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2);
child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VSIM, pdata->vsim);
child = add_regulator(TWL4030_REG_VSIM, pdata->vsim,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1);
child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3);
child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4);
child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4,
features);
if (IS_ERR(child))
return PTR_ERR(child);
}
/* twl6030 regulators */
if (twl_has_regulator() && twl_class_is_6030() &&
!(features & TWL6025_SUBCLASS)) {
child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VPP, pdata->vpp,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VDAC, pdata->vdac,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg,
features);
if (IS_ERR(child))
return PTR_ERR(child);
}
/* 6030 and 6025 share this regulator */
if (twl_has_regulator() && twl_class_is_6030()) {
child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc);
child = add_regulator(TWL6030_REG_VANA, pdata->vana,
features);
if (IS_ERR(child))
return PTR_ERR(child);
}
child = add_regulator(TWL6030_REG_VPP, pdata->vpp);
/* twl6025 regulators */
if (twl_has_regulator() && twl_class_is_6030() &&
(features & TWL6025_SUBCLASS)) {
child = add_regulator(TWL6025_REG_LDO5, pdata->ldo5,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim);
child = add_regulator(TWL6025_REG_LDO1, pdata->ldo1,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VANA, pdata->vana);
child = add_regulator(TWL6025_REG_LDO7, pdata->ldo7,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio);
child = add_regulator(TWL6025_REG_LDO6, pdata->ldo6,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VDAC, pdata->vdac);
child = add_regulator(TWL6025_REG_LDOLN, pdata->ldoln,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1);
child = add_regulator(TWL6025_REG_LDO2, pdata->ldo2,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2);
child = add_regulator(TWL6025_REG_LDO4, pdata->ldo4,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3);
child = add_regulator(TWL6025_REG_LDO3, pdata->ldo3,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg);
child = add_regulator(TWL6025_REG_SMPS3, pdata->smps3,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6025_REG_SMPS4, pdata->smps4,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6025_REG_VIO, pdata->vio6025,
features);
if (IS_ERR(child))
return PTR_ERR(child);
}
if (twl_has_bci() && pdata->bci &&
......@@ -1014,6 +1184,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
unsigned i;
struct twl4030_platform_data *pdata = client->dev.platform_data;
u8 temp;
int ret = 0;
if (!pdata) {
dev_dbg(&client->dev, "no platform data?\n");
......@@ -1060,6 +1231,12 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
/* setup clock framework */
clocks_init(&client->dev, pdata->clock);
/* read TWL IDCODE Register */
if (twl_id == TWL4030_CLASS_ID) {
ret = twl_read_idcode_register();
WARN(ret < 0, "Error: reading twl_idcode register value\n");
}
/* load power event scripts */
if (twl_has_power() && pdata->power)
twl4030_power_init(pdata->power);
......@@ -1108,6 +1285,7 @@ static const struct i2c_device_id twl_ids[] = {
{ "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */
{ "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */
{ "twl6030", TWL6030_CLASS }, /* "Phoenix power chip" */
{ "twl6025", TWL6030_CLASS | TWL6025_SUBCLASS }, /* "Phoenix lite" */
{ /* end of list */ },
};
MODULE_DEVICE_TABLE(i2c, twl_ids);
......
/*
* MFD driver for twl4030 codec submodule
*
* Author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
* Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
*
* Copyright: (C) 2009 Nokia Corporation
*
......@@ -208,13 +208,15 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
if (pdata->audio) {
cell = &codec->cells[childs];
cell->name = "twl4030-codec";
cell->mfd_data = pdata->audio;
cell->platform_data = pdata->audio;
cell->pdata_size = sizeof(*pdata->audio);
childs++;
}
if (pdata->vibra) {
cell = &codec->cells[childs];
cell->name = "twl4030-vibra";
cell->mfd_data = pdata->vibra;
cell->platform_data = pdata->vibra;
cell->pdata_size = sizeof(*pdata->vibra);
childs++;
}
......@@ -270,6 +272,6 @@ static void __devexit twl4030_codec_exit(void)
}
module_exit(twl4030_codec_exit);
MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@nokia.com>");
MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
MODULE_LICENSE("GPL");
......@@ -120,7 +120,7 @@ static u8 res_config_addrs[] = {
[RES_HFCLKOUT] = 0x8b,
[RES_32KCLKOUT] = 0x8e,
[RES_RESET] = 0x91,
[RES_Main_Ref] = 0x94,
[RES_MAIN_REF] = 0x94,
};
static int __init twl4030_write_script_byte(u8 address, u8 byte)
......@@ -448,7 +448,7 @@ static int __init load_twl4030_script(struct twl4030_script *tscript,
goto out;
}
if (tscript->flags & TWL4030_SLEEP_SCRIPT) {
if (order)
if (!order)
pr_warning("TWL4030: Bad order of scripts (sleep "\
"script before wakeup) Leads to boot"\
"failure on some boards\n");
......@@ -485,9 +485,9 @@ int twl4030_remove_script(u8 flags)
return err;
}
if (flags & TWL4030_WAKEUP12_SCRIPT) {
if (err)
err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
R_SEQ_ADD_S2A12);
if (err)
return err;
}
if (flags & TWL4030_WAKEUP3_SCRIPT) {
......
......@@ -76,8 +76,8 @@ static int twl6030_interrupt_mapping[24] = {
USBOTG_INTR_OFFSET, /* Bit 18 ID */
USB_PRES_INTR_OFFSET, /* Bit 19 VBUS */
CHARGER_INTR_OFFSET, /* Bit 20 CHRG_CTRL */
CHARGER_INTR_OFFSET, /* Bit 21 EXT_CHRG */
CHARGER_INTR_OFFSET, /* Bit 22 INT_CHRG */
CHARGERFAULT_INTR_OFFSET, /* Bit 21 EXT_CHRG */
CHARGERFAULT_INTR_OFFSET, /* Bit 22 INT_CHRG */
RSV_INTR_OFFSET, /* Bit 23 Reserved */
};
/*----------------------------------------------------------------------*/
......
......@@ -153,7 +153,6 @@ static int wl1273_fm_set_audio(struct wl1273_core *core, unsigned int new_mode)
*/
static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume)
{
u16 val;
int r;
if (volume > WL1273_MAX_VOLUME)
......@@ -217,7 +216,8 @@ static int __devinit wl1273_core_probe(struct i2c_client *client,
cell = &core->cells[children];
cell->name = "wl1273_fm_radio";
cell->mfd_data = &core;
cell->platform_data = &core;
cell->pdata_size = sizeof(core);
children++;
core->read = wl1273_fm_read_reg;
......@@ -231,7 +231,8 @@ static int __devinit wl1273_core_probe(struct i2c_client *client,
dev_dbg(&client->dev, "%s: Have codec.\n", __func__);
cell->name = "wl1273-codec";
cell->mfd_data = &core;
cell->platform_data = &core;
cell->pdata_size = sizeof(core);
children++;
}
......
......@@ -1442,7 +1442,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
int rev;
enum wm831x_parent parent;
int ret;
int ret, i;
mutex_init(&wm831x->io_lock);
mutex_init(&wm831x->key_lock);
......@@ -1581,6 +1581,17 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
}
}
if (pdata) {
for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
if (!pdata->gpio_defaults[i])
continue;
wm831x_reg_write(wm831x,
WM831X_GPIO1_CONTROL + i,
pdata->gpio_defaults[i] & 0xffff);
}
}
ret = wm831x_irq_init(wm831x, irq);
if (ret != 0)
goto err;
......
......@@ -515,12 +515,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
0xffff);
}
if (!irq) {
dev_warn(wm831x->dev,
"No interrupt specified - functionality limited\n");
return 0;
}
if (!pdata || !pdata->irq_base) {
dev_err(wm831x->dev,
"No interrupt base specified, no interrupts\n");
......@@ -567,15 +561,22 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
#endif
}
ret = request_threaded_irq(irq, NULL, wm831x_irq_thread,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"wm831x", wm831x);
if (ret != 0) {
dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n",
irq, ret);
return ret;
if (irq) {
ret = request_threaded_irq(irq, NULL, wm831x_irq_thread,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"wm831x", wm831x);
if (ret != 0) {
dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n",
irq, ret);
return ret;
}
} else {
dev_warn(wm831x->dev,
"No interrupt specified - functionality limited\n");
}
/* Enable top level interrupts, we mask at secondary level */
wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0);
......
......@@ -245,7 +245,8 @@ static int wm8400_register_codec(struct wm8400 *wm8400)
{
struct mfd_cell cell = {
.name = "wm8400-codec",
.mfd_data = wm8400,
.platform_data = wm8400,
.pdata_size = sizeof(*wm8400),
};
return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0);
......
......@@ -69,7 +69,7 @@ static int __devinit tmio_mmc_probe(struct platform_device *pdev)
if (pdev->num_resources != 2)
goto out;
pdata = mfd_get_data(pdev);
pdata = pdev->dev.platform_data;
if (!pdata || !pdata->hclk)
goto out;
......
......@@ -372,7 +372,7 @@ static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio)
static int tmio_probe(struct platform_device *dev)
{
struct tmio_nand_data *data = mfd_get_data(dev);
struct tmio_nand_data *data = dev->dev.platform_data;
struct resource *fcr = platform_get_resource(dev,
IORESOURCE_MEM, 0);
struct resource *ccr = platform_get_resource(dev,
......
......@@ -15,7 +15,6 @@
#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>
......@@ -1644,7 +1643,7 @@ static int __devinit ican3_probe(struct platform_device *pdev)
struct device *dev;
int ret;
pdata = mfd_get_data(pdev);
pdata = pdev->dev.platform_data;
if (!pdata)
return -ENXIO;
......
......@@ -26,7 +26,6 @@
#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>
......@@ -1146,7 +1145,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 = mfd_get_data(pdev);
struct ks8842_platform_data *pdata = pdev->dev.platform_data;
u16 id;
unsigned i;
......
......@@ -425,16 +425,11 @@ static __devexit int max8925_deinit_charger(struct max8925_power_info *info)
static __devinit int max8925_power_probe(struct platform_device *pdev)
{
struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct max8925_platform_data *max8925_pdata;
struct max8925_power_pdata *pdata = NULL;
struct max8925_power_info *info;
int ret;
if (pdev->dev.parent->platform_data) {
max8925_pdata = pdev->dev.parent->platform_data;
pdata = max8925_pdata->power;
}
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "platform data isn't assigned to "
"power supply\n");
......@@ -447,6 +442,7 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
info->chip = chip;
info->gpm = chip->i2c;
info->adc = chip->adc;
platform_set_drvdata(pdev, info);
info->ac.name = "max8925-ac";
info->ac.type = POWER_SUPPLY_TYPE_MAINS;
......@@ -482,8 +478,6 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
info->topoff_threshold = pdata->topoff_threshold;
info->fast_charge = pdata->fast_charge;
info->set_charger = pdata->set_charger;
dev_set_drvdata(&pdev->dev, info);
platform_set_drvdata(pdev, info);
max8925_init_charger(chip, info);
return 0;
......
......@@ -15,7 +15,6 @@
#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 {
......@@ -399,36 +398,33 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
{
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;
struct regulator_init_data *pdata = pdev->dev.platform_data;
struct resource *res;
int i;
cell = pdev->dev.platform_data;
if (cell == NULL)
return -ENODEV;
pdata = cell->mfd_data;
if (pdata == NULL)
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (res == NULL) {
dev_err(&pdev->dev, "No I/O resource!\n");
return -EINVAL;
}
for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
info = &pm8607_regulator_info[i];
if (!strcmp(info->desc.name, pdata->constraints.name))
if (info->desc.id == res->start)
break;
}
if (i > ARRAY_SIZE(pm8607_regulator_info)) {
dev_err(&pdev->dev, "Failed to find regulator %s\n",
pdata->constraints.name);
if ((i < 0) || (i > PM8607_ID_RG_MAX)) {
dev_err(&pdev->dev, "Failed to find regulator %llu\n",
(unsigned long long)res->start);
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;
if ((i == PM8607_ID_BUCK3) && info->chip->buck3_double)
info->slope_double = 1;
/* replace driver_data with info */
info->regulator = regulator_register(&info->desc, &pdev->dev,
pdata, info);
if (IS_ERR(info->regulator)) {
......
......@@ -17,7 +17,6 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/core.h>
/* LDO registers and some handy masking definitions for AB3100 */
#define AB3100_LDO_A 0x40
......@@ -582,7 +581,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
{
struct ab3100_platform_data *plfdata = mfd_get_data(pdev);
struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
int err = 0;
u8 data;
int i;
......
......@@ -13,7 +13,6 @@
#include <linux/err.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/db8500-prcmu.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
......@@ -471,7 +470,8 @@ static struct db8500_regulator_info
static int __devinit db8500_regulator_probe(struct platform_device *pdev)
{
struct regulator_init_data *db8500_init_data = mfd_get_data(pdev);
struct regulator_init_data *db8500_init_data =
dev_get_platdata(&pdev->dev);
int i, err;
/* register all regulators */
......
......@@ -23,6 +23,10 @@
#define SD1_DVM_SHIFT 5 /* SDCTL1 bit5 */
#define SD1_DVM_EN 6 /* SDV1 bit 6 */
/* bit definitions in SD & LDO control registers */
#define OUT_ENABLE 0x1f /* Power U/D sequence as I2C */
#define OUT_DISABLE 0x1e /* Power U/D sequence as I2C */
struct max8925_regulator_info {
struct regulator_desc desc;
struct regulator_dev *regulator;
......@@ -93,8 +97,8 @@ static int max8925_enable(struct regulator_dev *rdev)
struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
return max8925_set_bits(info->i2c, info->enable_reg,
1 << info->enable_bit,
1 << info->enable_bit);
OUT_ENABLE << info->enable_bit,
OUT_ENABLE << info->enable_bit);
}
static int max8925_disable(struct regulator_dev *rdev)
......@@ -102,7 +106,8 @@ static int max8925_disable(struct regulator_dev *rdev)
struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
return max8925_set_bits(info->i2c, info->enable_reg,
1 << info->enable_bit, 0);
OUT_ENABLE << info->enable_bit,
OUT_DISABLE << info->enable_bit);
}
static int max8925_is_enabled(struct regulator_dev *rdev)
......
......@@ -15,7 +15,6 @@
#include <linux/regulator/driver.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/err.h>
......@@ -337,7 +336,8 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv;
struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
struct mc13783_regulator_platform_data *pdata = mfd_get_data(pdev);
struct mc13783_regulator_platform_data *pdata =
dev_get_platdata(&pdev->dev);
struct mc13783_regulator_init_data *init_data;
int i, ret;
......@@ -381,7 +381,8 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
struct mc13783_regulator_platform_data *pdata = mfd_get_data(pdev);
struct mc13783_regulator_platform_data *pdata =
dev_get_platdata(&pdev->dev);
int i;
platform_set_drvdata(pdev, NULL);
......
......@@ -15,7 +15,6 @@
#include <linux/regulator/driver.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/err.h>
......@@ -521,7 +520,8 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv;
struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent);
struct mc13xxx_regulator_platform_data *pdata = mfd_get_data(pdev);
struct mc13xxx_regulator_platform_data *pdata =
dev_get_platdata(&pdev->dev);
struct mc13xxx_regulator_init_data *init_data;
int i, ret;
u32 val;
......@@ -595,7 +595,8 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
static int __devexit mc13892_regulator_remove(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
struct mc13xxx_regulator_platform_data *pdata = mfd_get_data(pdev);
struct mc13xxx_regulator_platform_data *pdata =
dev_get_platdata(&pdev->dev);
int i;
platform_set_drvdata(pdev, NULL);
......
......@@ -137,7 +137,7 @@ static struct regulator_desc tps6105x_regulator_desc = {
*/
static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
{
struct tps6105x *tps6105x = mfd_get_data(pdev);
struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
struct tps6105x_platform_data *pdata = tps6105x->pdata;
int ret;
......@@ -164,7 +164,7 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
static int __devexit tps6105x_regulator_remove(struct platform_device *pdev)
{
struct tps6105x *tps6105x = platform_get_drvdata(pdev);
struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
regulator_unregister(tps6105x->regulator);
return 0;
}
......
......@@ -125,6 +125,16 @@ comment "I2C RTC drivers"
if I2C
config RTC_DRV_88PM860X
tristate "Marvell 88PM860x"
depends on RTC_CLASS && I2C && MFD_88PM860X
help
If you say yes here you get support for RTC function in Marvell
88PM860x chips.
This driver can also be built as a module. If so, the module
will be called rtc-88pm860x.
config RTC_DRV_DS1307
tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025"
help
......
......@@ -15,6 +15,7 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
# Keep the list ordered.
obj-$(CONFIG_RTC_DRV_88PM860X) += rtc-88pm860x.o
obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o
obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o
obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
......
/*
* Real Time Clock driver for Marvell 88PM860x PMIC
*
* Copyright (c) 2010 Marvell International Ltd.
* Author: Haojian Zhuang <haojian.zhuang@marvell.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.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/rtc.h>
#include <linux/delay.h>
#include <linux/mfd/core.h>
#include <linux/mfd/88pm860x.h>
#define VRTC_CALIBRATION
struct pm860x_rtc_info {
struct pm860x_chip *chip;
struct i2c_client *i2c;
struct rtc_device *rtc_dev;
struct device *dev;
struct delayed_work calib_work;
int irq;
int vrtc;
int (*sync)(unsigned int ticks);
};
#define REG_VRTC_MEAS1 0x7D
#define REG0_ADDR 0xB0
#define REG1_ADDR 0xB2
#define REG2_ADDR 0xB4
#define REG3_ADDR 0xB6
#define REG0_DATA 0xB1
#define REG1_DATA 0xB3
#define REG2_DATA 0xB5
#define REG3_DATA 0xB7
/* bit definitions of Measurement Enable Register 2 (0x51) */
#define MEAS2_VRTC (1 << 0)
/* bit definitions of RTC Register 1 (0xA0) */
#define ALARM_EN (1 << 3)
#define ALARM_WAKEUP (1 << 4)
#define ALARM (1 << 5)
#define RTC1_USE_XO (1 << 7)
#define VRTC_CALIB_INTERVAL (HZ * 60 * 10) /* 10 minutes */
static irqreturn_t rtc_update_handler(int irq, void *data)
{
struct pm860x_rtc_info *info = (struct pm860x_rtc_info *)data;
int mask;
mask = ALARM | ALARM_WAKEUP;
pm860x_set_bits(info->i2c, PM8607_RTC1, mask | ALARM_EN, mask);
rtc_update_irq(info->rtc_dev, 1, RTC_AF);
return IRQ_HANDLED;
}
static int pm860x_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct pm860x_rtc_info *info = dev_get_drvdata(dev);
if (enabled)
pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, ALARM);
else
pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, 0);
return 0;
}
/*
* Calculate the next alarm time given the requested alarm time mask
* and the current time.
*/
static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
struct rtc_time *alrm)
{
unsigned long next_time;
unsigned long now_time;
next->tm_year = now->tm_year;
next->tm_mon = now->tm_mon;
next->tm_mday = now->tm_mday;
next->tm_hour = alrm->tm_hour;
next->tm_min = alrm->tm_min;
next->tm_sec = alrm->tm_sec;
rtc_tm_to_time(now, &now_time);
rtc_tm_to_time(next, &next_time);
if (next_time < now_time) {
/* Advance one day */
next_time += 60 * 60 * 24;
rtc_time_to_tm(next_time, next);
}
}
static int pm860x_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct pm860x_rtc_info *info = dev_get_drvdata(dev);
unsigned char buf[8];
unsigned long ticks, base, data;
pm860x_page_bulk_read(info->i2c, REG0_ADDR, 8, buf);
dev_dbg(info->dev, "%x-%x-%x-%x-%x-%x-%x-%x\n", buf[0], buf[1],
buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
base = (buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7];
/* load 32-bit read-only counter */
pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf);
data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
ticks = base + data;
dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
base, data, ticks);
rtc_time_to_tm(ticks, tm);
return 0;
}
static int pm860x_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct pm860x_rtc_info *info = dev_get_drvdata(dev);
unsigned char buf[4];
unsigned long ticks, base, data;
if ((tm->tm_year < 70) || (tm->tm_year > 138)) {
dev_dbg(info->dev, "Set time %d out of range. "
"Please set time between 1970 to 2038.\n",
1900 + tm->tm_year);
return -EINVAL;
}
rtc_tm_to_time(tm, &ticks);
/* load 32-bit read-only counter */
pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf);
data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
base = ticks - data;
dev_dbg(info->dev, "set base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
base, data, ticks);
pm860x_page_reg_write(info->i2c, REG0_DATA, (base >> 24) & 0xFF);
pm860x_page_reg_write(info->i2c, REG1_DATA, (base >> 16) & 0xFF);
pm860x_page_reg_write(info->i2c, REG2_DATA, (base >> 8) & 0xFF);
pm860x_page_reg_write(info->i2c, REG3_DATA, base & 0xFF);
if (info->sync)
info->sync(ticks);
return 0;
}
static int pm860x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct pm860x_rtc_info *info = dev_get_drvdata(dev);
unsigned char buf[8];
unsigned long ticks, base, data;
int ret;
pm860x_page_bulk_read(info->i2c, REG0_ADDR, 8, buf);
dev_dbg(info->dev, "%x-%x-%x-%x-%x-%x-%x-%x\n", buf[0], buf[1],
buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
base = (buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7];
pm860x_bulk_read(info->i2c, PM8607_RTC_EXPIRE1, 4, buf);
data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
ticks = base + data;
dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
base, data, ticks);
rtc_time_to_tm(ticks, &alrm->time);
ret = pm860x_reg_read(info->i2c, PM8607_RTC1);
alrm->enabled = (ret & ALARM_EN) ? 1 : 0;
alrm->pending = (ret & (ALARM | ALARM_WAKEUP)) ? 1 : 0;
return 0;
}
static int pm860x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct pm860x_rtc_info *info = dev_get_drvdata(dev);
struct rtc_time now_tm, alarm_tm;
unsigned long ticks, base, data;
unsigned char buf[8];
int mask;
pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM_EN, 0);
pm860x_page_bulk_read(info->i2c, REG0_ADDR, 8, buf);
dev_dbg(info->dev, "%x-%x-%x-%x-%x-%x-%x-%x\n", buf[0], buf[1],
buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
base = (buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7];
/* load 32-bit read-only counter */
pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf);
data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
ticks = base + data;
dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
base, data, ticks);
rtc_time_to_tm(ticks, &now_tm);
rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time);
/* get new ticks for alarm in 24 hours */
rtc_tm_to_time(&alarm_tm, &ticks);
data = ticks - base;
buf[0] = data & 0xff;
buf[1] = (data >> 8) & 0xff;
buf[2] = (data >> 16) & 0xff;
buf[3] = (data >> 24) & 0xff;
pm860x_bulk_write(info->i2c, PM8607_RTC_EXPIRE1, 4, buf);
if (alrm->enabled) {
mask = ALARM | ALARM_WAKEUP | ALARM_EN;
pm860x_set_bits(info->i2c, PM8607_RTC1, mask, mask);
} else {
mask = ALARM | ALARM_WAKEUP | ALARM_EN;
pm860x_set_bits(info->i2c, PM8607_RTC1, mask,
ALARM | ALARM_WAKEUP);
}
return 0;
}
static const struct rtc_class_ops pm860x_rtc_ops = {
.read_time = pm860x_rtc_read_time,
.set_time = pm860x_rtc_set_time,
.read_alarm = pm860x_rtc_read_alarm,
.set_alarm = pm860x_rtc_set_alarm,
.alarm_irq_enable = pm860x_rtc_alarm_irq_enable,
};
#ifdef VRTC_CALIBRATION
static void calibrate_vrtc_work(struct work_struct *work)
{
struct pm860x_rtc_info *info = container_of(work,
struct pm860x_rtc_info, calib_work.work);
unsigned char buf[2];
unsigned int sum, data, mean, vrtc_set;
int i;
for (i = 0, sum = 0; i < 16; i++) {
msleep(100);
pm860x_bulk_read(info->i2c, REG_VRTC_MEAS1, 2, buf);
data = (buf[0] << 4) | buf[1];
data = (data * 5400) >> 12; /* convert to mv */
sum += data;
}
mean = sum >> 4;
vrtc_set = 2700 + (info->vrtc & 0x3) * 200;
dev_dbg(info->dev, "mean:%d, vrtc_set:%d\n", mean, vrtc_set);
sum = pm860x_reg_read(info->i2c, PM8607_RTC_MISC1);
data = sum & 0x3;
if ((mean + 200) < vrtc_set) {
/* try higher voltage */
if (++data == 4)
goto out;
data = (sum & 0xf8) | (data & 0x3);
pm860x_reg_write(info->i2c, PM8607_RTC_MISC1, data);
} else if ((mean - 200) > vrtc_set) {
/* try lower voltage */
if (data-- == 0)
goto out;
data = (sum & 0xf8) | (data & 0x3);
pm860x_reg_write(info->i2c, PM8607_RTC_MISC1, data);
} else
goto out;
dev_dbg(info->dev, "set 0x%x to RTC_MISC1\n", data);
/* trigger next calibration since VRTC is updated */
schedule_delayed_work(&info->calib_work, VRTC_CALIB_INTERVAL);
return;
out:
/* disable measurement */
pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, 0);
dev_dbg(info->dev, "finish VRTC calibration\n");
return;
}
#endif
static int __devinit pm860x_rtc_probe(struct platform_device *pdev)
{
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm860x_rtc_pdata *pdata = NULL;
struct pm860x_rtc_info *info;
struct rtc_time tm;
unsigned long ticks = 0;
int ret;
pdata = pdev->dev.platform_data;
if (pdata == NULL)
dev_warn(&pdev->dev, "No platform data!\n");
info = kzalloc(sizeof(struct pm860x_rtc_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
info->irq = platform_get_irq(pdev, 0);
if (info->irq < 0) {
dev_err(&pdev->dev, "No IRQ resource!\n");
ret = -EINVAL;
goto out;
}
info->chip = chip;
info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
info->dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, info);
ret = request_threaded_irq(info->irq, NULL, rtc_update_handler,
IRQF_ONESHOT, "rtc", info);
if (ret < 0) {
dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
info->irq, ret);
goto out;
}
/* set addresses of 32-bit base value for RTC time */
pm860x_page_reg_write(info->i2c, REG0_ADDR, REG0_DATA);
pm860x_page_reg_write(info->i2c, REG1_ADDR, REG1_DATA);
pm860x_page_reg_write(info->i2c, REG2_ADDR, REG2_DATA);
pm860x_page_reg_write(info->i2c, REG3_ADDR, REG3_DATA);
ret = pm860x_rtc_read_time(&pdev->dev, &tm);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to read initial time.\n");
goto out_rtc;
}
if ((tm.tm_year < 70) || (tm.tm_year > 138)) {
tm.tm_year = 70;
tm.tm_mon = 0;
tm.tm_mday = 1;
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
ret = pm860x_rtc_set_time(&pdev->dev, &tm);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to set initial time.\n");
goto out_rtc;
}
}
rtc_tm_to_time(&tm, &ticks);
if (pdata && pdata->sync) {
pdata->sync(ticks);
info->sync = pdata->sync;
}
info->rtc_dev = rtc_device_register("88pm860x-rtc", &pdev->dev,
&pm860x_rtc_ops, THIS_MODULE);
ret = PTR_ERR(info->rtc_dev);
if (IS_ERR(info->rtc_dev)) {
dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
goto out_rtc;
}
/*
* enable internal XO instead of internal 3.25MHz clock since it can
* free running in PMIC power-down state.
*/
pm860x_set_bits(info->i2c, PM8607_RTC1, RTC1_USE_XO, RTC1_USE_XO);
#ifdef VRTC_CALIBRATION
/* <00> -- 2.7V, <01> -- 2.9V, <10> -- 3.1V, <11> -- 3.3V */
if (pdata && pdata->vrtc)
info->vrtc = pdata->vrtc & 0x3;
else
info->vrtc = 1;
pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, MEAS2_VRTC);
/* calibrate VRTC */
INIT_DELAYED_WORK(&info->calib_work, calibrate_vrtc_work);
schedule_delayed_work(&info->calib_work, VRTC_CALIB_INTERVAL);
#endif /* VRTC_CALIBRATION */
return 0;
out_rtc:
free_irq(info->irq, info);
out:
kfree(info);
return ret;
}
static int __devexit pm860x_rtc_remove(struct platform_device *pdev)
{
struct pm860x_rtc_info *info = platform_get_drvdata(pdev);
#ifdef VRTC_CALIBRATION
flush_scheduled_work();
/* disable measurement */
pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, 0);
#endif /* VRTC_CALIBRATION */
platform_set_drvdata(pdev, NULL);
rtc_device_unregister(info->rtc_dev);
free_irq(info->irq, info);
kfree(info);
return 0;
}
static struct platform_driver pm860x_rtc_driver = {
.driver = {
.name = "88pm860x-rtc",
.owner = THIS_MODULE,
},
.probe = pm860x_rtc_probe,
.remove = __devexit_p(pm860x_rtc_remove),
};
static int __init pm860x_rtc_init(void)
{
return platform_driver_register(&pm860x_rtc_driver);
}
module_init(pm860x_rtc_init);
static void __exit pm860x_rtc_exit(void)
{
platform_driver_unregister(&pm860x_rtc_driver);
}
module_exit(pm860x_rtc_exit);
MODULE_DESCRIPTION("Marvell 88PM860x RTC driver");
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
MODULE_LICENSE("GPL");
......@@ -18,7 +18,6 @@
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/spi/xilinx_spi.h>
......@@ -471,7 +470,7 @@ static int __devinit xilinx_spi_probe(struct platform_device *dev)
struct spi_master *master;
u8 i;
pdata = mfd_get_data(dev);
pdata = dev->dev.platform_data;
if (pdata) {
num_cs = pdata->num_chipselect;
little_endian = pdata->little_endian;
......
......@@ -16,7 +16,6 @@
#include <linux/fb.h>
#include <linux/i2c.h>
#include <linux/backlight.h>
#include <linux/mfd/core.h>
#include <linux/mfd/88pm860x.h>
#define MAX_BRIGHTNESS (0xFF)
......@@ -168,7 +167,6 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
struct pm860x_backlight_pdata *pdata = NULL;
struct pm860x_backlight_data *data;
struct backlight_device *bl;
struct mfd_cell *cell;
struct resource *res;
struct backlight_properties props;
unsigned char value;
......@@ -181,10 +179,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
return -EINVAL;
}
cell = pdev->dev.platform_data;
if (cell == NULL)
return -ENODEV;
pdata = cell->mfd_data;
pdata = pdev->dev.platform_data;
if (pdata == NULL) {
dev_err(&pdev->dev, "platform data isn't assigned to "
"backlight\n");
......
......@@ -250,7 +250,7 @@ static irqreturn_t tmiofb_irq(int irq, void *__info)
*/
static int tmiofb_hw_stop(struct platform_device *dev)
{
struct tmio_fb_data *data = mfd_get_data(dev);
struct tmio_fb_data *data = dev->dev.platform_data;
struct fb_info *info = platform_get_drvdata(dev);
struct tmiofb_par *par = info->par;
......@@ -311,7 +311,7 @@ static int tmiofb_hw_init(struct platform_device *dev)
*/
static void tmiofb_hw_mode(struct platform_device *dev)
{
struct tmio_fb_data *data = mfd_get_data(dev);
struct tmio_fb_data *data = dev->dev.platform_data;
struct fb_info *info = platform_get_drvdata(dev);
struct fb_videomode *mode = info->mode;
struct tmiofb_par *par = info->par;
......@@ -557,8 +557,7 @@ static int tmiofb_ioctl(struct fb_info *fbi,
static struct fb_videomode *
tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var)
{
struct tmio_fb_data *data =
mfd_get_data(to_platform_device(info->device));
struct tmio_fb_data *data = info->device->platform_data;
struct fb_videomode *best = NULL;
int i;
......@@ -578,8 +577,7 @@ static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct fb_videomode *mode;
struct tmio_fb_data *data =
mfd_get_data(to_platform_device(info->device));
struct tmio_fb_data *data = info->device->platform_data;
mode = tmiofb_find_mode(info, var);
if (!mode || var->bits_per_pixel > 16)
......@@ -680,7 +678,7 @@ static struct fb_ops tmiofb_ops = {
static int __devinit tmiofb_probe(struct platform_device *dev)
{
const struct mfd_cell *cell = mfd_get_cell(dev);
struct tmio_fb_data *data = mfd_get_data(dev);
struct tmio_fb_data *data = dev->dev.platform_data;
struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1);
struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0);
struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2);
......
......@@ -216,7 +216,7 @@ static int ds1wm_find_divisor(int gclk)
static void ds1wm_up(struct ds1wm_data *ds1wm_data)
{
int divisor;
struct ds1wm_driver_data *plat = mfd_get_data(ds1wm_data->pdev);
struct ds1wm_driver_data *plat = ds1wm_data->pdev->dev.platform_data;
if (ds1wm_data->cell->enable)
ds1wm_data->cell->enable(ds1wm_data->pdev);
......@@ -351,13 +351,21 @@ static int ds1wm_probe(struct platform_device *pdev)
ret = -ENOMEM;
goto err0;
}
plat = mfd_get_data(pdev);
/* calculate bus shift from mem resource */
ds1wm_data->bus_shift = resource_size(res) >> 3;
ds1wm_data->pdev = pdev;
ds1wm_data->cell = mfd_get_cell(pdev);
if (!ds1wm_data->cell) {
ret = -ENODEV;
goto err1;
}
plat = pdev->dev.platform_data;
if (!plat) {
ret = -ENODEV;
goto err1;
}
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
......
......@@ -37,7 +37,6 @@
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/mfd/rdc321x.h>
#include <linux/mfd/core.h>
#define RDC_WDT_MASK 0x80000000 /* Mask */
#define RDC_WDT_EN 0x00800000 /* Enable bit */
......@@ -232,7 +231,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
struct resource *r;
struct rdc321x_wdt_pdata *pdata;
pdata = mfd_get_data(pdev);
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "no platform data supplied\n");
return -ENODEV;
......
此差异已折叠。
此差异已折叠。
/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only 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.
*/
#ifndef __PMIC8XXX_PWRKEY_H__
#define __PMIC8XXX_PWRKEY_H__
#define PM8XXX_PWRKEY_DEV_NAME "pm8xxx-pwrkey"
/**
* struct pm8xxx_pwrkey_platform_data - platform data for pwrkey driver
* @pull up: power on register control for pull up/down configuration
* @kpd_trigger_delay_us: time delay for power key state change interrupt
* trigger.
* @wakeup: configure power key as wakeup source
*/
struct pm8xxx_pwrkey_platform_data {
bool pull_up;
u32 kpd_trigger_delay_us;
u32 wakeup;
};
#endif /* __PMIC8XXX_PWRKEY_H__ */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
* MFD driver for twl4030 codec submodule
*
* Author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
* Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
*
* Copyright: (C) 2009 Nokia Corporation
*
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册