b53: fix mmap register read/writes > 32 bit
authorJonas Gorski <jogo@openwrt.org>
Fri, 27 Feb 2015 17:40:17 +0000 (17:40 +0000)
committerJonas Gorski <jogo@openwrt.org>
Fri, 27 Feb 2015 17:40:17 +0000 (17:40 +0000)
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>
SVN-Revision: 44568

target/linux/generic/files/drivers/net/phy/b53/b53_mmap.c

index 272360f6deedac41740ed938786725e1d543dfbb..b8681660ccaeb3aa88ba02157cee9bc051b9119b 100644 (file)
@@ -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;
 }