| .. | .. | 
|---|
|  | 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) { | 
|---|
| 765 |  | -		ret = EPROBE_DEFER; | 
|---|
|  | 758 | +	if (PTR_ERR(xor_dev->clk) == -EPROBE_DEFER) { | 
|---|
|  | 759 | +		ret = -EPROBE_DEFER; | 
|---|
| 766 | 760 | goto disable_reg_clk; | 
|---|
| 767 | 761 | } | 
|---|
| 768 | 762 | if (!IS_ERR(xor_dev->clk)) { | 
|---|
| .. | .. | 
|---|
| 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 | } | 
|---|