summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorflorian <florian@3c298f89-4303-0410-b956-a3cf2f4a3e73>2007-06-03 15:25:05 +0000
committerflorian <florian@3c298f89-4303-0410-b956-a3cf2f4a3e73>2007-06-03 15:25:05 +0000
commit558115a6413a2d048afd55194da2a2443a9d2c48 (patch)
treecbb34911c5a57ed1412c768e497736d10e95eae1
parentb66b4775513d1535de6ef02c58fdb6c212b5bb40 (diff)
Fix endianness issues with adm5120eb, thanks to Gabor !
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@7479 3c298f89-4303-0410-b956-a3cf2f4a3e73
-rw-r--r--package/acx/patches/003-endianness-fixes.patch112
-rw-r--r--target/linux/adm5120-2.6/files/arch/mips/pci/ops-adm5120.c93
2 files changed, 184 insertions, 21 deletions
diff --git a/package/acx/patches/003-endianness-fixes.patch b/package/acx/patches/003-endianness-fixes.patch
new file mode 100644
index 000000000..05f6acf98
--- /dev/null
+++ b/package/acx/patches/003-endianness-fixes.patch
@@ -0,0 +1,112 @@
+diff -Nur -x '*.o' -x '*.ko' acx-20070101/pci.c acx-20070101.big/pci.c
+--- acx-20070101/pci.c 2007-06-02 17:29:53.000000000 +0200
++++ acx-20070101.big/pci.c 2007-06-02 17:23:37.000000000 +0200
+@@ -123,6 +123,11 @@
+ ** Register access
+ */
+
++#define acx_readl(v) le32_to_cpu(readl((v)))
++#define acx_readw(v) le16_to_cpu(readw((v)))
++#define acx_writew(v,r) writew(le16_to_cpu((v)), r)
++#define acx_writel(v,r) writel(le32_to_cpu((v)), r)
++
+ /* Pick one */
+ /* #define INLINE_IO static */
+ #define INLINE_IO static inline
+@@ -131,17 +136,17 @@
+ read_reg32(acx_device_t *adev, unsigned int offset)
+ {
+ #if ACX_IO_WIDTH == 32
+- return readl((u8 *)adev->iobase + adev->io[offset]);
++ return acx_readl((u8 *)adev->iobase + adev->io[offset]);
+ #else
+- return readw((u8 *)adev->iobase + adev->io[offset])
+- + (readw((u8 *)adev->iobase + adev->io[offset] + 2) << 16);
++ return acx_readw((u8 *)adev->iobase + adev->io[offset])
++ + (acx_readw((u8 *)adev->iobase + adev->io[offset] + 2) << 16);
+ #endif
+ }
+
+ INLINE_IO u16
+ read_reg16(acx_device_t *adev, unsigned int offset)
+ {
+- return readw((u8 *)adev->iobase + adev->io[offset]);
++ return acx_readw((u8 *)adev->iobase + adev->io[offset]);
+ }
+
+ INLINE_IO u8
+@@ -154,17 +159,17 @@
+ write_reg32(acx_device_t *adev, unsigned int offset, u32 val)
+ {
+ #if ACX_IO_WIDTH == 32
+- writel(val, (u8 *)adev->iobase + adev->io[offset]);
++ acx_writel(val, (u8 *)adev->iobase + adev->io[offset]);
+ #else
+- writew(val & 0xffff, (u8 *)adev->iobase + adev->io[offset]);
+- writew(val >> 16, (u8 *)adev->iobase + adev->io[offset] + 2);
++ acx_writew(val & 0xffff, (u8 *)adev->iobase + adev->io[offset]);
++ acx_writew(val >> 16, (u8 *)adev->iobase + adev->io[offset] + 2);
+ #endif
+ }
+
+ INLINE_IO void
+ write_reg16(acx_device_t *adev, unsigned int offset, u16 val)
+ {
+- writew(val, (u8 *)adev->iobase + adev->io[offset]);
++ acx_writew(val, (u8 *)adev->iobase + adev->io[offset]);
+ }
+
+ INLINE_IO void
+@@ -192,7 +197,7 @@
+ {
+ /* fast version (accesses the first register, IO_ACX_SOFT_RESET,
+ * which should be safe): */
+- return readl(adev->iobase) != 0xffffffff;
++ return acx_readl(adev->iobase) != 0xffffffff;
+ }
+
+
+@@ -835,7 +840,7 @@
+ static inline void
+ acxpci_write_cmd_type_status(acx_device_t *adev, u16 type, u16 status)
+ {
+- writel(type | (status << 16), adev->cmd_area);
++ acx_writel(type | (status << 16), adev->cmd_area);
+ write_flush(adev);
+ }
+
+@@ -848,7 +853,7 @@
+ {
+ u32 cmd_type, cmd_status;
+
+- cmd_type = readl(adev->cmd_area);
++ cmd_type = acx_readl(adev->cmd_area);
+ cmd_status = (cmd_type >> 16);
+ cmd_type = (u16)cmd_type;
+
+@@ -2415,12 +2420,12 @@
+ #endif
+ u32 info_type, info_status;
+
+- info_type = readl(adev->info_area);
++ info_type = acx_readl(adev->info_area);
+ info_status = (info_type >> 16);
+ info_type = (u16)info_type;
+
+ /* inform fw that we have read this info message */
+- writel(info_type | 0x00010000, adev->info_area);
++ acx_writel(info_type | 0x00010000, adev->info_area);
+ write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_INFOACK);
+ write_flush(adev);
+
+@@ -4209,8 +4214,8 @@
+ #define ENDIANNESS_STRING "running on a BIG-ENDIAN CPU\n"
+ #endif
+ log(L_INIT,
+- ENDIANNESS_STRING
+- "PCI module " ACX_RELEASE " initialized, "
++ "acx: " ENDIANNESS_STRING
++ "acx: PCI module " ACX_RELEASE " initialized, "
+ "waiting for cards to probe...\n"
+ );
+
diff --git a/target/linux/adm5120-2.6/files/arch/mips/pci/ops-adm5120.c b/target/linux/adm5120-2.6/files/arch/mips/pci/ops-adm5120.c
index ff768033e..f7e4e6686 100644
--- a/target/linux/adm5120-2.6/files/arch/mips/pci/ops-adm5120.c
+++ b/target/linux/adm5120-2.6/files/arch/mips/pci/ops-adm5120.c
@@ -26,54 +26,105 @@
*/
#include <linux/types.h>
-#include <linux/pci.h>
#include <linux/kernel.h>
-#include <linux/init.h>
+#include <linux/pci.h>
#include <asm/mach-adm5120/adm5120_defs.h>
-volatile u32* pci_config_address_reg = (volatile u32*)KSEG1ADDR(ADM5120_PCICFG_ADDR);
-volatile u32* pci_config_data_reg = (volatile u32*)KSEG1ADDR(ADM5120_PCICFG_DATA);
+#define DEBUG 0
+#if DEBUG
+#define DBG(f, ...) printk(f, ## __VA_ARGS__ )
+#else
+#define DBG(f, ...)
+#endif
#define PCI_ENABLE 0x80000000
+static inline void write_cfgaddr(u32 addr)
+{
+ *(volatile u32*)KSEG1ADDR(ADM5120_PCICFG_ADDR) = (addr | PCI_ENABLE);
+}
+
+static inline void write_cfgdata(u32 data)
+{
+ *(volatile u32*)KSEG1ADDR(ADM5120_PCICFG_DATA) = data;
+
+}
+
+static inline u32 read_cfgdata(void)
+{
+ return (*(volatile u32*)KSEG1ADDR(ADM5120_PCICFG_DATA));
+}
+
+static inline u32 mkaddr(struct pci_bus *bus, unsigned int devfn, int where)
+{
+ return (((bus->number & 0xFF) << 16) | ((devfn & 0xFF) << 8) | \
+ (where & 0xFC));
+}
+
static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where,
- int size, uint32_t *val)
+ int size, u32 *val)
{
- *pci_config_address_reg = ((bus->number & 0xff) << 0x10) |
- ((devfn & 0xff) << 0x08) | (where & 0xfc) | PCI_ENABLE;
+ u32 data;
+
+ write_cfgaddr(mkaddr(bus,devfn,where));
+ data = read_cfgdata();
+
+ DBG("PCI: cfg_read %02u.%02u.%01u/%02X:%01d, cfg:0x%08X",
+ bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, data);
+
switch (size) {
case 1:
- *val = ((*pci_config_data_reg)>>((where&3)<<3))&0xff;
+ if (where & 1)
+ data >>= 8;
+ if (where & 2)
+ data >>= 16;
+ data &= 0xFF;
break;
case 2:
- *val = ((*pci_config_data_reg)>>((where&3)<<3))&0xffff;
- break;
- default:
- *val = (*pci_config_data_reg);
+ if (where & 2)
+ data >>= 16;
+ data &= 0xFFFF;
break;
}
+
+ *val = data;
+ DBG(", 0x%08X returned\n", data);
+
return PCIBIOS_SUCCESSFUL;
}
static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where,
- int size, uint32_t val)
+ int size, u32 val)
{
- *pci_config_address_reg = ((bus->number & 0xff) << 0x10) |
- ((devfn & 0xff) << 0x08) | (where & 0xfc) | PCI_ENABLE;
+ u32 data;
+ int s;
+
+ write_cfgaddr(mkaddr(bus,devfn,where));
+ data = read_cfgdata();
+
+ DBG("PCI: cfg_write %02u.%02u.%01u/%02X:%01d, cfg:0x%08X",
+ bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, data);
+
switch (size) {
case 1:
- *(volatile u8 *)(((int)pci_config_data_reg) +
- (where & 3)) = val;
+ s = ((where & 3) << 3);
+ data &= ~(0xFF << s);
+ data |= ((val & 0xFF) << s);
break;
case 2:
- *(volatile u16 *)(((int)pci_config_data_reg) +
- (where & 2)) = (val);
+ s = ((where & 2) << 4);
+ data &= ~(0xFFFF << s);
+ data |= ((val & 0xFFFF) << s);
+ break;
+ case 4:
+ data = val;
break;
- default:
- *pci_config_data_reg = (val);
}
+ write_cfgdata(data);
+ DBG(", 0x%08X written\n", data);
+
return PCIBIOS_SUCCESSFUL;
}