From 1866368a8ab8cacf73aa47f67138040d5620439d Mon Sep 17 00:00:00 2001 From: Yutang Jiang Date: Sat, 24 Dec 2016 01:11:32 +0800 Subject: layerscape: add ls1088ardb device support LS1088A is an ARMv8 implementation combining eight ARM A53 processor cores. The LS1088ARDB is an evaluatoin platform that supports the LS1088A family SoCs. Features summary: - Eight 64-bit ARM v8 Cortex-A53 CPUs - Data path acceleration architecture 2.0 (DPAA2) - Ethernet interfaces - QUADSPI flash, 3 PCIe, 2 USB, 1 SD, 2 DUARTs etc Signed-off-by: Yutang Jiang --- ...-mc-Extended-MC-bus-allocator-to-include-.patch | 326 +++++++++++++++++++++ 1 file changed, 326 insertions(+) create mode 100644 target/linux/layerscape/patches-4.4/7147-staging-fsl-mc-Extended-MC-bus-allocator-to-include-.patch (limited to 'target/linux/layerscape/patches-4.4/7147-staging-fsl-mc-Extended-MC-bus-allocator-to-include-.patch') diff --git a/target/linux/layerscape/patches-4.4/7147-staging-fsl-mc-Extended-MC-bus-allocator-to-include-.patch b/target/linux/layerscape/patches-4.4/7147-staging-fsl-mc-Extended-MC-bus-allocator-to-include-.patch new file mode 100644 index 0000000000..c02c892b21 --- /dev/null +++ b/target/linux/layerscape/patches-4.4/7147-staging-fsl-mc-Extended-MC-bus-allocator-to-include-.patch @@ -0,0 +1,326 @@ +From 23b09c6b4162a8264b600f35d7048256a7afc0cd Mon Sep 17 00:00:00 2001 +From: "J. German Rivera" +Date: Wed, 6 Jan 2016 16:03:23 -0600 +Subject: [PATCH 147/226] staging: fsl-mc: Extended MC bus allocator to + include IRQs + +All the IRQs for DPAA2 objects in the same DPRC must use +the ICID of that DPRC, as their device Id in the GIC-ITS. +Thus, all these IRQs must share the same ITT table in the GIC. +As a result, a pool of IRQs with the same device Id must be +preallocated per DPRC (fsl-mc bus instance). So, the fsl-mc +bus object allocator is extended to also provide services +to allocate IRQs to DPAA2 devices, from their parent fsl-mc bus +IRQ pool. + +Signed-off-by: J. German Rivera +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/fsl-mc/bus/mc-allocator.c | 199 +++++++++++++++++++++++++++ + drivers/staging/fsl-mc/include/mc-private.h | 15 ++ + drivers/staging/fsl-mc/include/mc.h | 9 ++ + 3 files changed, 223 insertions(+) + +--- a/drivers/staging/fsl-mc/bus/mc-allocator.c ++++ b/drivers/staging/fsl-mc/bus/mc-allocator.c +@@ -15,6 +15,7 @@ + #include "../include/dpcon-cmd.h" + #include "dpmcp-cmd.h" + #include "dpmcp.h" ++#include + + /** + * fsl_mc_resource_pool_add_device - add allocatable device to a resource +@@ -160,6 +161,7 @@ static const char *const fsl_mc_pool_typ + [FSL_MC_POOL_DPMCP] = "dpmcp", + [FSL_MC_POOL_DPBP] = "dpbp", + [FSL_MC_POOL_DPCON] = "dpcon", ++ [FSL_MC_POOL_IRQ] = "irq", + }; + + static int __must_check object_type_to_pool_type(const char *object_type, +@@ -465,6 +467,203 @@ void fsl_mc_object_free(struct fsl_mc_de + } + EXPORT_SYMBOL_GPL(fsl_mc_object_free); + ++/* ++ * Initialize the interrupt pool associated with a MC bus. ++ * It allocates a block of IRQs from the GIC-ITS ++ */ ++int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, ++ unsigned int irq_count) ++{ ++ unsigned int i; ++ struct msi_desc *msi_desc; ++ struct fsl_mc_device_irq *irq_resources; ++ struct fsl_mc_device_irq *mc_dev_irq; ++ int error; ++ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; ++ struct fsl_mc_resource_pool *res_pool = ++ &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; ++ ++ if (WARN_ON(irq_count == 0 || ++ irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)) ++ return -EINVAL; ++ ++ error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); ++ if (error < 0) ++ return error; ++ ++ irq_resources = devm_kzalloc(&mc_bus_dev->dev, ++ sizeof(*irq_resources) * irq_count, ++ GFP_KERNEL); ++ if (!irq_resources) { ++ error = -ENOMEM; ++ goto cleanup_msi_irqs; ++ } ++ ++ for (i = 0; i < irq_count; i++) { ++ mc_dev_irq = &irq_resources[i]; ++ ++ /* ++ * NOTE: This mc_dev_irq's MSI addr/value pair will be set ++ * by the fsl_mc_msi_write_msg() callback ++ */ ++ mc_dev_irq->resource.type = res_pool->type; ++ mc_dev_irq->resource.data = mc_dev_irq; ++ mc_dev_irq->resource.parent_pool = res_pool; ++ INIT_LIST_HEAD(&mc_dev_irq->resource.node); ++ list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list); ++ } ++ ++ for_each_msi_entry(msi_desc, &mc_bus_dev->dev) { ++ mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index]; ++ mc_dev_irq->msi_desc = msi_desc; ++ mc_dev_irq->resource.id = msi_desc->irq; ++ } ++ ++ res_pool->max_count = irq_count; ++ res_pool->free_count = irq_count; ++ mc_bus->irq_resources = irq_resources; ++ return 0; ++ ++cleanup_msi_irqs: ++ fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); ++ return error; ++} ++EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); ++ ++/** ++ * Teardown the interrupt pool associated with an MC bus. ++ * It frees the IRQs that were allocated to the pool, back to the GIC-ITS. ++ */ ++void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) ++{ ++ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; ++ struct fsl_mc_resource_pool *res_pool = ++ &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; ++ ++ if (WARN_ON(!mc_bus->irq_resources)) ++ return; ++ ++ if (WARN_ON(res_pool->max_count == 0)) ++ return; ++ ++ if (WARN_ON(res_pool->free_count != res_pool->max_count)) ++ return; ++ ++ INIT_LIST_HEAD(&res_pool->free_list); ++ res_pool->max_count = 0; ++ res_pool->free_count = 0; ++ mc_bus->irq_resources = NULL; ++ fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); ++} ++EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool); ++ ++/** ++ * It allocates the IRQs required by a given MC object device. The ++ * IRQs are allocated from the interrupt pool associated with the ++ * MC bus that contains the device, if the device is not a DPRC device. ++ * Otherwise, the IRQs are allocated from the interrupt pool associated ++ * with the MC bus that represents the DPRC device itself. ++ */ ++int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) ++{ ++ int i; ++ int irq_count; ++ int res_allocated_count = 0; ++ int error = -EINVAL; ++ struct fsl_mc_device_irq **irqs = NULL; ++ struct fsl_mc_bus *mc_bus; ++ struct fsl_mc_resource_pool *res_pool; ++ ++ if (WARN_ON(mc_dev->irqs)) ++ return -EINVAL; ++ ++ irq_count = mc_dev->obj_desc.irq_count; ++ if (WARN_ON(irq_count == 0)) ++ return -EINVAL; ++ ++ if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) ++ mc_bus = to_fsl_mc_bus(mc_dev); ++ else ++ mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); ++ ++ if (WARN_ON(!mc_bus->irq_resources)) ++ return -EINVAL; ++ ++ res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; ++ if (res_pool->free_count < irq_count) { ++ dev_err(&mc_dev->dev, ++ "Not able to allocate %u irqs for device\n", irq_count); ++ return -ENOSPC; ++ } ++ ++ irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]), ++ GFP_KERNEL); ++ if (!irqs) ++ return -ENOMEM; ++ ++ for (i = 0; i < irq_count; i++) { ++ struct fsl_mc_resource *resource; ++ ++ error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ, ++ &resource); ++ if (error < 0) ++ goto error_resource_alloc; ++ ++ irqs[i] = to_fsl_mc_irq(resource); ++ res_allocated_count++; ++ ++ WARN_ON(irqs[i]->mc_dev); ++ irqs[i]->mc_dev = mc_dev; ++ irqs[i]->dev_irq_index = i; ++ } ++ ++ mc_dev->irqs = irqs; ++ return 0; ++ ++error_resource_alloc: ++ for (i = 0; i < res_allocated_count; i++) { ++ irqs[i]->mc_dev = NULL; ++ fsl_mc_resource_free(&irqs[i]->resource); ++ } ++ ++ return error; ++} ++EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs); ++ ++/* ++ * It frees the IRQs that were allocated for a MC object device, by ++ * returning them to the corresponding interrupt pool. ++ */ ++void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) ++{ ++ int i; ++ int irq_count; ++ struct fsl_mc_bus *mc_bus; ++ struct fsl_mc_device_irq **irqs = mc_dev->irqs; ++ ++ if (WARN_ON(!irqs)) ++ return; ++ ++ irq_count = mc_dev->obj_desc.irq_count; ++ ++ if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) ++ mc_bus = to_fsl_mc_bus(mc_dev); ++ else ++ mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); ++ ++ if (WARN_ON(!mc_bus->irq_resources)) ++ return; ++ ++ for (i = 0; i < irq_count; i++) { ++ WARN_ON(!irqs[i]->mc_dev); ++ irqs[i]->mc_dev = NULL; ++ fsl_mc_resource_free(&irqs[i]->resource); ++ } ++ ++ mc_dev->irqs = NULL; ++} ++EXPORT_SYMBOL_GPL(fsl_mc_free_irqs); ++ + /** + * fsl_mc_allocator_probe - callback invoked when an allocatable device is + * being added to the system +--- a/drivers/staging/fsl-mc/include/mc-private.h ++++ b/drivers/staging/fsl-mc/include/mc-private.h +@@ -30,6 +30,16 @@ struct irq_domain; + struct msi_domain_info; + + /** ++ * Maximum number of total IRQs that can be pre-allocated for an MC bus' ++ * IRQ pool ++ */ ++#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256 ++ ++struct device_node; ++struct irq_domain; ++struct msi_domain_info; ++ ++/** + * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device + * @root_mc_bus_dev: MC object device representing the root DPRC + * @num_translation_ranges: number of entries in addr_translation_ranges +@@ -137,4 +147,9 @@ int __init its_fsl_mc_msi_init(void); + + void its_fsl_mc_msi_cleanup(void); + ++int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, ++ unsigned int irq_count); ++ ++void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus); ++ + #endif /* _FSL_MC_PRIVATE_H_ */ +--- a/drivers/staging/fsl-mc/include/mc.h ++++ b/drivers/staging/fsl-mc/include/mc.h +@@ -14,12 +14,14 @@ + #include + #include + #include ++#include + #include "../include/dprc.h" + + #define FSL_MC_VENDOR_FREESCALE 0x1957 + + struct fsl_mc_device; + struct fsl_mc_io; ++struct fsl_mc_bus; + + /** + * struct fsl_mc_driver - MC object device driver object +@@ -75,6 +77,7 @@ enum fsl_mc_pool_type { + FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */ + FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */ + FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */ ++ FSL_MC_POOL_IRQ, + + /* + * NOTE: New resource pool types must be added before this entry +@@ -141,6 +144,7 @@ struct fsl_mc_device_irq { + * NULL if none. + * @obj_desc: MC description of the DPAA device + * @regions: pointer to array of MMIO region entries ++ * @irqs: pointer to array of pointers to interrupts allocated to this device + * @resource: generic resource associated with this MC object device, if any. + * + * Generic device object for MC object devices that are "attached" to a +@@ -172,6 +176,7 @@ struct fsl_mc_device { + struct fsl_mc_io *mc_io; + struct dprc_obj_desc obj_desc; + struct resource *regions; ++ struct fsl_mc_device_irq **irqs; + struct fsl_mc_resource *resource; + }; + +@@ -215,6 +220,10 @@ int __must_check fsl_mc_object_allocate( + + void fsl_mc_object_free(struct fsl_mc_device *mc_adev); + ++int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev); ++ ++void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev); ++ + extern struct bus_type fsl_mc_bus_type; + + #endif /* _FSL_MC_H_ */ -- cgit v1.2.3