Skip to content

Commit

Permalink
mfd: Separate out STMPE controller and interface specific code
Browse files Browse the repository at this point in the history
Few STMPE controller can have register interface over SPI or I2C. Current
implementation only supports I2C and all code is present in a single file
stmpe.c. It would be better to separate out I2C interface specific code from
controller specific code. Later SPI specific code can be added in a separate
file.

This patch separates out I2C and controller specific code into separate files,
making stmpe.c independent of I2C.

Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
  • Loading branch information
Viresh Kumar authored and Samuel Ortiz committed Jan 8, 2012
1 parent 71e5878 commit 1a6e4b7
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 92 deletions.
11 changes: 11 additions & 0 deletions drivers/mfd/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,17 @@ 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
default y
help
This is used to enable I2C interface of STMPE
endmenu

config MFD_TC3589X
bool "Support Toshiba TC35892 and variants"
depends on I2C=y && GENERIC_HARDIRQS
Expand Down
1 change: 1 addition & 0 deletions drivers/mfd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ 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_MFD_TC3589X) += tc3589x.o
obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o
Expand Down
107 changes: 107 additions & 0 deletions drivers/mfd/stmpe-i2c.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* 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[] = {
{ "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 <rabin.vincent@stericsson.com>");
133 changes: 43 additions & 90 deletions drivers/mfd/stmpe.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/*
* ST Microelectronics MFD: stmpe's driver
*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License, version 2
Expand All @@ -7,13 +9,11 @@

#include <linux/gpio.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)
Expand All @@ -30,10 +30,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);

Expand All @@ -46,10 +45,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;
}
Expand All @@ -73,10 +71,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);
Expand All @@ -92,11 +89,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;
}
Expand Down Expand Up @@ -874,34 +869,10 @@ static int __devinit stmpe_devices_init(struct stmpe *stmpe)
return ret;
}

#ifdef CONFIG_PM
static int stmpe_suspend(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
struct stmpe *stmpe = i2c_get_clientdata(i2c);

if (device_may_wakeup(&i2c->dev))
enable_irq_wake(stmpe->irq);

return 0;
}

static int stmpe_resume(struct device *dev)
/* Called from client specific probe routines */
int stmpe_probe(struct stmpe_client_info *ci, int partnum)
{
struct i2c_client *i2c = to_i2c_client(dev);
struct stmpe *stmpe = i2c_get_clientdata(i2c);

if (device_may_wakeup(&i2c->dev))
disable_irq_wake(stmpe->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;

Expand All @@ -915,18 +886,19 @@ 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");
Expand All @@ -938,7 +910,7 @@ static int __devinit stmpe_probe(struct i2c_client *i2c,

stmpe->irq = gpio_to_irq(pdata->irq_gpio);
} else {
stmpe->irq = i2c->irq;
stmpe->irq = ci->irq;
}

ret = stmpe_chip_init(stmpe);
Expand All @@ -950,8 +922,7 @@ static int __devinit stmpe_probe(struct i2c_client *i2c,
goto free_gpio;

ret = request_threaded_irq(stmpe->irq, NULL, stmpe_irq,
pdata->irq_trigger | IRQF_ONESHOT,
"stmpe", stmpe);
pdata->irq_trigger | IRQF_ONESHOT, "stmpe", stmpe);
if (ret) {
dev_err(stmpe->dev, "failed to request IRQ: %d\n", ret);
goto out_removeirq;
Expand All @@ -978,10 +949,8 @@ static int __devinit stmpe_probe(struct i2c_client *i2c,
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->irq, stmpe);
Expand All @@ -995,45 +964,29 @@ static int __devexit stmpe_remove(struct i2c_client *client)
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 = {
.suspend = stmpe_suspend,
.resume = stmpe_resume,
};
#endif
static int stmpe_suspend(struct device *dev)
{
struct stmpe *stmpe = dev_get_drvdata(dev);

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,
};
if (device_may_wakeup(dev))
enable_irq_wake(stmpe->irq);

static int __init stmpe_init(void)
{
return i2c_add_driver(&stmpe_driver);
return 0;
}
subsys_initcall(stmpe_init);

static void __exit stmpe_exit(void)
static int stmpe_resume(struct device *dev)
{
i2c_del_driver(&stmpe_driver);
struct stmpe *stmpe = dev_get_drvdata(dev);

if (device_may_wakeup(dev))
disable_irq_wake(stmpe->irq);

return 0;
}
module_exit(stmpe_exit);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("STMPE MFD core driver");
MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>");
const struct dev_pm_ops stmpe_dev_pm_ops = {
.suspend = stmpe_suspend,
.resume = stmpe_resume,
};
#endif
Loading

0 comments on commit 1a6e4b7

Please sign in to comment.