/* * RTL8196C PCIE Host Controller Glue Driver * Author: ghhuang@realtek.com.tw * * Notes: * - Two host controllers available. * - Each host direcly connects to one device * - Supports PCI devices through PCIE-to-PCI bridges * - If no PCI devices are connected to RC. Timeout monitor shall be * enabled to prevent bus hanging. */ #include #include #include #include #include //#include #include "bspchip.h" #define PCI_8BIT_ACCESS 1 #define PCI_16BIT_ACCESS 2 #define PCI_32BIT_ACCESS 4 #define PCI_ACCESS_READ 8 #define PCI_ACCESS_WRITE 16 #define MAX_NUM_DEV 4 #define DEBUG_PRINTK 0 #define CLK_MANAGE 0xb8000010 #define SYS_PCIE_PHY0 (0xb8000000 +0x50) #define SYS_PCIE_PHY1 (0xb8000000 +0x54) #define PCIE_PHY0 0xb8b01008 #define PCIE_PHY1 0xb8b21008 #define MAX_PAYLOAD_SIZE_128B 0 static int pci0_bus_number = 0xff; static struct resource rtl8196b_pci0_io_resource = { .name = "RTL8196C PCI0 IO", .flags = IORESOURCE_IO, .start = PADDR(BSP_PCIE0_D_IO), .end = PADDR(BSP_PCIE0_D_IO + 0x1FFFFF) }; static struct resource rtl8196b_pci0_mem_resource = { .name = "RTL8196C PCI0 MEM", .flags = IORESOURCE_MEM, .start = PADDR(BSP_PCIE0_D_MEM), .end = PADDR(BSP_PCIE0_D_MEM + 0xFFFFFF) }; //HOST PCIE #define PCIE0_RC_EXT_BASE (0xb8b01000) //RC Extended register #define PCIE0_MDIO (PCIE0_RC_EXT_BASE+0x00) //MDIO #define PCIE_MDIO_DATA_OFFSET (16) #define PCIE_MDIO_DATA_MASK (0xffff <>PCIE_MDIO_DATA_OFFSET)&0xffff); } void HostPCIe_SetPhyMdioWrite(unsigned int portnum, unsigned int regaddr, unsigned short val) { unsigned int mdioaddr; mdioaddr=PCIE0_MDIO; REG32(mdioaddr)= ( (regaddr&0x1f)<number; #if DEBUG_PRINTK //printk("File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__); //printk("Bus: %d, Slot: %d, Func: %d, Where: %d, Size: %d\n", bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size); #endif if (bus->number == pci0_bus_number) { /* PCIE host controller */ if (PCI_SLOT(devfn) == 0) { addr = BSP_PCIE0_H_CFG + where; if (rtl8196b_pcibios_config_access(PCI_ACCESS_READ | PCI_32BIT_ACCESS, addr & ~(0x3), &data)) return PCIBIOS_DEVICE_NOT_FOUND; if (size == 1) *val = (data >> ((where & 3) << 3)) & 0xff; else if (size == 2) *val = (data >> ((where & 3) << 3)) & 0xffff; else *val = data; } else return PCIBIOS_DEVICE_NOT_FOUND; } else if (bus->number == (pci0_bus_number + 1)) { /* PCIE devices directly connected */ if (PCI_SLOT(devfn) == 0) { addr = BSP_PCIE0_D_CFG0 + (PCI_FUNC(devfn) << 12) + where; if (rtl8196b_pcibios_config_access(PCI_ACCESS_READ | size, addr, val)) return PCIBIOS_DEVICE_NOT_FOUND; } else return PCIBIOS_DEVICE_NOT_FOUND; } else { /* Devices connected through bridge */ if (PCI_SLOT(devfn) < MAX_NUM_DEV) { WRITE_MEM32(BSP_PCIE0_H_IPCFG, ((bus->number) << 8) | (PCI_SLOT(devfn) << 3) | PCI_FUNC(devfn)); addr = BSP_PCIE0_D_CFG1 + where; if (rtl8196b_pcibios_config_access(PCI_ACCESS_READ | size, addr, val)) return PCIBIOS_DEVICE_NOT_FOUND; } else return PCIBIOS_DEVICE_NOT_FOUND; } #if DEBUG_PRINTK //printk("File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__); //printk("Read Value: 0x%08X\n", *val); #endif return PCIBIOS_SUCCESSFUL; } //======================================================================================== static int rtl8196b_pcibios0_write(struct pci_bus *bus, unsigned int devfn, int where, int size, unsigned int val) { unsigned int data = 0; unsigned int addr = 0; static int pci0_bus_number = 0xff; if (pci0_bus_number == 0xff) pci0_bus_number = bus->number; #if DEBUG_PRINTK //printk("File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__); //printk("Bus: %d, Slot: %d, Func: %d, Where: %d, Size: %d\n", bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size); #endif if (bus->number == pci0_bus_number) { /* PCIE host controller */ if (PCI_SLOT(devfn) == 0) { addr = BSP_PCIE0_H_CFG + where; if (rtl8196b_pcibios_config_access(PCI_ACCESS_READ | PCI_32BIT_ACCESS, addr & ~(0x3), &data)) return PCIBIOS_DEVICE_NOT_FOUND; if (size == 1) data = (data & ~(0xff << ((where & 3) << 3))) | (val << ((where & 3) << 3)); else if (size == 2) data = (data & ~(0xffff << ((where & 3) << 3))) | (val << ((where & 3) << 3)); else data = val; if (rtl8196b_pcibios_config_access(PCI_ACCESS_WRITE | PCI_32BIT_ACCESS, addr & ~(0x3), &data)) return PCIBIOS_DEVICE_NOT_FOUND; } else return PCIBIOS_DEVICE_NOT_FOUND; } else if (bus->number == (pci0_bus_number + 1)) { /* PCIE devices directly connected */ if (PCI_SLOT(devfn) == 0) { addr = BSP_PCIE0_D_CFG0 + (PCI_FUNC(devfn) << 12) + where; if (rtl8196b_pcibios_config_access(PCI_ACCESS_WRITE | size, addr, &val)) return PCIBIOS_DEVICE_NOT_FOUND; } else return PCIBIOS_DEVICE_NOT_FOUND; } else { /* Devices connected through bridge */ if (PCI_SLOT(devfn) < MAX_NUM_DEV) { WRITE_MEM32(BSP_PCIE0_H_IPCFG, ((bus->number) << 8) | (PCI_SLOT(devfn) << 3) | PCI_FUNC(devfn)); addr = BSP_PCIE0_D_CFG1 + where; if (rtl8196b_pcibios_config_access(PCI_ACCESS_WRITE | size, addr, &val)) return PCIBIOS_DEVICE_NOT_FOUND; } else return PCIBIOS_DEVICE_NOT_FOUND; } return PCIBIOS_SUCCESSFUL; } //======================================================================================== //======================================================================================== struct pci_ops rtl8196b_pci0_ops = { .read = rtl8196b_pcibios0_read, .write = rtl8196b_pcibios0_write }; static struct pci_controller rtl8196b_pci0_controller = { .pci_ops = &rtl8196b_pci0_ops, .mem_resource = &rtl8196b_pci0_mem_resource, .io_resource = &rtl8196b_pci0_io_resource, }; //======================================================================================== int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { #if DEBUG_PRINTK printk("File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__); printk("**Slot: %d\n", slot); printk("**Pin: %d\n", pin); printk("**Dev->BUS->Number: %d\n", dev->bus->number); #endif return BSP_PCIE_IRQ; } //======================================================================================== /* Do platform specific device initialization at pci_enable_device() time */ int pcibios_plat_dev_init(struct pci_dev *dev) { #if DEBUG_PRINTK printk("File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__); #endif return 0; } static __init int bsp_pcie_init(void) { int result=0; printk("<<<<>>>>\n"); mdelay(1); result=PCIE_reset_procedure(0, 0, 1); if (result) register_pci_controller(&rtl8196b_pci0_controller); else REG32(CLK_MANAGE) &= (~(1<<11)); //disable active_pcie0 return 0; } arch_initcall(bsp_pcie_init);