Commit 822e5215 authored by Linus Torvalds's avatar Linus Torvalds

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

* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (59 commits)
  mfd: ab8500-core chip version cut 2.0 support
  mfd: Flag WM831x /IRQ as a wake source
  mfd: Convert WM831x away from legacy I2C PM operations
  regulator: Support MAX8998/LP3974 DVS-GPIO
  mfd: Support LP3974 RTC
  i2c: Convert SCx200 driver from using raw PCI to platform device
  x86: OLPC: convert olpc-xo1 driver from pci device to platform device
  mfd: MAX8998/LP3974 hibernation support
  mfd/ab8500: remove spi support
  mfd: Remove ARCH_U8500 dependency from AB8500
  misc: Make AB8500_PWM driver depend on U8500 due to PWM breakage
  mfd: Add __devexit annotation for vx855_remove
  mfd: twl6030 irq_data conversion.
  gpio: Fix cs5535 printk warnings
  misc: Fix cs5535 printk warnings
  mfd: Convert Wolfson MFD drivers to use irq_data accessor function
  mfd: Convert TWL4030 to new irq_ APIs
  mfd: Convert tps6586x driver to new irq_ API
  mfd: Convert tc6393xb driver to new irq_ APIs
  mfd: Convert t7166xb driver to new irq_ API
  ...
parents c1e0d97d 92d50a41
...@@ -2068,7 +2068,7 @@ config OLPC ...@@ -2068,7 +2068,7 @@ config OLPC
config OLPC_XO1 config OLPC_XO1
tristate "OLPC XO-1 support" tristate "OLPC XO-1 support"
depends on OLPC && PCI depends on OLPC && MFD_CS5535
---help--- ---help---
Add support for non-essential features of the OLPC XO-1 laptop. Add support for non-essential features of the OLPC XO-1 laptop.
......
/* /*
* Support for features of the OLPC XO-1 laptop * Support for features of the OLPC XO-1 laptop
* *
* Copyright (C) 2010 Andres Salomon <dilinger@queued.net>
* Copyright (C) 2010 One Laptop per Child * Copyright (C) 2010 One Laptop per Child
* Copyright (C) 2006 Red Hat, Inc. * Copyright (C) 2006 Red Hat, Inc.
* Copyright (C) 2006 Advanced Micro Devices, Inc. * Copyright (C) 2006 Advanced Micro Devices, Inc.
...@@ -12,8 +13,6 @@ ...@@ -12,8 +13,6 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm.h> #include <linux/pm.h>
...@@ -22,9 +21,6 @@ ...@@ -22,9 +21,6 @@
#define DRV_NAME "olpc-xo1" #define DRV_NAME "olpc-xo1"
#define PMS_BAR 4
#define ACPI_BAR 5
/* PMC registers (PMS block) */ /* PMC registers (PMS block) */
#define PM_SCLK 0x10 #define PM_SCLK 0x10
#define PM_IN_SLPCTL 0x20 #define PM_IN_SLPCTL 0x20
...@@ -57,65 +53,67 @@ static void xo1_power_off(void) ...@@ -57,65 +53,67 @@ static void xo1_power_off(void)
outl(0x00002000, acpi_base + PM1_CNT); outl(0x00002000, acpi_base + PM1_CNT);
} }
/* Read the base addresses from the PCI BAR info */ static int __devinit olpc_xo1_probe(struct platform_device *pdev)
static int __devinit setup_bases(struct pci_dev *pdev)
{ {
int r; struct resource *res;
r = pci_enable_device_io(pdev); /* don't run on non-XOs */
if (r) { if (!machine_is_olpc())
dev_err(&pdev->dev, "can't enable device IO\n"); return -ENODEV;
return r;
}
r = pci_request_region(pdev, ACPI_BAR, DRV_NAME); res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (r) { if (!res) {
dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", ACPI_BAR); dev_err(&pdev->dev, "can't fetch device resource info\n");
return r; return -EIO;
} }
r = pci_request_region(pdev, PMS_BAR, DRV_NAME); if (!request_region(res->start, resource_size(res), DRV_NAME)) {
if (r) { dev_err(&pdev->dev, "can't request region\n");
dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", PMS_BAR); return -EIO;
pci_release_region(pdev, ACPI_BAR);
return r;
} }
acpi_base = pci_resource_start(pdev, ACPI_BAR); if (strcmp(pdev->name, "cs5535-pms") == 0)
pms_base = pci_resource_start(pdev, PMS_BAR); pms_base = res->start;
else if (strcmp(pdev->name, "cs5535-acpi") == 0)
return 0; acpi_base = res->start;
}
static int __devinit olpc_xo1_probe(struct platform_device *pdev)
{
struct pci_dev *pcidev;
int r;
pcidev = pci_get_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA,
NULL);
if (!pdev)
return -ENODEV;
r = setup_bases(pcidev);
if (r)
return r;
/* If we have both addresses, we can override the poweroff hook */
if (pms_base && acpi_base) {
pm_power_off = xo1_power_off; pm_power_off = xo1_power_off;
printk(KERN_INFO "OLPC XO-1 support registered\n"); printk(KERN_INFO "OLPC XO-1 support registered\n");
}
return 0; return 0;
} }
static int __devexit olpc_xo1_remove(struct platform_device *pdev) static int __devexit olpc_xo1_remove(struct platform_device *pdev)
{ {
struct resource *r;
r = platform_get_resource(pdev, IORESOURCE_IO, 0);
release_region(r->start, resource_size(r));
if (strcmp(pdev->name, "cs5535-pms") == 0)
pms_base = 0;
else if (strcmp(pdev->name, "cs5535-acpi") == 0)
acpi_base = 0;
pm_power_off = NULL; pm_power_off = NULL;
return 0; return 0;
} }
static struct platform_driver olpc_xo1_driver = { static struct platform_driver cs5535_pms_drv = {
.driver = {
.name = "cs5535-pms",
.owner = THIS_MODULE,
},
.probe = olpc_xo1_probe,
.remove = __devexit_p(olpc_xo1_remove),
};
static struct platform_driver cs5535_acpi_drv = {
.driver = { .driver = {
.name = DRV_NAME, .name = "cs5535-acpi",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = olpc_xo1_probe, .probe = olpc_xo1_probe,
...@@ -124,12 +122,23 @@ static struct platform_driver olpc_xo1_driver = { ...@@ -124,12 +122,23 @@ static struct platform_driver olpc_xo1_driver = {
static int __init olpc_xo1_init(void) static int __init olpc_xo1_init(void)
{ {
return platform_driver_register(&olpc_xo1_driver); int r;
r = platform_driver_register(&cs5535_pms_drv);
if (r)
return r;
r = platform_driver_register(&cs5535_acpi_drv);
if (r)
platform_driver_unregister(&cs5535_pms_drv);
return r;
} }
static void __exit olpc_xo1_exit(void) static void __exit olpc_xo1_exit(void)
{ {
platform_driver_unregister(&olpc_xo1_driver); platform_driver_unregister(&cs5535_acpi_drv);
platform_driver_unregister(&cs5535_pms_drv);
} }
MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>"); MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
......
...@@ -11,14 +11,13 @@ ...@@ -11,14 +11,13 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/platform_device.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/cs5535.h> #include <linux/cs5535.h>
#include <asm/msr.h> #include <asm/msr.h>
#define DRV_NAME "cs5535-gpio" #define DRV_NAME "cs5535-gpio"
#define GPIO_BAR 1
/* /*
* Some GPIO pins * Some GPIO pins
...@@ -47,7 +46,7 @@ static struct cs5535_gpio_chip { ...@@ -47,7 +46,7 @@ static struct cs5535_gpio_chip {
struct gpio_chip chip; struct gpio_chip chip;
resource_size_t base; resource_size_t base;
struct pci_dev *pdev; struct platform_device *pdev;
spinlock_t lock; spinlock_t lock;
} cs5535_gpio_chip; } cs5535_gpio_chip;
...@@ -301,10 +300,10 @@ static struct cs5535_gpio_chip cs5535_gpio_chip = { ...@@ -301,10 +300,10 @@ static struct cs5535_gpio_chip cs5535_gpio_chip = {
}, },
}; };
static int __init cs5535_gpio_probe(struct pci_dev *pdev, static int __devinit cs5535_gpio_probe(struct platform_device *pdev)
const struct pci_device_id *pci_id)
{ {
int err; struct resource *res;
int err = -EIO;
ulong mask_orig = mask; ulong mask_orig = mask;
/* There are two ways to get the GPIO base address; one is by /* There are two ways to get the GPIO base address; one is by
...@@ -314,25 +313,23 @@ static int __init cs5535_gpio_probe(struct pci_dev *pdev, ...@@ -314,25 +313,23 @@ static int __init cs5535_gpio_probe(struct pci_dev *pdev,
* it turns out to be unreliable in the face of crappy BIOSes, we * it turns out to be unreliable in the face of crappy BIOSes, we
* can always go back to using MSRs.. */ * can always go back to using MSRs.. */
err = pci_enable_device_io(pdev); res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (err) { if (!res) {
dev_err(&pdev->dev, "can't enable device IO\n"); dev_err(&pdev->dev, "can't fetch device resource info\n");
goto done; goto done;
} }
err = pci_request_region(pdev, GPIO_BAR, DRV_NAME); if (!request_region(res->start, resource_size(res), pdev->name)) {
if (err) { dev_err(&pdev->dev, "can't request region\n");
dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", GPIO_BAR);
goto done; goto done;
} }
/* set up the driver-specific struct */ /* set up the driver-specific struct */
cs5535_gpio_chip.base = pci_resource_start(pdev, GPIO_BAR); cs5535_gpio_chip.base = res->start;
cs5535_gpio_chip.pdev = pdev; cs5535_gpio_chip.pdev = pdev;
spin_lock_init(&cs5535_gpio_chip.lock); spin_lock_init(&cs5535_gpio_chip.lock);
dev_info(&pdev->dev, "allocated PCI BAR #%d: base 0x%llx\n", GPIO_BAR, dev_info(&pdev->dev, "reserved resource region %pR\n", res);
(unsigned long long) cs5535_gpio_chip.base);
/* mask out reserved pins */ /* mask out reserved pins */
mask &= 0x1F7FFFFF; mask &= 0x1F7FFFFF;
...@@ -350,78 +347,49 @@ static int __init cs5535_gpio_probe(struct pci_dev *pdev, ...@@ -350,78 +347,49 @@ static int __init cs5535_gpio_probe(struct pci_dev *pdev,
if (err) if (err)
goto release_region; goto release_region;
dev_info(&pdev->dev, DRV_NAME ": GPIO support successfully loaded.\n"); dev_info(&pdev->dev, "GPIO support successfully loaded.\n");
return 0; return 0;
release_region: release_region:
pci_release_region(pdev, GPIO_BAR); release_region(res->start, resource_size(res));
done: done:
return err; return err;
} }
static void __exit cs5535_gpio_remove(struct pci_dev *pdev) static int __devexit cs5535_gpio_remove(struct platform_device *pdev)
{ {
struct resource *r;
int err; int err;
err = gpiochip_remove(&cs5535_gpio_chip.chip); err = gpiochip_remove(&cs5535_gpio_chip.chip);
if (err) { if (err) {
/* uhh? */ /* uhh? */
dev_err(&pdev->dev, "unable to remove gpio_chip?\n"); dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
} return err;
pci_release_region(pdev, GPIO_BAR);
}
static struct pci_device_id cs5535_gpio_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, cs5535_gpio_pci_tbl);
/*
* We can't use the standard PCI driver registration stuff here, since
* that allows only one driver to bind to each PCI device (and we want
* multiple drivers to be able to bind to the device). Instead, manually
* scan for the PCI device, request a single region, and keep track of the
* devices that we're using.
*/
static int __init cs5535_gpio_scan_pci(void)
{
struct pci_dev *pdev;
int err = -ENODEV;
int i;
for (i = 0; i < ARRAY_SIZE(cs5535_gpio_pci_tbl); i++) {
pdev = pci_get_device(cs5535_gpio_pci_tbl[i].vendor,
cs5535_gpio_pci_tbl[i].device, NULL);
if (pdev) {
err = cs5535_gpio_probe(pdev, &cs5535_gpio_pci_tbl[i]);
if (err)
pci_dev_put(pdev);
/* we only support a single CS5535/6 southbridge */
break;
}
} }
return err; r = platform_get_resource(pdev, IORESOURCE_IO, 0);
release_region(r->start, resource_size(r));
return 0;
} }
static void __exit cs5535_gpio_free_pci(void) static struct platform_driver cs5535_gpio_drv = {
{ .driver = {
cs5535_gpio_remove(cs5535_gpio_chip.pdev); .name = DRV_NAME,
pci_dev_put(cs5535_gpio_chip.pdev); .owner = THIS_MODULE,
} },
.probe = cs5535_gpio_probe,
.remove = __devexit_p(cs5535_gpio_remove),
};
static int __init cs5535_gpio_init(void) static int __init cs5535_gpio_init(void)
{ {
return cs5535_gpio_scan_pci(); return platform_driver_register(&cs5535_gpio_drv);
} }
static void __exit cs5535_gpio_exit(void) static void __exit cs5535_gpio_exit(void)
{ {
cs5535_gpio_free_pci(); platform_driver_unregister(&cs5535_gpio_drv);
} }
module_init(cs5535_gpio_init); module_init(cs5535_gpio_init);
...@@ -430,3 +398,4 @@ module_exit(cs5535_gpio_exit); ...@@ -430,3 +398,4 @@ module_exit(cs5535_gpio_exit);
MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>"); MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver"); MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -40,6 +41,7 @@ ...@@ -40,6 +41,7 @@
MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>"); MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
MODULE_DESCRIPTION("NatSemi SCx200 ACCESS.bus Driver"); MODULE_DESCRIPTION("NatSemi SCx200 ACCESS.bus Driver");
MODULE_ALIAS("platform:cs5535-smb");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#define MAX_DEVICES 4 #define MAX_DEVICES 4
...@@ -84,10 +86,6 @@ struct scx200_acb_iface { ...@@ -84,10 +86,6 @@ struct scx200_acb_iface {
u8 *ptr; u8 *ptr;
char needs_reset; char needs_reset;
unsigned len; unsigned len;
/* PCI device info */
struct pci_dev *pdev;
int bar;
}; };
/* Register Definitions */ /* Register Definitions */
...@@ -391,7 +389,7 @@ static const struct i2c_algorithm scx200_acb_algorithm = { ...@@ -391,7 +389,7 @@ static const struct i2c_algorithm scx200_acb_algorithm = {
static struct scx200_acb_iface *scx200_acb_list; static struct scx200_acb_iface *scx200_acb_list;
static DEFINE_MUTEX(scx200_acb_list_mutex); static DEFINE_MUTEX(scx200_acb_list_mutex);
static __init int scx200_acb_probe(struct scx200_acb_iface *iface) static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface)
{ {
u8 val; u8 val;
...@@ -427,7 +425,7 @@ static __init int scx200_acb_probe(struct scx200_acb_iface *iface) ...@@ -427,7 +425,7 @@ static __init int scx200_acb_probe(struct scx200_acb_iface *iface)
return 0; return 0;
} }
static __init struct scx200_acb_iface *scx200_create_iface(const char *text, static __devinit struct scx200_acb_iface *scx200_create_iface(const char *text,
struct device *dev, int index) struct device *dev, int index)
{ {
struct scx200_acb_iface *iface; struct scx200_acb_iface *iface;
...@@ -452,7 +450,7 @@ static __init struct scx200_acb_iface *scx200_create_iface(const char *text, ...@@ -452,7 +450,7 @@ static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
return iface; return iface;
} }
static int __init scx200_acb_create(struct scx200_acb_iface *iface) static int __devinit scx200_acb_create(struct scx200_acb_iface *iface)
{ {
struct i2c_adapter *adapter; struct i2c_adapter *adapter;
int rc; int rc;
...@@ -472,183 +470,145 @@ static int __init scx200_acb_create(struct scx200_acb_iface *iface) ...@@ -472,183 +470,145 @@ static int __init scx200_acb_create(struct scx200_acb_iface *iface)
return -ENODEV; return -ENODEV;
} }
if (!adapter->dev.parent) {
/* If there's no dev, we're tracking (ISA) ifaces manually */
mutex_lock(&scx200_acb_list_mutex); mutex_lock(&scx200_acb_list_mutex);
iface->next = scx200_acb_list; iface->next = scx200_acb_list;
scx200_acb_list = iface; scx200_acb_list = iface;
mutex_unlock(&scx200_acb_list_mutex); mutex_unlock(&scx200_acb_list_mutex);
}
return 0; return 0;
} }
static __init int scx200_create_pci(const char *text, struct pci_dev *pdev, static struct scx200_acb_iface * __devinit scx200_create_dev(const char *text,
int bar) unsigned long base, int index, struct device *dev)
{ {
struct scx200_acb_iface *iface; struct scx200_acb_iface *iface;
int rc; int rc;
iface = scx200_create_iface(text, &pdev->dev, 0); iface = scx200_create_iface(text, dev, index);
if (iface == NULL) if (iface == NULL)
return -ENOMEM; return NULL;
iface->pdev = pdev;
iface->bar = bar;
rc = pci_enable_device_io(iface->pdev);
if (rc)
goto errout_free;
rc = pci_request_region(iface->pdev, iface->bar, iface->adapter.name); if (!request_region(base, 8, iface->adapter.name)) {
if (rc) { printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n",
printk(KERN_ERR NAME ": can't allocate PCI BAR %d\n", base, base + 8 - 1);
iface->bar);
goto errout_free; goto errout_free;
} }
iface->base = pci_resource_start(iface->pdev, iface->bar); iface->base = base;
rc = scx200_acb_create(iface); rc = scx200_acb_create(iface);
if (rc == 0) if (rc == 0)
return 0; return iface;
pci_release_region(iface->pdev, iface->bar); release_region(base, 8);
pci_dev_put(iface->pdev);
errout_free: errout_free:
kfree(iface); kfree(iface);
return rc; return NULL;
} }
static int __init scx200_create_isa(const char *text, unsigned long base, static int __devinit scx200_probe(struct platform_device *pdev)
int index)
{ {
struct scx200_acb_iface *iface; struct scx200_acb_iface *iface;
int rc; struct resource *res;
iface = scx200_create_iface(text, NULL, index); res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!res) {
if (iface == NULL) dev_err(&pdev->dev, "can't fetch device resource info\n");
return -ENOMEM; return -ENODEV;
if (!request_region(base, 8, iface->adapter.name)) {
printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n",
base, base + 8 - 1);
rc = -EBUSY;
goto errout_free;
} }
iface->base = base; iface = scx200_create_dev("CS5535", res->start, 0, &pdev->dev);
rc = scx200_acb_create(iface); if (!iface)
return -EIO;
dev_info(&pdev->dev, "SCx200 device '%s' registered\n",
iface->adapter.name);
platform_set_drvdata(pdev, iface);
if (rc == 0)
return 0; return 0;
}
release_region(base, 8); static void __devexit scx200_cleanup_iface(struct scx200_acb_iface *iface)
errout_free: {
i2c_del_adapter(&iface->adapter);
release_region(iface->base, 8);
kfree(iface); kfree(iface);
return rc;
} }
/* Driver data is an index into the scx200_data array that indicates static int __devexit scx200_remove(struct platform_device *pdev)
* the name and the BAR where the I/O address resource is located. ISA
* devices are flagged with a bar value of -1 */
static const struct pci_device_id scx200_pci[] __initconst = {
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE),
.driver_data = 0 },
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE),
.driver_data = 0 },
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA),
.driver_data = 1 },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA),
.driver_data = 2 },
{ 0, }
};
static struct {
const char *name;
int bar;
} scx200_data[] = {
{ "SCx200", -1 },
{ "CS5535", 0 },
{ "CS5536", 0 }
};
static __init int scx200_scan_pci(void)
{ {
int data, dev; struct scx200_acb_iface *iface;
int rc = -ENODEV;
struct pci_dev *pdev;
for(dev = 0; dev < ARRAY_SIZE(scx200_pci); dev++) { iface = platform_get_drvdata(pdev);
pdev = pci_get_device(scx200_pci[dev].vendor, platform_set_drvdata(pdev, NULL);
scx200_pci[dev].device, NULL); scx200_cleanup_iface(iface);
if (pdev == NULL) return 0;
continue; }
data = scx200_pci[dev].driver_data; static struct platform_driver scx200_pci_drv = {
.driver = {
.name = "cs5535-smb",
.owner = THIS_MODULE,
},
.probe = scx200_probe,
.remove = __devexit_p(scx200_remove),
};
/* if .bar is greater or equal to zero, this is a static const struct pci_device_id scx200_isa[] __initconst = {
* PCI device - otherwise, we assume { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) },
that the ports are ISA based { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) },
*/ { 0, }
};
if (scx200_data[data].bar >= 0) static __init void scx200_scan_isa(void)
rc = scx200_create_pci(scx200_data[data].name, pdev, {
scx200_data[data].bar);
else {
int i; int i;
pci_dev_put(pdev); if (!pci_dev_present(scx200_isa))
return;
for (i = 0; i < MAX_DEVICES; ++i) { for (i = 0; i < MAX_DEVICES; ++i) {
if (base[i] == 0) if (base[i] == 0)
continue; continue;
rc = scx200_create_isa(scx200_data[data].name, /* XXX: should we care about failures? */
base[i], scx200_create_dev("SCx200", base[i], i, NULL);
i);
} }
}
break;
}
return rc;
} }
static int __init scx200_acb_init(void) static int __init scx200_acb_init(void)
{ {
int rc;
pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n"); pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n");
rc = scx200_scan_pci(); /* First scan for ISA-based devices */
scx200_scan_isa(); /* XXX: should we care about errors? */
/* If at least one bus was created, init must succeed */ /* If at least one bus was created, init must succeed */
if (scx200_acb_list) if (scx200_acb_list)
return 0; return 0;
return rc;
/* No ISA devices; register the platform driver for PCI-based devices */
return platform_driver_register(&scx200_pci_drv);
} }
static void __exit scx200_acb_cleanup(void) static void __exit scx200_acb_cleanup(void)
{ {
struct scx200_acb_iface *iface; struct scx200_acb_iface *iface;
platform_driver_unregister(&scx200_pci_drv);
mutex_lock(&scx200_acb_list_mutex); mutex_lock(&scx200_acb_list_mutex);
while ((iface = scx200_acb_list) != NULL) { while ((iface = scx200_acb_list) != NULL) {
scx200_acb_list = iface->next; scx200_acb_list = iface->next;
mutex_unlock(&scx200_acb_list_mutex); mutex_unlock(&scx200_acb_list_mutex);
i2c_del_adapter(&iface->adapter); scx200_cleanup_iface(iface);
if (iface->pdev) {
pci_release_region(iface->pdev, iface->bar);
pci_dev_put(iface->pdev);
}
else
release_region(iface->base, 8);
kfree(iface);
mutex_lock(&scx200_acb_list_mutex); mutex_lock(&scx200_acb_list_mutex);
} }
mutex_unlock(&scx200_acb_list_mutex); mutex_unlock(&scx200_acb_list_mutex);
......
...@@ -361,12 +361,6 @@ static struct pm860x_irq_data pm860x_irqs[] = { ...@@ -361,12 +361,6 @@ static struct pm860x_irq_data pm860x_irqs[] = {
}, },
}; };
static inline struct pm860x_irq_data *irq_to_pm860x(struct pm860x_chip *chip,
int irq)
{
return &pm860x_irqs[irq - chip->irq_base];
}
static irqreturn_t pm860x_irq(int irq, void *data) static irqreturn_t pm860x_irq(int irq, void *data)
{ {
struct pm860x_chip *chip = data; struct pm860x_chip *chip = data;
...@@ -388,16 +382,16 @@ static irqreturn_t pm860x_irq(int irq, void *data) ...@@ -388,16 +382,16 @@ static irqreturn_t pm860x_irq(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void pm860x_irq_lock(unsigned int irq) static void pm860x_irq_lock(struct irq_data *data)
{ {
struct pm860x_chip *chip = get_irq_chip_data(irq); struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
mutex_lock(&chip->irq_lock); mutex_lock(&chip->irq_lock);
} }
static void pm860x_irq_sync_unlock(unsigned int irq) static void pm860x_irq_sync_unlock(struct irq_data *data)
{ {
struct pm860x_chip *chip = get_irq_chip_data(irq); struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
struct pm860x_irq_data *irq_data; struct pm860x_irq_data *irq_data;
struct i2c_client *i2c; struct i2c_client *i2c;
static unsigned char cached[3] = {0x0, 0x0, 0x0}; static unsigned char cached[3] = {0x0, 0x0, 0x0};
...@@ -439,25 +433,25 @@ static void pm860x_irq_sync_unlock(unsigned int irq) ...@@ -439,25 +433,25 @@ static void pm860x_irq_sync_unlock(unsigned int irq)
mutex_unlock(&chip->irq_lock); mutex_unlock(&chip->irq_lock);
} }
static void pm860x_irq_enable(unsigned int irq) static void pm860x_irq_enable(struct irq_data *data)
{ {
struct pm860x_chip *chip = get_irq_chip_data(irq); struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
pm860x_irqs[irq - chip->irq_base].enable pm860x_irqs[data->irq - chip->irq_base].enable
= pm860x_irqs[irq - chip->irq_base].offs; = pm860x_irqs[data->irq - chip->irq_base].offs;
} }
static void pm860x_irq_disable(unsigned int irq) static void pm860x_irq_disable(struct irq_data *data)
{ {
struct pm860x_chip *chip = get_irq_chip_data(irq); struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
pm860x_irqs[irq - chip->irq_base].enable = 0; pm860x_irqs[data->irq - chip->irq_base].enable = 0;
} }
static struct irq_chip pm860x_irq_chip = { static struct irq_chip pm860x_irq_chip = {
.name = "88pm860x", .name = "88pm860x",
.bus_lock = pm860x_irq_lock, .irq_bus_lock = pm860x_irq_lock,
.bus_sync_unlock = pm860x_irq_sync_unlock, .irq_bus_sync_unlock = pm860x_irq_sync_unlock,
.enable = pm860x_irq_enable, .irq_enable = pm860x_irq_enable,
.disable = pm860x_irq_disable, .irq_disable = pm860x_irq_disable,
}; };
static int __devinit device_gpadc_init(struct pm860x_chip *chip, static int __devinit device_gpadc_init(struct pm860x_chip *chip,
......
...@@ -496,13 +496,13 @@ config EZX_PCAP ...@@ -496,13 +496,13 @@ config EZX_PCAP
config AB8500_CORE config AB8500_CORE
bool "ST-Ericsson AB8500 Mixed Signal Power Management chip" bool "ST-Ericsson AB8500 Mixed Signal Power Management chip"
depends on GENERIC_HARDIRQS && ABX500_CORE && SPI_MASTER && ARCH_U8500 depends on GENERIC_HARDIRQS && ABX500_CORE
select MFD_CORE select MFD_CORE
help help
Select this option to enable access to AB8500 power management Select this option to enable access to AB8500 power management
chip. This connects to U8500 either on the SSP/SPI bus chip. This connects to U8500 either on the SSP/SPI bus (deprecated
or the I2C bus via PRCMU. It also adds the irq_chip since hardware version v1.0) or the I2C bus via PRCMU. It also adds
parts for handling the Mixed Signal chip events. the irq_chip parts for handling the Mixed Signal chip events.
This chip embeds various other multimedia funtionalities as well. This chip embeds various other multimedia funtionalities as well.
config AB8500_I2C_CORE config AB8500_I2C_CORE
...@@ -537,6 +537,14 @@ config AB3550_CORE ...@@ -537,6 +537,14 @@ config AB3550_CORE
LEDs, vibrator, system power and temperature, power management LEDs, vibrator, system power and temperature, power management
and ALSA sound. and ALSA sound.
config MFD_CS5535
tristate "Support for CS5535 and CS5536 southbridge core functions"
select MFD_CORE
depends on PCI
---help---
This is the core driver for CS5535/CS5536 MFD functions. This is
necessary for using the board's GPIO and MFGPT functionality.
config MFD_TIMBERDALE config MFD_TIMBERDALE
tristate "Support for the Timberdale FPGA" tristate "Support for the Timberdale FPGA"
select MFD_CORE select MFD_CORE
......
...@@ -70,7 +70,7 @@ obj-$(CONFIG_ABX500_CORE) += abx500-core.o ...@@ -70,7 +70,7 @@ obj-$(CONFIG_ABX500_CORE) += abx500-core.o
obj-$(CONFIG_AB3100_CORE) += ab3100-core.o obj-$(CONFIG_AB3100_CORE) += ab3100-core.o
obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o
obj-$(CONFIG_AB3550_CORE) += ab3550-core.o obj-$(CONFIG_AB3550_CORE) += ab3550-core.o
obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-spi.o obj-$(CONFIG_AB8500_CORE) += ab8500-core.o
obj-$(CONFIG_AB8500_I2C_CORE) += ab8500-i2c.o obj-$(CONFIG_AB8500_I2C_CORE) += ab8500-i2c.o
obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o
obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
...@@ -82,3 +82,4 @@ obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o ...@@ -82,3 +82,4 @@ obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o
obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o
obj-$(CONFIG_MFD_VX855) += vx855.o obj-$(CONFIG_MFD_VX855) += vx855.o
obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o
obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o
...@@ -1159,15 +1159,16 @@ static void ab3550_mask_work(struct work_struct *work) ...@@ -1159,15 +1159,16 @@ static void ab3550_mask_work(struct work_struct *work)
} }
} }
static void ab3550_mask(unsigned int irq) static void ab3550_mask(struct irq_data *data)
{ {
unsigned long flags; unsigned long flags;
struct ab3550 *ab; struct ab3550 *ab;
struct ab3550_platform_data *plf_data; struct ab3550_platform_data *plf_data;
int irq;
ab = get_irq_chip_data(irq); ab = irq_data_get_irq_chip_data(data);
plf_data = ab->i2c_client[0]->dev.platform_data; plf_data = ab->i2c_client[0]->dev.platform_data;
irq -= plf_data->irq.base; irq = data->irq - plf_data->irq.base;
spin_lock_irqsave(&ab->event_lock, flags); spin_lock_irqsave(&ab->event_lock, flags);
ab->event_mask[irq / 8] |= BIT(irq % 8); ab->event_mask[irq / 8] |= BIT(irq % 8);
...@@ -1176,15 +1177,16 @@ static void ab3550_mask(unsigned int irq) ...@@ -1176,15 +1177,16 @@ static void ab3550_mask(unsigned int irq)
schedule_work(&ab->mask_work); schedule_work(&ab->mask_work);
} }
static void ab3550_unmask(unsigned int irq) static void ab3550_unmask(struct irq_data *data)
{ {
unsigned long flags; unsigned long flags;
struct ab3550 *ab; struct ab3550 *ab;
struct ab3550_platform_data *plf_data; struct ab3550_platform_data *plf_data;
int irq;
ab = get_irq_chip_data(irq); ab = irq_data_get_irq_chip_data(data);
plf_data = ab->i2c_client[0]->dev.platform_data; plf_data = ab->i2c_client[0]->dev.platform_data;
irq -= plf_data->irq.base; irq = data->irq - plf_data->irq.base;
spin_lock_irqsave(&ab->event_lock, flags); spin_lock_irqsave(&ab->event_lock, flags);
ab->event_mask[irq / 8] &= ~BIT(irq % 8); ab->event_mask[irq / 8] &= ~BIT(irq % 8);
...@@ -1193,20 +1195,16 @@ static void ab3550_unmask(unsigned int irq) ...@@ -1193,20 +1195,16 @@ static void ab3550_unmask(unsigned int irq)
schedule_work(&ab->mask_work); schedule_work(&ab->mask_work);
} }
static void noop(unsigned int irq) static void noop(struct irq_data *data)
{ {
} }
static struct irq_chip ab3550_irq_chip = { static struct irq_chip ab3550_irq_chip = {
.name = "ab3550-core", /* Keep the same name as the request */ .name = "ab3550-core", /* Keep the same name as the request */
.startup = NULL, /* defaults to enable */ .irq_disable = ab3550_mask, /* No default to mask in chip.c */
.shutdown = NULL, /* defaults to disable */ .irq_ack = noop,
.enable = NULL, /* defaults to unmask */ .irq_mask = ab3550_mask,
.disable = ab3550_mask, /* No default to mask in chip.c */ .irq_unmask = ab3550_unmask,
.ack = noop,
.mask = ab3550_mask,
.unmask = ab3550_unmask,
.end = NULL,
}; };
struct ab_family_id { struct ab_family_id {
......
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#define AB8500_IT_LATCH8_REG 0x27 #define AB8500_IT_LATCH8_REG 0x27
#define AB8500_IT_LATCH9_REG 0x28 #define AB8500_IT_LATCH9_REG 0x28
#define AB8500_IT_LATCH10_REG 0x29 #define AB8500_IT_LATCH10_REG 0x29
#define AB8500_IT_LATCH12_REG 0x2B
#define AB8500_IT_LATCH19_REG 0x32 #define AB8500_IT_LATCH19_REG 0x32
#define AB8500_IT_LATCH20_REG 0x33 #define AB8500_IT_LATCH20_REG 0x33
#define AB8500_IT_LATCH21_REG 0x34 #define AB8500_IT_LATCH21_REG 0x34
...@@ -98,13 +99,17 @@ ...@@ -98,13 +99,17 @@
* offset 0. * offset 0.
*/ */
static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
0, 1, 2, 3, 4, 6, 7, 8, 9, 18, 19, 20, 21, 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
}; };
static int ab8500_get_chip_id(struct device *dev) static int ab8500_get_chip_id(struct device *dev)
{ {
struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); struct ab8500 *ab8500;
return (int)ab8500->chip_id;
if (!dev)
return -EINVAL;
ab8500 = dev_get_drvdata(dev->parent);
return ab8500 ? (int)ab8500->chip_id : -EINVAL;
} }
static int set_register_interruptible(struct ab8500 *ab8500, u8 bank, static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
...@@ -228,16 +233,16 @@ static struct abx500_ops ab8500_ops = { ...@@ -228,16 +233,16 @@ static struct abx500_ops ab8500_ops = {
.startup_irq_enabled = NULL, .startup_irq_enabled = NULL,
}; };
static void ab8500_irq_lock(unsigned int irq) static void ab8500_irq_lock(struct irq_data *data)
{ {
struct ab8500 *ab8500 = get_irq_chip_data(irq); struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
mutex_lock(&ab8500->irq_lock); mutex_lock(&ab8500->irq_lock);
} }
static void ab8500_irq_sync_unlock(unsigned int irq) static void ab8500_irq_sync_unlock(struct irq_data *data)
{ {
struct ab8500 *ab8500 = get_irq_chip_data(irq); struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
int i; int i;
for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
...@@ -248,6 +253,10 @@ static void ab8500_irq_sync_unlock(unsigned int irq) ...@@ -248,6 +253,10 @@ static void ab8500_irq_sync_unlock(unsigned int irq)
if (new == old) if (new == old)
continue; continue;
/* Interrupt register 12 does'nt exist prior to version 0x20 */
if (ab8500_irq_regoffset[i] == 11 && ab8500->chip_id < 0x20)
continue;
ab8500->oldmask[i] = new; ab8500->oldmask[i] = new;
reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i]; reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i];
...@@ -257,20 +266,20 @@ static void ab8500_irq_sync_unlock(unsigned int irq) ...@@ -257,20 +266,20 @@ static void ab8500_irq_sync_unlock(unsigned int irq)
mutex_unlock(&ab8500->irq_lock); mutex_unlock(&ab8500->irq_lock);
} }
static void ab8500_irq_mask(unsigned int irq) static void ab8500_irq_mask(struct irq_data *data)
{ {
struct ab8500 *ab8500 = get_irq_chip_data(irq); struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
int offset = irq - ab8500->irq_base; int offset = data->irq - ab8500->irq_base;
int index = offset / 8; int index = offset / 8;
int mask = 1 << (offset % 8); int mask = 1 << (offset % 8);
ab8500->mask[index] |= mask; ab8500->mask[index] |= mask;
} }
static void ab8500_irq_unmask(unsigned int irq) static void ab8500_irq_unmask(struct irq_data *data)
{ {
struct ab8500 *ab8500 = get_irq_chip_data(irq); struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
int offset = irq - ab8500->irq_base; int offset = data->irq - ab8500->irq_base;
int index = offset / 8; int index = offset / 8;
int mask = 1 << (offset % 8); int mask = 1 << (offset % 8);
...@@ -279,10 +288,10 @@ static void ab8500_irq_unmask(unsigned int irq) ...@@ -279,10 +288,10 @@ static void ab8500_irq_unmask(unsigned int irq)
static struct irq_chip ab8500_irq_chip = { static struct irq_chip ab8500_irq_chip = {
.name = "ab8500", .name = "ab8500",
.bus_lock = ab8500_irq_lock, .irq_bus_lock = ab8500_irq_lock,
.bus_sync_unlock = ab8500_irq_sync_unlock, .irq_bus_sync_unlock = ab8500_irq_sync_unlock,
.mask = ab8500_irq_mask, .irq_mask = ab8500_irq_mask,
.unmask = ab8500_irq_unmask, .irq_unmask = ab8500_irq_unmask,
}; };
static irqreturn_t ab8500_irq(int irq, void *dev) static irqreturn_t ab8500_irq(int irq, void *dev)
...@@ -297,6 +306,10 @@ static irqreturn_t ab8500_irq(int irq, void *dev) ...@@ -297,6 +306,10 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
int status; int status;
u8 value; u8 value;
/* Interrupt register 12 does'nt exist prior to version 0x20 */
if (regoffset == 11 && ab8500->chip_id < 0x20)
continue;
status = get_register_interruptible(ab8500, AB8500_INTERRUPT, status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
AB8500_IT_LATCH1_REG + regoffset, &value); AB8500_IT_LATCH1_REG + regoffset, &value);
if (status < 0 || value == 0) if (status < 0 || value == 0)
...@@ -393,12 +406,194 @@ static struct resource ab8500_poweronkey_db_resources[] = { ...@@ -393,12 +406,194 @@ static struct resource ab8500_poweronkey_db_resources[] = {
}, },
}; };
static struct resource ab8500_bm_resources[] = {
{
.name = "MAIN_EXT_CH_NOT_OK",
.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
.end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
.flags = IORESOURCE_IRQ,
},
{
.name = "BATT_OVV",
.start = AB8500_INT_BATT_OVV,
.end = AB8500_INT_BATT_OVV,
.flags = IORESOURCE_IRQ,
},
{
.name = "MAIN_CH_UNPLUG_DET",
.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
.end = AB8500_INT_MAIN_CH_UNPLUG_DET,
.flags = IORESOURCE_IRQ,
},
{
.name = "MAIN_CHARGE_PLUG_DET",
.start = AB8500_INT_MAIN_CH_PLUG_DET,
.end = AB8500_INT_MAIN_CH_PLUG_DET,
.flags = IORESOURCE_IRQ,
},
{
.name = "VBUS_DET_F",
.start = AB8500_INT_VBUS_DET_F,
.end = AB8500_INT_VBUS_DET_F,
.flags = IORESOURCE_IRQ,
},
{
.name = "VBUS_DET_R",
.start = AB8500_INT_VBUS_DET_R,
.end = AB8500_INT_VBUS_DET_R,
.flags = IORESOURCE_IRQ,
},
{
.name = "BAT_CTRL_INDB",
.start = AB8500_INT_BAT_CTRL_INDB,
.end = AB8500_INT_BAT_CTRL_INDB,
.flags = IORESOURCE_IRQ,
},
{
.name = "CH_WD_EXP",
.start = AB8500_INT_CH_WD_EXP,
.end = AB8500_INT_CH_WD_EXP,
.flags = IORESOURCE_IRQ,
},
{
.name = "VBUS_OVV",
.start = AB8500_INT_VBUS_OVV,
.end = AB8500_INT_VBUS_OVV,
.flags = IORESOURCE_IRQ,
},
{
.name = "NCONV_ACCU",
.start = AB8500_INT_CCN_CONV_ACC,
.end = AB8500_INT_CCN_CONV_ACC,
.flags = IORESOURCE_IRQ,
},
{
.name = "LOW_BAT_F",
.start = AB8500_INT_LOW_BAT_F,
.end = AB8500_INT_LOW_BAT_F,
.flags = IORESOURCE_IRQ,
},
{
.name = "LOW_BAT_R",
.start = AB8500_INT_LOW_BAT_R,
.end = AB8500_INT_LOW_BAT_R,
.flags = IORESOURCE_IRQ,
},
{
.name = "BTEMP_LOW",
.start = AB8500_INT_BTEMP_LOW,
.end = AB8500_INT_BTEMP_LOW,
.flags = IORESOURCE_IRQ,
},
{
.name = "BTEMP_HIGH",
.start = AB8500_INT_BTEMP_HIGH,
.end = AB8500_INT_BTEMP_HIGH,
.flags = IORESOURCE_IRQ,
},
{
.name = "USB_CHARGER_NOT_OKR",
.start = AB8500_INT_USB_CHARGER_NOT_OK,
.end = AB8500_INT_USB_CHARGER_NOT_OK,
.flags = IORESOURCE_IRQ,
},
{
.name = "USB_CHARGE_DET_DONE",
.start = AB8500_INT_USB_CHG_DET_DONE,
.end = AB8500_INT_USB_CHG_DET_DONE,
.flags = IORESOURCE_IRQ,
},
{
.name = "USB_CH_TH_PROT_R",
.start = AB8500_INT_USB_CH_TH_PROT_R,
.end = AB8500_INT_USB_CH_TH_PROT_R,
.flags = IORESOURCE_IRQ,
},
{
.name = "MAIN_CH_TH_PROT_R",
.start = AB8500_INT_MAIN_CH_TH_PROT_R,
.end = AB8500_INT_MAIN_CH_TH_PROT_R,
.flags = IORESOURCE_IRQ,
},
{
.name = "USB_CHARGER_NOT_OKF",
.start = AB8500_INT_USB_CHARGER_NOT_OKF,
.end = AB8500_INT_USB_CHARGER_NOT_OKF,
.flags = IORESOURCE_IRQ,
},
};
static struct resource ab8500_debug_resources[] = {
{
.name = "IRQ_FIRST",
.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
.end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
.flags = IORESOURCE_IRQ,
},
{
.name = "IRQ_LAST",
.start = AB8500_INT_USB_CHARGER_NOT_OKF,
.end = AB8500_INT_USB_CHARGER_NOT_OKF,
.flags = IORESOURCE_IRQ,
},
};
static struct resource ab8500_usb_resources[] = {
{
.name = "ID_WAKEUP_R",
.start = AB8500_INT_ID_WAKEUP_R,
.end = AB8500_INT_ID_WAKEUP_R,
.flags = IORESOURCE_IRQ,
},
{
.name = "ID_WAKEUP_F",
.start = AB8500_INT_ID_WAKEUP_F,
.end = AB8500_INT_ID_WAKEUP_F,
.flags = IORESOURCE_IRQ,
},
{
.name = "VBUS_DET_F",
.start = AB8500_INT_VBUS_DET_F,
.end = AB8500_INT_VBUS_DET_F,
.flags = IORESOURCE_IRQ,
},
{
.name = "VBUS_DET_R",
.start = AB8500_INT_VBUS_DET_R,
.end = AB8500_INT_VBUS_DET_R,
.flags = IORESOURCE_IRQ,
},
{
.name = "USB_LINK_STATUS",
.start = AB8500_INT_USB_LINK_STATUS,
.end = AB8500_INT_USB_LINK_STATUS,
.flags = IORESOURCE_IRQ,
},
};
static struct resource ab8500_temp_resources[] = {
{
.name = "AB8500_TEMP_WARM",
.start = AB8500_INT_TEMP_WARM,
.end = AB8500_INT_TEMP_WARM,
.flags = IORESOURCE_IRQ,
},
};
static struct mfd_cell ab8500_devs[] = { static struct mfd_cell ab8500_devs[] = {
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
{ {
.name = "ab8500-debug", .name = "ab8500-debug",
.num_resources = ARRAY_SIZE(ab8500_debug_resources),
.resources = ab8500_debug_resources,
}, },
#endif #endif
{
.name = "ab8500-sysctrl",
},
{
.name = "ab8500-regulator",
},
{ {
.name = "ab8500-gpadc", .name = "ab8500-gpadc",
.num_resources = ARRAY_SIZE(ab8500_gpadc_resources), .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
...@@ -409,6 +604,22 @@ static struct mfd_cell ab8500_devs[] = { ...@@ -409,6 +604,22 @@ static struct mfd_cell ab8500_devs[] = {
.num_resources = ARRAY_SIZE(ab8500_rtc_resources), .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
.resources = ab8500_rtc_resources, .resources = ab8500_rtc_resources,
}, },
{
.name = "ab8500-bm",
.num_resources = ARRAY_SIZE(ab8500_bm_resources),
.resources = ab8500_bm_resources,
},
{ .name = "ab8500-codec", },
{
.name = "ab8500-usb",
.num_resources = ARRAY_SIZE(ab8500_usb_resources),
.resources = ab8500_usb_resources,
},
{
.name = "ab8500-poweron-key",
.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
.resources = ab8500_poweronkey_db_resources,
},
{ {
.name = "ab8500-pwm", .name = "ab8500-pwm",
.id = 1, .id = 1,
...@@ -421,17 +632,37 @@ static struct mfd_cell ab8500_devs[] = { ...@@ -421,17 +632,37 @@ static struct mfd_cell ab8500_devs[] = {
.name = "ab8500-pwm", .name = "ab8500-pwm",
.id = 3, .id = 3,
}, },
{ .name = "ab8500-charger", }, { .name = "ab8500-leds", },
{ .name = "ab8500-audio", },
{ .name = "ab8500-usb", },
{ .name = "ab8500-regulator", },
{ {
.name = "ab8500-poweron-key", .name = "ab8500-denc",
.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), },
.resources = ab8500_poweronkey_db_resources, {
.name = "ab8500-temp",
.num_resources = ARRAY_SIZE(ab8500_temp_resources),
.resources = ab8500_temp_resources,
}, },
}; };
static ssize_t show_chip_id(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct ab8500 *ab8500;
ab8500 = dev_get_drvdata(dev);
return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
}
static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
static struct attribute *ab8500_sysfs_entries[] = {
&dev_attr_chip_id.attr,
NULL,
};
static struct attribute_group ab8500_attr_group = {
.attrs = ab8500_sysfs_entries,
};
int __devinit ab8500_init(struct ab8500 *ab8500) int __devinit ab8500_init(struct ab8500 *ab8500)
{ {
struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev); struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev);
...@@ -454,8 +685,9 @@ int __devinit ab8500_init(struct ab8500 *ab8500) ...@@ -454,8 +685,9 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
* 0x0 - Early Drop * 0x0 - Early Drop
* 0x10 - Cut 1.0 * 0x10 - Cut 1.0
* 0x11 - Cut 1.1 * 0x11 - Cut 1.1
* 0x20 - Cut 2.0
*/ */
if (value == 0x0 || value == 0x10 || value == 0x11) { if (value == 0x0 || value == 0x10 || value == 0x11 || value == 0x20) {
ab8500->revision = value; ab8500->revision = value;
dev_info(ab8500->dev, "detected chip, revision: %#x\n", value); dev_info(ab8500->dev, "detected chip, revision: %#x\n", value);
} else { } else {
...@@ -468,18 +700,16 @@ int __devinit ab8500_init(struct ab8500 *ab8500) ...@@ -468,18 +700,16 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
plat->init(ab8500); plat->init(ab8500);
/* Clear and mask all interrupts */ /* Clear and mask all interrupts */
for (i = 0; i < 10; i++) { for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
get_register_interruptible(ab8500, AB8500_INTERRUPT, /* Interrupt register 12 does'nt exist prior to version 0x20 */
AB8500_IT_LATCH1_REG + i, &value); if (ab8500_irq_regoffset[i] == 11 && ab8500->chip_id < 0x20)
set_register_interruptible(ab8500, AB8500_INTERRUPT, continue;
AB8500_IT_MASK1_REG + i, 0xff);
}
for (i = 18; i < 24; i++) {
get_register_interruptible(ab8500, AB8500_INTERRUPT, get_register_interruptible(ab8500, AB8500_INTERRUPT,
AB8500_IT_LATCH1_REG + i, &value); AB8500_IT_LATCH1_REG + ab8500_irq_regoffset[i],
&value);
set_register_interruptible(ab8500, AB8500_INTERRUPT, set_register_interruptible(ab8500, AB8500_INTERRUPT,
AB8500_IT_MASK1_REG + i, 0xff); AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i], 0xff);
} }
ret = abx500_register_ops(ab8500->dev, &ab8500_ops); ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
...@@ -495,7 +725,8 @@ int __devinit ab8500_init(struct ab8500 *ab8500) ...@@ -495,7 +725,8 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
return ret; return ret;
ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq, ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq,
IRQF_ONESHOT, "ab8500", ab8500); IRQF_ONESHOT | IRQF_NO_SUSPEND,
"ab8500", ab8500);
if (ret) if (ret)
goto out_removeirq; goto out_removeirq;
} }
...@@ -506,6 +737,10 @@ int __devinit ab8500_init(struct ab8500 *ab8500) ...@@ -506,6 +737,10 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
if (ret) if (ret)
goto out_freeirq; goto out_freeirq;
ret = sysfs_create_group(&ab8500->dev->kobj, &ab8500_attr_group);
if (ret)
dev_err(ab8500->dev, "error creating sysfs entries\n");
return ret; return ret;
out_freeirq: out_freeirq:
...@@ -519,6 +754,7 @@ int __devinit ab8500_init(struct ab8500 *ab8500) ...@@ -519,6 +754,7 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
int __devexit ab8500_exit(struct ab8500 *ab8500) int __devexit ab8500_exit(struct ab8500 *ab8500)
{ {
sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
mfd_remove_devices(ab8500->dev); mfd_remove_devices(ab8500->dev);
if (ab8500->irq_base) { if (ab8500->irq_base) {
free_irq(ab8500->irq, ab8500); free_irq(ab8500->irq, ab8500);
......
...@@ -189,7 +189,7 @@ static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = { ...@@ -189,7 +189,7 @@ static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = {
}, },
[AB8500_DBI] = { [AB8500_DBI] = {
.num_ranges = 0, .num_ranges = 0,
.range = 0, .range = NULL,
}, },
[AB8500_ECI_AV_ACC] = { [AB8500_ECI_AV_ACC] = {
.num_ranges = 1, .num_ranges = 1,
...@@ -202,7 +202,7 @@ static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = { ...@@ -202,7 +202,7 @@ static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = {
}, },
[0x9] = { [0x9] = {
.num_ranges = 0, .num_ranges = 0,
.range = 0, .range = NULL,
}, },
[AB8500_GPADC] = { [AB8500_GPADC] = {
.num_ranges = 1, .num_ranges = 1,
...@@ -278,7 +278,7 @@ static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = { ...@@ -278,7 +278,7 @@ static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = {
}, },
[AB8500_INTERRUPT] = { [AB8500_INTERRUPT] = {
.num_ranges = 0, .num_ranges = 0,
.range = 0, .range = NULL,
}, },
[AB8500_RTC] = { [AB8500_RTC] = {
.num_ranges = 1, .num_ranges = 1,
...@@ -328,19 +328,19 @@ static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = { ...@@ -328,19 +328,19 @@ static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = {
}, },
[0x11] = { [0x11] = {
.num_ranges = 0, .num_ranges = 0,
.range = 0, .range = NULL,
}, },
[0x12] = { [0x12] = {
.num_ranges = 0, .num_ranges = 0,
.range = 0, .range = NULL,
}, },
[0x13] = { [0x13] = {
.num_ranges = 0, .num_ranges = 0,
.range = 0, .range = NULL,
}, },
[0x14] = { [0x14] = {
.num_ranges = 0, .num_ranges = 0,
.range = 0, .range = NULL,
}, },
[AB8500_OTP_EMUL] = { [AB8500_OTP_EMUL] = {
.num_ranges = 1, .num_ranges = 1,
......
/*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License v2
* Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/mfd/ab8500.h>
/*
* This funtion writes to any AB8500 registers using
* SPI protocol & before it writes it packs the data
* in the below 24 bit frame format
*
* *|------------------------------------|
* *| 23|22...18|17.......10|9|8|7......0|
* *| r/w bank adr data |
* * ------------------------------------
*
* This function shouldn't be called from interrupt
* context
*/
static int ab8500_spi_write(struct ab8500 *ab8500, u16 addr, u8 data)
{
struct spi_device *spi = container_of(ab8500->dev, struct spi_device,
dev);
unsigned long spi_data = addr << 10 | data;
struct spi_transfer xfer;
struct spi_message msg;
ab8500->tx_buf[0] = spi_data;
ab8500->rx_buf[0] = 0;
xfer.tx_buf = ab8500->tx_buf;
xfer.rx_buf = NULL;
xfer.len = sizeof(unsigned long);
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
return spi_sync(spi, &msg);
}
static int ab8500_spi_read(struct ab8500 *ab8500, u16 addr)
{
struct spi_device *spi = container_of(ab8500->dev, struct spi_device,
dev);
unsigned long spi_data = 1 << 23 | addr << 10;
struct spi_transfer xfer;
struct spi_message msg;
int ret;
ab8500->tx_buf[0] = spi_data;
ab8500->rx_buf[0] = 0;
xfer.tx_buf = ab8500->tx_buf;
xfer.rx_buf = ab8500->rx_buf;
xfer.len = sizeof(unsigned long);
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(spi, &msg);
if (!ret)
/*
* Only the 8 lowermost bytes are
* defined with value, the rest may
* vary depending on chip/board noise.
*/
ret = ab8500->rx_buf[0] & 0xFFU;
return ret;
}
static int __devinit ab8500_spi_probe(struct spi_device *spi)
{
struct ab8500 *ab8500;
int ret;
spi->bits_per_word = 24;
ret = spi_setup(spi);
if (ret < 0)
return ret;
ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL);
if (!ab8500)
return -ENOMEM;
ab8500->dev = &spi->dev;
ab8500->irq = spi->irq;
ab8500->read = ab8500_spi_read;
ab8500->write = ab8500_spi_write;
spi_set_drvdata(spi, ab8500);
ret = ab8500_init(ab8500);
if (ret)
kfree(ab8500);
return ret;
}
static int __devexit ab8500_spi_remove(struct spi_device *spi)
{
struct ab8500 *ab8500 = spi_get_drvdata(spi);
ab8500_exit(ab8500);
kfree(ab8500);
return 0;
}
static struct spi_driver ab8500_spi_driver = {
.driver = {
.name = "ab8500-spi",
.owner = THIS_MODULE,
},
.probe = ab8500_spi_probe,
.remove = __devexit_p(ab8500_spi_remove)
};
static int __init ab8500_spi_init(void)
{
return spi_register_driver(&ab8500_spi_driver);
}
subsys_initcall(ab8500_spi_init);
static void __exit ab8500_spi_exit(void)
{
spi_unregister_driver(&ab8500_spi_driver);
}
module_exit(ab8500_spi_exit);
MODULE_AUTHOR("Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com");
MODULE_DESCRIPTION("AB8500 SPI");
MODULE_LICENSE("GPL v2");
...@@ -57,7 +57,7 @@ struct asic3_clk { ...@@ -57,7 +57,7 @@ struct asic3_clk {
.rate = _rate, \ .rate = _rate, \
} }
struct asic3_clk asic3_clk_init[] __initdata = { static struct asic3_clk asic3_clk_init[] __initdata = {
INIT_CDEX(SPI, 0), INIT_CDEX(SPI, 0),
INIT_CDEX(OWM, 5000000), INIT_CDEX(OWM, 5000000),
INIT_CDEX(PWM0, 0), INIT_CDEX(PWM0, 0),
...@@ -102,7 +102,7 @@ static inline u32 asic3_read_register(struct asic3 *asic, ...@@ -102,7 +102,7 @@ static inline u32 asic3_read_register(struct asic3 *asic,
(reg >> asic->bus_shift)); (reg >> asic->bus_shift));
} }
void asic3_set_register(struct asic3 *asic, u32 reg, u32 bits, bool set) static void asic3_set_register(struct asic3 *asic, u32 reg, u32 bits, bool set)
{ {
unsigned long flags; unsigned long flags;
u32 val; u32 val;
...@@ -226,14 +226,14 @@ static inline int asic3_irq_to_index(struct asic3 *asic, int irq) ...@@ -226,14 +226,14 @@ static inline int asic3_irq_to_index(struct asic3 *asic, int irq)
return (irq - asic->irq_base) & 0xf; return (irq - asic->irq_base) & 0xf;
} }
static void asic3_mask_gpio_irq(unsigned int irq) static void asic3_mask_gpio_irq(struct irq_data *data)
{ {
struct asic3 *asic = get_irq_chip_data(irq); struct asic3 *asic = irq_data_get_irq_chip_data(data);
u32 val, bank, index; u32 val, bank, index;
unsigned long flags; unsigned long flags;
bank = asic3_irq_to_bank(asic, irq); bank = asic3_irq_to_bank(asic, data->irq);
index = asic3_irq_to_index(asic, irq); index = asic3_irq_to_index(asic, data->irq);
spin_lock_irqsave(&asic->lock, flags); spin_lock_irqsave(&asic->lock, flags);
val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK); val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK);
...@@ -242,9 +242,9 @@ static void asic3_mask_gpio_irq(unsigned int irq) ...@@ -242,9 +242,9 @@ static void asic3_mask_gpio_irq(unsigned int irq)
spin_unlock_irqrestore(&asic->lock, flags); spin_unlock_irqrestore(&asic->lock, flags);
} }
static void asic3_mask_irq(unsigned int irq) static void asic3_mask_irq(struct irq_data *data)
{ {
struct asic3 *asic = get_irq_chip_data(irq); struct asic3 *asic = irq_data_get_irq_chip_data(data);
int regval; int regval;
unsigned long flags; unsigned long flags;
...@@ -254,7 +254,7 @@ static void asic3_mask_irq(unsigned int irq) ...@@ -254,7 +254,7 @@ static void asic3_mask_irq(unsigned int irq)
ASIC3_INTR_INT_MASK); ASIC3_INTR_INT_MASK);
regval &= ~(ASIC3_INTMASK_MASK0 << regval &= ~(ASIC3_INTMASK_MASK0 <<
(irq - (asic->irq_base + ASIC3_NUM_GPIOS))); (data->irq - (asic->irq_base + ASIC3_NUM_GPIOS)));
asic3_write_register(asic, asic3_write_register(asic,
ASIC3_INTR_BASE + ASIC3_INTR_BASE +
...@@ -263,14 +263,14 @@ static void asic3_mask_irq(unsigned int irq) ...@@ -263,14 +263,14 @@ static void asic3_mask_irq(unsigned int irq)
spin_unlock_irqrestore(&asic->lock, flags); spin_unlock_irqrestore(&asic->lock, flags);
} }
static void asic3_unmask_gpio_irq(unsigned int irq) static void asic3_unmask_gpio_irq(struct irq_data *data)
{ {
struct asic3 *asic = get_irq_chip_data(irq); struct asic3 *asic = irq_data_get_irq_chip_data(data);
u32 val, bank, index; u32 val, bank, index;
unsigned long flags; unsigned long flags;
bank = asic3_irq_to_bank(asic, irq); bank = asic3_irq_to_bank(asic, data->irq);
index = asic3_irq_to_index(asic, irq); index = asic3_irq_to_index(asic, data->irq);
spin_lock_irqsave(&asic->lock, flags); spin_lock_irqsave(&asic->lock, flags);
val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK); val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK);
...@@ -279,9 +279,9 @@ static void asic3_unmask_gpio_irq(unsigned int irq) ...@@ -279,9 +279,9 @@ static void asic3_unmask_gpio_irq(unsigned int irq)
spin_unlock_irqrestore(&asic->lock, flags); spin_unlock_irqrestore(&asic->lock, flags);
} }
static void asic3_unmask_irq(unsigned int irq) static void asic3_unmask_irq(struct irq_data *data)
{ {
struct asic3 *asic = get_irq_chip_data(irq); struct asic3 *asic = irq_data_get_irq_chip_data(data);
int regval; int regval;
unsigned long flags; unsigned long flags;
...@@ -291,7 +291,7 @@ static void asic3_unmask_irq(unsigned int irq) ...@@ -291,7 +291,7 @@ static void asic3_unmask_irq(unsigned int irq)
ASIC3_INTR_INT_MASK); ASIC3_INTR_INT_MASK);
regval |= (ASIC3_INTMASK_MASK0 << regval |= (ASIC3_INTMASK_MASK0 <<
(irq - (asic->irq_base + ASIC3_NUM_GPIOS))); (data->irq - (asic->irq_base + ASIC3_NUM_GPIOS)));
asic3_write_register(asic, asic3_write_register(asic,
ASIC3_INTR_BASE + ASIC3_INTR_BASE +
...@@ -300,15 +300,15 @@ static void asic3_unmask_irq(unsigned int irq) ...@@ -300,15 +300,15 @@ static void asic3_unmask_irq(unsigned int irq)
spin_unlock_irqrestore(&asic->lock, flags); spin_unlock_irqrestore(&asic->lock, flags);
} }
static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) static int asic3_gpio_irq_type(struct irq_data *data, unsigned int type)
{ {
struct asic3 *asic = get_irq_chip_data(irq); struct asic3 *asic = irq_data_get_irq_chip_data(data);
u32 bank, index; u32 bank, index;
u16 trigger, level, edge, bit; u16 trigger, level, edge, bit;
unsigned long flags; unsigned long flags;
bank = asic3_irq_to_bank(asic, irq); bank = asic3_irq_to_bank(asic, data->irq);
index = asic3_irq_to_index(asic, irq); index = asic3_irq_to_index(asic, data->irq);
bit = 1<<index; bit = 1<<index;
spin_lock_irqsave(&asic->lock, flags); spin_lock_irqsave(&asic->lock, flags);
...@@ -318,7 +318,7 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) ...@@ -318,7 +318,7 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type)
bank + ASIC3_GPIO_EDGE_TRIGGER); bank + ASIC3_GPIO_EDGE_TRIGGER);
trigger = asic3_read_register(asic, trigger = asic3_read_register(asic,
bank + ASIC3_GPIO_TRIGGER_TYPE); bank + ASIC3_GPIO_TRIGGER_TYPE);
asic->irq_bothedge[(irq - asic->irq_base) >> 4] &= ~bit; asic->irq_bothedge[(data->irq - asic->irq_base) >> 4] &= ~bit;
if (type == IRQ_TYPE_EDGE_RISING) { if (type == IRQ_TYPE_EDGE_RISING) {
trigger |= bit; trigger |= bit;
...@@ -328,11 +328,11 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) ...@@ -328,11 +328,11 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type)
edge &= ~bit; edge &= ~bit;
} else if (type == IRQ_TYPE_EDGE_BOTH) { } else if (type == IRQ_TYPE_EDGE_BOTH) {
trigger |= bit; trigger |= bit;
if (asic3_gpio_get(&asic->gpio, irq - asic->irq_base)) if (asic3_gpio_get(&asic->gpio, data->irq - asic->irq_base))
edge &= ~bit; edge &= ~bit;
else else
edge |= bit; edge |= bit;
asic->irq_bothedge[(irq - asic->irq_base) >> 4] |= bit; asic->irq_bothedge[(data->irq - asic->irq_base) >> 4] |= bit;
} else if (type == IRQ_TYPE_LEVEL_LOW) { } else if (type == IRQ_TYPE_LEVEL_LOW) {
trigger &= ~bit; trigger &= ~bit;
level &= ~bit; level &= ~bit;
...@@ -359,17 +359,17 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) ...@@ -359,17 +359,17 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type)
static struct irq_chip asic3_gpio_irq_chip = { static struct irq_chip asic3_gpio_irq_chip = {
.name = "ASIC3-GPIO", .name = "ASIC3-GPIO",
.ack = asic3_mask_gpio_irq, .irq_ack = asic3_mask_gpio_irq,
.mask = asic3_mask_gpio_irq, .irq_mask = asic3_mask_gpio_irq,
.unmask = asic3_unmask_gpio_irq, .irq_unmask = asic3_unmask_gpio_irq,
.set_type = asic3_gpio_irq_type, .irq_set_type = asic3_gpio_irq_type,
}; };
static struct irq_chip asic3_irq_chip = { static struct irq_chip asic3_irq_chip = {
.name = "ASIC3", .name = "ASIC3",
.ack = asic3_mask_irq, .irq_ack = asic3_mask_irq,
.mask = asic3_mask_irq, .irq_mask = asic3_mask_irq,
.unmask = asic3_unmask_irq, .irq_unmask = asic3_unmask_irq,
}; };
static int __init asic3_irq_probe(struct platform_device *pdev) static int __init asic3_irq_probe(struct platform_device *pdev)
...@@ -635,7 +635,7 @@ static struct resource ds1wm_resources[] = { ...@@ -635,7 +635,7 @@ static struct resource ds1wm_resources[] = {
}, },
{ {
.start = ASIC3_IRQ_OWM, .start = ASIC3_IRQ_OWM,
.start = ASIC3_IRQ_OWM, .end = ASIC3_IRQ_OWM,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
}, },
}; };
......
/*
* cs5535-mfd.c - core MFD driver for CS5535/CS5536 southbridges
*
* The CS5535 and CS5536 has an ISA bridge on the PCI bus that is
* used for accessing GPIOs, MFGPTs, ACPI, etc. Each subdevice has
* an IO range that's specified in a single BAR. The BAR order is
* hardcoded in the CS553x specifications.
*
* Copyright (c) 2010 Andres Salomon <dilinger@queued.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/pci.h>
#define DRV_NAME "cs5535-mfd"
enum cs5535_mfd_bars {
SMB_BAR = 0,
GPIO_BAR = 1,
MFGPT_BAR = 2,
PMS_BAR = 4,
ACPI_BAR = 5,
NR_BARS,
};
static __devinitdata struct resource cs5535_mfd_resources[NR_BARS];
static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
{
.id = SMB_BAR,
.name = "cs5535-smb",
.num_resources = 1,
.resources = &cs5535_mfd_resources[SMB_BAR],
},
{
.id = GPIO_BAR,
.name = "cs5535-gpio",
.num_resources = 1,
.resources = &cs5535_mfd_resources[GPIO_BAR],
},
{
.id = MFGPT_BAR,
.name = "cs5535-mfgpt",
.num_resources = 1,
.resources = &cs5535_mfd_resources[MFGPT_BAR],
},
{
.id = PMS_BAR,
.name = "cs5535-pms",
.num_resources = 1,
.resources = &cs5535_mfd_resources[PMS_BAR],
},
{
.id = ACPI_BAR,
.name = "cs5535-acpi",
.num_resources = 1,
.resources = &cs5535_mfd_resources[ACPI_BAR],
},
};
static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int err, i;
err = pci_enable_device(pdev);
if (err)
return err;
/* fill in IO range for each cell; subdrivers handle the region */
for (i = 0; i < ARRAY_SIZE(cs5535_mfd_cells); i++) {
int bar = cs5535_mfd_cells[i].id;
struct resource *r = &cs5535_mfd_resources[bar];
r->flags = IORESOURCE_IO;
r->start = pci_resource_start(pdev, bar);
r->end = pci_resource_end(pdev, bar);
/* id is used for temporarily storing BAR; unset it now */
cs5535_mfd_cells[i].id = 0;
}
err = mfd_add_devices(&pdev->dev, -1, cs5535_mfd_cells,
ARRAY_SIZE(cs5535_mfd_cells), NULL, 0);
if (err) {
dev_err(&pdev->dev, "MFD add devices failed: %d\n", err);
goto err_disable;
}
dev_info(&pdev->dev, "%zu devices registered.\n",
ARRAY_SIZE(cs5535_mfd_cells));
return 0;
err_disable:
pci_disable_device(pdev);
return err;
}
static void __devexit cs5535_mfd_remove(struct pci_dev *pdev)
{
mfd_remove_devices(&pdev->dev);
pci_disable_device(pdev);
}
static struct pci_device_id cs5535_mfd_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, cs5535_mfd_pci_tbl);
static struct pci_driver cs5535_mfd_drv = {
.name = DRV_NAME,
.id_table = cs5535_mfd_pci_tbl,
.probe = cs5535_mfd_probe,
.remove = __devexit_p(cs5535_mfd_remove),
};
static int __init cs5535_mfd_init(void)
{
return pci_register_driver(&cs5535_mfd_drv);
}
static void __exit cs5535_mfd_exit(void)
{
pci_unregister_driver(&cs5535_mfd_drv);
}
module_init(cs5535_mfd_init);
module_exit(cs5535_mfd_exit);
MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
MODULE_DESCRIPTION("MFD driver for CS5535/CS5536 southbridge's ISA PCI device");
MODULE_LICENSE("GPL");
...@@ -144,26 +144,26 @@ int pcap_to_irq(struct pcap_chip *pcap, int irq) ...@@ -144,26 +144,26 @@ int pcap_to_irq(struct pcap_chip *pcap, int irq)
} }
EXPORT_SYMBOL_GPL(pcap_to_irq); EXPORT_SYMBOL_GPL(pcap_to_irq);
static void pcap_mask_irq(unsigned int irq) static void pcap_mask_irq(struct irq_data *d)
{ {
struct pcap_chip *pcap = get_irq_chip_data(irq); struct pcap_chip *pcap = irq_data_get_irq_chip_data(d);
pcap->msr |= 1 << irq_to_pcap(pcap, irq); pcap->msr |= 1 << irq_to_pcap(pcap, d->irq);
queue_work(pcap->workqueue, &pcap->msr_work); queue_work(pcap->workqueue, &pcap->msr_work);
} }
static void pcap_unmask_irq(unsigned int irq) static void pcap_unmask_irq(struct irq_data *d)
{ {
struct pcap_chip *pcap = get_irq_chip_data(irq); struct pcap_chip *pcap = irq_data_get_irq_chip_data(d);
pcap->msr &= ~(1 << irq_to_pcap(pcap, irq)); pcap->msr &= ~(1 << irq_to_pcap(pcap, d->irq));
queue_work(pcap->workqueue, &pcap->msr_work); queue_work(pcap->workqueue, &pcap->msr_work);
} }
static struct irq_chip pcap_irq_chip = { static struct irq_chip pcap_irq_chip = {
.name = "pcap", .name = "pcap",
.mask = pcap_mask_irq, .irq_mask = pcap_mask_irq,
.unmask = pcap_unmask_irq, .irq_unmask = pcap_unmask_irq,
}; };
static void pcap_msr_work(struct work_struct *work) static void pcap_msr_work(struct work_struct *work)
...@@ -199,8 +199,7 @@ static void pcap_isr_work(struct work_struct *work) ...@@ -199,8 +199,7 @@ static void pcap_isr_work(struct work_struct *work)
if (service & 1) { if (service & 1) {
struct irq_desc *desc = irq_to_desc(irq); struct irq_desc *desc = irq_to_desc(irq);
if (WARN(!desc, KERN_WARNING if (WARN(!desc, "Invalid PCAP IRQ %d\n", irq))
"Invalid PCAP IRQ %d\n", irq))
break; break;
if (desc->status & IRQ_DISABLED) if (desc->status & IRQ_DISABLED)
...@@ -218,7 +217,7 @@ static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc) ...@@ -218,7 +217,7 @@ static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc)
{ {
struct pcap_chip *pcap = get_irq_data(irq); struct pcap_chip *pcap = get_irq_data(irq);
desc->chip->ack(irq); desc->irq_data.chip->irq_ack(&desc->irq_data);
queue_work(pcap->workqueue, &pcap->isr_work); queue_work(pcap->workqueue, &pcap->isr_work);
return; return;
} }
...@@ -282,7 +281,7 @@ static irqreturn_t pcap_adc_irq(int irq, void *_pcap) ...@@ -282,7 +281,7 @@ static irqreturn_t pcap_adc_irq(int irq, void *_pcap)
mutex_lock(&pcap->adc_mutex); mutex_lock(&pcap->adc_mutex);
req = pcap->adc_queue[pcap->adc_head]; req = pcap->adc_queue[pcap->adc_head];
if (WARN(!req, KERN_WARNING "adc irq without pending request\n")) { if (WARN(!req, "adc irq without pending request\n")) {
mutex_unlock(&pcap->adc_mutex); mutex_unlock(&pcap->adc_mutex);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -70,31 +70,32 @@ static inline void ack_irqs(struct egpio_info *ei) ...@@ -70,31 +70,32 @@ static inline void ack_irqs(struct egpio_info *ei)
ei->ack_write, ei->ack_register << ei->bus_shift); ei->ack_write, ei->ack_register << ei->bus_shift);
} }
static void egpio_ack(unsigned int irq) static void egpio_ack(struct irq_data *data)
{ {
} }
/* There does not appear to be a way to proactively mask interrupts /* There does not appear to be a way to proactively mask interrupts
* on the egpio chip itself. So, we simply ignore interrupts that * on the egpio chip itself. So, we simply ignore interrupts that
* aren't desired. */ * aren't desired. */
static void egpio_mask(unsigned int irq) static void egpio_mask(struct irq_data *data)
{ {
struct egpio_info *ei = get_irq_chip_data(irq); struct egpio_info *ei = irq_data_get_irq_chip_data(data);
ei->irqs_enabled &= ~(1 << (irq - ei->irq_start)); ei->irqs_enabled &= ~(1 << (data->irq - ei->irq_start));
pr_debug("EGPIO mask %d %04x\n", irq, ei->irqs_enabled); pr_debug("EGPIO mask %d %04x\n", data->irq, ei->irqs_enabled);
} }
static void egpio_unmask(unsigned int irq)
static void egpio_unmask(struct irq_data *data)
{ {
struct egpio_info *ei = get_irq_chip_data(irq); struct egpio_info *ei = irq_data_get_irq_chip_data(data);
ei->irqs_enabled |= 1 << (irq - ei->irq_start); ei->irqs_enabled |= 1 << (data->irq - ei->irq_start);
pr_debug("EGPIO unmask %d %04x\n", irq, ei->irqs_enabled); pr_debug("EGPIO unmask %d %04x\n", data->irq, ei->irqs_enabled);
} }
static struct irq_chip egpio_muxed_chip = { static struct irq_chip egpio_muxed_chip = {
.name = "htc-egpio", .name = "htc-egpio",
.ack = egpio_ack, .irq_ack = egpio_ack,
.mask = egpio_mask, .irq_mask = egpio_mask,
.unmask = egpio_unmask, .irq_unmask = egpio_unmask,
}; };
static void egpio_handler(unsigned int irq, struct irq_desc *desc) static void egpio_handler(unsigned int irq, struct irq_desc *desc)
......
...@@ -82,25 +82,25 @@ struct htcpld_data { ...@@ -82,25 +82,25 @@ struct htcpld_data {
/* There does not appear to be a way to proactively mask interrupts /* There does not appear to be a way to proactively mask interrupts
* on the htcpld chip itself. So, we simply ignore interrupts that * on the htcpld chip itself. So, we simply ignore interrupts that
* aren't desired. */ * aren't desired. */
static void htcpld_mask(unsigned int irq) static void htcpld_mask(struct irq_data *data)
{ {
struct htcpld_chip *chip = get_irq_chip_data(irq); struct htcpld_chip *chip = irq_data_get_irq_chip_data(data);
chip->irqs_enabled &= ~(1 << (irq - chip->irq_start)); chip->irqs_enabled &= ~(1 << (data->irq - chip->irq_start));
pr_debug("HTCPLD mask %d %04x\n", irq, chip->irqs_enabled); pr_debug("HTCPLD mask %d %04x\n", data->irq, chip->irqs_enabled);
} }
static void htcpld_unmask(unsigned int irq) static void htcpld_unmask(struct irq_data *data)
{ {
struct htcpld_chip *chip = get_irq_chip_data(irq); struct htcpld_chip *chip = irq_data_get_irq_chip_data(data);
chip->irqs_enabled |= 1 << (irq - chip->irq_start); chip->irqs_enabled |= 1 << (data->irq - chip->irq_start);
pr_debug("HTCPLD unmask %d %04x\n", irq, chip->irqs_enabled); pr_debug("HTCPLD unmask %d %04x\n", data->irq, chip->irqs_enabled);
} }
static int htcpld_set_type(unsigned int irq, unsigned int flags) static int htcpld_set_type(struct irq_data *data, unsigned int flags)
{ {
struct irq_desc *d = irq_to_desc(irq); struct irq_desc *d = irq_to_desc(data->irq);
if (!d) { if (!d) {
pr_err("HTCPLD invalid IRQ: %d\n", irq); pr_err("HTCPLD invalid IRQ: %d\n", data->irq);
return -EINVAL; return -EINVAL;
} }
...@@ -119,9 +119,9 @@ static int htcpld_set_type(unsigned int irq, unsigned int flags) ...@@ -119,9 +119,9 @@ static int htcpld_set_type(unsigned int irq, unsigned int flags)
static struct irq_chip htcpld_muxed_chip = { static struct irq_chip htcpld_muxed_chip = {
.name = "htcpld", .name = "htcpld",
.mask = htcpld_mask, .irq_mask = htcpld_mask,
.unmask = htcpld_unmask, .irq_unmask = htcpld_unmask,
.set_type = htcpld_set_type, .irq_set_type = htcpld_set_type,
}; };
/* To properly dispatch IRQ events, we need to read from the /* To properly dispatch IRQ events, we need to read from the
...@@ -235,7 +235,7 @@ static irqreturn_t htcpld_handler(int irq, void *dev) ...@@ -235,7 +235,7 @@ static irqreturn_t htcpld_handler(int irq, void *dev)
* and that work is scheduled in the set routine. The kernel can then run * and that work is scheduled in the set routine. The kernel can then run
* the I2C functions, which will sleep, in process context. * the I2C functions, which will sleep, in process context.
*/ */
void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val) static void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val)
{ {
struct i2c_client *client; struct i2c_client *client;
struct htcpld_chip *chip_data; struct htcpld_chip *chip_data;
...@@ -259,7 +259,7 @@ void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val) ...@@ -259,7 +259,7 @@ void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val)
schedule_work(&(chip_data->set_val_work)); schedule_work(&(chip_data->set_val_work));
} }
void htcpld_chip_set_ni(struct work_struct *work) static void htcpld_chip_set_ni(struct work_struct *work)
{ {
struct htcpld_chip *chip_data; struct htcpld_chip *chip_data;
struct i2c_client *client; struct i2c_client *client;
...@@ -269,7 +269,7 @@ void htcpld_chip_set_ni(struct work_struct *work) ...@@ -269,7 +269,7 @@ void htcpld_chip_set_ni(struct work_struct *work)
i2c_smbus_read_byte_data(client, chip_data->cache_out); i2c_smbus_read_byte_data(client, chip_data->cache_out);
} }
int htcpld_chip_get(struct gpio_chip *chip, unsigned offset) static int htcpld_chip_get(struct gpio_chip *chip, unsigned offset)
{ {
struct htcpld_chip *chip_data; struct htcpld_chip *chip_data;
int val = 0; int val = 0;
...@@ -316,7 +316,7 @@ static int htcpld_direction_input(struct gpio_chip *chip, ...@@ -316,7 +316,7 @@ static int htcpld_direction_input(struct gpio_chip *chip,
return (offset < chip->ngpio) ? 0 : -EINVAL; return (offset < chip->ngpio) ? 0 : -EINVAL;
} }
int htcpld_chip_to_irq(struct gpio_chip *chip, unsigned offset) static int htcpld_chip_to_irq(struct gpio_chip *chip, unsigned offset)
{ {
struct htcpld_chip *chip_data; struct htcpld_chip *chip_data;
...@@ -328,7 +328,7 @@ int htcpld_chip_to_irq(struct gpio_chip *chip, unsigned offset) ...@@ -328,7 +328,7 @@ int htcpld_chip_to_irq(struct gpio_chip *chip, unsigned offset)
return -EINVAL; return -EINVAL;
} }
void htcpld_chip_reset(struct i2c_client *client) static void htcpld_chip_reset(struct i2c_client *client)
{ {
struct htcpld_chip *chip_data = i2c_get_clientdata(client); struct htcpld_chip *chip_data = i2c_get_clientdata(client);
if (!chip_data) if (!chip_data)
......
...@@ -84,31 +84,30 @@ static inline void jz4740_adc_irq_set_masked(struct jz4740_adc *adc, int irq, ...@@ -84,31 +84,30 @@ static inline void jz4740_adc_irq_set_masked(struct jz4740_adc *adc, int irq,
spin_unlock_irqrestore(&adc->lock, flags); spin_unlock_irqrestore(&adc->lock, flags);
} }
static void jz4740_adc_irq_mask(unsigned int irq) static void jz4740_adc_irq_mask(struct irq_data *data)
{ {
struct jz4740_adc *adc = get_irq_chip_data(irq); struct jz4740_adc *adc = irq_data_get_irq_chip_data(data);
jz4740_adc_irq_set_masked(adc, irq, true); jz4740_adc_irq_set_masked(adc, data->irq, true);
} }
static void jz4740_adc_irq_unmask(unsigned int irq) static void jz4740_adc_irq_unmask(struct irq_data *data)
{ {
struct jz4740_adc *adc = get_irq_chip_data(irq); struct jz4740_adc *adc = irq_data_get_irq_chip_data(data);
jz4740_adc_irq_set_masked(adc, irq, false); jz4740_adc_irq_set_masked(adc, data->irq, false);
} }
static void jz4740_adc_irq_ack(unsigned int irq) static void jz4740_adc_irq_ack(struct irq_data *data)
{ {
struct jz4740_adc *adc = get_irq_chip_data(irq); struct jz4740_adc *adc = irq_data_get_irq_chip_data(data);
unsigned int irq = data->irq - adc->irq_base;
irq -= adc->irq_base;
writeb(BIT(irq), adc->base + JZ_REG_ADC_STATUS); writeb(BIT(irq), adc->base + JZ_REG_ADC_STATUS);
} }
static struct irq_chip jz4740_adc_irq_chip = { static struct irq_chip jz4740_adc_irq_chip = {
.name = "jz4740-adc", .name = "jz4740-adc",
.mask = jz4740_adc_irq_mask, .irq_mask = jz4740_adc_irq_mask,
.unmask = jz4740_adc_irq_unmask, .irq_unmask = jz4740_adc_irq_unmask,
.ack = jz4740_adc_irq_ack, .irq_ack = jz4740_adc_irq_ack,
}; };
static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc) static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc)
......
...@@ -407,16 +407,16 @@ static irqreturn_t max8925_tsc_irq(int irq, void *data) ...@@ -407,16 +407,16 @@ static irqreturn_t max8925_tsc_irq(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void max8925_irq_lock(unsigned int irq) static void max8925_irq_lock(struct irq_data *data)
{ {
struct max8925_chip *chip = get_irq_chip_data(irq); struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
mutex_lock(&chip->irq_lock); mutex_lock(&chip->irq_lock);
} }
static void max8925_irq_sync_unlock(unsigned int irq) static void max8925_irq_sync_unlock(struct irq_data *data)
{ {
struct max8925_chip *chip = get_irq_chip_data(irq); struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
struct max8925_irq_data *irq_data; struct max8925_irq_data *irq_data;
static unsigned char cache_chg[2] = {0xff, 0xff}; static unsigned char cache_chg[2] = {0xff, 0xff};
static unsigned char cache_on[2] = {0xff, 0xff}; static unsigned char cache_on[2] = {0xff, 0xff};
...@@ -492,25 +492,25 @@ static void max8925_irq_sync_unlock(unsigned int irq) ...@@ -492,25 +492,25 @@ static void max8925_irq_sync_unlock(unsigned int irq)
mutex_unlock(&chip->irq_lock); mutex_unlock(&chip->irq_lock);
} }
static void max8925_irq_enable(unsigned int irq) static void max8925_irq_enable(struct irq_data *data)
{ {
struct max8925_chip *chip = get_irq_chip_data(irq); struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
max8925_irqs[irq - chip->irq_base].enable max8925_irqs[data->irq - chip->irq_base].enable
= max8925_irqs[irq - chip->irq_base].offs; = max8925_irqs[data->irq - chip->irq_base].offs;
} }
static void max8925_irq_disable(unsigned int irq) static void max8925_irq_disable(struct irq_data *data)
{ {
struct max8925_chip *chip = get_irq_chip_data(irq); struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
max8925_irqs[irq - chip->irq_base].enable = 0; max8925_irqs[data->irq - chip->irq_base].enable = 0;
} }
static struct irq_chip max8925_irq_chip = { static struct irq_chip max8925_irq_chip = {
.name = "max8925", .name = "max8925",
.bus_lock = max8925_irq_lock, .irq_bus_lock = max8925_irq_lock,
.bus_sync_unlock = max8925_irq_sync_unlock, .irq_bus_sync_unlock = max8925_irq_sync_unlock,
.enable = max8925_irq_enable, .irq_enable = max8925_irq_enable,
.disable = max8925_irq_disable, .irq_disable = max8925_irq_disable,
}; };
static int max8925_irq_init(struct max8925_chip *chip, int irq, static int max8925_irq_init(struct max8925_chip *chip, int irq,
......
...@@ -102,16 +102,16 @@ irq_to_max8998_irq(struct max8998_dev *max8998, int irq) ...@@ -102,16 +102,16 @@ irq_to_max8998_irq(struct max8998_dev *max8998, int irq)
return &max8998_irqs[irq - max8998->irq_base]; return &max8998_irqs[irq - max8998->irq_base];
} }
static void max8998_irq_lock(unsigned int irq) static void max8998_irq_lock(struct irq_data *data)
{ {
struct max8998_dev *max8998 = get_irq_chip_data(irq); struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data);
mutex_lock(&max8998->irqlock); mutex_lock(&max8998->irqlock);
} }
static void max8998_irq_sync_unlock(unsigned int irq) static void max8998_irq_sync_unlock(struct irq_data *data)
{ {
struct max8998_dev *max8998 = get_irq_chip_data(irq); struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data);
int i; int i;
for (i = 0; i < ARRAY_SIZE(max8998->irq_masks_cur); i++) { for (i = 0; i < ARRAY_SIZE(max8998->irq_masks_cur); i++) {
...@@ -129,28 +129,30 @@ static void max8998_irq_sync_unlock(unsigned int irq) ...@@ -129,28 +129,30 @@ static void max8998_irq_sync_unlock(unsigned int irq)
mutex_unlock(&max8998->irqlock); mutex_unlock(&max8998->irqlock);
} }
static void max8998_irq_unmask(unsigned int irq) static void max8998_irq_unmask(struct irq_data *data)
{ {
struct max8998_dev *max8998 = get_irq_chip_data(irq); struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data);
struct max8998_irq_data *irq_data = irq_to_max8998_irq(max8998, irq); struct max8998_irq_data *irq_data = irq_to_max8998_irq(max8998,
data->irq);
max8998->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; max8998->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
} }
static void max8998_irq_mask(unsigned int irq) static void max8998_irq_mask(struct irq_data *data)
{ {
struct max8998_dev *max8998 = get_irq_chip_data(irq); struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data);
struct max8998_irq_data *irq_data = irq_to_max8998_irq(max8998, irq); struct max8998_irq_data *irq_data = irq_to_max8998_irq(max8998,
data->irq);
max8998->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; max8998->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
} }
static struct irq_chip max8998_irq_chip = { static struct irq_chip max8998_irq_chip = {
.name = "max8998", .name = "max8998",
.bus_lock = max8998_irq_lock, .irq_bus_lock = max8998_irq_lock,
.bus_sync_unlock = max8998_irq_sync_unlock, .irq_bus_sync_unlock = max8998_irq_sync_unlock,
.mask = max8998_irq_mask, .irq_mask = max8998_irq_mask,
.unmask = max8998_irq_unmask, .irq_unmask = max8998_irq_unmask,
}; };
static irqreturn_t max8998_irq_thread(int irq, void *data) static irqreturn_t max8998_irq_thread(int irq, void *data)
...@@ -181,6 +183,13 @@ static irqreturn_t max8998_irq_thread(int irq, void *data) ...@@ -181,6 +183,13 @@ static irqreturn_t max8998_irq_thread(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
int max8998_irq_resume(struct max8998_dev *max8998)
{
if (max8998->irq && max8998->irq_base)
max8998_irq_thread(max8998->irq_base, max8998);
return 0;
}
int max8998_irq_init(struct max8998_dev *max8998) int max8998_irq_init(struct max8998_dev *max8998)
{ {
int i; int i;
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/mfd/max8998.h> #include <linux/mfd/max8998.h>
...@@ -40,6 +42,14 @@ static struct mfd_cell max8998_devs[] = { ...@@ -40,6 +42,14 @@ static struct mfd_cell max8998_devs[] = {
}, },
}; };
static struct mfd_cell lp3974_devs[] = {
{
.name = "lp3974-pmic",
}, {
.name = "lp3974-rtc",
},
};
int max8998_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest) int max8998_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
{ {
struct max8998_dev *max8998 = i2c_get_clientdata(i2c); struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
...@@ -135,6 +145,7 @@ static int max8998_i2c_probe(struct i2c_client *i2c, ...@@ -135,6 +145,7 @@ static int max8998_i2c_probe(struct i2c_client *i2c,
if (pdata) { if (pdata) {
max8998->ono = pdata->ono; max8998->ono = pdata->ono;
max8998->irq_base = pdata->irq_base; max8998->irq_base = pdata->irq_base;
max8998->wakeup = pdata->wakeup;
} }
mutex_init(&max8998->iolock); mutex_init(&max8998->iolock);
...@@ -143,9 +154,23 @@ static int max8998_i2c_probe(struct i2c_client *i2c, ...@@ -143,9 +154,23 @@ static int max8998_i2c_probe(struct i2c_client *i2c,
max8998_irq_init(max8998); max8998_irq_init(max8998);
pm_runtime_set_active(max8998->dev);
switch (id->driver_data) {
case TYPE_LP3974:
ret = mfd_add_devices(max8998->dev, -1,
lp3974_devs, ARRAY_SIZE(lp3974_devs),
NULL, 0);
break;
case TYPE_MAX8998:
ret = mfd_add_devices(max8998->dev, -1, ret = mfd_add_devices(max8998->dev, -1,
max8998_devs, ARRAY_SIZE(max8998_devs), max8998_devs, ARRAY_SIZE(max8998_devs),
NULL, 0); NULL, 0);
break;
default:
ret = -EINVAL;
}
if (ret < 0) if (ret < 0)
goto err; goto err;
...@@ -178,10 +203,113 @@ static const struct i2c_device_id max8998_i2c_id[] = { ...@@ -178,10 +203,113 @@ static const struct i2c_device_id max8998_i2c_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, max8998_i2c_id); MODULE_DEVICE_TABLE(i2c, max8998_i2c_id);
static int max8998_suspend(struct device *dev)
{
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
if (max8998->wakeup)
set_irq_wake(max8998->irq, 1);
return 0;
}
static int max8998_resume(struct device *dev)
{
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
if (max8998->wakeup)
set_irq_wake(max8998->irq, 0);
/*
* In LP3974, if IRQ registers are not "read & clear"
* when it's set during sleep, the interrupt becomes
* disabled.
*/
return max8998_irq_resume(i2c_get_clientdata(i2c));
}
struct max8998_reg_dump {
u8 addr;
u8 val;
};
#define SAVE_ITEM(x) { .addr = (x), .val = 0x0, }
struct max8998_reg_dump max8998_dump[] = {
SAVE_ITEM(MAX8998_REG_IRQM1),
SAVE_ITEM(MAX8998_REG_IRQM2),
SAVE_ITEM(MAX8998_REG_IRQM3),
SAVE_ITEM(MAX8998_REG_IRQM4),
SAVE_ITEM(MAX8998_REG_STATUSM1),
SAVE_ITEM(MAX8998_REG_STATUSM2),
SAVE_ITEM(MAX8998_REG_CHGR1),
SAVE_ITEM(MAX8998_REG_CHGR2),
SAVE_ITEM(MAX8998_REG_LDO_ACTIVE_DISCHARGE1),
SAVE_ITEM(MAX8998_REG_LDO_ACTIVE_DISCHARGE1),
SAVE_ITEM(MAX8998_REG_BUCK_ACTIVE_DISCHARGE3),
SAVE_ITEM(MAX8998_REG_ONOFF1),
SAVE_ITEM(MAX8998_REG_ONOFF2),
SAVE_ITEM(MAX8998_REG_ONOFF3),
SAVE_ITEM(MAX8998_REG_ONOFF4),
SAVE_ITEM(MAX8998_REG_BUCK1_VOLTAGE1),
SAVE_ITEM(MAX8998_REG_BUCK1_VOLTAGE2),
SAVE_ITEM(MAX8998_REG_BUCK1_VOLTAGE3),
SAVE_ITEM(MAX8998_REG_BUCK1_VOLTAGE4),
SAVE_ITEM(MAX8998_REG_BUCK2_VOLTAGE1),
SAVE_ITEM(MAX8998_REG_BUCK2_VOLTAGE2),
SAVE_ITEM(MAX8998_REG_LDO2_LDO3),
SAVE_ITEM(MAX8998_REG_LDO4),
SAVE_ITEM(MAX8998_REG_LDO5),
SAVE_ITEM(MAX8998_REG_LDO6),
SAVE_ITEM(MAX8998_REG_LDO7),
SAVE_ITEM(MAX8998_REG_LDO8_LDO9),
SAVE_ITEM(MAX8998_REG_LDO10_LDO11),
SAVE_ITEM(MAX8998_REG_LDO12),
SAVE_ITEM(MAX8998_REG_LDO13),
SAVE_ITEM(MAX8998_REG_LDO14),
SAVE_ITEM(MAX8998_REG_LDO15),
SAVE_ITEM(MAX8998_REG_LDO16),
SAVE_ITEM(MAX8998_REG_LDO17),
SAVE_ITEM(MAX8998_REG_BKCHR),
SAVE_ITEM(MAX8998_REG_LBCNFG1),
SAVE_ITEM(MAX8998_REG_LBCNFG2),
};
/* Save registers before hibernation */
static int max8998_freeze(struct device *dev)
{
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
int i;
for (i = 0; i < ARRAY_SIZE(max8998_dump); i++)
max8998_read_reg(i2c, max8998_dump[i].addr,
&max8998_dump[i].val);
return 0;
}
/* Restore registers after hibernation */
static int max8998_restore(struct device *dev)
{
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
int i;
for (i = 0; i < ARRAY_SIZE(max8998_dump); i++)
max8998_write_reg(i2c, max8998_dump[i].addr,
max8998_dump[i].val);
return 0;
}
const struct dev_pm_ops max8998_pm = {
.suspend = max8998_suspend,
.resume = max8998_resume,
.freeze = max8998_freeze,
.restore = max8998_restore,
};
static struct i2c_driver max8998_i2c_driver = { static struct i2c_driver max8998_i2c_driver = {
.driver = { .driver = {
.name = "max8998", .name = "max8998",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &max8998_pm,
}, },
.probe = max8998_i2c_probe, .probe = max8998_i2c_probe,
.remove = max8998_i2c_remove, .remove = max8998_i2c_remove,
......
...@@ -749,7 +749,7 @@ static int mc13xxx_probe(struct spi_device *spi) ...@@ -749,7 +749,7 @@ static int mc13xxx_probe(struct spi_device *spi)
if (ret) { if (ret) {
err_mask: err_mask:
err_revision: err_revision:
mutex_unlock(&mc13xxx->lock); mc13xxx_unlock(mc13xxx);
dev_set_drvdata(&spi->dev, NULL); dev_set_drvdata(&spi->dev, NULL);
kfree(mc13xxx); kfree(mc13xxx);
return ret; return ret;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h> #include <linux/slab.h>
static int mfd_add_device(struct device *parent, int id, static int mfd_add_device(struct device *parent, int id,
...@@ -82,6 +83,9 @@ static int mfd_add_device(struct device *parent, int id, ...@@ -82,6 +83,9 @@ static int mfd_add_device(struct device *parent, int id,
if (ret) if (ret)
goto fail_res; goto fail_res;
if (cell->pm_runtime_no_callbacks)
pm_runtime_no_callbacks(&pdev->dev);
kfree(res); kfree(res);
return 0; return 0;
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include <linux/sm501-regs.h> #include <linux/sm501-regs.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <asm/io.h> #include <linux/io.h>
struct sm501_device { struct sm501_device {
struct list_head list; struct list_head list;
...@@ -745,11 +745,8 @@ static int sm501_register_device(struct sm501_devdata *sm, ...@@ -745,11 +745,8 @@ static int sm501_register_device(struct sm501_devdata *sm,
int ret; int ret;
for (ptr = 0; ptr < pdev->num_resources; ptr++) { for (ptr = 0; ptr < pdev->num_resources; ptr++) {
printk(KERN_DEBUG "%s[%d] flags %08lx: %08llx..%08llx\n", printk(KERN_DEBUG "%s[%d] %pR\n",
pdev->name, ptr, pdev->name, ptr, &pdev->resource[ptr]);
pdev->resource[ptr].flags,
(unsigned long long)pdev->resource[ptr].start,
(unsigned long long)pdev->resource[ptr].end);
} }
ret = platform_device_register(pdev); ret = platform_device_register(pdev);
......
...@@ -699,16 +699,16 @@ static irqreturn_t stmpe_irq(int irq, void *data) ...@@ -699,16 +699,16 @@ static irqreturn_t stmpe_irq(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void stmpe_irq_lock(unsigned int irq) static void stmpe_irq_lock(struct irq_data *data)
{ {
struct stmpe *stmpe = get_irq_chip_data(irq); struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
mutex_lock(&stmpe->irq_lock); mutex_lock(&stmpe->irq_lock);
} }
static void stmpe_irq_sync_unlock(unsigned int irq) static void stmpe_irq_sync_unlock(struct irq_data *data)
{ {
struct stmpe *stmpe = get_irq_chip_data(irq); struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
struct stmpe_variant_info *variant = stmpe->variant; struct stmpe_variant_info *variant = stmpe->variant;
int num = DIV_ROUND_UP(variant->num_irqs, 8); int num = DIV_ROUND_UP(variant->num_irqs, 8);
int i; int i;
...@@ -727,20 +727,20 @@ static void stmpe_irq_sync_unlock(unsigned int irq) ...@@ -727,20 +727,20 @@ static void stmpe_irq_sync_unlock(unsigned int irq)
mutex_unlock(&stmpe->irq_lock); mutex_unlock(&stmpe->irq_lock);
} }
static void stmpe_irq_mask(unsigned int irq) static void stmpe_irq_mask(struct irq_data *data)
{ {
struct stmpe *stmpe = get_irq_chip_data(irq); struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
int offset = irq - stmpe->irq_base; int offset = data->irq - stmpe->irq_base;
int regoffset = offset / 8; int regoffset = offset / 8;
int mask = 1 << (offset % 8); int mask = 1 << (offset % 8);
stmpe->ier[regoffset] &= ~mask; stmpe->ier[regoffset] &= ~mask;
} }
static void stmpe_irq_unmask(unsigned int irq) static void stmpe_irq_unmask(struct irq_data *data)
{ {
struct stmpe *stmpe = get_irq_chip_data(irq); struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
int offset = irq - stmpe->irq_base; int offset = data->irq - stmpe->irq_base;
int regoffset = offset / 8; int regoffset = offset / 8;
int mask = 1 << (offset % 8); int mask = 1 << (offset % 8);
...@@ -749,10 +749,10 @@ static void stmpe_irq_unmask(unsigned int irq) ...@@ -749,10 +749,10 @@ static void stmpe_irq_unmask(unsigned int irq)
static struct irq_chip stmpe_irq_chip = { static struct irq_chip stmpe_irq_chip = {
.name = "stmpe", .name = "stmpe",
.bus_lock = stmpe_irq_lock, .irq_bus_lock = stmpe_irq_lock,
.bus_sync_unlock = stmpe_irq_sync_unlock, .irq_bus_sync_unlock = stmpe_irq_sync_unlock,
.mask = stmpe_irq_mask, .irq_mask = stmpe_irq_mask,
.unmask = stmpe_irq_unmask, .irq_unmask = stmpe_irq_unmask,
}; };
static int __devinit stmpe_irq_init(struct stmpe *stmpe) static int __devinit stmpe_irq_init(struct stmpe *stmpe)
......
...@@ -199,37 +199,37 @@ static void t7l66xb_irq(unsigned int irq, struct irq_desc *desc) ...@@ -199,37 +199,37 @@ static void t7l66xb_irq(unsigned int irq, struct irq_desc *desc)
generic_handle_irq(irq_base + i); generic_handle_irq(irq_base + i);
} }
static void t7l66xb_irq_mask(unsigned int irq) static void t7l66xb_irq_mask(struct irq_data *data)
{ {
struct t7l66xb *t7l66xb = get_irq_chip_data(irq); struct t7l66xb *t7l66xb = irq_data_get_irq_chip_data(data);
unsigned long flags; unsigned long flags;
u8 imr; u8 imr;
spin_lock_irqsave(&t7l66xb->lock, flags); spin_lock_irqsave(&t7l66xb->lock, flags);
imr = tmio_ioread8(t7l66xb->scr + SCR_IMR); imr = tmio_ioread8(t7l66xb->scr + SCR_IMR);
imr |= 1 << (irq - t7l66xb->irq_base); imr |= 1 << (data->irq - t7l66xb->irq_base);
tmio_iowrite8(imr, t7l66xb->scr + SCR_IMR); tmio_iowrite8(imr, t7l66xb->scr + SCR_IMR);
spin_unlock_irqrestore(&t7l66xb->lock, flags); spin_unlock_irqrestore(&t7l66xb->lock, flags);
} }
static void t7l66xb_irq_unmask(unsigned int irq) static void t7l66xb_irq_unmask(struct irq_data *data)
{ {
struct t7l66xb *t7l66xb = get_irq_chip_data(irq); struct t7l66xb *t7l66xb = irq_data_get_irq_chip_data(data);
unsigned long flags; unsigned long flags;
u8 imr; u8 imr;
spin_lock_irqsave(&t7l66xb->lock, flags); spin_lock_irqsave(&t7l66xb->lock, flags);
imr = tmio_ioread8(t7l66xb->scr + SCR_IMR); imr = tmio_ioread8(t7l66xb->scr + SCR_IMR);
imr &= ~(1 << (irq - t7l66xb->irq_base)); imr &= ~(1 << (data->irq - t7l66xb->irq_base));
tmio_iowrite8(imr, t7l66xb->scr + SCR_IMR); tmio_iowrite8(imr, t7l66xb->scr + SCR_IMR);
spin_unlock_irqrestore(&t7l66xb->lock, flags); spin_unlock_irqrestore(&t7l66xb->lock, flags);
} }
static struct irq_chip t7l66xb_chip = { static struct irq_chip t7l66xb_chip = {
.name = "t7l66xb", .name = "t7l66xb",
.ack = t7l66xb_irq_mask, .irq_ack = t7l66xb_irq_mask,
.mask = t7l66xb_irq_mask, .irq_mask = t7l66xb_irq_mask,
.unmask = t7l66xb_irq_unmask, .irq_unmask = t7l66xb_irq_unmask,
}; };
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
......
...@@ -527,41 +527,41 @@ tc6393xb_irq(unsigned int irq, struct irq_desc *desc) ...@@ -527,41 +527,41 @@ tc6393xb_irq(unsigned int irq, struct irq_desc *desc)
} }
} }
static void tc6393xb_irq_ack(unsigned int irq) static void tc6393xb_irq_ack(struct irq_data *data)
{ {
} }
static void tc6393xb_irq_mask(unsigned int irq) static void tc6393xb_irq_mask(struct irq_data *data)
{ {
struct tc6393xb *tc6393xb = get_irq_chip_data(irq); struct tc6393xb *tc6393xb = irq_data_get_irq_chip_data(data);
unsigned long flags; unsigned long flags;
u8 imr; u8 imr;
spin_lock_irqsave(&tc6393xb->lock, flags); spin_lock_irqsave(&tc6393xb->lock, flags);
imr = tmio_ioread8(tc6393xb->scr + SCR_IMR); imr = tmio_ioread8(tc6393xb->scr + SCR_IMR);
imr |= 1 << (irq - tc6393xb->irq_base); imr |= 1 << (data->irq - tc6393xb->irq_base);
tmio_iowrite8(imr, tc6393xb->scr + SCR_IMR); tmio_iowrite8(imr, tc6393xb->scr + SCR_IMR);
spin_unlock_irqrestore(&tc6393xb->lock, flags); spin_unlock_irqrestore(&tc6393xb->lock, flags);
} }
static void tc6393xb_irq_unmask(unsigned int irq) static void tc6393xb_irq_unmask(struct irq_data *data)
{ {
struct tc6393xb *tc6393xb = get_irq_chip_data(irq); struct tc6393xb *tc6393xb = irq_data_get_irq_chip_data(data);
unsigned long flags; unsigned long flags;
u8 imr; u8 imr;
spin_lock_irqsave(&tc6393xb->lock, flags); spin_lock_irqsave(&tc6393xb->lock, flags);
imr = tmio_ioread8(tc6393xb->scr + SCR_IMR); imr = tmio_ioread8(tc6393xb->scr + SCR_IMR);
imr &= ~(1 << (irq - tc6393xb->irq_base)); imr &= ~(1 << (data->irq - tc6393xb->irq_base));
tmio_iowrite8(imr, tc6393xb->scr + SCR_IMR); tmio_iowrite8(imr, tc6393xb->scr + SCR_IMR);
spin_unlock_irqrestore(&tc6393xb->lock, flags); spin_unlock_irqrestore(&tc6393xb->lock, flags);
} }
static struct irq_chip tc6393xb_chip = { static struct irq_chip tc6393xb_chip = {
.name = "tc6393xb", .name = "tc6393xb",
.ack = tc6393xb_irq_ack, .irq_ack = tc6393xb_irq_ack,
.mask = tc6393xb_irq_mask, .irq_mask = tc6393xb_irq_mask,
.unmask = tc6393xb_irq_unmask, .irq_unmask = tc6393xb_irq_unmask,
}; };
static void tc6393xb_attach_irq(struct platform_device *dev) static void tc6393xb_attach_irq(struct platform_device *dev)
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#include <linux/i2c/tps65010.h> #include <linux/i2c/tps65010.h>
#include <asm/gpio.h> #include <linux/gpio.h>
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
......
...@@ -46,8 +46,6 @@ ...@@ -46,8 +46,6 @@
/* device id */ /* device id */
#define TPS6586X_VERSIONCRC 0xcd #define TPS6586X_VERSIONCRC 0xcd
#define TPS658621A_VERSIONCRC 0x15
#define TPS658621C_VERSIONCRC 0x2c
struct tps6586x_irq_data { struct tps6586x_irq_data {
u8 mask_reg; u8 mask_reg;
...@@ -325,37 +323,37 @@ static int tps6586x_remove_subdevs(struct tps6586x *tps6586x) ...@@ -325,37 +323,37 @@ static int tps6586x_remove_subdevs(struct tps6586x *tps6586x)
return device_for_each_child(tps6586x->dev, NULL, __remove_subdev); return device_for_each_child(tps6586x->dev, NULL, __remove_subdev);
} }
static void tps6586x_irq_lock(unsigned int irq) static void tps6586x_irq_lock(struct irq_data *data)
{ {
struct tps6586x *tps6586x = get_irq_chip_data(irq); struct tps6586x *tps6586x = irq_data_get_irq_chip_data(data);
mutex_lock(&tps6586x->irq_lock); mutex_lock(&tps6586x->irq_lock);
} }
static void tps6586x_irq_enable(unsigned int irq) static void tps6586x_irq_enable(struct irq_data *irq_data)
{ {
struct tps6586x *tps6586x = get_irq_chip_data(irq); struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data);
unsigned int __irq = irq - tps6586x->irq_base; unsigned int __irq = irq_data->irq - tps6586x->irq_base;
const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq]; const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq];
tps6586x->mask_reg[data->mask_reg] &= ~data->mask_mask; tps6586x->mask_reg[data->mask_reg] &= ~data->mask_mask;
tps6586x->irq_en |= (1 << __irq); tps6586x->irq_en |= (1 << __irq);
} }
static void tps6586x_irq_disable(unsigned int irq) static void tps6586x_irq_disable(struct irq_data *irq_data)
{ {
struct tps6586x *tps6586x = get_irq_chip_data(irq); struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data);
unsigned int __irq = irq - tps6586x->irq_base; unsigned int __irq = irq_data->irq - tps6586x->irq_base;
const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq]; const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq];
tps6586x->mask_reg[data->mask_reg] |= data->mask_mask; tps6586x->mask_reg[data->mask_reg] |= data->mask_mask;
tps6586x->irq_en &= ~(1 << __irq); tps6586x->irq_en &= ~(1 << __irq);
} }
static void tps6586x_irq_sync_unlock(unsigned int irq) static void tps6586x_irq_sync_unlock(struct irq_data *data)
{ {
struct tps6586x *tps6586x = get_irq_chip_data(irq); struct tps6586x *tps6586x = irq_data_get_irq_chip_data(data);
int i; int i;
for (i = 0; i < ARRAY_SIZE(tps6586x->mask_reg); i++) { for (i = 0; i < ARRAY_SIZE(tps6586x->mask_reg); i++) {
...@@ -421,10 +419,10 @@ static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq, ...@@ -421,10 +419,10 @@ static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
tps6586x->irq_base = irq_base; tps6586x->irq_base = irq_base;
tps6586x->irq_chip.name = "tps6586x"; tps6586x->irq_chip.name = "tps6586x";
tps6586x->irq_chip.enable = tps6586x_irq_enable; tps6586x->irq_chip.irq_enable = tps6586x_irq_enable;
tps6586x->irq_chip.disable = tps6586x_irq_disable; tps6586x->irq_chip.irq_disable = tps6586x_irq_disable;
tps6586x->irq_chip.bus_lock = tps6586x_irq_lock; tps6586x->irq_chip.irq_bus_lock = tps6586x_irq_lock;
tps6586x->irq_chip.bus_sync_unlock = tps6586x_irq_sync_unlock; tps6586x->irq_chip.irq_bus_sync_unlock = tps6586x_irq_sync_unlock;
for (i = 0; i < ARRAY_SIZE(tps6586x_irqs); i++) { for (i = 0; i < ARRAY_SIZE(tps6586x_irqs); i++) {
int __irq = i + tps6586x->irq_base; int __irq = i + tps6586x->irq_base;
...@@ -498,11 +496,7 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client, ...@@ -498,11 +496,7 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
return -EIO; return -EIO;
} }
if ((ret != TPS658621A_VERSIONCRC) && dev_info(&client->dev, "VERSIONCRC is %02x\n", ret);
(ret != TPS658621C_VERSIONCRC)) {
dev_err(&client->dev, "Unsupported chip ID: %x\n", ret);
return -ENODEV;
}
tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL); tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL);
if (tps6586x == NULL) if (tps6586x == NULL)
......
...@@ -1003,7 +1003,7 @@ static int twl_remove(struct i2c_client *client) ...@@ -1003,7 +1003,7 @@ static int twl_remove(struct i2c_client *client)
} }
/* NOTE: this driver only handles a single twl4030/tps659x0 chip */ /* NOTE: this driver only handles a single twl4030/tps659x0 chip */
static int __init static int __devinit
twl_probe(struct i2c_client *client, const struct i2c_device_id *id) twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
{ {
int status; int status;
......
...@@ -599,38 +599,38 @@ static void twl4030_sih_do_edge(struct work_struct *work) ...@@ -599,38 +599,38 @@ static void twl4030_sih_do_edge(struct work_struct *work)
* completion, potentially including some re-ordering, of these requests. * completion, potentially including some re-ordering, of these requests.
*/ */
static void twl4030_sih_mask(unsigned irq) static void twl4030_sih_mask(struct irq_data *data)
{ {
struct sih_agent *sih = get_irq_chip_data(irq); struct sih_agent *sih = irq_data_get_irq_chip_data(data);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&sih_agent_lock, flags); spin_lock_irqsave(&sih_agent_lock, flags);
sih->imr |= BIT(irq - sih->irq_base); sih->imr |= BIT(data->irq - sih->irq_base);
sih->imr_change_pending = true; sih->imr_change_pending = true;
queue_work(wq, &sih->mask_work); queue_work(wq, &sih->mask_work);
spin_unlock_irqrestore(&sih_agent_lock, flags); spin_unlock_irqrestore(&sih_agent_lock, flags);
} }
static void twl4030_sih_unmask(unsigned irq) static void twl4030_sih_unmask(struct irq_data *data)
{ {
struct sih_agent *sih = get_irq_chip_data(irq); struct sih_agent *sih = irq_data_get_irq_chip_data(data);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&sih_agent_lock, flags); spin_lock_irqsave(&sih_agent_lock, flags);
sih->imr &= ~BIT(irq - sih->irq_base); sih->imr &= ~BIT(data->irq - sih->irq_base);
sih->imr_change_pending = true; sih->imr_change_pending = true;
queue_work(wq, &sih->mask_work); queue_work(wq, &sih->mask_work);
spin_unlock_irqrestore(&sih_agent_lock, flags); spin_unlock_irqrestore(&sih_agent_lock, flags);
} }
static int twl4030_sih_set_type(unsigned irq, unsigned trigger) static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger)
{ {
struct sih_agent *sih = get_irq_chip_data(irq); struct sih_agent *sih = irq_data_get_irq_chip_data(data);
struct irq_desc *desc = irq_to_desc(irq); struct irq_desc *desc = irq_to_desc(data->irq);
unsigned long flags; unsigned long flags;
if (!desc) { if (!desc) {
pr_err("twl4030: Invalid IRQ: %d\n", irq); pr_err("twl4030: Invalid IRQ: %d\n", data->irq);
return -EINVAL; return -EINVAL;
} }
...@@ -641,7 +641,7 @@ static int twl4030_sih_set_type(unsigned irq, unsigned trigger) ...@@ -641,7 +641,7 @@ static int twl4030_sih_set_type(unsigned irq, unsigned trigger)
if ((desc->status & IRQ_TYPE_SENSE_MASK) != trigger) { if ((desc->status & IRQ_TYPE_SENSE_MASK) != trigger) {
desc->status &= ~IRQ_TYPE_SENSE_MASK; desc->status &= ~IRQ_TYPE_SENSE_MASK;
desc->status |= trigger; desc->status |= trigger;
sih->edge_change |= BIT(irq - sih->irq_base); sih->edge_change |= BIT(data->irq - sih->irq_base);
queue_work(wq, &sih->edge_work); queue_work(wq, &sih->edge_work);
} }
spin_unlock_irqrestore(&sih_agent_lock, flags); spin_unlock_irqrestore(&sih_agent_lock, flags);
...@@ -650,9 +650,9 @@ static int twl4030_sih_set_type(unsigned irq, unsigned trigger) ...@@ -650,9 +650,9 @@ static int twl4030_sih_set_type(unsigned irq, unsigned trigger)
static struct irq_chip twl4030_sih_irq_chip = { static struct irq_chip twl4030_sih_irq_chip = {
.name = "twl4030", .name = "twl4030",
.mask = twl4030_sih_mask, .irq_mask = twl4030_sih_mask,
.unmask = twl4030_sih_unmask, .irq_unmask = twl4030_sih_unmask,
.set_type = twl4030_sih_set_type, .irq_set_type = twl4030_sih_set_type,
}; };
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
......
...@@ -332,7 +332,7 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) ...@@ -332,7 +332,7 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
*/ */
twl6030_irq_chip = dummy_irq_chip; twl6030_irq_chip = dummy_irq_chip;
twl6030_irq_chip.name = "twl6030"; twl6030_irq_chip.name = "twl6030";
twl6030_irq_chip.set_type = NULL; twl6030_irq_chip.irq_set_type = NULL;
for (i = irq_base; i < irq_end; i++) { for (i = irq_base; i < irq_end; i++) {
set_irq_chip_and_handler(i, &twl6030_irq_chip, set_irq_chip_and_handler(i, &twl6030_irq_chip,
......
...@@ -112,7 +112,7 @@ static __devinit int vx855_probe(struct pci_dev *pdev, ...@@ -112,7 +112,7 @@ static __devinit int vx855_probe(struct pci_dev *pdev,
return ret; return ret;
} }
static void vx855_remove(struct pci_dev *pdev) static void __devexit vx855_remove(struct pci_dev *pdev)
{ {
mfd_remove_devices(&pdev->dev); mfd_remove_devices(&pdev->dev);
pci_disable_device(pdev); pci_disable_device(pdev);
......
...@@ -1541,6 +1541,12 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ...@@ -1541,6 +1541,12 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
dev_info(wm831x->dev, "WM8325 revision %c\n", 'A' + rev); dev_info(wm831x->dev, "WM8325 revision %c\n", 'A' + rev);
break; break;
case WM8326:
parent = WM8326;
wm831x->num_gpio = 12;
dev_info(wm831x->dev, "WM8326 revision %c\n", 'A' + rev);
break;
default: default:
dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret); dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret);
ret = -EINVAL; ret = -EINVAL;
...@@ -1610,18 +1616,9 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) ...@@ -1610,18 +1616,9 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
break; break;
case WM8320: case WM8320:
ret = mfd_add_devices(wm831x->dev, -1,
wm8320_devs, ARRAY_SIZE(wm8320_devs),
NULL, 0);
break;
case WM8321: case WM8321:
ret = mfd_add_devices(wm831x->dev, -1,
wm8320_devs, ARRAY_SIZE(wm8320_devs),
NULL, 0);
break;
case WM8325: case WM8325:
case WM8326:
ret = mfd_add_devices(wm831x->dev, -1, ret = mfd_add_devices(wm831x->dev, -1,
wm8320_devs, ARRAY_SIZE(wm8320_devs), wm8320_devs, ARRAY_SIZE(wm8320_devs),
NULL, wm831x->irq_base); NULL, wm831x->irq_base);
......
...@@ -94,9 +94,9 @@ static int wm831x_i2c_remove(struct i2c_client *i2c) ...@@ -94,9 +94,9 @@ static int wm831x_i2c_remove(struct i2c_client *i2c)
return 0; return 0;
} }
static int wm831x_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg) static int wm831x_i2c_suspend(struct device *dev)
{ {
struct wm831x *wm831x = i2c_get_clientdata(i2c); struct wm831x *wm831x = dev_get_drvdata(dev);
return wm831x_device_suspend(wm831x); return wm831x_device_suspend(wm831x);
} }
...@@ -108,19 +108,23 @@ static const struct i2c_device_id wm831x_i2c_id[] = { ...@@ -108,19 +108,23 @@ static const struct i2c_device_id wm831x_i2c_id[] = {
{ "wm8320", WM8320 }, { "wm8320", WM8320 },
{ "wm8321", WM8321 }, { "wm8321", WM8321 },
{ "wm8325", WM8325 }, { "wm8325", WM8325 },
{ "wm8326", WM8326 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
static const struct dev_pm_ops wm831x_pm_ops = {
.suspend = wm831x_i2c_suspend,
};
static struct i2c_driver wm831x_i2c_driver = { static struct i2c_driver wm831x_i2c_driver = {
.driver = { .driver = {
.name = "wm831x", .name = "wm831x",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &wm831x_pm_ops,
}, },
.probe = wm831x_i2c_probe, .probe = wm831x_i2c_probe,
.remove = wm831x_i2c_remove, .remove = wm831x_i2c_remove,
.suspend = wm831x_i2c_suspend,
.id_table = wm831x_i2c_id, .id_table = wm831x_i2c_id,
}; };
......
...@@ -345,16 +345,16 @@ static inline struct wm831x_irq_data *irq_to_wm831x_irq(struct wm831x *wm831x, ...@@ -345,16 +345,16 @@ static inline struct wm831x_irq_data *irq_to_wm831x_irq(struct wm831x *wm831x,
return &wm831x_irqs[irq - wm831x->irq_base]; return &wm831x_irqs[irq - wm831x->irq_base];
} }
static void wm831x_irq_lock(unsigned int irq) static void wm831x_irq_lock(struct irq_data *data)
{ {
struct wm831x *wm831x = get_irq_chip_data(irq); struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
mutex_lock(&wm831x->irq_lock); mutex_lock(&wm831x->irq_lock);
} }
static void wm831x_irq_sync_unlock(unsigned int irq) static void wm831x_irq_sync_unlock(struct irq_data *data)
{ {
struct wm831x *wm831x = get_irq_chip_data(irq); struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
int i; int i;
for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) { for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
...@@ -371,28 +371,30 @@ static void wm831x_irq_sync_unlock(unsigned int irq) ...@@ -371,28 +371,30 @@ static void wm831x_irq_sync_unlock(unsigned int irq)
mutex_unlock(&wm831x->irq_lock); mutex_unlock(&wm831x->irq_lock);
} }
static void wm831x_irq_unmask(unsigned int irq) static void wm831x_irq_unmask(struct irq_data *data)
{ {
struct wm831x *wm831x = get_irq_chip_data(irq); struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq); struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x,
data->irq);
wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
} }
static void wm831x_irq_mask(unsigned int irq) static void wm831x_irq_mask(struct irq_data *data)
{ {
struct wm831x *wm831x = get_irq_chip_data(irq); struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq); struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x,
data->irq);
wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
} }
static int wm831x_irq_set_type(unsigned int irq, unsigned int type) static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
{ {
struct wm831x *wm831x = get_irq_chip_data(irq); struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
int val; int val, irq;
irq = irq - wm831x->irq_base; irq = data->irq - wm831x->irq_base;
if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) { if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) {
/* Ignore internal-only IRQs */ /* Ignore internal-only IRQs */
...@@ -422,11 +424,11 @@ static int wm831x_irq_set_type(unsigned int irq, unsigned int type) ...@@ -422,11 +424,11 @@ static int wm831x_irq_set_type(unsigned int irq, unsigned int type)
static struct irq_chip wm831x_irq_chip = { static struct irq_chip wm831x_irq_chip = {
.name = "wm831x", .name = "wm831x",
.bus_lock = wm831x_irq_lock, .irq_bus_lock = wm831x_irq_lock,
.bus_sync_unlock = wm831x_irq_sync_unlock, .irq_bus_sync_unlock = wm831x_irq_sync_unlock,
.mask = wm831x_irq_mask, .irq_mask = wm831x_irq_mask,
.unmask = wm831x_irq_unmask, .irq_unmask = wm831x_irq_unmask,
.set_type = wm831x_irq_set_type, .irq_set_type = wm831x_irq_set_type,
}; };
/* The processing of the primary interrupt occurs in a thread so that /* The processing of the primary interrupt occurs in a thread so that
...@@ -515,6 +517,17 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) ...@@ -515,6 +517,17 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
return 0; return 0;
} }
/* Try to flag /IRQ as a wake source; there are a number of
* unconditional wake sources in the PMIC so this isn't
* conditional but we don't actually care *too* much if it
* fails.
*/
ret = enable_irq_wake(irq);
if (ret != 0) {
dev_warn(wm831x->dev, "Can't enable IRQ as wake source: %d\n",
ret);
}
wm831x->irq = irq; wm831x->irq = irq;
wm831x->irq_base = pdata->irq_base; wm831x->irq_base = pdata->irq_base;
......
...@@ -81,6 +81,8 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi) ...@@ -81,6 +81,8 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
type = WM8321; type = WM8321;
else if (strcmp(spi->modalias, "wm8325") == 0) else if (strcmp(spi->modalias, "wm8325") == 0)
type = WM8325; type = WM8325;
else if (strcmp(spi->modalias, "wm8326") == 0)
type = WM8326;
else { else {
dev_err(&spi->dev, "Unknown device type\n"); dev_err(&spi->dev, "Unknown device type\n");
return -EINVAL; return -EINVAL;
...@@ -184,6 +186,17 @@ static struct spi_driver wm8325_spi_driver = { ...@@ -184,6 +186,17 @@ static struct spi_driver wm8325_spi_driver = {
.suspend = wm831x_spi_suspend, .suspend = wm831x_spi_suspend,
}; };
static struct spi_driver wm8326_spi_driver = {
.driver = {
.name = "wm8326",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove),
.suspend = wm831x_spi_suspend,
};
static int __init wm831x_spi_init(void) static int __init wm831x_spi_init(void)
{ {
int ret; int ret;
...@@ -212,12 +225,17 @@ static int __init wm831x_spi_init(void) ...@@ -212,12 +225,17 @@ static int __init wm831x_spi_init(void)
if (ret != 0) if (ret != 0)
pr_err("Failed to register WM8325 SPI driver: %d\n", ret); pr_err("Failed to register WM8325 SPI driver: %d\n", ret);
ret = spi_register_driver(&wm8326_spi_driver);
if (ret != 0)
pr_err("Failed to register WM8326 SPI driver: %d\n", ret);
return 0; return 0;
} }
subsys_initcall(wm831x_spi_init); subsys_initcall(wm831x_spi_init);
static void __exit wm831x_spi_exit(void) static void __exit wm831x_spi_exit(void)
{ {
spi_unregister_driver(&wm8326_spi_driver);
spi_unregister_driver(&wm8325_spi_driver); spi_unregister_driver(&wm8325_spi_driver);
spi_unregister_driver(&wm8321_spi_driver); spi_unregister_driver(&wm8321_spi_driver);
spi_unregister_driver(&wm8320_spi_driver); spi_unregister_driver(&wm8320_spi_driver);
......
...@@ -417,16 +417,16 @@ static irqreturn_t wm8350_irq(int irq, void *irq_data) ...@@ -417,16 +417,16 @@ static irqreturn_t wm8350_irq(int irq, void *irq_data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void wm8350_irq_lock(unsigned int irq) static void wm8350_irq_lock(struct irq_data *data)
{ {
struct wm8350 *wm8350 = get_irq_chip_data(irq); struct wm8350 *wm8350 = irq_data_get_irq_chip_data(data);
mutex_lock(&wm8350->irq_lock); mutex_lock(&wm8350->irq_lock);
} }
static void wm8350_irq_sync_unlock(unsigned int irq) static void wm8350_irq_sync_unlock(struct irq_data *data)
{ {
struct wm8350 *wm8350 = get_irq_chip_data(irq); struct wm8350 *wm8350 = irq_data_get_irq_chip_data(data);
int i; int i;
for (i = 0; i < ARRAY_SIZE(wm8350->irq_masks); i++) { for (i = 0; i < ARRAY_SIZE(wm8350->irq_masks); i++) {
...@@ -442,28 +442,30 @@ static void wm8350_irq_sync_unlock(unsigned int irq) ...@@ -442,28 +442,30 @@ static void wm8350_irq_sync_unlock(unsigned int irq)
mutex_unlock(&wm8350->irq_lock); mutex_unlock(&wm8350->irq_lock);
} }
static void wm8350_irq_enable(unsigned int irq) static void wm8350_irq_enable(struct irq_data *data)
{ {
struct wm8350 *wm8350 = get_irq_chip_data(irq); struct wm8350 *wm8350 = irq_data_get_irq_chip_data(data);
struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350, irq); struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350,
data->irq);
wm8350->irq_masks[irq_data->reg] &= ~irq_data->mask; wm8350->irq_masks[irq_data->reg] &= ~irq_data->mask;
} }
static void wm8350_irq_disable(unsigned int irq) static void wm8350_irq_disable(struct irq_data *data)
{ {
struct wm8350 *wm8350 = get_irq_chip_data(irq); struct wm8350 *wm8350 = irq_data_get_irq_chip_data(data);
struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350, irq); struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350,
data->irq);
wm8350->irq_masks[irq_data->reg] |= irq_data->mask; wm8350->irq_masks[irq_data->reg] |= irq_data->mask;
} }
static struct irq_chip wm8350_irq_chip = { static struct irq_chip wm8350_irq_chip = {
.name = "wm8350", .name = "wm8350",
.bus_lock = wm8350_irq_lock, .irq_bus_lock = wm8350_irq_lock,
.bus_sync_unlock = wm8350_irq_sync_unlock, .irq_bus_sync_unlock = wm8350_irq_sync_unlock,
.disable = wm8350_irq_disable, .irq_disable = wm8350_irq_disable,
.enable = wm8350_irq_enable, .irq_enable = wm8350_irq_enable,
}; };
int wm8350_irq_init(struct wm8350 *wm8350, int irq, int wm8350_irq_init(struct wm8350 *wm8350, int irq,
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
...@@ -169,8 +170,16 @@ int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg, ...@@ -169,8 +170,16 @@ int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
EXPORT_SYMBOL_GPL(wm8994_set_bits); EXPORT_SYMBOL_GPL(wm8994_set_bits);
static struct mfd_cell wm8994_regulator_devs[] = { static struct mfd_cell wm8994_regulator_devs[] = {
{ .name = "wm8994-ldo", .id = 1 }, {
{ .name = "wm8994-ldo", .id = 2 }, .name = "wm8994-ldo",
.id = 1,
.pm_runtime_no_callbacks = true,
},
{
.name = "wm8994-ldo",
.id = 2,
.pm_runtime_no_callbacks = true,
},
}; };
static struct resource wm8994_codec_resources[] = { static struct resource wm8994_codec_resources[] = {
...@@ -200,6 +209,7 @@ static struct mfd_cell wm8994_devs[] = { ...@@ -200,6 +209,7 @@ static struct mfd_cell wm8994_devs[] = {
.name = "wm8994-gpio", .name = "wm8994-gpio",
.num_resources = ARRAY_SIZE(wm8994_gpio_resources), .num_resources = ARRAY_SIZE(wm8994_gpio_resources),
.resources = wm8994_gpio_resources, .resources = wm8994_gpio_resources,
.pm_runtime_no_callbacks = true,
}, },
}; };
...@@ -231,7 +241,7 @@ static const char *wm8958_main_supplies[] = { ...@@ -231,7 +241,7 @@ static const char *wm8958_main_supplies[] = {
}; };
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int wm8994_device_suspend(struct device *dev) static int wm8994_suspend(struct device *dev)
{ {
struct wm8994 *wm8994 = dev_get_drvdata(dev); struct wm8994 *wm8994 = dev_get_drvdata(dev);
int ret; int ret;
...@@ -261,7 +271,7 @@ static int wm8994_device_suspend(struct device *dev) ...@@ -261,7 +271,7 @@ static int wm8994_device_suspend(struct device *dev)
return 0; return 0;
} }
static int wm8994_device_resume(struct device *dev) static int wm8994_resume(struct device *dev)
{ {
struct wm8994 *wm8994 = dev_get_drvdata(dev); struct wm8994 *wm8994 = dev_get_drvdata(dev);
int ret; int ret;
...@@ -471,6 +481,9 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) ...@@ -471,6 +481,9 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
goto err_irq; goto err_irq;
} }
pm_runtime_enable(wm8994->dev);
pm_runtime_resume(wm8994->dev);
return 0; return 0;
err_irq: err_irq:
...@@ -490,6 +503,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) ...@@ -490,6 +503,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
static void wm8994_device_exit(struct wm8994 *wm8994) static void wm8994_device_exit(struct wm8994 *wm8994)
{ {
pm_runtime_disable(wm8994->dev);
mfd_remove_devices(wm8994->dev); mfd_remove_devices(wm8994->dev);
wm8994_irq_exit(wm8994); wm8994_irq_exit(wm8994);
regulator_bulk_disable(wm8994->num_supplies, regulator_bulk_disable(wm8994->num_supplies,
...@@ -573,21 +587,6 @@ static int wm8994_i2c_remove(struct i2c_client *i2c) ...@@ -573,21 +587,6 @@ static int wm8994_i2c_remove(struct i2c_client *i2c)
return 0; return 0;
} }
#ifdef CONFIG_PM
static int wm8994_i2c_suspend(struct i2c_client *i2c, pm_message_t state)
{
return wm8994_device_suspend(&i2c->dev);
}
static int wm8994_i2c_resume(struct i2c_client *i2c)
{
return wm8994_device_resume(&i2c->dev);
}
#else
#define wm8994_i2c_suspend NULL
#define wm8994_i2c_resume NULL
#endif
static const struct i2c_device_id wm8994_i2c_id[] = { static const struct i2c_device_id wm8994_i2c_id[] = {
{ "wm8994", WM8994 }, { "wm8994", WM8994 },
{ "wm8958", WM8958 }, { "wm8958", WM8958 },
...@@ -595,15 +594,16 @@ static const struct i2c_device_id wm8994_i2c_id[] = { ...@@ -595,15 +594,16 @@ static const struct i2c_device_id wm8994_i2c_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id); MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
UNIVERSAL_DEV_PM_OPS(wm8994_pm_ops, wm8994_suspend, wm8994_resume, NULL);
static struct i2c_driver wm8994_i2c_driver = { static struct i2c_driver wm8994_i2c_driver = {
.driver = { .driver = {
.name = "wm8994", .name = "wm8994",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &wm8994_pm_ops,
}, },
.probe = wm8994_i2c_probe, .probe = wm8994_i2c_probe,
.remove = wm8994_i2c_remove, .remove = wm8994_i2c_remove,
.suspend = wm8994_i2c_suspend,
.resume = wm8994_i2c_resume,
.id_table = wm8994_i2c_id, .id_table = wm8994_i2c_id,
}; };
......
...@@ -156,16 +156,16 @@ static inline struct wm8994_irq_data *irq_to_wm8994_irq(struct wm8994 *wm8994, ...@@ -156,16 +156,16 @@ static inline struct wm8994_irq_data *irq_to_wm8994_irq(struct wm8994 *wm8994,
return &wm8994_irqs[irq - wm8994->irq_base]; return &wm8994_irqs[irq - wm8994->irq_base];
} }
static void wm8994_irq_lock(unsigned int irq) static void wm8994_irq_lock(struct irq_data *data)
{ {
struct wm8994 *wm8994 = get_irq_chip_data(irq); struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
mutex_lock(&wm8994->irq_lock); mutex_lock(&wm8994->irq_lock);
} }
static void wm8994_irq_sync_unlock(unsigned int irq) static void wm8994_irq_sync_unlock(struct irq_data *data)
{ {
struct wm8994 *wm8994 = get_irq_chip_data(irq); struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
int i; int i;
for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) { for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) {
...@@ -182,28 +182,30 @@ static void wm8994_irq_sync_unlock(unsigned int irq) ...@@ -182,28 +182,30 @@ static void wm8994_irq_sync_unlock(unsigned int irq)
mutex_unlock(&wm8994->irq_lock); mutex_unlock(&wm8994->irq_lock);
} }
static void wm8994_irq_unmask(unsigned int irq) static void wm8994_irq_unmask(struct irq_data *data)
{ {
struct wm8994 *wm8994 = get_irq_chip_data(irq); struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994, irq); struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994,
data->irq);
wm8994->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; wm8994->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
} }
static void wm8994_irq_mask(unsigned int irq) static void wm8994_irq_mask(struct irq_data *data)
{ {
struct wm8994 *wm8994 = get_irq_chip_data(irq); struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994, irq); struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994,
data->irq);
wm8994->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; wm8994->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
} }
static struct irq_chip wm8994_irq_chip = { static struct irq_chip wm8994_irq_chip = {
.name = "wm8994", .name = "wm8994",
.bus_lock = wm8994_irq_lock, .irq_bus_lock = wm8994_irq_lock,
.bus_sync_unlock = wm8994_irq_sync_unlock, .irq_bus_sync_unlock = wm8994_irq_sync_unlock,
.mask = wm8994_irq_mask, .irq_mask = wm8994_irq_mask,
.unmask = wm8994_irq_unmask, .irq_unmask = wm8994_irq_unmask,
}; };
/* The processing of the primary interrupt occurs in a thread so that /* The processing of the primary interrupt occurs in a thread so that
......
...@@ -64,7 +64,7 @@ config ATMEL_PWM ...@@ -64,7 +64,7 @@ config ATMEL_PWM
config AB8500_PWM config AB8500_PWM
bool "AB8500 PWM support" bool "AB8500 PWM support"
depends on AB8500_CORE depends on AB8500_CORE && ARCH_U8500
select HAVE_PWM select HAVE_PWM
help help
This driver exports functions to enable/disble/config/free Pulse This driver exports functions to enable/disble/config/free Pulse
......
...@@ -16,12 +16,11 @@ ...@@ -16,12 +16,11 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/platform_device.h>
#include <linux/cs5535.h> #include <linux/cs5535.h>
#include <linux/slab.h> #include <linux/slab.h>
#define DRV_NAME "cs5535-mfgpt" #define DRV_NAME "cs5535-mfgpt"
#define MFGPT_BAR 2
static int mfgpt_reset_timers; static int mfgpt_reset_timers;
module_param_named(mfgptfix, mfgpt_reset_timers, int, 0644); module_param_named(mfgptfix, mfgpt_reset_timers, int, 0644);
...@@ -37,7 +36,7 @@ static struct cs5535_mfgpt_chip { ...@@ -37,7 +36,7 @@ static struct cs5535_mfgpt_chip {
DECLARE_BITMAP(avail, MFGPT_MAX_TIMERS); DECLARE_BITMAP(avail, MFGPT_MAX_TIMERS);
resource_size_t base; resource_size_t base;
struct pci_dev *pdev; struct platform_device *pdev;
spinlock_t lock; spinlock_t lock;
int initialized; int initialized;
} cs5535_mfgpt_chip; } cs5535_mfgpt_chip;
...@@ -290,10 +289,10 @@ static int __init scan_timers(struct cs5535_mfgpt_chip *mfgpt) ...@@ -290,10 +289,10 @@ static int __init scan_timers(struct cs5535_mfgpt_chip *mfgpt)
return timers; return timers;
} }
static int __init cs5535_mfgpt_probe(struct pci_dev *pdev, static int __devinit cs5535_mfgpt_probe(struct platform_device *pdev)
const struct pci_device_id *pci_id)
{ {
int err, t; struct resource *res;
int err = -EIO, t;
/* There are two ways to get the MFGPT base address; one is by /* There are two ways to get the MFGPT base address; one is by
* fetching it from MSR_LBAR_MFGPT, the other is by reading the * fetching it from MSR_LBAR_MFGPT, the other is by reading the
...@@ -302,29 +301,27 @@ static int __init cs5535_mfgpt_probe(struct pci_dev *pdev, ...@@ -302,29 +301,27 @@ static int __init cs5535_mfgpt_probe(struct pci_dev *pdev,
* it turns out to be unreliable in the face of crappy BIOSes, we * it turns out to be unreliable in the face of crappy BIOSes, we
* can always go back to using MSRs.. */ * can always go back to using MSRs.. */
err = pci_enable_device_io(pdev); res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (err) { if (!res) {
dev_err(&pdev->dev, "can't enable device IO\n"); dev_err(&pdev->dev, "can't fetch device resource info\n");
goto done; goto done;
} }
err = pci_request_region(pdev, MFGPT_BAR, DRV_NAME); if (!request_region(res->start, resource_size(res), pdev->name)) {
if (err) { dev_err(&pdev->dev, "can't request region\n");
dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", MFGPT_BAR);
goto done; goto done;
} }
/* set up the driver-specific struct */ /* set up the driver-specific struct */
cs5535_mfgpt_chip.base = pci_resource_start(pdev, MFGPT_BAR); cs5535_mfgpt_chip.base = res->start;
cs5535_mfgpt_chip.pdev = pdev; cs5535_mfgpt_chip.pdev = pdev;
spin_lock_init(&cs5535_mfgpt_chip.lock); spin_lock_init(&cs5535_mfgpt_chip.lock);
dev_info(&pdev->dev, "allocated PCI BAR #%d: base 0x%llx\n", MFGPT_BAR, dev_info(&pdev->dev, "reserved resource region %pR\n", res);
(unsigned long long) cs5535_mfgpt_chip.base);
/* detect the available timers */ /* detect the available timers */
t = scan_timers(&cs5535_mfgpt_chip); t = scan_timers(&cs5535_mfgpt_chip);
dev_info(&pdev->dev, DRV_NAME ": %d MFGPT timers available\n", t); dev_info(&pdev->dev, "%d MFGPT timers available\n", t);
cs5535_mfgpt_chip.initialized = 1; cs5535_mfgpt_chip.initialized = 1;
return 0; return 0;
...@@ -332,47 +329,18 @@ static int __init cs5535_mfgpt_probe(struct pci_dev *pdev, ...@@ -332,47 +329,18 @@ static int __init cs5535_mfgpt_probe(struct pci_dev *pdev,
return err; return err;
} }
static struct pci_device_id cs5535_mfgpt_pci_tbl[] = { static struct platform_driver cs5535_mfgpt_drv = {
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) }, .driver = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) }, .name = DRV_NAME,
{ 0, }, .owner = THIS_MODULE,
},
.probe = cs5535_mfgpt_probe,
}; };
MODULE_DEVICE_TABLE(pci, cs5535_mfgpt_pci_tbl);
/*
* Just like with the cs5535-gpio driver, we can't use the standard PCI driver
* registration stuff. It only allows only one driver to bind to each PCI
* device, and we want the GPIO and MFGPT drivers to be able to share a PCI
* device. Instead, we manually scan for the PCI device, request a single
* region, and keep track of the devices that we're using.
*/
static int __init cs5535_mfgpt_scan_pci(void)
{
struct pci_dev *pdev;
int err = -ENODEV;
int i;
for (i = 0; i < ARRAY_SIZE(cs5535_mfgpt_pci_tbl); i++) {
pdev = pci_get_device(cs5535_mfgpt_pci_tbl[i].vendor,
cs5535_mfgpt_pci_tbl[i].device, NULL);
if (pdev) {
err = cs5535_mfgpt_probe(pdev,
&cs5535_mfgpt_pci_tbl[i]);
if (err)
pci_dev_put(pdev);
/* we only support a single CS5535/6 southbridge */
break;
}
}
return err;
}
static int __init cs5535_mfgpt_init(void) static int __init cs5535_mfgpt_init(void)
{ {
return cs5535_mfgpt_scan_pci(); return platform_driver_register(&cs5535_mfgpt_drv);
} }
module_init(cs5535_mfgpt_init); module_init(cs5535_mfgpt_init);
...@@ -380,3 +348,4 @@ module_init(cs5535_mfgpt_init); ...@@ -380,3 +348,4 @@ module_init(cs5535_mfgpt_init);
MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>"); MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
MODULE_DESCRIPTION("CS5535/CS5536 MFGPT timer driver"); MODULE_DESCRIPTION("CS5535/CS5536 MFGPT timer driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
...@@ -424,6 +424,9 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev, ...@@ -424,6 +424,9 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
} }
} }
if (pdata->buck_voltage_lock)
return -EINVAL;
/* no predefine regulator found */ /* no predefine regulator found */
max8998->buck1_idx = (buck1_last_val % 2) + 2; max8998->buck1_idx = (buck1_last_val % 2) + 2;
dev_dbg(max8998->dev, "max8998->buck1_idx:%d\n", dev_dbg(max8998->dev, "max8998->buck1_idx:%d\n",
...@@ -451,18 +454,26 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev, ...@@ -451,18 +454,26 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
"BUCK2, i:%d buck2_vol1:%d, buck2_vol2:%d\n" "BUCK2, i:%d buck2_vol1:%d, buck2_vol2:%d\n"
, i, max8998->buck2_vol[0], max8998->buck2_vol[1]); , i, max8998->buck2_vol[0], max8998->buck2_vol[1]);
if (gpio_is_valid(pdata->buck2_set3)) { if (gpio_is_valid(pdata->buck2_set3)) {
if (max8998->buck2_vol[0] == i) {
max8998->buck1_idx = 0; /* check if requested voltage */
buck2_gpio_set(pdata->buck2_set3, 0); /* value is already defined */
} else { for (j = 0; j < ARRAY_SIZE(max8998->buck2_vol); j++) {
max8998->buck1_idx = 1; if (max8998->buck2_vol[j] == i) {
ret = max8998_get_voltage_register(rdev, &reg, max8998->buck2_idx = j;
&shift, buck2_gpio_set(pdata->buck2_set3, j);
&mask); goto buck2_exit;
ret = max8998_write_reg(i2c, reg, i);
max8998->buck2_vol[1] = i;
buck2_gpio_set(pdata->buck2_set3, 1);
} }
}
if (pdata->buck_voltage_lock)
return -EINVAL;
max8998_get_voltage_register(rdev,
&reg, &shift, &mask);
ret = max8998_write_reg(i2c, reg, i);
max8998->buck2_vol[max8998->buck2_idx] = i;
buck2_gpio_set(pdata->buck2_set3, max8998->buck2_idx);
buck2_exit:
dev_dbg(max8998->dev, "%s: SET3:%d\n", i2c->name, dev_dbg(max8998->dev, "%s: SET3:%d\n", i2c->name,
gpio_get_value(pdata->buck2_set3)); gpio_get_value(pdata->buck2_set3));
} else { } else {
...@@ -707,6 +718,9 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) ...@@ -707,6 +718,9 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, max8998); platform_set_drvdata(pdev, max8998);
i2c = max8998->iodev->i2c; i2c = max8998->iodev->i2c;
max8998->buck1_idx = pdata->buck1_default_idx;
max8998->buck2_idx = pdata->buck2_default_idx;
/* NOTE: */ /* NOTE: */
/* For unused GPIO NOT marked as -1 (thereof equal to 0) WARN_ON */ /* For unused GPIO NOT marked as -1 (thereof equal to 0) WARN_ON */
/* will be displayed */ /* will be displayed */
...@@ -739,23 +753,46 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) ...@@ -739,23 +753,46 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
i = 0; i = 0;
while (buck12_voltage_map_desc.min + while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i buck12_voltage_map_desc.step*i
!= (pdata->buck1_max_voltage1 / 1000)) < (pdata->buck1_voltage1 / 1000))
i++; i++;
printk(KERN_ERR "i:%d, buck1_idx:%d\n", i, max8998->buck1_idx);
max8998->buck1_vol[0] = i; max8998->buck1_vol[0] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i);
if (ret)
return ret;
/* Set predefined value for BUCK1 register 2 */ /* Set predefined value for BUCK1 register 2 */
i = 0; i = 0;
while (buck12_voltage_map_desc.min + while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i buck12_voltage_map_desc.step*i
!= (pdata->buck1_max_voltage2 / 1000)) < (pdata->buck1_voltage2 / 1000))
i++; i++;
max8998->buck1_vol[1] = i; max8998->buck1_vol[1] = i;
printk(KERN_ERR "i:%d, buck1_idx:%d\n", i, max8998->buck1_idx); ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i);
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i) if (ret)
+ ret; return ret;
/* Set predefined value for BUCK1 register 3 */
i = 0;
while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i
< (pdata->buck1_voltage3 / 1000))
i++;
max8998->buck1_vol[2] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE3, i);
if (ret)
return ret;
/* Set predefined value for BUCK1 register 4 */
i = 0;
while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i
< (pdata->buck1_voltage4 / 1000))
i++;
max8998->buck1_vol[3] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE4, i);
if (ret) if (ret)
return ret; return ret;
...@@ -772,18 +809,28 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) ...@@ -772,18 +809,28 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
gpio_direction_output(pdata->buck2_set3, gpio_direction_output(pdata->buck2_set3,
max8998->buck2_idx & 0x1); max8998->buck2_idx & 0x1);
/* BUCK2 - set preset default voltage value to buck2_vol[0] */ /* BUCK2 register 1 */
i = 0; i = 0;
while (buck12_voltage_map_desc.min + while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i buck12_voltage_map_desc.step*i
!= (pdata->buck2_max_voltage / 1000)) < (pdata->buck2_voltage1 / 1000))
i++; i++;
printk(KERN_ERR "i:%d, buck2_idx:%d\n", i, max8998->buck2_idx);
max8998->buck2_vol[0] = i; max8998->buck2_vol[0] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i);
if (ret) if (ret)
return ret; return ret;
/* BUCK2 register 2 */
i = 0;
while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i
< (pdata->buck2_voltage2 / 1000))
i++;
printk(KERN_ERR "i2:%d, buck2_idx:%d\n", i, max8998->buck2_idx);
max8998->buck2_vol[1] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i);
if (ret)
return ret;
} }
for (i = 0; i < pdata->num_regulators; i++) { for (i = 0; i < pdata->num_regulators; i++) {
...@@ -835,6 +882,12 @@ static int __devexit max8998_pmic_remove(struct platform_device *pdev) ...@@ -835,6 +882,12 @@ static int __devexit max8998_pmic_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct platform_device_id max8998_pmic_id[] = {
{ "max8998-pmic", TYPE_MAX8998 },
{ "lp3974-pmic", TYPE_LP3974 },
{ }
};
static struct platform_driver max8998_pmic_driver = { static struct platform_driver max8998_pmic_driver = {
.driver = { .driver = {
.name = "max8998-pmic", .name = "max8998-pmic",
...@@ -842,6 +895,7 @@ static struct platform_driver max8998_pmic_driver = { ...@@ -842,6 +895,7 @@ static struct platform_driver max8998_pmic_driver = {
}, },
.probe = max8998_pmic_probe, .probe = max8998_pmic_probe,
.remove = __devexit_p(max8998_pmic_remove), .remove = __devexit_p(max8998_pmic_remove),
.id_table = max8998_pmic_id,
}; };
static int __init max8998_pmic_init(void) static int __init max8998_pmic_init(void)
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/max8998.h> #include <linux/mfd/max8998.h>
#include <linux/mfd/max8998-private.h> #include <linux/mfd/max8998-private.h>
#include <linux/delay.h>
#define MAX8998_RTC_SEC 0x00 #define MAX8998_RTC_SEC 0x00
#define MAX8998_RTC_MIN 0x01 #define MAX8998_RTC_MIN 0x01
...@@ -73,6 +74,7 @@ struct max8998_rtc_info { ...@@ -73,6 +74,7 @@ struct max8998_rtc_info {
struct i2c_client *rtc; struct i2c_client *rtc;
struct rtc_device *rtc_dev; struct rtc_device *rtc_dev;
int irq; int irq;
bool lp3974_bug_workaround;
}; };
static void max8998_data_to_tm(u8 *data, struct rtc_time *tm) static void max8998_data_to_tm(u8 *data, struct rtc_time *tm)
...@@ -124,10 +126,16 @@ static int max8998_rtc_set_time(struct device *dev, struct rtc_time *tm) ...@@ -124,10 +126,16 @@ static int max8998_rtc_set_time(struct device *dev, struct rtc_time *tm)
{ {
struct max8998_rtc_info *info = dev_get_drvdata(dev); struct max8998_rtc_info *info = dev_get_drvdata(dev);
u8 data[8]; u8 data[8];
int ret;
max8998_tm_to_data(tm, data); max8998_tm_to_data(tm, data);
return max8998_bulk_write(info->rtc, MAX8998_RTC_SEC, 8, data); ret = max8998_bulk_write(info->rtc, MAX8998_RTC_SEC, 8, data);
if (info->lp3974_bug_workaround)
msleep(2000);
return ret;
} }
static int max8998_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int max8998_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
...@@ -163,12 +171,29 @@ static int max8998_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -163,12 +171,29 @@ static int max8998_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int max8998_rtc_stop_alarm(struct max8998_rtc_info *info) static int max8998_rtc_stop_alarm(struct max8998_rtc_info *info)
{ {
return max8998_write_reg(info->rtc, MAX8998_ALARM0_CONF, 0); int ret = max8998_write_reg(info->rtc, MAX8998_ALARM0_CONF, 0);
if (info->lp3974_bug_workaround)
msleep(2000);
return ret;
} }
static int max8998_rtc_start_alarm(struct max8998_rtc_info *info) static int max8998_rtc_start_alarm(struct max8998_rtc_info *info)
{ {
return max8998_write_reg(info->rtc, MAX8998_ALARM0_CONF, 0x77); int ret;
u8 alarm0_conf = 0x77;
/* LP3974 with delay bug chips has rtc alarm bugs with "MONTH" field */
if (info->lp3974_bug_workaround)
alarm0_conf = 0x57;
ret = max8998_write_reg(info->rtc, MAX8998_ALARM0_CONF, alarm0_conf);
if (info->lp3974_bug_workaround)
msleep(2000);
return ret;
} }
static int max8998_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int max8998_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
...@@ -187,10 +212,13 @@ static int max8998_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -187,10 +212,13 @@ static int max8998_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
if (ret < 0) if (ret < 0)
return ret; return ret;
if (info->lp3974_bug_workaround)
msleep(2000);
if (alrm->enabled) if (alrm->enabled)
return max8998_rtc_start_alarm(info); ret = max8998_rtc_start_alarm(info);
return 0; return ret;
} }
static int max8998_rtc_alarm_irq_enable(struct device *dev, static int max8998_rtc_alarm_irq_enable(struct device *dev,
...@@ -224,6 +252,7 @@ static const struct rtc_class_ops max8998_rtc_ops = { ...@@ -224,6 +252,7 @@ static const struct rtc_class_ops max8998_rtc_ops = {
static int __devinit max8998_rtc_probe(struct platform_device *pdev) static int __devinit max8998_rtc_probe(struct platform_device *pdev)
{ {
struct max8998_dev *max8998 = dev_get_drvdata(pdev->dev.parent); struct max8998_dev *max8998 = dev_get_drvdata(pdev->dev.parent);
struct max8998_platform_data *pdata = dev_get_platdata(max8998->dev);
struct max8998_rtc_info *info; struct max8998_rtc_info *info;
int ret; int ret;
...@@ -249,10 +278,18 @@ static int __devinit max8998_rtc_probe(struct platform_device *pdev) ...@@ -249,10 +278,18 @@ static int __devinit max8998_rtc_probe(struct platform_device *pdev)
ret = request_threaded_irq(info->irq, NULL, max8998_rtc_alarm_irq, 0, ret = request_threaded_irq(info->irq, NULL, max8998_rtc_alarm_irq, 0,
"rtc-alarm0", info); "rtc-alarm0", info);
if (ret < 0) if (ret < 0)
dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
info->irq, ret); info->irq, ret);
dev_info(&pdev->dev, "RTC CHIP NAME: %s\n", pdev->id_entry->name);
if (pdata->rtc_delay) {
info->lp3974_bug_workaround = true;
dev_warn(&pdev->dev, "LP3974 with RTC REGERR option."
" RTC updates will be extremely slow.\n");
}
return 0; return 0;
out_rtc: out_rtc:
...@@ -273,6 +310,12 @@ static int __devexit max8998_rtc_remove(struct platform_device *pdev) ...@@ -273,6 +310,12 @@ static int __devexit max8998_rtc_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct platform_device_id max8998_rtc_id[] = {
{ "max8998-rtc", TYPE_MAX8998 },
{ "lp3974-rtc", TYPE_LP3974 },
{ }
};
static struct platform_driver max8998_rtc_driver = { static struct platform_driver max8998_rtc_driver = {
.driver = { .driver = {
.name = "max8998-rtc", .name = "max8998-rtc",
...@@ -280,6 +323,7 @@ static struct platform_driver max8998_rtc_driver = { ...@@ -280,6 +323,7 @@ static struct platform_driver max8998_rtc_driver = {
}, },
.probe = max8998_rtc_probe, .probe = max8998_rtc_probe,
.remove = __devexit_p(max8998_rtc_remove), .remove = __devexit_p(max8998_rtc_remove),
.id_table = max8998_rtc_id,
}; };
static int __init max8998_rtc_init(void) static int __init max8998_rtc_init(void)
......
...@@ -74,30 +74,37 @@ ...@@ -74,30 +74,37 @@
#define AB8500_INT_ACC_DETECT_21DB_F 37 #define AB8500_INT_ACC_DETECT_21DB_F 37
#define AB8500_INT_ACC_DETECT_21DB_R 38 #define AB8500_INT_ACC_DETECT_21DB_R 38
#define AB8500_INT_GP_SW_ADC_CONV_END 39 #define AB8500_INT_GP_SW_ADC_CONV_END 39
#define AB8500_INT_BTEMP_LOW 72 #define AB8500_INT_ADP_SOURCE_ERROR 72
#define AB8500_INT_BTEMP_LOW_MEDIUM 73 #define AB8500_INT_ADP_SINK_ERROR 73
#define AB8500_INT_BTEMP_MEDIUM_HIGH 74 #define AB8500_INT_ADP_PROBE_PLUG 74
#define AB8500_INT_BTEMP_HIGH 75 #define AB8500_INT_ADP_PROBE_UNPLUG 75
#define AB8500_INT_USB_CHARGER_NOT_OK 81 #define AB8500_INT_ADP_SENSE_OFF 76
#define AB8500_INT_ID_WAKEUP_R 82 #define AB8500_INT_USB_PHY_POWER_ERR 78
#define AB8500_INT_ID_DET_R1R 84 #define AB8500_INT_USB_LINK_STATUS 79
#define AB8500_INT_ID_DET_R2R 85 #define AB8500_INT_BTEMP_LOW 80
#define AB8500_INT_ID_DET_R3R 86 #define AB8500_INT_BTEMP_LOW_MEDIUM 81
#define AB8500_INT_ID_DET_R4R 87 #define AB8500_INT_BTEMP_MEDIUM_HIGH 82
#define AB8500_INT_ID_WAKEUP_F 88 #define AB8500_INT_BTEMP_HIGH 83
#define AB8500_INT_ID_DET_R1F 90 #define AB8500_INT_USB_CHARGER_NOT_OK 89
#define AB8500_INT_ID_DET_R2F 91 #define AB8500_INT_ID_WAKEUP_R 90
#define AB8500_INT_ID_DET_R3F 92 #define AB8500_INT_ID_DET_R1R 92
#define AB8500_INT_ID_DET_R4F 93 #define AB8500_INT_ID_DET_R2R 93
#define AB8500_INT_USB_CHG_DET_DONE 94 #define AB8500_INT_ID_DET_R3R 94
#define AB8500_INT_USB_CH_TH_PROT_F 96 #define AB8500_INT_ID_DET_R4R 95
#define AB8500_INT_USB_CH_TH_PROP_R 97 #define AB8500_INT_ID_WAKEUP_F 96
#define AB8500_INT_MAIN_CH_TH_PROP_F 98 #define AB8500_INT_ID_DET_R1F 98
#define AB8500_INT_MAIN_CH_TH_PROT_R 99 #define AB8500_INT_ID_DET_R2F 99
#define AB8500_INT_USB_CHARGER_NOT_OKF 103 #define AB8500_INT_ID_DET_R3F 100
#define AB8500_INT_ID_DET_R4F 101
#define AB8500_INT_USB_CHG_DET_DONE 102
#define AB8500_INT_USB_CH_TH_PROT_F 104
#define AB8500_INT_USB_CH_TH_PROT_R 105
#define AB8500_INT_MAIN_CH_TH_PROT_F 106
#define AB8500_INT_MAIN_CH_TH_PROT_R 107
#define AB8500_INT_USB_CHARGER_NOT_OKF 111
#define AB8500_NR_IRQS 104 #define AB8500_NR_IRQS 112
#define AB8500_NUM_IRQ_REGS 13 #define AB8500_NUM_IRQ_REGS 14
/** /**
* struct ab8500 - ab8500 internal structure * struct ab8500 - ab8500 internal structure
......
...@@ -47,6 +47,12 @@ struct mfd_cell { ...@@ -47,6 +47,12 @@ struct mfd_cell {
/* don't check for resource conflicts */ /* don't check for resource conflicts */
bool ignore_resource_conflicts; bool ignore_resource_conflicts;
/*
* Disable runtime PM callbacks for this subdevice - see
* pm_runtime_no_callbacks().
*/
bool pm_runtime_no_callbacks;
}; };
extern int mfd_add_devices(struct device *parent, int id, extern int mfd_add_devices(struct device *parent, int id,
......
...@@ -159,10 +159,12 @@ struct max8998_dev { ...@@ -159,10 +159,12 @@ struct max8998_dev {
u8 irq_masks_cur[MAX8998_NUM_IRQ_REGS]; u8 irq_masks_cur[MAX8998_NUM_IRQ_REGS];
u8 irq_masks_cache[MAX8998_NUM_IRQ_REGS]; u8 irq_masks_cache[MAX8998_NUM_IRQ_REGS];
int type; int type;
bool wakeup;
}; };
int max8998_irq_init(struct max8998_dev *max8998); int max8998_irq_init(struct max8998_dev *max8998);
void max8998_irq_exit(struct max8998_dev *max8998); void max8998_irq_exit(struct max8998_dev *max8998);
int max8998_irq_resume(struct max8998_dev *max8998);
extern int max8998_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest); extern int max8998_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest);
extern int max8998_bulk_read(struct i2c_client *i2c, u8 reg, int count, extern int max8998_bulk_read(struct i2c_client *i2c, u8 reg, int count,
......
...@@ -70,24 +70,43 @@ struct max8998_regulator_data { ...@@ -70,24 +70,43 @@ struct max8998_regulator_data {
* @num_regulators: number of regultors used * @num_regulators: number of regultors used
* @irq_base: base IRQ number for max8998, required for IRQs * @irq_base: base IRQ number for max8998, required for IRQs
* @ono: power onoff IRQ number for max8998 * @ono: power onoff IRQ number for max8998
* @buck1_max_voltage1: BUCK1 maximum alowed voltage register 1 * @buck_voltage_lock: Do NOT change the values of the following six
* @buck1_max_voltage2: BUCK1 maximum alowed voltage register 2 * registers set by buck?_voltage?. The voltage of BUCK1/2 cannot
* @buck2_max_voltage: BUCK2 maximum alowed voltage * be other than the preset values.
* @buck1_voltage1: BUCK1 DVS mode 1 voltage register
* @buck1_voltage2: BUCK1 DVS mode 2 voltage register
* @buck1_voltage3: BUCK1 DVS mode 3 voltage register
* @buck1_voltage4: BUCK1 DVS mode 4 voltage register
* @buck2_voltage1: BUCK2 DVS mode 1 voltage register
* @buck2_voltage2: BUCK2 DVS mode 2 voltage register
* @buck1_set1: BUCK1 gpio pin 1 to set output voltage * @buck1_set1: BUCK1 gpio pin 1 to set output voltage
* @buck1_set2: BUCK1 gpio pin 2 to set output voltage * @buck1_set2: BUCK1 gpio pin 2 to set output voltage
* @buck1_default_idx: Default for BUCK1 gpio pin 1, 2
* @buck2_set3: BUCK2 gpio pin to set output voltage * @buck2_set3: BUCK2 gpio pin to set output voltage
* @buck2_default_idx: Default for BUCK2 gpio pin.
* @wakeup: Allow to wake up from suspend
* @rtc_delay: LP3974 RTC chip bug that requires delay after a register
* write before reading it.
*/ */
struct max8998_platform_data { struct max8998_platform_data {
struct max8998_regulator_data *regulators; struct max8998_regulator_data *regulators;
int num_regulators; int num_regulators;
int irq_base; int irq_base;
int ono; int ono;
int buck1_max_voltage1; bool buck_voltage_lock;
int buck1_max_voltage2; int buck1_voltage1;
int buck2_max_voltage; int buck1_voltage2;
int buck1_voltage3;
int buck1_voltage4;
int buck2_voltage1;
int buck2_voltage2;
int buck1_set1; int buck1_set1;
int buck1_set2; int buck1_set2;
int buck1_default_idx;
int buck2_set3; int buck2_set3;
int buck2_default_idx;
bool wakeup;
bool rtc_delay;
}; };
#endif /* __LINUX_MFD_MAX8998_H */ #endif /* __LINUX_MFD_MAX8998_H */
...@@ -245,6 +245,7 @@ enum wm831x_parent { ...@@ -245,6 +245,7 @@ enum wm831x_parent {
WM8320 = 0x8320, WM8320 = 0x8320,
WM8321 = 0x8321, WM8321 = 0x8321,
WM8325 = 0x8325, WM8325 = 0x8325,
WM8326 = 0x8326,
}; };
struct wm831x { struct wm831x {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment