Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * The driver for Freescale MPC512x LocalPlus Bus FIFO
0004  * (called SCLPC in the Reference Manual).
0005  *
0006  * Copyright (C) 2013-2015 Alexander Popov <alex.popov@linux.com>.
0007  */
0008 
0009 #include <linux/interrupt.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/of.h>
0013 #include <linux/of_platform.h>
0014 #include <linux/of_address.h>
0015 #include <linux/of_irq.h>
0016 #include <asm/mpc5121.h>
0017 #include <asm/io.h>
0018 #include <linux/spinlock.h>
0019 #include <linux/slab.h>
0020 #include <linux/dmaengine.h>
0021 #include <linux/dma-direction.h>
0022 #include <linux/dma-mapping.h>
0023 
0024 #define DRV_NAME "mpc512x_lpbfifo"
0025 
0026 struct cs_range {
0027     u32 csnum;
0028     u32 base; /* must be zero */
0029     u32 addr;
0030     u32 size;
0031 };
0032 
0033 static struct lpbfifo_data {
0034     spinlock_t lock; /* for protecting lpbfifo_data */
0035     phys_addr_t regs_phys;
0036     resource_size_t regs_size;
0037     struct mpc512x_lpbfifo __iomem *regs;
0038     int irq;
0039     struct cs_range *cs_ranges;
0040     size_t cs_n;
0041     struct dma_chan *chan;
0042     struct mpc512x_lpbfifo_request *req;
0043     dma_addr_t ram_bus_addr;
0044     bool wait_lpbfifo_irq;
0045     bool wait_lpbfifo_callback;
0046 } lpbfifo;
0047 
0048 /*
0049  * A data transfer from RAM to some device on LPB is finished
0050  * when both mpc512x_lpbfifo_irq() and mpc512x_lpbfifo_callback()
0051  * have been called. We execute the callback registered in
0052  * mpc512x_lpbfifo_request just after that.
0053  * But for a data transfer from some device on LPB to RAM we don't enable
0054  * LPBFIFO interrupt because clearing MPC512X_SCLPC_SUCCESS interrupt flag
0055  * automatically disables LPBFIFO reading request to the DMA controller
0056  * and the data transfer hangs. So the callback registered in
0057  * mpc512x_lpbfifo_request is executed at the end of mpc512x_lpbfifo_callback().
0058  */
0059 
0060 /*
0061  * mpc512x_lpbfifo_irq - IRQ handler for LPB FIFO
0062  */
0063 static irqreturn_t mpc512x_lpbfifo_irq(int irq, void *param)
0064 {
0065     struct device *dev = (struct device *)param;
0066     struct mpc512x_lpbfifo_request *req = NULL;
0067     unsigned long flags;
0068     u32 status;
0069 
0070     spin_lock_irqsave(&lpbfifo.lock, flags);
0071 
0072     if (!lpbfifo.regs)
0073         goto end;
0074 
0075     req = lpbfifo.req;
0076     if (!req || req->dir == MPC512X_LPBFIFO_REQ_DIR_READ) {
0077         dev_err(dev, "bogus LPBFIFO IRQ\n");
0078         goto end;
0079     }
0080 
0081     status = in_be32(&lpbfifo.regs->status);
0082     if (status != MPC512X_SCLPC_SUCCESS) {
0083         dev_err(dev, "DMA transfer from RAM to peripheral failed\n");
0084         out_be32(&lpbfifo.regs->enable,
0085                 MPC512X_SCLPC_RESET | MPC512X_SCLPC_FIFO_RESET);
0086         goto end;
0087     }
0088     /* Clear the interrupt flag */
0089     out_be32(&lpbfifo.regs->status, MPC512X_SCLPC_SUCCESS);
0090 
0091     lpbfifo.wait_lpbfifo_irq = false;
0092 
0093     if (lpbfifo.wait_lpbfifo_callback)
0094         goto end;
0095 
0096     /* Transfer is finished, set the FIFO as idle */
0097     lpbfifo.req = NULL;
0098 
0099     spin_unlock_irqrestore(&lpbfifo.lock, flags);
0100 
0101     if (req->callback)
0102         req->callback(req);
0103 
0104     return IRQ_HANDLED;
0105 
0106  end:
0107     spin_unlock_irqrestore(&lpbfifo.lock, flags);
0108     return IRQ_HANDLED;
0109 }
0110 
0111 /*
0112  * mpc512x_lpbfifo_callback is called by DMA driver when
0113  * DMA transaction is finished.
0114  */
0115 static void mpc512x_lpbfifo_callback(void *param)
0116 {
0117     unsigned long flags;
0118     struct mpc512x_lpbfifo_request *req = NULL;
0119     enum dma_data_direction dir;
0120 
0121     spin_lock_irqsave(&lpbfifo.lock, flags);
0122 
0123     if (!lpbfifo.regs) {
0124         spin_unlock_irqrestore(&lpbfifo.lock, flags);
0125         return;
0126     }
0127 
0128     req = lpbfifo.req;
0129     if (!req) {
0130         pr_err("bogus LPBFIFO callback\n");
0131         spin_unlock_irqrestore(&lpbfifo.lock, flags);
0132         return;
0133     }
0134 
0135     /* Release the mapping */
0136     if (req->dir == MPC512X_LPBFIFO_REQ_DIR_WRITE)
0137         dir = DMA_TO_DEVICE;
0138     else
0139         dir = DMA_FROM_DEVICE;
0140     dma_unmap_single(lpbfifo.chan->device->dev,
0141             lpbfifo.ram_bus_addr, req->size, dir);
0142 
0143     lpbfifo.wait_lpbfifo_callback = false;
0144 
0145     if (!lpbfifo.wait_lpbfifo_irq) {
0146         /* Transfer is finished, set the FIFO as idle */
0147         lpbfifo.req = NULL;
0148 
0149         spin_unlock_irqrestore(&lpbfifo.lock, flags);
0150 
0151         if (req->callback)
0152             req->callback(req);
0153     } else {
0154         spin_unlock_irqrestore(&lpbfifo.lock, flags);
0155     }
0156 }
0157 
0158 static int mpc512x_lpbfifo_kick(void)
0159 {
0160     u32 bits;
0161     bool no_incr = false;
0162     u32 bpt = 32; /* max bytes per LPBFIFO transaction involving DMA */
0163     u32 cs = 0;
0164     size_t i;
0165     struct dma_device *dma_dev = NULL;
0166     struct scatterlist sg;
0167     enum dma_data_direction dir;
0168     struct dma_slave_config dma_conf = {};
0169     struct dma_async_tx_descriptor *dma_tx = NULL;
0170     dma_cookie_t cookie;
0171     int ret;
0172 
0173     /*
0174      * 1. Fit the requirements:
0175      * - the packet size must be a multiple of 4 since FIFO Data Word
0176      *    Register allows only full-word access according the Reference
0177      *    Manual;
0178      * - the physical address of the device on LPB and the packet size
0179      *    must be aligned on BPT (bytes per transaction) or 8-bytes
0180      *    boundary according the Reference Manual;
0181      * - but we choose DMA maxburst equal (or very close to) BPT to prevent
0182      *    DMA controller from overtaking FIFO and causing FIFO underflow
0183      *    error. So we force the packet size to be aligned on BPT boundary
0184      *    not to confuse DMA driver which requires the packet size to be
0185      *    aligned on maxburst boundary;
0186      * - BPT should be set to the LPB device port size for operation with
0187      *    disabled auto-incrementing according Reference Manual.
0188      */
0189     if (lpbfifo.req->size == 0 || !IS_ALIGNED(lpbfifo.req->size, 4))
0190         return -EINVAL;
0191 
0192     if (lpbfifo.req->portsize != LPB_DEV_PORTSIZE_UNDEFINED) {
0193         bpt = lpbfifo.req->portsize;
0194         no_incr = true;
0195     }
0196 
0197     while (bpt > 1) {
0198         if (IS_ALIGNED(lpbfifo.req->dev_phys_addr, min(bpt, 0x8u)) &&
0199                     IS_ALIGNED(lpbfifo.req->size, bpt)) {
0200             break;
0201         }
0202 
0203         if (no_incr)
0204             return -EINVAL;
0205 
0206         bpt >>= 1;
0207     }
0208     dma_conf.dst_maxburst = max(bpt, 0x4u) / 4;
0209     dma_conf.src_maxburst = max(bpt, 0x4u) / 4;
0210 
0211     for (i = 0; i < lpbfifo.cs_n; i++) {
0212         phys_addr_t cs_start = lpbfifo.cs_ranges[i].addr;
0213         phys_addr_t cs_end = cs_start + lpbfifo.cs_ranges[i].size;
0214         phys_addr_t access_start = lpbfifo.req->dev_phys_addr;
0215         phys_addr_t access_end = access_start + lpbfifo.req->size;
0216 
0217         if (access_start >= cs_start && access_end <= cs_end) {
0218             cs = lpbfifo.cs_ranges[i].csnum;
0219             break;
0220         }
0221     }
0222     if (i == lpbfifo.cs_n)
0223         return -EFAULT;
0224 
0225     /* 2. Prepare DMA */
0226     dma_dev = lpbfifo.chan->device;
0227 
0228     if (lpbfifo.req->dir == MPC512X_LPBFIFO_REQ_DIR_WRITE) {
0229         dir = DMA_TO_DEVICE;
0230         dma_conf.direction = DMA_MEM_TO_DEV;
0231         dma_conf.dst_addr = lpbfifo.regs_phys +
0232                 offsetof(struct mpc512x_lpbfifo, data_word);
0233     } else {
0234         dir = DMA_FROM_DEVICE;
0235         dma_conf.direction = DMA_DEV_TO_MEM;
0236         dma_conf.src_addr = lpbfifo.regs_phys +
0237                 offsetof(struct mpc512x_lpbfifo, data_word);
0238     }
0239     dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
0240     dma_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
0241 
0242     /* Make DMA channel work with LPB FIFO data register */
0243     if (dma_dev->device_config(lpbfifo.chan, &dma_conf)) {
0244         ret = -EINVAL;
0245         goto err_dma_prep;
0246     }
0247 
0248     sg_init_table(&sg, 1);
0249 
0250     sg_dma_address(&sg) = dma_map_single(dma_dev->dev,
0251             lpbfifo.req->ram_virt_addr, lpbfifo.req->size, dir);
0252     if (dma_mapping_error(dma_dev->dev, sg_dma_address(&sg)))
0253         return -EFAULT;
0254 
0255     lpbfifo.ram_bus_addr = sg_dma_address(&sg); /* For freeing later */
0256 
0257     sg_dma_len(&sg) = lpbfifo.req->size;
0258 
0259     dma_tx = dmaengine_prep_slave_sg(lpbfifo.chan, &sg,
0260                         1, dma_conf.direction, 0);
0261     if (!dma_tx) {
0262         ret = -ENOSPC;
0263         goto err_dma_prep;
0264     }
0265     dma_tx->callback = mpc512x_lpbfifo_callback;
0266     dma_tx->callback_param = NULL;
0267 
0268     /* 3. Prepare FIFO */
0269     out_be32(&lpbfifo.regs->enable,
0270                 MPC512X_SCLPC_RESET | MPC512X_SCLPC_FIFO_RESET);
0271     out_be32(&lpbfifo.regs->enable, 0x0);
0272 
0273     /*
0274      * Configure the watermarks for write operation (RAM->DMA->FIFO->dev):
0275      * - high watermark 7 words according the Reference Manual,
0276      * - low watermark 512 bytes (half of the FIFO).
0277      * These watermarks don't work for read operation since the
0278      * MPC512X_SCLPC_FLUSH bit is set (according the Reference Manual).
0279      */
0280     out_be32(&lpbfifo.regs->fifo_ctrl, MPC512X_SCLPC_FIFO_CTRL(0x7));
0281     out_be32(&lpbfifo.regs->fifo_alarm, MPC512X_SCLPC_FIFO_ALARM(0x200));
0282 
0283     /*
0284      * Start address is a physical address of the region which belongs
0285      * to the device on the LocalPlus Bus
0286      */
0287     out_be32(&lpbfifo.regs->start_addr, lpbfifo.req->dev_phys_addr);
0288 
0289     /*
0290      * Configure chip select, transfer direction, address increment option
0291      * and bytes per transaction option
0292      */
0293     bits = MPC512X_SCLPC_CS(cs);
0294     if (lpbfifo.req->dir == MPC512X_LPBFIFO_REQ_DIR_READ)
0295         bits |= MPC512X_SCLPC_READ | MPC512X_SCLPC_FLUSH;
0296     if (no_incr)
0297         bits |= MPC512X_SCLPC_DAI;
0298     bits |= MPC512X_SCLPC_BPT(bpt);
0299     out_be32(&lpbfifo.regs->ctrl, bits);
0300 
0301     /* Unmask irqs */
0302     bits = MPC512X_SCLPC_ENABLE | MPC512X_SCLPC_ABORT_INT_ENABLE;
0303     if (lpbfifo.req->dir == MPC512X_LPBFIFO_REQ_DIR_WRITE)
0304         bits |= MPC512X_SCLPC_NORM_INT_ENABLE;
0305     else
0306         lpbfifo.wait_lpbfifo_irq = false;
0307 
0308     out_be32(&lpbfifo.regs->enable, bits);
0309 
0310     /* 4. Set packet size and kick FIFO off */
0311     bits = lpbfifo.req->size | MPC512X_SCLPC_START;
0312     out_be32(&lpbfifo.regs->pkt_size, bits);
0313 
0314     /* 5. Finally kick DMA off */
0315     cookie = dma_tx->tx_submit(dma_tx);
0316     if (dma_submit_error(cookie)) {
0317         ret = -ENOSPC;
0318         goto err_dma_submit;
0319     }
0320 
0321     return 0;
0322 
0323  err_dma_submit:
0324     out_be32(&lpbfifo.regs->enable,
0325                 MPC512X_SCLPC_RESET | MPC512X_SCLPC_FIFO_RESET);
0326  err_dma_prep:
0327     dma_unmap_single(dma_dev->dev, sg_dma_address(&sg),
0328                         lpbfifo.req->size, dir);
0329     return ret;
0330 }
0331 
0332 static int mpc512x_lpbfifo_submit_locked(struct mpc512x_lpbfifo_request *req)
0333 {
0334     int ret = 0;
0335 
0336     if (!lpbfifo.regs)
0337         return -ENODEV;
0338 
0339     /* Check whether a transfer is in progress */
0340     if (lpbfifo.req)
0341         return -EBUSY;
0342 
0343     lpbfifo.wait_lpbfifo_irq = true;
0344     lpbfifo.wait_lpbfifo_callback = true;
0345     lpbfifo.req = req;
0346 
0347     ret = mpc512x_lpbfifo_kick();
0348     if (ret != 0)
0349         lpbfifo.req = NULL; /* Set the FIFO as idle */
0350 
0351     return ret;
0352 }
0353 
0354 int mpc512x_lpbfifo_submit(struct mpc512x_lpbfifo_request *req)
0355 {
0356     unsigned long flags;
0357     int ret = 0;
0358 
0359     spin_lock_irqsave(&lpbfifo.lock, flags);
0360     ret = mpc512x_lpbfifo_submit_locked(req);
0361     spin_unlock_irqrestore(&lpbfifo.lock, flags);
0362 
0363     return ret;
0364 }
0365 EXPORT_SYMBOL(mpc512x_lpbfifo_submit);
0366 
0367 /*
0368  * LPBFIFO driver uses "ranges" property of "localbus" device tree node
0369  * for being able to determine the chip select number of a client device
0370  * ordering a DMA transfer.
0371  */
0372 static int get_cs_ranges(struct device *dev)
0373 {
0374     int ret = -ENODEV;
0375     struct device_node *lb_node;
0376     const u32 *addr_cells_p;
0377     const u32 *size_cells_p;
0378     int proplen;
0379     size_t i;
0380 
0381     lb_node = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-localbus");
0382     if (!lb_node)
0383         return ret;
0384 
0385     /*
0386      * The node defined as compatible with 'fsl,mpc5121-localbus'
0387      * should have two address cells and one size cell.
0388      * Every item of its ranges property should consist of:
0389      * - the first address cell which is the chipselect number;
0390      * - the second address cell which is the offset in the chipselect,
0391      *    must be zero.
0392      * - CPU address of the beginning of an access window;
0393      * - the only size cell which is the size of an access window.
0394      */
0395     addr_cells_p = of_get_property(lb_node, "#address-cells", NULL);
0396     size_cells_p = of_get_property(lb_node, "#size-cells", NULL);
0397     if (addr_cells_p == NULL || *addr_cells_p != 2 ||
0398                 size_cells_p == NULL || *size_cells_p != 1) {
0399         goto end;
0400     }
0401 
0402     proplen = of_property_count_u32_elems(lb_node, "ranges");
0403     if (proplen <= 0 || proplen % 4 != 0)
0404         goto end;
0405 
0406     lpbfifo.cs_n = proplen / 4;
0407     lpbfifo.cs_ranges = devm_kcalloc(dev, lpbfifo.cs_n,
0408                     sizeof(struct cs_range), GFP_KERNEL);
0409     if (!lpbfifo.cs_ranges)
0410         goto end;
0411 
0412     if (of_property_read_u32_array(lb_node, "ranges",
0413                 (u32 *)lpbfifo.cs_ranges, proplen) != 0) {
0414         goto end;
0415     }
0416 
0417     for (i = 0; i < lpbfifo.cs_n; i++) {
0418         if (lpbfifo.cs_ranges[i].base != 0)
0419             goto end;
0420     }
0421 
0422     ret = 0;
0423 
0424  end:
0425     of_node_put(lb_node);
0426     return ret;
0427 }
0428 
0429 static int mpc512x_lpbfifo_probe(struct platform_device *pdev)
0430 {
0431     struct resource r;
0432     int ret = 0;
0433 
0434     memset(&lpbfifo, 0, sizeof(struct lpbfifo_data));
0435     spin_lock_init(&lpbfifo.lock);
0436 
0437     lpbfifo.chan = dma_request_chan(&pdev->dev, "rx-tx");
0438     if (IS_ERR(lpbfifo.chan))
0439         return PTR_ERR(lpbfifo.chan);
0440 
0441     if (of_address_to_resource(pdev->dev.of_node, 0, &r) != 0) {
0442         dev_err(&pdev->dev, "bad 'reg' in 'sclpc' device tree node\n");
0443         ret = -ENODEV;
0444         goto err0;
0445     }
0446 
0447     lpbfifo.regs_phys = r.start;
0448     lpbfifo.regs_size = resource_size(&r);
0449 
0450     if (!devm_request_mem_region(&pdev->dev, lpbfifo.regs_phys,
0451                     lpbfifo.regs_size, DRV_NAME)) {
0452         dev_err(&pdev->dev, "unable to request region\n");
0453         ret = -EBUSY;
0454         goto err0;
0455     }
0456 
0457     lpbfifo.regs = devm_ioremap(&pdev->dev,
0458                     lpbfifo.regs_phys, lpbfifo.regs_size);
0459     if (!lpbfifo.regs) {
0460         dev_err(&pdev->dev, "mapping registers failed\n");
0461         ret = -ENOMEM;
0462         goto err0;
0463     }
0464 
0465     out_be32(&lpbfifo.regs->enable,
0466                 MPC512X_SCLPC_RESET | MPC512X_SCLPC_FIFO_RESET);
0467 
0468     if (get_cs_ranges(&pdev->dev) != 0) {
0469         dev_err(&pdev->dev, "bad '/localbus' device tree node\n");
0470         ret = -ENODEV;
0471         goto err0;
0472     }
0473 
0474     lpbfifo.irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
0475     if (!lpbfifo.irq) {
0476         dev_err(&pdev->dev, "mapping irq failed\n");
0477         ret = -ENODEV;
0478         goto err0;
0479     }
0480 
0481     if (request_irq(lpbfifo.irq, mpc512x_lpbfifo_irq, 0,
0482                         DRV_NAME, &pdev->dev) != 0) {
0483         dev_err(&pdev->dev, "requesting irq failed\n");
0484         ret = -ENODEV;
0485         goto err1;
0486     }
0487 
0488     dev_info(&pdev->dev, "probe succeeded\n");
0489     return 0;
0490 
0491  err1:
0492     irq_dispose_mapping(lpbfifo.irq);
0493  err0:
0494     dma_release_channel(lpbfifo.chan);
0495     return ret;
0496 }
0497 
0498 static int mpc512x_lpbfifo_remove(struct platform_device *pdev)
0499 {
0500     unsigned long flags;
0501     struct dma_device *dma_dev = lpbfifo.chan->device;
0502     struct mpc512x_lpbfifo __iomem *regs = NULL;
0503 
0504     spin_lock_irqsave(&lpbfifo.lock, flags);
0505     regs = lpbfifo.regs;
0506     lpbfifo.regs = NULL;
0507     spin_unlock_irqrestore(&lpbfifo.lock, flags);
0508 
0509     dma_dev->device_terminate_all(lpbfifo.chan);
0510     out_be32(&regs->enable, MPC512X_SCLPC_RESET | MPC512X_SCLPC_FIFO_RESET);
0511 
0512     free_irq(lpbfifo.irq, &pdev->dev);
0513     irq_dispose_mapping(lpbfifo.irq);
0514     dma_release_channel(lpbfifo.chan);
0515 
0516     return 0;
0517 }
0518 
0519 static const struct of_device_id mpc512x_lpbfifo_match[] = {
0520     { .compatible = "fsl,mpc512x-lpbfifo", },
0521     {},
0522 };
0523 MODULE_DEVICE_TABLE(of, mpc512x_lpbfifo_match);
0524 
0525 static struct platform_driver mpc512x_lpbfifo_driver = {
0526     .probe = mpc512x_lpbfifo_probe,
0527     .remove = mpc512x_lpbfifo_remove,
0528     .driver = {
0529         .name = DRV_NAME,
0530         .of_match_table = mpc512x_lpbfifo_match,
0531     },
0532 };
0533 
0534 module_platform_driver(mpc512x_lpbfifo_driver);
0535 
0536 MODULE_AUTHOR("Alexander Popov <alex.popov@linux.com>");
0537 MODULE_DESCRIPTION("MPC512x LocalPlus Bus FIFO device driver");
0538 MODULE_LICENSE("GPL v2");