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>

SVN-Revision: 44568
This commit is contained in:
Jonas Gorski 2015-02-27 17:40:17 +00:00
parent 8ff23c60e2
commit d75cd5be37

View 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;
}