Home | History | Annotate | Download | only in pci
      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  */
     20 struct 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  */
     38 static 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  */
     66 static 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  */
     86 static 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  */
    104 static 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 
    125 static 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 
    130 static const struct udevice_id pci_generic_ecam_ids[] = {
    131 	{ .compatible = "pci-host-ecam-generic" },
    132 	{ }
    133 };
    134 
    135 U_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