14e0ee78fSHiroshi Doyu /* 24e0ee78fSHiroshi Doyu * OF helpers for IOMMU 34e0ee78fSHiroshi Doyu * 44e0ee78fSHiroshi Doyu * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 54e0ee78fSHiroshi Doyu * 64e0ee78fSHiroshi Doyu * This program is free software; you can redistribute it and/or modify it 74e0ee78fSHiroshi Doyu * under the terms and conditions of the GNU General Public License, 84e0ee78fSHiroshi Doyu * version 2, as published by the Free Software Foundation. 94e0ee78fSHiroshi Doyu * 104e0ee78fSHiroshi Doyu * This program is distributed in the hope it will be useful, but WITHOUT 114e0ee78fSHiroshi Doyu * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 124e0ee78fSHiroshi Doyu * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 134e0ee78fSHiroshi Doyu * more details. 144e0ee78fSHiroshi Doyu * 154e0ee78fSHiroshi Doyu * You should have received a copy of the GNU General Public License along with 164e0ee78fSHiroshi Doyu * this program; if not, write to the Free Software Foundation, Inc., 174e0ee78fSHiroshi Doyu * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 184e0ee78fSHiroshi Doyu */ 194e0ee78fSHiroshi Doyu 204e0ee78fSHiroshi Doyu #include <linux/export.h> 217eba1d51SWill Deacon #include <linux/iommu.h> 224e0ee78fSHiroshi Doyu #include <linux/limits.h> 234e0ee78fSHiroshi Doyu #include <linux/of.h> 24cbff5634SBrian Norris #include <linux/of_iommu.h> 25*b996444cSRobin Murphy #include <linux/of_pci.h> 26a42a7a1fSRobin Murphy #include <linux/slab.h> 274e0ee78fSHiroshi Doyu 281cd076bfSWill Deacon static const struct of_device_id __iommu_of_table_sentinel 291cd076bfSWill Deacon __used __section(__iommu_of_table_end); 301cd076bfSWill Deacon 314e0ee78fSHiroshi Doyu /** 324e0ee78fSHiroshi Doyu * of_get_dma_window - Parse *dma-window property and returns 0 if found. 334e0ee78fSHiroshi Doyu * 344e0ee78fSHiroshi Doyu * @dn: device node 354e0ee78fSHiroshi Doyu * @prefix: prefix for property name if any 364e0ee78fSHiroshi Doyu * @index: index to start to parse 374e0ee78fSHiroshi Doyu * @busno: Returns busno if supported. Otherwise pass NULL 384e0ee78fSHiroshi Doyu * @addr: Returns address that DMA starts 394e0ee78fSHiroshi Doyu * @size: Returns the range that DMA can handle 404e0ee78fSHiroshi Doyu * 414e0ee78fSHiroshi Doyu * This supports different formats flexibly. "prefix" can be 424e0ee78fSHiroshi Doyu * configured if any. "busno" and "index" are optionally 434e0ee78fSHiroshi Doyu * specified. Set 0(or NULL) if not used. 444e0ee78fSHiroshi Doyu */ 454e0ee78fSHiroshi Doyu int of_get_dma_window(struct device_node *dn, const char *prefix, int index, 464e0ee78fSHiroshi Doyu unsigned long *busno, dma_addr_t *addr, size_t *size) 474e0ee78fSHiroshi Doyu { 484e0ee78fSHiroshi Doyu const __be32 *dma_window, *end; 494e0ee78fSHiroshi Doyu int bytes, cur_index = 0; 504e0ee78fSHiroshi Doyu char propname[NAME_MAX], addrname[NAME_MAX], sizename[NAME_MAX]; 514e0ee78fSHiroshi Doyu 524e0ee78fSHiroshi Doyu if (!dn || !addr || !size) 534e0ee78fSHiroshi Doyu return -EINVAL; 544e0ee78fSHiroshi Doyu 554e0ee78fSHiroshi Doyu if (!prefix) 564e0ee78fSHiroshi Doyu prefix = ""; 574e0ee78fSHiroshi Doyu 584e0ee78fSHiroshi Doyu snprintf(propname, sizeof(propname), "%sdma-window", prefix); 594e0ee78fSHiroshi Doyu snprintf(addrname, sizeof(addrname), "%s#dma-address-cells", prefix); 604e0ee78fSHiroshi Doyu snprintf(sizename, sizeof(sizename), "%s#dma-size-cells", prefix); 614e0ee78fSHiroshi Doyu 624e0ee78fSHiroshi Doyu dma_window = of_get_property(dn, propname, &bytes); 634e0ee78fSHiroshi Doyu if (!dma_window) 644e0ee78fSHiroshi Doyu return -ENODEV; 654e0ee78fSHiroshi Doyu end = dma_window + bytes / sizeof(*dma_window); 664e0ee78fSHiroshi Doyu 674e0ee78fSHiroshi Doyu while (dma_window < end) { 684e0ee78fSHiroshi Doyu u32 cells; 694e0ee78fSHiroshi Doyu const void *prop; 704e0ee78fSHiroshi Doyu 714e0ee78fSHiroshi Doyu /* busno is one cell if supported */ 724e0ee78fSHiroshi Doyu if (busno) 734e0ee78fSHiroshi Doyu *busno = be32_to_cpup(dma_window++); 744e0ee78fSHiroshi Doyu 754e0ee78fSHiroshi Doyu prop = of_get_property(dn, addrname, NULL); 764e0ee78fSHiroshi Doyu if (!prop) 774e0ee78fSHiroshi Doyu prop = of_get_property(dn, "#address-cells", NULL); 784e0ee78fSHiroshi Doyu 794e0ee78fSHiroshi Doyu cells = prop ? be32_to_cpup(prop) : of_n_addr_cells(dn); 804e0ee78fSHiroshi Doyu if (!cells) 814e0ee78fSHiroshi Doyu return -EINVAL; 824e0ee78fSHiroshi Doyu *addr = of_read_number(dma_window, cells); 834e0ee78fSHiroshi Doyu dma_window += cells; 844e0ee78fSHiroshi Doyu 854e0ee78fSHiroshi Doyu prop = of_get_property(dn, sizename, NULL); 864e0ee78fSHiroshi Doyu cells = prop ? be32_to_cpup(prop) : of_n_size_cells(dn); 874e0ee78fSHiroshi Doyu if (!cells) 884e0ee78fSHiroshi Doyu return -EINVAL; 894e0ee78fSHiroshi Doyu *size = of_read_number(dma_window, cells); 904e0ee78fSHiroshi Doyu dma_window += cells; 914e0ee78fSHiroshi Doyu 924e0ee78fSHiroshi Doyu if (cur_index++ == index) 934e0ee78fSHiroshi Doyu break; 944e0ee78fSHiroshi Doyu } 954e0ee78fSHiroshi Doyu return 0; 964e0ee78fSHiroshi Doyu } 974e0ee78fSHiroshi Doyu EXPORT_SYMBOL_GPL(of_get_dma_window); 981cd076bfSWill Deacon 99a42a7a1fSRobin Murphy struct of_iommu_node { 100a42a7a1fSRobin Murphy struct list_head list; 101a42a7a1fSRobin Murphy struct device_node *np; 10253c92d79SRobin Murphy const struct iommu_ops *ops; 103a42a7a1fSRobin Murphy }; 104a42a7a1fSRobin Murphy static LIST_HEAD(of_iommu_list); 105a42a7a1fSRobin Murphy static DEFINE_SPINLOCK(of_iommu_lock); 106a42a7a1fSRobin Murphy 10753c92d79SRobin Murphy void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops) 108a42a7a1fSRobin Murphy { 109a42a7a1fSRobin Murphy struct of_iommu_node *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); 110a42a7a1fSRobin Murphy 111a42a7a1fSRobin Murphy if (WARN_ON(!iommu)) 112a42a7a1fSRobin Murphy return; 113a42a7a1fSRobin Murphy 11445bb966dSAnup Patel of_node_get(np); 115a42a7a1fSRobin Murphy INIT_LIST_HEAD(&iommu->list); 116a42a7a1fSRobin Murphy iommu->np = np; 117a42a7a1fSRobin Murphy iommu->ops = ops; 118a42a7a1fSRobin Murphy spin_lock(&of_iommu_lock); 119a42a7a1fSRobin Murphy list_add_tail(&iommu->list, &of_iommu_list); 120a42a7a1fSRobin Murphy spin_unlock(&of_iommu_lock); 121a42a7a1fSRobin Murphy } 122a42a7a1fSRobin Murphy 12353c92d79SRobin Murphy const struct iommu_ops *of_iommu_get_ops(struct device_node *np) 124a42a7a1fSRobin Murphy { 125a42a7a1fSRobin Murphy struct of_iommu_node *node; 12653c92d79SRobin Murphy const struct iommu_ops *ops = NULL; 127a42a7a1fSRobin Murphy 128a42a7a1fSRobin Murphy spin_lock(&of_iommu_lock); 129a42a7a1fSRobin Murphy list_for_each_entry(node, &of_iommu_list, list) 130a42a7a1fSRobin Murphy if (node->np == np) { 131a42a7a1fSRobin Murphy ops = node->ops; 132a42a7a1fSRobin Murphy break; 133a42a7a1fSRobin Murphy } 134a42a7a1fSRobin Murphy spin_unlock(&of_iommu_lock); 135a42a7a1fSRobin Murphy return ops; 136a42a7a1fSRobin Murphy } 137a42a7a1fSRobin Murphy 138*b996444cSRobin Murphy static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data) 139*b996444cSRobin Murphy { 140*b996444cSRobin Murphy struct of_phandle_args *iommu_spec = data; 141*b996444cSRobin Murphy 142*b996444cSRobin Murphy iommu_spec->args[0] = alias; 143*b996444cSRobin Murphy return iommu_spec->np == pdev->bus->dev.of_node; 144*b996444cSRobin Murphy } 145*b996444cSRobin Murphy 146*b996444cSRobin Murphy static const struct iommu_ops 147*b996444cSRobin Murphy *of_pci_iommu_configure(struct pci_dev *pdev, struct device_node *bridge_np) 148*b996444cSRobin Murphy { 149*b996444cSRobin Murphy const struct iommu_ops *ops; 150*b996444cSRobin Murphy struct of_phandle_args iommu_spec; 151*b996444cSRobin Murphy 152*b996444cSRobin Murphy /* 153*b996444cSRobin Murphy * Start by tracing the RID alias down the PCI topology as 154*b996444cSRobin Murphy * far as the host bridge whose OF node we have... 155*b996444cSRobin Murphy * (we're not even attempting to handle multi-alias devices yet) 156*b996444cSRobin Murphy */ 157*b996444cSRobin Murphy iommu_spec.args_count = 1; 158*b996444cSRobin Murphy iommu_spec.np = bridge_np; 159*b996444cSRobin Murphy pci_for_each_dma_alias(pdev, __get_pci_rid, &iommu_spec); 160*b996444cSRobin Murphy /* 161*b996444cSRobin Murphy * ...then find out what that becomes once it escapes the PCI 162*b996444cSRobin Murphy * bus into the system beyond, and which IOMMU it ends up at. 163*b996444cSRobin Murphy */ 164*b996444cSRobin Murphy iommu_spec.np = NULL; 165*b996444cSRobin Murphy if (of_pci_map_rid(bridge_np, iommu_spec.args[0], "iommu-map", 166*b996444cSRobin Murphy "iommu-map-mask", &iommu_spec.np, iommu_spec.args)) 167*b996444cSRobin Murphy return NULL; 168*b996444cSRobin Murphy 169*b996444cSRobin Murphy ops = of_iommu_get_ops(iommu_spec.np); 170*b996444cSRobin Murphy if (!ops || !ops->of_xlate || ops->of_xlate(&pdev->dev, &iommu_spec)) 171*b996444cSRobin Murphy ops = NULL; 172*b996444cSRobin Murphy 173*b996444cSRobin Murphy of_node_put(iommu_spec.np); 174*b996444cSRobin Murphy return ops; 175*b996444cSRobin Murphy } 176*b996444cSRobin Murphy 17753c92d79SRobin Murphy const struct iommu_ops *of_iommu_configure(struct device *dev, 178ed748621SMurali Karicheri struct device_node *master_np) 1797eba1d51SWill Deacon { 1807eba1d51SWill Deacon struct of_phandle_args iommu_spec; 1817eba1d51SWill Deacon struct device_node *np; 18253c92d79SRobin Murphy const struct iommu_ops *ops = NULL; 1837eba1d51SWill Deacon int idx = 0; 1847eba1d51SWill Deacon 1857b0ce727SRobin Murphy if (dev_is_pci(dev)) 186*b996444cSRobin Murphy return of_pci_iommu_configure(to_pci_dev(dev), master_np); 187ed748621SMurali Karicheri 1887eba1d51SWill Deacon /* 1897eba1d51SWill Deacon * We don't currently walk up the tree looking for a parent IOMMU. 1907eba1d51SWill Deacon * See the `Notes:' section of 1917eba1d51SWill Deacon * Documentation/devicetree/bindings/iommu/iommu.txt 1927eba1d51SWill Deacon */ 193ed748621SMurali Karicheri while (!of_parse_phandle_with_args(master_np, "iommus", 1947eba1d51SWill Deacon "#iommu-cells", idx, 1957eba1d51SWill Deacon &iommu_spec)) { 1967eba1d51SWill Deacon np = iommu_spec.np; 1977eba1d51SWill Deacon ops = of_iommu_get_ops(np); 1987eba1d51SWill Deacon 1997eba1d51SWill Deacon if (!ops || !ops->of_xlate || ops->of_xlate(dev, &iommu_spec)) 2007eba1d51SWill Deacon goto err_put_node; 2017eba1d51SWill Deacon 2027eba1d51SWill Deacon of_node_put(np); 2037eba1d51SWill Deacon idx++; 2047eba1d51SWill Deacon } 2057eba1d51SWill Deacon 2067eba1d51SWill Deacon return ops; 2077eba1d51SWill Deacon 2087eba1d51SWill Deacon err_put_node: 2097eba1d51SWill Deacon of_node_put(np); 2107eba1d51SWill Deacon return NULL; 2117eba1d51SWill Deacon } 2127eba1d51SWill Deacon 213bb8e15d6SKefeng Wang static int __init of_iommu_init(void) 2141cd076bfSWill Deacon { 2151cd076bfSWill Deacon struct device_node *np; 2161cd076bfSWill Deacon const struct of_device_id *match, *matches = &__iommu_of_table; 2171cd076bfSWill Deacon 2181cd076bfSWill Deacon for_each_matching_node_and_match(np, matches, &match) { 2191cd076bfSWill Deacon const of_iommu_init_fn init_fn = match->data; 2201cd076bfSWill Deacon 2211cd076bfSWill Deacon if (init_fn(np)) 2221cd076bfSWill Deacon pr_err("Failed to initialise IOMMU %s\n", 2231cd076bfSWill Deacon of_node_full_name(np)); 2241cd076bfSWill Deacon } 225bb8e15d6SKefeng Wang 226bb8e15d6SKefeng Wang return 0; 2271cd076bfSWill Deacon } 228bb8e15d6SKefeng Wang postcore_initcall_sync(of_iommu_init); 229