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