};
sec_dma: sec_dma@16008000 {
- compatible = "starfive,jh7110-pl080", "arm,pl080";
+ compatible = "arm,pl080", "arm,primecell";
+ arm,primecell-periphid = <0x00041080>;
reg = <0x0 0x16008000 0x0 0x4000>;
reg-names = "sec_dma";
interrupts = <29>;
clocks = <&clkgen JH7110_SEC_HCLK>,
<&clkgen JH7110_SEC_MISCAHB_CLK>;
- clock-names = "sec_hclk","sec_ahb";
+ clock-names = "sec_hclk","apb_pclk";
resets = <&rstgen RSTN_U0_SEC_TOP_HRESETN>;
reset-names = "sec_hre";
lli-bus-interface-ahb1;
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
+#include <linux/amba/pl080.h>
#include <crypto/hash.h>
#include <crypto/gcm.h>
#include <crypto/internal/hash.h>
#include <crypto/internal/skcipher.h>
-#include "jh7110-pl080.h"
#include "jh7110-str.h"
/* Mode mask = bits [3..0] */
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright 2021 StarFive, Inc <huan.feng@starfivetech.com>
- *
- * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING
- * CUSTOMERS WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER
- * FOR THEM TO SAVE TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE
- * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY
- * CLAIMS ARISING FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE
- * BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONNECTION
- * WITH THEIR PRODUCTS.
- */
-#include <linux/clk.h>
-#include <linux/crypto.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/reset.h>
-#include <linux/dma-direct.h>
-#include <crypto/scatterwalk.h>
-
-#include "jh7110-pl080.h"
-#include "jh7110-str.h"
-
-static volatile u32 g_dmac_done;
-static volatile u32 g_dmac_err;
-struct jh7110_pl080_lli_build_data *bd;
-
-/* Maximum times we call dma_pool_alloc on this pool without freeing */
-#define MAX_NUM_TSFR_LLIS 512
-
-static inline int jh7110_dma_wait_done(struct jh7110_sec_dev *sdev, int chan)
-{
- int ret = -1;
-
- mutex_lock(&sdev->pl080_doing);
- if (g_dmac_done & BIT(chan))
- ret = 0;
- mutex_unlock(&sdev->pl080_doing);
-
- return ret;
-}
-
-static inline int jh7110_dmac_channel_wait_busy(struct jh7110_sec_dev *sdev, u8 chan)
-{
- u32 status;
-
- return readl_relaxed_poll_timeout(sdev->pl080->phy_chans[chan].base + PL080_CH_CONFIG, status,
- !(status & PL080_CONFIG_ACTIVE), 10, 100000);
-}
-
-static irqreturn_t jh7110_pl080_irq_thread(int irq, void *arg)
-{
- struct jh7110_sec_dev *sdev = (struct jh7110_sec_dev *) arg;
-
- pr_debug("this is debug mutex_unlock doing ---------------- %s %s %d\n", __FILE__, __func__, __LINE__);
- mutex_unlock(&sdev->pl080_doing);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t jh7110_pl080_irq(int irq, void *dev)
-{
- struct jh7110_sec_dev *sdev = (struct jh7110_sec_dev *) dev;
- u32 err, tc, i;
-
- /* check & clear - ERR & TC interrupts */
- err = readl_relaxed(sdev->dma_base + PL080_ERR_STATUS);
- if (err) {
- pr_err("%s error interrupt, register value 0x%08x\n",
- __func__, err);
- writel_relaxed(err, sdev->dma_base + PL080_ERR_CLEAR);
- }
- tc = readl_relaxed(sdev->dma_base + PL080_TC_STATUS);
- if (tc)
- writel_relaxed(tc, sdev->dma_base + PL080_TC_CLEAR);
-
- if (!err && !tc)
- return IRQ_NONE;
-
- for (i = 0; i < PL080_CHANNELS_NUM; i++) {
- if (BIT(i) & err)
- g_dmac_err |= BIT(i);
- if (BIT(i) & tc)
- g_dmac_done |= BIT(i);
- }
-
- return IRQ_WAKE_THREAD;
-}
-
-static int jh7110_dmac_enable(struct jh7110_sec_dev *sdev)
-{
- writel_relaxed(PL080_CONFIG_ENABLE, sdev->dma_base + PL080_CONFIG);
-
- return 0;
-}
-
-static int jh7110_dmac_disable(struct jh7110_sec_dev *sdev)
-{
- writel_relaxed(0, sdev->dma_base + PL080_CONFIG);
- return 0;
-}
-
-static int jh7110_dmac_channel_enable(struct jh7110_sec_dev *sdev, u8 chan)
-{
- u32 control;
-
- control = readl_relaxed(sdev->pl080->phy_chans[chan].base + PL080_CH_CONFIG);
- control |= PL080_CONFIG_ENABLE;
- writel_relaxed(control, sdev->pl080->phy_chans[chan].base + PL080_CH_CONFIG);
-
- return 0;
-}
-
-static int jh7110_dmac_channel_disable(struct jh7110_sec_dev *sdev, u8 chan)
-{
- u32 control;
-
- control = readl_relaxed(sdev->pl080->phy_chans[chan].base + PL080_CH_CONFIG);
- control &= (~PL080_CONFIG_ENABLE);
- writel_relaxed(control, sdev->pl080->phy_chans[chan].base + PL080_CH_CONFIG);
-
- return 0;
-}
-
-static int jh7110_dmac_channel_halt(struct jh7110_sec_dev *sdev, u8 chan)
-{
- u32 val;
-
- val = readl_relaxed(sdev->pl080->phy_chans[chan].base + PL080_CH_CONFIG);
- val |= PL080_CONFIG_HALT;
- writel_relaxed(val, sdev->pl080->phy_chans[chan].base + PL080_CH_CONFIG);
-
- return 0;
-}
-
-static int jh7110_dmac_channel_resume(struct jh7110_sec_dev *sdev, u8 chan)
-{
- u32 val;
-
- val = readl_relaxed(sdev->pl080->phy_chans[chan].base + PL080_CH_CONFIG);
- val &= (~PL080_CONFIG_HALT);
- writel_relaxed(val, sdev->pl080->phy_chans[chan].base + PL080_CH_CONFIG);
-
- return 0;
-}
-
-static void jh7110_dmac_interrupt_enable(struct jh7110_sec_dev *sdev, u8 chan)
-{
- u32 val;
-
- val = readl_relaxed(sdev->pl080->phy_chans[chan].base + PL080_CH_CONFIG);
- val |= PL080_CONFIG_TC_IRQ_MASK | PL080_CONFIG_ERR_IRQ_MASK;
- writel_relaxed(val, sdev->pl080->phy_chans[chan].base + PL080_CH_CONFIG);
-}
-
-static void jh7110_dmac_interrupt_disable(struct jh7110_sec_dev *sdev, u8 chan)
-{
- u32 val;
-
- val = readl_relaxed(sdev->pl080->phy_chans[chan].base + PL080_CH_CONFIG);
- val &= ~(PL080_CONFIG_TC_IRQ_MASK | PL080_CONFIG_ERR_IRQ_MASK);
- writel_relaxed(val, sdev->pl080->phy_chans[chan].base + PL080_CH_CONFIG);
-}
-
-static u32 jh7110_dmac_cctl_bits(struct jh7110_pl080_chan_config *config, u32 tsize)
-{
- u32 cctl = 0;
-
- if (config->src_width == PL08X_BUS_WIDTH_16_BITS)
- tsize >>= 1;
- else if (config->src_width == PL08X_BUS_WIDTH_32_BITS)
- tsize >>= 2;
-
- cctl = (1 << PL080_CONTROL_PROT_SYS) | (config->di<<27) | (config->si<<26) | (config->dst_ahb << 25)
- | (config->src_ahb << 24) | (config->dst_width << 21) | (config->src_width << 18) | (config->dst_bsize<<15)
- | (config->src_bsize<<12) | tsize;
- return cctl;
-}
-
-static int jh7110_dmac_fill_llis(struct jh7110_pl080_lli_build_data *bd, int num_llis,
- struct jh7110_pl080_chan_config *config)
-{
- u32 cctl;
- u32 llis_addr = bd->llis_phy_addr;
- struct jh7110_pl080_lli *llis = bd->llis;
-
- cctl = jh7110_dmac_cctl_bits(config, bd->tsize);
-
- llis[num_llis].control0 = cctl;
- llis[num_llis].src_addr = bd->src_addr;
- llis[num_llis].dst_addr = bd->dst_addr;
- llis[num_llis].next_lli = llis_addr + (num_llis + 1) * sizeof(struct jh7110_pl080_lli);
-
- bd->remainder -= bd->tsize;
- if (bd->remainder == 0) {
- llis[num_llis].next_lli = 0;
- llis[num_llis].control0 |= PL080_CONTROL_TC_IRQ_EN;
- }
-
- return 0;
-}
-
-static int jh7110_dmac_llis_prep(struct jh7110_pl080_lli_build_data *bd, struct jh7110_pl080_chan_config *config)
-{
- u32 llisize;
- u32 buswidth, width;
- u32 max_bytes_per_lli, tsize;
- u32 src_tsize, dst_tsize;
- u32 num_llis = 0;
-
- bd->src_addr = config->src_addr;
- bd->dst_addr = config->dst_addr;
- bd->remainder = config->xfer_size;
-
- buswidth = min(config->src_width, config->dst_width);
- switch (buswidth) {
- case PL08X_BUS_WIDTH_8_BITS:
- width = 1;
- break;
- case PL08X_BUS_WIDTH_16_BITS:
- width = 2;
- break;
- case PL08X_BUS_WIDTH_32_BITS:
- width = 4;
- break;
- default:
- break;
- }
- max_bytes_per_lli = width * PL080_CONTROL_TRANSFER_SIZE_MASK;
- tsize = max_bytes_per_lli;
- llisize = bd->remainder % tsize;
- if (llisize == 0)
- llisize = bd->remainder / tsize;
- else
- llisize = (bd->remainder / tsize) + 1;
-
- if (llisize > MAX_NUM_TSFR_LLIS)
- return -1;
-
- llisize += 1;
-
- bd->llis = kmalloc(llisize * sizeof(struct jh7110_pl080_lli), GFP_KERNEL);
- if (bd->llis == NULL)
- return -1;
- memset(bd->llis, 0, llisize * sizeof(struct jh7110_pl080_lli));
- bd->llis_phy_addr = (u32)bd->llis;
-
- while (1) {
- if (!bd->remainder)
- break;
-
- if (bd->remainder > tsize)
- bd->tsize = tsize;
- else
- bd->tsize = bd->remainder;
-
- jh7110_dmac_fill_llis(bd, num_llis++, config);
-
- if (config->si)
- bd->src_addr += bd->tsize;
- if (config->di)
- bd->dst_addr += bd->tsize;
- }
- config->src_addr = bd->src_addr;
- config->dst_addr = bd->dst_addr;
-
- return 0;
-}
-
-/*dmac_setup_xfer support dma link item*/
-int jh7110_dmac_setup_xfer(struct jh7110_sec_dev *sdev, u8 chan, struct jh7110_pl080_chan_config *config)
-{
- u32 val;
- struct jh7110_pl080_lli *lli = NULL;
-
- bd = kmalloc(sizeof(struct jh7110_pl080_lli_build_data), GFP_KERNEL);
- if (bd == NULL)
- return -1;
-
- memset(bd, 0, sizeof(struct jh7110_pl080_lli_build_data));
- jh7110_dmac_llis_prep(bd, config);
- lli = &bd->llis[0];
-
- writel_relaxed(lli->src_addr, sdev->pl080->phy_chans[chan].base + PL080_CH_SRC_ADDR);
- writel_relaxed(lli->dst_addr, sdev->pl080->phy_chans[chan].base + PL080_CH_DST_ADDR);
- writel_relaxed(lli->next_lli, sdev->pl080->phy_chans[chan].base + PL080_CH_LLI);
- writel_relaxed(lli->control0, sdev->pl080->phy_chans[chan].base + PL080_CH_CONTROL);
-
- val = (config->flow << 11)|(config->src_peri<<1)|(config->dst_peri<<6);
-
- writel_relaxed(val, sdev->pl080->phy_chans[chan].base + PL080_CH_CONFIG);
-
- jh7110_dmac_interrupt_enable(sdev, chan);
-
- g_dmac_done &= ~BIT(chan);
- g_dmac_err &= ~BIT(chan);
-
-
- if (chan)
- mutex_lock(&sdev->pl080_doing);
-
- return 0;
-}
-
-void jh7110_dmac_free_llis(void)
-{
- if (bd) {
- kfree(bd->llis);
- kfree(bd);
- bd = NULL;
- }
-}
-
-int jh7110_dmac_wait_done(struct jh7110_sec_dev *sdev, u8 chan)
-{
- if (jh7110_dma_wait_done(sdev, chan)) {
- pr_debug("this is debug for lophyel status = %x err = %x control0 = %x control1 = %x %s %s %d\n",
- readl_relaxed(sdev->dma_base + PL080_TC_STATUS), readl_relaxed(sdev->dma_base + PL080_ERR_STATUS),
- readl_relaxed(sdev->dma_base + 0x10c), readl_relaxed(sdev->dma_base + 0x12c),
- __FILE__, __func__, __LINE__);
-
- return -1;
- }
-
- g_dmac_done &= ~BIT(chan);
- jh7110_dmac_free_llis();
-
- return 0;
-}
-
-int jh7110_dmac_secdata_in(struct jh7110_sec_dev *sdev, u8 chan, u32 src, u32 dst, u32 size)
-{
- struct jh7110_pl080_chan_config config;
- int ret;
-
- config.si = PL08X_INCREMENT;
- config.di = PL08X_INCREMENT_FIX;
- config.src_ahb = PL08X_AHB1;
- config.dst_ahb = PL08X_AHB2;
- config.src_width = PL08X_BUS_WIDTH_32_BITS;
- config.dst_width = PL08X_BUS_WIDTH_32_BITS;
- config.src_bsize = PL08X_BURST_SZ_32;
- config.dst_bsize = PL08X_BURST_SZ_32;
- config.src_peri = 1;
- config.dst_peri = 1;
- config.src_addr = src;
- config.dst_addr = dst;
- config.xfer_size = size;
- config.flow = PL080_FLOW_MEM2PER;
-
- if (jh7110_dmac_channel_wait_busy(sdev, chan))
- return -ETIMEDOUT;
-
- ret = jh7110_dmac_setup_xfer(sdev, chan, &config);
- if (ret != 0)
- return ret;
-
- jh7110_dmac_channel_enable(sdev, chan);
-
- return 0;
-}
-
-int jh7110_dmac_secdata_out(struct jh7110_sec_dev *sdev, u8 chan, u32 src, u32 dst, u32 size)
-{
- struct jh7110_pl080_chan_config config;
- int ret;
-
- config.si = PL08X_INCREMENT_FIX;
- config.di = PL08X_INCREMENT;
- config.src_ahb = PL08X_AHB2;
- config.dst_ahb = PL08X_AHB1;
- config.src_width = PL08X_BUS_WIDTH_32_BITS;
- config.dst_width = PL08X_BUS_WIDTH_32_BITS;
- config.src_bsize = PL08X_BURST_SZ_4;//follow hardware limit
- config.dst_bsize = PL08X_BURST_SZ_4;
- config.src_peri = 0;
- config.dst_peri = 0;
- config.src_addr = src;
- config.dst_addr = dst;
- config.xfer_size = size;
- config.flow = PL080_FLOW_PER2MEM;
-
- if (jh7110_dmac_channel_wait_busy(sdev, chan))
- return -ETIMEDOUT;
-
- ret = jh7110_dmac_setup_xfer(sdev, chan, &config);
- if (ret != 0)
- return ret;
-
- jh7110_dmac_channel_enable(sdev, chan);
-
- return 0;
-}
-
-int jh7110_dmac_init(struct jh7110_sec_dev *sdev, int irq)
-{
- int chan;
- int ret;
-
- ret = devm_request_threaded_irq(sdev->dev, irq, jh7110_pl080_irq,
- jh7110_pl080_irq_thread, 0,
- dev_name(sdev->dev), sdev);
- if (ret) {
- dev_err(sdev->dev, "Can't get interrupt working.\n");
- return ret;
- }
-
- sdev->pl080 = kmalloc(sizeof(struct jh7110_pl08x_device), GFP_KERNEL);
- if (!sdev->pl080)
- return -ENOMEM;
-
- memset(sdev->pl080, 0, sizeof(struct jh7110_pl08x_device));
-
- for (chan = 0; chan < PL080_CHANNELS_NUM; chan++) {
- struct jh7110_pl08x_phy_chan *ch = &sdev->pl080->phy_chans[chan];
-
- ch->id = chan;
- ch->base = sdev->dma_base + PL080_Cx_BASE(chan);
- ch->reg_config = ch->base + PL080_CH_CONFIG;
- ch->reg_control = ch->base + PL080_CH_CONTROL;
- ch->reg_src = ch->base + PL080_CH_SRC_ADDR;
- ch->reg_dst = ch->base + PL080_CH_DST_ADDR;
- ch->reg_lli = ch->base + PL080_CH_LLI;
- }
-
- jh7110_dmac_enable(sdev);
- g_dmac_done = 0;
- g_dmac_err = 0;
-
- return 0;
-}
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0
- *
- * Copyright 2021 StarFive, Inc <huan.feng@starfivetech.com>
- */
-
-
-#ifndef __JH7110_PL080_H__
-#define __JH7110_PL080_H__
-
-#define PL080_INT_STATUS (0x00)
-#define PL080_TC_STATUS (0x04)
-#define PL080_TC_CLEAR (0x08)
-#define PL080_ERR_STATUS (0x0C)
-#define PL080_ERR_CLEAR (0x10)
-#define PL080_RAW_TC_STATUS (0x14)
-#define PL080_RAW_ERR_STATUS (0x18)
-#define PL080_EN_CHAN (0x1c)
-#define PL080_SOFT_BREQ (0x20)
-#define PL080_SOFT_SREQ (0x24)
-#define PL080_SOFT_LBREQ (0x28)
-#define PL080_SOFT_LSREQ (0x2C)
-#define PL080_CONFIG (0x30)
-#define PL080_CONFIG_M2_BE BIT(2)
-#define PL080_CONFIG_M1_BE BIT(1)
-#define PL080_CONFIG_ENABLE BIT(0)
-#define PL080_SYNC (0x34)
-
-/* Per channel configuration registers */
-#define PL080_Cx_BASE(x) ((0x100 + (x * 0x20)))
-#define PL080_CH_SRC_ADDR (0x00)
-#define PL080_CH_DST_ADDR (0x04)
-#define PL080_CH_LLI (0x08)
-#define PL080_CH_CONTROL (0x0C)
-#define PL080_CH_CONFIG (0x10)
-#define PL080S_CH_CONTROL2 (0x10)
-#define PL080S_CH_CONFIG (0x14)
-
-#define PL080_LLI_ADDR_SHIFT (2)
-#define PL080_CONTROL_PROT_SHIFT (28)
-#define PL080_CONTROL_DWIDTH_SHIFT (21)
-#define PL080_CONTROL_SWIDTH_SHIFT (18)
-#define PL080_CONTROL_DB_SIZE_SHIFT (15)
-#define PL080_CONTROL_SB_SIZE_SHIFT (12)
-#define PL080_CONTROL_TRANSFER_SIZE_SHIFT (0)
-
-#define PL080_LLI_LM_AHB2 BIT(0)
-#define PL080_CONTROL_TC_IRQ_EN BIT(31)
-#define PL080_CONTROL_PROT_CACHE BIT(30)
-#define PL080_CONTROL_PROT_BUFF BIT(29)
-#define PL080_CONTROL_PROT_SYS BIT(28)
-#define PL080_CONTROL_DST_INCR BIT(27)
-#define PL080_CONTROL_SRC_INCR BIT(26)
-#define PL080_CONTROL_DST_AHB2 BIT(25)
-#define PL080_CONTROL_SRC_AHB2 BIT(24)
-
-#define PL080_CONTROL_TRANSFER_SIZE_MASK (0xfff<<0)
-#define PL080N_CONFIG_ITPROT BIT(20)
-#define PL080N_CONFIG_SECPROT BIT(19)
-#define PL080_CONFIG_HALT BIT(18)
-#define PL080_CONFIG_ACTIVE BIT(17) /* RO */
-#define PL080_CONFIG_LOCK BIT(16)
-#define PL080_CONFIG_TC_IRQ_MASK BIT(15)
-#define PL080_CONFIG_ERR_IRQ_MASK BIT(14)
-#define PL080_CONFIG_ENABLE BIT(0)
-
-#define PL080_CONFIG_FLOW_CONTROL_SHIFT (11)
-#define PL080_CONFIG_DST_SEL_SHIFT (6)
-#define PL080_CONFIG_SRC_SEL_SHIFT (1)
-
-#define PL080_CONFIG_FLOW_CONTROL_MASK GENMASK(13, 11)
-#define PL080_CONFIG_DST_SEL_MASK GENMASK(9, 6)
-#define PL080_CONFIG_SRC_SEL_MASK GENMASK(4, 1)
-
-
-#define PL080_CHANNELS_NUM (8)
-#define PL080_SIGNAL_NUM (16)
-
-/* Bitmasks for selecting AHB ports for DMA transfers */
-enum jh7110_pl08x_ahb_master {
- PL08X_AHB1 = (0 << 0),
- PL08X_AHB2 = (1 << 0)
-};
-
-enum jh7110_pl08x_burst_size {
- PL08X_BURST_SZ_1,
- PL08X_BURST_SZ_4,
- PL08X_BURST_SZ_8,
- PL08X_BURST_SZ_16,
- PL08X_BURST_SZ_32,
- PL08X_BURST_SZ_64,
- PL08X_BURST_SZ_128,
- PL08X_BURST_SZ_256,
-};
-
-enum jh7110_pl08x_bus_width {
- PL08X_BUS_WIDTH_8_BITS,
- PL08X_BUS_WIDTH_16_BITS,
- PL08X_BUS_WIDTH_32_BITS,
-};
-
-enum jh7110_pl08x_flow_control {
- PL080_FLOW_MEM2MEM,
- PL080_FLOW_MEM2PER,
- PL080_FLOW_PER2MEM,
- PL080_FLOW_SRC2DST,
- PL080_FLOW_SRC2DST_DST,
- PL080_FLOW_MEM2PER_PER,
- PL080_FLOW_PER2MEM_PER,
- PL080_FLOW_SRC2DST_SRC
-};
-
-enum jh7110_pl08x_increment {
- PL08X_INCREMENT_FIX,
- PL08X_INCREMENT,
-};
-
-struct jh7110_pl080_chan_config {
- u8 src_peri;
- u8 dst_peri;
- u32 src_addr;
- u32 dst_addr;
- u32 xfer_size;
- u32 data_scattered;
- u32 src_distance;
- u32 dst_distance;
- enum jh7110_pl08x_increment si;
- enum jh7110_pl08x_increment di;
- enum jh7110_pl08x_ahb_master src_ahb;
- enum jh7110_pl08x_ahb_master dst_ahb;
- enum jh7110_pl08x_bus_width src_width;
- enum jh7110_pl08x_bus_width dst_width;
- enum jh7110_pl08x_burst_size src_bsize;
- enum jh7110_pl08x_burst_size dst_bsize;
- enum jh7110_pl08x_flow_control flow;
-};
-
-/* DMA linked list chain structure */
-struct jh7110_pl080_lli {
- u32 src_addr;
- u32 dst_addr;
- u32 next_lli;
- u32 control0;
-};
-
-struct jh7110_pl080_lli_build_data {
- u32 src_addr;
- u32 dst_addr;
- struct jh7110_pl080_lli *llis;
- u32 llis_phy_addr;
- u32 tsize;
- u32 remainder;
-};
-
-struct jh7110_pl08x_phy_chan {
- unsigned int id;
- void *base;
- void *reg_config;
- void *reg_control;
- void *reg_src;
- void *reg_dst;
- void *reg_lli;
-};
-
-struct jh7110_pl08x_device {
- struct jh7110_pl08x_phy_chan phy_chans[PL080_CHANNELS_NUM];
-};
-#endif
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
-
+#include <linux/amba/pl080.h>
#include <linux/dma-direct.h>
#include <crypto/hash.h>
#include <crypto/sm3.h>
#include <crypto/scatterwalk.h>
#include <crypto/internal/hash.h>
-#include "jh7110-pl080.h"
#include "jh7110-str.h"
#define HASH_OP_UPDATE 1
PL080 and PL081, Samsungs PL080 derivative and Faraday
Technology's FTDMAC020 PL080 derivative.
-config JH7110_PL08X
- tristate "Starfive sec PL080 support"
- depends on !AMBA_PL08X
- select DMA_ENGINE
- select DMA_VIRTUAL_CHANNELS
- help
- Say yes if your platform has a PL08x DMAC device which can
- provide DMA engine support. This includes the original ARM
- PL080 and PL081, Samsungs PL080 derivative and Faraday
- Technology's FTDMAC020 PL080 derivative.
-
config AMCC_PPC440SPE_ADMA
tristate "AMCC PPC440SPe ADMA support"
depends on 440SPe || 440SP
#devices
obj-$(CONFIG_ALTERA_MSGDMA) += altera-msgdma.o
obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
-obj-$(CONFIG_JH7110_PL08X) += jh7110-pl08x.o
obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/
obj-$(CONFIG_AMD_PTDMA) += ptdma/
obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
* after the final transfer signalled by LBREQ or LSREQ. The DMAC
* will then move to the next LLI entry. Unsupported by PL080S.
*/
-#ifndef CONFIG_SOC_STARFIVE_JH7110
#include <linux/amba/bus.h>
-#endif
#include <linux/amba/pl08x.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_dma.h>
-#ifdef CONFIG_SOC_STARFIVE_JH7110
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#endif
#include <linux/pm_runtime.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)
-#ifndef CONFIG_SOC_STARFIVE_JH7110
static struct amba_driver pl08x_amba_driver;
-#endif
struct pl08x_driver_data;
/**
struct pl08x_txd *at;
struct pl08x_driver_data *host;
enum pl08x_dma_chan_state state;
-#ifdef CONFIG_SOC_STARFIVE_JH7110
- int chan_id;
-#endif
bool slave;
int signal;
unsigned mux_use;
struct dma_device memcpy;
bool has_slave;
void __iomem *base;
-#ifdef CONFIG_SOC_STARFIVE_JH7110
- struct platform_device *adev;
-#else
struct amba_device *adev;
-#endif
const struct vendor_data *vd;
struct pl08x_platform_data *pd;
struct pl08x_phy_chan *phy_chans;
unsigned long flags;
int i;
-#ifdef CONFIG_SOC_STARFIVE_JH7110
- ch = &pl08x->phy_chans[virt_chan->chan_id];
-
- spin_lock_irqsave(&ch->lock, flags);
-
- if (!ch->locked && !ch->serving) {
- ch->serving = virt_chan;
- spin_unlock_irqrestore(&ch->lock, flags);
- return ch;
- }
-
- spin_unlock_irqrestore(&ch->lock, flags);
-#endif
for (i = 0; i < pl08x->vd->channels; i++) {
ch = &pl08x->phy_chans[i];
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
unsigned long flags;
-#ifdef CONFIG_SOC_STARFIVE_JH7110
- plchan->chan_id = chan->chan_id;
-#endif
spin_lock_irqsave(&plchan->vc.lock, flags);
if (vchan_issue_pending(&plchan->vc)) {
if (!plchan->phychan && plchan->state != PL08X_CHAN_WAITING)
dsg = kzalloc(sizeof(struct pl08x_sg), GFP_NOWAIT);
if (!dsg) {
pl08x_free_txd(pl08x, txd);
- dev_err(&pl08x->adev->dev,
- "%s no memory for kzalloc\n", __func__);
return NULL;
}
list_add_tail(&dsg->node, &txd->dsg_list);
ret = pl08x_fill_llis_for_desc(plchan->host, txd);
if (!ret) {
pl08x_free_txd(pl08x, txd);
- dev_err(&pl08x->adev->dev,
- "%s pl08x_fill_llis_for_desc error\n", __func__);
return NULL;
}
return 0;
}
-#ifndef CONFIG_SOC_STARFIVE_JH7110
bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
{
struct pl08x_dma_chan *plchan;
return false;
}
EXPORT_SYMBOL_GPL(pl08x_filter_id);
-#endif
static bool pl08x_filter_fn(struct dma_chan *chan, void *chan_id)
{
return dma_get_slave_channel(dma_chan);
}
-#ifdef CONFIG_SOC_STARFIVE_JH7110
-static int pl08x_of_probe(struct platform_device *adev,
-#else
static int pl08x_of_probe(struct amba_device *adev,
-#endif
struct pl08x_driver_data *pl08x,
struct device_node *np)
{
pl08x);
}
#else
-#ifdef CONFIG_SOC_STARFIVE_JH7110
-static inline int pl08x_of_probe(struct platform_device *adev,
-#else
static inline int pl08x_of_probe(struct amba_device *adev,
-#endif
struct pl08x_driver_data *pl08x,
struct device_node *np)
{
}
#endif
-#ifdef CONFIG_SOC_STARFIVE_JH7110
-static int pl08x_probe(struct platform_device *adev) //, const struct amba_id *id)
-#else
static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
-#endif
{
struct pl08x_driver_data *pl08x;
+ struct vendor_data *vd = id->data;
struct device_node *np = adev->dev.of_node;
u32 tsfr_size;
-#ifdef CONFIG_SOC_STARFIVE_JH7110
- struct vendor_data *vd;
- struct resource *res;
- int irq, ret = 0;
-#else
- struct vendor_data *vd = id->data;
int ret = 0;
-#endif
int i;
-#ifndef CONFIG_SOC_STARFIVE_JH7110
ret = amba_request_regions(adev, NULL);
if (ret)
return ret;
-#endif
/* Ensure that we can do DMA */
ret = dma_set_mask_and_coherent(&adev->dev, DMA_BIT_MASK(32));
-#ifdef CONFIG_SOC_STARFIVE_JH7110
- if (ret)
- return ret;
-#else
if (ret)
goto out_no_pl08x;
-#endif
/* Create the driver state holder */
pl08x = kzalloc(sizeof(*pl08x), GFP_KERNEL);
if (!pl08x) {
ret = -ENOMEM;
-#ifdef CONFIG_SOC_STARFIVE_JH7110
- return ret;
-#else
goto out_no_pl08x;
-#endif
}
/* Assign useful pointers to the driver state */
pl08x->adev = adev;
-#ifdef CONFIG_SOC_STARFIVE_JH7110
- vd = (struct vendor_data *)of_device_get_match_data(&adev->dev);
- if(!vd)
- return -ENODEV;
-#endif
pl08x->vd = vd;
-#ifdef CONFIG_SOC_STARFIVE_JH7110
- res = platform_get_resource_byname(adev, IORESOURCE_MEM, "sec_dma");
- pl08x->base = devm_ioremap_resource(&adev->dev, res);
-#else
pl08x->base = ioremap(adev->res.start, resource_size(&adev->res));
-#endif
if (!pl08x->base) {
ret = -ENOMEM;
goto out_no_ioremap;
writel(0x000000FF, pl08x->base + PL080_TC_CLEAR);
/* Attach the interrupt handler */
-#ifdef CONFIG_SOC_STARFIVE_JH7110
- irq = platform_get_irq(adev, 0);
- if (irq < 0) {
- dev_err(&adev->dev, "Cannot get IRQ resource\n");
- return irq;
- }
-
- ret = request_irq(irq, pl08x_irq, 0, DRIVER_NAME, pl08x);
-#else
ret = request_irq(adev->irq[0], pl08x_irq, 0, DRIVER_NAME, pl08x);
-#endif
if (ret) {
dev_err(&adev->dev, "%s failed to request interrupt %d\n",
-#ifdef CONFIG_SOC_STARFIVE_JH7110
- __func__, irq);
-#else
__func__, adev->irq[0]);
-#endif
goto out_no_irq;
}
}
}
-#ifdef CONFIG_SOC_STARFIVE_JH7110
- platform_set_drvdata(adev, pl08x);
-#else
amba_set_drvdata(adev, pl08x);
-#endif
init_pl08x_debugfs(pl08x);
-#ifdef CONFIG_SOC_STARFIVE_JH7110
- dev_dbg(&pl08x->adev->dev, "DMA: PL080 at 0x%08llx irq %d\n",
- (unsigned long long)res->start, irq);
-#else
dev_info(&pl08x->adev->dev, "DMA: PL%03x%s rev%u at 0x%08llx irq %d\n",
amba_part(adev), pl08x->vd->pl080s ? "s" : "", amba_rev(adev),
(unsigned long long)adev->res.start, adev->irq[0]);
-#endif
return 0;
out_no_memcpy:
kfree(pl08x->phy_chans);
out_no_phychans:
-#ifdef CONFIG_SOC_STARFIVE_JH7110
- free_irq(irq, pl08x);
-#else
free_irq(adev->irq[0], pl08x);
-#endif
out_no_irq:
dma_pool_destroy(pl08x->pool);
out_no_lli_pool:
iounmap(pl08x->base);
out_no_ioremap:
kfree(pl08x);
-
-#ifndef CONFIG_SOC_STARFIVE_JH7110
out_no_pl08x:
amba_release_regions(adev);
-#endif
return ret;
}
.dualmaster = true,
.max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK,
};
-#ifdef CONFIG_SOC_STARFIVE_JH7110
-static const struct of_device_id jh7110_dma_ids[] = {
- { .compatible = "starfive,jh7110-pl080", .data = &vendor_pl080},
- {},
-};
-MODULE_DEVICE_TABLE(of, jh7110_dma_ids);
-
-static struct platform_driver jh7110_pl08x_driver = {
- .probe = pl08x_probe,
- .driver = {
- .name = DRIVER_NAME,
- .of_match_table = jh7110_dma_ids,
- },
-};
-module_platform_driver(jh7110_pl08x_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Huan Feng <huan.feng@starfivetech.com>");
-#else
static struct vendor_data vendor_nomadik = {
.config_offset = PL080_CH_CONFIG,
.channels = 8,
return retval;
}
subsys_initcall(pl08x_init);
-#endif