blob: 8a5ba0aa095abd5cb58c30ce272cd721626acc0e [file] [log] [blame]
Stephen Streete0c99052006-03-07 23:53:24 -08001/*
2 * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19#include <linux/init.h>
20#include <linux/module.h>
21#include <linux/device.h>
22#include <linux/ioport.h>
23#include <linux/errno.h>
24#include <linux/interrupt.h>
25#include <linux/platform_device.h>
Sebastian Andrzej Siewior8348c252010-11-22 17:12:15 -080026#include <linux/spi/pxa2xx_spi.h>
Stephen Streete0c99052006-03-07 23:53:24 -080027#include <linux/spi/spi.h>
28#include <linux/workqueue.h>
Stephen Streete0c99052006-03-07 23:53:24 -080029#include <linux/delay.h>
Eric Miaoa7bb3902009-04-06 19:00:54 -070030#include <linux/gpio.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090031#include <linux/slab.h>
Mika Westerberg3343b7a2013-01-22 12:26:27 +020032#include <linux/clk.h>
Mika Westerberg7d94a502013-01-22 12:26:30 +020033#include <linux/pm_runtime.h>
Stephen Streete0c99052006-03-07 23:53:24 -080034
35#include <asm/io.h>
36#include <asm/irq.h>
Stephen Streete0c99052006-03-07 23:53:24 -080037#include <asm/delay.h>
Stephen Streete0c99052006-03-07 23:53:24 -080038
Mika Westerbergcd7bed02013-01-22 12:26:28 +020039#include "spi-pxa2xx.h"
Stephen Streete0c99052006-03-07 23:53:24 -080040
41MODULE_AUTHOR("Stephen Street");
Will Newton037cdaf2007-12-10 15:49:25 -080042MODULE_DESCRIPTION("PXA2xx SSP SPI Controller");
Stephen Streete0c99052006-03-07 23:53:24 -080043MODULE_LICENSE("GPL");
Kay Sievers7e38c3c2008-04-10 21:29:20 -070044MODULE_ALIAS("platform:pxa2xx-spi");
Stephen Streete0c99052006-03-07 23:53:24 -080045
46#define MAX_BUSES 3
47
Vernon Sauderf1f640a2008-10-15 22:02:43 -070048#define TIMOUT_DFLT 1000
49
Ned Forresterb97c74b2008-02-23 15:23:40 -080050/*
51 * for testing SSCR1 changes that require SSP restart, basically
52 * everything except the service and interrupt enables, the pxa270 developer
53 * manual says only SSCR1_SCFR, SSCR1_SPH, SSCR1_SPO need to be in this
54 * list, but the PXA255 dev man says all bits without really meaning the
55 * service and interrupt enables
56 */
57#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_SCFR \
Stephen Street8d94cc52006-12-10 02:18:54 -080058 | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
Ned Forresterb97c74b2008-02-23 15:23:40 -080059 | SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \
60 | SSCR1_IFS | SSCR1_STRF | SSCR1_EFWR \
61 | SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \
62 | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
Stephen Street8d94cc52006-12-10 02:18:54 -080063
Eric Miaoa7bb3902009-04-06 19:00:54 -070064static void cs_assert(struct driver_data *drv_data)
65{
66 struct chip_data *chip = drv_data->cur_chip;
67
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -080068 if (drv_data->ssp_type == CE4100_SSP) {
69 write_SSSR(drv_data->cur_chip->frm, drv_data->ioaddr);
70 return;
71 }
72
Eric Miaoa7bb3902009-04-06 19:00:54 -070073 if (chip->cs_control) {
74 chip->cs_control(PXA2XX_CS_ASSERT);
75 return;
76 }
77
78 if (gpio_is_valid(chip->gpio_cs))
79 gpio_set_value(chip->gpio_cs, chip->gpio_cs_inverted);
80}
81
82static void cs_deassert(struct driver_data *drv_data)
83{
84 struct chip_data *chip = drv_data->cur_chip;
85
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -080086 if (drv_data->ssp_type == CE4100_SSP)
87 return;
88
Eric Miaoa7bb3902009-04-06 19:00:54 -070089 if (chip->cs_control) {
Daniel Ribeiro2b2562d2009-04-08 22:48:03 -030090 chip->cs_control(PXA2XX_CS_DEASSERT);
Eric Miaoa7bb3902009-04-06 19:00:54 -070091 return;
92 }
93
94 if (gpio_is_valid(chip->gpio_cs))
95 gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted);
96}
97
Mika Westerbergcd7bed02013-01-22 12:26:28 +020098int pxa2xx_spi_flush(struct driver_data *drv_data)
Stephen Streete0c99052006-03-07 23:53:24 -080099{
100 unsigned long limit = loops_per_jiffy << 1;
101
David Brownellcf433692008-04-28 02:14:17 -0700102 void __iomem *reg = drv_data->ioaddr;
Stephen Streete0c99052006-03-07 23:53:24 -0800103
104 do {
105 while (read_SSSR(reg) & SSSR_RNE) {
106 read_SSDR(reg);
107 }
Roel Kluin306c68a2009-04-21 12:24:46 -0700108 } while ((read_SSSR(reg) & SSSR_BSY) && --limit);
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800109 write_SSSR_CS(drv_data, SSSR_ROR);
Stephen Streete0c99052006-03-07 23:53:24 -0800110
111 return limit;
112}
113
Stephen Street8d94cc52006-12-10 02:18:54 -0800114static int null_writer(struct driver_data *drv_data)
Stephen Streete0c99052006-03-07 23:53:24 -0800115{
David Brownellcf433692008-04-28 02:14:17 -0700116 void __iomem *reg = drv_data->ioaddr;
Stephen Street9708c122006-03-28 14:05:23 -0800117 u8 n_bytes = drv_data->n_bytes;
Stephen Streete0c99052006-03-07 23:53:24 -0800118
Sebastian Andrzej Siewior4a256052010-11-22 17:12:15 -0800119 if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
Stephen Street8d94cc52006-12-10 02:18:54 -0800120 || (drv_data->tx == drv_data->tx_end))
121 return 0;
122
123 write_SSDR(0, reg);
124 drv_data->tx += n_bytes;
125
126 return 1;
Stephen Streete0c99052006-03-07 23:53:24 -0800127}
128
Stephen Street8d94cc52006-12-10 02:18:54 -0800129static int null_reader(struct driver_data *drv_data)
Stephen Streete0c99052006-03-07 23:53:24 -0800130{
David Brownellcf433692008-04-28 02:14:17 -0700131 void __iomem *reg = drv_data->ioaddr;
Stephen Street9708c122006-03-28 14:05:23 -0800132 u8 n_bytes = drv_data->n_bytes;
Stephen Streete0c99052006-03-07 23:53:24 -0800133
134 while ((read_SSSR(reg) & SSSR_RNE)
Stephen Street8d94cc52006-12-10 02:18:54 -0800135 && (drv_data->rx < drv_data->rx_end)) {
Stephen Streete0c99052006-03-07 23:53:24 -0800136 read_SSDR(reg);
137 drv_data->rx += n_bytes;
138 }
Stephen Street8d94cc52006-12-10 02:18:54 -0800139
140 return drv_data->rx == drv_data->rx_end;
Stephen Streete0c99052006-03-07 23:53:24 -0800141}
142
Stephen Street8d94cc52006-12-10 02:18:54 -0800143static int u8_writer(struct driver_data *drv_data)
Stephen Streete0c99052006-03-07 23:53:24 -0800144{
David Brownellcf433692008-04-28 02:14:17 -0700145 void __iomem *reg = drv_data->ioaddr;
Stephen Streete0c99052006-03-07 23:53:24 -0800146
Sebastian Andrzej Siewior4a256052010-11-22 17:12:15 -0800147 if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
Stephen Street8d94cc52006-12-10 02:18:54 -0800148 || (drv_data->tx == drv_data->tx_end))
149 return 0;
150
151 write_SSDR(*(u8 *)(drv_data->tx), reg);
152 ++drv_data->tx;
153
154 return 1;
Stephen Streete0c99052006-03-07 23:53:24 -0800155}
156
Stephen Street8d94cc52006-12-10 02:18:54 -0800157static int u8_reader(struct driver_data *drv_data)
Stephen Streete0c99052006-03-07 23:53:24 -0800158{
David Brownellcf433692008-04-28 02:14:17 -0700159 void __iomem *reg = drv_data->ioaddr;
Stephen Streete0c99052006-03-07 23:53:24 -0800160
161 while ((read_SSSR(reg) & SSSR_RNE)
Stephen Street8d94cc52006-12-10 02:18:54 -0800162 && (drv_data->rx < drv_data->rx_end)) {
Stephen Streete0c99052006-03-07 23:53:24 -0800163 *(u8 *)(drv_data->rx) = read_SSDR(reg);
164 ++drv_data->rx;
165 }
Stephen Street8d94cc52006-12-10 02:18:54 -0800166
167 return drv_data->rx == drv_data->rx_end;
Stephen Streete0c99052006-03-07 23:53:24 -0800168}
169
Stephen Street8d94cc52006-12-10 02:18:54 -0800170static int u16_writer(struct driver_data *drv_data)
Stephen Streete0c99052006-03-07 23:53:24 -0800171{
David Brownellcf433692008-04-28 02:14:17 -0700172 void __iomem *reg = drv_data->ioaddr;
Stephen Streete0c99052006-03-07 23:53:24 -0800173
Sebastian Andrzej Siewior4a256052010-11-22 17:12:15 -0800174 if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
Stephen Street8d94cc52006-12-10 02:18:54 -0800175 || (drv_data->tx == drv_data->tx_end))
176 return 0;
177
178 write_SSDR(*(u16 *)(drv_data->tx), reg);
179 drv_data->tx += 2;
180
181 return 1;
Stephen Streete0c99052006-03-07 23:53:24 -0800182}
183
Stephen Street8d94cc52006-12-10 02:18:54 -0800184static int u16_reader(struct driver_data *drv_data)
Stephen Streete0c99052006-03-07 23:53:24 -0800185{
David Brownellcf433692008-04-28 02:14:17 -0700186 void __iomem *reg = drv_data->ioaddr;
Stephen Streete0c99052006-03-07 23:53:24 -0800187
188 while ((read_SSSR(reg) & SSSR_RNE)
Stephen Street8d94cc52006-12-10 02:18:54 -0800189 && (drv_data->rx < drv_data->rx_end)) {
Stephen Streete0c99052006-03-07 23:53:24 -0800190 *(u16 *)(drv_data->rx) = read_SSDR(reg);
191 drv_data->rx += 2;
192 }
Stephen Street8d94cc52006-12-10 02:18:54 -0800193
194 return drv_data->rx == drv_data->rx_end;
Stephen Streete0c99052006-03-07 23:53:24 -0800195}
Stephen Street8d94cc52006-12-10 02:18:54 -0800196
197static int u32_writer(struct driver_data *drv_data)
Stephen Streete0c99052006-03-07 23:53:24 -0800198{
David Brownellcf433692008-04-28 02:14:17 -0700199 void __iomem *reg = drv_data->ioaddr;
Stephen Streete0c99052006-03-07 23:53:24 -0800200
Sebastian Andrzej Siewior4a256052010-11-22 17:12:15 -0800201 if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
Stephen Street8d94cc52006-12-10 02:18:54 -0800202 || (drv_data->tx == drv_data->tx_end))
203 return 0;
204
205 write_SSDR(*(u32 *)(drv_data->tx), reg);
206 drv_data->tx += 4;
207
208 return 1;
Stephen Streete0c99052006-03-07 23:53:24 -0800209}
210
Stephen Street8d94cc52006-12-10 02:18:54 -0800211static int u32_reader(struct driver_data *drv_data)
Stephen Streete0c99052006-03-07 23:53:24 -0800212{
David Brownellcf433692008-04-28 02:14:17 -0700213 void __iomem *reg = drv_data->ioaddr;
Stephen Streete0c99052006-03-07 23:53:24 -0800214
215 while ((read_SSSR(reg) & SSSR_RNE)
Stephen Street8d94cc52006-12-10 02:18:54 -0800216 && (drv_data->rx < drv_data->rx_end)) {
Stephen Streete0c99052006-03-07 23:53:24 -0800217 *(u32 *)(drv_data->rx) = read_SSDR(reg);
218 drv_data->rx += 4;
219 }
Stephen Street8d94cc52006-12-10 02:18:54 -0800220
221 return drv_data->rx == drv_data->rx_end;
Stephen Streete0c99052006-03-07 23:53:24 -0800222}
223
Mika Westerbergcd7bed02013-01-22 12:26:28 +0200224void *pxa2xx_spi_next_transfer(struct driver_data *drv_data)
Stephen Streete0c99052006-03-07 23:53:24 -0800225{
226 struct spi_message *msg = drv_data->cur_msg;
227 struct spi_transfer *trans = drv_data->cur_transfer;
228
229 /* Move to next transfer */
230 if (trans->transfer_list.next != &msg->transfers) {
231 drv_data->cur_transfer =
232 list_entry(trans->transfer_list.next,
233 struct spi_transfer,
234 transfer_list);
235 return RUNNING_STATE;
236 } else
237 return DONE_STATE;
238}
239
Stephen Streete0c99052006-03-07 23:53:24 -0800240/* caller already set message->status; dma and pio irqs are blocked */
Stephen Street5daa3ba2006-05-20 15:00:19 -0700241static void giveback(struct driver_data *drv_data)
Stephen Streete0c99052006-03-07 23:53:24 -0800242{
243 struct spi_transfer* last_transfer;
Stephen Street5daa3ba2006-05-20 15:00:19 -0700244 struct spi_message *msg;
Stephen Streete0c99052006-03-07 23:53:24 -0800245
Stephen Street5daa3ba2006-05-20 15:00:19 -0700246 msg = drv_data->cur_msg;
247 drv_data->cur_msg = NULL;
248 drv_data->cur_transfer = NULL;
Stephen Street5daa3ba2006-05-20 15:00:19 -0700249
250 last_transfer = list_entry(msg->transfers.prev,
Stephen Streete0c99052006-03-07 23:53:24 -0800251 struct spi_transfer,
252 transfer_list);
253
Ned Forrester84235972008-09-13 02:33:17 -0700254 /* Delay if requested before any change in chip select */
255 if (last_transfer->delay_usecs)
256 udelay(last_transfer->delay_usecs);
257
258 /* Drop chip select UNLESS cs_change is true or we are returning
259 * a message with an error, or next message is for another chip
260 */
Stephen Streete0c99052006-03-07 23:53:24 -0800261 if (!last_transfer->cs_change)
Eric Miaoa7bb3902009-04-06 19:00:54 -0700262 cs_deassert(drv_data);
Ned Forrester84235972008-09-13 02:33:17 -0700263 else {
264 struct spi_message *next_msg;
265
266 /* Holding of cs was hinted, but we need to make sure
267 * the next message is for the same chip. Don't waste
268 * time with the following tests unless this was hinted.
269 *
270 * We cannot postpone this until pump_messages, because
271 * after calling msg->complete (below) the driver that
272 * sent the current message could be unloaded, which
273 * could invalidate the cs_control() callback...
274 */
275
276 /* get a pointer to the next message, if any */
Mika Westerberg7f86bde2013-01-22 12:26:26 +0200277 next_msg = spi_get_next_queued_message(drv_data->master);
Ned Forrester84235972008-09-13 02:33:17 -0700278
279 /* see if the next and current messages point
280 * to the same chip
281 */
282 if (next_msg && next_msg->spi != msg->spi)
283 next_msg = NULL;
284 if (!next_msg || msg->state == ERROR_STATE)
Eric Miaoa7bb3902009-04-06 19:00:54 -0700285 cs_deassert(drv_data);
Ned Forrester84235972008-09-13 02:33:17 -0700286 }
Stephen Streete0c99052006-03-07 23:53:24 -0800287
Mika Westerberg7f86bde2013-01-22 12:26:26 +0200288 spi_finalize_current_message(drv_data->master);
Eric Miaoa7bb3902009-04-06 19:00:54 -0700289 drv_data->cur_chip = NULL;
Stephen Streete0c99052006-03-07 23:53:24 -0800290}
291
Sebastian Andrzej Siewior579d3bb2010-11-22 17:12:17 -0800292static void reset_sccr1(struct driver_data *drv_data)
293{
294 void __iomem *reg = drv_data->ioaddr;
295 struct chip_data *chip = drv_data->cur_chip;
296 u32 sccr1_reg;
297
298 sccr1_reg = read_SSCR1(reg) & ~drv_data->int_cr1;
299 sccr1_reg &= ~SSCR1_RFT;
300 sccr1_reg |= chip->threshold;
301 write_SSCR1(sccr1_reg, reg);
302}
303
Stephen Street8d94cc52006-12-10 02:18:54 -0800304static void int_error_stop(struct driver_data *drv_data, const char* msg)
305{
David Brownellcf433692008-04-28 02:14:17 -0700306 void __iomem *reg = drv_data->ioaddr;
Stephen Street8d94cc52006-12-10 02:18:54 -0800307
308 /* Stop and reset SSP */
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800309 write_SSSR_CS(drv_data, drv_data->clear_sr);
Sebastian Andrzej Siewior579d3bb2010-11-22 17:12:17 -0800310 reset_sccr1(drv_data);
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800311 if (!pxa25x_ssp_comp(drv_data))
Stephen Street8d94cc52006-12-10 02:18:54 -0800312 write_SSTO(0, reg);
Mika Westerbergcd7bed02013-01-22 12:26:28 +0200313 pxa2xx_spi_flush(drv_data);
Stephen Street8d94cc52006-12-10 02:18:54 -0800314 write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
315
316 dev_err(&drv_data->pdev->dev, "%s\n", msg);
317
318 drv_data->cur_msg->state = ERROR_STATE;
319 tasklet_schedule(&drv_data->pump_transfers);
320}
321
322static void int_transfer_complete(struct driver_data *drv_data)
323{
David Brownellcf433692008-04-28 02:14:17 -0700324 void __iomem *reg = drv_data->ioaddr;
Stephen Street8d94cc52006-12-10 02:18:54 -0800325
326 /* Stop SSP */
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800327 write_SSSR_CS(drv_data, drv_data->clear_sr);
Sebastian Andrzej Siewior579d3bb2010-11-22 17:12:17 -0800328 reset_sccr1(drv_data);
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800329 if (!pxa25x_ssp_comp(drv_data))
Stephen Street8d94cc52006-12-10 02:18:54 -0800330 write_SSTO(0, reg);
331
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300332 /* Update total byte transferred return count actual bytes read */
Stephen Street8d94cc52006-12-10 02:18:54 -0800333 drv_data->cur_msg->actual_length += drv_data->len -
334 (drv_data->rx_end - drv_data->rx);
335
Ned Forrester84235972008-09-13 02:33:17 -0700336 /* Transfer delays and chip select release are
337 * handled in pump_transfers or giveback
338 */
Stephen Street8d94cc52006-12-10 02:18:54 -0800339
340 /* Move to next transfer */
Mika Westerbergcd7bed02013-01-22 12:26:28 +0200341 drv_data->cur_msg->state = pxa2xx_spi_next_transfer(drv_data);
Stephen Street8d94cc52006-12-10 02:18:54 -0800342
343 /* Schedule transfer tasklet */
344 tasklet_schedule(&drv_data->pump_transfers);
345}
346
Stephen Streete0c99052006-03-07 23:53:24 -0800347static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
348{
David Brownellcf433692008-04-28 02:14:17 -0700349 void __iomem *reg = drv_data->ioaddr;
Stephen Street8d94cc52006-12-10 02:18:54 -0800350
Stephen Street5daa3ba2006-05-20 15:00:19 -0700351 u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ?
352 drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
Stephen Streete0c99052006-03-07 23:53:24 -0800353
Stephen Street8d94cc52006-12-10 02:18:54 -0800354 u32 irq_status = read_SSSR(reg) & irq_mask;
Stephen Streete0c99052006-03-07 23:53:24 -0800355
Stephen Street8d94cc52006-12-10 02:18:54 -0800356 if (irq_status & SSSR_ROR) {
357 int_error_stop(drv_data, "interrupt_transfer: fifo overrun");
358 return IRQ_HANDLED;
359 }
Stephen Streete0c99052006-03-07 23:53:24 -0800360
Stephen Street8d94cc52006-12-10 02:18:54 -0800361 if (irq_status & SSSR_TINT) {
362 write_SSSR(SSSR_TINT, reg);
363 if (drv_data->read(drv_data)) {
364 int_transfer_complete(drv_data);
Stephen Streete0c99052006-03-07 23:53:24 -0800365 return IRQ_HANDLED;
366 }
Stephen Street8d94cc52006-12-10 02:18:54 -0800367 }
Stephen Streete0c99052006-03-07 23:53:24 -0800368
Stephen Street8d94cc52006-12-10 02:18:54 -0800369 /* Drain rx fifo, Fill tx fifo and prevent overruns */
370 do {
371 if (drv_data->read(drv_data)) {
372 int_transfer_complete(drv_data);
373 return IRQ_HANDLED;
Stephen Streete0c99052006-03-07 23:53:24 -0800374 }
Stephen Street8d94cc52006-12-10 02:18:54 -0800375 } while (drv_data->write(drv_data));
Stephen Streete0c99052006-03-07 23:53:24 -0800376
Stephen Street8d94cc52006-12-10 02:18:54 -0800377 if (drv_data->read(drv_data)) {
378 int_transfer_complete(drv_data);
379 return IRQ_HANDLED;
380 }
Stephen Streete0c99052006-03-07 23:53:24 -0800381
Stephen Street8d94cc52006-12-10 02:18:54 -0800382 if (drv_data->tx == drv_data->tx_end) {
Sebastian Andrzej Siewior579d3bb2010-11-22 17:12:17 -0800383 u32 bytes_left;
384 u32 sccr1_reg;
385
386 sccr1_reg = read_SSCR1(reg);
387 sccr1_reg &= ~SSCR1_TIE;
388
389 /*
390 * PXA25x_SSP has no timeout, set up rx threshould for the
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300391 * remaining RX bytes.
Sebastian Andrzej Siewior579d3bb2010-11-22 17:12:17 -0800392 */
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800393 if (pxa25x_ssp_comp(drv_data)) {
Sebastian Andrzej Siewior579d3bb2010-11-22 17:12:17 -0800394
395 sccr1_reg &= ~SSCR1_RFT;
396
397 bytes_left = drv_data->rx_end - drv_data->rx;
398 switch (drv_data->n_bytes) {
399 case 4:
400 bytes_left >>= 1;
401 case 2:
402 bytes_left >>= 1;
Stephen Street8d94cc52006-12-10 02:18:54 -0800403 }
Sebastian Andrzej Siewior579d3bb2010-11-22 17:12:17 -0800404
405 if (bytes_left > RX_THRESH_DFLT)
406 bytes_left = RX_THRESH_DFLT;
407
408 sccr1_reg |= SSCR1_RxTresh(bytes_left);
Stephen Streete0c99052006-03-07 23:53:24 -0800409 }
Sebastian Andrzej Siewior579d3bb2010-11-22 17:12:17 -0800410 write_SSCR1(sccr1_reg, reg);
Stephen Streete0c99052006-03-07 23:53:24 -0800411 }
412
Stephen Street5daa3ba2006-05-20 15:00:19 -0700413 /* We did something */
414 return IRQ_HANDLED;
Stephen Streete0c99052006-03-07 23:53:24 -0800415}
416
David Howells7d12e782006-10-05 14:55:46 +0100417static irqreturn_t ssp_int(int irq, void *dev_id)
Stephen Streete0c99052006-03-07 23:53:24 -0800418{
Jeff Garzikc7bec5a2006-10-06 15:00:58 -0400419 struct driver_data *drv_data = dev_id;
David Brownellcf433692008-04-28 02:14:17 -0700420 void __iomem *reg = drv_data->ioaddr;
Mika Westerberg7d94a502013-01-22 12:26:30 +0200421 u32 sccr1_reg;
Sebastian Andrzej Siewior49cbb1e2010-11-22 17:12:14 -0800422 u32 mask = drv_data->mask_sr;
423 u32 status;
424
Mika Westerberg7d94a502013-01-22 12:26:30 +0200425 /*
426 * The IRQ might be shared with other peripherals so we must first
427 * check that are we RPM suspended or not. If we are we assume that
428 * the IRQ was not for us (we shouldn't be RPM suspended when the
429 * interrupt is enabled).
430 */
431 if (pm_runtime_suspended(&drv_data->pdev->dev))
432 return IRQ_NONE;
433
434 sccr1_reg = read_SSCR1(reg);
Sebastian Andrzej Siewior49cbb1e2010-11-22 17:12:14 -0800435 status = read_SSSR(reg);
436
437 /* Ignore possible writes if we don't need to write */
438 if (!(sccr1_reg & SSCR1_TIE))
439 mask &= ~SSSR_TFS;
440
441 if (!(status & mask))
442 return IRQ_NONE;
Stephen Streete0c99052006-03-07 23:53:24 -0800443
444 if (!drv_data->cur_msg) {
Stephen Street5daa3ba2006-05-20 15:00:19 -0700445
446 write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
447 write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800448 if (!pxa25x_ssp_comp(drv_data))
Stephen Street5daa3ba2006-05-20 15:00:19 -0700449 write_SSTO(0, reg);
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800450 write_SSSR_CS(drv_data, drv_data->clear_sr);
Stephen Street5daa3ba2006-05-20 15:00:19 -0700451
Stephen Streete0c99052006-03-07 23:53:24 -0800452 dev_err(&drv_data->pdev->dev, "bad message state "
Stephen Street8d94cc52006-12-10 02:18:54 -0800453 "in interrupt handler\n");
Stephen Street5daa3ba2006-05-20 15:00:19 -0700454
Stephen Streete0c99052006-03-07 23:53:24 -0800455 /* Never fail */
456 return IRQ_HANDLED;
457 }
458
459 return drv_data->transfer_handler(drv_data);
460}
461
Mika Westerberg3343b7a2013-01-22 12:26:27 +0200462static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
eric miao2f1a74e2007-11-21 18:50:53 +0800463{
Mika Westerberg3343b7a2013-01-22 12:26:27 +0200464 unsigned long ssp_clk = drv_data->max_clk_rate;
465 const struct ssp_device *ssp = drv_data->ssp;
466
467 rate = min_t(int, ssp_clk, rate);
eric miao2f1a74e2007-11-21 18:50:53 +0800468
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800469 if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
eric miao2f1a74e2007-11-21 18:50:53 +0800470 return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
471 else
472 return ((ssp_clk / rate - 1) & 0xfff) << 8;
473}
474
Stephen Streete0c99052006-03-07 23:53:24 -0800475static void pump_transfers(unsigned long data)
476{
477 struct driver_data *drv_data = (struct driver_data *)data;
478 struct spi_message *message = NULL;
479 struct spi_transfer *transfer = NULL;
480 struct spi_transfer *previous = NULL;
481 struct chip_data *chip = NULL;
David Brownellcf433692008-04-28 02:14:17 -0700482 void __iomem *reg = drv_data->ioaddr;
Stephen Street9708c122006-03-28 14:05:23 -0800483 u32 clk_div = 0;
484 u8 bits = 0;
485 u32 speed = 0;
486 u32 cr0;
Stephen Street8d94cc52006-12-10 02:18:54 -0800487 u32 cr1;
488 u32 dma_thresh = drv_data->cur_chip->dma_threshold;
489 u32 dma_burst = drv_data->cur_chip->dma_burst_size;
Stephen Streete0c99052006-03-07 23:53:24 -0800490
491 /* Get current state information */
492 message = drv_data->cur_msg;
493 transfer = drv_data->cur_transfer;
494 chip = drv_data->cur_chip;
495
496 /* Handle for abort */
497 if (message->state == ERROR_STATE) {
498 message->status = -EIO;
Stephen Street5daa3ba2006-05-20 15:00:19 -0700499 giveback(drv_data);
Stephen Streete0c99052006-03-07 23:53:24 -0800500 return;
501 }
502
503 /* Handle end of message */
504 if (message->state == DONE_STATE) {
505 message->status = 0;
Stephen Street5daa3ba2006-05-20 15:00:19 -0700506 giveback(drv_data);
Stephen Streete0c99052006-03-07 23:53:24 -0800507 return;
508 }
509
Ned Forrester84235972008-09-13 02:33:17 -0700510 /* Delay if requested at end of transfer before CS change */
Stephen Streete0c99052006-03-07 23:53:24 -0800511 if (message->state == RUNNING_STATE) {
512 previous = list_entry(transfer->transfer_list.prev,
513 struct spi_transfer,
514 transfer_list);
515 if (previous->delay_usecs)
516 udelay(previous->delay_usecs);
Ned Forrester84235972008-09-13 02:33:17 -0700517
518 /* Drop chip select only if cs_change is requested */
519 if (previous->cs_change)
Eric Miaoa7bb3902009-04-06 19:00:54 -0700520 cs_deassert(drv_data);
Stephen Streete0c99052006-03-07 23:53:24 -0800521 }
522
Mika Westerbergcd7bed02013-01-22 12:26:28 +0200523 /* Check if we can DMA this transfer */
524 if (!pxa2xx_spi_dma_is_possible(transfer->len) && chip->enable_dma) {
Ned Forrester7e964452008-09-13 02:33:18 -0700525
526 /* reject already-mapped transfers; PIO won't always work */
527 if (message->is_dma_mapped
528 || transfer->rx_dma || transfer->tx_dma) {
529 dev_err(&drv_data->pdev->dev,
530 "pump_transfers: mapped transfer length "
Mike Rapoport20b918d2008-10-01 10:39:24 -0700531 "of %u is greater than %d\n",
Ned Forrester7e964452008-09-13 02:33:18 -0700532 transfer->len, MAX_DMA_LEN);
533 message->status = -EINVAL;
534 giveback(drv_data);
535 return;
536 }
537
538 /* warn ... we force this to PIO mode */
539 if (printk_ratelimit())
540 dev_warn(&message->spi->dev, "pump_transfers: "
541 "DMA disabled for transfer length %ld "
542 "greater than %d\n",
543 (long)drv_data->len, MAX_DMA_LEN);
Stephen Street8d94cc52006-12-10 02:18:54 -0800544 }
545
Stephen Streete0c99052006-03-07 23:53:24 -0800546 /* Setup the transfer state based on the type of transfer */
Mika Westerbergcd7bed02013-01-22 12:26:28 +0200547 if (pxa2xx_spi_flush(drv_data) == 0) {
Stephen Streete0c99052006-03-07 23:53:24 -0800548 dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
549 message->status = -EIO;
Stephen Street5daa3ba2006-05-20 15:00:19 -0700550 giveback(drv_data);
Stephen Streete0c99052006-03-07 23:53:24 -0800551 return;
552 }
Stephen Street9708c122006-03-28 14:05:23 -0800553 drv_data->n_bytes = chip->n_bytes;
Stephen Streete0c99052006-03-07 23:53:24 -0800554 drv_data->tx = (void *)transfer->tx_buf;
555 drv_data->tx_end = drv_data->tx + transfer->len;
556 drv_data->rx = transfer->rx_buf;
557 drv_data->rx_end = drv_data->rx + transfer->len;
558 drv_data->rx_dma = transfer->rx_dma;
559 drv_data->tx_dma = transfer->tx_dma;
Mika Westerbergcd7bed02013-01-22 12:26:28 +0200560 drv_data->len = transfer->len;
Stephen Streete0c99052006-03-07 23:53:24 -0800561 drv_data->write = drv_data->tx ? chip->write : null_writer;
562 drv_data->read = drv_data->rx ? chip->read : null_reader;
Stephen Street9708c122006-03-28 14:05:23 -0800563
564 /* Change speed and bit per word on a per transfer */
Stephen Street8d94cc52006-12-10 02:18:54 -0800565 cr0 = chip->cr0;
Stephen Street9708c122006-03-28 14:05:23 -0800566 if (transfer->speed_hz || transfer->bits_per_word) {
567
Stephen Street9708c122006-03-28 14:05:23 -0800568 bits = chip->bits_per_word;
569 speed = chip->speed_hz;
570
571 if (transfer->speed_hz)
572 speed = transfer->speed_hz;
573
574 if (transfer->bits_per_word)
575 bits = transfer->bits_per_word;
576
Mika Westerberg3343b7a2013-01-22 12:26:27 +0200577 clk_div = ssp_get_clk_div(drv_data, speed);
Stephen Street9708c122006-03-28 14:05:23 -0800578
579 if (bits <= 8) {
580 drv_data->n_bytes = 1;
Stephen Street9708c122006-03-28 14:05:23 -0800581 drv_data->read = drv_data->read != null_reader ?
582 u8_reader : null_reader;
583 drv_data->write = drv_data->write != null_writer ?
584 u8_writer : null_writer;
585 } else if (bits <= 16) {
586 drv_data->n_bytes = 2;
Stephen Street9708c122006-03-28 14:05:23 -0800587 drv_data->read = drv_data->read != null_reader ?
588 u16_reader : null_reader;
589 drv_data->write = drv_data->write != null_writer ?
590 u16_writer : null_writer;
591 } else if (bits <= 32) {
592 drv_data->n_bytes = 4;
Stephen Street9708c122006-03-28 14:05:23 -0800593 drv_data->read = drv_data->read != null_reader ?
594 u32_reader : null_reader;
595 drv_data->write = drv_data->write != null_writer ?
596 u32_writer : null_writer;
597 }
Stephen Street8d94cc52006-12-10 02:18:54 -0800598 /* if bits/word is changed in dma mode, then must check the
599 * thresholds and burst also */
600 if (chip->enable_dma) {
Mika Westerbergcd7bed02013-01-22 12:26:28 +0200601 if (pxa2xx_spi_set_dma_burst_and_threshold(chip,
602 message->spi,
Stephen Street8d94cc52006-12-10 02:18:54 -0800603 bits, &dma_burst,
604 &dma_thresh))
605 if (printk_ratelimit())
606 dev_warn(&message->spi->dev,
Ned Forrester7e964452008-09-13 02:33:18 -0700607 "pump_transfers: "
Stephen Street8d94cc52006-12-10 02:18:54 -0800608 "DMA burst size reduced to "
609 "match bits_per_word\n");
610 }
Stephen Street9708c122006-03-28 14:05:23 -0800611
612 cr0 = clk_div
613 | SSCR0_Motorola
Stephen Street5daa3ba2006-05-20 15:00:19 -0700614 | SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
Stephen Street9708c122006-03-28 14:05:23 -0800615 | SSCR0_SSE
616 | (bits > 16 ? SSCR0_EDSS : 0);
Stephen Street9708c122006-03-28 14:05:23 -0800617 }
618
Stephen Streete0c99052006-03-07 23:53:24 -0800619 message->state = RUNNING_STATE;
620
Ned Forrester7e964452008-09-13 02:33:18 -0700621 drv_data->dma_mapped = 0;
Mika Westerbergcd7bed02013-01-22 12:26:28 +0200622 if (pxa2xx_spi_dma_is_possible(drv_data->len))
623 drv_data->dma_mapped = pxa2xx_spi_map_dma_buffers(drv_data);
Ned Forrester7e964452008-09-13 02:33:18 -0700624 if (drv_data->dma_mapped) {
Stephen Streete0c99052006-03-07 23:53:24 -0800625
626 /* Ensure we have the correct interrupt handler */
Mika Westerbergcd7bed02013-01-22 12:26:28 +0200627 drv_data->transfer_handler = pxa2xx_spi_dma_transfer;
Stephen Streete0c99052006-03-07 23:53:24 -0800628
Mika Westerbergcd7bed02013-01-22 12:26:28 +0200629 pxa2xx_spi_dma_prepare(drv_data, dma_burst);
Stephen Streete0c99052006-03-07 23:53:24 -0800630
Stephen Street8d94cc52006-12-10 02:18:54 -0800631 /* Clear status and start DMA engine */
632 cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1;
Stephen Streete0c99052006-03-07 23:53:24 -0800633 write_SSSR(drv_data->clear_sr, reg);
Mika Westerbergcd7bed02013-01-22 12:26:28 +0200634
635 pxa2xx_spi_dma_start(drv_data);
Stephen Streete0c99052006-03-07 23:53:24 -0800636 } else {
637 /* Ensure we have the correct interrupt handler */
638 drv_data->transfer_handler = interrupt_transfer;
639
Stephen Street8d94cc52006-12-10 02:18:54 -0800640 /* Clear status */
641 cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1;
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800642 write_SSSR_CS(drv_data, drv_data->clear_sr);
Stephen Street8d94cc52006-12-10 02:18:54 -0800643 }
644
645 /* see if we need to reload the config registers */
646 if ((read_SSCR0(reg) != cr0)
647 || (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
648 (cr1 & SSCR1_CHANGE_MASK)) {
649
Ned Forresterb97c74b2008-02-23 15:23:40 -0800650 /* stop the SSP, and update the other bits */
Stephen Street8d94cc52006-12-10 02:18:54 -0800651 write_SSCR0(cr0 & ~SSCR0_SSE, reg);
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800652 if (!pxa25x_ssp_comp(drv_data))
Stephen Streete0c99052006-03-07 23:53:24 -0800653 write_SSTO(chip->timeout, reg);
Ned Forresterb97c74b2008-02-23 15:23:40 -0800654 /* first set CR1 without interrupt and service enables */
655 write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg);
656 /* restart the SSP */
Stephen Street8d94cc52006-12-10 02:18:54 -0800657 write_SSCR0(cr0, reg);
Ned Forresterb97c74b2008-02-23 15:23:40 -0800658
Stephen Street8d94cc52006-12-10 02:18:54 -0800659 } else {
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800660 if (!pxa25x_ssp_comp(drv_data))
Stephen Street8d94cc52006-12-10 02:18:54 -0800661 write_SSTO(chip->timeout, reg);
Stephen Streete0c99052006-03-07 23:53:24 -0800662 }
Ned Forresterb97c74b2008-02-23 15:23:40 -0800663
Eric Miaoa7bb3902009-04-06 19:00:54 -0700664 cs_assert(drv_data);
Ned Forresterb97c74b2008-02-23 15:23:40 -0800665
666 /* after chip select, release the data by enabling service
667 * requests and interrupts, without changing any mode bits */
668 write_SSCR1(cr1, reg);
Stephen Streete0c99052006-03-07 23:53:24 -0800669}
670
Mika Westerberg7f86bde2013-01-22 12:26:26 +0200671static int pxa2xx_spi_transfer_one_message(struct spi_master *master,
672 struct spi_message *msg)
Stephen Streete0c99052006-03-07 23:53:24 -0800673{
Mika Westerberg7f86bde2013-01-22 12:26:26 +0200674 struct driver_data *drv_data = spi_master_get_devdata(master);
Stephen Streete0c99052006-03-07 23:53:24 -0800675
Mika Westerberg7f86bde2013-01-22 12:26:26 +0200676 drv_data->cur_msg = msg;
Stephen Streete0c99052006-03-07 23:53:24 -0800677 /* Initial message state*/
678 drv_data->cur_msg->state = START_STATE;
679 drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
680 struct spi_transfer,
681 transfer_list);
682
Stephen Street8d94cc52006-12-10 02:18:54 -0800683 /* prepare to setup the SSP, in pump_transfers, using the per
684 * chip configuration */
Stephen Streete0c99052006-03-07 23:53:24 -0800685 drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
Stephen Streete0c99052006-03-07 23:53:24 -0800686
687 /* Mark as busy and launch transfers */
688 tasklet_schedule(&drv_data->pump_transfers);
Stephen Streete0c99052006-03-07 23:53:24 -0800689 return 0;
690}
691
Mika Westerberg7d94a502013-01-22 12:26:30 +0200692static int pxa2xx_spi_prepare_transfer(struct spi_master *master)
693{
694 struct driver_data *drv_data = spi_master_get_devdata(master);
695
696 pm_runtime_get_sync(&drv_data->pdev->dev);
697 return 0;
698}
699
700static int pxa2xx_spi_unprepare_transfer(struct spi_master *master)
701{
702 struct driver_data *drv_data = spi_master_get_devdata(master);
703
704 /* Disable the SSP now */
705 write_SSCR0(read_SSCR0(drv_data->ioaddr) & ~SSCR0_SSE,
706 drv_data->ioaddr);
707
708 pm_runtime_mark_last_busy(&drv_data->pdev->dev);
709 pm_runtime_put_autosuspend(&drv_data->pdev->dev);
710 return 0;
711}
712
Eric Miaoa7bb3902009-04-06 19:00:54 -0700713static int setup_cs(struct spi_device *spi, struct chip_data *chip,
714 struct pxa2xx_spi_chip *chip_info)
715{
716 int err = 0;
717
718 if (chip == NULL || chip_info == NULL)
719 return 0;
720
721 /* NOTE: setup() can be called multiple times, possibly with
722 * different chip_info, release previously requested GPIO
723 */
724 if (gpio_is_valid(chip->gpio_cs))
725 gpio_free(chip->gpio_cs);
726
727 /* If (*cs_control) is provided, ignore GPIO chip select */
728 if (chip_info->cs_control) {
729 chip->cs_control = chip_info->cs_control;
730 return 0;
731 }
732
733 if (gpio_is_valid(chip_info->gpio_cs)) {
734 err = gpio_request(chip_info->gpio_cs, "SPI_CS");
735 if (err) {
736 dev_err(&spi->dev, "failed to request chip select "
737 "GPIO%d\n", chip_info->gpio_cs);
738 return err;
739 }
740
741 chip->gpio_cs = chip_info->gpio_cs;
742 chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH;
743
744 err = gpio_direction_output(chip->gpio_cs,
745 !chip->gpio_cs_inverted);
746 }
747
748 return err;
749}
750
Stephen Streete0c99052006-03-07 23:53:24 -0800751static int setup(struct spi_device *spi)
752{
753 struct pxa2xx_spi_chip *chip_info = NULL;
754 struct chip_data *chip;
755 struct driver_data *drv_data = spi_master_get_devdata(spi->master);
756 unsigned int clk_div;
Vernon Sauderf1f640a2008-10-15 22:02:43 -0700757 uint tx_thres = TX_THRESH_DFLT;
758 uint rx_thres = RX_THRESH_DFLT;
Stephen Streete0c99052006-03-07 23:53:24 -0800759
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800760 if (!pxa25x_ssp_comp(drv_data)
Stephen Street8d94cc52006-12-10 02:18:54 -0800761 && (spi->bits_per_word < 4 || spi->bits_per_word > 32)) {
762 dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
763 "b/w not 4-32 for type non-PXA25x_SSP\n",
764 drv_data->ssp_type, spi->bits_per_word);
Stephen Streete0c99052006-03-07 23:53:24 -0800765 return -EINVAL;
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800766 } else if (pxa25x_ssp_comp(drv_data)
Stephen Street8d94cc52006-12-10 02:18:54 -0800767 && (spi->bits_per_word < 4
768 || spi->bits_per_word > 16)) {
769 dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
770 "b/w not 4-16 for type PXA25x_SSP\n",
771 drv_data->ssp_type, spi->bits_per_word);
Stephen Streete0c99052006-03-07 23:53:24 -0800772 return -EINVAL;
Stephen Street8d94cc52006-12-10 02:18:54 -0800773 }
Stephen Streete0c99052006-03-07 23:53:24 -0800774
Stephen Street8d94cc52006-12-10 02:18:54 -0800775 /* Only alloc on first setup */
Stephen Streete0c99052006-03-07 23:53:24 -0800776 chip = spi_get_ctldata(spi);
Stephen Street8d94cc52006-12-10 02:18:54 -0800777 if (!chip) {
Stephen Streete0c99052006-03-07 23:53:24 -0800778 chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
Stephen Street8d94cc52006-12-10 02:18:54 -0800779 if (!chip) {
780 dev_err(&spi->dev,
781 "failed setup: can't allocate chip data\n");
Stephen Streete0c99052006-03-07 23:53:24 -0800782 return -ENOMEM;
Stephen Street8d94cc52006-12-10 02:18:54 -0800783 }
Stephen Streete0c99052006-03-07 23:53:24 -0800784
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800785 if (drv_data->ssp_type == CE4100_SSP) {
786 if (spi->chip_select > 4) {
787 dev_err(&spi->dev, "failed setup: "
788 "cs number must not be > 4.\n");
789 kfree(chip);
790 return -EINVAL;
791 }
792
793 chip->frm = spi->chip_select;
794 } else
795 chip->gpio_cs = -1;
Stephen Streete0c99052006-03-07 23:53:24 -0800796 chip->enable_dma = 0;
Vernon Sauderf1f640a2008-10-15 22:02:43 -0700797 chip->timeout = TIMOUT_DFLT;
Stephen Streete0c99052006-03-07 23:53:24 -0800798 }
799
Stephen Street8d94cc52006-12-10 02:18:54 -0800800 /* protocol drivers may change the chip settings, so...
801 * if chip_info exists, use it */
802 chip_info = spi->controller_data;
803
Stephen Streete0c99052006-03-07 23:53:24 -0800804 /* chip_info isn't always needed */
Stephen Street8d94cc52006-12-10 02:18:54 -0800805 chip->cr1 = 0;
Stephen Streete0c99052006-03-07 23:53:24 -0800806 if (chip_info) {
Vernon Sauderf1f640a2008-10-15 22:02:43 -0700807 if (chip_info->timeout)
808 chip->timeout = chip_info->timeout;
809 if (chip_info->tx_threshold)
810 tx_thres = chip_info->tx_threshold;
811 if (chip_info->rx_threshold)
812 rx_thres = chip_info->rx_threshold;
813 chip->enable_dma = drv_data->master_info->enable_dma;
Stephen Streete0c99052006-03-07 23:53:24 -0800814 chip->dma_threshold = 0;
Stephen Streete0c99052006-03-07 23:53:24 -0800815 if (chip_info->enable_loopback)
816 chip->cr1 = SSCR1_LBM;
817 }
818
Vernon Sauderf1f640a2008-10-15 22:02:43 -0700819 chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
820 (SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
821
Stephen Street8d94cc52006-12-10 02:18:54 -0800822 /* set dma burst and threshold outside of chip_info path so that if
823 * chip_info goes away after setting chip->enable_dma, the
824 * burst and threshold can still respond to changes in bits_per_word */
825 if (chip->enable_dma) {
826 /* set up legal burst and threshold for dma */
Mika Westerbergcd7bed02013-01-22 12:26:28 +0200827 if (pxa2xx_spi_set_dma_burst_and_threshold(chip, spi,
828 spi->bits_per_word,
Stephen Street8d94cc52006-12-10 02:18:54 -0800829 &chip->dma_burst_size,
830 &chip->dma_threshold)) {
831 dev_warn(&spi->dev, "in setup: DMA burst size reduced "
832 "to match bits_per_word\n");
833 }
834 }
835
Mika Westerberg3343b7a2013-01-22 12:26:27 +0200836 clk_div = ssp_get_clk_div(drv_data, spi->max_speed_hz);
Stephen Street9708c122006-03-28 14:05:23 -0800837 chip->speed_hz = spi->max_speed_hz;
Stephen Streete0c99052006-03-07 23:53:24 -0800838
839 chip->cr0 = clk_div
840 | SSCR0_Motorola
Stephen Street5daa3ba2006-05-20 15:00:19 -0700841 | SSCR0_DataSize(spi->bits_per_word > 16 ?
842 spi->bits_per_word - 16 : spi->bits_per_word)
Stephen Streete0c99052006-03-07 23:53:24 -0800843 | SSCR0_SSE
844 | (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
Justin Clacherty7f6ee1a2007-01-26 00:56:44 -0800845 chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
846 chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
847 | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
Stephen Streete0c99052006-03-07 23:53:24 -0800848
Mika Westerbergb8331722013-01-22 12:26:31 +0200849 if (spi->mode & SPI_LOOP)
850 chip->cr1 |= SSCR1_LBM;
851
Stephen Streete0c99052006-03-07 23:53:24 -0800852 /* NOTE: PXA25x_SSP _could_ use external clocking ... */
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800853 if (!pxa25x_ssp_comp(drv_data))
David Brownell7d077192009-06-17 16:26:03 -0700854 dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
Mika Westerberg3343b7a2013-01-22 12:26:27 +0200855 drv_data->max_clk_rate
Eric Miaoc9840da2010-03-16 16:48:01 +0800856 / (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
857 chip->enable_dma ? "DMA" : "PIO");
Stephen Streete0c99052006-03-07 23:53:24 -0800858 else
David Brownell7d077192009-06-17 16:26:03 -0700859 dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
Mika Westerberg3343b7a2013-01-22 12:26:27 +0200860 drv_data->max_clk_rate / 2
Eric Miaoc9840da2010-03-16 16:48:01 +0800861 / (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)),
862 chip->enable_dma ? "DMA" : "PIO");
Stephen Streete0c99052006-03-07 23:53:24 -0800863
864 if (spi->bits_per_word <= 8) {
865 chip->n_bytes = 1;
Stephen Streete0c99052006-03-07 23:53:24 -0800866 chip->read = u8_reader;
867 chip->write = u8_writer;
868 } else if (spi->bits_per_word <= 16) {
869 chip->n_bytes = 2;
Stephen Streete0c99052006-03-07 23:53:24 -0800870 chip->read = u16_reader;
871 chip->write = u16_writer;
872 } else if (spi->bits_per_word <= 32) {
873 chip->cr0 |= SSCR0_EDSS;
874 chip->n_bytes = 4;
Stephen Streete0c99052006-03-07 23:53:24 -0800875 chip->read = u32_reader;
876 chip->write = u32_writer;
877 } else {
878 dev_err(&spi->dev, "invalid wordsize\n");
Stephen Streete0c99052006-03-07 23:53:24 -0800879 return -ENODEV;
880 }
Stephen Street9708c122006-03-28 14:05:23 -0800881 chip->bits_per_word = spi->bits_per_word;
Stephen Streete0c99052006-03-07 23:53:24 -0800882
883 spi_set_ctldata(spi, chip);
884
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800885 if (drv_data->ssp_type == CE4100_SSP)
886 return 0;
887
Eric Miaoa7bb3902009-04-06 19:00:54 -0700888 return setup_cs(spi, chip, chip_info);
Stephen Streete0c99052006-03-07 23:53:24 -0800889}
890
Hans-Peter Nilsson0ffa0282007-02-12 00:52:45 -0800891static void cleanup(struct spi_device *spi)
Stephen Streete0c99052006-03-07 23:53:24 -0800892{
Hans-Peter Nilsson0ffa0282007-02-12 00:52:45 -0800893 struct chip_data *chip = spi_get_ctldata(spi);
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800894 struct driver_data *drv_data = spi_master_get_devdata(spi->master);
Stephen Streete0c99052006-03-07 23:53:24 -0800895
Daniel Ribeiro7348d822009-05-12 13:19:36 -0700896 if (!chip)
897 return;
898
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800899 if (drv_data->ssp_type != CE4100_SSP && gpio_is_valid(chip->gpio_cs))
Eric Miaoa7bb3902009-04-06 19:00:54 -0700900 gpio_free(chip->gpio_cs);
901
Stephen Streete0c99052006-03-07 23:53:24 -0800902 kfree(chip);
903}
904
Grant Likelyfd4a3192012-12-07 16:57:14 +0000905static int pxa2xx_spi_probe(struct platform_device *pdev)
Stephen Streete0c99052006-03-07 23:53:24 -0800906{
907 struct device *dev = &pdev->dev;
908 struct pxa2xx_spi_master *platform_info;
909 struct spi_master *master;
Guennadi Liakhovetski65a00a22008-10-15 22:02:42 -0700910 struct driver_data *drv_data;
eric miao2f1a74e2007-11-21 18:50:53 +0800911 struct ssp_device *ssp;
Guennadi Liakhovetski65a00a22008-10-15 22:02:42 -0700912 int status;
Stephen Streete0c99052006-03-07 23:53:24 -0800913
Mika Westerberg851bacf2013-01-07 12:44:33 +0200914 platform_info = dev_get_platdata(dev);
915 if (!platform_info) {
916 dev_err(&pdev->dev, "missing platform data\n");
917 return -ENODEV;
918 }
Stephen Streete0c99052006-03-07 23:53:24 -0800919
Haojian Zhuangbaffe162010-05-05 10:11:15 -0400920 ssp = pxa_ssp_request(pdev->id, pdev->name);
Mika Westerberg851bacf2013-01-07 12:44:33 +0200921 if (!ssp)
922 ssp = &platform_info->ssp;
923
924 if (!ssp->mmio_base) {
925 dev_err(&pdev->dev, "failed to get ssp\n");
Stephen Streete0c99052006-03-07 23:53:24 -0800926 return -ENODEV;
927 }
928
929 /* Allocate master with space for drv_data and null dma buffer */
930 master = spi_alloc_master(dev, sizeof(struct driver_data) + 16);
931 if (!master) {
Guennadi Liakhovetski65a00a22008-10-15 22:02:42 -0700932 dev_err(&pdev->dev, "cannot alloc spi_master\n");
Haojian Zhuangbaffe162010-05-05 10:11:15 -0400933 pxa_ssp_free(ssp);
Stephen Streete0c99052006-03-07 23:53:24 -0800934 return -ENOMEM;
935 }
936 drv_data = spi_master_get_devdata(master);
937 drv_data->master = master;
938 drv_data->master_info = platform_info;
939 drv_data->pdev = pdev;
eric miao2f1a74e2007-11-21 18:50:53 +0800940 drv_data->ssp = ssp;
Stephen Streete0c99052006-03-07 23:53:24 -0800941
Sebastian Andrzej Siewior21486af2010-10-08 18:11:19 +0200942 master->dev.parent = &pdev->dev;
Sebastian Andrzej Siewior21486af2010-10-08 18:11:19 +0200943 master->dev.of_node = pdev->dev.of_node;
David Brownelle7db06b2009-06-17 16:26:04 -0700944 /* the spi->mode bits understood by this driver: */
Mika Westerbergb8331722013-01-22 12:26:31 +0200945 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
David Brownelle7db06b2009-06-17 16:26:04 -0700946
Mika Westerberg851bacf2013-01-07 12:44:33 +0200947 master->bus_num = ssp->port_id;
Stephen Streete0c99052006-03-07 23:53:24 -0800948 master->num_chipselect = platform_info->num_chipselect;
Mike Rapoport7ad0ba92009-04-06 19:00:57 -0700949 master->dma_alignment = DMA_ALIGNMENT;
Stephen Streete0c99052006-03-07 23:53:24 -0800950 master->cleanup = cleanup;
951 master->setup = setup;
Mika Westerberg7f86bde2013-01-22 12:26:26 +0200952 master->transfer_one_message = pxa2xx_spi_transfer_one_message;
Mika Westerberg7d94a502013-01-22 12:26:30 +0200953 master->prepare_transfer_hardware = pxa2xx_spi_prepare_transfer;
954 master->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer;
Stephen Streete0c99052006-03-07 23:53:24 -0800955
eric miao2f1a74e2007-11-21 18:50:53 +0800956 drv_data->ssp_type = ssp->type;
Mika Westerberg2b9b84f2013-01-22 12:26:25 +0200957 drv_data->null_dma_buf = (u32 *)PTR_ALIGN(&drv_data[1], DMA_ALIGNMENT);
Stephen Streete0c99052006-03-07 23:53:24 -0800958
eric miao2f1a74e2007-11-21 18:50:53 +0800959 drv_data->ioaddr = ssp->mmio_base;
960 drv_data->ssdr_physical = ssp->phys_base + SSDR;
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -0800961 if (pxa25x_ssp_comp(drv_data)) {
Stephen Streete0c99052006-03-07 23:53:24 -0800962 drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE;
963 drv_data->dma_cr1 = 0;
964 drv_data->clear_sr = SSSR_ROR;
965 drv_data->mask_sr = SSSR_RFS | SSSR_TFS | SSSR_ROR;
966 } else {
967 drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE;
Mika Westerberg59288082013-01-22 12:26:29 +0200968 drv_data->dma_cr1 = DEFAULT_DMA_CR1;
Stephen Streete0c99052006-03-07 23:53:24 -0800969 drv_data->clear_sr = SSSR_ROR | SSSR_TINT;
970 drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR;
971 }
972
Sebastian Andrzej Siewior49cbb1e2010-11-22 17:12:14 -0800973 status = request_irq(ssp->irq, ssp_int, IRQF_SHARED, dev_name(dev),
974 drv_data);
Stephen Streete0c99052006-03-07 23:53:24 -0800975 if (status < 0) {
Guennadi Liakhovetski65a00a22008-10-15 22:02:42 -0700976 dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq);
Stephen Streete0c99052006-03-07 23:53:24 -0800977 goto out_error_master_alloc;
978 }
979
980 /* Setup DMA if requested */
981 drv_data->tx_channel = -1;
982 drv_data->rx_channel = -1;
983 if (platform_info->enable_dma) {
Mika Westerbergcd7bed02013-01-22 12:26:28 +0200984 status = pxa2xx_spi_dma_setup(drv_data);
985 if (status) {
986 dev_warn(dev, "failed to setup DMA, using PIO\n");
987 platform_info->enable_dma = false;
Stephen Streete0c99052006-03-07 23:53:24 -0800988 }
Stephen Streete0c99052006-03-07 23:53:24 -0800989 }
990
991 /* Enable SOC clock */
Mika Westerberg3343b7a2013-01-22 12:26:27 +0200992 clk_prepare_enable(ssp->clk);
993
994 drv_data->max_clk_rate = clk_get_rate(ssp->clk);
Stephen Streete0c99052006-03-07 23:53:24 -0800995
996 /* Load default SSP configuration */
997 write_SSCR0(0, drv_data->ioaddr);
Vernon Sauderf1f640a2008-10-15 22:02:43 -0700998 write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) |
999 SSCR1_TxTresh(TX_THRESH_DFLT),
1000 drv_data->ioaddr);
Eric Miaoc9840da2010-03-16 16:48:01 +08001001 write_SSCR0(SSCR0_SCR(2)
Stephen Streete0c99052006-03-07 23:53:24 -08001002 | SSCR0_Motorola
1003 | SSCR0_DataSize(8),
1004 drv_data->ioaddr);
Sebastian Andrzej Siewior2a8626a2010-11-22 17:12:17 -08001005 if (!pxa25x_ssp_comp(drv_data))
Stephen Streete0c99052006-03-07 23:53:24 -08001006 write_SSTO(0, drv_data->ioaddr);
1007 write_SSPSP(0, drv_data->ioaddr);
1008
Mika Westerberg7f86bde2013-01-22 12:26:26 +02001009 tasklet_init(&drv_data->pump_transfers, pump_transfers,
1010 (unsigned long)drv_data);
Stephen Streete0c99052006-03-07 23:53:24 -08001011
1012 /* Register with the SPI framework */
1013 platform_set_drvdata(pdev, drv_data);
1014 status = spi_register_master(master);
1015 if (status != 0) {
1016 dev_err(&pdev->dev, "problem registering spi master\n");
Mika Westerberg7f86bde2013-01-22 12:26:26 +02001017 goto out_error_clock_enabled;
Stephen Streete0c99052006-03-07 23:53:24 -08001018 }
1019
Mika Westerberg7d94a502013-01-22 12:26:30 +02001020 pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
1021 pm_runtime_use_autosuspend(&pdev->dev);
1022 pm_runtime_set_active(&pdev->dev);
1023 pm_runtime_enable(&pdev->dev);
1024
Stephen Streete0c99052006-03-07 23:53:24 -08001025 return status;
1026
Stephen Streete0c99052006-03-07 23:53:24 -08001027out_error_clock_enabled:
Mika Westerberg3343b7a2013-01-22 12:26:27 +02001028 clk_disable_unprepare(ssp->clk);
Mika Westerbergcd7bed02013-01-22 12:26:28 +02001029 pxa2xx_spi_dma_release(drv_data);
eric miao2f1a74e2007-11-21 18:50:53 +08001030 free_irq(ssp->irq, drv_data);
Stephen Streete0c99052006-03-07 23:53:24 -08001031
1032out_error_master_alloc:
1033 spi_master_put(master);
Haojian Zhuangbaffe162010-05-05 10:11:15 -04001034 pxa_ssp_free(ssp);
Stephen Streete0c99052006-03-07 23:53:24 -08001035 return status;
1036}
1037
1038static int pxa2xx_spi_remove(struct platform_device *pdev)
1039{
1040 struct driver_data *drv_data = platform_get_drvdata(pdev);
Julia Lawall51e911e2009-01-06 14:41:45 -08001041 struct ssp_device *ssp;
Stephen Streete0c99052006-03-07 23:53:24 -08001042
1043 if (!drv_data)
1044 return 0;
Julia Lawall51e911e2009-01-06 14:41:45 -08001045 ssp = drv_data->ssp;
Stephen Streete0c99052006-03-07 23:53:24 -08001046
Mika Westerberg7d94a502013-01-22 12:26:30 +02001047 pm_runtime_get_sync(&pdev->dev);
1048
Stephen Streete0c99052006-03-07 23:53:24 -08001049 /* Disable the SSP at the peripheral and SOC level */
1050 write_SSCR0(0, drv_data->ioaddr);
Mika Westerberg3343b7a2013-01-22 12:26:27 +02001051 clk_disable_unprepare(ssp->clk);
Stephen Streete0c99052006-03-07 23:53:24 -08001052
1053 /* Release DMA */
Mika Westerbergcd7bed02013-01-22 12:26:28 +02001054 if (drv_data->master_info->enable_dma)
1055 pxa2xx_spi_dma_release(drv_data);
Stephen Streete0c99052006-03-07 23:53:24 -08001056
Mika Westerberg7d94a502013-01-22 12:26:30 +02001057 pm_runtime_put_noidle(&pdev->dev);
1058 pm_runtime_disable(&pdev->dev);
1059
Stephen Streete0c99052006-03-07 23:53:24 -08001060 /* Release IRQ */
eric miao2f1a74e2007-11-21 18:50:53 +08001061 free_irq(ssp->irq, drv_data);
1062
1063 /* Release SSP */
Haojian Zhuangbaffe162010-05-05 10:11:15 -04001064 pxa_ssp_free(ssp);
Stephen Streete0c99052006-03-07 23:53:24 -08001065
1066 /* Disconnect from the SPI framework */
1067 spi_unregister_master(drv_data->master);
1068
1069 /* Prevent double remove */
1070 platform_set_drvdata(pdev, NULL);
1071
1072 return 0;
1073}
1074
1075static void pxa2xx_spi_shutdown(struct platform_device *pdev)
1076{
1077 int status = 0;
1078
1079 if ((status = pxa2xx_spi_remove(pdev)) != 0)
1080 dev_err(&pdev->dev, "shutdown failed with %d\n", status);
1081}
1082
1083#ifdef CONFIG_PM
Mike Rapoport86d25932009-07-21 17:50:16 +03001084static int pxa2xx_spi_suspend(struct device *dev)
Stephen Streete0c99052006-03-07 23:53:24 -08001085{
Mike Rapoport86d25932009-07-21 17:50:16 +03001086 struct driver_data *drv_data = dev_get_drvdata(dev);
eric miao2f1a74e2007-11-21 18:50:53 +08001087 struct ssp_device *ssp = drv_data->ssp;
Stephen Streete0c99052006-03-07 23:53:24 -08001088 int status = 0;
1089
Mika Westerberg7f86bde2013-01-22 12:26:26 +02001090 status = spi_master_suspend(drv_data->master);
Stephen Streete0c99052006-03-07 23:53:24 -08001091 if (status != 0)
1092 return status;
1093 write_SSCR0(0, drv_data->ioaddr);
Mika Westerberg3343b7a2013-01-22 12:26:27 +02001094 clk_disable_unprepare(ssp->clk);
Stephen Streete0c99052006-03-07 23:53:24 -08001095
1096 return 0;
1097}
1098
Mike Rapoport86d25932009-07-21 17:50:16 +03001099static int pxa2xx_spi_resume(struct device *dev)
Stephen Streete0c99052006-03-07 23:53:24 -08001100{
Mike Rapoport86d25932009-07-21 17:50:16 +03001101 struct driver_data *drv_data = dev_get_drvdata(dev);
eric miao2f1a74e2007-11-21 18:50:53 +08001102 struct ssp_device *ssp = drv_data->ssp;
Stephen Streete0c99052006-03-07 23:53:24 -08001103 int status = 0;
1104
Mika Westerbergcd7bed02013-01-22 12:26:28 +02001105 pxa2xx_spi_dma_resume(drv_data);
Daniel Ribeiro148da332009-04-21 12:24:43 -07001106
Stephen Streete0c99052006-03-07 23:53:24 -08001107 /* Enable the SSP clock */
Mika Westerberg3343b7a2013-01-22 12:26:27 +02001108 clk_prepare_enable(ssp->clk);
Stephen Streete0c99052006-03-07 23:53:24 -08001109
1110 /* Start the queue running */
Mika Westerberg7f86bde2013-01-22 12:26:26 +02001111 status = spi_master_resume(drv_data->master);
Stephen Streete0c99052006-03-07 23:53:24 -08001112 if (status != 0) {
Mike Rapoport86d25932009-07-21 17:50:16 +03001113 dev_err(dev, "problem starting queue (%d)\n", status);
Stephen Streete0c99052006-03-07 23:53:24 -08001114 return status;
1115 }
1116
1117 return 0;
1118}
Mika Westerberg7d94a502013-01-22 12:26:30 +02001119#endif
1120
1121#ifdef CONFIG_PM_RUNTIME
1122static int pxa2xx_spi_runtime_suspend(struct device *dev)
1123{
1124 struct driver_data *drv_data = dev_get_drvdata(dev);
1125
1126 clk_disable_unprepare(drv_data->ssp->clk);
1127 return 0;
1128}
1129
1130static int pxa2xx_spi_runtime_resume(struct device *dev)
1131{
1132 struct driver_data *drv_data = dev_get_drvdata(dev);
1133
1134 clk_prepare_enable(drv_data->ssp->clk);
1135 return 0;
1136}
1137#endif
Mike Rapoport86d25932009-07-21 17:50:16 +03001138
Alexey Dobriyan47145212009-12-14 18:00:08 -08001139static const struct dev_pm_ops pxa2xx_spi_pm_ops = {
Mika Westerberg7d94a502013-01-22 12:26:30 +02001140 SET_SYSTEM_SLEEP_PM_OPS(pxa2xx_spi_suspend, pxa2xx_spi_resume)
1141 SET_RUNTIME_PM_OPS(pxa2xx_spi_runtime_suspend,
1142 pxa2xx_spi_runtime_resume, NULL)
Mike Rapoport86d25932009-07-21 17:50:16 +03001143};
Stephen Streete0c99052006-03-07 23:53:24 -08001144
1145static struct platform_driver driver = {
1146 .driver = {
Mike Rapoport86d25932009-07-21 17:50:16 +03001147 .name = "pxa2xx-spi",
1148 .owner = THIS_MODULE,
Mike Rapoport86d25932009-07-21 17:50:16 +03001149 .pm = &pxa2xx_spi_pm_ops,
Stephen Streete0c99052006-03-07 23:53:24 -08001150 },
Sebastian Andrzej Siewiorfbd29a12010-11-19 09:00:11 -08001151 .probe = pxa2xx_spi_probe,
David Brownelld1e44d92007-10-16 01:27:46 -07001152 .remove = pxa2xx_spi_remove,
Stephen Streete0c99052006-03-07 23:53:24 -08001153 .shutdown = pxa2xx_spi_shutdown,
Stephen Streete0c99052006-03-07 23:53:24 -08001154};
1155
1156static int __init pxa2xx_spi_init(void)
1157{
Sebastian Andrzej Siewiorfbd29a12010-11-19 09:00:11 -08001158 return platform_driver_register(&driver);
Stephen Streete0c99052006-03-07 23:53:24 -08001159}
Antonio Ospite5b61a742009-09-22 16:46:10 -07001160subsys_initcall(pxa2xx_spi_init);
Stephen Streete0c99052006-03-07 23:53:24 -08001161
1162static void __exit pxa2xx_spi_exit(void)
1163{
1164 platform_driver_unregister(&driver);
1165}
1166module_exit(pxa2xx_spi_exit);