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
89b7e78f
Commit
89b7e78f
authored
Aug 17, 2018
by
Vinod Koul
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/renesas' into for-linus
parents
35e0db66
218c2104
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
47 additions
and
66 deletions
+47
-66
Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt
Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt
+1
-0
drivers/dma/sh/rcar-dmac.c
drivers/dma/sh/rcar-dmac.c
+46
-66
No files found.
Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt
View file @
89b7e78f
...
...
@@ -29,6 +29,7 @@ Required Properties:
- "renesas,dmac-r8a77965" (R-Car M3-N)
- "renesas,dmac-r8a77970" (R-Car V3M)
- "renesas,dmac-r8a77980" (R-Car V3H)
- "renesas,dmac-r8a77990" (R-Car E3)
- "renesas,dmac-r8a77995" (R-Car D3)
- reg: base address and length of the registers block for the DMAC
...
...
drivers/dma/sh/rcar-dmac.c
View file @
89b7e78f
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car Gen2 DMA Controller Driver
*
* Copyright (C) 2014 Renesas Electronics Inc.
*
* Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
*
* This is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*/
#include <linux/delay.h>
...
...
@@ -431,7 +428,8 @@ static void rcar_dmac_chan_start_xfer(struct rcar_dmac_chan *chan)
chcr
|=
RCAR_DMACHCR_DPM_DISABLED
|
RCAR_DMACHCR_IE
;
}
rcar_dmac_chan_write
(
chan
,
RCAR_DMACHCR
,
chcr
|
RCAR_DMACHCR_DE
);
rcar_dmac_chan_write
(
chan
,
RCAR_DMACHCR
,
chcr
|
RCAR_DMACHCR_DE
|
RCAR_DMACHCR_CAIE
);
}
static
int
rcar_dmac_init
(
struct
rcar_dmac
*
dmac
)
...
...
@@ -761,21 +759,15 @@ static void rcar_dmac_chcr_de_barrier(struct rcar_dmac_chan *chan)
dev_err
(
chan
->
chan
.
device
->
dev
,
"CHCR DE check error
\n
"
);
}
static
void
rcar_dmac_
sync_tcr
(
struct
rcar_dmac_chan
*
chan
)
static
void
rcar_dmac_
clear_chcr_de
(
struct
rcar_dmac_chan
*
chan
)
{
u32
chcr
=
rcar_dmac_chan_read
(
chan
,
RCAR_DMACHCR
);
if
(
!
(
chcr
&
RCAR_DMACHCR_DE
))
return
;
/* set DE=0 and flush remaining data */
rcar_dmac_chan_write
(
chan
,
RCAR_DMACHCR
,
(
chcr
&
~
RCAR_DMACHCR_DE
));
/* make sure all remaining data was flushed */
rcar_dmac_chcr_de_barrier
(
chan
);
/* back DE */
rcar_dmac_chan_write
(
chan
,
RCAR_DMACHCR
,
chcr
);
}
static
void
rcar_dmac_chan_halt
(
struct
rcar_dmac_chan
*
chan
)
...
...
@@ -783,7 +775,8 @@ static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan)
u32
chcr
=
rcar_dmac_chan_read
(
chan
,
RCAR_DMACHCR
);
chcr
&=
~
(
RCAR_DMACHCR_DSE
|
RCAR_DMACHCR_DSIE
|
RCAR_DMACHCR_IE
|
RCAR_DMACHCR_TE
|
RCAR_DMACHCR_DE
);
RCAR_DMACHCR_TE
|
RCAR_DMACHCR_DE
|
RCAR_DMACHCR_CAE
|
RCAR_DMACHCR_CAIE
);
rcar_dmac_chan_write
(
chan
,
RCAR_DMACHCR
,
chcr
);
rcar_dmac_chcr_de_barrier
(
chan
);
}
...
...
@@ -812,12 +805,7 @@ static void rcar_dmac_chan_reinit(struct rcar_dmac_chan *chan)
}
}
static
void
rcar_dmac_stop
(
struct
rcar_dmac
*
dmac
)
{
rcar_dmac_write
(
dmac
,
RCAR_DMAOR
,
0
);
}
static
void
rcar_dmac_abort
(
struct
rcar_dmac
*
dmac
)
static
void
rcar_dmac_stop_all_chan
(
struct
rcar_dmac
*
dmac
)
{
unsigned
int
i
;
...
...
@@ -826,14 +814,24 @@ static void rcar_dmac_abort(struct rcar_dmac *dmac)
struct
rcar_dmac_chan
*
chan
=
&
dmac
->
channels
[
i
];
/* Stop and reinitialize the channel. */
spin_lock
(
&
chan
->
lock
);
spin_lock
_irq
(
&
chan
->
lock
);
rcar_dmac_chan_halt
(
chan
);
spin_unlock
(
&
chan
->
lock
);
rcar_dmac_chan_reinit
(
chan
);
spin_unlock_irq
(
&
chan
->
lock
);
}
}
static
int
rcar_dmac_chan_pause
(
struct
dma_chan
*
chan
)
{
unsigned
long
flags
;
struct
rcar_dmac_chan
*
rchan
=
to_rcar_dmac_chan
(
chan
);
spin_lock_irqsave
(
&
rchan
->
lock
,
flags
);
rcar_dmac_clear_chcr_de
(
rchan
);
spin_unlock_irqrestore
(
&
rchan
->
lock
,
flags
);
return
0
;
}
/* -----------------------------------------------------------------------------
* Descriptors preparation
*/
...
...
@@ -1355,9 +1353,6 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan,
residue
+=
chunk
->
size
;
}
if
(
desc
->
direction
==
DMA_DEV_TO_MEM
)
rcar_dmac_sync_tcr
(
chan
);
/* Add the residue for the current chunk. */
residue
+=
rcar_dmac_chan_read
(
chan
,
RCAR_DMATCRB
)
<<
desc
->
xfer_shift
;
...
...
@@ -1522,11 +1517,26 @@ static irqreturn_t rcar_dmac_isr_channel(int irq, void *dev)
u32
mask
=
RCAR_DMACHCR_DSE
|
RCAR_DMACHCR_TE
;
struct
rcar_dmac_chan
*
chan
=
dev
;
irqreturn_t
ret
=
IRQ_NONE
;
bool
reinit
=
false
;
u32
chcr
;
spin_lock
(
&
chan
->
lock
);
chcr
=
rcar_dmac_chan_read
(
chan
,
RCAR_DMACHCR
);
if
(
chcr
&
RCAR_DMACHCR_CAE
)
{
struct
rcar_dmac
*
dmac
=
to_rcar_dmac
(
chan
->
chan
.
device
);
/*
* We don't need to call rcar_dmac_chan_halt()
* because channel is already stopped in error case.
* We need to clear register and check DE bit as recovery.
*/
rcar_dmac_write
(
dmac
,
RCAR_DMACHCLR
,
1
<<
chan
->
index
);
rcar_dmac_chcr_de_barrier
(
chan
);
reinit
=
true
;
goto
spin_lock_end
;
}
if
(
chcr
&
RCAR_DMACHCR_TE
)
mask
|=
RCAR_DMACHCR_DE
;
rcar_dmac_chan_write
(
chan
,
RCAR_DMACHCR
,
chcr
&
~
mask
);
...
...
@@ -1539,8 +1549,16 @@ static irqreturn_t rcar_dmac_isr_channel(int irq, void *dev)
if
(
chcr
&
RCAR_DMACHCR_TE
)
ret
|=
rcar_dmac_isr_transfer_end
(
chan
);
spin_lock_end:
spin_unlock
(
&
chan
->
lock
);
if
(
reinit
)
{
dev_err
(
chan
->
chan
.
device
->
dev
,
"Channel Address Error
\n
"
);
rcar_dmac_chan_reinit
(
chan
);
ret
=
IRQ_HANDLED
;
}
return
ret
;
}
...
...
@@ -1597,24 +1615,6 @@ static irqreturn_t rcar_dmac_isr_channel_thread(int irq, void *dev)
return
IRQ_HANDLED
;
}
static
irqreturn_t
rcar_dmac_isr_error
(
int
irq
,
void
*
data
)
{
struct
rcar_dmac
*
dmac
=
data
;
if
(
!
(
rcar_dmac_read
(
dmac
,
RCAR_DMAOR
)
&
RCAR_DMAOR_AE
))
return
IRQ_NONE
;
/*
* An unrecoverable error occurred on an unknown channel. Halt the DMAC,
* abort transfers on all channels, and reinitialize the DMAC.
*/
rcar_dmac_stop
(
dmac
);
rcar_dmac_abort
(
dmac
);
rcar_dmac_init
(
dmac
);
return
IRQ_HANDLED
;
}
/* -----------------------------------------------------------------------------
* OF xlate and channel filter
*/
...
...
@@ -1784,8 +1784,6 @@ static int rcar_dmac_probe(struct platform_device *pdev)
struct
rcar_dmac
*
dmac
;
struct
resource
*
mem
;
unsigned
int
i
;
char
*
irqname
;
int
irq
;
int
ret
;
dmac
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
dmac
),
GFP_KERNEL
);
...
...
@@ -1824,17 +1822,6 @@ static int rcar_dmac_probe(struct platform_device *pdev)
if
(
IS_ERR
(
dmac
->
iomem
))
return
PTR_ERR
(
dmac
->
iomem
);
irq
=
platform_get_irq_byname
(
pdev
,
"error"
);
if
(
irq
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"no error IRQ specified
\n
"
);
return
-
ENODEV
;
}
irqname
=
devm_kasprintf
(
dmac
->
dev
,
GFP_KERNEL
,
"%s:error"
,
dev_name
(
dmac
->
dev
));
if
(
!
irqname
)
return
-
ENOMEM
;
/* Enable runtime PM and initialize the device. */
pm_runtime_enable
(
&
pdev
->
dev
);
ret
=
pm_runtime_get_sync
(
&
pdev
->
dev
);
...
...
@@ -1871,6 +1858,7 @@ static int rcar_dmac_probe(struct platform_device *pdev)
engine
->
device_prep_slave_sg
=
rcar_dmac_prep_slave_sg
;
engine
->
device_prep_dma_cyclic
=
rcar_dmac_prep_dma_cyclic
;
engine
->
device_config
=
rcar_dmac_device_config
;
engine
->
device_pause
=
rcar_dmac_chan_pause
;
engine
->
device_terminate_all
=
rcar_dmac_chan_terminate_all
;
engine
->
device_tx_status
=
rcar_dmac_tx_status
;
engine
->
device_issue_pending
=
rcar_dmac_issue_pending
;
...
...
@@ -1885,14 +1873,6 @@ static int rcar_dmac_probe(struct platform_device *pdev)
goto
error
;
}
ret
=
devm_request_irq
(
&
pdev
->
dev
,
irq
,
rcar_dmac_isr_error
,
0
,
irqname
,
dmac
);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"failed to request IRQ %u (%d)
\n
"
,
irq
,
ret
);
return
ret
;
}
/* Register the DMAC as a DMA provider for DT. */
ret
=
of_dma_controller_register
(
pdev
->
dev
.
of_node
,
rcar_dmac_of_xlate
,
NULL
);
...
...
@@ -1932,7 +1912,7 @@ static void rcar_dmac_shutdown(struct platform_device *pdev)
{
struct
rcar_dmac
*
dmac
=
platform_get_drvdata
(
pdev
);
rcar_dmac_stop
(
dmac
);
rcar_dmac_stop
_all_chan
(
dmac
);
}
static
const
struct
of_device_id
rcar_dmac_of_ids
[]
=
{
...
...
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