uboot/drivers/pci/pcie_ecam_generic.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Generic PCIE host provided by e.g. QEMU
   4 *
   5 * Heavily based on drivers/pci/pcie_xilinx.c
   6 *
   7 * Copyright (C) 2016 Imagination Technologies
   8 */
   9
  10#include <common.h>
  11#include <dm.h>
  12#include <pci.h>
  13
  14#include <asm/io.h>
  15
  16/**
  17 * struct generic_ecam_pcie - generic_ecam PCIe controller state
  18 * @cfg_base: The base address of memory mapped configuration space
  19 */
  20struct generic_ecam_pcie {
  21        void *cfg_base;
  22};
  23
  24/**
  25 * pci_generic_ecam_conf_address() - Calculate the address of a config access
  26 * @bus: Pointer to the PCI bus
  27 * @bdf: Identifies the PCIe device to access
  28 * @offset: The offset into the device's configuration space
  29 * @paddress: Pointer to the pointer to write the calculates address to
  30 *
  31 * Calculates the address that should be accessed to perform a PCIe
  32 * configuration space access for a given device identified by the PCIe
  33 * controller device @pcie and the bus, device & function numbers in @bdf. If
  34 * access to the device is not valid then the function will return an error
  35 * code. Otherwise the address to access will be written to the pointer pointed
  36 * to by @paddress.
  37 */
  38static int pci_generic_ecam_conf_address(struct udevice *bus, pci_dev_t bdf,
  39                                            uint offset, void **paddress)
  40{
  41        struct generic_ecam_pcie *pcie = dev_get_priv(bus);
  42        void *addr;
  43
  44        addr = pcie->cfg_base;
  45        addr += PCI_BUS(bdf) << 20;
  46        addr += PCI_DEV(bdf) << 15;
  47        addr += PCI_FUNC(bdf) << 12;
  48        addr += offset;
  49        *paddress = addr;
  50
  51        return 0;
  52}
  53
  54/**
  55 * pci_generic_ecam_read_config() - Read from configuration space
  56 * @bus: Pointer to the PCI bus
  57 * @bdf: Identifies the PCIe device to access
  58 * @offset: The offset into the device's configuration space
  59 * @valuep: A pointer at which to store the read value
  60 * @size: Indicates the size of access to perform
  61 *
  62 * Read a value of size @size from offset @offset within the configuration
  63 * space of the device identified by the bus, device & function numbers in @bdf
  64 * on the PCI bus @bus.
  65 */
  66static int pci_generic_ecam_read_config(struct udevice *bus, pci_dev_t bdf,
  67                                   uint offset, ulong *valuep,
  68                                   enum pci_size_t size)
  69{
  70        return pci_generic_mmap_read_config(bus, pci_generic_ecam_conf_address,
  71                                            bdf, offset, valuep, size);
  72}
  73
  74/**
  75 * pci_generic_ecam_write_config() - Write to configuration space
  76 * @bus: Pointer to the PCI bus
  77 * @bdf: Identifies the PCIe device to access
  78 * @offset: The offset into the device's configuration space
  79 * @value: The value to write
  80 * @size: Indicates the size of access to perform
  81 *
  82 * Write the value @value of size @size from offset @offset within the
  83 * configuration space of the device identified by the bus, device & function
  84 * numbers in @bdf on the PCI bus @bus.
  85 */
  86static int pci_generic_ecam_write_config(struct udevice *bus, pci_dev_t bdf,
  87                                    uint offset, ulong value,
  88                                    enum pci_size_t size)
  89{
  90        return pci_generic_mmap_write_config(bus, pci_generic_ecam_conf_address,
  91                                             bdf, offset, value, size);
  92}
  93
  94/**
  95 * pci_generic_ecam_ofdata_to_platdata() - Translate from DT to device state
  96 * @dev: A pointer to the device being operated on
  97 *
  98 * Translate relevant data from the device tree pertaining to device @dev into
  99 * state that the driver will later make use of. This state is stored in the
 100 * device's private data structure.
 101 *
 102 * Return: 0 on success, else -EINVAL
 103 */
 104static int pci_generic_ecam_ofdata_to_platdata(struct udevice *dev)
 105{
 106        struct generic_ecam_pcie *pcie = dev_get_priv(dev);
 107        struct fdt_resource reg_res;
 108        DECLARE_GLOBAL_DATA_PTR;
 109        int err;
 110
 111        err = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev), "reg",
 112                               0, &reg_res);
 113        if (err < 0) {
 114                pr_err("\"reg\" resource not found\n");
 115                return err;
 116        }
 117
 118        pcie->cfg_base = map_physmem(reg_res.start,
 119                                     fdt_resource_size(&reg_res),
 120                                     MAP_NOCACHE);
 121
 122        return 0;
 123}
 124
 125static const struct dm_pci_ops pci_generic_ecam_ops = {
 126        .read_config    = pci_generic_ecam_read_config,
 127        .write_config   = pci_generic_ecam_write_config,
 128};
 129
 130static const struct udevice_id pci_generic_ecam_ids[] = {
 131        { .compatible = "pci-host-ecam-generic" },
 132        { }
 133};
 134
 135U_BOOT_DRIVER(pci_generic_ecam) = {
 136        .name                   = "pci_generic_ecam",
 137        .id                     = UCLASS_PCI,
 138        .of_match               = pci_generic_ecam_ids,
 139        .ops                    = &pci_generic_ecam_ops,
 140        .ofdata_to_platdata     = pci_generic_ecam_ofdata_to_platdata,
 141        .priv_auto_alloc_size   = sizeof(struct generic_ecam_pcie),
 142};
 143