Linux Audio

Check our new training course

Loading...
v5.9
 1// SPDX-License-Identifier: GPL-2.0-or-later
 2/*
 3 * Contains routines needed to support swiotlb for ppc.
 4 *
 5 * Copyright (C) 2009-2010 Freescale Semiconductor, Inc.
 6 * Author: Becky Bruce
 
 
 
 
 
 
 7 */
 8#include <linux/memblock.h>
 
 
 
 
 
 
 9#include <asm/machdep.h>
10#include <asm/swiotlb.h>
 
 
11
12unsigned int ppc_swiotlb_enable;
13
14void __init swiotlb_detect_4g(void)
15{
16	if ((memblock_end_of_DRAM() - 1) > 0xffffffff)
17		ppc_swiotlb_enable = 1;
 
 
 
 
 
 
 
 
 
18}
19
20static int __init check_swiotlb_enabled(void)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21{
22	if (ppc_swiotlb_enable)
23		swiotlb_print_info();
24	else
25		swiotlb_exit();
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27	return 0;
28}
29subsys_initcall(check_swiotlb_enabled);
v3.5.6
 
  1/*
  2 * Contains routines needed to support swiotlb for ppc.
  3 *
  4 * Copyright (C) 2009-2010 Freescale Semiconductor, Inc.
  5 * Author: Becky Bruce
  6 *
  7 * This program is free software; you can redistribute  it and/or modify it
  8 * under  the terms of  the GNU General  Public License as published by the
  9 * Free Software Foundation;  either version 2 of the  License, or (at your
 10 * option) any later version.
 11 *
 12 */
 13
 14#include <linux/dma-mapping.h>
 15#include <linux/pfn.h>
 16#include <linux/of_platform.h>
 17#include <linux/platform_device.h>
 18#include <linux/pci.h>
 19
 20#include <asm/machdep.h>
 21#include <asm/swiotlb.h>
 22#include <asm/dma.h>
 23#include <asm/abs_addr.h>
 24
 25unsigned int ppc_swiotlb_enable;
 26
 27static u64 swiotlb_powerpc_get_required(struct device *dev)
 28{
 29	u64 end, mask, max_direct_dma_addr = dev->archdata.max_direct_dma_addr;
 30
 31	end = memblock_end_of_DRAM();
 32	if (max_direct_dma_addr && end > max_direct_dma_addr)
 33		end = max_direct_dma_addr;
 34	end += get_dma_offset(dev);
 35
 36	mask = 1ULL << (fls64(end) - 1);
 37	mask += mask - 1;
 38
 39	return mask;
 40}
 41
 42/*
 43 * At the moment, all platforms that use this code only require
 44 * swiotlb to be used if we're operating on HIGHMEM.  Since
 45 * we don't ever call anything other than map_sg, unmap_sg,
 46 * map_page, and unmap_page on highmem, use normal dma_ops
 47 * for everything else.
 48 */
 49struct dma_map_ops swiotlb_dma_ops = {
 50	.alloc = dma_direct_alloc_coherent,
 51	.free = dma_direct_free_coherent,
 52	.map_sg = swiotlb_map_sg_attrs,
 53	.unmap_sg = swiotlb_unmap_sg_attrs,
 54	.dma_supported = swiotlb_dma_supported,
 55	.map_page = swiotlb_map_page,
 56	.unmap_page = swiotlb_unmap_page,
 57	.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
 58	.sync_single_for_device = swiotlb_sync_single_for_device,
 59	.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
 60	.sync_sg_for_device = swiotlb_sync_sg_for_device,
 61	.mapping_error = swiotlb_dma_mapping_error,
 62	.get_required_mask = swiotlb_powerpc_get_required,
 63};
 64
 65void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev)
 66{
 67	struct pci_controller *hose;
 68	struct dev_archdata *sd;
 
 
 69
 70	hose = pci_bus_to_host(pdev->bus);
 71	sd = &pdev->dev.archdata;
 72	sd->max_direct_dma_addr =
 73		hose->dma_window_base_cur + hose->dma_window_size;
 74}
 75
 76static int ppc_swiotlb_bus_notify(struct notifier_block *nb,
 77				  unsigned long action, void *data)
 78{
 79	struct device *dev = data;
 80	struct dev_archdata *sd;
 81
 82	/* We are only intereted in device addition */
 83	if (action != BUS_NOTIFY_ADD_DEVICE)
 84		return 0;
 85
 86	sd = &dev->archdata;
 87	sd->max_direct_dma_addr = 0;
 88
 89	/* May need to bounce if the device can't address all of DRAM */
 90	if ((dma_get_mask(dev) + 1) < memblock_end_of_DRAM())
 91		set_dma_ops(dev, &swiotlb_dma_ops);
 92
 93	return NOTIFY_DONE;
 94}
 95
 96static struct notifier_block ppc_swiotlb_plat_bus_notifier = {
 97	.notifier_call = ppc_swiotlb_bus_notify,
 98	.priority = 0,
 99};
100
101int __init swiotlb_setup_bus_notifier(void)
102{
103	bus_register_notifier(&platform_bus_type,
104			      &ppc_swiotlb_plat_bus_notifier);
105	return 0;
106}