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> 214e0ee78fSHiroshi Doyu #include <linux/limits.h> 224e0ee78fSHiroshi Doyu #include <linux/of.h> 23cbff5634SBrian Norris #include <linux/of_iommu.h> 244e0ee78fSHiroshi Doyu 25*1cd076bfSWill Deacon static const struct of_device_id __iommu_of_table_sentinel 26*1cd076bfSWill Deacon __used __section(__iommu_of_table_end); 27*1cd076bfSWill Deacon 284e0ee78fSHiroshi Doyu /** 294e0ee78fSHiroshi Doyu * of_get_dma_window - Parse *dma-window property and returns 0 if found. 304e0ee78fSHiroshi Doyu * 314e0ee78fSHiroshi Doyu * @dn: device node 324e0ee78fSHiroshi Doyu * @prefix: prefix for property name if any 334e0ee78fSHiroshi Doyu * @index: index to start to parse 344e0ee78fSHiroshi Doyu * @busno: Returns busno if supported. Otherwise pass NULL 354e0ee78fSHiroshi Doyu * @addr: Returns address that DMA starts 364e0ee78fSHiroshi Doyu * @size: Returns the range that DMA can handle 374e0ee78fSHiroshi Doyu * 384e0ee78fSHiroshi Doyu * This supports different formats flexibly. "prefix" can be 394e0ee78fSHiroshi Doyu * configured if any. "busno" and "index" are optionally 404e0ee78fSHiroshi Doyu * specified. Set 0(or NULL) if not used. 414e0ee78fSHiroshi Doyu */ 424e0ee78fSHiroshi Doyu int of_get_dma_window(struct device_node *dn, const char *prefix, int index, 434e0ee78fSHiroshi Doyu unsigned long *busno, dma_addr_t *addr, size_t *size) 444e0ee78fSHiroshi Doyu { 454e0ee78fSHiroshi Doyu const __be32 *dma_window, *end; 464e0ee78fSHiroshi Doyu int bytes, cur_index = 0; 474e0ee78fSHiroshi Doyu char propname[NAME_MAX], addrname[NAME_MAX], sizename[NAME_MAX]; 484e0ee78fSHiroshi Doyu 494e0ee78fSHiroshi Doyu if (!dn || !addr || !size) 504e0ee78fSHiroshi Doyu return -EINVAL; 514e0ee78fSHiroshi Doyu 524e0ee78fSHiroshi Doyu if (!prefix) 534e0ee78fSHiroshi Doyu prefix = ""; 544e0ee78fSHiroshi Doyu 554e0ee78fSHiroshi Doyu snprintf(propname, sizeof(propname), "%sdma-window", prefix); 564e0ee78fSHiroshi Doyu snprintf(addrname, sizeof(addrname), "%s#dma-address-cells", prefix); 574e0ee78fSHiroshi Doyu snprintf(sizename, sizeof(sizename), "%s#dma-size-cells", prefix); 584e0ee78fSHiroshi Doyu 594e0ee78fSHiroshi Doyu dma_window = of_get_property(dn, propname, &bytes); 604e0ee78fSHiroshi Doyu if (!dma_window) 614e0ee78fSHiroshi Doyu return -ENODEV; 624e0ee78fSHiroshi Doyu end = dma_window + bytes / sizeof(*dma_window); 634e0ee78fSHiroshi Doyu 644e0ee78fSHiroshi Doyu while (dma_window < end) { 654e0ee78fSHiroshi Doyu u32 cells; 664e0ee78fSHiroshi Doyu const void *prop; 674e0ee78fSHiroshi Doyu 684e0ee78fSHiroshi Doyu /* busno is one cell if supported */ 694e0ee78fSHiroshi Doyu if (busno) 704e0ee78fSHiroshi Doyu *busno = be32_to_cpup(dma_window++); 714e0ee78fSHiroshi Doyu 724e0ee78fSHiroshi Doyu prop = of_get_property(dn, addrname, NULL); 734e0ee78fSHiroshi Doyu if (!prop) 744e0ee78fSHiroshi Doyu prop = of_get_property(dn, "#address-cells", NULL); 754e0ee78fSHiroshi Doyu 764e0ee78fSHiroshi Doyu cells = prop ? be32_to_cpup(prop) : of_n_addr_cells(dn); 774e0ee78fSHiroshi Doyu if (!cells) 784e0ee78fSHiroshi Doyu return -EINVAL; 794e0ee78fSHiroshi Doyu *addr = of_read_number(dma_window, cells); 804e0ee78fSHiroshi Doyu dma_window += cells; 814e0ee78fSHiroshi Doyu 824e0ee78fSHiroshi Doyu prop = of_get_property(dn, sizename, NULL); 834e0ee78fSHiroshi Doyu cells = prop ? be32_to_cpup(prop) : of_n_size_cells(dn); 844e0ee78fSHiroshi Doyu if (!cells) 854e0ee78fSHiroshi Doyu return -EINVAL; 864e0ee78fSHiroshi Doyu *size = of_read_number(dma_window, cells); 874e0ee78fSHiroshi Doyu dma_window += cells; 884e0ee78fSHiroshi Doyu 894e0ee78fSHiroshi Doyu if (cur_index++ == index) 904e0ee78fSHiroshi Doyu break; 914e0ee78fSHiroshi Doyu } 924e0ee78fSHiroshi Doyu return 0; 934e0ee78fSHiroshi Doyu } 944e0ee78fSHiroshi Doyu EXPORT_SYMBOL_GPL(of_get_dma_window); 95*1cd076bfSWill Deacon 96*1cd076bfSWill Deacon void __init of_iommu_init(void) 97*1cd076bfSWill Deacon { 98*1cd076bfSWill Deacon struct device_node *np; 99*1cd076bfSWill Deacon const struct of_device_id *match, *matches = &__iommu_of_table; 100*1cd076bfSWill Deacon 101*1cd076bfSWill Deacon for_each_matching_node_and_match(np, matches, &match) { 102*1cd076bfSWill Deacon const of_iommu_init_fn init_fn = match->data; 103*1cd076bfSWill Deacon 104*1cd076bfSWill Deacon if (init_fn(np)) 105*1cd076bfSWill Deacon pr_err("Failed to initialise IOMMU %s\n", 106*1cd076bfSWill Deacon of_node_full_name(np)); 107*1cd076bfSWill Deacon } 108*1cd076bfSWill Deacon } 109