+/*
+ * 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)
+{
+ /* Accessing device 31 crashes the GT-64240. */
+ if (dev < 5)
+ return 0;
+ return -1;
+}
+
+/*
+ * galileo_pcibios_(read/write)_config_(dword/word/byte) -
+ *
+ * reads/write a dword/word/byte register from the configuration space
+ * of a device.
+ *
+ * Note that bus 0 and bus 1 are local, and we assume all other busses are
+ * bridged from bus 1. This is a safe assumption, since any other
+ * configuration will require major modifications to the CP7000G
+ *
+ * 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(int bus, int devfn,
+ int offset, u32 * val)
+{
+ int dev, func;
+ uint32_t address_reg, data_reg;
+ uint32_t address;
+
+ dev = PCI_SLOT(devfn);
+ func = PCI_FUNC(devfn);
+
+ /* verify the range */
+ if (pci_range_ck(bus, dev))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* select the GT-64240 registers to communicate with the PCI bus */
+ if (bus == 0) {
+ address_reg = PCI_0CONFIGURATION_ADDRESS;
+ data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER;
+ GT_WRITE(PCI_0ERROR_CAUSE, ~MASTER_ABORT_BIT);
+ } else {
+ address_reg = PCI_1CONFIGURATION_ADDRESS;
+ data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER;
+ GT_WRITE(PCI_1ERROR_CAUSE, ~MASTER_ABORT_BIT);
+ if (bus == 1)
+ bus = 0;
+ }
+
+ address = (bus << 16) | (dev << 11) | (func << 8) |
+ (offset & 0xfc) | 0x80000000;
+
+ /* start the configuration cycle */
+ GT_WRITE(address_reg, address);
+
+ /* read the data */
+ GT_READ(data_reg, val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int galileo_pcibios_read_config_word(int bus, int devfn,
+ int offset, u16 * val)
+{
+ int dev, func;
+ uint32_t address_reg, data_reg;
+ uint32_t address;
+
+ dev = PCI_SLOT(devfn);
+ func = PCI_FUNC(devfn);
+
+ /* verify the range */
+ if (pci_range_ck(bus, dev))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* select the GT-64240 registers to communicate with the PCI bus */
+ if (bus == 0) {
+ address_reg = PCI_0CONFIGURATION_ADDRESS;
+ data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER;
+ GT_WRITE(PCI_0ERROR_CAUSE, ~MASTER_ABORT_BIT);
+ } else {
+ address_reg = PCI_1CONFIGURATION_ADDRESS;
+ data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER;
+ GT_WRITE(PCI_1ERROR_CAUSE, ~MASTER_ABORT_BIT);
+ if (bus == 1)
+ bus = 0;
+ }
+
+ address = (bus << 16) | (dev << 11) | (func << 8) |
+ (offset & 0xfc) | 0x80000000;
+
+ /* start the configuration cycle */
+ GT_WRITE(address_reg, address);
+
+ /* read the data */
+ GT_READ_16(data_reg + (offset & 0x3), val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int galileo_pcibios_read_config_byte(int bus, int devfn,
+ int offset, u8 * val)
+{
+ int dev, func;
+ uint32_t address_reg, data_reg;
+ uint32_t address;
+
+ dev = PCI_SLOT(devfn);
+ func = PCI_FUNC(devfn);
+
+ /* verify the range */
+ if (pci_range_ck(bus, dev))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* select the GT-64240 registers to communicate with the PCI bus */
+ if (bus == 0) {
+ address_reg = PCI_0CONFIGURATION_ADDRESS;
+ data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER;
+ } else {
+ address_reg = PCI_1CONFIGURATION_ADDRESS;
+ data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER;
+ if (bus == 1)
+ bus = 0;
+ }
+
+ address = (bus << 16) | (dev << 11) | (func << 8) |
+ (offset & 0xfc) | 0x80000000;
+
+ /* start the configuration cycle */
+ GT_WRITE(address_reg, address);
+
+ /* write the data */
+ GT_READ_8(data_reg + (offset & 0x3), val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int galileo_pcibios_write_config_dword(int bus, int devfn,
+ int offset, u32 val)
+{
+ int dev, func;
+ uint32_t address_reg, data_reg;
+ uint32_t address;
+
+ dev = PCI_SLOT(devfn);
+ func = PCI_FUNC(devfn);
+
+ /* verify the range */
+ if (pci_range_ck(bus, dev))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* select the GT-64240 registers to communicate with the PCI bus */
+ if (bus == 0) {
+ address_reg = PCI_0CONFIGURATION_ADDRESS;
+ data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER;
+ } else {
+ address_reg = PCI_1CONFIGURATION_ADDRESS;
+ data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER;
+ if (bus == 1)
+ bus = 0;
+ }
+
+ address = (bus << 16) | (dev << 11) | (func << 8) |
+ (offset & 0xfc) | 0x80000000;
+
+ /* start the configuration cycle */
+ GT_WRITE(address_reg, address);
+
+ /* write the data */
+ GT_WRITE(data_reg, val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int galileo_pcibios_write_config_word(int bus, int devfn,
+ int offset, u16 val)
+{
+ int dev, func;
+ uint32_t address_reg, data_reg;
+ uint32_t address;
+
+ dev = PCI_SLOT(devfn);
+ func = PCI_FUNC(devfn);
+
+ /* verify the range */
+ if (pci_range_ck(bus, dev))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* select the GT-64240 registers to communicate with the PCI bus */
+ if (bus == 0) {
+ address_reg = PCI_0CONFIGURATION_ADDRESS;
+ data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER;
+ } else {
+ address_reg = PCI_1CONFIGURATION_ADDRESS;
+ data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER;
+ if (bus == 1)
+ bus = 0;
+ }
+
+ address = (bus << 16) | (dev << 11) | (func << 8) |
+ (offset & 0xfc) | 0x80000000;
+
+ /* start the configuration cycle */
+ GT_WRITE(address_reg, address);
+
+ /* write the data */
+ GT_WRITE_16(data_reg + (offset & 0x3), val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int galileo_pcibios_write_config_byte(int bus, int devfn,
+ int offset, u8 val)
+{
+ int dev, func;
+ uint32_t address_reg, data_reg;
+ uint32_t address;
+
+ dev = PCI_SLOT(devfn);
+ func = PCI_FUNC(devfn);
+
+ /* verify the range */
+ if (pci_range_ck(bus, dev))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* select the GT-64240 registers to communicate with the PCI bus */
+ if (bus == 0) {
+ address_reg = PCI_0CONFIGURATION_ADDRESS;
+ data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER;
+ } else {
+ address_reg = PCI_1CONFIGURATION_ADDRESS;
+ data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER;
+ if (bus == 1)
+ bus = 0;
+ }
+
+ address = (bus << 16) | (dev << 11) | (func << 8) |
+ (offset & 0xfc) | 0x80000000;
+
+ /* start the configuration cycle */
+ GT_WRITE(address_reg, address);
+
+ /* write the data */
+ GT_WRITE_8(data_reg + (offset & 0x3), val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops galileo_pci_ops = {
+ .read = pci_read,
+ .write = pci_write