📄 pci_bios.c
字号:
unsigned int base; GT_READ(GT_PCI1M1LD_OFS, &base); base = base << 21; return base;}/* * pci1GetMemory1Size - Return PCI1 Memory 1 Bar Size. * Inputs: N/A * Returns: PCI1 Memory 1 Bar Size. */static unsigned int pci1GetMemory1Size(void){ unsigned int top, base, size; GT_READ(GT_PCI1M1LD_OFS, &base); base = base << 21; GT_READ(GT_PCI1M1HD_OFS, &top); top = (top << 21); size = ((top - base) & 0xfffffff); size = size | 0x1fffff; return (size + 1);}/* * pci_range_ck - * * Check if the pci device that are trying to access does really exists * on the evaluation board. * * Inputs : * bus - bus number (0 for PCI 0 ; 1 for PCI 1) * dev - number of device on the specific pci bus * * Outpus : * 0 - if OK , 1 - if failure */static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev){ //DBG(KERN_INFO "p_r_c %d %d\n",bus,dev); if (((bus == 0) || (bus == 1)) && (dev >= 6) && (dev <= 8)) return 0; // Bus/Device Number OK return -1; // Bus/Device Number not OK }/* * pciXReadConfigReg - Read from a PCI configuration register * - Make sure the GT is configured as a master before * reading from another device on the PCI. * - The function takes care of Big/Little endian conversion. * INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI * spec) * pciDevNum: The device number needs to be addressed. * RETURNS: data , if the data == 0xffffffff check the master abort bit in the * cause register to make sure the data is valid * * Configuration Address 0xCF8: * * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number * |congif|Reserved| Bus |Device|Function|Register|00| * |Enable| |Number|Number| Number | Number | | <=field Name * */static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device){ unsigned int DataForRegCf8; unsigned int data; DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | (PCI_FUNC(device->devfn) << 8) | (offset & ~0x3)) | 0x80000000; GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); /* The casual observer might wonder why the READ is duplicated here, rather than immediately following the WRITE, and just have the swap in the "if". That's because there is a latency problem with trying to read immediately after setting up the address register. The "if" check gives enough time for the address to stabilize, so the READ can work. */ if (PCI_SLOT(device->devfn) == SELF) { /* This board */ GT_READ(GT_PCI0_CFGDATA_OFS, &data); return data; } else { /* The PCI is working in LE Mode so swap the Data. */ GT_READ(GT_PCI0_CFGDATA_OFS, &data); return cpu_to_le32(data); }}static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device){ unsigned int DataForRegCf8; unsigned int data; DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | (PCI_FUNC(device->devfn) << 8) | (offset & ~0x3)) | 0x80000000; /* The casual observer might wonder why the READ is duplicated here, rather than immediately following the WRITE, and just have the swap in the "if". That's because there is a latency problem with trying to read immediately after setting up the address register. The "if" check gives enough time for the address to stabilize, so the READ can work. */ if (PCI_SLOT(device->devfn) == SELF) { /* This board */ /* when configurating our own PCI 1 L-unit the access is through the PCI 0 interface with reg number = reg number + 0x80 */ DataForRegCf8 |= 0x80; GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); } else { /* The PCI is working in LE Mode so swap the Data. */ GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8); } if (PCI_SLOT(device->devfn) == SELF) { /* This board */ GT_READ(GT_PCI0_CFGDATA_OFS, &data); return data; } else { GT_READ(GT_PCI1_CFGDATA_OFS, &data); return cpu_to_le32(data); }}/* * pciXWriteConfigReg - Write to a PCI configuration register * - Make sure the GT is configured as a master before * writingto another device on the PCI. * - The function takes care of Big/Little endian conversion. * Inputs: unsigned int regOffset: The register offset as it apears in the * GT spec * (or any other PCI device spec) * pciDevNum: The device number needs to be addressed. * * Configuration Address 0xCF8: * * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number * |congif|Reserved| Bus |Device|Function|Register|00| * |Enable| |Number|Number| Number | Number | | <=field Name * */static void pci0WriteConfigReg(unsigned int offset, struct pci_dev *device, unsigned int data){ unsigned int DataForRegCf8; DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | (PCI_FUNC(device->devfn) << 8) | (offset & ~0x3)) | 0x80000000; GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); if (PCI_SLOT(device->devfn) == SELF) { /* This board */ GT_WRITE(GT_PCI0_CFGDATA_OFS, data); } else { /* configuration Transaction over the pci. */ /* The PCI is working in LE Mode so swap the Data. */ GT_WRITE(GT_PCI0_CFGDATA_OFS, le32_to_cpu(data)); }}static void pci1WriteConfigReg(unsigned int offset, struct pci_dev *device, unsigned int data){ unsigned int DataForRegCf8; DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | (PCI_FUNC(device->devfn) << 8) | (offset & ~0x3)) | 0x80000000; /* There is a latency problem with trying to read immediately after setting up the address register. The "if" check gives enough time for the address to stabilize, so the WRITE can work. */ if (PCI_SLOT(device->devfn) == SELF) { /* This board */ /* when configurating our own PCI 1 L-unit the access is through the PCI 0 interface with reg number = reg number + 0x80 */ DataForRegCf8 |= 0x80; GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); } else { /* configuration Transaction over the pci. */ /* The PCI is working in LE Mode so swap the Data. */ GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8); } if (PCI_SLOT(device->devfn) == SELF) { /* This board */ GT_WRITE(GT_PCI0_CFGDATA_OFS, data); } else { /* configuration Transaction over the pci. */ GT_WRITE(GT_PCI1_CFGADDR_OFS, le32_to_cpu(data)); }}/* * galileo_pcibios_(read/write)_config_(dword/word/byte) - * * reads/write a dword/word/byte register from the configuration space * of a device. * * Inputs : * bus - bus number * dev - device number * offset - register offset in the configuration space * val - value to be written / read * * Outputs : * PCIBIOS_SUCCESSFUL when operation was succesfull * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned */static int galileo_pcibios_read_config_dword(struct pci_dev *device, int offset, u32 * val){ int dev, bus; //DBG(KERN_INFO "rcd entry \n",offset,val); bus = device->bus->number; dev = PCI_SLOT(device->devfn); if (pci_range_ck(bus, dev)) { *val = 0xffffffff; return PCIBIOS_DEVICE_NOT_FOUND; } if (offset & 0x3) return PCIBIOS_BAD_REGISTER_NUMBER; if (bus == 0) *val = pci0ReadConfigReg(offset, device);// if (bus == 1) *val = pci1ReadConfigReg (offset,device); DBG(KERN_INFO "rr: rcd dev %d offset %x %x\n", dev, offset, *val); /* * This is so that the upper PCI layer will get the correct return * value if we're not attached to anything. */ if ((offset == 0) && (*val == 0xffffffff)) { return PCIBIOS_DEVICE_NOT_FOUND; } return PCIBIOS_SUCCESSFUL;}static int galileo_pcibios_read_config_word(struct pci_dev *device, int offset, u16 * val){ int dev, bus; bus = device->bus->number; dev = PCI_SLOT(device->devfn); if (pci_range_ck(bus, dev)) { *val = 0xffff; return PCIBIOS_DEVICE_NOT_FOUND; } if (offset & 0x1) return PCIBIOS_BAD_REGISTER_NUMBER; if (bus == 0) *val = (unsigned short) (pci0ReadConfigReg(offset, device) >> ((offset & ~0x3) * 8));// if (bus == 1) *val = (unsigned short) (pci1ReadConfigReg(offset,device) >> ((offset & ~0x3) * 8)); DBG(KERN_INFO "rr: rcw dev %d offset %x %x\n", dev, offset, *val); return PCIBIOS_SUCCESSFUL;}static int galileo_pcibios_read_config_byte(struct pci_dev *device, int offset, u8 * val){ int dev, bus; bus = device->bus->number; dev = PCI_SLOT(device->devfn); if (pci_range_ck(bus, dev)) { *val = 0xff; return PCIBIOS_DEVICE_NOT_FOUND; } if (bus == 0) *val = (unsigned char) (pci0ReadConfigReg(offset, device) >> ((offset & ~0x3) * 8));// if (bus == 1) *val = (unsigned char) (pci1ReadConfigReg(offset,device) >> ((offset & ~0x3) * 8)); DBG(KERN_INFO "rr: rcb dev %d offset %x %x\n", dev, offset, *val); /* This is so that the upper PCI layer will get the correct return value if we're not attached to anything. */ if ((offset == 0xe) && (*val == 0xff)) { u32 MasterAbort; GT_READ(GT_INTRCAUSE_OFS, &MasterAbort); if (MasterAbort & 0x40000) { DBG(KERN_INFO "PCI Master Abort, ICR %x\n", MasterAbort); GT_WRITE(GT_INTRCAUSE_OFS, (MasterAbort & 0xfffbffff)); return PCIBIOS_DEVICE_NOT_FOUND; } } return PCIBIOS_SUCCESSFUL;}static int galileo_pcibios_write_config_dword(struct pci_dev *device, int offset, u32 val){ int dev, bus; bus = device->bus->number; dev = PCI_SLOT(device->devfn); if (pci_range_ck(bus, dev)) return PCIBIOS_DEVICE_NOT_FOUND; if (offset & 0x3) return PCIBIOS_BAD_REGISTER_NUMBER; if (bus == 0) pci0WriteConfigReg(offset, device, val);// if (bus == 1) pci1WriteConfigReg (offset,device,val); DBG(KERN_INFO "rr: wcd dev %d, offset %x, val %x\n", dev, offset, val); return PCIBIOS_SUCCESSFUL;}static int galileo_pcibios_write_config_word(struct pci_dev *device, int offset, u16 val){ int dev, bus; unsigned long tmp; bus = device->bus->number; dev = PCI_SLOT(device->devfn); if (pci_range_ck(bus, dev)) return PCIBIOS_DEVICE_NOT_FOUND; if (offset & 0x1) return PCIBIOS_BAD_REGISTER_NUMBER; if (bus == 0) tmp = pci0ReadConfigReg(offset, device);// if (bus == 1) tmp = pci1ReadConfigReg (offset,device); if ((offset % 4) == 0) tmp = (tmp & 0xffff0000) | (val & 0xffff); if ((offset % 4) == 2) tmp = (tmp & 0x0000ffff) | ((val & 0xffff) << 16); if (bus == 0) pci0WriteConfigReg(offset, device, tmp);// if (bus == 1) pci1WriteConfigReg (offset,device,tmp); DBG(KERN_INFO "rr: wcw dev %d, offset %x, val %x\n", dev, offset, val); return PCIBIOS_SUCCESSFUL;}static int galileo_pcibios_write_config_byte(struct pci_dev *device, int offset, u8 val){ int dev, bus; unsigned long tmp; bus = device->bus->number; dev = PCI_SLOT(device->devfn); if (pci_range_ck(bus, dev)) return PCIBIOS_DEVICE_NOT_FOUND; if (bus == 0) tmp = pci0ReadConfigReg(offset, device);// if (bus == 1) tmp = pci1ReadConfigReg (offset,device); if ((offset % 4) == 0) tmp = (tmp & 0xffffff00) | (val & 0xff); if ((offset % 4) == 1) tmp = (tmp & 0xffff00ff) | ((val & 0xff) << 8); if ((offset % 4) == 2) tmp = (tmp & 0xff00ffff) | ((val & 0xff) << 16); if ((offset % 4) == 3) tmp = (tmp & 0x00ffffff) | ((val & 0xff) << 24); if (bus == 0) pci0WriteConfigReg(offset, device, tmp);// if (bus == 1) pci1WriteConfigReg (offset,device,tmp); DBG(KERN_INFO "rr: wcb dev %d, offset %x, val %x\n", dev, offset, val); return PCIBIOS_SUCCESSFUL;}static void galileo_pcibios_set_master(struct pci_dev *dev){ u16 cmd; DBG(KERN_INFO "rr: galileo_pcibios_set_master\n"); galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd); cmd |= PCI_COMMAND_MASTER; galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd); DBG("PCI: Enabling device %s (%04x)\n", dev->slot_name, cmd);}/* Externally-expected functions. Do not change function names */int pcibios_enable_resources(struct pci_dev *dev){ u16 cmd, old_cmd; u16 tmp; u8 tmp1; int idx; struct resource *r; DBG(KERN_INFO "rr: pcibios_enable_resources\n"); galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd); old_cmd = cmd; for (idx = 0; idx < 6; idx++) { r = &dev->resource[idx];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -