Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3ecf51a4 authored by Boojin Kim's avatar Boojin Kim Committed by Vinod Koul
Browse files

DMA: PL330: Support MEMTOMEM transmit w/o RMB, WMB



The DMAC PL330 r1p0 version fixed the lockup error being on r0p0.
This patch supports the DMA transmission without memory barrier
operation when the revision of DMAC PL330 is the next of r0p0.

Cc: Jassi Brar <jassisinghbrar@gmail.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Acked-by: default avatarVinod Koul <vinod.koul@intel.com>
Signed-off-by: default avatarBoojin Kim <boojin.kim@samsung.com>
Signed-off-by: default avatarKukjin Kim <kgene.kim@samsung.com>
Acked-by: default avatarJassi Brar <jassisinghbrar@gmail.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@linux.intel.com>
parent b06db6e5
Loading
Loading
Loading
Loading
+26 −5
Original line number Original line Diff line number Diff line
@@ -151,6 +151,11 @@ enum pl330_reqtype {
#define CRD			0xe14
#define CRD			0xe14


#define PERIPH_ID		0xfe0
#define PERIPH_ID		0xfe0
#define PERIPH_REV_SHIFT	20
#define PERIPH_REV_MASK		0xf
#define PERIPH_REV_R0P0		0
#define PERIPH_REV_R1P0		1
#define PERIPH_REV_R1P1		2
#define PCELL_ID		0xff0
#define PCELL_ID		0xff0


#define CR0_PERIPH_REQ_SET	(1 << 0)
#define CR0_PERIPH_REQ_SET	(1 << 0)
@@ -344,6 +349,7 @@ struct pl330_reqcfg {
	enum pl330_dstcachectrl dcctl;
	enum pl330_dstcachectrl dcctl;
	enum pl330_srccachectrl scctl;
	enum pl330_srccachectrl scctl;
	enum pl330_byteswap swap;
	enum pl330_byteswap swap;
	struct pl330_config *pcfg;
};
};


/*
/*
@@ -655,6 +661,11 @@ static inline u32 get_id(struct pl330_info *pi, u32 off)
	return id;
	return id;
}
}


static inline u32 get_revision(u32 periph_id)
{
	return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK;
}

static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[],
static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[],
		enum pl330_dst da, u16 val)
		enum pl330_dst da, u16 val)
{
{
@@ -1241,13 +1252,22 @@ static inline int _ldst_memtomem(unsigned dry_run, u8 buf[],
		const struct _xfer_spec *pxs, int cyc)
		const struct _xfer_spec *pxs, int cyc)
{
{
	int off = 0;
	int off = 0;
	struct pl330_config *pcfg = pxs->r->cfg->pcfg;


	/* check lock-up free version */
	if (get_revision(pcfg->periph_id) >= PERIPH_REV_R1P0) {
		while (cyc--) {
			off += _emit_LD(dry_run, &buf[off], ALWAYS);
			off += _emit_ST(dry_run, &buf[off], ALWAYS);
		}
	} else {
		while (cyc--) {
		while (cyc--) {
			off += _emit_LD(dry_run, &buf[off], ALWAYS);
			off += _emit_LD(dry_run, &buf[off], ALWAYS);
			off += _emit_RMB(dry_run, &buf[off]);
			off += _emit_RMB(dry_run, &buf[off]);
			off += _emit_ST(dry_run, &buf[off], ALWAYS);
			off += _emit_ST(dry_run, &buf[off], ALWAYS);
			off += _emit_WMB(dry_run, &buf[off]);
			off += _emit_WMB(dry_run, &buf[off]);
		}
		}
	}


	return off;
	return off;
}
}
@@ -2619,6 +2639,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
	async_tx_ack(&desc->txd);
	async_tx_ack(&desc->txd);


	desc->req.peri = peri_id ? pch->chan.chan_id : 0;
	desc->req.peri = peri_id ? pch->chan.chan_id : 0;
	desc->rqcfg.pcfg = &pch->dmac->pif.pcfg;


	dma_async_tx_descriptor_init(&desc->txd, &pch->chan);
	dma_async_tx_descriptor_init(&desc->txd, &pch->chan);