Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 14767
b: refs/heads/master
c: 3c77354
h: refs/heads/master
i:
  14765: 853e981
  14763: edbf3a8
  14759: 7b2c7f3
  14751: 23f7151
v: v3
  • Loading branch information
John Bowler authored and Thomas Gleixner committed Nov 29, 2005
1 parent a01779d commit b0bc287
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 13 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 987d24018dc83d27e491674c50ff2272f51eb719
refs/heads/master: 3c77354794939143fdf1dd669895a812f94f9a38
78 changes: 66 additions & 12 deletions trunk/drivers/mtd/maps/ixp4xx.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* $Id: ixp4xx.c,v 1.12 2005/11/07 11:14:27 gleixner Exp $
* $Id: ixp4xx.c,v 1.13 2005/11/16 16:23:21 dvrabel Exp $
*
* drivers/mtd/maps/ixp4xx.c
*
Expand Down Expand Up @@ -34,18 +34,63 @@

#include <linux/reboot.h>

/*
* Read/write a 16 bit word from flash address 'addr'.
*
* When the cpu is in little-endian mode it swizzles the address lines
* ('address coherency') so we need to undo the swizzling to ensure commands
* and the like end up on the correct flash address.
*
* To further complicate matters, due to the way the expansion bus controller
* handles 32 bit reads, the byte stream ABCD is stored on the flash as:
* D15 D0
* +---+---+
* | A | B | 0
* +---+---+
* | C | D | 2
* +---+---+
* This means that on LE systems each 16 bit word must be swapped. Note that
* this requires CONFIG_MTD_CFI_BE_BYTE_SWAP to be enabled to 'unswap' the CFI
* data and other flash commands which are always in D7-D0.
*/
#ifndef __ARMEB__
#ifndef CONFIG_MTD_CFI_BE_BYTE_SWAP
# error CONFIG_MTD_CFI_BE_BYTE_SWAP required
#endif

static inline u16 flash_read16(void __iomem *addr)
{
return be16_to_cpu(__raw_readw((void __iomem *)((unsigned long)addr ^ 0x2)));
}

static inline void flash_write16(u16 d, void __iomem *addr)
{
__raw_writew(cpu_to_be16(d), (void __iomem *)((unsigned long)addr ^ 0x2));
}

#define BYTE0(h) ((h) & 0xFF)
#define BYTE1(h) (((h) >> 8) & 0xFF)

#else

static inline u16 flash_read16(const void __iomem *addr)
{
return __raw_readw(addr);
}

static inline void flash_write16(u16 d, void __iomem *addr)
{
__raw_writew(d, addr);
}

#define BYTE0(h) (((h) >> 8) & 0xFF)
#define BYTE1(h) ((h) & 0xFF)
#endif

static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs)
{
map_word val;
val.x[0] = le16_to_cpu(readw(map->virt + ofs));
val.x[0] = flash_read16(map->virt + ofs);
return val;
}

Expand All @@ -57,19 +102,28 @@ static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs)
static void ixp4xx_copy_from(struct map_info *map, void *to,
unsigned long from, ssize_t len)
{
int i;
u8 *dest = (u8 *) to;
void __iomem *src = map->virt + from;
u16 data;

for (i = 0; i < (len / 2); i++) {
data = le16_to_cpu(readw(src + 2*i));
dest[i * 2] = BYTE0(data);
dest[i * 2 + 1] = BYTE1(data);
if (len <= 0)
return;

if (from & 1) {
*dest++ = BYTE1(flash_read16(src));
src++;
--len;
}

if (len & 1)
dest[len - 1] = BYTE0(le16_to_cpu(readw(src + 2*i)));
while (len >= 2) {
u16 data = flash_read16(src);
*dest++ = BYTE0(data);
*dest++ = BYTE1(data);
src += 2;
len -= 2;
}

if (len > 0)
*dest++ = BYTE0(flash_read16(src));
}

/*
Expand All @@ -79,15 +133,15 @@ static void ixp4xx_copy_from(struct map_info *map, void *to,
static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr)
{
if (!(adr & 1))
writew(cpu_to_le16(d.x[0]), map->virt + adr);
flash_write16(d.x[0], map->virt + adr);
}

/*
* Fast write16 function without the probing check above
*/
static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
{
writew(cpu_to_le16(d.x[0]), map->virt + adr);
flash_write16(d.x[0], map->virt + adr);
}

struct ixp4xx_flash_info {
Expand Down

0 comments on commit b0bc287

Please sign in to comment.