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