Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
5c196f5e
Commit
5c196f5e
authored
Mar 12, 2019
by
Vinod Koul
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/brcm' into for-linus
parents
a3711d49
37c22cab
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
31 additions
and
61 deletions
+31
-61
drivers/dma/bcm2835-dma.c
drivers/dma/bcm2835-dma.c
+31
-61
No files found.
drivers/dma/bcm2835-dma.c
View file @
5c196f5e
...
...
@@ -2,9 +2,6 @@
/*
* BCM2835 DMA engine support
*
* This driver only supports cyclic DMA transfers
* as needed for the I2S module.
*
* Author: Florian Meier <florian.meier@koalo.de>
* Copyright 2013
*
...
...
@@ -42,7 +39,6 @@
struct
bcm2835_dmadev
{
struct
dma_device
ddev
;
spinlock_t
lock
;
void
__iomem
*
base
;
struct
device_dma_parameters
dma_parms
;
};
...
...
@@ -64,7 +60,6 @@ struct bcm2835_cb_entry {
struct
bcm2835_chan
{
struct
virt_dma_chan
vc
;
struct
list_head
node
;
struct
dma_slave_config
cfg
;
unsigned
int
dreq
;
...
...
@@ -405,39 +400,32 @@ static void bcm2835_dma_fill_cb_chain_with_sg(
}
}
static
int
bcm2835_dma_abort
(
void
__iomem
*
chan_base
)
static
void
bcm2835_dma_abort
(
struct
bcm2835_chan
*
c
)
{
unsigned
long
cs
;
void
__iomem
*
chan_base
=
c
->
chan_base
;
long
int
timeout
=
10000
;
cs
=
readl
(
chan_base
+
BCM2835_DMA_CS
);
if
(
!
(
cs
&
BCM2835_DMA_ACTIVE
))
return
0
;
/*
* A zero control block address means the channel is idle.
* (The ACTIVE flag in the CS register is not a reliable indicator.)
*/
if
(
!
readl
(
chan_base
+
BCM2835_DMA_ADDR
))
return
;
/* Write 0 to the active bit - Pause the DMA */
writel
(
0
,
chan_base
+
BCM2835_DMA_CS
);
/* Wait for any current AXI transfer to complete */
while
((
cs
&
BCM2835_DMA_ISPAUSED
)
&&
--
timeout
)
{
while
((
readl
(
chan_base
+
BCM2835_DMA_CS
)
&
BCM2835_DMA_WAITING_FOR_WRITES
)
&&
--
timeout
)
cpu_relax
();
cs
=
readl
(
chan_base
+
BCM2835_DMA_CS
);
}
/*
We'll un-pause when we set of our next DMA
*/
/*
Peripheral might be stuck and fail to signal AXI write responses
*/
if
(
!
timeout
)
return
-
ETIMEDOUT
;
if
(
!
(
cs
&
BCM2835_DMA_ACTIVE
))
return
0
;
dev_err
(
c
->
vc
.
chan
.
device
->
dev
,
"failed to complete outstanding writes
\n
"
);
/* Terminate the control block chain */
writel
(
0
,
chan_base
+
BCM2835_DMA_NEXTCB
);
/* Abort the whole DMA */
writel
(
BCM2835_DMA_ABORT
|
BCM2835_DMA_ACTIVE
,
chan_base
+
BCM2835_DMA_CS
);
return
0
;
writel
(
BCM2835_DMA_RESET
,
chan_base
+
BCM2835_DMA_CS
);
}
static
void
bcm2835_dma_start_desc
(
struct
bcm2835_chan
*
c
)
...
...
@@ -475,8 +463,15 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
spin_lock_irqsave
(
&
c
->
vc
.
lock
,
flags
);
/* Acknowledge interrupt */
writel
(
BCM2835_DMA_INT
,
c
->
chan_base
+
BCM2835_DMA_CS
);
/*
* Clear the INT flag to receive further interrupts. Keep the channel
* active in case the descriptor is cyclic or in case the client has
* already terminated the descriptor and issued a new one. (May happen
* if this IRQ handler is threaded.) If the channel is finished, it
* will remain idle despite the ACTIVE flag being set.
*/
writel
(
BCM2835_DMA_INT
|
BCM2835_DMA_ACTIVE
,
c
->
chan_base
+
BCM2835_DMA_CS
);
d
=
c
->
desc
;
...
...
@@ -484,11 +479,7 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
if
(
d
->
cyclic
)
{
/* call the cyclic callback */
vchan_cyclic_callback
(
&
d
->
vd
);
/* Keep the DMA engine running */
writel
(
BCM2835_DMA_ACTIVE
,
c
->
chan_base
+
BCM2835_DMA_CS
);
}
else
{
}
else
if
(
!
readl
(
c
->
chan_base
+
BCM2835_DMA_ADDR
))
{
vchan_cookie_complete
(
&
c
->
desc
->
vd
);
bcm2835_dma_start_desc
(
c
);
}
...
...
@@ -506,8 +497,12 @@ static int bcm2835_dma_alloc_chan_resources(struct dma_chan *chan)
dev_dbg
(
dev
,
"Allocating DMA channel %d
\n
"
,
c
->
ch
);
/*
* Control blocks are 256 bit in length and must start at a 256 bit
* (32 byte) aligned address (BCM2835 ARM Peripherals, sec. 4.2.1.1).
*/
c
->
cb_pool
=
dma_pool_create
(
dev_name
(
dev
),
dev
,
sizeof
(
struct
bcm2835_dma_cb
),
0
,
0
);
sizeof
(
struct
bcm2835_dma_cb
),
32
,
0
);
if
(
!
c
->
cb_pool
)
{
dev_err
(
dev
,
"unable to allocate descriptor pool
\n
"
);
return
-
ENOMEM
;
...
...
@@ -776,39 +771,16 @@ static int bcm2835_dma_slave_config(struct dma_chan *chan,
static
int
bcm2835_dma_terminate_all
(
struct
dma_chan
*
chan
)
{
struct
bcm2835_chan
*
c
=
to_bcm2835_dma_chan
(
chan
);
struct
bcm2835_dmadev
*
d
=
to_bcm2835_dma_dev
(
c
->
vc
.
chan
.
device
);
unsigned
long
flags
;
int
timeout
=
10000
;
LIST_HEAD
(
head
);
spin_lock_irqsave
(
&
c
->
vc
.
lock
,
flags
);
/* Prevent this channel being scheduled */
spin_lock
(
&
d
->
lock
);
list_del_init
(
&
c
->
node
);
spin_unlock
(
&
d
->
lock
);
/*
* Stop DMA activity: we assume the callback will not be called
* after bcm_dma_abort() returns (even if it does, it will see
* c->desc is NULL and exit.)
*/
/* stop DMA activity */
if
(
c
->
desc
)
{
vchan_terminate_vdesc
(
&
c
->
desc
->
vd
);
c
->
desc
=
NULL
;
bcm2835_dma_abort
(
c
->
chan_base
);
/* Wait for stopping */
while
(
--
timeout
)
{
if
(
!
(
readl
(
c
->
chan_base
+
BCM2835_DMA_CS
)
&
BCM2835_DMA_ACTIVE
))
break
;
cpu_relax
();
}
if
(
!
timeout
)
dev_err
(
d
->
ddev
.
dev
,
"DMA transfer could not be terminated
\n
"
);
bcm2835_dma_abort
(
c
);
}
vchan_get_all_descriptors
(
&
c
->
vc
,
&
head
);
...
...
@@ -836,7 +808,6 @@ static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id,
c
->
vc
.
desc_free
=
bcm2835_dma_desc_free
;
vchan_init
(
&
c
->
vc
,
&
d
->
ddev
);
INIT_LIST_HEAD
(
&
c
->
node
);
c
->
chan_base
=
BCM2835_DMA_CHANIO
(
d
->
base
,
chan_id
);
c
->
ch
=
chan_id
;
...
...
@@ -939,7 +910,6 @@ static int bcm2835_dma_probe(struct platform_device *pdev)
od
->
ddev
.
residue_granularity
=
DMA_RESIDUE_GRANULARITY_BURST
;
od
->
ddev
.
dev
=
&
pdev
->
dev
;
INIT_LIST_HEAD
(
&
od
->
ddev
.
channels
);
spin_lock_init
(
&
od
->
lock
);
platform_set_drvdata
(
pdev
,
od
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment