1 /* 2 * Support for indirect PCI bridges. 3 * 4 * Copyright (C) 1998 Gabriel Paubert. 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <common.h> 10 11 #if !defined(__I386__) 12 13 #include <asm/processor.h> 14 #include <asm/io.h> 15 #include <pci.h> 16 17 #define cfg_read(val, addr, type, op) *val = op((type)(addr)) 18 #define cfg_write(val, addr, type, op) op((type *)(addr), (val)) 19 20 #if defined(CONFIG_E500) || defined(CONFIG_MPC86xx) 21 #define INDIRECT_PCI_OP(rw, size, type, op, mask) \ 22 static int \ 23 indirect_##rw##_config_##size(struct pci_controller *hose, \ 24 pci_dev_t dev, int offset, type val) \ 25 { \ 26 u32 b, d,f; \ 27 b = PCI_BUS(dev); d = PCI_DEV(dev); f = PCI_FUNC(dev); \ 28 b = b - hose->first_busno; \ 29 dev = PCI_BDF(b, d, f); \ 30 *(hose->cfg_addr) = dev | (offset & 0xfc) | ((offset & 0xf00) << 16) | 0x80000000; \ 31 sync(); \ 32 cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \ 33 return 0; \ 34 } 35 #else 36 #define INDIRECT_PCI_OP(rw, size, type, op, mask) \ 37 static int \ 38 indirect_##rw##_config_##size(struct pci_controller *hose, \ 39 pci_dev_t dev, int offset, type val) \ 40 { \ 41 u32 b, d,f; \ 42 b = PCI_BUS(dev); d = PCI_DEV(dev); f = PCI_FUNC(dev); \ 43 b = b - hose->first_busno; \ 44 dev = PCI_BDF(b, d, f); \ 45 out_le32(hose->cfg_addr, dev | (offset & 0xfc) | 0x80000000); \ 46 cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \ 47 return 0; \ 48 } 49 #endif 50 51 INDIRECT_PCI_OP(read, byte, u8 *, in_8, 3) 52 INDIRECT_PCI_OP(read, word, u16 *, in_le16, 2) 53 INDIRECT_PCI_OP(read, dword, u32 *, in_le32, 0) 54 INDIRECT_PCI_OP(write, byte, u8, out_8, 3) 55 INDIRECT_PCI_OP(write, word, u16, out_le16, 2) 56 INDIRECT_PCI_OP(write, dword, u32, out_le32, 0) 57 58 void pci_setup_indirect(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) 59 { 60 pci_set_ops(hose, 61 indirect_read_config_byte, 62 indirect_read_config_word, 63 indirect_read_config_dword, 64 indirect_write_config_byte, 65 indirect_write_config_word, 66 indirect_write_config_dword); 67 68 hose->cfg_addr = (unsigned int *) cfg_addr; 69 hose->cfg_data = (unsigned char *) cfg_data; 70 } 71 72 #endif /* !__I386__ */ 73