1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Xilinx AXI Bridge for PCI Express Driver 4 * 5 * Copyright (C) 2016 Imagination Technologies 6 */ 7 8 #include <common.h> 9 #include <dm.h> 10 #include <pci.h> 11 12 #include <asm/io.h> 13 14 /** 15 * struct xilinx_pcie - Xilinx PCIe controller state 16 * @cfg_base: The base address of memory mapped configuration space 17 */ 18 struct xilinx_pcie { 19 void *cfg_base; 20 }; 21 22 /* Register definitions */ 23 #define XILINX_PCIE_REG_PSCR 0x144 24 #define XILINX_PCIE_REG_PSCR_LNKUP BIT(11) 25 26 /** 27 * pcie_xilinx_link_up() - Check whether the PCIe link is up 28 * @pcie: Pointer to the PCI controller state 29 * 30 * Checks whether the PCIe link for the given device is up or down. 31 * 32 * Return: true if the link is up, else false 33 */ 34 static bool pcie_xilinx_link_up(struct xilinx_pcie *pcie) 35 { 36 uint32_t pscr = __raw_readl(pcie->cfg_base + XILINX_PCIE_REG_PSCR); 37 38 return pscr & XILINX_PCIE_REG_PSCR_LNKUP; 39 } 40 41 /** 42 * pcie_xilinx_config_address() - Calculate the address of a config access 43 * @udev: Pointer to the PCI bus 44 * @bdf: Identifies the PCIe device to access 45 * @offset: The offset into the device's configuration space 46 * @paddress: Pointer to the pointer to write the calculates address to 47 * 48 * Calculates the address that should be accessed to perform a PCIe 49 * configuration space access for a given device identified by the PCIe 50 * controller device @pcie and the bus, device & function numbers in @bdf. If 51 * access to the device is not valid then the function will return an error 52 * code. Otherwise the address to access will be written to the pointer pointed 53 * to by @paddress. 54 * 55 * Return: 0 on success, else -ENODEV 56 */ 57 static int pcie_xilinx_config_address(struct udevice *udev, pci_dev_t bdf, 58 uint offset, void **paddress) 59 { 60 struct xilinx_pcie *pcie = dev_get_priv(udev); 61 unsigned int bus = PCI_BUS(bdf); 62 unsigned int dev = PCI_DEV(bdf); 63 unsigned int func = PCI_FUNC(bdf); 64 void *addr; 65 66 if ((bus > 0) && !pcie_xilinx_link_up(pcie)) 67 return -ENODEV; 68 69 /* 70 * Busses 0 (host-PCIe bridge) & 1 (its immediate child) are 71 * limited to a single device each. 72 */ 73 if ((bus < 2) && (dev > 0)) 74 return -ENODEV; 75 76 addr = pcie->cfg_base; 77 addr += bus << 20; 78 addr += dev << 15; 79 addr += func << 12; 80 addr += offset; 81 *paddress = addr; 82 83 return 0; 84 } 85 86 /** 87 * pcie_xilinx_read_config() - Read from configuration space 88 * @bus: Pointer to the PCI bus 89 * @bdf: Identifies the PCIe device to access 90 * @offset: The offset into the device's configuration space 91 * @valuep: A pointer at which to store the read value 92 * @size: Indicates the size of access to perform 93 * 94 * Read a value of size @size from offset @offset within the configuration 95 * space of the device identified by the bus, device & function numbers in @bdf 96 * on the PCI bus @bus. 97 * 98 * Return: 0 on success, else -ENODEV or -EINVAL 99 */ 100 static int pcie_xilinx_read_config(struct udevice *bus, pci_dev_t bdf, 101 uint offset, ulong *valuep, 102 enum pci_size_t size) 103 { 104 return pci_generic_mmap_read_config(bus, pcie_xilinx_config_address, 105 bdf, offset, valuep, size); 106 } 107 108 /** 109 * pcie_xilinx_write_config() - Write to configuration space 110 * @bus: Pointer to the PCI bus 111 * @bdf: Identifies the PCIe device to access 112 * @offset: The offset into the device's configuration space 113 * @value: The value to write 114 * @size: Indicates the size of access to perform 115 * 116 * Write the value @value of size @size from offset @offset within the 117 * configuration space of the device identified by the bus, device & function 118 * numbers in @bdf on the PCI bus @bus. 119 * 120 * Return: 0 on success, else -ENODEV or -EINVAL 121 */ 122 static int pcie_xilinx_write_config(struct udevice *bus, pci_dev_t bdf, 123 uint offset, ulong value, 124 enum pci_size_t size) 125 { 126 return pci_generic_mmap_write_config(bus, pcie_xilinx_config_address, 127 bdf, offset, value, size); 128 } 129 130 /** 131 * pcie_xilinx_ofdata_to_platdata() - Translate from DT to device state 132 * @dev: A pointer to the device being operated on 133 * 134 * Translate relevant data from the device tree pertaining to device @dev into 135 * state that the driver will later make use of. This state is stored in the 136 * device's private data structure. 137 * 138 * Return: 0 on success, else -EINVAL 139 */ 140 static int pcie_xilinx_ofdata_to_platdata(struct udevice *dev) 141 { 142 struct xilinx_pcie *pcie = dev_get_priv(dev); 143 struct fdt_resource reg_res; 144 DECLARE_GLOBAL_DATA_PTR; 145 int err; 146 147 err = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev), "reg", 148 0, ®_res); 149 if (err < 0) { 150 pr_err("\"reg\" resource not found\n"); 151 return err; 152 } 153 154 pcie->cfg_base = map_physmem(reg_res.start, 155 fdt_resource_size(®_res), 156 MAP_NOCACHE); 157 158 return 0; 159 } 160 161 static const struct dm_pci_ops pcie_xilinx_ops = { 162 .read_config = pcie_xilinx_read_config, 163 .write_config = pcie_xilinx_write_config, 164 }; 165 166 static const struct udevice_id pcie_xilinx_ids[] = { 167 { .compatible = "xlnx,axi-pcie-host-1.00.a" }, 168 { } 169 }; 170 171 U_BOOT_DRIVER(pcie_xilinx) = { 172 .name = "pcie_xilinx", 173 .id = UCLASS_PCI, 174 .of_match = pcie_xilinx_ids, 175 .ops = &pcie_xilinx_ops, 176 .ofdata_to_platdata = pcie_xilinx_ofdata_to_platdata, 177 .priv_auto_alloc_size = sizeof(struct xilinx_pcie), 178 }; 179