Path: blob/master/drivers/dma/loongson/loongson2-apb-dma.c
170890 views
// SPDX-License-Identifier: GPL-2.0-or-later1/*2* Driver for the Loongson-2 APB DMA Controller3*4* Copyright (C) 2017-2023 Loongson Corporation5*/67#include <linux/clk.h>8#include <linux/dma-mapping.h>9#include <linux/dmapool.h>10#include <linux/interrupt.h>11#include <linux/io.h>12#include <linux/io-64-nonatomic-lo-hi.h>13#include <linux/module.h>14#include <linux/of.h>15#include <linux/of_dma.h>16#include <linux/platform_device.h>17#include <linux/slab.h>1819#include "../dmaengine.h"20#include "../virt-dma.h"2122/* Global Configuration Register */23#define LDMA_ORDER_ERG 0x02425/* Bitfield definitions */2627/* Bitfields in Global Configuration Register */28#define LDMA_64BIT_EN BIT(0) /* 1: 64 bit support */29#define LDMA_UNCOHERENT_EN BIT(1) /* 0: cache, 1: uncache */30#define LDMA_ASK_VALID BIT(2)31#define LDMA_START BIT(3) /* DMA start operation */32#define LDMA_STOP BIT(4) /* DMA stop operation */33#define LDMA_CONFIG_MASK GENMASK_ULL(4, 0) /* DMA controller config bits mask */3435/* Bitfields in ndesc_addr field of HW descriptor */36#define LDMA_DESC_EN BIT(0) /*1: The next descriptor is valid */37#define LDMA_DESC_ADDR_LOW GENMASK(31, 1)3839/* Bitfields in cmd field of HW descriptor */40#define LDMA_INT BIT(1) /* Enable DMA interrupts */41#define LDMA_DATA_DIRECTION BIT(12) /* 1: write to device, 0: read from device */4243#define LDMA_SLAVE_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \44BIT(DMA_SLAVE_BUSWIDTH_8_BYTES))4546#define LDMA_MAX_TRANS_LEN U32_MAX4748/*-- descriptors -----------------------------------------------------*/4950/*51* struct ls2x_dma_hw_desc - DMA HW descriptor52* @ndesc_addr: the next descriptor low address.53* @mem_addr: memory low address.54* @apb_addr: device buffer address.55* @len: length of a piece of carried content, in words.56* @step_len: length between two moved memory data blocks.57* @step_times: number of blocks to be carried in a single DMA operation.58* @cmd: descriptor command or state.59* @stats: DMA status.60* @high_ndesc_addr: the next descriptor high address.61* @high_mem_addr: memory high address.62* @reserved: reserved63*/64struct ls2x_dma_hw_desc {65u32 ndesc_addr;66u32 mem_addr;67u32 apb_addr;68u32 len;69u32 step_len;70u32 step_times;71u32 cmd;72u32 stats;73u32 high_ndesc_addr;74u32 high_mem_addr;75u32 reserved[2];76} __packed;7778/*79* struct ls2x_dma_sg - ls2x dma scatter gather entry80* @hw: the pointer to DMA HW descriptor.81* @llp: physical address of the DMA HW descriptor.82* @phys: destination or source address(mem).83* @len: number of Bytes to read.84*/85struct ls2x_dma_sg {86struct ls2x_dma_hw_desc *hw;87dma_addr_t llp;88dma_addr_t phys;89u32 len;90};9192/*93* struct ls2x_dma_desc - software descriptor94* @vdesc: pointer to the virtual dma descriptor.95* @cyclic: flag to dma cyclic96* @burst_size: burst size of transaction, in words.97* @desc_num: number of sg entries.98* @direction: transfer direction, to or from device.99* @status: dma controller status.100* @sg: array of sgs.101*/102struct ls2x_dma_desc {103struct virt_dma_desc vdesc;104bool cyclic;105size_t burst_size;106u32 desc_num;107enum dma_transfer_direction direction;108enum dma_status status;109struct ls2x_dma_sg sg[] __counted_by(desc_num);110};111112/*-- Channels --------------------------------------------------------*/113114/*115* struct ls2x_dma_chan - internal representation of an LS2X APB DMA channel116* @vchan: virtual dma channel entry.117* @desc: pointer to the ls2x sw dma descriptor.118* @pool: hw desc table119* @irq: irq line120* @sconfig: configuration for slave transfers, passed via .device_config121*/122struct ls2x_dma_chan {123struct virt_dma_chan vchan;124struct ls2x_dma_desc *desc;125void *pool;126int irq;127struct dma_slave_config sconfig;128};129130/*-- Controller ------------------------------------------------------*/131132/*133* struct ls2x_dma_priv - LS2X APB DMAC specific information134* @ddev: dmaengine dma_device object members135* @dma_clk: DMAC clock source136* @regs: memory mapped register base137* @lchan: channel to store ls2x_dma_chan structures138*/139struct ls2x_dma_priv {140struct dma_device ddev;141struct clk *dma_clk;142void __iomem *regs;143struct ls2x_dma_chan lchan;144};145146/*-- Helper functions ------------------------------------------------*/147148static inline struct ls2x_dma_desc *to_ldma_desc(struct virt_dma_desc *vdesc)149{150return container_of(vdesc, struct ls2x_dma_desc, vdesc);151}152153static inline struct ls2x_dma_chan *to_ldma_chan(struct dma_chan *chan)154{155return container_of(chan, struct ls2x_dma_chan, vchan.chan);156}157158static inline struct ls2x_dma_priv *to_ldma_priv(struct dma_device *ddev)159{160return container_of(ddev, struct ls2x_dma_priv, ddev);161}162163static struct device *chan2dev(struct dma_chan *chan)164{165return &chan->dev->device;166}167168static void ls2x_dma_desc_free(struct virt_dma_desc *vdesc)169{170struct ls2x_dma_chan *lchan = to_ldma_chan(vdesc->tx.chan);171struct ls2x_dma_desc *desc = to_ldma_desc(vdesc);172int i;173174for (i = 0; i < desc->desc_num; i++) {175if (desc->sg[i].hw)176dma_pool_free(lchan->pool, desc->sg[i].hw,177desc->sg[i].llp);178}179180kfree(desc);181}182183static void ls2x_dma_write_cmd(struct ls2x_dma_chan *lchan, bool cmd)184{185struct ls2x_dma_priv *priv = to_ldma_priv(lchan->vchan.chan.device);186u64 val;187188val = lo_hi_readq(priv->regs + LDMA_ORDER_ERG) & ~LDMA_CONFIG_MASK;189val |= LDMA_64BIT_EN | cmd;190lo_hi_writeq(val, priv->regs + LDMA_ORDER_ERG);191}192193static void ls2x_dma_start_transfer(struct ls2x_dma_chan *lchan)194{195struct ls2x_dma_priv *priv = to_ldma_priv(lchan->vchan.chan.device);196struct ls2x_dma_sg *ldma_sg;197struct virt_dma_desc *vdesc;198u64 val;199200/* Get the next descriptor */201vdesc = vchan_next_desc(&lchan->vchan);202if (!vdesc) {203lchan->desc = NULL;204return;205}206207list_del(&vdesc->node);208lchan->desc = to_ldma_desc(vdesc);209ldma_sg = &lchan->desc->sg[0];210211/* Start DMA */212lo_hi_writeq(0, priv->regs + LDMA_ORDER_ERG);213val = (ldma_sg->llp & ~LDMA_CONFIG_MASK) | LDMA_64BIT_EN | LDMA_START;214lo_hi_writeq(val, priv->regs + LDMA_ORDER_ERG);215}216217static size_t ls2x_dmac_detect_burst(struct ls2x_dma_chan *lchan)218{219u32 maxburst, buswidth;220221/* Reject definitely invalid configurations */222if ((lchan->sconfig.src_addr_width & LDMA_SLAVE_BUSWIDTHS) &&223(lchan->sconfig.dst_addr_width & LDMA_SLAVE_BUSWIDTHS))224return 0;225226if (lchan->sconfig.direction == DMA_MEM_TO_DEV) {227maxburst = lchan->sconfig.dst_maxburst;228buswidth = lchan->sconfig.dst_addr_width;229} else {230maxburst = lchan->sconfig.src_maxburst;231buswidth = lchan->sconfig.src_addr_width;232}233234/* If maxburst is zero, fallback to LDMA_MAX_TRANS_LEN */235return maxburst ? (maxburst * buswidth) >> 2 : LDMA_MAX_TRANS_LEN;236}237238static void ls2x_dma_fill_desc(struct ls2x_dma_chan *lchan, u32 sg_index,239struct ls2x_dma_desc *desc)240{241struct ls2x_dma_sg *ldma_sg = &desc->sg[sg_index];242u32 num_segments, segment_size;243244if (desc->direction == DMA_MEM_TO_DEV) {245ldma_sg->hw->cmd = LDMA_INT | LDMA_DATA_DIRECTION;246ldma_sg->hw->apb_addr = lchan->sconfig.dst_addr;247} else {248ldma_sg->hw->cmd = LDMA_INT;249ldma_sg->hw->apb_addr = lchan->sconfig.src_addr;250}251252ldma_sg->hw->mem_addr = lower_32_bits(ldma_sg->phys);253ldma_sg->hw->high_mem_addr = upper_32_bits(ldma_sg->phys);254255/* Split into multiple equally sized segments if necessary */256num_segments = DIV_ROUND_UP((ldma_sg->len + 3) >> 2, desc->burst_size);257segment_size = DIV_ROUND_UP((ldma_sg->len + 3) >> 2, num_segments);258259/* Word count register takes input in words */260ldma_sg->hw->len = segment_size;261ldma_sg->hw->step_times = num_segments;262ldma_sg->hw->step_len = 0;263264/* lets make a link list */265if (sg_index) {266desc->sg[sg_index - 1].hw->ndesc_addr = ldma_sg->llp | LDMA_DESC_EN;267desc->sg[sg_index - 1].hw->high_ndesc_addr = upper_32_bits(ldma_sg->llp);268}269}270271/*-- DMA Engine API --------------------------------------------------*/272273/*274* ls2x_dma_alloc_chan_resources - allocate resources for DMA channel275* @chan: allocate descriptor resources for this channel276*277* return - the number of allocated descriptors278*/279static int ls2x_dma_alloc_chan_resources(struct dma_chan *chan)280{281struct ls2x_dma_chan *lchan = to_ldma_chan(chan);282283/* Create a pool of consistent memory blocks for hardware descriptors */284lchan->pool = dma_pool_create(dev_name(chan2dev(chan)),285chan->device->dev, PAGE_SIZE,286__alignof__(struct ls2x_dma_hw_desc), 0);287if (!lchan->pool) {288dev_err(chan2dev(chan), "No memory for descriptors\n");289return -ENOMEM;290}291292return 1;293}294295/*296* ls2x_dma_free_chan_resources - free all channel resources297* @chan: DMA channel298*/299static void ls2x_dma_free_chan_resources(struct dma_chan *chan)300{301struct ls2x_dma_chan *lchan = to_ldma_chan(chan);302303vchan_free_chan_resources(to_virt_chan(chan));304dma_pool_destroy(lchan->pool);305lchan->pool = NULL;306}307308/*309* ls2x_dma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction310* @chan: DMA channel311* @sgl: scatterlist to transfer to/from312* @sg_len: number of entries in @scatterlist313* @direction: DMA direction314* @flags: tx descriptor status flags315* @context: transaction context (ignored)316*317* Return: Async transaction descriptor on success and NULL on failure318*/319static struct dma_async_tx_descriptor *320ls2x_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,321u32 sg_len, enum dma_transfer_direction direction,322unsigned long flags, void *context)323{324struct ls2x_dma_chan *lchan = to_ldma_chan(chan);325struct ls2x_dma_desc *desc;326struct scatterlist *sg;327size_t burst_size;328int i;329330if (unlikely(!sg_len || !is_slave_direction(direction)))331return NULL;332333burst_size = ls2x_dmac_detect_burst(lchan);334if (!burst_size)335return NULL;336337desc = kzalloc_flex(*desc, sg, sg_len, GFP_NOWAIT);338if (!desc)339return NULL;340341desc->desc_num = sg_len;342desc->direction = direction;343desc->burst_size = burst_size;344345for_each_sg(sgl, sg, sg_len, i) {346struct ls2x_dma_sg *ldma_sg = &desc->sg[i];347348/* Allocate DMA capable memory for hardware descriptor */349ldma_sg->hw = dma_pool_alloc(lchan->pool, GFP_NOWAIT, &ldma_sg->llp);350if (!ldma_sg->hw) {351desc->desc_num = i;352ls2x_dma_desc_free(&desc->vdesc);353return NULL;354}355356ldma_sg->phys = sg_dma_address(sg);357ldma_sg->len = sg_dma_len(sg);358359ls2x_dma_fill_desc(lchan, i, desc);360}361362/* Setting the last descriptor enable bit */363desc->sg[sg_len - 1].hw->ndesc_addr &= ~LDMA_DESC_EN;364desc->status = DMA_IN_PROGRESS;365366return vchan_tx_prep(&lchan->vchan, &desc->vdesc, flags);367}368369/*370* ls2x_dma_prep_dma_cyclic - prepare the cyclic DMA transfer371* @chan: the DMA channel to prepare372* @buf_addr: physical DMA address where the buffer starts373* @buf_len: total number of bytes for the entire buffer374* @period_len: number of bytes for each period375* @direction: transfer direction, to or from device376* @flags: tx descriptor status flags377*378* Return: Async transaction descriptor on success and NULL on failure379*/380static struct dma_async_tx_descriptor *381ls2x_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,382size_t period_len, enum dma_transfer_direction direction,383unsigned long flags)384{385struct ls2x_dma_chan *lchan = to_ldma_chan(chan);386struct ls2x_dma_desc *desc;387size_t burst_size;388u32 num_periods;389int i;390391if (unlikely(!buf_len || !period_len))392return NULL;393394if (unlikely(!is_slave_direction(direction)))395return NULL;396397burst_size = ls2x_dmac_detect_burst(lchan);398if (!burst_size)399return NULL;400401num_periods = buf_len / period_len;402desc = kzalloc_flex(*desc, sg, num_periods, GFP_NOWAIT);403if (!desc)404return NULL;405406desc->desc_num = num_periods;407desc->direction = direction;408desc->burst_size = burst_size;409410/* Build cyclic linked list */411for (i = 0; i < num_periods; i++) {412struct ls2x_dma_sg *ldma_sg = &desc->sg[i];413414/* Allocate DMA capable memory for hardware descriptor */415ldma_sg->hw = dma_pool_alloc(lchan->pool, GFP_NOWAIT, &ldma_sg->llp);416if (!ldma_sg->hw) {417desc->desc_num = i;418ls2x_dma_desc_free(&desc->vdesc);419return NULL;420}421422ldma_sg->phys = buf_addr + period_len * i;423ldma_sg->len = period_len;424425ls2x_dma_fill_desc(lchan, i, desc);426}427428/* Lets make a cyclic list */429desc->sg[num_periods - 1].hw->ndesc_addr = desc->sg[0].llp | LDMA_DESC_EN;430desc->sg[num_periods - 1].hw->high_ndesc_addr = upper_32_bits(desc->sg[0].llp);431desc->cyclic = true;432desc->status = DMA_IN_PROGRESS;433434return vchan_tx_prep(&lchan->vchan, &desc->vdesc, flags);435}436437/*438* ls2x_slave_config - set slave configuration for channel439* @chan: dma channel440* @cfg: slave configuration441*442* Sets slave configuration for channel443*/444static int ls2x_dma_slave_config(struct dma_chan *chan,445struct dma_slave_config *config)446{447struct ls2x_dma_chan *lchan = to_ldma_chan(chan);448449memcpy(&lchan->sconfig, config, sizeof(*config));450return 0;451}452453/*454* ls2x_dma_issue_pending - push pending transactions to the hardware455* @chan: channel456*457* When this function is called, all pending transactions are pushed to the458* hardware and executed.459*/460static void ls2x_dma_issue_pending(struct dma_chan *chan)461{462struct ls2x_dma_chan *lchan = to_ldma_chan(chan);463464guard(spinlock_irqsave)(&lchan->vchan.lock);465466if (vchan_issue_pending(&lchan->vchan) && !lchan->desc)467ls2x_dma_start_transfer(lchan);468}469470/*471* ls2x_dma_terminate_all - terminate all transactions472* @chan: channel473*474* Stops all DMA transactions.475*/476static int ls2x_dma_terminate_all(struct dma_chan *chan)477{478struct ls2x_dma_chan *lchan = to_ldma_chan(chan);479LIST_HEAD(head);480481scoped_guard(spinlock_irqsave, &lchan->vchan.lock) {482/* Setting stop cmd */483ls2x_dma_write_cmd(lchan, LDMA_STOP);484if (lchan->desc) {485vchan_terminate_vdesc(&lchan->desc->vdesc);486lchan->desc = NULL;487}488489vchan_get_all_descriptors(&lchan->vchan, &head);490}491492vchan_dma_desc_free_list(&lchan->vchan, &head);493return 0;494}495496/*497* ls2x_dma_synchronize - Synchronizes the termination of transfers to the498* current context.499* @chan: channel500*/501static void ls2x_dma_synchronize(struct dma_chan *chan)502{503struct ls2x_dma_chan *lchan = to_ldma_chan(chan);504505vchan_synchronize(&lchan->vchan);506}507508static int ls2x_dma_pause(struct dma_chan *chan)509{510struct ls2x_dma_chan *lchan = to_ldma_chan(chan);511512guard(spinlock_irqsave)(&lchan->vchan.lock);513514if (lchan->desc && lchan->desc->status == DMA_IN_PROGRESS) {515ls2x_dma_write_cmd(lchan, LDMA_STOP);516lchan->desc->status = DMA_PAUSED;517}518519return 0;520}521522static int ls2x_dma_resume(struct dma_chan *chan)523{524struct ls2x_dma_chan *lchan = to_ldma_chan(chan);525526guard(spinlock_irqsave)(&lchan->vchan.lock);527528if (lchan->desc && lchan->desc->status == DMA_PAUSED) {529lchan->desc->status = DMA_IN_PROGRESS;530ls2x_dma_write_cmd(lchan, LDMA_START);531}532533return 0;534}535536/*537* ls2x_dma_isr - LS2X DMA Interrupt handler538* @irq: IRQ number539* @dev_id: Pointer to ls2x_dma_chan540*541* Return: IRQ_HANDLED/IRQ_NONE542*/543static irqreturn_t ls2x_dma_isr(int irq, void *dev_id)544{545struct ls2x_dma_chan *lchan = dev_id;546struct ls2x_dma_desc *desc;547548scoped_guard(spinlock, &lchan->vchan.lock) {549desc = lchan->desc;550if (desc) {551if (desc->cyclic) {552vchan_cyclic_callback(&desc->vdesc);553} else {554desc->status = DMA_COMPLETE;555vchan_cookie_complete(&desc->vdesc);556ls2x_dma_start_transfer(lchan);557}558559/* ls2x_dma_start_transfer() updates lchan->desc */560if (!lchan->desc)561ls2x_dma_write_cmd(lchan, LDMA_STOP);562}563}564565return IRQ_HANDLED;566}567568static int ls2x_dma_chan_init(struct platform_device *pdev,569struct ls2x_dma_priv *priv)570{571struct ls2x_dma_chan *lchan = &priv->lchan;572struct device *dev = &pdev->dev;573int ret;574575lchan->irq = platform_get_irq(pdev, 0);576if (lchan->irq < 0)577return lchan->irq;578579ret = devm_request_irq(dev, lchan->irq, ls2x_dma_isr, IRQF_TRIGGER_RISING,580dev_name(&pdev->dev), lchan);581if (ret)582return ret;583584/* Initialize channels related values */585INIT_LIST_HEAD(&priv->ddev.channels);586lchan->vchan.desc_free = ls2x_dma_desc_free;587vchan_init(&lchan->vchan, &priv->ddev);588589return 0;590}591592/*593* ls2x_dma_probe - Driver probe function594* @pdev: Pointer to the platform_device structure595*596* Return: '0' on success and failure value on error597*/598static int ls2x_dma_probe(struct platform_device *pdev)599{600struct device *dev = &pdev->dev;601struct ls2x_dma_priv *priv;602struct dma_device *ddev;603int ret;604605priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);606if (!priv)607return -ENOMEM;608609priv->regs = devm_platform_ioremap_resource(pdev, 0);610if (IS_ERR(priv->regs))611return dev_err_probe(dev, PTR_ERR(priv->regs),612"devm_platform_ioremap_resource failed.\n");613614priv->dma_clk = devm_clk_get_enabled(dev, NULL);615if (IS_ERR(priv->dma_clk))616return dev_err_probe(dev, PTR_ERR(priv->dma_clk), "Couldn't start the clock.\n");617618ret = ls2x_dma_chan_init(pdev, priv);619if (ret)620return ret;621622ddev = &priv->ddev;623ddev->dev = dev;624dma_cap_zero(ddev->cap_mask);625dma_cap_set(DMA_SLAVE, ddev->cap_mask);626dma_cap_set(DMA_CYCLIC, ddev->cap_mask);627628ddev->device_alloc_chan_resources = ls2x_dma_alloc_chan_resources;629ddev->device_free_chan_resources = ls2x_dma_free_chan_resources;630ddev->device_tx_status = dma_cookie_status;631ddev->device_issue_pending = ls2x_dma_issue_pending;632ddev->device_prep_slave_sg = ls2x_dma_prep_slave_sg;633ddev->device_prep_dma_cyclic = ls2x_dma_prep_dma_cyclic;634ddev->device_config = ls2x_dma_slave_config;635ddev->device_terminate_all = ls2x_dma_terminate_all;636ddev->device_synchronize = ls2x_dma_synchronize;637ddev->device_pause = ls2x_dma_pause;638ddev->device_resume = ls2x_dma_resume;639640ddev->src_addr_widths = LDMA_SLAVE_BUSWIDTHS;641ddev->dst_addr_widths = LDMA_SLAVE_BUSWIDTHS;642ddev->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);643644ret = dmaenginem_async_device_register(&priv->ddev);645if (ret < 0)646return dev_err_probe(dev, ret, "Failed to register DMA engine device.\n");647648ret = of_dma_controller_register(dev->of_node, of_dma_xlate_by_chan_id, priv);649if (ret < 0)650return dev_err_probe(dev, ret, "Failed to register dma controller.\n");651652platform_set_drvdata(pdev, priv);653654dev_info(dev, "Loongson LS2X APB DMA driver registered successfully.\n");655return 0;656}657658/*659* ls2x_dma_remove - Driver remove function660* @pdev: Pointer to the platform_device structure661*/662static void ls2x_dma_remove(struct platform_device *pdev)663{664of_dma_controller_free(pdev->dev.of_node);665}666667static const struct of_device_id ls2x_dma_of_match_table[] = {668{ .compatible = "loongson,ls2k1000-apbdma" },669{ /* sentinel */ }670};671MODULE_DEVICE_TABLE(of, ls2x_dma_of_match_table);672673static struct platform_driver ls2x_dmac_driver = {674.probe = ls2x_dma_probe,675.remove = ls2x_dma_remove,676.driver = {677.name = "ls2x-apbdma",678.of_match_table = ls2x_dma_of_match_table,679},680};681module_platform_driver(ls2x_dmac_driver);682683MODULE_DESCRIPTION("Loongson-2 APB DMA Controller driver");684MODULE_AUTHOR("Loongson Technology Corporation Limited");685MODULE_LICENSE("GPL");686687688