linux/drivers/iommu/of_iommu.c
<<
>>
Prefs
   1/*
   2 * OF helpers for IOMMU
   3 *
   4 * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms and conditions of the GNU General Public License,
   8 * version 2, as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope it will be useful, but WITHOUT
  11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  13 * more details.
  14 *
  15 * You should have received a copy of the GNU General Public License along with
  16 * this program; if not, write to the Free Software Foundation, Inc.,
  17 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  18 */
  19
  20#include <linux/export.h>
  21#include <linux/limits.h>
  22#include <linux/of.h>
  23
  24/**
  25 * of_get_dma_window - Parse *dma-window property and returns 0 if found.
  26 *
  27 * @dn: device node
  28 * @prefix: prefix for property name if any
  29 * @index: index to start to parse
  30 * @busno: Returns busno if supported. Otherwise pass NULL
  31 * @addr: Returns address that DMA starts
  32 * @size: Returns the range that DMA can handle
  33 *
  34 * This supports different formats flexibly. "prefix" can be
  35 * configured if any. "busno" and "index" are optionally
  36 * specified. Set 0(or NULL) if not used.
  37 */
  38int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
  39                      unsigned long *busno, dma_addr_t *addr, size_t *size)
  40{
  41        const __be32 *dma_window, *end;
  42        int bytes, cur_index = 0;
  43        char propname[NAME_MAX], addrname[NAME_MAX], sizename[NAME_MAX];
  44
  45        if (!dn || !addr || !size)
  46                return -EINVAL;
  47
  48        if (!prefix)
  49                prefix = "";
  50
  51        snprintf(propname, sizeof(propname), "%sdma-window", prefix);
  52        snprintf(addrname, sizeof(addrname), "%s#dma-address-cells", prefix);
  53        snprintf(sizename, sizeof(sizename), "%s#dma-size-cells", prefix);
  54
  55        dma_window = of_get_property(dn, propname, &bytes);
  56        if (!dma_window)
  57                return -ENODEV;
  58        end = dma_window + bytes / sizeof(*dma_window);
  59
  60        while (dma_window < end) {
  61                u32 cells;
  62                const void *prop;
  63
  64                /* busno is one cell if supported */
  65                if (busno)
  66                        *busno = be32_to_cpup(dma_window++);
  67
  68                prop = of_get_property(dn, addrname, NULL);
  69                if (!prop)
  70                        prop = of_get_property(dn, "#address-cells", NULL);
  71
  72                cells = prop ? be32_to_cpup(prop) : of_n_addr_cells(dn);
  73                if (!cells)
  74                        return -EINVAL;
  75                *addr = of_read_number(dma_window, cells);
  76                dma_window += cells;
  77
  78                prop = of_get_property(dn, sizename, NULL);
  79                cells = prop ? be32_to_cpup(prop) : of_n_size_cells(dn);
  80                if (!cells)
  81                        return -EINVAL;
  82                *size = of_read_number(dma_window, cells);
  83                dma_window += cells;
  84
  85                if (cur_index++ == index)
  86                        break;
  87        }
  88        return 0;
  89}
  90EXPORT_SYMBOL_GPL(of_get_dma_window);
  91