a3bbe02cda98110cbbf267898e489f0e581cdf13
[firefly-linux-kernel-4.4.55.git] / arch / powerpc / kernel / dma-swiotlb.c
1 /*
2  * Contains routines needed to support swiotlb for ppc.
3  *
4  * Copyright (C) 2009 Becky Bruce, Freescale Semiconductor
5  *
6  * This program is free software; you can redistribute  it and/or modify it
7  * under  the terms of  the GNU General  Public License as published by the
8  * Free Software Foundation;  either version 2 of the  License, or (at your
9  * option) any later version.
10  *
11  */
12
13 #include <linux/dma-mapping.h>
14 #include <linux/pfn.h>
15 #include <linux/of_platform.h>
16 #include <linux/platform_device.h>
17 #include <linux/pci.h>
18
19 #include <asm/machdep.h>
20 #include <asm/swiotlb.h>
21 #include <asm/dma.h>
22 #include <asm/abs_addr.h>
23
24 int swiotlb __read_mostly;
25 unsigned int ppc_swiotlb_enable;
26
27 dma_addr_t swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
28 {
29         return paddr + get_dma_direct_offset(hwdev);
30 }
31
32 phys_addr_t swiotlb_bus_to_phys(struct device *hwdev, dma_addr_t baddr)
33
34 {
35         return baddr - get_dma_direct_offset(hwdev);
36 }
37
38 /*
39  * Determine if an address is reachable by a pci device, or if we must bounce.
40  */
41 static int
42 swiotlb_pci_addr_needs_map(struct device *hwdev, dma_addr_t addr, size_t size)
43 {
44         dma_addr_t max;
45         struct pci_controller *hose;
46         struct pci_dev *pdev = to_pci_dev(hwdev);
47
48         hose = pci_bus_to_host(pdev->bus);
49         max = hose->dma_window_base_cur + hose->dma_window_size;
50
51         /* check that we're within mapped pci window space */
52         if ((addr + size > max) | (addr < hose->dma_window_base_cur))
53                 return 1;
54
55         return 0;
56 }
57
58 /*
59  * At the moment, all platforms that use this code only require
60  * swiotlb to be used if we're operating on HIGHMEM.  Since
61  * we don't ever call anything other than map_sg, unmap_sg,
62  * map_page, and unmap_page on highmem, use normal dma_ops
63  * for everything else.
64  */
65 struct dma_mapping_ops swiotlb_dma_ops = {
66         .alloc_coherent = dma_direct_alloc_coherent,
67         .free_coherent = dma_direct_free_coherent,
68         .map_sg = swiotlb_map_sg_attrs,
69         .unmap_sg = swiotlb_unmap_sg_attrs,
70         .dma_supported = swiotlb_dma_supported,
71         .map_page = swiotlb_map_page,
72         .unmap_page = swiotlb_unmap_page,
73         .sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
74         .sync_single_range_for_device = swiotlb_sync_single_range_for_device,
75         .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
76         .sync_sg_for_device = swiotlb_sync_sg_for_device
77 };
78
79 struct dma_mapping_ops swiotlb_pci_dma_ops = {
80         .alloc_coherent = dma_direct_alloc_coherent,
81         .free_coherent = dma_direct_free_coherent,
82         .map_sg = swiotlb_map_sg_attrs,
83         .unmap_sg = swiotlb_unmap_sg_attrs,
84         .dma_supported = swiotlb_dma_supported,
85         .map_page = swiotlb_map_page,
86         .unmap_page = swiotlb_unmap_page,
87         .addr_needs_map = swiotlb_pci_addr_needs_map,
88         .sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
89         .sync_single_range_for_device = swiotlb_sync_single_range_for_device,
90         .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
91         .sync_sg_for_device = swiotlb_sync_sg_for_device
92 };
93
94 static int ppc_swiotlb_bus_notify(struct notifier_block *nb,
95                                   unsigned long action, void *data)
96 {
97         struct device *dev = data;
98
99         /* We are only intereted in device addition */
100         if (action != BUS_NOTIFY_ADD_DEVICE)
101                 return 0;
102
103         /* May need to bounce if the device can't address all of DRAM */
104         if (dma_get_mask(dev) < lmb_end_of_DRAM())
105                 set_dma_ops(dev, &swiotlb_dma_ops);
106
107         return NOTIFY_DONE;
108 }
109
110 static struct notifier_block ppc_swiotlb_plat_bus_notifier = {
111         .notifier_call = ppc_swiotlb_bus_notify,
112         .priority = 0,
113 };
114
115 static struct notifier_block ppc_swiotlb_of_bus_notifier = {
116         .notifier_call = ppc_swiotlb_bus_notify,
117         .priority = 0,
118 };
119
120 int __init swiotlb_setup_bus_notifier(void)
121 {
122         bus_register_notifier(&platform_bus_type,
123                               &ppc_swiotlb_plat_bus_notifier);
124         bus_register_notifier(&of_platform_bus_type,
125                               &ppc_swiotlb_of_bus_notifier);
126
127         return 0;
128 }