|
@@ -1378,12 +1378,76 @@ EXPORT_SYMBOL(edma_clear_event);
|
|
|
|
|
|
#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DMADEVICES)
|
|
|
|
|
|
+static int edma_of_read_u32_to_s16_array(const struct device_node *np,
|
|
|
+ const char *propname, s16 *out_values,
|
|
|
+ size_t sz)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = of_property_read_u16_array(np, propname, out_values, sz);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ /* Terminate it */
|
|
|
+ *out_values++ = -1;
|
|
|
+ *out_values++ = -1;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int edma_xbar_event_map(struct device *dev,
|
|
|
+ struct device_node *node,
|
|
|
+ struct edma_soc_info *pdata, int len)
|
|
|
+{
|
|
|
+ int ret, i;
|
|
|
+ struct resource res;
|
|
|
+ void __iomem *xbar;
|
|
|
+ const s16 (*xbar_chans)[2];
|
|
|
+ u32 shift, offset, mux;
|
|
|
+
|
|
|
+ xbar_chans = devm_kzalloc(dev,
|
|
|
+ len/sizeof(s16) + 2*sizeof(s16),
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (!xbar_chans)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ ret = of_address_to_resource(node, 1, &res);
|
|
|
+ if (ret)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ xbar = devm_ioremap(dev, res.start, resource_size(&res));
|
|
|
+ if (!xbar)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ ret = edma_of_read_u32_to_s16_array(node,
|
|
|
+ "ti,edma-xbar-event-map",
|
|
|
+ (s16 *)xbar_chans,
|
|
|
+ len/sizeof(u32));
|
|
|
+ if (ret)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ for (i = 0; xbar_chans[i][0] != -1; i++) {
|
|
|
+ shift = (xbar_chans[i][1] & 0x03) << 3;
|
|
|
+ offset = xbar_chans[i][1] & 0xfffffffc;
|
|
|
+ mux = readl(xbar + offset);
|
|
|
+ mux &= ~(0xff << shift);
|
|
|
+ mux |= xbar_chans[i][0] << shift;
|
|
|
+ writel(mux, (xbar + offset));
|
|
|
+ }
|
|
|
+
|
|
|
+ pdata->xbar_chans = xbar_chans;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int edma_of_parse_dt(struct device *dev,
|
|
|
struct device_node *node,
|
|
|
struct edma_soc_info *pdata)
|
|
|
{
|
|
|
int ret = 0, i;
|
|
|
u32 value;
|
|
|
+ struct property *prop;
|
|
|
+ size_t sz;
|
|
|
struct edma_rsv_info *rsv_info;
|
|
|
s8 (*queue_tc_map)[2], (*queue_priority_map)[2];
|
|
|
|
|
@@ -1439,6 +1503,10 @@ static int edma_of_parse_dt(struct device *dev,
|
|
|
|
|
|
pdata->default_queue = 0;
|
|
|
|
|
|
+ prop = of_find_property(node, "ti,edma-xbar-event-map", &sz);
|
|
|
+ if (prop)
|
|
|
+ ret = edma_xbar_event_map(dev, node, pdata, sz);
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -1484,6 +1552,7 @@ static int edma_probe(struct platform_device *pdev)
|
|
|
int status = -1;
|
|
|
const s16 (*rsv_chans)[2];
|
|
|
const s16 (*rsv_slots)[2];
|
|
|
+ const s16 (*xbar_chans)[2];
|
|
|
int irq[EDMA_MAX_CC] = {0, 0};
|
|
|
int err_irq[EDMA_MAX_CC] = {0, 0};
|
|
|
struct resource *r[EDMA_MAX_CC] = {NULL};
|
|
@@ -1599,6 +1668,15 @@ static int edma_probe(struct platform_device *pdev)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /* Clear the xbar mapped channels in unused list */
|
|
|
+ xbar_chans = info[j]->xbar_chans;
|
|
|
+ if (xbar_chans) {
|
|
|
+ for (i = 0; xbar_chans[i][1] != -1; i++) {
|
|
|
+ off = xbar_chans[i][1];
|
|
|
+ clear_bits(off, 1,
|
|
|
+ edma_cc[j]->edma_unused);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
if (node) {
|
|
|
irq[j] = irq_of_parse_and_map(node, 0);
|