1
0
This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
TP-Link_Archer-XR500v/EN7526G_3.18Kernel_SDK/linux-3.18.21/arch/mips/pci/ops-tc3162u.c
2024-07-22 01:58:46 -03:00

231 lines
5.2 KiB
C
Executable File

#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/addrspace.h>
#include <asm/tc3162/tc3162.h>
uint32 pcie_config_addr = 0x1fb81cf8;
uint32 pcie_config_data = 0x1fb81cfc;
#undef DEBUG
//#define DEBUG
#ifdef DEBUG
#define DBG(f, a...) printk(f, ## a )
#else
#define DBG(f, a...) do {} while (0)
#endif
#define PCIE_ENABLE 0x80000000
spinlock_t pcie_lock = SPIN_LOCK_UNLOCKED;
/* -------------------------------------------------------------------------*/
static inline void write_cfgaddr(u32 addr)
{
__raw_writel(addr,
(void __iomem *)(KSEG1ADDR(pcie_config_addr)));
// __raw_writel((addr | PCI_ENABLE),
// (void __iomem *)(KSEG1ADDR(PCI_CONFIG_ADDR)));
}
static inline void write_cfgdata(u32 data)
{
__raw_writel(data, (void __iomem *)KSEG1ADDR(pcie_config_data));
}
static inline u32 read_cfgdata(void)
{
u32 tmp;
if(isRT63365)
tmp = __raw_readl((void __iomem *)KSEG1ADDR(pcie_config_data));
return __raw_readl((void __iomem *)KSEG1ADDR(pcie_config_data));
}
static inline u32 mkaddr(struct pci_bus *bus, unsigned int devfn, int where)
{
u32 type;
if(isRT63165 || isRT63365 || isMT751020 || isMT7505 || isEN751221){
return (((bus->number & 0xFF) << 24) | ((devfn & 0xFF) << 16) |\
(where & 0xFFC));
}else{
type=(bus->number & 0xFF)?PCIE_ENABLE:0;
return (type | ((bus->number & 0xFF) << 20) | ((devfn & 0xFF) << 12) | \
(where & 0xFFC));
}
}
/* -------------------------------------------------------------------------*/
extern unsigned long int pcie_read_config_word_extend(unsigned char bus,unsigned char dev,unsigned char func,unsigned int reg);
extern int pcie_write_config_word_extend(unsigned char bus, unsigned char dev,unsigned char func, unsigned int reg, unsigned long int value);
static int mt7512_pciebios_read(struct pci_bus *bus, unsigned int devfn, int where,int size, u32 *val)
{
unsigned long flags;
u32 data,addr;
/* spin_lock_irqsave(&pcie_lock, flags);*/
addr = mkaddr(bus,devfn,where);
data = pcie_read_config_word_extend((addr>>24)&0xff,(addr>>19)&0x1f,(addr>>16)&0x7,addr&0xffc);
/* printk("\n pcie_read: bus = %d, dev = %d func = %d, reg = %x, val = %x",(addr>>24)&0xff,(addr>>19)&0x1f,(addr>>16)&0x7,addr&0xffc,data); */
switch (size) {
case 1:
if (where & 1)
data >>= 8;
if (where & 2)
data >>= 16;
data &= 0xFF;
break;
case 2:
if (where & 2)
data >>= 16;
data &= 0xFFFF;
break;
}
*val = data;
/* spin_unlock_irqrestore(&pcie_lock, flags);*/
return PCIBIOS_SUCCESSFUL;
}
static int mt7512_pciebios_write(struct pci_bus *bus, unsigned int devfn, int where,int size, u32 val)
{
unsigned long flags;
u32 data,addr;
int s;
addr= mkaddr(bus,devfn,where);
data = pcie_read_config_word_extend((addr>>24)&0xff,(addr>>19)&0x1f,(addr>>16)&0x7,addr&0xffc);
switch (size) {
case 1:
s = ((where & 3) << 3);
data &= ~(0xFF << s);
data |= ((val & 0xFF) << s);
break;
case 2:
s = ((where & 2) << 3);
data &= ~(0xFFFF << s);
data |= ((val & 0xFFFF) << s);
break;
case 4:
data = val;
break;
}
/* printk("\n pcie_write: bus = %d, dev = %d func = %d, reg = %x, val = %x",(addr>>24)&0xff,(addr>>19)&0x1f,(addr>>16)&0x7,addr&0xffc,data);*/
pcie_write_config_word_extend((addr>>24)&0xff,(addr>>19)&0x1f,(addr>>16)&0x7,addr&0xffc,data);
return PCIBIOS_SUCCESSFUL;
}
static int tc3162_pciebios_read(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *val)
{
unsigned long flags;
u32 data;
spin_lock_irqsave(&pcie_lock, flags);
if(isRT63165){
if((devfn & 0xFF) != 0){
*val = 0xffffffff;
spin_unlock_irqrestore(&pcie_lock, flags);
return PCIBIOS_SUCCESSFUL;
}
}
write_cfgaddr(mkaddr(bus,devfn,where));
data = read_cfgdata();
DBG("PCIE: 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:
if (where & 1)
data >>= 8;
if (where & 2)
data >>= 16;
data &= 0xFF;
break;
case 2:
if (where & 2)
data >>= 16;
data &= 0xFFFF;
break;
}
*val = data;
DBG(", 0x%08X returned\n", data);
spin_unlock_irqrestore(&pcie_lock, flags);
return PCIBIOS_SUCCESSFUL;
}
static int tc3162_pciebios_write(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val)
{
unsigned long flags;
u32 data;
int s;
spin_lock_irqsave(&pcie_lock, flags);
write_cfgaddr(mkaddr(bus,devfn,where));
data = read_cfgdata();
DBG("PCIE: cfg_write %02u.%02u.%01u/%02X:%01d,%08x, cfg:0x%08X",
bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn),
where, size, val, data);
switch (size) {
case 1:
s = ((where & 3) << 3);
data &= ~(0xFF << s);
data |= ((val & 0xFF) << s);
break;
case 2:
//s = ((where & 2) << 4);
s = ((where & 2) << 3);//krammer try
data &= ~(0xFFFF << s);
data |= ((val & 0xFFFF) << s);
break;
case 4:
data = val;
break;
}
write_cfgdata(data);
DBG(", 0x%08X written\n", data);
spin_unlock_irqrestore(&pcie_lock, flags);
return PCIBIOS_SUCCESSFUL;
}
struct pci_ops mt7512_pcie_ops = {
.read = mt7512_pciebios_read,
.write = mt7512_pciebios_write
};
struct pci_ops tc3162_pcie_ops = {
.read = tc3162_pciebios_read,
.write = tc3162_pciebios_write
};