WATCHDOG: use base address from platform resources and make 2430 boot again
[linux-ginger.git] / drivers / spi / tsc2101.c
blob258d856349ac9ee38f475328f44d13abe797d672
1 /*
2 * linux/drivers/spi/tsc2101.c
4 * TSC2101 codec interface driver for the OMAP platform
6 * Copyright (C) 2004 Texas Instruments, Inc.
8 * This package is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 * History:
18 * 2004/11/07 Nishanth Menon - Modified for common hooks for Audio and Touchscreen
21 #include <linux/kernel.h>
22 #include <linux/clk.h>
23 #include <linux/device.h>
24 #include <linux/spi/spi.h>
25 #include <linux/spi/tsc2101.h>
27 struct tsc2101_device {
28 struct mutex mutex;
29 int mclk_enabled;
30 struct clock *mclk_ck;
31 struct spi_message message;
32 struct spi_transfer transfer[2];
33 u16 command;
34 void (*enable_mclk)(struct spi_device *spi);
35 void (*disable_mclk)(struct spi_device *spi);
38 int tsc2101_enable_mclk(struct spi_device *spi)
40 struct tsc2101_device *tsc2101;
42 tsc2101 = spi_get_drvdata(spi);
44 mutex_lock(&tsc2101->mutex);
46 if (spi->dev.power.power_state.event != PM_EVENT_ON) {
47 mutex_unlock(&tsc2101->mutex);
48 return -ENODEV;
51 if (tsc2101->mclk_enabled++ == 0) {
52 if (tsc2101->enable_mclk != NULL)
53 tsc2101->enable_mclk(spi);
56 mutex_unlock(&tsc2101->mutex);
57 return 0;
59 EXPORT_SYMBOL(tsc2101_enable_mclk);
61 void tsc2101_disable_mclk(struct spi_device *spi)
63 struct tsc2101_device *tsc2101;
65 tsc2101 = spi_get_drvdata(spi);
67 mutex_lock(&tsc2101->mutex);
69 if (--tsc2101->mclk_enabled == 0) {
70 if (tsc2101->disable_mclk != NULL &&
71 spi->dev.power.power_state.event == PM_EVENT_ON)
72 tsc2101->disable_mclk(spi);
75 mutex_lock(&tsc2101->mutex);
77 EXPORT_SYMBOL(tsc2101_disable_mclk);
79 int tsc2101_write_sync(struct spi_device *spi, int page, u8 address, u16 data)
81 struct tsc2101_device *tsc2101;
82 struct spi_message *m;
83 struct spi_transfer *t;
84 int ret;
86 tsc2101 = spi_get_drvdata(spi);
88 mutex_lock(&tsc2101->mutex);
89 if (spi->dev.power.power_state.event != PM_EVENT_ON) {
90 mutex_unlock(&tsc2101->mutex);
91 return -ENODEV;
94 m = &tsc2101->message;
95 spi_message_init(m);
96 t = &tsc2101->transfer[0];
97 memset(t, 0, sizeof(tsc2101->transfer));
99 /* Address */
100 tsc2101->command = (page << 11) | (address << 5);
101 t->tx_buf = &tsc2101->command;
102 t->len = 2;
103 spi_message_add_tail(t, m);
105 /* Data */
106 t++;
107 t->tx_buf = &data;
108 t->len = 2;
109 spi_message_add_tail(t, m);
111 ret = spi_sync(spi, m);
112 if (!ret)
113 ret = tsc2101->message.status;
114 mutex_unlock(&tsc2101->mutex);
116 return ret;
118 EXPORT_SYMBOL(tsc2101_write_sync);
120 int tsc2101_reads_sync(struct spi_device *spi,
121 int page, u8 startaddress, u16 *data, int numregs)
123 struct tsc2101_device *tsc2101;
124 struct spi_message *m;
125 struct spi_transfer *t;
126 int ret;
128 tsc2101 = spi_get_drvdata(spi);
130 mutex_lock(&tsc2101->mutex);
131 if (spi->dev.power.power_state.event != PM_EVENT_ON) {
132 mutex_unlock(&tsc2101->mutex);
133 return -ENODEV;
136 m = &tsc2101->message;
137 spi_message_init(m);
138 t = &tsc2101->transfer[0];
139 memset(t, 0, sizeof(tsc2101->transfer));
141 /* Address */
142 tsc2101->command = 0x8000 | (page << 11) | (startaddress << 5);
143 t->tx_buf = &tsc2101->command;
144 t->len = 2;
145 spi_message_add_tail(t, m);
147 /* Data */
148 t++;
149 t->rx_buf = data;
150 t->len = numregs << 1;
151 spi_message_add_tail(t, m);
153 ret = spi_sync(spi, m);
154 if (!ret)
155 ret = tsc2101->message.status;
157 mutex_unlock(&tsc2101->mutex);
159 return ret;
161 EXPORT_SYMBOL(tsc2101_reads_sync);
163 int tsc2101_read_sync(struct spi_device *spi, int page, u8 address)
165 int err;
166 u16 val;
168 err = tsc2101_reads_sync(spi, page, address, &val, 1);
169 if (err)
170 return err;
171 return val;
173 EXPORT_SYMBOL(tsc2101_read_sync);
175 static int tsc2101_suspend(struct spi_device *spi, pm_message_t state)
177 struct tsc2101_device *tsc2101;
179 tsc2101 = spi_get_drvdata(spi);
181 if (tsc2101 == NULL)
182 return 0;
184 mutex_lock(&tsc2101->mutex);
186 spi->dev.power.power_state = state;
187 if (tsc2101->mclk_enabled && tsc2101->disable_mclk != NULL)
188 tsc2101->disable_mclk(spi);
190 mutex_unlock(&tsc2101->mutex);
192 return 0;
195 static int tsc2101_resume(struct spi_device *spi)
197 struct tsc2101_device *tsc2101;
199 tsc2101 = spi_get_drvdata(spi);
201 if (tsc2101 == NULL)
202 return 0;
204 mutex_lock(&tsc2101->mutex);
206 spi->dev.power.power_state = PMSG_ON;
207 if (tsc2101->mclk_enabled && tsc2101->enable_mclk != NULL)
208 tsc2101->enable_mclk(spi);
210 mutex_unlock(&tsc2101->mutex);
212 return 0;
215 static int tsc2101_probe(struct spi_device *spi)
217 struct tsc2101_platform_data *pdata;
218 struct tsc2101_device *tsc2101;
219 u16 w;
220 int r;
222 pdata = spi->dev.platform_data;
223 if (pdata == NULL) {
224 dev_err(&spi->dev, "no platform data\n");
225 return -ENODEV;
228 tsc2101 = kzalloc(sizeof(*tsc2101), GFP_KERNEL);
229 if (tsc2101 == NULL) {
230 dev_err(&spi->dev, "out of mem\n");
231 return -ENOMEM;
234 spi_set_drvdata(spi, tsc2101);
235 tsc2101->enable_mclk = pdata->enable_mclk;
236 tsc2101->disable_mclk = pdata->disable_mclk;
238 mutex_init(&tsc2101->mutex);
240 spi->mode = SPI_MODE_0;
241 spi->bits_per_word = 16;
242 if ((r = spi_setup(spi)) < 0) {
243 dev_err(&spi->dev, "SPI setup failed\n");
244 goto err;
247 w = tsc2101_read_sync(spi, 1, 0);
248 if (!(w & (1 << 14))) {
249 dev_err(&spi->dev, "invalid ADC register value %04x\n", w);
250 goto err;
253 if (pdata->init != NULL) {
254 if ((r = pdata->init(spi)) < 0) {
255 dev_err(&spi->dev, "platform init failed\n");
256 goto err;
260 dev_info(&spi->dev, "initialized\n");
262 return 0;
263 err:
264 kfree(tsc2101);
265 return r;
268 static int tsc2101_remove(struct spi_device *spi)
270 struct tsc2101_platform_data *pdata;
271 struct tsc2101_device *tsc2101;
273 pdata = spi->dev.platform_data;
274 tsc2101 = spi_get_drvdata(spi);
276 /* We assume that this can't race with the rest of the driver. */
277 if (tsc2101->mclk_enabled && tsc2101->disable_mclk != NULL)
278 tsc2101->disable_mclk(spi);
280 if (pdata->cleanup != NULL)
281 pdata->cleanup(spi);
283 spi_set_drvdata(spi, NULL);
284 kfree(tsc2101);
286 return 0;
289 static struct spi_driver tsc2101_driver = {
290 .probe = tsc2101_probe,
291 .remove = tsc2101_remove,
292 .suspend = tsc2101_suspend,
293 .resume = tsc2101_resume,
294 .driver = {
295 .name = "tsc2101",
296 .owner = THIS_MODULE,
300 static int tsc2101_init(void)
302 return spi_register_driver(&tsc2101_driver);
305 static void tsc2101_exit(void)
307 spi_unregister_driver(&tsc2101_driver);
310 module_init(tsc2101_init);
311 module_exit(tsc2101_exit);
313 MODULE_AUTHOR("Texas Instruments");
314 MODULE_DESCRIPTION
315 ("Glue audio driver for the TI OMAP1610/OMAP1710 TSC2101 codec.");
316 MODULE_LICENSE("GPL");