Lines Matching refs:pl330
1202 static inline int _ldst_peripheral(struct pl330_dmac *pl330, in _ldst_peripheral() argument
1213 if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) in _ldst_peripheral()
1244 static int _bursts(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[], in _bursts() argument
1250 if (pl330->quirks & PL330_QUIRK_PERIPH_BURST) in _bursts()
1256 off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs, cyc, in _bursts()
1278 static int _dregs(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[], in _dregs() argument
1306 off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs, 1, in _dregs()
1332 static inline int _loop(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[], in _loop() argument
1340 return _bursts(pl330, dry_run, buf, pxs, 1); in _loop()
1358 szbrst = _bursts(pl330, 1, buf, pxs, 1); in _loop()
1390 off += _bursts(pl330, dry_run, &buf[off], pxs, cyc); in _loop()
1413 static int _period(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[], in _period() argument
1432 off += _bursts(pl330, dry_run, &buf[off], pxs, cyc); in _period()
1445 off += _bursts(pl330, dry_run, &buf[off], pxs, 1); in _period()
1459 off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs); in _period()
1467 off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs); in _period()
1477 static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned int dry_run, in _loop_cyclic() argument
1507 off += _period(pl330, dry_run, &buf[off], bursts, pxs, ev); in _loop_cyclic()
1516 off += _period(pl330, dry_run, &buf[off], bursts, pxs, ev); in _loop_cyclic()
1527 static inline int _setup_loops(struct pl330_dmac *pl330, in _setup_loops() argument
1548 off += _loop(pl330, dry_run, &buf[off], &c, pxs); in _setup_loops()
1554 off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs); in _setup_loops()
1556 off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs); in _setup_loops()
1561 static inline int _setup_xfer(struct pl330_dmac *pl330, in _setup_xfer() argument
1574 off += _setup_loops(pl330, dry_run, &buf[off], pxs); in _setup_xfer()
1579 static inline int _setup_xfer_cyclic(struct pl330_dmac *pl330, in _setup_xfer_cyclic() argument
1597 off += _loop_cyclic(pl330, dry_run, &buf[off], bursts, pxs, ev); in _setup_xfer_cyclic()
1606 static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run, in _setup_req() argument
1620 off += _setup_xfer(pl330, dry_run, &buf[off], pxs); in _setup_req()
1627 off += _setup_xfer_cyclic(pl330, dry_run, &buf[off], in _setup_req()
1674 struct pl330_dmac *pl330 = thrd->dmac; in pl330_submit_req() local
1695 if (pl330->state == DYING in pl330_submit_req()
1696 || pl330->dmac_tbd.reset_chan & (1 << thrd->id)) { in pl330_submit_req()
1704 desc->peri >= pl330->pcfg.num_peri) { in pl330_submit_req()
1711 spin_lock_irqsave(&pl330->lock, flags); in pl330_submit_req()
1732 ret = _setup_req(pl330, 1, thrd, idx, &xs); in pl330_submit_req()
1736 if (ret > pl330->mcbufsz / 2) { in pl330_submit_req()
1737 dev_info(pl330->ddma.dev, "%s:%d Try increasing mcbufsz (%i/%i)\n", in pl330_submit_req()
1738 __func__, __LINE__, ret, pl330->mcbufsz / 2); in pl330_submit_req()
1746 _setup_req(pl330, 0, thrd, idx, &xs); in pl330_submit_req()
1751 spin_unlock_irqrestore(&pl330->lock, flags); in pl330_submit_req()
1781 struct pl330_dmac *pl330 = from_tasklet(pl330, t, tasks); in pl330_dotask() local
1785 spin_lock_irqsave(&pl330->lock, flags); in pl330_dotask()
1788 if (pl330->dmac_tbd.reset_dmac) { in pl330_dotask()
1789 pl330->state = DYING; in pl330_dotask()
1791 pl330->dmac_tbd.reset_mngr = true; in pl330_dotask()
1793 pl330->dmac_tbd.reset_dmac = false; in pl330_dotask()
1796 if (pl330->dmac_tbd.reset_mngr) { in pl330_dotask()
1797 _stop(pl330->manager); in pl330_dotask()
1799 pl330->dmac_tbd.reset_chan = (1 << pl330->pcfg.num_chan) - 1; in pl330_dotask()
1801 pl330->dmac_tbd.reset_mngr = false; in pl330_dotask()
1804 for (i = 0; i < pl330->pcfg.num_chan; i++) { in pl330_dotask()
1806 if (pl330->dmac_tbd.reset_chan & (1 << i)) { in pl330_dotask()
1807 struct pl330_thread *thrd = &pl330->channels[i]; in pl330_dotask()
1808 void __iomem *regs = pl330->base; in pl330_dotask()
1818 spin_unlock_irqrestore(&pl330->lock, flags); in pl330_dotask()
1821 spin_lock_irqsave(&pl330->lock, flags); in pl330_dotask()
1828 pl330->dmac_tbd.reset_chan &= ~(1 << i); in pl330_dotask()
1832 spin_unlock_irqrestore(&pl330->lock, flags); in pl330_dotask()
1838 static int pl330_update(struct pl330_dmac *pl330) in pl330_update() argument
1846 regs = pl330->base; in pl330_update()
1848 spin_lock_irqsave(&pl330->lock, flags); in pl330_update()
1852 pl330->dmac_tbd.reset_mngr = true; in pl330_update()
1854 pl330->dmac_tbd.reset_mngr = false; in pl330_update()
1856 val = readl(regs + FSC) & ((1 << pl330->pcfg.num_chan) - 1); in pl330_update()
1857 pl330->dmac_tbd.reset_chan |= val; in pl330_update()
1860 while (i < pl330->pcfg.num_chan) { in pl330_update()
1862 dev_info(pl330->ddma.dev, in pl330_update()
1866 _stop(&pl330->channels[i]); in pl330_update()
1874 if (pl330->pcfg.num_events < 32 in pl330_update()
1875 && val & ~((1 << pl330->pcfg.num_events) - 1)) { in pl330_update()
1876 pl330->dmac_tbd.reset_dmac = true; in pl330_update()
1877 dev_err(pl330->ddma.dev, "%s:%d Unexpected!\n", __func__, in pl330_update()
1883 for (ev = 0; ev < pl330->pcfg.num_events; ev++) { in pl330_update()
1895 id = pl330->events[ev]; in pl330_update()
1897 thrd = &pl330->channels[id]; in pl330_update()
1914 list_add_tail(&descdone->rqd, &pl330->req_done); in pl330_update()
1920 while (!list_empty(&pl330->req_done)) { in pl330_update()
1921 descdone = list_first_entry(&pl330->req_done, in pl330_update()
1924 spin_unlock_irqrestore(&pl330->lock, flags); in pl330_update()
1926 spin_lock_irqsave(&pl330->lock, flags); in pl330_update()
1930 spin_unlock_irqrestore(&pl330->lock, flags); in pl330_update()
1932 if (pl330->dmac_tbd.reset_dmac in pl330_update()
1933 || pl330->dmac_tbd.reset_mngr in pl330_update()
1934 || pl330->dmac_tbd.reset_chan) { in pl330_update()
1936 tasklet_schedule(&pl330->tasks); in pl330_update()
1945 struct pl330_dmac *pl330 = thrd->dmac; in _alloc_event() local
1948 for (ev = 0; ev < pl330->pcfg.num_events; ev++) in _alloc_event()
1949 if (pl330->events[ev] == -1) { in _alloc_event()
1950 pl330->events[ev] = thrd->id; in _alloc_event()
1957 static bool _chan_ns(const struct pl330_dmac *pl330, int i) in _chan_ns() argument
1959 return pl330->pcfg.irq_ns & (1 << i); in _chan_ns()
1965 static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330) in pl330_request_channel() argument
1970 if (pl330->state == DYING) in pl330_request_channel()
1973 chans = pl330->pcfg.num_chan; in pl330_request_channel()
1976 thrd = &pl330->channels[i]; in pl330_request_channel()
1978 _chan_ns(pl330, i))) { in pl330_request_channel()
1998 struct pl330_dmac *pl330 = thrd->dmac; in _free_event() local
2001 if (ev >= 0 && ev < pl330->pcfg.num_events in _free_event()
2002 && pl330->events[ev] == thrd->id) in _free_event()
2003 pl330->events[ev] = -1; in _free_event()
2023 static void read_dmac_config(struct pl330_dmac *pl330) in read_dmac_config() argument
2025 void __iomem *regs = pl330->base; in read_dmac_config()
2030 pl330->pcfg.data_bus_width = 8 * (1 << val); in read_dmac_config()
2034 pl330->pcfg.data_buf_dep = val + 1; in read_dmac_config()
2039 pl330->pcfg.num_chan = val; in read_dmac_config()
2045 pl330->pcfg.num_peri = val; in read_dmac_config()
2046 pl330->pcfg.peri_ns = readl(regs + CR4); in read_dmac_config()
2048 pl330->pcfg.num_peri = 0; in read_dmac_config()
2053 pl330->pcfg.mode |= DMAC_MODE_NS; in read_dmac_config()
2055 pl330->pcfg.mode &= ~DMAC_MODE_NS; in read_dmac_config()
2060 pl330->pcfg.num_events = val; in read_dmac_config()
2062 pl330->pcfg.irq_ns = readl(regs + CR3); in read_dmac_config()
2067 struct pl330_dmac *pl330 = thrd->dmac; in _reset_thread() local
2069 thrd->req[0].mc_cpu = pl330->mcode_cpu in _reset_thread()
2070 + (thrd->id * pl330->mcbufsz); in _reset_thread()
2071 thrd->req[0].mc_bus = pl330->mcode_bus in _reset_thread()
2072 + (thrd->id * pl330->mcbufsz); in _reset_thread()
2076 + pl330->mcbufsz / 2; in _reset_thread()
2078 + pl330->mcbufsz / 2; in _reset_thread()
2084 static int dmac_alloc_threads(struct pl330_dmac *pl330) in dmac_alloc_threads() argument
2086 int chans = pl330->pcfg.num_chan; in dmac_alloc_threads()
2091 pl330->channels = kcalloc(1 + chans, sizeof(*thrd), in dmac_alloc_threads()
2093 if (!pl330->channels) in dmac_alloc_threads()
2098 thrd = &pl330->channels[i]; in dmac_alloc_threads()
2100 thrd->dmac = pl330; in dmac_alloc_threads()
2106 thrd = &pl330->channels[chans]; in dmac_alloc_threads()
2108 thrd->dmac = pl330; in dmac_alloc_threads()
2110 pl330->manager = thrd; in dmac_alloc_threads()
2115 static int dmac_alloc_resources(struct pl330_dmac *pl330) in dmac_alloc_resources() argument
2117 int chans = pl330->pcfg.num_chan; in dmac_alloc_resources()
2124 pl330->mcode_cpu = dma_alloc_attrs(pl330->ddma.dev, in dmac_alloc_resources()
2125 chans * pl330->mcbufsz, in dmac_alloc_resources()
2126 &pl330->mcode_bus, GFP_KERNEL, in dmac_alloc_resources()
2128 if (!pl330->mcode_cpu) { in dmac_alloc_resources()
2129 dev_err(pl330->ddma.dev, "%s:%d Can't allocate memory!\n", in dmac_alloc_resources()
2134 ret = dmac_alloc_threads(pl330); in dmac_alloc_resources()
2136 dev_err(pl330->ddma.dev, "%s:%d Can't to create channels for DMAC!\n", in dmac_alloc_resources()
2138 dma_free_attrs(pl330->ddma.dev, in dmac_alloc_resources()
2139 chans * pl330->mcbufsz, in dmac_alloc_resources()
2140 pl330->mcode_cpu, pl330->mcode_bus, in dmac_alloc_resources()
2148 static int pl330_add(struct pl330_dmac *pl330) in pl330_add() argument
2153 if ((pl330->pcfg.periph_id & 0xfffff) != PERIPH_ID_VAL) { in pl330_add()
2154 dev_err(pl330->ddma.dev, "PERIPH_ID 0x%x !\n", in pl330_add()
2155 pl330->pcfg.periph_id); in pl330_add()
2160 read_dmac_config(pl330); in pl330_add()
2162 if (pl330->pcfg.num_events == 0) { in pl330_add()
2163 dev_err(pl330->ddma.dev, "%s:%d Can't work without events!\n", in pl330_add()
2168 spin_lock_init(&pl330->lock); in pl330_add()
2170 INIT_LIST_HEAD(&pl330->req_done); in pl330_add()
2173 if (!pl330->mcbufsz) in pl330_add()
2174 pl330->mcbufsz = MCODE_BUFF_PER_REQ * 2; in pl330_add()
2177 for (i = 0; i < pl330->pcfg.num_events; i++) in pl330_add()
2178 pl330->events[i] = -1; in pl330_add()
2181 ret = dmac_alloc_resources(pl330); in pl330_add()
2183 dev_err(pl330->ddma.dev, "Unable to create channels for DMAC\n"); in pl330_add()
2187 tasklet_setup(&pl330->tasks, pl330_dotask); in pl330_add()
2189 pl330->state = INIT; in pl330_add()
2194 static int dmac_free_threads(struct pl330_dmac *pl330) in dmac_free_threads() argument
2200 for (i = 0; i < pl330->pcfg.num_chan; i++) { in dmac_free_threads()
2201 thrd = &pl330->channels[i]; in dmac_free_threads()
2206 kfree(pl330->channels); in dmac_free_threads()
2211 static void pl330_del(struct pl330_dmac *pl330) in pl330_del() argument
2213 pl330->state = UNINIT; in pl330_del()
2215 tasklet_kill(&pl330->tasks); in pl330_del()
2218 dmac_free_threads(pl330); in pl330_del()
2220 dma_free_attrs(pl330->ddma.dev, in pl330_del()
2221 pl330->pcfg.num_chan * pl330->mcbufsz, pl330->mcode_cpu, in pl330_del()
2222 pl330->mcode_bus, DMA_ATTR_PRIVILEGED); in pl330_del()
2348 struct pl330_dmac *pl330 = ofdma->of_dma_data; in of_dma_pl330_xlate() local
2351 if (!pl330) in of_dma_pl330_xlate()
2358 if (chan_id >= pl330->num_peripherals) in of_dma_pl330_xlate()
2361 return dma_get_slave_channel(&pl330->peripherals[chan_id].chan); in of_dma_pl330_xlate()
2367 struct pl330_dmac *pl330 = pch->dmac; in pl330_alloc_chan_resources() local
2370 spin_lock_irqsave(&pl330->lock, flags); in pl330_alloc_chan_resources()
2374 pch->thread = pl330_request_channel(pl330); in pl330_alloc_chan_resources()
2376 spin_unlock_irqrestore(&pl330->lock, flags); in pl330_alloc_chan_resources()
2382 spin_unlock_irqrestore(&pl330->lock, flags); in pl330_alloc_chan_resources()
2494 struct pl330_dmac *pl330 = pch->dmac; in pl330_terminate_all() local
2497 pm_runtime_get_sync(pl330->ddma.dev); in pl330_terminate_all()
2500 spin_lock(&pl330->lock); in pl330_terminate_all()
2505 spin_unlock(&pl330->lock); in pl330_terminate_all()
2521 list_splice_tail_init(&pch->submitted_list, &pl330->desc_pool); in pl330_terminate_all()
2522 list_splice_tail_init(&pch->work_list, &pl330->desc_pool); in pl330_terminate_all()
2523 list_splice_tail_init(&pch->completed_list, &pl330->desc_pool); in pl330_terminate_all()
2525 pm_runtime_mark_last_busy(pl330->ddma.dev); in pl330_terminate_all()
2527 pm_runtime_put_autosuspend(pl330->ddma.dev); in pl330_terminate_all()
2528 pm_runtime_put_autosuspend(pl330->ddma.dev); in pl330_terminate_all()
2543 struct pl330_dmac *pl330 = pch->dmac; in pl330_pause() local
2546 pm_runtime_get_sync(pl330->ddma.dev); in pl330_pause()
2549 spin_lock(&pl330->lock); in pl330_pause()
2551 spin_unlock(&pl330->lock); in pl330_pause()
2554 pm_runtime_mark_last_busy(pl330->ddma.dev); in pl330_pause()
2555 pm_runtime_put_autosuspend(pl330->ddma.dev); in pl330_pause()
2563 struct pl330_dmac *pl330 = pch->dmac; in pl330_free_chan_resources() local
2569 spin_lock_irqsave(&pl330->lock, flags); in pl330_free_chan_resources()
2576 spin_unlock_irqrestore(&pl330->lock, flags); in pl330_free_chan_resources()
2586 struct pl330_dmac *pl330 = pch->dmac; in pl330_get_current_xferred_count() local
2590 pm_runtime_get_sync(pl330->ddma.dev); in pl330_get_current_xferred_count()
2600 pm_runtime_put_autosuspend(pl330->ddma.dev); in pl330_get_current_xferred_count()
2794 struct pl330_dmac *pl330 = pch->dmac; in pl330_get_desc() local
2799 desc = pluck_desc(&pl330->desc_pool, &pl330->pool_lock); in pl330_get_desc()
2868 struct pl330_dmac *pl330 = pch->dmac; in get_burst_len() local
2871 burst_len = pl330->pcfg.data_bus_width / 8; in get_burst_len()
2872 burst_len *= pl330->pcfg.data_buf_dep / pl330->pcfg.num_chan; in get_burst_len()
2952 struct pl330_dmac *pl330; in pl330_prep_dma_memcpy() local
2958 pl330 = pch->dmac; in pl330_prep_dma_memcpy()
2969 burst = pl330->pcfg.data_bus_width / 8; in pl330_prep_dma_memcpy()
2988 if (burst * 8 < pl330->pcfg.data_bus_width) in pl330_prep_dma_memcpy()
2998 static void __pl330_giveback_desc(struct pl330_dmac *pl330, in __pl330_giveback_desc() argument
3007 spin_lock_irqsave(&pl330->pool_lock, flags); in __pl330_giveback_desc()
3012 list_move_tail(&desc->node, &pl330->desc_pool); in __pl330_giveback_desc()
3015 list_move_tail(&first->node, &pl330->desc_pool); in __pl330_giveback_desc()
3017 spin_unlock_irqrestore(&pl330->pool_lock, flags); in __pl330_giveback_desc()
3044 struct pl330_dmac *pl330 = pch->dmac; in pl330_prep_slave_sg() local
3049 __pl330_giveback_desc(pl330, first); in pl330_prep_slave_sg()
3104 struct pl330_dmac *pl330 = s->private; in pl330_debugfs_show() local
3107 chans = pl330->pcfg.num_chan; in pl330_debugfs_show()
3108 pchs = pl330->num_peripherals; in pl330_debugfs_show()
3114 struct pl330_thread *thrd = &pl330->channels[ch]; in pl330_debugfs_show()
3118 struct dma_pl330_chan *pch = &pl330->peripherals[pr]; in pl330_debugfs_show()
3138 static inline void init_pl330_debugfs(struct pl330_dmac *pl330) in init_pl330_debugfs() argument
3140 debugfs_create_file(dev_name(pl330->ddma.dev), in init_pl330_debugfs()
3141 S_IFREG | 0444, NULL, pl330, in init_pl330_debugfs()
3145 static inline void init_pl330_debugfs(struct pl330_dmac *pl330) in init_pl330_debugfs() argument
3188 struct pl330_dmac *pl330; in pl330_probe() local
3201 pl330 = devm_kzalloc(&adev->dev, sizeof(*pl330), GFP_KERNEL); in pl330_probe()
3202 if (!pl330) in pl330_probe()
3205 pd = &pl330->ddma; in pl330_probe()
3208 pl330->mcbufsz = 0; in pl330_probe()
3213 pl330->quirks |= of_quirks[i].id; in pl330_probe()
3216 pl330->base = devm_ioremap_resource(&adev->dev, res); in pl330_probe()
3217 if (IS_ERR(pl330->base)) in pl330_probe()
3218 return PTR_ERR(pl330->base); in pl330_probe()
3220 amba_set_drvdata(adev, pl330); in pl330_probe()
3222 pl330->rstc = devm_reset_control_get_optional(&adev->dev, "dma"); in pl330_probe()
3223 if (IS_ERR(pl330->rstc)) { in pl330_probe()
3224 return dev_err_probe(&adev->dev, PTR_ERR(pl330->rstc), "Failed to get reset!\n"); in pl330_probe()
3226 ret = reset_control_deassert(pl330->rstc); in pl330_probe()
3233 pl330->rstc_ocp = devm_reset_control_get_optional(&adev->dev, "dma-ocp"); in pl330_probe()
3234 if (IS_ERR(pl330->rstc_ocp)) { in pl330_probe()
3235 return dev_err_probe(&adev->dev, PTR_ERR(pl330->rstc_ocp), in pl330_probe()
3238 ret = reset_control_deassert(pl330->rstc_ocp); in pl330_probe()
3250 dev_name(&adev->dev), pl330); in pl330_probe()
3258 pcfg = &pl330->pcfg; in pl330_probe()
3261 ret = pl330_add(pl330); in pl330_probe()
3265 INIT_LIST_HEAD(&pl330->desc_pool); in pl330_probe()
3266 spin_lock_init(&pl330->pool_lock); in pl330_probe()
3269 if (!add_desc(&pl330->desc_pool, &pl330->pool_lock, in pl330_probe()
3278 pl330->num_peripherals = num_chan; in pl330_probe()
3280 pl330->peripherals = kcalloc(num_chan, sizeof(*pch), GFP_KERNEL); in pl330_probe()
3281 if (!pl330->peripherals) { in pl330_probe()
3287 pch = &pl330->peripherals[i]; in pl330_probe()
3296 pch->dmac = pl330; in pl330_probe()
3334 of_dma_pl330_xlate, pl330); in pl330_probe()
3350 init_pl330_debugfs(pl330); in pl330_probe()
3367 list_for_each_entry_safe(pch, _p, &pl330->ddma.channels, in pl330_probe()
3380 pl330_del(pl330); in pl330_probe()
3382 if (pl330->rstc_ocp) in pl330_probe()
3383 reset_control_assert(pl330->rstc_ocp); in pl330_probe()
3385 if (pl330->rstc) in pl330_probe()
3386 reset_control_assert(pl330->rstc); in pl330_probe()
3392 struct pl330_dmac *pl330 = amba_get_drvdata(adev); in pl330_remove() local
3396 pm_runtime_get_noresume(pl330->ddma.dev); in pl330_remove()
3404 devm_free_irq(&adev->dev, irq, pl330); in pl330_remove()
3407 dma_async_device_unregister(&pl330->ddma); in pl330_remove()
3410 list_for_each_entry_safe(pch, _p, &pl330->ddma.channels, in pl330_remove()
3423 pl330_del(pl330); in pl330_remove()
3425 if (pl330->rstc_ocp) in pl330_remove()
3426 reset_control_assert(pl330->rstc_ocp); in pl330_remove()
3428 if (pl330->rstc) in pl330_remove()
3429 reset_control_assert(pl330->rstc); in pl330_remove()