This code was based on:
    "arch/microblaze/kernel/prom_parse.c"
    "arch/powerpc/kernel/prom_parse.c"
Can replace "of_parse_dma_window()" in the above. This supports
different formats flexibly. "prefix" can be configured if any. "busno"
and "index" are optionally specified. Set NULL and 0 if not used.
Signed-off-by: Hiroshi DOYU <hdoyu@nvidia.com>
Acked-by: Stephen Warren <swarren@wwwdotorg.org>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
		
	
			
		
			
				
	
	
		
			90 lines
		
	
	
	
		
			2.7 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			90 lines
		
	
	
	
		
			2.7 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * OF helpers for IOMMU
 | 
						|
 *
 | 
						|
 * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
 | 
						|
 *
 | 
						|
 * This program is free software; you can redistribute it and/or modify it
 | 
						|
 * under the terms and conditions of the GNU General Public License,
 | 
						|
 * version 2, as published by the Free Software Foundation.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
						|
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
						|
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
						|
 * more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License along with
 | 
						|
 * this program; if not, write to the Free Software Foundation, Inc.,
 | 
						|
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 | 
						|
 */
 | 
						|
 | 
						|
#include <linux/export.h>
 | 
						|
#include <linux/limits.h>
 | 
						|
#include <linux/of.h>
 | 
						|
 | 
						|
/**
 | 
						|
 * of_get_dma_window - Parse *dma-window property and returns 0 if found.
 | 
						|
 *
 | 
						|
 * @dn: device node
 | 
						|
 * @prefix: prefix for property name if any
 | 
						|
 * @index: index to start to parse
 | 
						|
 * @busno: Returns busno if supported. Otherwise pass NULL
 | 
						|
 * @addr: Returns address that DMA starts
 | 
						|
 * @size: Returns the range that DMA can handle
 | 
						|
 *
 | 
						|
 * This supports different formats flexibly. "prefix" can be
 | 
						|
 * configured if any. "busno" and "index" are optionally
 | 
						|
 * specified. Set 0(or NULL) if not used.
 | 
						|
 */
 | 
						|
int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
 | 
						|
		      unsigned long *busno, dma_addr_t *addr, size_t *size)
 | 
						|
{
 | 
						|
	const __be32 *dma_window, *end;
 | 
						|
	int bytes, cur_index = 0;
 | 
						|
	char propname[NAME_MAX], addrname[NAME_MAX], sizename[NAME_MAX];
 | 
						|
 | 
						|
	if (!dn || !addr || !size)
 | 
						|
		return -EINVAL;
 | 
						|
 | 
						|
	if (!prefix)
 | 
						|
		prefix = "";
 | 
						|
 | 
						|
	snprintf(propname, sizeof(propname), "%sdma-window", prefix);
 | 
						|
	snprintf(addrname, sizeof(addrname), "%s#dma-address-cells", prefix);
 | 
						|
	snprintf(sizename, sizeof(sizename), "%s#dma-size-cells", prefix);
 | 
						|
 | 
						|
	dma_window = of_get_property(dn, propname, &bytes);
 | 
						|
	if (!dma_window)
 | 
						|
		return -ENODEV;
 | 
						|
	end = dma_window + bytes / sizeof(*dma_window);
 | 
						|
 | 
						|
	while (dma_window < end) {
 | 
						|
		u32 cells;
 | 
						|
		const void *prop;
 | 
						|
 | 
						|
		/* busno is one cell if supported */
 | 
						|
		if (busno)
 | 
						|
			*busno = be32_to_cpup(dma_window++);
 | 
						|
 | 
						|
		prop = of_get_property(dn, addrname, NULL);
 | 
						|
		if (!prop)
 | 
						|
			prop = of_get_property(dn, "#address-cells", NULL);
 | 
						|
 | 
						|
		cells = prop ? be32_to_cpup(prop) : of_n_addr_cells(dn);
 | 
						|
		if (!cells)
 | 
						|
			return -EINVAL;
 | 
						|
		*addr = of_read_number(dma_window, cells);
 | 
						|
		dma_window += cells;
 | 
						|
 | 
						|
		prop = of_get_property(dn, sizename, NULL);
 | 
						|
		cells = prop ? be32_to_cpup(prop) : of_n_size_cells(dn);
 | 
						|
		if (!cells)
 | 
						|
			return -EINVAL;
 | 
						|
		*size = of_read_number(dma_window, cells);
 | 
						|
		dma_window += cells;
 | 
						|
 | 
						|
		if (cur_index++ == index)
 | 
						|
			break;
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(of_get_dma_window);
 |