diff options
author | Vipul Pandya <vipul@chelsio.com> | 2012-09-25 22:39:37 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-09-27 17:55:50 -0400 |
commit | 5afc8b84eb7b29e4646d6e8ca7e6d7196031d6f7 (patch) | |
tree | 34382fe914af703cbe1bf921c6a2ddac040f91e3 /drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | |
parent | 3eb4afbfceb44750d9afb832e6c992adec9fc571 (diff) |
cxgb4: Add functions to read memory via PCIE memory window
This patch implements two new functions t4_mem_win_read and t4_memory_read.
These new functions can be used to read memory via the PCIE memory window.
Please note, for proper execution of these functions PCIE_MEM_ACCESS_BASE_WIN
registers must be setup correctly like how setup_memwin in the cxgb4 driver
does it.
Signed-off-by: Jay Hernandez <jay@chelsio.com>
Signed-off-by: Vipul Pandya <vipul@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/chelsio/cxgb4/t4_hw.c')
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 8e988d699d05..259d0dcb0089 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | |||
@@ -330,6 +330,143 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc) | |||
330 | return 0; | 330 | return 0; |
331 | } | 331 | } |
332 | 332 | ||
333 | /* | ||
334 | * t4_mem_win_rw - read/write memory through PCIE memory window | ||
335 | * @adap: the adapter | ||
336 | * @addr: address of first byte requested | ||
337 | * @data: MEMWIN0_APERTURE bytes of data containing the requested address | ||
338 | * @dir: direction of transfer 1 => read, 0 => write | ||
339 | * | ||
340 | * Read/write MEMWIN0_APERTURE bytes of data from MC starting at a | ||
341 | * MEMWIN0_APERTURE-byte-aligned address that covers the requested | ||
342 | * address @addr. | ||
343 | */ | ||
344 | static int t4_mem_win_rw(struct adapter *adap, u32 addr, __be32 *data, int dir) | ||
345 | { | ||
346 | int i; | ||
347 | |||
348 | /* | ||
349 | * Setup offset into PCIE memory window. Address must be a | ||
350 | * MEMWIN0_APERTURE-byte-aligned address. (Read back MA register to | ||
351 | * ensure that changes propagate before we attempt to use the new | ||
352 | * values.) | ||
353 | */ | ||
354 | t4_write_reg(adap, PCIE_MEM_ACCESS_OFFSET, | ||
355 | addr & ~(MEMWIN0_APERTURE - 1)); | ||
356 | t4_read_reg(adap, PCIE_MEM_ACCESS_OFFSET); | ||
357 | |||
358 | /* Collecting data 4 bytes at a time upto MEMWIN0_APERTURE */ | ||
359 | for (i = 0; i < MEMWIN0_APERTURE; i = i+0x4) { | ||
360 | if (dir) | ||
361 | *data++ = t4_read_reg(adap, (MEMWIN0_BASE + i)); | ||
362 | else | ||
363 | t4_write_reg(adap, (MEMWIN0_BASE + i), *data++); | ||
364 | } | ||
365 | |||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | /** | ||
370 | * t4_memory_rw - read/write EDC 0, EDC 1 or MC via PCIE memory window | ||
371 | * @adap: the adapter | ||
372 | * @mtype: memory type: MEM_EDC0, MEM_EDC1 or MEM_MC | ||
373 | * @addr: address within indicated memory type | ||
374 | * @len: amount of memory to transfer | ||
375 | * @buf: host memory buffer | ||
376 | * @dir: direction of transfer 1 => read, 0 => write | ||
377 | * | ||
378 | * Reads/writes an [almost] arbitrary memory region in the firmware: the | ||
379 | * firmware memory address, length and host buffer must be aligned on | ||
380 | * 32-bit boudaries. The memory is transferred as a raw byte sequence | ||
381 | * from/to the firmware's memory. If this memory contains data | ||
382 | * structures which contain multi-byte integers, it's the callers | ||
383 | * responsibility to perform appropriate byte order conversions. | ||
384 | */ | ||
385 | static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len, | ||
386 | __be32 *buf, int dir) | ||
387 | { | ||
388 | u32 pos, start, end, offset, memoffset; | ||
389 | int ret; | ||
390 | |||
391 | /* | ||
392 | * Argument sanity checks ... | ||
393 | */ | ||
394 | if ((addr & 0x3) || (len & 0x3)) | ||
395 | return -EINVAL; | ||
396 | |||
397 | /* | ||
398 | * Offset into the region of memory which is being accessed | ||
399 | * MEM_EDC0 = 0 | ||
400 | * MEM_EDC1 = 1 | ||
401 | * MEM_MC = 2 | ||
402 | */ | ||
403 | memoffset = (mtype * (5 * 1024 * 1024)); | ||
404 | |||
405 | /* Determine the PCIE_MEM_ACCESS_OFFSET */ | ||
406 | addr = addr + memoffset; | ||
407 | |||
408 | /* | ||
409 | * The underlaying EDC/MC read routines read MEMWIN0_APERTURE bytes | ||
410 | * at a time so we need to round down the start and round up the end. | ||
411 | * We'll start copying out of the first line at (addr - start) a word | ||
412 | * at a time. | ||
413 | */ | ||
414 | start = addr & ~(MEMWIN0_APERTURE-1); | ||
415 | end = (addr + len + MEMWIN0_APERTURE-1) & ~(MEMWIN0_APERTURE-1); | ||
416 | offset = (addr - start)/sizeof(__be32); | ||
417 | |||
418 | for (pos = start; pos < end; pos += MEMWIN0_APERTURE, offset = 0) { | ||
419 | __be32 data[MEMWIN0_APERTURE/sizeof(__be32)]; | ||
420 | |||
421 | /* | ||
422 | * If we're writing, copy the data from the caller's memory | ||
423 | * buffer | ||
424 | */ | ||
425 | if (!dir) { | ||
426 | /* | ||
427 | * If we're doing a partial write, then we need to do | ||
428 | * a read-modify-write ... | ||
429 | */ | ||
430 | if (offset || len < MEMWIN0_APERTURE) { | ||
431 | ret = t4_mem_win_rw(adap, pos, data, 1); | ||
432 | if (ret) | ||
433 | return ret; | ||
434 | } | ||
435 | while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) && | ||
436 | len > 0) { | ||
437 | data[offset++] = *buf++; | ||
438 | len -= sizeof(__be32); | ||
439 | } | ||
440 | } | ||
441 | |||
442 | /* | ||
443 | * Transfer a block of memory and bail if there's an error. | ||
444 | */ | ||
445 | ret = t4_mem_win_rw(adap, pos, data, dir); | ||
446 | if (ret) | ||
447 | return ret; | ||
448 | |||
449 | /* | ||
450 | * If we're reading, copy the data into the caller's memory | ||
451 | * buffer. | ||
452 | */ | ||
453 | if (dir) | ||
454 | while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) && | ||
455 | len > 0) { | ||
456 | *buf++ = data[offset++]; | ||
457 | len -= sizeof(__be32); | ||
458 | } | ||
459 | } | ||
460 | |||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len, | ||
465 | __be32 *buf) | ||
466 | { | ||
467 | return t4_memory_rw(adap, mtype, addr, len, buf, 0); | ||
468 | } | ||
469 | |||
333 | #define EEPROM_STAT_ADDR 0x7bfc | 470 | #define EEPROM_STAT_ADDR 0x7bfc |
334 | #define VPD_BASE 0 | 471 | #define VPD_BASE 0 |
335 | #define VPD_LEN 512 | 472 | #define VPD_LEN 512 |