diff options
author | Jonas Gorski <jogo@openwrt.org> | 2015-02-27 17:40:17 +0000 |
---|---|---|
committer | Jonas Gorski <jogo@openwrt.org> | 2015-02-27 17:40:17 +0000 |
commit | aa4d5abef003bad1eea90560ab8a5d507a349de0 (patch) | |
tree | a5593f9bedc20d4b71279f3e1babbba599f83e16 /target/linux/generic/files/drivers/net | |
parent | c5696515d1ae7d88c59291367198ed3a73d5de59 (diff) | |
download | master-187ad058-aa4d5abef003bad1eea90560ab8a5d507a349de0.tar.gz master-187ad058-aa4d5abef003bad1eea90560ab8a5d507a349de0.tar.bz2 master-187ad058-aa4d5abef003bad1eea90560ab8a5d507a349de0.zip |
b53: fix mmap register read/writes > 32 bit
For bcm63xx integrated switches, broadcom changed the data endianess
to match the system endianess. But this only applies to within one word,
which causes 48/64 bit values to be still split into their "litte endian"
groups.
E.g. 48 bit values (with 5 being the most significant byte) aligned
0x00 ..01 or 0123
0x04 2345 45..
will become
0x00 ..10 resp. 3210
0x04 5432 54..
Likewise for 64 bit values.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@44568 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/generic/files/drivers/net')
-rw-r--r-- | target/linux/generic/files/drivers/net/phy/b53/b53_mmap.c | 70 |
1 files changed, 36 insertions, 34 deletions
diff --git a/target/linux/generic/files/drivers/net/phy/b53/b53_mmap.c b/target/linux/generic/files/drivers/net/phy/b53/b53_mmap.c index 272360f6de..b8681660cc 100644 --- a/target/linux/generic/files/drivers/net/phy/b53/b53_mmap.c +++ b/target/linux/generic/files/drivers/net/phy/b53/b53_mmap.c @@ -64,19 +64,25 @@ static int b53_mmap_read32(struct b53_device *dev, u8 page, u8 reg, u32 *val) static int b53_mmap_read48(struct b53_device *dev, u8 page, u8 reg, u64 *val) { - u8 __iomem *regs = dev->priv; - - if (WARN_ON(reg % 4)) + if (WARN_ON(reg % 2)) return -EINVAL; - if (dev->pdata && dev->pdata->big_endian) { - *val = readl_be(regs + (page << 8) + reg); - *val <<= 16; - *val |= readw_be(regs + (page << 8) + reg + 4); + if (reg % 4) { + u16 lo; + u32 hi; + + b53_mmap_read16(dev, page, reg, &lo); + b53_mmap_read32(dev, page, reg + 2, &hi); + + *val = ((u64)hi << 16) | lo; } else { - *val |= readw(regs + (page << 8) + reg + 4); - *val <<= 32; - *val = readl(regs + (page << 8) + reg); + u32 lo; + u16 hi; + + b53_mmap_read32(dev, page, reg, &lo); + b53_mmap_read16(dev, page, reg + 4, &hi); + + *val = ((u64)hi << 32) | lo; } return 0; @@ -84,19 +90,13 @@ static int b53_mmap_read48(struct b53_device *dev, u8 page, u8 reg, u64 *val) static int b53_mmap_read64(struct b53_device *dev, u8 page, u8 reg, u64 *val) { - u8 __iomem *regs = dev->priv; u32 hi, lo; if (WARN_ON(reg % 4)) return -EINVAL; - if (dev->pdata && dev->pdata->big_endian) { - lo = readl_be(regs + (page << 8) + reg); - hi = readl_be(regs + (page << 8) + reg + 4); - } else { - lo = readl(regs + (page << 8) + reg); - hi = readl(regs + (page << 8) + reg + 4); - } + b53_mmap_read32(dev, page, reg, &lo); + b53_mmap_read32(dev, page, reg + 4, &hi); *val = ((u64)hi << 32) | lo; @@ -147,17 +147,21 @@ static int b53_mmap_write32(struct b53_device *dev, u8 page, u8 reg, static int b53_mmap_write48(struct b53_device *dev, u8 page, u8 reg, u64 value) { - u8 __iomem *regs = dev->priv; - - if (WARN_ON(reg % 4)) + if (WARN_ON(reg % 2)) return -EINVAL; - if (dev->pdata && dev->pdata->big_endian) { - writel_be((u32)(value >> 16), regs + (page << 8) + reg); - writew_be((u16)value, regs + (page << 8) + reg + 4); + if (reg % 4) { + u32 hi = (u32)(value >> 16); + u16 lo = (u16)value; + + b53_mmap_write16(dev, page, reg, lo); + b53_mmap_write32(dev, page, reg + 2, hi); } else { - writel((u32)value, regs + (page << 8) + reg); - writew((u16)(value >> 32), regs + (page << 8) + reg + 4); + u16 hi = (u16)(value >> 32); + u32 lo = (u32)value; + + b53_mmap_write32(dev, page, reg, lo); + b53_mmap_write16(dev, page, reg + 4, hi); } return 0; @@ -166,18 +170,16 @@ static int b53_mmap_write48(struct b53_device *dev, u8 page, u8 reg, static int b53_mmap_write64(struct b53_device *dev, u8 page, u8 reg, u64 value) { - u8 __iomem *regs = dev->priv; + u32 hi, lo; + + hi = (u32)(value >> 32); + lo = (u32)value; if (WARN_ON(reg % 4)) return -EINVAL; - if (dev->pdata && dev->pdata->big_endian) { - writel_be((u32)(value >> 32), regs + (page << 8) + reg); - writel_be((u32)value, regs + (page << 8) + reg + 4); - } else { - writel((u32)value, regs + (page << 8) + reg); - writel((u32)(value >> 32), regs + (page << 8) + reg + 4); - } + b53_mmap_write32(dev, page, reg, lo); + b53_mmap_write32(dev, page, reg + 4, hi); return 0; } |