aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@st.com>2011-11-17 00:32:21 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2012-01-08 18:37:43 -0500
commite789995d5c612ecda83a9feb53fb2e42a51f685b (patch)
tree48f8b41b35ed5d096df820230021dc1328a02f5a /drivers/mfd
parent1a6e4b7415339e3b11a87cff0d701b8a2e55f062 (diff)
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>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/Kconfig8
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/stmpe-spi.c148
-rw-r--r--drivers/mfd/stmpe.h1
4 files changed, 157 insertions, 1 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 7bc55819ab4a..06766ec5e288 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -258,7 +258,7 @@ config TWL6040_CORE
258 258
259config MFD_STMPE 259config MFD_STMPE
260 bool "Support STMicroelectronics STMPE" 260 bool "Support STMicroelectronics STMPE"
261 depends on I2C=y && GENERIC_HARDIRQS 261 depends on (I2C=y || SPI_MASTER=y) && GENERIC_HARDIRQS
262 select MFD_CORE 262 select MFD_CORE
263 help 263 help
264 Support for the STMPE family of I/O Expanders from 264 Support for the STMPE family of I/O Expanders from
@@ -288,6 +288,12 @@ config STMPE_I2C
288 default y 288 default y
289 help 289 help
290 This is used to enable I2C interface of STMPE 290 This is used to enable I2C interface of STMPE
291
292config STMPE_SPI
293 bool "STMPE SPI Inteface"
294 depends on SPI_MASTER
295 help
296 This is used to enable SPI interface of STMPE
291endmenu 297endmenu
292 298
293config MFD_TC3589X 299config MFD_TC3589X
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 5eb90a70c1a5..7f389a8895cb 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MFD_TI_SSP) += ti-ssp.o
17 17
18obj-$(CONFIG_MFD_STMPE) += stmpe.o 18obj-$(CONFIG_MFD_STMPE) += stmpe.o
19obj-$(CONFIG_STMPE_I2C) += stmpe-i2c.o 19obj-$(CONFIG_STMPE_I2C) += stmpe-i2c.o
20obj-$(CONFIG_STMPE_SPI) += stmpe-spi.o
20obj-$(CONFIG_MFD_TC3589X) += tc3589x.o 21obj-$(CONFIG_MFD_TC3589X) += tc3589x.o
21obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o 22obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
22obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o 23obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o
diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c
new file mode 100644
index 000000000000..53efce4fe294
--- /dev/null
+++ b/drivers/mfd/stmpe-spi.c
@@ -0,0 +1,148 @@
1/*
2 * ST Microelectronics MFD: stmpe's spi client specific driver
3 *
4 * Copyright (C) ST Microelectronics SA 2011
5 *
6 * License Terms: GNU General Public License, version 2
7 * Author: Viresh Kumar <viresh.kumar@st.com> for ST Microelectronics
8 */
9
10#include <linux/spi/spi.h>
11#include <linux/interrupt.h>
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/types.h>
15#include "stmpe.h"
16
17#define READ_CMD (1 << 7)
18
19static int spi_reg_read(struct stmpe *stmpe, u8 reg)
20{
21 struct spi_device *spi = stmpe->client;
22 int status = spi_w8r16(spi, reg | READ_CMD);
23
24 return (status < 0) ? status : status >> 8;
25}
26
27static int spi_reg_write(struct stmpe *stmpe, u8 reg, u8 val)
28{
29 struct spi_device *spi = stmpe->client;
30 u16 cmd = (val << 8) | reg;
31
32 return spi_write(spi, (const u8 *)&cmd, 2);
33}
34
35static int spi_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values)
36{
37 int ret, i;
38
39 for (i = 0; i < length; i++) {
40 ret = spi_reg_read(stmpe, reg + i);
41 if (ret < 0)
42 return ret;
43 *(values + i) = ret;
44 }
45
46 return 0;
47}
48
49static int spi_block_write(struct stmpe *stmpe, u8 reg, u8 length,
50 const u8 *values)
51{
52 int ret = 0, i;
53
54 for (i = length; i > 0; i--, reg++) {
55 ret = spi_reg_write(stmpe, reg, *(values + i - 1));
56 if (ret < 0)
57 return ret;
58 }
59
60 return ret;
61}
62
63static void spi_init(struct stmpe *stmpe)
64{
65 struct spi_device *spi = stmpe->client;
66
67 spi->bits_per_word = 8;
68
69 /* This register is only present for stmpe811 */
70 if (stmpe->variant->id_val == 0x0811)
71 spi_reg_write(stmpe, STMPE811_REG_SPI_CFG, spi->mode);
72
73 if (spi_setup(spi) < 0)
74 dev_dbg(&spi->dev, "spi_setup failed\n");
75}
76
77static struct stmpe_client_info spi_ci = {
78 .read_byte = spi_reg_read,
79 .write_byte = spi_reg_write,
80 .read_block = spi_block_read,
81 .write_block = spi_block_write,
82 .init = spi_init,
83};
84
85static int __devinit
86stmpe_spi_probe(struct spi_device *spi)
87{
88 const struct spi_device_id *id = spi_get_device_id(spi);
89
90 /* don't exceed max specified rate - 1MHz - Limitation of STMPE */
91 if (spi->max_speed_hz > 1000000) {
92 dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
93 (spi->max_speed_hz/1000));
94 return -EINVAL;
95 }
96
97 spi_ci.irq = spi->irq;
98 spi_ci.client = spi;
99 spi_ci.dev = &spi->dev;
100
101 return stmpe_probe(&spi_ci, id->driver_data);
102}
103
104static int __devexit stmpe_spi_remove(struct spi_device *spi)
105{
106 struct stmpe *stmpe = dev_get_drvdata(&spi->dev);
107
108 return stmpe_remove(stmpe);
109}
110
111static const struct spi_device_id stmpe_spi_id[] = {
112 { "stmpe811", STMPE811 },
113 { "stmpe1601", STMPE1601 },
114 { "stmpe2401", STMPE2401 },
115 { "stmpe2403", STMPE2403 },
116 { }
117};
118MODULE_DEVICE_TABLE(spi, stmpe_id);
119
120static struct spi_driver stmpe_spi_driver = {
121 .driver = {
122 .name = "stmpe-spi",
123 .bus = &spi_bus_type,
124 .owner = THIS_MODULE,
125#ifdef CONFIG_PM
126 .pm = &stmpe_dev_pm_ops,
127#endif
128 },
129 .probe = stmpe_spi_probe,
130 .remove = __devexit_p(stmpe_spi_remove),
131 .id_table = stmpe_spi_id,
132};
133
134static int __init stmpe_init(void)
135{
136 return spi_register_driver(&stmpe_spi_driver);
137}
138subsys_initcall(stmpe_init);
139
140static void __exit stmpe_exit(void)
141{
142 spi_unregister_driver(&stmpe_spi_driver);
143}
144module_exit(stmpe_exit);
145
146MODULE_LICENSE("GPL v2");
147MODULE_DESCRIPTION("STMPE MFD SPI Interface Driver");
148MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h
index 18d89a68ce40..a73f4c1085f2 100644
--- a/drivers/mfd/stmpe.h
+++ b/drivers/mfd/stmpe.h
@@ -120,6 +120,7 @@ int stmpe_remove(struct stmpe *stmpe);
120 120
121#define STMPE811_REG_CHIP_ID 0x00 121#define STMPE811_REG_CHIP_ID 0x00
122#define STMPE811_REG_SYS_CTRL2 0x04 122#define STMPE811_REG_SYS_CTRL2 0x04
123#define STMPE811_REG_SPI_CFG 0x08
123#define STMPE811_REG_INT_CTRL 0x09 124#define STMPE811_REG_INT_CTRL 0x09
124#define STMPE811_REG_INT_EN 0x0A 125#define STMPE811_REG_INT_EN 0x0A
125#define STMPE811_REG_INT_STA 0x0B 126#define STMPE811_REG_INT_STA 0x0B