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)
  rtc: max8925: Add function to work as wakeup source
  mfd: Add pm ops to max8925
  mfd: Convert aat2870 to dev_pm_ops
  mfd: Still check other interrupts if we get a wm831x touchscreen IRQ
  mfd: Introduce missing kfree in 88pm860x probe routine
  mfd: Add S5M series configuration
  mfd: Add s5m series irq driver
  mfd: Add S5M core driver
  mfd: Improve mc13xxx dt binding document
  mfd: Fix stmpe section mismatch
  mfd: Fix stmpe build warning
  mfd: Fix STMPE I2c build failure
  mfd: Constify aat2870-core i2c_device_id table
  gpio: Add support for stmpe variant 801
  mfd: Add support for stmpe variant 801
  mfd: Add support for stmpe variant 610
  mfd: Add support for STMPE SPI interface
  mfd: Separate out STMPE controller and interface specific code
  misc: Remove max8997-muic sysfs attributes
  mfd: Remove unused wm831x_irq_data_to_mask_reg()
  ...

Fix up trivial conflict in drivers/leds/Kconfig due to addition of
LEDS_MAX8997 and LEDS_TCA6507 next to each other.
This commit is contained in:
Linus Torvalds 2012-01-13 20:43:32 -08:00
commit 21ebd6c68b
98 changed files with 3636 additions and 547 deletions

View file

