参照元

説明

引数

返り値

参考

実装

/**
 * of_dma_configure - Setup DMA configuration
 * @dev:        Device to apply DMA configuration
 * @np:         Pointer to OF node having DMA configuration
 *
 * Try to get devices's DMA configuration from DT and update it
 * accordingly.
 *
 * If platform code needs to use its own special DMA configuration, it
 * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
 * to fix up DMA configuration.
 */
void of_dma_configure(struct device *dev, struct device_node *np)
{
        u64 dma_addr, paddr, size;
        int ret;
        bool coherent;
        unsigned long offset;
        struct iommu_ops *iommu;
        /*
         * Set default coherent_dma_mask to 32 bit.  Drivers are expected to
         * setup the correct supported mask.
         */
        if (!dev->coherent_dma_mask)
                dev->coherent_dma_mask = DMA_BIT_MASK(32);
        /*
         * Set it to coherent_dma_mask by default if the architecture
         * code has not set it.
         */
        if (!dev->dma_mask)
                dev->dma_mask = &dev->coherent_dma_mask;

        ret = of_dma_get_range(np, &dma_addr, &paddr, &size);
        if (ret < 0) {
                dma_addr = offset = 0;
                size = dev->coherent_dma_mask + 1;
        } else {
                offset = PFN_DOWN(paddr - dma_addr);
                /*
                 * Add a work around to treat the size as mask + 1 in case
                 * it is defined in DT as a mask.
                 */
                if (size & 1) {
                        dev_warn(dev, "Invalid size 0x%llx for dma-range\n",
                                 size);
                        size = size + 1;
                }

                if (!size) {
                        dev_err(dev, "Adjusted size 0x%llx invalid\n", size);
                        return;
                }
                dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
        }

        dev->dma_pfn_offset = offset;

        /*
         * Limit coherent and dma mask based on size and default mask
         * set by the driver.
         */
        dev->coherent_dma_mask = min(dev->coherent_dma_mask,
                                     DMA_BIT_MASK(ilog2(dma_addr + size)));
        *dev->dma_mask = min((*dev->dma_mask),
                             DMA_BIT_MASK(ilog2(dma_addr + size)));
        coherent = of_dma_is_coherent(np);
        dev_dbg(dev, "device is%sdma coherent\n",
                coherent ? " " : " not ");
        iommu = of_iommu_configure(dev, np);
        dev_dbg(dev, "device is%sbehind an iommu\n",
                iommu ? " " : " not ");
        arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent);
}
EXPORT_SYMBOL_GPL(of_dma_configure);

コメント


トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-06-30 (木) 20:20:27