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> 23*cbff5634SBrian Norris #include <linux/of_iommu.h> 244e0ee78fSHiroshi Doyu 254e0ee78fSHiroshi Doyu /** 264e0ee78fSHiroshi Doyu * of_get_dma_window - Parse *dma-window property and returns 0 if found. 274e0ee78fSHiroshi Doyu * 284e0ee78fSHiroshi Doyu * @dn: device node 294e0ee78fSHiroshi Doyu * @prefix: prefix for property name if any 304e0ee78fSHiroshi Doyu * @index: index to start to parse 314e0ee78fSHiroshi Doyu * @busno: Returns busno if supported. Otherwise pass NULL 324e0ee78fSHiroshi Doyu * @addr: Returns address that DMA starts 334e0ee78fSHiroshi Doyu * @size: Returns the range that DMA can handle 344e0ee78fSHiroshi Doyu * 354e0ee78fSHiroshi Doyu * This supports different formats flexibly. "prefix" can be 364e0ee78fSHiroshi Doyu * configured if any. "busno" and "index" are optionally 374e0ee78fSHiroshi Doyu * specified. Set 0(or NULL) if not used. 384e0ee78fSHiroshi Doyu */ 394e0ee78fSHiroshi Doyu int of_get_dma_window(struct device_node *dn, const char *prefix, int index, 404e0ee78fSHiroshi Doyu unsigned long *busno, dma_addr_t *addr, size_t *size) 414e0ee78fSHiroshi Doyu { 424e0ee78fSHiroshi Doyu const __be32 *dma_window, *end; 434e0ee78fSHiroshi Doyu int bytes, cur_index = 0; 444e0ee78fSHiroshi Doyu char propname[NAME_MAX], addrname[NAME_MAX], sizename[NAME_MAX]; 454e0ee78fSHiroshi Doyu 464e0ee78fSHiroshi Doyu if (!dn || !addr || !size) 474e0ee78fSHiroshi Doyu return -EINVAL; 484e0ee78fSHiroshi Doyu 494e0ee78fSHiroshi Doyu if (!prefix) 504e0ee78fSHiroshi Doyu prefix = ""; 514e0ee78fSHiroshi Doyu 524e0ee78fSHiroshi Doyu snprintf(propname, sizeof(propname), "%sdma-window", prefix); 534e0ee78fSHiroshi Doyu snprintf(addrname, sizeof(addrname), "%s#dma-address-cells", prefix); 544e0ee78fSHiroshi Doyu snprintf(sizename, sizeof(sizename), "%s#dma-size-cells", prefix); 554e0ee78fSHiroshi Doyu 564e0ee78fSHiroshi Doyu dma_window = of_get_property(dn, propname, &bytes); 574e0ee78fSHiroshi Doyu if (!dma_window) 584e0ee78fSHiroshi Doyu return -ENODEV; 594e0ee78fSHiroshi Doyu end = dma_window + bytes / sizeof(*dma_window); 604e0ee78fSHiroshi Doyu 614e0ee78fSHiroshi Doyu while (dma_window < end) { 624e0ee78fSHiroshi Doyu u32 cells; 634e0ee78fSHiroshi Doyu const void *prop; 644e0ee78fSHiroshi Doyu 654e0ee78fSHiroshi Doyu /* busno is one cell if supported */ 664e0ee78fSHiroshi Doyu if (busno) 674e0ee78fSHiroshi Doyu *busno = be32_to_cpup(dma_window++); 684e0ee78fSHiroshi Doyu 694e0ee78fSHiroshi Doyu prop = of_get_property(dn, addrname, NULL); 704e0ee78fSHiroshi Doyu if (!prop) 714e0ee78fSHiroshi Doyu prop = of_get_property(dn, "#address-cells", NULL); 724e0ee78fSHiroshi Doyu 734e0ee78fSHiroshi Doyu cells = prop ? be32_to_cpup(prop) : of_n_addr_cells(dn); 744e0ee78fSHiroshi Doyu if (!cells) 754e0ee78fSHiroshi Doyu return -EINVAL; 764e0ee78fSHiroshi Doyu *addr = of_read_number(dma_window, cells); 774e0ee78fSHiroshi Doyu dma_window += cells; 784e0ee78fSHiroshi Doyu 794e0ee78fSHiroshi Doyu prop = of_get_property(dn, sizename, NULL); 804e0ee78fSHiroshi Doyu cells = prop ? be32_to_cpup(prop) : of_n_size_cells(dn); 814e0ee78fSHiroshi Doyu if (!cells) 824e0ee78fSHiroshi Doyu return -EINVAL; 834e0ee78fSHiroshi Doyu *size = of_read_number(dma_window, cells); 844e0ee78fSHiroshi Doyu dma_window += cells; 854e0ee78fSHiroshi Doyu 864e0ee78fSHiroshi Doyu if (cur_index++ == index) 874e0ee78fSHiroshi Doyu break; 884e0ee78fSHiroshi Doyu } 894e0ee78fSHiroshi Doyu return 0; 904e0ee78fSHiroshi Doyu } 914e0ee78fSHiroshi Doyu EXPORT_SYMBOL_GPL(of_get_dma_window); 92