aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/stmpe-spi.c
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/stmpe-spi.c
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/stmpe-spi.c')
-rw-r--r--drivers/mfd/stmpe-spi.c148
1 files changed, 148 insertions, 0 deletions
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>");