| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2015-2016 Marvell International Ltd. |
|---|
| 3 | 4 | |
|---|
| 4 | | - * This program is free software: you can redistribute it and/or |
|---|
| 5 | | - * modify it under the terms of the GNU General Public License as |
|---|
| 6 | | - * published by the Free Software Foundation, either version 2 of the |
|---|
| 7 | | - * License, or any later version. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is distributed in the hope that it will be useful, but |
|---|
| 10 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|---|
| 12 | | - * General Public License for more details. |
|---|
| 13 | 5 | */ |
|---|
| 14 | 6 | |
|---|
| 15 | 7 | #include <linux/clk.h> |
|---|
| .. | .. |
|---|
| 41 | 33 | #define MV_XOR_V2_DMA_IMSG_CDAT_OFF 0x014 |
|---|
| 42 | 34 | #define MV_XOR_V2_DMA_IMSG_THRD_OFF 0x018 |
|---|
| 43 | 35 | #define MV_XOR_V2_DMA_IMSG_THRD_MASK 0x7FFF |
|---|
| 44 | | -#define MV_XOR_V2_DMA_IMSG_THRD_SHIFT 0x0 |
|---|
| 45 | 36 | #define MV_XOR_V2_DMA_IMSG_TIMER_EN BIT(18) |
|---|
| 46 | 37 | #define MV_XOR_V2_DMA_DESQ_AWATTR_OFF 0x01C |
|---|
| 47 | 38 | /* Same flags as MV_XOR_V2_DMA_DESQ_ARATTR_OFF */ |
|---|
| .. | .. |
|---|
| 58 | 49 | #define MV_XOR_V2_DMA_DESQ_ADD_OFF 0x808 |
|---|
| 59 | 50 | #define MV_XOR_V2_DMA_IMSG_TMOT 0x810 |
|---|
| 60 | 51 | #define MV_XOR_V2_DMA_IMSG_TIMER_THRD_MASK 0x1FFF |
|---|
| 61 | | -#define MV_XOR_V2_DMA_IMSG_TIMER_THRD_SHIFT 0 |
|---|
| 62 | 52 | |
|---|
| 63 | 53 | /* XOR Global registers */ |
|---|
| 64 | 54 | #define MV_XOR_V2_GLOB_BW_CTRL 0x4 |
|---|
| .. | .. |
|---|
| 145 | 135 | /** |
|---|
| 146 | 136 | * struct mv_xor_v2_device - implements a xor device |
|---|
| 147 | 137 | * @lock: lock for the engine |
|---|
| 138 | + * @clk: reference to the 'core' clock |
|---|
| 139 | + * @reg_clk: reference to the 'reg' clock |
|---|
| 148 | 140 | * @dma_base: memory mapped DMA register base |
|---|
| 149 | 141 | * @glob_base: memory mapped global register base |
|---|
| 150 | | - * @irq_tasklet: |
|---|
| 142 | + * @irq_tasklet: tasklet used for IRQ handling call-backs |
|---|
| 151 | 143 | * @free_sw_desc: linked list of free SW descriptors |
|---|
| 152 | 144 | * @dmadev: dma device |
|---|
| 153 | 145 | * @dmachan: dma channel |
|---|
| .. | .. |
|---|
| 156 | 148 | * @sw_desq: SW descriptors queue |
|---|
| 157 | 149 | * @desc_size: HW descriptor size |
|---|
| 158 | 150 | * @npendings: number of pending descriptors (for which tx_submit has |
|---|
| 151 | + * @hw_queue_idx: HW queue index |
|---|
| 152 | + * @msi_desc: local interrupt descriptor information |
|---|
| 159 | 153 | * been called, but not yet issue_pending) |
|---|
| 160 | 154 | */ |
|---|
| 161 | 155 | struct mv_xor_v2_device { |
|---|
| .. | .. |
|---|
| 269 | 263 | |
|---|
| 270 | 264 | /* Configure threshold of number of descriptors, and enable timer */ |
|---|
| 271 | 265 | reg = readl(xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_THRD_OFF); |
|---|
| 272 | | - reg &= (~MV_XOR_V2_DMA_IMSG_THRD_MASK << MV_XOR_V2_DMA_IMSG_THRD_SHIFT); |
|---|
| 273 | | - reg |= (MV_XOR_V2_DONE_IMSG_THRD << MV_XOR_V2_DMA_IMSG_THRD_SHIFT); |
|---|
| 266 | + reg &= ~MV_XOR_V2_DMA_IMSG_THRD_MASK; |
|---|
| 267 | + reg |= MV_XOR_V2_DONE_IMSG_THRD; |
|---|
| 274 | 268 | reg |= MV_XOR_V2_DMA_IMSG_TIMER_EN; |
|---|
| 275 | 269 | writel(reg, xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_THRD_OFF); |
|---|
| 276 | 270 | |
|---|
| 277 | 271 | /* Configure Timer Threshold */ |
|---|
| 278 | 272 | reg = readl(xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_TMOT); |
|---|
| 279 | | - reg &= (~MV_XOR_V2_DMA_IMSG_TIMER_THRD_MASK << |
|---|
| 280 | | - MV_XOR_V2_DMA_IMSG_TIMER_THRD_SHIFT); |
|---|
| 281 | | - reg |= (MV_XOR_V2_TIMER_THRD << MV_XOR_V2_DMA_IMSG_TIMER_THRD_SHIFT); |
|---|
| 273 | + reg &= ~MV_XOR_V2_DMA_IMSG_TIMER_THRD_MASK; |
|---|
| 274 | + reg |= MV_XOR_V2_TIMER_THRD; |
|---|
| 282 | 275 | writel(reg, xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_TMOT); |
|---|
| 283 | 276 | } |
|---|
| 284 | 277 | |
|---|
| .. | .. |
|---|
| 560 | 553 | /* |
|---|
| 561 | 554 | * handle the descriptors after HW process |
|---|
| 562 | 555 | */ |
|---|
| 563 | | -static void mv_xor_v2_tasklet(unsigned long data) |
|---|
| 556 | +static void mv_xor_v2_tasklet(struct tasklet_struct *t) |
|---|
| 564 | 557 | { |
|---|
| 565 | | - struct mv_xor_v2_device *xor_dev = (struct mv_xor_v2_device *) data; |
|---|
| 558 | + struct mv_xor_v2_device *xor_dev = from_tasklet(xor_dev, t, |
|---|
| 559 | + irq_tasklet); |
|---|
| 566 | 560 | int pending_ptr, num_of_pending, i; |
|---|
| 567 | 561 | struct mv_xor_v2_sw_desc *next_pending_sw_desc = NULL; |
|---|
| 568 | 562 | |
|---|
| .. | .. |
|---|
| 761 | 755 | } |
|---|
| 762 | 756 | |
|---|
| 763 | 757 | xor_dev->clk = devm_clk_get(&pdev->dev, NULL); |
|---|
| 764 | | - if (IS_ERR(xor_dev->clk) && PTR_ERR(xor_dev->clk) == -EPROBE_DEFER) { |
|---|
| 758 | + if (PTR_ERR(xor_dev->clk) == -EPROBE_DEFER) { |
|---|
| 765 | 759 | ret = EPROBE_DEFER; |
|---|
| 766 | 760 | goto disable_reg_clk; |
|---|
| 767 | 761 | } |
|---|
| .. | .. |
|---|
| 789 | 783 | if (ret) |
|---|
| 790 | 784 | goto free_msi_irqs; |
|---|
| 791 | 785 | |
|---|
| 792 | | - tasklet_init(&xor_dev->irq_tasklet, mv_xor_v2_tasklet, |
|---|
| 793 | | - (unsigned long) xor_dev); |
|---|
| 786 | + tasklet_setup(&xor_dev->irq_tasklet, mv_xor_v2_tasklet); |
|---|
| 794 | 787 | |
|---|
| 795 | 788 | xor_dev->desc_size = mv_xor_v2_set_desc_size(xor_dev); |
|---|
| 796 | 789 | |
|---|
| .. | .. |
|---|
| 906 | 899 | tasklet_kill(&xor_dev->irq_tasklet); |
|---|
| 907 | 900 | |
|---|
| 908 | 901 | clk_disable_unprepare(xor_dev->clk); |
|---|
| 902 | + clk_disable_unprepare(xor_dev->reg_clk); |
|---|
| 909 | 903 | |
|---|
| 910 | 904 | return 0; |
|---|
| 911 | 905 | } |
|---|