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