-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mfd: Add support for STMPE SPI interface
Few STMPE controller can have register interface over SPI or I2C. Current implementation only supports I2C. This patch adds support for SPI interface for accessing STMPE's address space. 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
1a6e4b7
commit e789995
Showing
4 changed files
with
157 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
/* | ||
* 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[] = { | ||
{ "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 <viresh.kumar@st.com>"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters