diff options
Diffstat (limited to 'drivers/mfd/stmpe-spi.c')
-rw-r--r-- | drivers/mfd/stmpe-spi.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c new file mode 100644 index 00000000000..b58c43c7ea9 --- /dev/null +++ b/drivers/mfd/stmpe-spi.c | |||
@@ -0,0 +1,150 @@ | |||
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 | |||
19 | static 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 | |||
27 | static 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 | |||
35 | static 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 | |||
49 | static 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 | |||
63 | static 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 | |||
77 | static 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 | |||
85 | static int __devinit | ||
86 | stmpe_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 | |||
104 | static 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 | |||
111 | static const struct spi_device_id stmpe_spi_id[] = { | ||
112 | { "stmpe610", STMPE610 }, | ||
113 | { "stmpe801", STMPE801 }, | ||
114 | { "stmpe811", STMPE811 }, | ||
115 | { "stmpe1601", STMPE1601 }, | ||
116 | { "stmpe2401", STMPE2401 }, | ||
117 | { "stmpe2403", STMPE2403 }, | ||
118 | { } | ||
119 | }; | ||
120 | MODULE_DEVICE_TABLE(spi, stmpe_id); | ||
121 | |||
122 | static struct spi_driver stmpe_spi_driver = { | ||
123 | .driver = { | ||
124 | .name = "stmpe-spi", | ||
125 | .bus = &spi_bus_type, | ||
126 | .owner = THIS_MODULE, | ||
127 | #ifdef CONFIG_PM | ||
128 | .pm = &stmpe_dev_pm_ops, | ||
129 | #endif | ||
130 | }, | ||
131 | .probe = stmpe_spi_probe, | ||
132 | .remove = __devexit_p(stmpe_spi_remove), | ||
133 | .id_table = stmpe_spi_id, | ||
134 | }; | ||
135 | |||
136 | static int __init stmpe_init(void) | ||
137 | { | ||
138 | return spi_register_driver(&stmpe_spi_driver); | ||
139 | } | ||
140 | subsys_initcall(stmpe_init); | ||
141 | |||
142 | static void __exit stmpe_exit(void) | ||
143 | { | ||
144 | spi_unregister_driver(&stmpe_spi_driver); | ||
145 | } | ||
146 | module_exit(stmpe_exit); | ||
147 | |||
148 | MODULE_LICENSE("GPL v2"); | ||
149 | MODULE_DESCRIPTION("STMPE MFD SPI Interface Driver"); | ||
150 | MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>"); | ||