Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/dma/dw/of.c
26282 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Platform driver for the Synopsys DesignWare DMA Controller
4
*
5
* Copyright (C) 2007-2008 Atmel Corporation
6
* Copyright (C) 2010-2011 ST Microelectronics
7
* Copyright (C) 2013 Intel Corporation
8
*/
9
10
#include <linux/of.h>
11
#include <linux/of_dma.h>
12
#include <linux/platform_device.h>
13
14
#include "internal.h"
15
16
static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec,
17
struct of_dma *ofdma)
18
{
19
struct dw_dma *dw = ofdma->of_dma_data;
20
struct dw_dma_slave slave = {
21
.dma_dev = dw->dma.dev,
22
};
23
dma_cap_mask_t cap;
24
25
if (dma_spec->args_count < 3 || dma_spec->args_count > 4)
26
return NULL;
27
28
slave.src_id = dma_spec->args[0];
29
slave.dst_id = dma_spec->args[0];
30
slave.m_master = dma_spec->args[1];
31
slave.p_master = dma_spec->args[2];
32
if (dma_spec->args_count >= 4)
33
slave.channels = dma_spec->args[3];
34
35
if (WARN_ON(slave.src_id >= DW_DMA_MAX_NR_REQUESTS ||
36
slave.dst_id >= DW_DMA_MAX_NR_REQUESTS ||
37
slave.m_master >= dw->pdata->nr_masters ||
38
slave.p_master >= dw->pdata->nr_masters ||
39
slave.channels >= BIT(dw->pdata->nr_channels)))
40
return NULL;
41
42
dma_cap_zero(cap);
43
dma_cap_set(DMA_SLAVE, cap);
44
45
/* TODO: there should be a simpler way to do this */
46
return dma_request_channel(cap, dw_dma_filter, &slave);
47
}
48
49
struct dw_dma_platform_data *dw_dma_parse_dt(struct platform_device *pdev)
50
{
51
struct device_node *np = pdev->dev.of_node;
52
struct dw_dma_platform_data *pdata;
53
u32 tmp, arr[DW_DMA_MAX_NR_MASTERS];
54
u32 nr_masters;
55
u32 nr_channels;
56
57
if (of_property_read_u32(np, "dma-masters", &nr_masters))
58
return NULL;
59
if (nr_masters < 1 || nr_masters > DW_DMA_MAX_NR_MASTERS)
60
return NULL;
61
62
if (of_property_read_u32(np, "dma-channels", &nr_channels))
63
return NULL;
64
if (nr_channels > DW_DMA_MAX_NR_CHANNELS)
65
return NULL;
66
67
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
68
if (!pdata)
69
return NULL;
70
71
pdata->nr_masters = nr_masters;
72
pdata->nr_channels = nr_channels;
73
74
of_property_read_u32(np, "chan_allocation_order", &pdata->chan_allocation_order);
75
of_property_read_u32(np, "chan_priority", &pdata->chan_priority);
76
77
of_property_read_u32(np, "block_size", &pdata->block_size);
78
79
/* Try deprecated property first */
80
if (!of_property_read_u32_array(np, "data_width", arr, nr_masters)) {
81
for (tmp = 0; tmp < nr_masters; tmp++)
82
pdata->data_width[tmp] = BIT(arr[tmp] & 0x07);
83
}
84
85
/* If "data_width" and "data-width" both provided use the latter one */
86
of_property_read_u32_array(np, "data-width", pdata->data_width, nr_masters);
87
88
memset32(pdata->multi_block, 1, nr_channels);
89
of_property_read_u32_array(np, "multi-block", pdata->multi_block, nr_channels);
90
91
memset32(pdata->max_burst, DW_DMA_MAX_BURST, nr_channels);
92
of_property_read_u32_array(np, "snps,max-burst-len", pdata->max_burst, nr_channels);
93
94
of_property_read_u32(np, "snps,dma-protection-control", &pdata->protctl);
95
if (pdata->protctl > CHAN_PROTCTL_MASK)
96
return NULL;
97
98
return pdata;
99
}
100
101
void dw_dma_of_controller_register(struct dw_dma *dw)
102
{
103
struct device *dev = dw->dma.dev;
104
int ret;
105
106
if (!dev->of_node)
107
return;
108
109
ret = of_dma_controller_register(dev->of_node, dw_dma_of_xlate, dw);
110
if (ret)
111
dev_err(dev, "could not register of_dma_controller\n");
112
}
113
114
void dw_dma_of_controller_free(struct dw_dma *dw)
115
{
116
struct device *dev = dw->dma.dev;
117
118
if (!dev->of_node)
119
return;
120
121
of_dma_controller_free(dev->of_node);
122
}
123
124