summaryrefslogtreecommitdiff
path: root/drivers/pci/of.c
diff options
context:
space:
mode:
authorRob Herring <robh@kernel.org>2019-10-30 17:30:57 -0500
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2019-11-20 16:59:58 +0000
commit331f63457165a30c708280de2c77f1742c6351dc (patch)
tree0ec53251ad99144028bbeef689bddf4b4f52e364 /drivers/pci/of.c
parentecf8fd6d917dca1065e1021ff7fc6b6c282373f9 (diff)
PCI: of: Add inbound resource parsing to helpers
Extend devm_of_pci_get_host_bridge_resources() and pci_parse_request_of_pci_ranges() helpers to also parse the inbound addresses from DT 'dma-ranges' and populate a resource list with the translated addresses. This will help ensure 'dma-ranges' is always parsed in a consistent way. Tested-by: Srinath Mannam <srinath.mannam@broadcom.com> Tested-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com> # for AArdvark Signed-off-by: Rob Herring <robh@kernel.org> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Reviewed-by: Srinath Mannam <srinath.mannam@broadcom.com> Reviewed-by: Andrew Murray <andrew.murray@arm.com> Acked-by: Gustavo Pimentel <gustavo.pimentel@synopsys.com> Cc: Jingoo Han <jingoohan1@gmail.com> Cc: Gustavo Pimentel <gustavo.pimentel@synopsys.com> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com> Cc: Will Deacon <will@kernel.org> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Toan Le <toan@os.amperecomputing.com> Cc: Ley Foon Tan <lftan@altera.com> Cc: Tom Joseph <tjoseph@cadence.com> Cc: Ray Jui <rjui@broadcom.com> Cc: Scott Branden <sbranden@broadcom.com> Cc: bcm-kernel-feedback-list@broadcom.com Cc: Ryder Lee <ryder.lee@mediatek.com> Cc: Karthikeyan Mitran <m.karthikeyan@mobiveil.co.in> Cc: Hou Zhiqiang <Zhiqiang.Hou@nxp.com> Cc: Simon Horman <horms@verge.net.au> Cc: Shawn Lin <shawn.lin@rock-chips.com> Cc: Heiko Stuebner <heiko@sntech.de> Cc: Michal Simek <michal.simek@xilinx.com> Cc: rfi@lists.rocketboards.org Cc: linux-mediatek@lists.infradead.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-rockchip@lists.infradead.org
Diffstat (limited to 'drivers/pci/of.c')
-rw-r--r--drivers/pci/of.c61
1 files changed, 54 insertions, 7 deletions
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index f3da49a31db4..1dfde6f9e82d 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -257,14 +257,16 @@ EXPORT_SYMBOL_GPL(of_pci_check_probe_only);
*/
int devm_of_pci_get_host_bridge_resources(struct device *dev,
unsigned char busno, unsigned char bus_max,
- struct list_head *resources, resource_size_t *io_base)
+ struct list_head *resources,
+ struct list_head *ib_resources,
+ resource_size_t *io_base)
{
struct device_node *dev_node = dev->of_node;
struct resource *res, tmp_res;
struct resource *bus_range;
struct of_pci_range range;
struct of_pci_range_parser parser;
- char range_type[4];
+ const char *range_type;
int err;
if (io_base)
@@ -298,12 +300,12 @@ int devm_of_pci_get_host_bridge_resources(struct device *dev,
for_each_of_pci_range(&parser, &range) {
/* Read next ranges element */
if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
- snprintf(range_type, 4, " IO");
+ range_type = "IO";
else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
- snprintf(range_type, 4, "MEM");
+ range_type = "MEM";
else
- snprintf(range_type, 4, "err");
- dev_info(dev, " %s %#010llx..%#010llx -> %#010llx\n",
+ range_type = "err";
+ dev_info(dev, " %6s %#012llx..%#012llx -> %#012llx\n",
range_type, range.cpu_addr,
range.cpu_addr + range.size - 1, range.pci_addr);
@@ -340,6 +342,48 @@ int devm_of_pci_get_host_bridge_resources(struct device *dev,
pci_add_resource_offset(resources, res, res->start - range.pci_addr);
}
+ /* Check for dma-ranges property */
+ if (!ib_resources)
+ return 0;
+ err = of_pci_dma_range_parser_init(&parser, dev_node);
+ if (err)
+ return 0;
+
+ dev_dbg(dev, "Parsing dma-ranges property...\n");
+ for_each_of_pci_range(&parser, &range) {
+ struct resource_entry *entry;
+ /*
+ * If we failed translation or got a zero-sized region
+ * then skip this range
+ */
+ if (((range.flags & IORESOURCE_TYPE_BITS) != IORESOURCE_MEM) ||
+ range.cpu_addr == OF_BAD_ADDR || range.size == 0)
+ continue;
+
+ dev_info(dev, " %6s %#012llx..%#012llx -> %#012llx\n",
+ "IB MEM", range.cpu_addr,
+ range.cpu_addr + range.size - 1, range.pci_addr);
+
+
+ err = of_pci_range_to_resource(&range, dev_node, &tmp_res);
+ if (err)
+ continue;
+
+ res = devm_kmemdup(dev, &tmp_res, sizeof(tmp_res), GFP_KERNEL);
+ if (!res) {
+ err = -ENOMEM;
+ goto failed;
+ }
+
+ /* Keep the resource list sorted */
+ resource_list_for_each_entry(entry, ib_resources)
+ if (entry->res->start > res->start)
+ break;
+
+ pci_add_resource_offset(&entry->node, res,
+ res->start - range.pci_addr);
+ }
+
return 0;
failed:
@@ -482,6 +526,7 @@ EXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci);
int pci_parse_request_of_pci_ranges(struct device *dev,
struct list_head *resources,
+ struct list_head *ib_resources,
struct resource **bus_range)
{
int err, res_valid = 0;
@@ -489,8 +534,10 @@ int pci_parse_request_of_pci_ranges(struct device *dev,
struct resource_entry *win, *tmp;
INIT_LIST_HEAD(resources);
+ if (ib_resources)
+ INIT_LIST_HEAD(ib_resources);
err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff, resources,
- &iobase);
+ ib_resources, &iobase);
if (err)
return err;