@ -12,51 +12,20 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/mfd/88pm860x.h>
#include <linux/slab.h>
static inline int pm860x_read_device(struct i2c_client *i2c,
int reg, int bytes, void *dest)
{
unsigned char data;
int ret;
data = (unsigned char)reg;
ret = i2c_master_send(i2c, &data, 1);
if (ret < 0)
return ret;
ret = i2c_master_recv(i2c, dest, bytes);
if (ret < 0)
return ret;
return 0;
}
static inline int pm860x_write_device(struct i2c_client *i2c,
int reg, int bytes, void *src)
{
unsigned char buf[bytes + 1];
int ret;
buf[0] = (unsigned char)reg;
memcpy(&buf[1], src, bytes);
ret = i2c_master_send(i2c, buf, bytes + 1);
if (ret < 0)
return ret;
return 0;
}
int pm860x_reg_read(struct i2c_client *i2c, int reg)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char data;
struct regmap *map = (i2c == chip->client) ? chip->regmap
: chip->regmap_companion;
unsigned int data;
int ret;
mutex_lock(&chip->io_lock);
ret = pm860x_read_device(i2c, reg, 1, &data);
mutex_unlock(&chip->io_lock);
ret = regmap_read(map, reg, &data);
if (ret < 0)
return ret;
else
@ -68,12 +37,11 @@ int pm860x_reg_write(struct i2c_client *i2c, int reg,
unsigned char data)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
struct regmap *map = (i2c == chip->client) ? chip->regmap
: chip->regmap_companion;
int ret;
mutex_lock(&chip->io_lock);
ret = pm860x_write_device(i2c, reg, 1, &data);
mutex_unlock(&chip->io_lock);
ret = regmap_write(map, reg, data);
return ret;
}
EXPORT_SYMBOL(pm860x_reg_write);
@ -82,12 +50,11 @@ int pm860x_bulk_read(struct i2c_client *i2c, int reg,
int count, unsigned char *buf)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
struct regmap *map = (i2c == chip->client) ? chip->regmap
: chip->regmap_companion;
int ret;
mutex_lock(&chip->io_lock);
ret = pm860x_read_device(i2c, reg, count, buf);
mutex_unlock(&chip->io_lock);
ret = regmap_raw_read(map, reg, buf, count);
return ret;
}
EXPORT_SYMBOL(pm860x_bulk_read);
@ -96,12 +63,11 @@ int pm860x_bulk_write(struct i2c_client *i2c, int reg,
int count, unsigned char *buf)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
struct regmap *map = (i2c == chip->client) ? chip->regmap
: chip->regmap_companion;
int ret;
mutex_lock(&chip->io_lock);
ret = pm860x_write_device(i2c, reg, count, buf);
mutex_unlock(&chip->io_lock);
ret = regmap_raw_write(map, reg, buf, count);
return ret;
}
EXPORT_SYMBOL(pm860x_bulk_write);
@ -110,39 +76,78 @@ int pm860x_set_bits(struct i2c_client *i2c, int reg,
unsigned char mask, unsigned char data)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char value;
struct regmap *map = (i2c == chip->client) ? chip->regmap
: chip->regmap_companion;
int ret;
mutex_lock(&chip->io_lock);
ret = pm860x_read_device(i2c, reg, 1, &value);
if (ret < 0)
goto out;
value &= ~mask;
value |= data;
ret = pm860x_write_device(i2c, reg, 1, &value);
out:
mutex_unlock(&chip->io_lock);
ret = regmap_update_bits(map, reg, mask, data);
return ret;
}
EXPORT_SYMBOL(pm860x_set_bits);
static int read_device(struct i2c_client *i2c, int reg,
int bytes, void *dest)
{
unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX + 3];
unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX + 2];
struct i2c_adapter *adap = i2c->adapter;
struct i2c_msg msg[2] = {{i2c->addr, 0, 1, msgbuf0},
{i2c->addr, I2C_M_RD, 0, msgbuf1},
};
int num = 1, ret = 0;
if (dest == NULL)
return -EINVAL;
msgbuf0[0] = (unsigned char)reg; /* command */
msg[1].len = bytes;
/* if data needs to read back, num should be 2 */
if (bytes > 0)
num = 2;
ret = adap->algo->master_xfer(adap, msg, num);
memcpy(dest, msgbuf1, bytes);
if (ret < 0)
return ret;
return 0;
}
static int write_device(struct i2c_client *i2c, int reg,
int bytes, void *src)
{
unsigned char buf[bytes + 1];
struct i2c_adapter *adap = i2c->adapter;
struct i2c_msg msg;
int ret;
buf[0] = (unsigned char)reg;
memcpy(&buf[1], src, bytes);
msg.addr = i2c->addr;
msg.flags = 0;
msg.len = bytes + 1;
msg.buf = buf;
ret = adap->algo->master_xfer(adap, &msg, 1);
if (ret < 0)
return ret;
return 0;
}
int pm860x_page_reg_read(struct i2c_client *i2c, int reg)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char zero = 0;
unsigned char data;
int ret;
mutex_lock(&chip->io_lock);
pm860x_write_device(i2c, 0xFA, 0, &zero);
pm860x_write_device(i2c, 0xFB, 0, &zero);
pm860x_write_device(i2c, 0xFF, 0, &zero);
ret = pm860x_read_device(i2c, reg, 1, &data);
i2c_lock_adapter(i2c->adapter);
read_device(i2c, 0xFA, 0, &zero);
read_device(i2c, 0xFB, 0, &zero);
read_device(i2c, 0xFF, 0, &zero);
ret = read_device(i2c, reg, 1, &data);
if (ret >= 0)
ret = (int)data;
pm860x_write_device(i2c, 0xFE, 0, &zero);
pm860x_write_device(i2c, 0xFC, 0, &zero);
mutex_unlock(&chip->io_lock);
read_device(i2c, 0xFE, 0, &zero);
read_device(i2c, 0xFC, 0, &zero);
i2c_unlock_adapter(i2c->adapter);
return ret;
}
EXPORT_SYMBOL(pm860x_page_reg_read);
@ -150,18 +155,17 @@ EXPORT_SYMBOL(pm860x_page_reg_read);
int pm860x_page_reg_write(struct i2c_client *i2c, int reg,
unsigned char data)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char zero;
int ret;
mutex_lock(&chip->io_lock);
pm860x_write_device(i2c, 0xFA, 0, &zero);
pm860x_write_device(i2c, 0xFB, 0, &zero);
pm860x_write_device(i2c, 0xFF, 0, &zero);
ret = pm860x_write_device(i2c, reg, 1, &data);
pm860x_write_device(i2c, 0xFE, 0, &zero);
pm860x_write_device(i2c, 0xFC, 0, &zero);
mutex_unlock(&chip->io_lock);
i2c_lock_adapter(i2c->adapter);
read_device(i2c, 0xFA, 0, &zero);
read_device(i2c, 0xFB, 0, &zero);
read_device(i2c, 0xFF, 0, &zero);
ret = write_device(i2c, reg, 1, &data);
read_device(i2c, 0xFE, 0, &zero);
read_device(i2c, 0xFC, 0, &zero);
i2c_unlock_adapter(i2c->adapter);
return ret;
}
EXPORT_SYMBOL(pm860x_page_reg_write);
@ -169,18 +173,17 @@ EXPORT_SYMBOL(pm860x_page_reg_write);
int pm860x_page_bulk_read(struct i2c_client *i2c, int reg,
int count, unsigned char *buf)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char zero = 0;
int ret;
mutex_lock(&chip->io_lock);
pm860x_write_device(i2c, 0xFA, 0, &zero);
pm860x_write_device(i2c, 0xFB, 0, &zero);
pm860x_write_device(i2c, 0xFF, 0, &zero);
ret = pm860x_read_device(i2c, reg, count, buf);
pm860x_write_device(i2c, 0xFE, 0, &zero);
pm860x_write_device(i2c, 0xFC, 0, &zero);
mutex_unlock(&chip->io_lock);
i2c_lock_adapter(i2c->adapter);
read_device(i2c, 0xfa, 0, &zero);
read_device(i2c, 0xfb, 0, &zero);
read_device(i2c, 0xff, 0, &zero);
ret = read_device(i2c, reg, count, buf);
read_device(i2c, 0xFE, 0, &zero);
read_device(i2c, 0xFC, 0, &zero);
i2c_unlock_adapter(i2c->adapter);
return ret;
}
EXPORT_SYMBOL(pm860x_page_bulk_read);
@ -188,18 +191,18 @@ EXPORT_SYMBOL(pm860x_page_bulk_read);
int pm860x_page_bulk_write(struct i2c_client *i2c, int reg,
int count, unsigned char *buf)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char zero = 0;
int ret;
mutex_lock(&chip->io_lock);
pm860x_write_device(i2c, 0xFA, 0, &zero);
pm860x_write_device(i2c, 0xFB, 0, &zero);
pm860x_write_device(i2c, 0xFF, 0, &zero);
ret = pm860x_write_device(i2c, reg, count, buf);
pm860x_write_device(i2c, 0xFE, 0, &zero);
pm860x_write_device(i2c, 0xFC, 0, &zero);
mutex_unlock(&chip->io_lock);
i2c_lock_adapter(i2c->adapter);
read_device(i2c, 0xFA, 0, &zero);
read_device(i2c, 0xFB, 0, &zero);
read_device(i2c, 0xFF, 0, &zero);
ret = write_device(i2c, reg, count, buf);
read_device(i2c, 0xFE, 0, &zero);
read_device(i2c, 0xFC, 0, &zero);
i2c_unlock_adapter(i2c->adapter);
i2c_unlock_adapter(i2c->adapter);
return ret;
}
EXPORT_SYMBOL(pm860x_page_bulk_write);
@ -207,25 +210,24 @@ EXPORT_SYMBOL(pm860x_page_bulk_write);
int pm860x_page_set_bits(struct i2c_client *i2c, int reg,
unsigned char mask, unsigned char data)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char zero;
unsigned char value;
int ret;
mutex_lock(&chip->io_lock);
pm860x_write_device(i2c, 0xFA, 0, &zero);
pm860x_write_device(i2c, 0xFB, 0, &zero);
pm860x_write_device(i2c, 0xFF, 0, &zero);
ret = pm860x_read_device(i2c, reg, 1, &value);
i2c_lock_adapter(i2c->adapter);
read_device(i2c, 0xFA, 0, &zero);
read_device(i2c, 0xFB, 0, &zero);
read_device(i2c, 0xFF, 0, &zero);
ret = read_device(i2c, reg, 1, &value);
if (ret < 0)
goto out;
value &= ~mask;
value |= data;
ret = pm860x_write_device(i2c, reg, 1, &value);
ret = write_device(i2c, reg, 1, &value);
out:
pm860x_write_device(i2c, 0xFE, 0, &zero);
pm860x_write_device(i2c, 0xFC, 0, &zero);
mutex_unlock(&chip->io_lock);
read_device(i2c, 0xFE, 0, &zero);
read_device(i2c, 0xFC, 0, &zero);
i2c_unlock_adapter(i2c->adapter);
return ret;
}
EXPORT_SYMBOL(pm860x_page_set_bits);
@ -257,11 +259,17 @@ static int verify_addr(struct i2c_client *i2c)
return 0;
}
static struct regmap_config pm860x_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static int __devinit pm860x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pm860x_platform_data *pdata = client->dev.platform_data;
struct pm860x_chip *chip;
int ret;
if (!pdata) {
pr_info("No platform data in %s!\n", __func__);
@ -273,10 +281,17 @@ static int __devinit pm860x_probe(struct i2c_client *client,
return -ENOMEM;
chip->id = verify_addr(client);
chip->regmap = regmap_init_i2c(client, &pm860x_regmap_config);
if (IS_ERR(chip->regmap)) {
ret = PTR_ERR(chip->regmap);
dev_err(&client->dev, "Failed to allocate register map: %d\n",
ret);
kfree(chip);
return ret;
}
chip->client = client;
i2c_set_clientdata(client, chip);
chip->dev = &client->dev;
mutex_init(&chip->io_lock);
dev_set_drvdata(chip->dev, chip);
/*
@ -290,6 +305,14 @@ static int __devinit pm860x_probe(struct i2c_client *client,
chip->companion_addr = pdata->companion_addr;
chip->companion = i2c_new_dummy(chip->client->adapter,
chip->companion_addr);
chip->regmap_companion = regmap_init_i2c(chip->companion,
&pm860x_regmap_config);
if (IS_ERR(chip->regmap_companion)) {
ret = PTR_ERR(chip->regmap_companion);
dev_err(&chip->companion->dev,
"Failed to allocate register map: %d\n", ret);
return ret;
}
i2c_set_clientdata(chip->companion, chip);
}
@ -302,7 +325,11 @@ static int __devexit pm860x_remove(struct i2c_client *client)
struct pm860x_chip *chip = i2c_get_clientdata(client);
pm860x_device_exit(chip);
i2c_unregister_device(chip->companion);
if (chip->companion) {
regmap_exit(chip->regmap_companion);
i2c_unregister_device(chip->companion);
}
regmap_exit(chip->regmap);
kfree(chip);
return 0;
}

View file

@ -12,6 +12,7 @@ config MFD_CORE
config MFD_88PM860X
bool "Support Marvell 88PM8606/88PM8607"
depends on I2C=y && GENERIC_HARDIRQS
select REGMAP_I2C
select MFD_CORE
help
This supports for Marvell 88PM8606/88PM8607 Power Management IC.
@ -199,7 +200,7 @@ config MENELAUS
config TWL4030_CORE
bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support"
depends on I2C=y && GENERIC_HARDIRQS
depends on I2C=y && GENERIC_HARDIRQS && IRQ_DOMAIN
help
Say yes here if you have TWL4030 / TWL6030 family chip on your board.
This core driver provides register access and IRQ handling
@ -257,7 +258,7 @@ config TWL6040_CORE
config MFD_STMPE
bool "Support STMicroelectronics STMPE"
depends on I2C=y && GENERIC_HARDIRQS
depends on (I2C=y || SPI_MASTER=y) && GENERIC_HARDIRQS
select MFD_CORE
help
Support for the STMPE family of I/O Expanders from
@ -278,6 +279,23 @@ config MFD_STMPE
Keypad: stmpe-keypad
Touchscreen: stmpe-ts
menu "STMPE Interface Drivers"
depends on MFD_STMPE
config STMPE_I2C
bool "STMPE I2C Inteface"
depends on I2C=y
default y
help
This is used to enable I2C interface of STMPE
config STMPE_SPI
bool "STMPE SPI Inteface"
depends on SPI_MASTER
help
This is used to enable SPI interface of STMPE
endmenu
config MFD_TC3589X
bool "Support Toshiba TC35892 and variants"
depends on I2C=y && GENERIC_HARDIRQS
@ -311,7 +329,7 @@ config MFD_TC6387XB
config MFD_TC6393XB
bool "Support Toshiba TC6393XB"
depends on GPIOLIB && ARM
depends on GPIOLIB && ARM && HAVE_CLK
select MFD_CORE
select MFD_TMIO
help
@ -399,6 +417,17 @@ config MFD_MAX8998
additional drivers must be enabled in order to use the functionality
of the device.
config MFD_S5M_CORE
bool "SAMSUNG S5M Series Support"
depends on I2C=y && GENERIC_HARDIRQS
select MFD_CORE
select REGMAP_I2C
help
Support for the Samsung Electronics S5M MFD series.
This driver provies common support for accessing the device,
additional drivers must be enabled in order to use the functionality
of the device
config MFD_WM8400
tristate "Support Wolfson Microelectronics WM8400"
select MFD_CORE

View file

@ -16,6 +16,8 @@ obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
obj-$(CONFIG_MFD_TI_SSP) += ti-ssp.o
obj-$(CONFIG_MFD_STMPE) += stmpe.o
obj-$(CONFIG_STMPE_I2C) += stmpe-i2c.o
obj-$(CONFIG_STMPE_SPI) += stmpe-spi.o
obj-$(CONFIG_MFD_TC3589X) += tc3589x.o
obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o
@ -109,3 +111,4 @@ obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o
obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
obj-$(CONFIG_MFD_S5M_CORE) += s5m-core.o s5m-irq.o

View file

@ -407,13 +407,13 @@ static int aat2870_i2c_probe(struct i2c_client *client,
aat2870->init(aat2870);
if (aat2870->en_pin >= 0) {
ret = gpio_request(aat2870->en_pin, "aat2870-en");
ret = gpio_request_one(aat2870->en_pin, GPIOF_OUT_INIT_HIGH,
"aat2870-en");
if (ret < 0) {
dev_err(&client->dev,
"Failed to request GPIO %d\n", aat2870->en_pin);
goto out_kfree;
}
gpio_direction_output(aat2870->en_pin, 1);
}
aat2870_enable(aat2870);
@ -468,9 +468,10 @@ static int aat2870_i2c_remove(struct i2c_client *client)
return 0;
}
#ifdef CONFIG_PM
static int aat2870_i2c_suspend(struct i2c_client *client, pm_message_t state)
#ifdef CONFIG_PM_SLEEP
static int aat2870_i2c_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct aat2870_data *aat2870 = i2c_get_clientdata(client);
aat2870_disable(aat2870);
@ -478,8 +479,9 @@ static int aat2870_i2c_suspend(struct i2c_client *client, pm_message_t state)
return 0;
}
static int aat2870_i2c_resume(struct i2c_client *client)
static int aat2870_i2c_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct aat2870_data *aat2870 = i2c_get_clientdata(client);
struct aat2870_register *reg = NULL;
int i;
@ -495,12 +497,12 @@ static int aat2870_i2c_resume(struct i2c_client *client)
return 0;
}
#else
#define aat2870_i2c_suspend NULL
#define aat2870_i2c_resume NULL
#endif /* CONFIG_PM */
#endif /* CONFIG_PM_SLEEP */
static struct i2c_device_id aat2870_i2c_id_table[] = {
static SIMPLE_DEV_PM_OPS(aat2870_pm_ops, aat2870_i2c_suspend,
aat2870_i2c_resume);
static const struct i2c_device_id aat2870_i2c_id_table[] = {
{ "aat2870", 0 },
{ }
};
@ -510,11 +512,10 @@ static struct i2c_driver aat2870_i2c_driver = {
.driver = {
.name = "aat2870",
.owner = THIS_MODULE,
.pm = &aat2870_pm_ops,
},
.probe = aat2870_i2c_probe,
.remove = aat2870_i2c_remove,
.suspend = aat2870_i2c_suspend,
.resume = aat2870_i2c_resume,
.id_table = aat2870_i2c_id_table,
};

View file

@ -22,8 +22,8 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/random.h>
#include <linux/mfd/ab5500/ab5500.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab5500.h>
#include <linux/list.h>
#include <linux/bitops.h>
#include <linux/spinlock.h>

View file

@ -7,8 +7,8 @@
#include <linux/module.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/mfd/ab5500/ab5500.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab5500.h>
#include <linux/uaccess.h>
#include "ab5500-core.h"

View file

@ -17,7 +17,7 @@
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/ab8500.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/regulator/ab8500.h>
/*

View file

@ -13,7 +13,7 @@
#include <linux/platform_device.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/ab8500.h>
#include <linux/mfd/abx500/ab8500.h>
static u32 debug_bank;
static u32 debug_address;

View file

@ -18,9 +18,9 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/mfd/ab8500.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/ab8500/gpadc.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500/ab8500-gpadc.h>
/*
* GPADC register offsets

View file

@ -10,7 +10,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/ab8500.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/db8500-prcmu.h>
static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data)

View file

@ -7,9 +7,9 @@
#include <linux/err.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/ab8500.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/ab8500/sysctrl.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500/ab8500-sysctrl.h>
static struct device *sysctrl_dev;

View file

@ -172,14 +172,14 @@ static void __devexit cs5535_mfd_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
static struct pci_device_id cs5535_mfd_pci_tbl[] = {
static DEFINE_PCI_DEVICE_TABLE(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 = {
static struct pci_driver cs5535_mfd_driver = {
.name = DRV_NAME,
.id_table = cs5535_mfd_pci_tbl,
.probe = cs5535_mfd_probe,
@ -188,12 +188,12 @@ static struct pci_driver cs5535_mfd_drv = {
static int __init cs5535_mfd_init(void)
{
return pci_register_driver(&cs5535_mfd_drv);
return pci_register_driver(&cs5535_mfd_driver);
}
static void __exit cs5535_mfd_exit(void)
{
pci_unregister_driver(&cs5535_mfd_drv);
pci_unregister_driver(&cs5535_mfd_driver);
}
module_init(cs5535_mfd_init);

View file

@ -308,8 +308,7 @@ static int add_children(struct i2c_client *client)
for (i = 0; i < ARRAY_SIZE(config_inputs); i++) {
int gpio = dm355evm_msp_gpio.base + config_inputs[i].offset;
gpio_request(gpio, config_inputs[i].label);
gpio_direction_input(gpio);
gpio_request_one(gpio, GPIOF_IN, config_inputs[i].label);
/* make it easy for userspace to see these */
gpio_export(gpio, false);

View file

@ -485,17 +485,7 @@ static struct platform_driver intel_msic_driver = {
},
};
static int __init intel_msic_init(void)
{
return platform_driver_register(&intel_msic_driver);
}
module_init(intel_msic_init);
static void __exit intel_msic_exit(void)
{
platform_driver_unregister(&intel_msic_driver);
}
module_exit(intel_msic_exit);
module_platform_driver(intel_msic_driver);
MODULE_DESCRIPTION("Driver for Intel MSIC");
MODULE_AUTHOR("Mika Westerberg <[email protected]>");

View file

@ -181,7 +181,7 @@ static struct resource jz4740_battery_resources[] = {
},
};
const struct mfd_cell jz4740_adc_cells[] = {
static struct mfd_cell jz4740_adc_cells[] = {
{
.id = 0,
.name = "jz4740-hwmon",
@ -338,17 +338,7 @@ static struct platform_driver jz4740_adc_driver = {
},
};
static int __init jz4740_adc_init(void)
{
return platform_driver_register(&jz4740_adc_driver);
}
module_init(jz4740_adc_init);
static void __exit jz4740_adc_exit(void)
{
platform_driver_unregister(&jz4740_adc_driver);
}
module_exit(jz4740_adc_exit);
module_platform_driver(jz4740_adc_driver);
MODULE_DESCRIPTION("JZ4740 SoC ADC driver");
MODULE_AUTHOR("Lars-Peter Clausen <[email protected]>");

View file

@ -74,7 +74,7 @@ static struct mfd_cell tunnelcreek_cells[] = {
},
};
static struct pci_device_id lpc_sch_ids[] = {
static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) },
{ 0, }

View file

@ -161,6 +161,8 @@ static int __devinit max8925_probe(struct i2c_client *client,
chip->adc = i2c_new_dummy(chip->i2c->adapter, ADC_I2C_ADDR);
i2c_set_clientdata(chip->adc, chip);
device_init_wakeup(&client->dev, 1);
max8925_device_init(chip, pdata);
return 0;
@ -177,10 +179,35 @@ static int __devexit max8925_remove(struct i2c_client *client)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int max8925_suspend(struct device *dev)
{
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
struct max8925_chip *chip = i2c_get_clientdata(client);
if (device_may_wakeup(dev) && chip->wakeup_flag)
enable_irq_wake(chip->core_irq);
return 0;
}
static int max8925_resume(struct device *dev)
{
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
struct max8925_chip *chip = i2c_get_clientdata(client);
if (device_may_wakeup(dev) && chip->wakeup_flag)
disable_irq_wake(chip->core_irq);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(max8925_pm_ops, max8925_suspend, max8925_resume);
static struct i2c_driver max8925_driver = {
.driver = {
.name = "max8925",
.owner = THIS_MODULE,
.pm = &max8925_pm_ops,
},
.probe = max8925_probe,
.remove = __devexit_p(max8925_remove),

View file

@ -43,7 +43,8 @@ static struct mfd_cell max8997_devs[] = {
{ .name = "max8997-battery", },
{ .name = "max8997-haptic", },
{ .name = "max8997-muic", },
{ .name = "max8997-flash", },
{ .name = "max8997-led", .id = 1 },
{ .name = "max8997-led", .id = 2 },
};
int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)

View file

@ -176,6 +176,8 @@ static int max8998_i2c_probe(struct i2c_client *i2c,
if (ret < 0)
goto err;
device_init_wakeup(max8998->dev, max8998->wakeup);
return ret;
err:
@ -210,7 +212,7 @@ 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)
if (device_may_wakeup(dev))
irq_set_irq_wake(max8998->irq, 1);
return 0;
}
@ -220,7 +222,7 @@ 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)
if (device_may_wakeup(dev))
irq_set_irq_wake(max8998->irq, 0);
/*
* In LP3974, if IRQ registers are not "read & clear"

View file

@ -18,11 +18,15 @@
#include <linux/spi/spi.h>
#include <linux/mfd/core.h>
#include <linux/mfd/mc13xxx.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
struct mc13xxx {
struct spi_device *spidev;
struct mutex lock;
int irq;
int flags;
irq_handler_t irqhandler[MC13XXX_NUM_IRQ];
void *irqdata[MC13XXX_NUM_IRQ];
@ -550,10 +554,7 @@ static const char *mc13xxx_get_chipname(struct mc13xxx *mc13xxx)
int mc13xxx_get_flags(struct mc13xxx *mc13xxx)
{
struct mc13xxx_platform_data *pdata =
dev_get_platdata(&mc13xxx->spidev->dev);
return pdata->flags;
return mc13xxx->flags;
}
EXPORT_SYMBOL(mc13xxx_get_flags);
@ -615,13 +616,13 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
break;
case MC13XXX_ADC_MODE_SINGLE_CHAN:
adc0 |= old_adc0 & MC13XXX_ADC0_TSMOD_MASK;
adc0 |= old_adc0 & MC13XXX_ADC0_CONFIG_MASK;
adc1 |= (channel & 0x7) << MC13XXX_ADC1_CHAN0_SHIFT;
adc1 |= MC13XXX_ADC1_RAND;
break;
case MC13XXX_ADC_MODE_MULT_CHAN:
adc0 |= old_adc0 & MC13XXX_ADC0_TSMOD_MASK;
adc0 |= old_adc0 & MC13XXX_ADC0_CONFIG_MASK;
adc1 |= 4 << MC13XXX_ADC1_CHAN1_SHIFT;
break;
@ -696,17 +697,67 @@ static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format)
return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL, 0);
}
#ifdef CONFIG_OF
static int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx)
{
struct device_node *np = mc13xxx->spidev->dev.of_node;
if (!np)
return -ENODEV;
if (of_get_property(np, "fsl,mc13xxx-uses-adc", NULL))
mc13xxx->flags |= MC13XXX_USE_ADC;
if (of_get_property(np, "fsl,mc13xxx-uses-codec", NULL))
mc13xxx->flags |= MC13XXX_USE_CODEC;
if (of_get_property(np, "fsl,mc13xxx-uses-rtc", NULL))
mc13xxx->flags |= MC13XXX_USE_RTC;
if (of_get_property(np, "fsl,mc13xxx-uses-touch", NULL))
mc13xxx->flags |= MC13XXX_USE_TOUCHSCREEN;
return 0;
}
#else
static inline int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx)
{
return -ENODEV;
}
#endif
static const struct spi_device_id mc13xxx_device_id[] = {
{
.name = "mc13783",
.driver_data = MC13XXX_ID_MC13783,
}, {
.name = "mc13892",
.driver_data = MC13XXX_ID_MC13892,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(spi, mc13xxx_device_id);
static const struct of_device_id mc13xxx_dt_ids[] = {
{ .compatible = "fsl,mc13783", .data = (void *) MC13XXX_ID_MC13783, },
{ .compatible = "fsl,mc13892", .data = (void *) MC13XXX_ID_MC13892, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mc13xxx_dt_ids);
static int mc13xxx_probe(struct spi_device *spi)
{
const struct of_device_id *of_id;
struct spi_driver *sdrv = to_spi_driver(spi->dev.driver);
struct mc13xxx *mc13xxx;
struct mc13xxx_platform_data *pdata = dev_get_platdata(&spi->dev);
enum mc13xxx_id id;
int ret;
if (!pdata) {
dev_err(&spi->dev, "invalid platform data\n");
return -EINVAL;
}
of_id = of_match_device(mc13xxx_dt_ids, &spi->dev);
if (of_id)
sdrv->id_table = &mc13xxx_device_id[(enum mc13xxx_id) of_id->data];
mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL);
if (!mc13xxx)
@ -749,28 +800,33 @@ err_revision:
mc13xxx_unlock(mc13xxx);
if (pdata->flags & MC13XXX_USE_ADC)
if (mc13xxx_probe_flags_dt(mc13xxx) < 0 && pdata)
mc13xxx->flags = pdata->flags;
if (mc13xxx->flags & MC13XXX_USE_ADC)
mc13xxx_add_subdevice(mc13xxx, "%s-adc");
if (pdata->flags & MC13XXX_USE_CODEC)
if (mc13xxx->flags & MC13XXX_USE_CODEC)
mc13xxx_add_subdevice(mc13xxx, "%s-codec");
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
&pdata->regulators, sizeof(pdata->regulators));
if (pdata->flags & MC13XXX_USE_RTC)
if (mc13xxx->flags & MC13XXX_USE_RTC)
mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
if (pdata->flags & MC13XXX_USE_TOUCHSCREEN)
if (mc13xxx->flags & MC13XXX_USE_TOUCHSCREEN)
mc13xxx_add_subdevice(mc13xxx, "%s-ts");
if (pdata->leds)
if (pdata) {
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
&pdata->regulators, sizeof(pdata->regulators));
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led",
pdata->leds, sizeof(*pdata->leds));
if (pdata->buttons)
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-pwrbutton",
pdata->buttons, sizeof(*pdata->buttons));
} else {
mc13xxx_add_subdevice(mc13xxx, "%s-regulator");
mc13xxx_add_subdevice(mc13xxx, "%s-led");
mc13xxx_add_subdevice(mc13xxx, "%s-pwrbutton");
}
return 0;
}
@ -788,25 +844,12 @@ static int __devexit mc13xxx_remove(struct spi_device *spi)
return 0;
}
static const struct spi_device_id mc13xxx_device_id[] = {
{
.name = "mc13783",
.driver_data = MC13XXX_ID_MC13783,
}, {
.name = "mc13892",
.driver_data = MC13XXX_ID_MC13892,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(spi, mc13xxx_device_id);
static struct spi_driver mc13xxx_driver = {
.id_table = mc13xxx_device_id,
.driver = {
.name = "mc13xxx",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.of_match_table = mc13xxx_dt_ids,
},
.probe = mc13xxx_probe,
.remove = __devexit_p(mc13xxx_remove),

View file

@ -26,9 +26,35 @@
#define to_mcp(d) container_of(d, struct mcp, attached_device)
#define to_mcp_driver(d) container_of(d, struct mcp_driver, drv)
static const struct mcp_device_id *mcp_match_id(const struct mcp_device_id *id,
const char *codec)
{
while (id->name[0]) {
if (strcmp(codec, id->name) == 0)
return id;
id++;
}
return NULL;
}
const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp)
{
const struct mcp_driver *driver =
to_mcp_driver(mcp->attached_device.driver);
return mcp_match_id(driver->id_table, mcp->codec);
}
EXPORT_SYMBOL(mcp_get_device_id);
static int mcp_bus_match(struct device *dev, struct device_driver *drv)
{
return 1;
const struct mcp *mcp = to_mcp(dev);
const struct mcp_driver *driver = to_mcp_driver(drv);
if (driver->id_table)
return !!mcp_match_id(driver->id_table, mcp->codec);
return 0;
}
static int mcp_bus_probe(struct device *dev)
@ -74,9 +100,18 @@ static int mcp_bus_resume(struct device *dev)
return ret;
}
static int mcp_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct mcp *mcp = to_mcp(dev);
add_uevent_var(env, "MODALIAS=%s%s", MCP_MODULE_PREFIX, mcp->codec);
return 0;
}
static struct bus_type mcp_bus_type = {
.name = "mcp",
.match = mcp_bus_match,
.uevent = mcp_bus_uevent,
.probe = mcp_bus_probe,
.remove = mcp_bus_remove,
.suspend = mcp_bus_suspend,
@ -212,9 +247,14 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size)
}
EXPORT_SYMBOL(mcp_host_alloc);
int mcp_host_register(struct mcp *mcp)
int mcp_host_register(struct mcp *mcp, void *pdata)
{
if (!mcp->codec)
return -EINVAL;
mcp->attached_device.platform_data = pdata;
dev_set_name(&mcp->attached_device, "mcp0");
request_module("%s%s", MCP_MODULE_PREFIX, mcp->codec);
return device_register(&mcp->attached_device);
}
EXPORT_SYMBOL(mcp_host_register);

View file

@ -19,6 +19,7 @@
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/mfd/mcp.h>
#include <linux/io.h>
#include <mach/dma.h>
#include <mach/hardware.h>
@ -26,12 +27,19 @@
#include <asm/system.h>
#include <mach/mcp.h>
#include <mach/assabet.h>
/* Register offsets */
#define MCCR0 0x00
#define MCDR0 0x08
#define MCDR1 0x0C
#define MCDR2 0x10
#define MCSR 0x18
#define MCCR1 0x00
struct mcp_sa11x0 {
u32 mccr0;
u32 mccr1;
u32 mccr0;
u32 mccr1;
unsigned char *mccr0_base;
unsigned char *mccr1_base;
};
#define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp))
@ -39,25 +47,25 @@ struct mcp_sa11x0 {
static void
mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
{
unsigned int mccr0;
struct mcp_sa11x0 *priv = priv(mcp);
divisor /= 32;
mccr0 = Ser4MCCR0 & ~0x00007f00;
mccr0 |= divisor << 8;
Ser4MCCR0 = mccr0;
priv->mccr0 &= ~0x00007f00;
priv->mccr0 |= divisor << 8;
__raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
}
static void
mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
{
unsigned int mccr0;
struct mcp_sa11x0 *priv = priv(mcp);
divisor /= 32;
mccr0 = Ser4MCCR0 & ~0x0000007f;
mccr0 |= divisor;
Ser4MCCR0 = mccr0;
priv->mccr0 &= ~0x0000007f;
priv->mccr0 |= divisor;
__raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
}
/*
@ -71,12 +79,16 @@ mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val)
{
int ret = -ETIME;
int i;
u32 mcpreg;
struct mcp_sa11x0 *priv = priv(mcp);
Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
mcpreg = reg << 17 | MCDR2_Wr | (val & 0xffff);
__raw_writel(mcpreg, priv->mccr0_base + MCDR2);
for (i = 0; i < 2; i++) {
udelay(mcp->rw_timeout);
if (Ser4MCSR & MCSR_CWC) {
mcpreg = __raw_readl(priv->mccr0_base + MCSR);
if (mcpreg & MCSR_CWC) {
ret = 0;
break;
}
@ -97,13 +109,18 @@ mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
{
int ret = -ETIME;
int i;
u32 mcpreg;
struct mcp_sa11x0 *priv = priv(mcp);
Ser4MCDR2 = reg << 17 | MCDR2_Rd;
mcpreg = reg << 17 | MCDR2_Rd;
__raw_writel(mcpreg, priv->mccr0_base + MCDR2);
for (i = 0; i < 2; i++) {
udelay(mcp->rw_timeout);
if (Ser4MCSR & MCSR_CRC) {
ret = Ser4MCDR2 & 0xffff;
mcpreg = __raw_readl(priv->mccr0_base + MCSR);
if (mcpreg & MCSR_CRC) {
ret = __raw_readl(priv->mccr0_base + MCDR2)
& 0xffff;
break;
}
}
@ -116,13 +133,19 @@ mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
static void mcp_sa11x0_enable(struct mcp *mcp)
{
Ser4MCSR = -1;
Ser4MCCR0 |= MCCR0_MCE;
struct mcp_sa11x0 *priv = priv(mcp);
__raw_writel(-1, priv->mccr0_base + MCSR);
priv->mccr0 |= MCCR0_MCE;
__raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
}
static void mcp_sa11x0_disable(struct mcp *mcp)
{
Ser4MCCR0 &= ~MCCR0_MCE;
struct mcp_sa11x0 *priv = priv(mcp);
priv->mccr0 &= ~MCCR0_MCE;
__raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
}
/*
@ -142,50 +165,69 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
struct mcp_plat_data *data = pdev->dev.platform_data;
struct mcp *mcp;
int ret;
struct mcp_sa11x0 *priv;
struct resource *res_mem0, *res_mem1;
u32 size0, size1;
if (!data)
return -ENODEV;
if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp"))
if (!data->codec)
return -ENODEV;
res_mem0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res_mem0)
return -ENODEV;
size0 = res_mem0->end - res_mem0->start + 1;
res_mem1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!res_mem1)
return -ENODEV;
size1 = res_mem1->end - res_mem1->start + 1;
if (!request_mem_region(res_mem0->start, size0, "sa11x0-mcp"))
return -EBUSY;
if (!request_mem_region(res_mem1->start, size1, "sa11x0-mcp")) {
ret = -EBUSY;
goto release;
}
mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0));
if (!mcp) {
ret = -ENOMEM;
goto release;
goto release2;
}
priv = priv(mcp);
mcp->owner = THIS_MODULE;
mcp->ops = &mcp_sa11x0;
mcp->sclk_rate = data->sclk_rate;
mcp->dma_audio_rd = DMA_Ser4MCP0Rd;
mcp->dma_audio_wr = DMA_Ser4MCP0Wr;
mcp->dma_telco_rd = DMA_Ser4MCP1Rd;
mcp->dma_telco_wr = DMA_Ser4MCP1Wr;
mcp->gpio_base = data->gpio_base;
mcp->dma_audio_rd = DDAR_DevAdd(res_mem0->start + MCDR0)
+ DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev;
mcp->dma_audio_wr = DDAR_DevAdd(res_mem0->start + MCDR0)
+ DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev;
mcp->dma_telco_rd = DDAR_DevAdd(res_mem0->start + MCDR1)
+ DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev;
mcp->dma_telco_wr = DDAR_DevAdd(res_mem0->start + MCDR1)
+ DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev;
mcp->codec = data->codec;
platform_set_drvdata(pdev, mcp);
if (machine_is_assabet()) {
ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
}
/*
* Setup the PPC unit correctly.
*/
PPDR &= ~PPC_RXD4;
PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
PSDR |= PPC_RXD4;
PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
/*
* Initialise device. Note that we initially
* set the sampling rate to minimum.
*/
Ser4MCSR = -1;
Ser4MCCR1 = data->mccr1;
Ser4MCCR0 = data->mccr0 | 0x7f7f;
priv->mccr0_base = ioremap(res_mem0->start, size0);
priv->mccr1_base = ioremap(res_mem1->start, size1);
__raw_writel(-1, priv->mccr0_base + MCSR);
priv->mccr1 = data->mccr1;
priv->mccr0 = data->mccr0 | 0x7f7f;
__raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
__raw_writel(priv->mccr1, priv->mccr1_base + MCCR1);
/*
* Calculate the read/write timeout (us) from the bit clock
@ -195,36 +237,53 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
mcp->sclk_rate;
ret = mcp_host_register(mcp);
ret = mcp_host_register(mcp, data->codec_pdata);
if (ret == 0)
goto out;
release2:
release_mem_region(res_mem1->start, size1);
release:
release_mem_region(0x80060000, 0x60);
release_mem_region(res_mem0->start, size0);
platform_set_drvdata(pdev, NULL);
out:
return ret;
}
static int mcp_sa11x0_remove(struct platform_device *dev)
static int mcp_sa11x0_remove(struct platform_device *pdev)
{
struct mcp *mcp = platform_get_drvdata(dev);
struct mcp *mcp = platform_get_drvdata(pdev);
struct mcp_sa11x0 *priv = priv(mcp);
struct resource *res_mem;
u32 size;
platform_set_drvdata(dev, NULL);
platform_set_drvdata(pdev, NULL);
mcp_host_unregister(mcp);
release_mem_region(0x80060000, 0x60);
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res_mem) {
size = res_mem->end - res_mem->start + 1;
release_mem_region(res_mem->start, size);
}
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (res_mem) {
size = res_mem->end - res_mem->start + 1;
release_mem_region(res_mem->start, size);
}
iounmap(priv->mccr0_base);
iounmap(priv->mccr1_base);
return 0;
}
static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state)
{
struct mcp *mcp = platform_get_drvdata(dev);
struct mcp_sa11x0 *priv = priv(mcp);
u32 mccr0;
priv(mcp)->mccr0 = Ser4MCCR0;
priv(mcp)->mccr1 = Ser4MCCR1;
Ser4MCCR0 &= ~MCCR0_MCE;
mccr0 = priv->mccr0 & ~MCCR0_MCE;
__raw_writel(mccr0, priv->mccr0_base + MCCR0);
return 0;
}
@ -232,9 +291,10 @@ static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state)
static int mcp_sa11x0_resume(struct platform_device *dev)
{
struct mcp *mcp = platform_get_drvdata(dev);
struct mcp_sa11x0 *priv = priv(mcp);
Ser4MCCR1 = priv(mcp)->mccr1;
Ser4MCCR0 = priv(mcp)->mccr0;
__raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
__raw_writel(priv->mccr1, priv->mccr1_base + MCCR1);
return 0;
}
@ -251,24 +311,14 @@ static struct platform_driver mcp_sa11x0_driver = {
.resume = mcp_sa11x0_resume,
.driver = {
.name = "sa11x0-mcp",
.owner = THIS_MODULE,
},
};
/*
* This needs re-working
*/
static int __init mcp_sa11x0_init(void)
{
return platform_driver_register(&mcp_sa11x0_driver);
}
static void __exit mcp_sa11x0_exit(void)
{
platform_driver_unregister(&mcp_sa11x0_driver);
}
module_init(mcp_sa11x0_init);
module_exit(mcp_sa11x0_exit);
module_platform_driver(mcp_sa11x0_driver);
MODULE_AUTHOR("Russell King <[email protected]>");
MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");

View file

@ -503,19 +503,13 @@ static void omap_usbhs_init(struct device *dev)
spin_lock_irqsave(&omap->lock, flags);
if (pdata->ehci_data->phy_reset) {
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) {
gpio_request(pdata->ehci_data->reset_gpio_port[0],
"USB1 PHY reset");
gpio_direction_output
(pdata->ehci_data->reset_gpio_port[0], 0);
}
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
gpio_request_one(pdata->ehci_data->reset_gpio_port[0],
GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) {
gpio_request(pdata->ehci_data->reset_gpio_port[1],
"USB2 PHY reset");
gpio_direction_output
(pdata->ehci_data->reset_gpio_port[1], 0);
}
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
gpio_request_one(pdata->ehci_data->reset_gpio_port[1],
GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
/* Hold the PHY in RESET for enough time till DIR is high */
udelay(10);

View file

@ -249,17 +249,7 @@ static struct platform_driver pcf50633_adc_driver = {
.remove = __devexit_p(pcf50633_adc_remove),
};
static int __init pcf50633_adc_init(void)
{
return platform_driver_register(&pcf50633_adc_driver);
}
module_init(pcf50633_adc_init);
static void __exit pcf50633_adc_exit(void)
{
platform_driver_unregister(&pcf50633_adc_driver);
}
module_exit(pcf50633_adc_exit);
module_platform_driver(pcf50633_adc_driver);
MODULE_AUTHOR("Balaji Rao <[email protected]>");
MODULE_DESCRIPTION("PCF50633 adc driver");

176
drivers/mfd/s5m-core.c Normal file
View file

@ -0,0 +1,176 @@
/*
* s5m87xx.c
*
* Copyright (c) 2011 Samsung Electronics Co., Ltd
* http://www.samsung.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
#include <linux/mutex.h>
#include <linux/mfd/core.h>
#include <linux/mfd/s5m87xx/s5m-core.h>
#include <linux/mfd/s5m87xx/s5m-pmic.h>
#include <linux/mfd/s5m87xx/s5m-rtc.h>
#include <linux/regmap.h>
static struct mfd_cell s5m87xx_devs[] = {
{
.name = "s5m8767-pmic",
}, {
.name = "s5m-rtc",
},
};
int s5m_reg_read(struct s5m87xx_dev *s5m87xx, u8 reg, void *dest)
{
return regmap_read(s5m87xx->regmap, reg, dest);
}
EXPORT_SYMBOL_GPL(s5m_reg_read);
int s5m_bulk_read(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf)
{
return regmap_bulk_read(s5m87xx->regmap, reg, buf, count);;
}
EXPORT_SYMBOL_GPL(s5m_bulk_read);
int s5m_reg_write(struct s5m87xx_dev *s5m87xx, u8 reg, u8 value)
{
return regmap_write(s5m87xx->regmap, reg, value);
}
EXPORT_SYMBOL_GPL(s5m_reg_write);
int s5m_bulk_write(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf)
{
return regmap_raw_write(s5m87xx->regmap, reg, buf, count * sizeof(u16));
}
EXPORT_SYMBOL_GPL(s5m_bulk_write);
int s5m_reg_update(struct s5m87xx_dev *s5m87xx, u8 reg, u8 val, u8 mask)
{
return regmap_update_bits(s5m87xx->regmap, reg, mask, val);
}
EXPORT_SYMBOL_GPL(s5m_reg_update);
static struct regmap_config s5m_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static int s5m87xx_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct s5m_platform_data *pdata = i2c->dev.platform_data;
struct s5m87xx_dev *s5m87xx;
int ret = 0;
int error;
s5m87xx = kzalloc(sizeof(struct s5m87xx_dev), GFP_KERNEL);
if (s5m87xx == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, s5m87xx);
s5m87xx->dev = &i2c->dev;
s5m87xx->i2c = i2c;
s5m87xx->irq = i2c->irq;
s5m87xx->type = id->driver_data;
if (pdata) {
s5m87xx->device_type = pdata->device_type;
s5m87xx->ono = pdata->ono;
s5m87xx->irq_base = pdata->irq_base;
s5m87xx->wakeup = pdata->wakeup;
}
s5m87xx->regmap = regmap_init_i2c(i2c, &s5m_regmap_config);
if (IS_ERR(s5m87xx->regmap)) {
error = PTR_ERR(s5m87xx->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
error);
goto err;
}
s5m87xx->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR);
i2c_set_clientdata(s5m87xx->rtc, s5m87xx);
if (pdata->cfg_pmic_irq)
pdata->cfg_pmic_irq();
s5m_irq_init(s5m87xx);
pm_runtime_set_active(s5m87xx->dev);
ret = mfd_add_devices(s5m87xx->dev, -1,
s5m87xx_devs, ARRAY_SIZE(s5m87xx_devs),
NULL, 0);
if (ret < 0)
goto err;
return ret;
err:
mfd_remove_devices(s5m87xx->dev);
s5m_irq_exit(s5m87xx);
i2c_unregister_device(s5m87xx->rtc);
regmap_exit(s5m87xx->regmap);
kfree(s5m87xx);
return ret;
}
static int s5m87xx_i2c_remove(struct i2c_client *i2c)
{
struct s5m87xx_dev *s5m87xx = i2c_get_clientdata(i2c);
mfd_remove_devices(s5m87xx->dev);
s5m_irq_exit(s5m87xx);
i2c_unregister_device(s5m87xx->rtc);
regmap_exit(s5m87xx->regmap);
kfree(s5m87xx);
return 0;
}
static const struct i2c_device_id s5m87xx_i2c_id[] = {
{ "s5m87xx", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, s5m87xx_i2c_id);
static struct i2c_driver s5m87xx_i2c_driver = {
.driver = {
.name = "s5m87xx",
.owner = THIS_MODULE,
},
.probe = s5m87xx_i2c_probe,
.remove = s5m87xx_i2c_remove,
.id_table = s5m87xx_i2c_id,
};
static int __init s5m87xx_i2c_init(void)
{
return i2c_add_driver(&s5m87xx_i2c_driver);
}
subsys_initcall(s5m87xx_i2c_init);
static void __exit s5m87xx_i2c_exit(void)
{
i2c_del_driver(&s5m87xx_i2c_driver);
}
module_exit(s5m87xx_i2c_exit);
MODULE_AUTHOR("Sangbeom Kim <[email protected]>");
MODULE_DESCRIPTION("Core support for the S5M MFD");
MODULE_LICENSE("GPL");

487
drivers/mfd/s5m-irq.c Normal file
View file

@ -0,0 +1,487 @@
/*
* s5m-irq.c
*
* Copyright (c) 2011 Samsung Electronics Co., Ltd
* http://www.samsung.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/mfd/s5m87xx/s5m-core.h>
struct s5m_irq_data {
int reg;
int mask;
};
static struct s5m_irq_data s5m8767_irqs[] = {
[S5M8767_IRQ_PWRR] = {
.reg = 1,
.mask = S5M8767_IRQ_PWRR_MASK,
},
[S5M8767_IRQ_PWRF] = {
.reg = 1,
.mask = S5M8767_IRQ_PWRF_MASK,
},
[S5M8767_IRQ_PWR1S] = {
.reg = 1,
.mask = S5M8767_IRQ_PWR1S_MASK,
},
[S5M8767_IRQ_JIGR] = {
.reg = 1,
.mask = S5M8767_IRQ_JIGR_MASK,
},
[S5M8767_IRQ_JIGF] = {
.reg = 1,
.mask = S5M8767_IRQ_JIGF_MASK,
},
[S5M8767_IRQ_LOWBAT2] = {
.reg = 1,
.mask = S5M8767_IRQ_LOWBAT2_MASK,
},
[S5M8767_IRQ_LOWBAT1] = {
.reg = 1,
.mask = S5M8767_IRQ_LOWBAT1_MASK,
},
[S5M8767_IRQ_MRB] = {
.reg = 2,
.mask = S5M8767_IRQ_MRB_MASK,
},
[S5M8767_IRQ_DVSOK2] = {
.reg = 2,
.mask = S5M8767_IRQ_DVSOK2_MASK,
},
[S5M8767_IRQ_DVSOK3] = {
.reg = 2,
.mask = S5M8767_IRQ_DVSOK3_MASK,
},
[S5M8767_IRQ_DVSOK4] = {
.reg = 2,
.mask = S5M8767_IRQ_DVSOK4_MASK,
},
[S5M8767_IRQ_RTC60S] = {
.reg = 3,
.mask = S5M8767_IRQ_RTC60S_MASK,
},
[S5M8767_IRQ_RTCA1] = {
.reg = 3,
.mask = S5M8767_IRQ_RTCA1_MASK,
},
[S5M8767_IRQ_RTCA2] = {
.reg = 3,
.mask = S5M8767_IRQ_RTCA2_MASK,
},
[S5M8767_IRQ_SMPL] = {
.reg = 3,
.mask = S5M8767_IRQ_SMPL_MASK,
},
[S5M8767_IRQ_RTC1S] = {
.reg = 3,
.mask = S5M8767_IRQ_RTC1S_MASK,
},
[S5M8767_IRQ_WTSR] = {
.reg = 3,
.mask = S5M8767_IRQ_WTSR_MASK,
},
};
static struct s5m_irq_data s5m8763_irqs[] = {
[S5M8763_IRQ_DCINF] = {
.reg = 1,
.mask = S5M8763_IRQ_DCINF_MASK,
},
[S5M8763_IRQ_DCINR] = {
.reg = 1,
.mask = S5M8763_IRQ_DCINR_MASK,
},
[S5M8763_IRQ_JIGF] = {
.reg = 1,
.mask = S5M8763_IRQ_JIGF_MASK,
},
[S5M8763_IRQ_JIGR] = {
.reg = 1,
.mask = S5M8763_IRQ_JIGR_MASK,
},
[S5M8763_IRQ_PWRONF] = {
.reg = 1,
.mask = S5M8763_IRQ_PWRONF_MASK,
},
[S5M8763_IRQ_PWRONR] = {
.reg = 1,
.mask = S5M8763_IRQ_PWRONR_MASK,
},
[S5M8763_IRQ_WTSREVNT] = {
.reg = 2,
.mask = S5M8763_IRQ_WTSREVNT_MASK,
},
[S5M8763_IRQ_SMPLEVNT] = {
.reg = 2,
.mask = S5M8763_IRQ_SMPLEVNT_MASK,
},
[S5M8763_IRQ_ALARM1] = {
.reg = 2,
.mask = S5M8763_IRQ_ALARM1_MASK,
},
[S5M8763_IRQ_ALARM0] = {
.reg = 2,
.mask = S5M8763_IRQ_ALARM0_MASK,
},
[S5M8763_IRQ_ONKEY1S] = {
.reg = 3,
.mask = S5M8763_IRQ_ONKEY1S_MASK,
},
[S5M8763_IRQ_TOPOFFR] = {
.reg = 3,
.mask = S5M8763_IRQ_TOPOFFR_MASK,
},
[S5M8763_IRQ_DCINOVPR] = {
.reg = 3,
.mask = S5M8763_IRQ_DCINOVPR_MASK,
},
[S5M8763_IRQ_CHGRSTF] = {
.reg = 3,
.mask = S5M8763_IRQ_CHGRSTF_MASK,
},
[S5M8763_IRQ_DONER] = {
.reg = 3,
.mask = S5M8763_IRQ_DONER_MASK,
},
[S5M8763_IRQ_CHGFAULT] = {
.reg = 3,
.mask = S5M8763_IRQ_CHGFAULT_MASK,
},
[S5M8763_IRQ_LOBAT1] = {
.reg = 4,
.mask = S5M8763_IRQ_LOBAT1_MASK,
},
[S5M8763_IRQ_LOBAT2] = {
.reg = 4,
.mask = S5M8763_IRQ_LOBAT2_MASK,
},
};
static inline struct s5m_irq_data *
irq_to_s5m8767_irq(struct s5m87xx_dev *s5m87xx, int irq)
{
return &s5m8767_irqs[irq - s5m87xx->irq_base];
}
static void s5m8767_irq_lock(struct irq_data *data)
{
struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
mutex_lock(&s5m87xx->irqlock);
}
static void s5m8767_irq_sync_unlock(struct irq_data *data)
{
struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
int i;
for (i = 0; i < ARRAY_SIZE(s5m87xx->irq_masks_cur); i++) {
if (s5m87xx->irq_masks_cur[i] != s5m87xx->irq_masks_cache[i]) {
s5m87xx->irq_masks_cache[i] = s5m87xx->irq_masks_cur[i];
s5m_reg_write(s5m87xx, S5M8767_REG_INT1M + i,
s5m87xx->irq_masks_cur[i]);
}
}
mutex_unlock(&s5m87xx->irqlock);
}
static void s5m8767_irq_unmask(struct irq_data *data)
{
struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
struct s5m_irq_data *irq_data = irq_to_s5m8767_irq(s5m87xx,
data->irq);
s5m87xx->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
}
static void s5m8767_irq_mask(struct irq_data *data)
{
struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
struct s5m_irq_data *irq_data = irq_to_s5m8767_irq(s5m87xx,
data->irq);
s5m87xx->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
}
static struct irq_chip s5m8767_irq_chip = {
.name = "s5m8767",
.irq_bus_lock = s5m8767_irq_lock,
.irq_bus_sync_unlock = s5m8767_irq_sync_unlock,
.irq_mask = s5m8767_irq_mask,
.irq_unmask = s5m8767_irq_unmask,
};
static inline struct s5m_irq_data *
irq_to_s5m8763_irq(struct s5m87xx_dev *s5m87xx, int irq)
{
return &s5m8763_irqs[irq - s5m87xx->irq_base];
}
static void s5m8763_irq_lock(struct irq_data *data)
{
struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
mutex_lock(&s5m87xx->irqlock);
}
static void s5m8763_irq_sync_unlock(struct irq_data *data)
{
struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
int i;
for (i = 0; i < ARRAY_SIZE(s5m87xx->irq_masks_cur); i++) {
if (s5m87xx->irq_masks_cur[i] != s5m87xx->irq_masks_cache[i]) {
s5m87xx->irq_masks_cache[i] = s5m87xx->irq_masks_cur[i];
s5m_reg_write(s5m87xx, S5M8763_REG_IRQM1 + i,
s5m87xx->irq_masks_cur[i]);
}
}
mutex_unlock(&s5m87xx->irqlock);
}
static void s5m8763_irq_unmask(struct irq_data *data)
{
struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
struct s5m_irq_data *irq_data = irq_to_s5m8763_irq(s5m87xx,
data->irq);
s5m87xx->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
}
static void s5m8763_irq_mask(struct irq_data *data)
{
struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
struct s5m_irq_data *irq_data = irq_to_s5m8763_irq(s5m87xx,
data->irq);
s5m87xx->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
}
static struct irq_chip s5m8763_irq_chip = {
.name = "s5m8763",
.irq_bus_lock = s5m8763_irq_lock,
.irq_bus_sync_unlock = s5m8763_irq_sync_unlock,
.irq_mask = s5m8763_irq_mask,
.irq_unmask = s5m8763_irq_unmask,
};
static irqreturn_t s5m8767_irq_thread(int irq, void *data)
{
struct s5m87xx_dev *s5m87xx = data;
u8 irq_reg[NUM_IRQ_REGS-1];
int ret;
int i;
ret = s5m_bulk_read(s5m87xx, S5M8767_REG_INT1,
NUM_IRQ_REGS - 1, irq_reg);
if (ret < 0) {
dev_err(s5m87xx->dev, "Failed to read interrupt register: %d\n",
ret);
return IRQ_NONE;
}
for (i = 0; i < NUM_IRQ_REGS - 1; i++)
irq_reg[i] &= ~s5m87xx->irq_masks_cur[i];
for (i = 0; i < S5M8767_IRQ_NR; i++) {
if (irq_reg[s5m8767_irqs[i].reg - 1] & s5m8767_irqs[i].mask)
handle_nested_irq(s5m87xx->irq_base + i);
}
return IRQ_HANDLED;
}
static irqreturn_t s5m8763_irq_thread(int irq, void *data)
{
struct s5m87xx_dev *s5m87xx = data;
u8 irq_reg[NUM_IRQ_REGS];
int ret;
int i;
ret = s5m_bulk_read(s5m87xx, S5M8763_REG_IRQ1,
NUM_IRQ_REGS, irq_reg);
if (ret < 0) {
dev_err(s5m87xx->dev, "Failed to read interrupt register: %d\n",
ret);
return IRQ_NONE;
}
for (i = 0; i < NUM_IRQ_REGS; i++)
irq_reg[i] &= ~s5m87xx->irq_masks_cur[i];
for (i = 0; i < S5M8763_IRQ_NR; i++) {
if (irq_reg[s5m8763_irqs[i].reg - 1] & s5m8763_irqs[i].mask)
handle_nested_irq(s5m87xx->irq_base + i);
}
return IRQ_HANDLED;
}
int s5m_irq_resume(struct s5m87xx_dev *s5m87xx)
{
if (s5m87xx->irq && s5m87xx->irq_base){
switch (s5m87xx->device_type) {
case S5M8763X:
s5m8763_irq_thread(s5m87xx->irq_base, s5m87xx);
break;
case S5M8767X:
s5m8767_irq_thread(s5m87xx->irq_base, s5m87xx);
break;
default:
break;
}
}
return 0;
}
int s5m_irq_init(struct s5m87xx_dev *s5m87xx)
{
int i;
int cur_irq;
int ret = 0;
int type = s5m87xx->device_type;
if (!s5m87xx->irq) {
dev_warn(s5m87xx->dev,
"No interrupt specified, no interrupts\n");
s5m87xx->irq_base = 0;
return 0;
}
if (!s5m87xx->irq_base) {
dev_err(s5m87xx->dev,
"No interrupt base specified, no interrupts\n");
return 0;
}
mutex_init(&s5m87xx->irqlock);
switch (type) {
case S5M8763X:
for (i = 0; i < NUM_IRQ_REGS; i++) {
s5m87xx->irq_masks_cur[i] = 0xff;
s5m87xx->irq_masks_cache[i] = 0xff;
s5m_reg_write(s5m87xx, S5M8763_REG_IRQM1 + i,
0xff);
}
s5m_reg_write(s5m87xx, S5M8763_REG_STATUSM1, 0xff);
s5m_reg_write(s5m87xx, S5M8763_REG_STATUSM2, 0xff);
for (i = 0; i < S5M8763_IRQ_NR; i++) {
cur_irq = i + s5m87xx->irq_base;
irq_set_chip_data(cur_irq, s5m87xx);
irq_set_chip_and_handler(cur_irq, &s5m8763_irq_chip,
handle_edge_irq);
irq_set_nested_thread(cur_irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(cur_irq, IRQF_VALID);
#else
irq_set_noprobe(cur_irq);
#endif
}
ret = request_threaded_irq(s5m87xx->irq, NULL,
s5m8763_irq_thread,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"s5m87xx-irq", s5m87xx);
if (ret) {
dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n",
s5m87xx->irq, ret);
return ret;
}
break;
case S5M8767X:
for (i = 0; i < NUM_IRQ_REGS - 1; i++) {
s5m87xx->irq_masks_cur[i] = 0xff;
s5m87xx->irq_masks_cache[i] = 0xff;
s5m_reg_write(s5m87xx, S5M8767_REG_INT1M + i,
0xff);
}
for (i = 0; i < S5M8767_IRQ_NR; i++) {
cur_irq = i + s5m87xx->irq_base;
irq_set_chip_data(cur_irq, s5m87xx);
if (ret) {
dev_err(s5m87xx->dev,
"Failed to irq_set_chip_data %d: %d\n",
s5m87xx->irq, ret);
return ret;
}
irq_set_chip_and_handler(cur_irq, &s5m8767_irq_chip,
handle_edge_irq);
irq_set_nested_thread(cur_irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(cur_irq, IRQF_VALID);
#else
irq_set_noprobe(cur_irq);
#endif
}
ret = request_threaded_irq(s5m87xx->irq, NULL,
s5m8767_irq_thread,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"s5m87xx-irq", s5m87xx);
if (ret) {
dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n",
s5m87xx->irq, ret);
return ret;
}
break;
default:
break;
}
if (!s5m87xx->ono)
return 0;
switch (type) {
case S5M8763X:
ret = request_threaded_irq(s5m87xx->ono, NULL,
s5m8763_irq_thread,
IRQF_TRIGGER_FALLING |
IRQF_TRIGGER_RISING |
IRQF_ONESHOT, "s5m87xx-ono",
s5m87xx);
break;
case S5M8767X:
ret = request_threaded_irq(s5m87xx->ono, NULL,
s5m8767_irq_thread,
IRQF_TRIGGER_FALLING |
IRQF_TRIGGER_RISING |
IRQF_ONESHOT, "s5m87xx-ono", s5m87xx);
break;
default:
break;
}
if (ret)
dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n",
s5m87xx->ono, ret);
return 0;
}
void s5m_irq_exit(struct s5m87xx_dev *s5m87xx)
{
if (s5m87xx->ono)
free_irq(s5m87xx->ono, s5m87xx);
if (s5m87xx->irq)
free_irq(s5m87xx->irq, s5m87xx);
}

View file

@ -1720,7 +1720,7 @@ static int sm501_plat_remove(struct platform_device *dev)
return 0;
}
static struct pci_device_id sm501_pci_tbl[] = {
static DEFINE_PCI_DEVICE_TABLE(sm501_pci_tbl) = {
{ 0x126f, 0x0501, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0, },
};

109
drivers/mfd/stmpe-i2c.c Normal file
View file

@ -0,0 +1,109 @@
/*
* ST Microelectronics MFD: stmpe's i2c client specific driver
*
* Copyright (C) ST-Ericsson SA 2010
* Copyright (C) ST Microelectronics SA 2011
*
* License Terms: GNU General Public License, version 2
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
* Author: Viresh Kumar <viresh.kumar@st.com> for ST Microelectronics
*/
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include "stmpe.h"
static int i2c_reg_read(struct stmpe *stmpe, u8 reg)
{
struct i2c_client *i2c = stmpe->client;
return i2c_smbus_read_byte_data(i2c, reg);
}
static int i2c_reg_write(struct stmpe *stmpe, u8 reg, u8 val)
{
struct i2c_client *i2c = stmpe->client;
return i2c_smbus_write_byte_data(i2c, reg, val);
}
static int i2c_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values)
{
struct i2c_client *i2c = stmpe->client;
return i2c_smbus_read_i2c_block_data(i2c, reg, length, values);
}
static int i2c_block_write(struct stmpe *stmpe, u8 reg, u8 length,
const u8 *values)
{
struct i2c_client *i2c = stmpe->client;
return i2c_smbus_write_i2c_block_data(i2c, reg, length, values);
}
static struct stmpe_client_info i2c_ci = {
.read_byte = i2c_reg_read,
.write_byte = i2c_reg_write,
.read_block = i2c_block_read,
.write_block = i2c_block_write,
};
static int __devinit
stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
i2c_ci.data = (void *)id;
i2c_ci.irq = i2c->irq;
i2c_ci.client = i2c;
i2c_ci.dev = &i2c->dev;
return stmpe_probe(&i2c_ci, id->driver_data);
}
static int __devexit stmpe_i2c_remove(struct i2c_client *i2c)
{
struct stmpe *stmpe = dev_get_drvdata(&i2c->dev);
return stmpe_remove(stmpe);
}
static const struct i2c_device_id stmpe_i2c_id[] = {
{ "stmpe610", STMPE610 },
{ "stmpe801", STMPE801 },
{ "stmpe811", STMPE811 },
{ "stmpe1601", STMPE1601 },
{ "stmpe2401", STMPE2401 },
{ "stmpe2403", STMPE2403 },
{ }
};
MODULE_DEVICE_TABLE(i2c, stmpe_id);
static struct i2c_driver stmpe_i2c_driver = {
.driver.name = "stmpe-i2c",
.driver.owner = THIS_MODULE,
#ifdef CONFIG_PM
.driver.pm = &stmpe_dev_pm_ops,
#endif
.probe = stmpe_i2c_probe,
.remove = __devexit_p(stmpe_i2c_remove),
.id_table = stmpe_i2c_id,
};
static int __init stmpe_init(void)
{
return i2c_add_driver(&stmpe_i2c_driver);
}
subsys_initcall(stmpe_init);
static void __exit stmpe_exit(void)
{
i2c_del_driver(&stmpe_i2c_driver);
}
module_exit(stmpe_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("STMPE MFD I2C Interface Driver");
MODULE_AUTHOR("Rabin Vincent <[email protected]>");

150
drivers/mfd/stmpe-spi.c Normal file
View file

@ -0,0 +1,150 @@
/*
* ST Microelectronics MFD: stmpe's spi client specific driver
*
* Copyright (C) ST Microelectronics SA 2011
*
* License Terms: GNU General Public License, version 2
* Author: Viresh Kumar <viresh.kumar@st.com> for ST Microelectronics
*/
#include <linux/spi/spi.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include "stmpe.h"
#define READ_CMD (1 << 7)
static int spi_reg_read(struct stmpe *stmpe, u8 reg)
{
struct spi_device *spi = stmpe->client;
int status = spi_w8r16(spi, reg | READ_CMD);
return (status < 0) ? status : status >> 8;
}
static int spi_reg_write(struct stmpe *stmpe, u8 reg, u8 val)
{
struct spi_device *spi = stmpe->client;
u16 cmd = (val << 8) | reg;
return spi_write(spi, (const u8 *)&cmd, 2);
}
static int spi_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values)
{
int ret, i;
for (i = 0; i < length; i++) {
ret = spi_reg_read(stmpe, reg + i);
if (ret < 0)
return ret;
*(values + i) = ret;
}
return 0;
}
static int spi_block_write(struct stmpe *stmpe, u8 reg, u8 length,
const u8 *values)
{
int ret = 0, i;
for (i = length; i > 0; i--, reg++) {
ret = spi_reg_write(stmpe, reg, *(values + i - 1));
if (ret < 0)
return ret;
}
return ret;
}
static void spi_init(struct stmpe *stmpe)
{
struct spi_device *spi = stmpe->client;
spi->bits_per_word = 8;
/* This register is only present for stmpe811 */
if (stmpe->variant->id_val == 0x0811)
spi_reg_write(stmpe, STMPE811_REG_SPI_CFG, spi->mode);
if (spi_setup(spi) < 0)
dev_dbg(&spi->dev, "spi_setup failed\n");
}
static struct stmpe_client_info spi_ci = {
.read_byte = spi_reg_read,
.write_byte = spi_reg_write,
.read_block = spi_block_read,
.write_block = spi_block_write,
.init = spi_init,
};
static int __devinit
stmpe_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
/* don't exceed max specified rate - 1MHz - Limitation of STMPE */
if (spi->max_speed_hz > 1000000) {
dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
(spi->max_speed_hz/1000));
return -EINVAL;
}
spi_ci.irq = spi->irq;
spi_ci.client = spi;
spi_ci.dev = &spi->dev;
return stmpe_probe(&spi_ci, id->driver_data);
}
static int __devexit stmpe_spi_remove(struct spi_device *spi)
{
struct stmpe *stmpe = dev_get_drvdata(&spi->dev);
return stmpe_remove(stmpe);
}
static const struct spi_device_id stmpe_spi_id[] = {
{ "stmpe610", STMPE610 },
{ "stmpe801", STMPE801 },
{ "stmpe811", STMPE811 },
{ "stmpe1601", STMPE1601 },
{ "stmpe2401", STMPE2401 },
{ "stmpe2403", STMPE2403 },
{ }
};
MODULE_DEVICE_TABLE(spi, stmpe_id);
static struct spi_driver stmpe_spi_driver = {
.driver = {
.name = "stmpe-spi",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &stmpe_dev_pm_ops,
#endif
},
.probe = stmpe_spi_probe,
.remove = __devexit_p(stmpe_spi_remove),
.id_table = stmpe_spi_id,
};
static int __init stmpe_init(void)
{
return spi_register_driver(&stmpe_spi_driver);
}
subsys_initcall(stmpe_init);
static void __exit stmpe_exit(void)
{
spi_unregister_driver(&stmpe_spi_driver);
}
module_exit(stmpe_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("STMPE MFD SPI Interface Driver");
MODULE_AUTHOR("Viresh Kumar <[email protected]>");

View file

@ -1,18 +1,20 @@
/*
* ST Microelectronics MFD: stmpe's driver
*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License, version 2
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
*/
#include <linux/gpio.h>
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/mfd/core.h>
#include <linux/mfd/stmpe.h>
#include "stmpe.h"
static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks)
@ -29,10 +31,9 @@ static int __stmpe_reg_read(struct stmpe *stmpe, u8 reg)
{
int ret;
ret = i2c_smbus_read_byte_data(stmpe->i2c, reg);
ret = stmpe->ci->read_byte(stmpe, reg);
if (ret < 0)
dev_err(stmpe->dev, "failed to read reg %#x: %d\n",
reg, ret);
dev_err(stmpe->dev, "failed to read reg %#x: %d\n", reg, ret);
dev_vdbg(stmpe->dev, "rd: reg %#x => data %#x\n", reg, ret);
@ -45,10 +46,9 @@ static int __stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val)
dev_vdbg(stmpe->dev, "wr: reg %#x <= %#x\n", reg, val);
ret = i2c_smbus_write_byte_data(stmpe->i2c, reg, val);
ret = stmpe->ci->write_byte(stmpe, reg, val);
if (ret < 0)
dev_err(stmpe->dev, "failed to write reg %#x: %d\n",
reg, ret);
dev_err(stmpe->dev, "failed to write reg %#x: %d\n", reg, ret);
return ret;
}
@ -72,10 +72,9 @@ static int __stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length,
{
int ret;
ret = i2c_smbus_read_i2c_block_data(stmpe->i2c, reg, length, values);
ret = stmpe->ci->read_block(stmpe, reg, length, values);
if (ret < 0)
dev_err(stmpe->dev, "failed to read regs %#x: %d\n",
reg, ret);
dev_err(stmpe->dev, "failed to read regs %#x: %d\n", reg, ret);
dev_vdbg(stmpe->dev, "rd: reg %#x (%d) => ret %#x\n", reg, length, ret);
stmpe_dump_bytes("stmpe rd: ", values, length);
@ -91,11 +90,9 @@ static int __stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length,
dev_vdbg(stmpe->dev, "wr: regs %#x (%d)\n", reg, length);
stmpe_dump_bytes("stmpe wr: ", values, length);
ret = i2c_smbus_write_i2c_block_data(stmpe->i2c, reg, length,
values);
ret = stmpe->ci->write_block(stmpe, reg, length, values);
if (ret < 0)
dev_err(stmpe->dev, "failed to write regs %#x: %d\n",
reg, ret);
dev_err(stmpe->dev, "failed to write regs %#x: %d\n", reg, ret);
return ret;
}
@ -245,12 +242,14 @@ int stmpe_set_altfunc(struct stmpe *stmpe, u32 pins, enum stmpe_block block)
u8 regaddr = stmpe->regs[STMPE_IDX_GPAFR_U_MSB];
int af_bits = variant->af_bits;
int numregs = DIV_ROUND_UP(stmpe->num_gpios * af_bits, 8);
int afperreg = 8 / af_bits;
int mask = (1 << af_bits) - 1;
u8 regs[numregs];
int af;
int ret;
int af, afperreg, ret;
if (!variant->get_altfunc)
return 0;
afperreg = 8 / af_bits;
mutex_lock(&stmpe->lock);
ret = __stmpe_enable(stmpe, STMPE_BLOCK_GPIO);
@ -325,7 +324,51 @@ static struct mfd_cell stmpe_keypad_cell = {
};
/*
* Touchscreen (STMPE811)
* STMPE801
*/
static const u8 stmpe801_regs[] = {
[STMPE_IDX_CHIP_ID] = STMPE801_REG_CHIP_ID,
[STMPE_IDX_ICR_LSB] = STMPE801_REG_SYS_CTRL,
[STMPE_IDX_GPMR_LSB] = STMPE801_REG_GPIO_MP_STA,
[STMPE_IDX_GPSR_LSB] = STMPE801_REG_GPIO_SET_PIN,
[STMPE_IDX_GPCR_LSB] = STMPE801_REG_GPIO_SET_PIN,
[STMPE_IDX_GPDR_LSB] = STMPE801_REG_GPIO_DIR,
[STMPE_IDX_IEGPIOR_LSB] = STMPE801_REG_GPIO_INT_EN,
[STMPE_IDX_ISGPIOR_MSB] = STMPE801_REG_GPIO_INT_STA,
};
static struct stmpe_variant_block stmpe801_blocks[] = {
{
.cell = &stmpe_gpio_cell,
.irq = 0,
.block = STMPE_BLOCK_GPIO,
},
};
static int stmpe801_enable(struct stmpe *stmpe, unsigned int blocks,
bool enable)
{
if (blocks & STMPE_BLOCK_GPIO)
return 0;
else
return -EINVAL;
}
static struct stmpe_variant_info stmpe801 = {
.name = "stmpe801",
.id_val = STMPE801_ID,
.id_mask = 0xffff,
.num_gpios = 8,
.regs = stmpe801_regs,
.blocks = stmpe801_blocks,
.num_blocks = ARRAY_SIZE(stmpe801_blocks),
.num_irqs = STMPE801_NR_INTERNAL_IRQS,
.enable = stmpe801_enable,
};
/*
* Touchscreen (STMPE811 or STMPE610)
*/
static struct resource stmpe_ts_resources[] = {
@ -350,7 +393,7 @@ static struct mfd_cell stmpe_ts_cell = {
};
/*
* STMPE811
* STMPE811 or STMPE610
*/
static const u8 stmpe811_regs[] = {
@ -421,6 +464,21 @@ static struct stmpe_variant_info stmpe811 = {
.get_altfunc = stmpe811_get_altfunc,
};
/* Similar to 811, except number of gpios */
static struct stmpe_variant_info stmpe610 = {
.name = "stmpe610",
.id_val = 0x0811,
.id_mask = 0xffff,
.num_gpios = 6,
.af_bits = 1,
.regs = stmpe811_regs,
.blocks = stmpe811_blocks,
.num_blocks = ARRAY_SIZE(stmpe811_blocks),
.num_irqs = STMPE811_NR_INTERNAL_IRQS,
.enable = stmpe811_enable,
.get_altfunc = stmpe811_get_altfunc,
};
/*
* STMPE1601
*/
@ -655,6 +713,8 @@ static struct stmpe_variant_info stmpe2403 = {
};
static struct stmpe_variant_info *stmpe_variant_info[] = {
[STMPE610] = &stmpe610,
[STMPE801] = &stmpe801,
[STMPE811] = &stmpe811,
[STMPE1601] = &stmpe1601,
[STMPE2401] = &stmpe2401,
@ -671,6 +731,11 @@ static irqreturn_t stmpe_irq(int irq, void *data)
int ret;
int i;
if (variant->id_val == STMPE801_ID) {
handle_nested_irq(stmpe->irq_base);
return IRQ_HANDLED;
}
ret = stmpe_block_read(stmpe, israddr, num, isr);
if (ret < 0)
return IRQ_NONE;
@ -757,14 +822,17 @@ static struct irq_chip stmpe_irq_chip = {
static int __devinit stmpe_irq_init(struct stmpe *stmpe)
{
struct irq_chip *chip = NULL;
int num_irqs = stmpe->variant->num_irqs;
int base = stmpe->irq_base;
int irq;
if (stmpe->variant->id_val != STMPE801_ID)
chip = &stmpe_irq_chip;
for (irq = base; irq < base + num_irqs; irq++) {
irq_set_chip_data(irq, stmpe);
irq_set_chip_and_handler(irq, &stmpe_irq_chip,
handle_edge_irq);
irq_set_chip_and_handler(irq, chip, handle_edge_irq);
irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
@ -796,7 +864,7 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe)
unsigned int irq_trigger = stmpe->pdata->irq_trigger;
int autosleep_timeout = stmpe->pdata->autosleep_timeout;
struct stmpe_variant_info *variant = stmpe->variant;
u8 icr = STMPE_ICR_LSB_GIM;
u8 icr;
unsigned int id;
u8 data[2];
int ret;
@ -819,16 +887,32 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe)
if (ret)
return ret;
if (irq_trigger == IRQF_TRIGGER_FALLING ||
irq_trigger == IRQF_TRIGGER_RISING)
icr |= STMPE_ICR_LSB_EDGE;
if (id == STMPE801_ID)
icr = STMPE801_REG_SYS_CTRL_INT_EN;
else
icr = STMPE_ICR_LSB_GIM;
/* STMPE801 doesn't support Edge interrupts */
if (id != STMPE801_ID) {
if (irq_trigger == IRQF_TRIGGER_FALLING ||
irq_trigger == IRQF_TRIGGER_RISING)
icr |= STMPE_ICR_LSB_EDGE;
}
if (irq_trigger == IRQF_TRIGGER_RISING ||
irq_trigger == IRQF_TRIGGER_HIGH)
icr |= STMPE_ICR_LSB_HIGH;
irq_trigger == IRQF_TRIGGER_HIGH) {
if (id == STMPE801_ID)
icr |= STMPE801_REG_SYS_CTRL_INT_HI;
else
icr |= STMPE_ICR_LSB_HIGH;
}
if (stmpe->pdata->irq_invert_polarity)
icr ^= STMPE_ICR_LSB_HIGH;
if (stmpe->pdata->irq_invert_polarity) {
if (id == STMPE801_ID)
icr ^= STMPE801_REG_SYS_CTRL_INT_HI;
else
icr ^= STMPE_ICR_LSB_HIGH;
}
if (stmpe->pdata->autosleep) {
ret = stmpe_autosleep(stmpe, autosleep_timeout);
@ -873,32 +957,10 @@ static int __devinit stmpe_devices_init(struct stmpe *stmpe)
return ret;
}
#ifdef CONFIG_PM
static int stmpe_suspend(struct device *dev)
/* Called from client specific probe routines */
int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
{
struct i2c_client *i2c = to_i2c_client(dev);
if (device_may_wakeup(&i2c->dev))
enable_irq_wake(i2c->irq);
return 0;
}
static int stmpe_resume(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
if (device_may_wakeup(&i2c->dev))
disable_irq_wake(i2c->irq);
return 0;
}
#endif
static int __devinit stmpe_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct stmpe_platform_data *pdata = i2c->dev.platform_data;
struct stmpe_platform_data *pdata = dev_get_platdata(ci->dev);
struct stmpe *stmpe;
int ret;
@ -912,30 +974,43 @@ static int __devinit stmpe_probe(struct i2c_client *i2c,
mutex_init(&stmpe->irq_lock);
mutex_init(&stmpe->lock);
stmpe->dev = &i2c->dev;
stmpe->i2c = i2c;
stmpe->dev = ci->dev;
stmpe->client = ci->client;
stmpe->pdata = pdata;
stmpe->irq_base = pdata->irq_base;
stmpe->partnum = id->driver_data;
stmpe->variant = stmpe_variant_info[stmpe->partnum];
stmpe->ci = ci;
stmpe->partnum = partnum;
stmpe->variant = stmpe_variant_info[partnum];
stmpe->regs = stmpe->variant->regs;
stmpe->num_gpios = stmpe->variant->num_gpios;
dev_set_drvdata(stmpe->dev, stmpe);
i2c_set_clientdata(i2c, stmpe);
if (ci->init)
ci->init(stmpe);
if (pdata->irq_over_gpio) {
ret = gpio_request_one(pdata->irq_gpio, GPIOF_DIR_IN, "stmpe");
if (ret) {
dev_err(stmpe->dev, "failed to request IRQ GPIO: %d\n",
ret);
goto out_free;
}
stmpe->irq = gpio_to_irq(pdata->irq_gpio);
} else {
stmpe->irq = ci->irq;
}
ret = stmpe_chip_init(stmpe);
if (ret)
goto out_free;
goto free_gpio;
ret = stmpe_irq_init(stmpe);
if (ret)
goto out_free;
goto free_gpio;
ret = request_threaded_irq(stmpe->i2c->irq, NULL, stmpe_irq,
pdata->irq_trigger | IRQF_ONESHOT,
"stmpe", stmpe);
ret = request_threaded_irq(stmpe->irq, NULL, stmpe_irq,
pdata->irq_trigger | IRQF_ONESHOT, "stmpe", stmpe);
if (ret) {
dev_err(stmpe->dev, "failed to request IRQ: %d\n", ret);
goto out_removeirq;
@ -951,67 +1026,55 @@ static int __devinit stmpe_probe(struct i2c_client *i2c,
out_removedevs:
mfd_remove_devices(stmpe->dev);
free_irq(stmpe->i2c->irq, stmpe);
free_irq(stmpe->irq, stmpe);
out_removeirq:
stmpe_irq_remove(stmpe);
free_gpio:
if (pdata->irq_over_gpio)
gpio_free(pdata->irq_gpio);
out_free:
kfree(stmpe);
return ret;
}
static int __devexit stmpe_remove(struct i2c_client *client)
int stmpe_remove(struct stmpe *stmpe)
{
struct stmpe *stmpe = i2c_get_clientdata(client);
mfd_remove_devices(stmpe->dev);
free_irq(stmpe->i2c->irq, stmpe);
free_irq(stmpe->irq, stmpe);
stmpe_irq_remove(stmpe);
if (stmpe->pdata->irq_over_gpio)
gpio_free(stmpe->pdata->irq_gpio);
kfree(stmpe);
return 0;
}
static const struct i2c_device_id stmpe_id[] = {
{ "stmpe811", STMPE811 },
{ "stmpe1601", STMPE1601 },
{ "stmpe2401", STMPE2401 },
{ "stmpe2403", STMPE2403 },
{ }
};
MODULE_DEVICE_TABLE(i2c, stmpe_id);
#ifdef CONFIG_PM
static const struct dev_pm_ops stmpe_dev_pm_ops = {
static int stmpe_suspend(struct device *dev)
{
struct stmpe *stmpe = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
enable_irq_wake(stmpe->irq);
return 0;
}
static int stmpe_resume(struct device *dev)
{
struct stmpe *stmpe = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
disable_irq_wake(stmpe->irq);
return 0;
}
const struct dev_pm_ops stmpe_dev_pm_ops = {
.suspend = stmpe_suspend,
.resume = stmpe_resume,
};
#endif
static struct i2c_driver stmpe_driver = {
.driver.name = "stmpe",
.driver.owner = THIS_MODULE,
#ifdef CONFIG_PM
.driver.pm = &stmpe_dev_pm_ops,
#endif
.probe = stmpe_probe,
.remove = __devexit_p(stmpe_remove),
.id_table = stmpe_id,
};
static int __init stmpe_init(void)
{
return i2c_add_driver(&stmpe_driver);
}
subsys_initcall(stmpe_init);
static void __exit stmpe_exit(void)
{
i2c_del_driver(&stmpe_driver);
}
module_exit(stmpe_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("STMPE MFD core driver");
MODULE_AUTHOR("Rabin Vincent <[email protected]>");

View file

@ -8,6 +8,14 @@
#ifndef __STMPE_H
#define __STMPE_H
#include <linux/device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/stmpe.h>
#include <linux/printk.h>
#include <linux/types.h>
extern const struct dev_pm_ops stmpe_dev_pm_ops;
#ifdef STMPE_DUMP_BYTES
static inline void stmpe_dump_bytes(const char *str, const void *buf,
size_t len)
@ -67,10 +75,54 @@ struct stmpe_variant_info {
int (*enable_autosleep)(struct stmpe *stmpe, int autosleep_timeout);
};
/**
* struct stmpe_client_info - i2c or spi specific routines/info
* @data: client specific data
* @read_byte: read single byte
* @write_byte: write single byte
* @read_block: read block or multiple bytes
* @write_block: write block or multiple bytes
* @init: client init routine, called during probe
*/
struct stmpe_client_info {
void *data;
int irq;
void *client;
struct device *dev;
int (*read_byte)(struct stmpe *stmpe, u8 reg);
int (*write_byte)(struct stmpe *stmpe, u8 reg, u8 val);
int (*read_block)(struct stmpe *stmpe, u8 reg, u8 len, u8 *values);
int (*write_block)(struct stmpe *stmpe, u8 reg, u8 len,
const u8 *values);
void (*init)(struct stmpe *stmpe);
};
int stmpe_probe(struct stmpe_client_info *ci, int partnum);
int stmpe_remove(struct stmpe *stmpe);
#define STMPE_ICR_LSB_HIGH (1 << 2)
#define STMPE_ICR_LSB_EDGE (1 << 1)
#define STMPE_ICR_LSB_GIM (1 << 0)
/*
* STMPE801
*/
#define STMPE801_ID 0x0108
#define STMPE801_NR_INTERNAL_IRQS 1
#define STMPE801_REG_CHIP_ID 0x00
#define STMPE801_REG_VERSION_ID 0x02
#define STMPE801_REG_SYS_CTRL 0x04
#define STMPE801_REG_GPIO_INT_EN 0x08
#define STMPE801_REG_GPIO_INT_STA 0x09
#define STMPE801_REG_GPIO_MP_STA 0x10
#define STMPE801_REG_GPIO_SET_PIN 0x11
#define STMPE801_REG_GPIO_DIR 0x12
#define STMPE801_REG_SYS_CTRL_RESET (1 << 7)
#define STMPE801_REG_SYS_CTRL_INT_EN (1 << 2)
#define STMPE801_REG_SYS_CTRL_INT_HI (1 << 0)
/*
* STMPE811
*/
@ -87,6 +139,7 @@ struct stmpe_variant_info {
#define STMPE811_REG_CHIP_ID 0x00
#define STMPE811_REG_SYS_CTRL2 0x04
#define STMPE811_REG_SPI_CFG 0x08
#define STMPE811_REG_INT_CTRL 0x09
#define STMPE811_REG_INT_EN 0x0A
#define STMPE811_REG_INT_STA 0x0B

View file

@ -442,21 +442,7 @@ static struct platform_driver t7l66xb_platform_driver = {
/*--------------------------------------------------------------------------*/
static int __init t7l66xb_init(void)
{
int retval = 0;
retval = platform_driver_register(&t7l66xb_platform_driver);
return retval;
}
static void __exit t7l66xb_exit(void)
{
platform_driver_unregister(&t7l66xb_platform_driver);
}
module_init(t7l66xb_init);
module_exit(t7l66xb_exit);
module_platform_driver(t7l66xb_platform_driver);
MODULE_DESCRIPTION("Toshiba T7L66XB core driver");
MODULE_LICENSE("GPL v2");

View file

@ -234,19 +234,7 @@ static struct platform_driver tc6387xb_platform_driver = {
.resume = tc6387xb_resume,
};
static int __init tc6387xb_init(void)
{
return platform_driver_register(&tc6387xb_platform_driver);
}
static void __exit tc6387xb_exit(void)
{
platform_driver_unregister(&tc6387xb_platform_driver);
}
module_init(tc6387xb_init);
module_exit(tc6387xb_exit);
module_platform_driver(tc6387xb_platform_driver);
MODULE_DESCRIPTION("Toshiba TC6387XB core driver");
MODULE_LICENSE("GPL v2");

View file

@ -458,17 +458,7 @@ static struct platform_driver ti_ssp_driver = {
}
};
static int __init ti_ssp_init(void)
{
return platform_driver_register(&ti_ssp_driver);
}
module_init(ti_ssp_init);
static void __exit ti_ssp_exit(void)
{
platform_driver_unregister(&ti_ssp_driver);
}
module_exit(ti_ssp_exit);
module_platform_driver(ti_ssp_driver);
MODULE_DESCRIPTION("Sequencer Serial Port (SSP) Driver");
MODULE_AUTHOR("Cyril Chemparathy");

View file

@ -857,7 +857,7 @@ static void __devexit timb_remove(struct pci_dev *dev)
kfree(priv);
}
static struct pci_device_id timberdale_pci_tbl[] = {
static DEFINE_PCI_DEVICE_TABLE(timberdale_pci_tbl) = {
{ PCI_DEVICE(PCI_VENDOR_ID_TIMB, PCI_DEVICE_ID_TIMB) },
{ 0 }
};

View file

@ -215,6 +215,7 @@ int tps65910_irq_init(struct tps65910 *tps65910, int irq,
int tps65910_irq_exit(struct tps65910 *tps65910)
{
free_irq(tps65910->chip_irq, tps65910);
if (tps65910->chip_irq)
free_irq(tps65910->chip_irq, tps65910);
return 0;
}

View file

@ -172,15 +172,12 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
tps65910_gpio_init(tps65910, pmic_plat_data->gpio_base);
ret = tps65910_irq_init(tps65910, init_data->irq, init_data);
if (ret < 0)
goto err;
tps65910_irq_init(tps65910, init_data->irq, init_data);
kfree(init_data);
return ret;
err:
mfd_remove_devices(tps65910->dev);
kfree(tps65910);
kfree(init_data);
return ret;
@ -190,8 +187,8 @@ static int tps65910_i2c_remove(struct i2c_client *i2c)
{
struct tps65910 *tps65910 = i2c_get_clientdata(i2c);
mfd_remove_devices(tps65910->dev);
tps65910_irq_exit(tps65910);
mfd_remove_devices(tps65910->dev);
kfree(tps65910);
return 0;

View file

@ -111,7 +111,6 @@ static int __devexit tps65912_spi_remove(struct spi_device *spi)
static struct spi_driver tps65912_spi_driver = {
.driver = {
.name = "tps65912",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = tps65912_spi_probe,

View file

@ -34,6 +34,11 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/irqdomain.h>
#include <linux/regulator/machine.h>
@ -144,6 +149,9 @@
#define TWL_MODULE_LAST TWL4030_MODULE_LAST
#define TWL4030_NR_IRQS 8
#define TWL6030_NR_IRQS 20
/* Base Address defns for twl4030_map[] */
/* subchip/slave 0 - USB ID */
@ -255,6 +263,7 @@ struct twl_client {
static struct twl_client twl_modules[TWL_NUM_SLAVES];
static struct irq_domain domain;
/* mapping the module id to slave id and base address */
struct twl_mapping {
@ -1183,14 +1192,48 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
int status;
unsigned i;
struct twl4030_platform_data *pdata = client->dev.platform_data;
struct device_node *node = client->dev.of_node;
u8 temp;
int ret = 0;
int nr_irqs = TWL4030_NR_IRQS;
if ((id->driver_data) & TWL6030_CLASS)
nr_irqs = TWL6030_NR_IRQS;
if (node && !pdata) {
/*
* XXX: Temporary pdata until the information is correctly
* retrieved by every TWL modules from DT.
*/
pdata = devm_kzalloc(&client->dev,
sizeof(struct twl4030_platform_data),
GFP_KERNEL);
if (!pdata)
return -ENOMEM;
}
if (!pdata) {
dev_dbg(&client->dev, "no platform data?\n");
return -EINVAL;
}
status = irq_alloc_descs(-1, pdata->irq_base, nr_irqs, 0);
if (IS_ERR_VALUE(status)) {
dev_err(&client->dev, "Fail to allocate IRQ descs\n");
return status;
}
pdata->irq_base = status;
pdata->irq_end = pdata->irq_base + nr_irqs;
domain.irq_base = pdata->irq_base;
domain.nr_irq = nr_irqs;
#ifdef CONFIG_OF_IRQ
domain.of_node = of_node_get(node);
domain.ops = &irq_domain_simple_ops;
#endif
irq_domain_add(&domain);
if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
dev_dbg(&client->dev, "can't talk I2C?\n");
return -EIO;
@ -1270,7 +1313,13 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
}
status = add_children(pdata, id->driver_data);
#ifdef CONFIG_OF_DEVICE
if (node)
status = of_platform_populate(node, NULL, NULL, &client->dev);
else
#endif
status = add_children(pdata, id->driver_data);
fail:
if (status < 0)
twl_remove(client);

View file

@ -261,17 +261,7 @@ static struct platform_driver twl4030_audio_driver = {
},
};
static int __devinit twl4030_audio_init(void)
{
return platform_driver_register(&twl4030_audio_driver);
}
module_init(twl4030_audio_init);
static void __devexit twl4030_audio_exit(void)
{
platform_driver_unregister(&twl4030_audio_driver);
}
module_exit(twl4030_audio_exit);
module_platform_driver(twl4030_audio_driver);
MODULE_AUTHOR("Peter Ujfalusi <[email protected]>");
MODULE_LICENSE("GPL");

View file

@ -492,7 +492,7 @@ static void twl4030_sih_bus_sync_unlock(struct irq_data *data)
u8 bytes[4];
} imr;
/* byte[0] gets overwriten as we write ... */
/* byte[0] gets overwritten as we write ... */
imr.word = cpu_to_le32(agent->imr << 8);
agent->imr_change_pending = false;
@ -667,6 +667,7 @@ int twl4030_sih_setup(int module)
irq_set_chip_data(irq, agent);
irq_set_chip_and_handler(irq, &twl4030_sih_irq_chip,
handle_edge_irq);
irq_set_nested_thread(irq, 1);
activate_irq(irq);
}

View file

@ -807,19 +807,7 @@ static struct platform_driver twl4030_madc_driver = {
},
};
static int __init twl4030_madc_init(void)
{
return platform_driver_register(&twl4030_madc_driver);
}
module_init(twl4030_madc_init);
static void __exit twl4030_madc_exit(void)
{
platform_driver_unregister(&twl4030_madc_driver);
}
module_exit(twl4030_madc_exit);
module_platform_driver(twl4030_madc_driver);
MODULE_DESCRIPTION("TWL4030 ADC driver");
MODULE_LICENSE("GPL");

View file

@ -34,7 +34,8 @@
static u8 twl4030_start_script_address = 0x2b;
#define PWR_P1_SW_EVENTS 0x10
#define PWR_DEVOFF (1<<0)
#define PWR_DEVOFF (1 << 0)
#define SEQ_OFFSYNC (1 << 0)
#define PHY_TO_OFF_PM_MASTER(p) (p - 0x36)
#define PHY_TO_OFF_PM_RECEIVER(p) (p - 0x5b)
@ -511,12 +512,27 @@ int twl4030_remove_script(u8 flags)
return err;
}
/*
* In master mode, start the power off sequence.
* After a successful execution, TWL shuts down the power to the SoC
* and all peripherals connected to it.
*/
void twl4030_power_off(void)
{
int err;
err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, PWR_DEVOFF,
TWL4030_PM_MASTER_P1_SW_EVENTS);
if (err)
pr_err("TWL4030 Unable to power off\n");
}
void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
{
int err = 0;
int i;
struct twl4030_resconfig *resconfig;
u8 address = twl4030_start_script_address;
u8 val, address = twl4030_start_script_address;
err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
TWL4030_PM_MASTER_KEY_CFG1,
@ -548,6 +564,28 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
}
}
/* Board has to be wired properly to use this feature */
if (twl4030_scripts->use_poweroff && !pm_power_off) {
/* Default for SEQ_OFFSYNC is set, lets ensure this */
err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val,
TWL4030_PM_MASTER_CFG_P123_TRANSITION);
if (err) {
pr_warning("TWL4030 Unable to read registers\n");
} else if (!(val & SEQ_OFFSYNC)) {
val |= SEQ_OFFSYNC;
err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val,
TWL4030_PM_MASTER_CFG_P123_TRANSITION);
if (err) {
pr_err("TWL4030 Unable to setup SEQ_OFFSYNC\n");
goto relock;
}
}
pm_power_off = twl4030_power_off;
}
relock:
err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0,
TWL4030_PM_MASTER_PROTECT_KEY);
if (err)

View file

@ -509,13 +509,10 @@ static int __devinit twl6040_probe(struct platform_device *pdev)
twl6040->audpwron = -EINVAL;
if (gpio_is_valid(twl6040->audpwron)) {
ret = gpio_request(twl6040->audpwron, "audpwron");
ret = gpio_request_one(twl6040->audpwron, GPIOF_OUT_INIT_LOW,
"audpwron");
if (ret)
goto gpio1_err;
ret = gpio_direction_output(twl6040->audpwron, 0);
if (ret)
goto gpio2_err;
}
/* codec interrupt */
@ -619,18 +616,7 @@ static struct platform_driver twl6040_driver = {
},
};
static int __devinit twl6040_init(void)
{
return platform_driver_register(&twl6040_driver);
}
module_init(twl6040_init);
static void __devexit twl6040_exit(void)
{
platform_driver_unregister(&twl6040_driver);
}
module_exit(twl6040_exit);
module_platform_driver(twl6040_driver);
MODULE_DESCRIPTION("TWL6040 MFD");
MODULE_AUTHOR("Misael Lopez Cruz <[email protected]>");

View file

@ -36,6 +36,15 @@ static DEFINE_MUTEX(ucb1x00_mutex);
static LIST_HEAD(ucb1x00_drivers);
static LIST_HEAD(ucb1x00_devices);
static struct mcp_device_id ucb1x00_id[] = {
{ "ucb1x00", 0 }, /* auto-detection */
{ "ucb1200", UCB_ID_1200 },
{ "ucb1300", UCB_ID_1300 },
{ "tc35143", UCB_ID_TC35143 },
{ }
};
MODULE_DEVICE_TABLE(mcp, ucb1x00_id);
/**
* ucb1x00_io_set_dir - set IO direction
* @ucb: UCB1x00 structure describing chip
@ -527,17 +536,33 @@ static struct class ucb1x00_class = {
static int ucb1x00_probe(struct mcp *mcp)
{
const struct mcp_device_id *mid;
struct ucb1x00 *ucb;
struct ucb1x00_driver *drv;
struct ucb1x00_plat_data *pdata;
unsigned int id;
int ret = -ENODEV;
int temp;
mcp_enable(mcp);
id = mcp_reg_read(mcp, UCB_ID);
mid = mcp_get_device_id(mcp);
if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) {
printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
if (mid && mid->driver_data) {
if (id != mid->driver_data) {
printk(KERN_WARNING "%s wrong ID %04x found: %04x\n",
mid->name, (unsigned int) mid->driver_data, id);
goto err_disable;
}
} else {
mid = &ucb1x00_id[1];
while (mid->driver_data) {
if (id == mid->driver_data)
break;
mid++;
}
printk(KERN_WARNING "%s ID not found: %04x\n",
ucb1x00_id[0].name, id);
goto err_disable;
}
@ -546,28 +571,28 @@ static int ucb1x00_probe(struct mcp *mcp)
if (!ucb)
goto err_disable;
pdata = mcp->attached_device.platform_data;
ucb->dev.class = &ucb1x00_class;
ucb->dev.parent = &mcp->attached_device;
dev_set_name(&ucb->dev, "ucb1x00");
dev_set_name(&ucb->dev, mid->name);
spin_lock_init(&ucb->lock);
spin_lock_init(&ucb->io_lock);
sema_init(&ucb->adc_sem, 1);
ucb->id = id;
ucb->id = mid;
ucb->mcp = mcp;
ucb->irq = ucb1x00_detect_irq(ucb);
if (ucb->irq == NO_IRQ) {
printk(KERN_ERR "UCB1x00: IRQ probe failed\n");
printk(KERN_ERR "%s: IRQ probe failed\n", mid->name);
ret = -ENODEV;
goto err_free;
}
ucb->gpio.base = -1;
if (mcp->gpio_base != 0) {
if (pdata && (pdata->gpio_base >= 0)) {
ucb->gpio.label = dev_name(&ucb->dev);
ucb->gpio.base = mcp->gpio_base;
ucb->gpio.base = pdata->gpio_base;
ucb->gpio.ngpio = 10;
ucb->gpio.set = ucb1x00_gpio_set;
ucb->gpio.get = ucb1x00_gpio_get;
@ -580,10 +605,10 @@ static int ucb1x00_probe(struct mcp *mcp)
dev_info(&ucb->dev, "gpio_base not set so no gpiolib support");
ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING,
"UCB1x00", ucb);
mid->name, ucb);
if (ret) {
printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
ucb->irq, ret);
printk(KERN_ERR "%s: unable to grab irq%d: %d\n",
mid->name, ucb->irq, ret);
goto err_gpio;
}
@ -705,6 +730,7 @@ static struct mcp_driver ucb1x00_driver = {
.remove = ucb1x00_remove,
.suspend = ucb1x00_suspend,
.resume = ucb1x00_resume,
.id_table = ucb1x00_id,
};
static int __init ucb1x00_init(void)

View file

@ -382,7 +382,7 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
idev->name = "Touchscreen panel";
idev->id.product = ts->ucb->id;
idev->id.product = ts->ucb->id->driver_data;
idev->open = ucb1x00_ts_open;
idev->close = ucb1x00_ts_close;

View file

@ -118,7 +118,7 @@ static void __devexit vx855_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
static struct pci_device_id vx855_pci_tbl[] = {
static DEFINE_PCI_DEVICE_TABLE(vx855_pci_tbl) = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
{ 0, }
};

View file

@ -559,6 +559,8 @@ static int wm831x_write(struct wm831x *wm831x, unsigned short reg,
dev_vdbg(wm831x->dev, "Write %04x to R%d(0x%x)\n",
buf[i], reg + i, reg + i);
ret = regmap_write(wm831x->regmap, reg + i, buf[i]);
if (ret != 0)
return ret;
}
return 0;
@ -1875,7 +1877,6 @@ err_irq:
err_regmap:
mfd_remove_devices(wm831x->dev);
regmap_exit(wm831x->regmap);
kfree(wm831x);
return ret;
}
@ -1887,7 +1888,6 @@ void wm831x_device_exit(struct wm831x *wm831x)
free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x);
wm831x_irq_exit(wm831x);
regmap_exit(wm831x->regmap);
kfree(wm831x);
}
int wm831x_device_suspend(struct wm831x *wm831x)

View file

@ -30,7 +30,7 @@ static int wm831x_i2c_probe(struct i2c_client *i2c,
struct wm831x *wm831x;
int ret;
wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
wm831x = devm_kzalloc(&i2c->dev, sizeof(struct wm831x), GFP_KERNEL);
if (wm831x == NULL)
return -ENOMEM;
@ -42,7 +42,6 @@ static int wm831x_i2c_probe(struct i2c_client *i2c,
ret = PTR_ERR(wm831x->regmap);
dev_err(wm831x->dev, "Failed to allocate register map: %d\n",
ret);
kfree(wm831x);
return ret;
}

View file

@ -325,11 +325,6 @@ static inline int irq_data_to_status_reg(struct wm831x_irq_data *irq_data)
return WM831X_INTERRUPT_STATUS_1 - 1 + irq_data->reg;
}
static inline int irq_data_to_mask_reg(struct wm831x_irq_data *irq_data)
{
return WM831X_INTERRUPT_STATUS_1_MASK - 1 + irq_data->reg;
}
static inline struct wm831x_irq_data *irq_to_wm831x_irq(struct wm831x *wm831x,
int irq)
{
@ -477,8 +472,7 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHPD);
if (primary & WM831X_TCHDATA_INT)
handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHDATA);
if (primary & (WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT))
goto out;
primary &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT);
for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) {
int offset = wm831x_irqs[i].reg - 1;

View file

@ -30,7 +30,7 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
type = (enum wm831x_parent)id->driver_data;
wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
wm831x = devm_kzalloc(&spi->dev, sizeof(struct wm831x), GFP_KERNEL);
if (wm831x == NULL)
return -ENOMEM;
@ -45,7 +45,6 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
ret = PTR_ERR(wm831x->regmap);
dev_err(wm831x->dev, "Failed to allocate register map: %d\n",
ret);
kfree(wm831x);
return ret;
}
@ -95,7 +94,6 @@ MODULE_DEVICE_TABLE(spi, wm831x_spi_id);
static struct spi_driver wm831x_spi_driver = {
.driver = {
.name = "wm831x",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.pm = &wm831x_spi_pm,
},

View file

@ -573,6 +573,8 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
u16 id1, id2, mask_rev;
u16 cust_id, mode, chip_rev;
dev_set_drvdata(wm8350->dev, wm8350);
/* get WM8350 revision and config mode */
ret = wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
if (ret != 0) {

View file

@ -63,7 +63,7 @@ static int wm8350_i2c_probe(struct i2c_client *i2c,
struct wm8350 *wm8350;
int ret = 0;
wm8350 = kzalloc(sizeof(struct wm8350), GFP_KERNEL);
wm8350 = devm_kzalloc(&i2c->dev, sizeof(struct wm8350), GFP_KERNEL);
if (wm8350 == NULL)
return -ENOMEM;
@ -80,7 +80,6 @@ static int wm8350_i2c_probe(struct i2c_client *i2c,
return ret;
err:
kfree(wm8350);
return ret;
}
@ -89,7 +88,6 @@ static int wm8350_i2c_remove(struct i2c_client *i2c)
struct wm8350 *wm8350 = i2c_get_clientdata(i2c);
wm8350_device_exit(wm8350);
kfree(wm8350);
return 0;
}

View file

@ -344,7 +344,7 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
struct wm8400 *wm8400;
int ret;
wm8400 = kzalloc(sizeof(struct wm8400), GFP_KERNEL);
wm8400 = devm_kzalloc(&i2c->dev, sizeof(struct wm8400), GFP_KERNEL);
if (wm8400 == NULL) {
ret = -ENOMEM;
goto err;
@ -353,7 +353,7 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
wm8400->regmap = regmap_init_i2c(i2c, &wm8400_regmap_config);
if (IS_ERR(wm8400->regmap)) {
ret = PTR_ERR(wm8400->regmap);
goto struct_err;
goto err;
}
wm8400->dev = &i2c->dev;
@ -367,8 +367,6 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
map_err:
regmap_exit(wm8400->regmap);
struct_err:
kfree(wm8400);
err:
return ret;
}
@ -379,7 +377,6 @@ static int wm8400_i2c_remove(struct i2c_client *i2c)
wm8400_release(wm8400);
regmap_exit(wm8400->regmap);
kfree(wm8400);
return 0;
}