diff options
author | Vitaly Wool <vwool@ru.mvista.com> | 2006-01-08 16:34:28 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-13 19:29:56 -0500 |
commit | 8275c642ccdce09a2146d0a9eb022e3698ee927e (patch) | |
tree | ea330810f665fcbdf36d31b0da1643db528ad83f /drivers/mtd/devices | |
parent | 2f9f762879015d738a5ec2ac8a16be94b3a4a06d (diff) |
[PATCH] spi: use linked lists rather than an array
This makes the SPI core and its users access transfers in the SPI message
structure as linked list not as an array, as discussed on LKML.
From: David Brownell <dbrownell@users.sourceforge.net>
Updates including doc, bugfixes to the list code, add
spi_message_add_tail(). Plus, initialize things _before_ grabbing the
locks in some cases (in case it grows more expensive). This also merges
some bitbang updates of mine that didn't yet make it into the mm tree.
Signed-off-by: Vitaly Wool <vwool@ru.mvista.com>
Signed-off-by: Dmitry Pervushin <dpervushin@gmail.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/mtd/devices')
-rw-r--r-- | drivers/mtd/devices/m25p80.c | 50 | ||||
-rw-r--r-- | drivers/mtd/devices/mtd_dataflash.c | 28 |
2 files changed, 42 insertions, 36 deletions
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 71a072103a7f..45108ed85588 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -245,6 +245,21 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
245 | if (from + len > flash->mtd.size) | 245 | if (from + len > flash->mtd.size) |
246 | return -EINVAL; | 246 | return -EINVAL; |
247 | 247 | ||
248 | spi_message_init(&m); | ||
249 | memset(t, 0, (sizeof t)); | ||
250 | |||
251 | t[0].tx_buf = flash->command; | ||
252 | t[0].len = sizeof(flash->command); | ||
253 | spi_message_add_tail(&t[0], &m); | ||
254 | |||
255 | t[1].rx_buf = buf; | ||
256 | t[1].len = len; | ||
257 | spi_message_add_tail(&t[1], &m); | ||
258 | |||
259 | /* Byte count starts at zero. */ | ||
260 | if (retlen) | ||
261 | *retlen = 0; | ||
262 | |||
248 | down(&flash->lock); | 263 | down(&flash->lock); |
249 | 264 | ||
250 | /* Wait till previous write/erase is done. */ | 265 | /* Wait till previous write/erase is done. */ |
@@ -254,8 +269,6 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
254 | return 1; | 269 | return 1; |
255 | } | 270 | } |
256 | 271 | ||
257 | memset(t, 0, (sizeof t)); | ||
258 | |||
259 | /* NOTE: OPCODE_FAST_READ (if available) is faster... */ | 272 | /* NOTE: OPCODE_FAST_READ (if available) is faster... */ |
260 | 273 | ||
261 | /* Set up the write data buffer. */ | 274 | /* Set up the write data buffer. */ |
@@ -264,19 +277,6 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
264 | flash->command[2] = from >> 8; | 277 | flash->command[2] = from >> 8; |
265 | flash->command[3] = from; | 278 | flash->command[3] = from; |
266 | 279 | ||
267 | /* Byte count starts at zero. */ | ||
268 | if (retlen) | ||
269 | *retlen = 0; | ||
270 | |||
271 | t[0].tx_buf = flash->command; | ||
272 | t[0].len = sizeof(flash->command); | ||
273 | |||
274 | t[1].rx_buf = buf; | ||
275 | t[1].len = len; | ||
276 | |||
277 | m.transfers = t; | ||
278 | m.n_transfer = 2; | ||
279 | |||
280 | spi_sync(flash->spi, &m); | 280 | spi_sync(flash->spi, &m); |
281 | 281 | ||
282 | *retlen = m.actual_length - sizeof(flash->command); | 282 | *retlen = m.actual_length - sizeof(flash->command); |
@@ -313,6 +313,16 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
313 | if (to + len > flash->mtd.size) | 313 | if (to + len > flash->mtd.size) |
314 | return -EINVAL; | 314 | return -EINVAL; |
315 | 315 | ||
316 | spi_message_init(&m); | ||
317 | memset(t, 0, (sizeof t)); | ||
318 | |||
319 | t[0].tx_buf = flash->command; | ||
320 | t[0].len = sizeof(flash->command); | ||
321 | spi_message_add_tail(&t[0], &m); | ||
322 | |||
323 | t[1].tx_buf = buf; | ||
324 | spi_message_add_tail(&t[1], &m); | ||
325 | |||
316 | down(&flash->lock); | 326 | down(&flash->lock); |
317 | 327 | ||
318 | /* Wait until finished previous write command. */ | 328 | /* Wait until finished previous write command. */ |
@@ -321,26 +331,17 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
321 | 331 | ||
322 | write_enable(flash); | 332 | write_enable(flash); |
323 | 333 | ||
324 | memset(t, 0, (sizeof t)); | ||
325 | |||
326 | /* Set up the opcode in the write buffer. */ | 334 | /* Set up the opcode in the write buffer. */ |
327 | flash->command[0] = OPCODE_PP; | 335 | flash->command[0] = OPCODE_PP; |
328 | flash->command[1] = to >> 16; | 336 | flash->command[1] = to >> 16; |
329 | flash->command[2] = to >> 8; | 337 | flash->command[2] = to >> 8; |
330 | flash->command[3] = to; | 338 | flash->command[3] = to; |
331 | 339 | ||
332 | t[0].tx_buf = flash->command; | ||
333 | t[0].len = sizeof(flash->command); | ||
334 | |||
335 | m.transfers = t; | ||
336 | m.n_transfer = 2; | ||
337 | |||
338 | /* what page do we start with? */ | 340 | /* what page do we start with? */ |
339 | page_offset = to % FLASH_PAGESIZE; | 341 | page_offset = to % FLASH_PAGESIZE; |
340 | 342 | ||
341 | /* do all the bytes fit onto one page? */ | 343 | /* do all the bytes fit onto one page? */ |
342 | if (page_offset + len <= FLASH_PAGESIZE) { | 344 | if (page_offset + len <= FLASH_PAGESIZE) { |
343 | t[1].tx_buf = buf; | ||
344 | t[1].len = len; | 345 | t[1].len = len; |
345 | 346 | ||
346 | spi_sync(flash->spi, &m); | 347 | spi_sync(flash->spi, &m); |
@@ -352,7 +353,6 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
352 | /* the size of data remaining on the first page */ | 353 | /* the size of data remaining on the first page */ |
353 | page_size = FLASH_PAGESIZE - page_offset; | 354 | page_size = FLASH_PAGESIZE - page_offset; |
354 | 355 | ||
355 | t[1].tx_buf = buf; | ||
356 | t[1].len = page_size; | 356 | t[1].len = page_size; |
357 | spi_sync(flash->spi, &m); | 357 | spi_sync(flash->spi, &m); |
358 | 358 | ||
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index a39b3b6b266c..99d3a0320fc9 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c | |||
@@ -147,7 +147,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
147 | { | 147 | { |
148 | struct dataflash *priv = (struct dataflash *)mtd->priv; | 148 | struct dataflash *priv = (struct dataflash *)mtd->priv; |
149 | struct spi_device *spi = priv->spi; | 149 | struct spi_device *spi = priv->spi; |
150 | struct spi_transfer x[1] = { { .tx_dma = 0, }, }; | 150 | struct spi_transfer x = { .tx_dma = 0, }; |
151 | struct spi_message msg; | 151 | struct spi_message msg; |
152 | unsigned blocksize = priv->page_size << 3; | 152 | unsigned blocksize = priv->page_size << 3; |
153 | u8 *command; | 153 | u8 *command; |
@@ -162,10 +162,11 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
162 | || (instr->addr % priv->page_size) != 0) | 162 | || (instr->addr % priv->page_size) != 0) |
163 | return -EINVAL; | 163 | return -EINVAL; |
164 | 164 | ||
165 | x[0].tx_buf = command = priv->command; | 165 | spi_message_init(&msg); |
166 | x[0].len = 4; | 166 | |
167 | msg.transfers = x; | 167 | x.tx_buf = command = priv->command; |
168 | msg.n_transfer = 1; | 168 | x.len = 4; |
169 | spi_message_add_tail(&x, &msg); | ||
169 | 170 | ||
170 | down(&priv->lock); | 171 | down(&priv->lock); |
171 | while (instr->len > 0) { | 172 | while (instr->len > 0) { |
@@ -256,12 +257,15 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
256 | DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n", | 257 | DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n", |
257 | command[0], command[1], command[2], command[3]); | 258 | command[0], command[1], command[2], command[3]); |
258 | 259 | ||
260 | spi_message_init(&msg); | ||
261 | |||
259 | x[0].tx_buf = command; | 262 | x[0].tx_buf = command; |
260 | x[0].len = 8; | 263 | x[0].len = 8; |
264 | spi_message_add_tail(&x[0], &msg); | ||
265 | |||
261 | x[1].rx_buf = buf; | 266 | x[1].rx_buf = buf; |
262 | x[1].len = len; | 267 | x[1].len = len; |
263 | msg.transfers = x; | 268 | spi_message_add_tail(&x[1], &msg); |
264 | msg.n_transfer = 2; | ||
265 | 269 | ||
266 | down(&priv->lock); | 270 | down(&priv->lock); |
267 | 271 | ||
@@ -320,9 +324,11 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
320 | if ((to + len) > mtd->size) | 324 | if ((to + len) > mtd->size) |
321 | return -EINVAL; | 325 | return -EINVAL; |
322 | 326 | ||
327 | spi_message_init(&msg); | ||
328 | |||
323 | x[0].tx_buf = command = priv->command; | 329 | x[0].tx_buf = command = priv->command; |
324 | x[0].len = 4; | 330 | x[0].len = 4; |
325 | msg.transfers = x; | 331 | spi_message_add_tail(&x[0], &msg); |
326 | 332 | ||
327 | pageaddr = ((unsigned)to / priv->page_size); | 333 | pageaddr = ((unsigned)to / priv->page_size); |
328 | offset = ((unsigned)to % priv->page_size); | 334 | offset = ((unsigned)to % priv->page_size); |
@@ -364,7 +370,6 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
364 | DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n", | 370 | DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n", |
365 | command[0], command[1], command[2], command[3]); | 371 | command[0], command[1], command[2], command[3]); |
366 | 372 | ||
367 | msg.n_transfer = 1; | ||
368 | status = spi_sync(spi, &msg); | 373 | status = spi_sync(spi, &msg); |
369 | if (status < 0) | 374 | if (status < 0) |
370 | DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n", | 375 | DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n", |
@@ -385,14 +390,16 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
385 | 390 | ||
386 | x[1].tx_buf = writebuf; | 391 | x[1].tx_buf = writebuf; |
387 | x[1].len = writelen; | 392 | x[1].len = writelen; |
388 | msg.n_transfer = 2; | 393 | spi_message_add_tail(x + 1, &msg); |
389 | status = spi_sync(spi, &msg); | 394 | status = spi_sync(spi, &msg); |
395 | spi_transfer_del(x + 1); | ||
390 | if (status < 0) | 396 | if (status < 0) |
391 | DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n", | 397 | DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n", |
392 | spi->dev.bus_id, addr, writelen, status); | 398 | spi->dev.bus_id, addr, writelen, status); |
393 | 399 | ||
394 | (void) dataflash_waitready(priv->spi); | 400 | (void) dataflash_waitready(priv->spi); |
395 | 401 | ||
402 | |||
396 | #ifdef CONFIG_DATAFLASH_WRITE_VERIFY | 403 | #ifdef CONFIG_DATAFLASH_WRITE_VERIFY |
397 | 404 | ||
398 | /* (3) Compare to Buffer1 */ | 405 | /* (3) Compare to Buffer1 */ |
@@ -405,7 +412,6 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
405 | DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n", | 412 | DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n", |
406 | command[0], command[1], command[2], command[3]); | 413 | command[0], command[1], command[2], command[3]); |
407 | 414 | ||
408 | msg.n_transfer = 1; | ||
409 | status = spi_sync(spi, &msg); | 415 | status = spi_sync(spi, &msg); |
410 | if (status < 0) | 416 | if (status < 0) |
411 | DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n", | 417 | DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n", |