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
nexedi
linux
Commits
4dfc9afe
Commit
4dfc9afe
authored
Oct 03, 2016
by
Vinod Koul
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/mv_xor' into for-linus
parents
850e0448
77ff7a70
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
117 additions
and
3 deletions
+117
-3
drivers/dma/mv_xor.c
drivers/dma/mv_xor.c
+94
-1
drivers/dma/mv_xor.h
drivers/dma/mv_xor.h
+7
-0
include/linux/mbus.h
include/linux/mbus.h
+16
-2
No files found.
drivers/dma/mv_xor.c
View file @
4dfc9afe
...
...
@@ -467,12 +467,90 @@ static int mv_xor_alloc_chan_resources(struct dma_chan *chan)
return
mv_chan
->
slots_allocated
?
:
-
ENOMEM
;
}
/*
* Check if source or destination is an PCIe/IO address (non-SDRAM) and add
* a new MBus window if necessary. Use a cache for these check so that
* the MMIO mapped registers don't have to be accessed for this check
* to speed up this process.
*/
static
int
mv_xor_add_io_win
(
struct
mv_xor_chan
*
mv_chan
,
u32
addr
)
{
struct
mv_xor_device
*
xordev
=
mv_chan
->
xordev
;
void
__iomem
*
base
=
mv_chan
->
mmr_high_base
;
u32
win_enable
;
u32
size
;
u8
target
,
attr
;
int
ret
;
int
i
;
/* Nothing needs to get done for the Armada 3700 */
if
(
xordev
->
xor_type
==
XOR_ARMADA_37XX
)
return
0
;
/*
* Loop over the cached windows to check, if the requested area
* is already mapped. If this the case, nothing needs to be done
* and we can return.
*/
for
(
i
=
0
;
i
<
WINDOW_COUNT
;
i
++
)
{
if
(
addr
>=
xordev
->
win_start
[
i
]
&&
addr
<=
xordev
->
win_end
[
i
])
{
/* Window is already mapped */
return
0
;
}
}
/*
* The window is not mapped, so we need to create the new mapping
*/
/* If no IO window is found that addr has to be located in SDRAM */
ret
=
mvebu_mbus_get_io_win_info
(
addr
,
&
size
,
&
target
,
&
attr
);
if
(
ret
<
0
)
return
0
;
/*
* Mask the base addr 'addr' according to 'size' read back from the
* MBus window. Otherwise we might end up with an address located
* somewhere in the middle of this area here.
*/
size
-=
1
;
addr
&=
~
size
;
/*
* Reading one of both enabled register is enough, as they are always
* programmed to the identical values
*/
win_enable
=
readl
(
base
+
WINDOW_BAR_ENABLE
(
0
));
/* Set 'i' to the first free window to write the new values to */
i
=
ffs
(
~
win_enable
)
-
1
;
if
(
i
>=
WINDOW_COUNT
)
return
-
ENOMEM
;
writel
((
addr
&
0xffff0000
)
|
(
attr
<<
8
)
|
target
,
base
+
WINDOW_BASE
(
i
));
writel
(
size
&
0xffff0000
,
base
+
WINDOW_SIZE
(
i
));
/* Fill the caching variables for later use */
xordev
->
win_start
[
i
]
=
addr
;
xordev
->
win_end
[
i
]
=
addr
+
size
;
win_enable
|=
(
1
<<
i
);
win_enable
|=
3
<<
(
16
+
(
2
*
i
));
writel
(
win_enable
,
base
+
WINDOW_BAR_ENABLE
(
0
));
writel
(
win_enable
,
base
+
WINDOW_BAR_ENABLE
(
1
));
return
0
;
}
static
struct
dma_async_tx_descriptor
*
mv_xor_prep_dma_xor
(
struct
dma_chan
*
chan
,
dma_addr_t
dest
,
dma_addr_t
*
src
,
unsigned
int
src_cnt
,
size_t
len
,
unsigned
long
flags
)
{
struct
mv_xor_chan
*
mv_chan
=
to_mv_xor_chan
(
chan
);
struct
mv_xor_desc_slot
*
sw_desc
;
int
ret
;
if
(
unlikely
(
len
<
MV_XOR_MIN_BYTE_COUNT
))
return
NULL
;
...
...
@@ -483,6 +561,11 @@ mv_xor_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
"%s src_cnt: %d len: %zu dest %pad flags: %ld
\n
"
,
__func__
,
src_cnt
,
len
,
&
dest
,
flags
);
/* Check if a new window needs to get added for 'dest' */
ret
=
mv_xor_add_io_win
(
mv_chan
,
dest
);
if
(
ret
)
return
NULL
;
sw_desc
=
mv_chan_alloc_slot
(
mv_chan
);
if
(
sw_desc
)
{
sw_desc
->
type
=
DMA_XOR
;
...
...
@@ -490,8 +573,13 @@ mv_xor_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
mv_desc_init
(
sw_desc
,
dest
,
len
,
flags
);
if
(
mv_chan
->
op_in_desc
==
XOR_MODE_IN_DESC
)
mv_desc_set_mode
(
sw_desc
);
while
(
src_cnt
--
)
while
(
src_cnt
--
)
{
/* Check if a new window needs to get added for 'src' */
ret
=
mv_xor_add_io_win
(
mv_chan
,
src
[
src_cnt
]);
if
(
ret
)
return
NULL
;
mv_desc_set_src_addr
(
sw_desc
,
src_cnt
,
src
[
src_cnt
]);
}
}
dev_dbg
(
mv_chan_to_devp
(
mv_chan
),
...
...
@@ -956,6 +1044,7 @@ mv_xor_channel_add(struct mv_xor_device *xordev,
mv_chan
->
op_in_desc
=
XOR_MODE_IN_DESC
;
dma_dev
=
&
mv_chan
->
dmadev
;
mv_chan
->
xordev
=
xordev
;
/*
* These source and destination dummy buffers are used to implement
...
...
@@ -1083,6 +1172,10 @@ mv_xor_conf_mbus_windows(struct mv_xor_device *xordev,
dram
->
mbus_dram_target_id
,
base
+
WINDOW_BASE
(
i
));
writel
((
cs
->
size
-
1
)
&
0xffff0000
,
base
+
WINDOW_SIZE
(
i
));
/* Fill the caching variables for later use */
xordev
->
win_start
[
i
]
=
cs
->
base
;
xordev
->
win_end
[
i
]
=
cs
->
base
+
cs
->
size
-
1
;
win_enable
|=
(
1
<<
i
);
win_enable
|=
3
<<
(
16
+
(
2
*
i
));
}
...
...
drivers/dma/mv_xor.h
View file @
4dfc9afe
...
...
@@ -80,12 +80,17 @@
#define WINDOW_BAR_ENABLE(chan) (0x40 + ((chan) << 2))
#define WINDOW_OVERRIDE_CTRL(chan) (0xA0 + ((chan) << 2))
#define WINDOW_COUNT 8
struct
mv_xor_device
{
void
__iomem
*
xor_base
;
void
__iomem
*
xor_high_base
;
struct
clk
*
clk
;
struct
mv_xor_chan
*
channels
[
MV_XOR_MAX_CHANNELS
];
int
xor_type
;
u32
win_start
[
WINDOW_COUNT
];
u32
win_end
[
WINDOW_COUNT
];
};
/**
...
...
@@ -127,6 +132,8 @@ struct mv_xor_chan {
char
dummy_dst
[
MV_XOR_MIN_BYTE_COUNT
];
dma_addr_t
dummy_src_addr
,
dummy_dst_addr
;
u32
saved_config_reg
,
saved_int_mask_reg
;
struct
mv_xor_device
*
xordev
;
};
/**
...
...
include/linux/mbus.h
View file @
4dfc9afe
...
...
@@ -11,6 +11,8 @@
#ifndef __LINUX_MBUS_H
#define __LINUX_MBUS_H
#include <linux/errno.h>
struct
resource
;
struct
mbus_dram_target_info
...
...
@@ -55,6 +57,8 @@ struct mbus_dram_target_info
#ifdef CONFIG_PLAT_ORION
extern
const
struct
mbus_dram_target_info
*
mv_mbus_dram_info
(
void
);
extern
const
struct
mbus_dram_target_info
*
mv_mbus_dram_info_nooverlap
(
void
);
int
mvebu_mbus_get_io_win_info
(
phys_addr_t
phyaddr
,
u32
*
size
,
u8
*
target
,
u8
*
attr
);
#else
static
inline
const
struct
mbus_dram_target_info
*
mv_mbus_dram_info
(
void
)
{
...
...
@@ -64,14 +68,24 @@ static inline const struct mbus_dram_target_info *mv_mbus_dram_info_nooverlap(vo
{
return
NULL
;
}
static
inline
int
mvebu_mbus_get_io_win_info
(
phys_addr_t
phyaddr
,
u32
*
size
,
u8
*
target
,
u8
*
attr
)
{
/*
* On all ARM32 MVEBU platforms with MBus support, this stub
* function will not get called. The real function from the
* MBus driver is called instead. ARM64 MVEBU platforms like
* the Armada 3700 could use the mv_xor device driver which calls
* into this function
*/
return
-
EINVAL
;
}
#endif
int
mvebu_mbus_save_cpu_target
(
u32
__iomem
*
store_addr
);
void
mvebu_mbus_get_pcie_mem_aperture
(
struct
resource
*
res
);
void
mvebu_mbus_get_pcie_io_aperture
(
struct
resource
*
res
);
int
mvebu_mbus_get_dram_win_info
(
phys_addr_t
phyaddr
,
u8
*
target
,
u8
*
attr
);
int
mvebu_mbus_get_io_win_info
(
phys_addr_t
phyaddr
,
u32
*
size
,
u8
*
target
,
u8
*
attr
);
int
mvebu_mbus_add_window_remap_by_id
(
unsigned
int
target
,
unsigned
int
attribute
,
phys_addr_t
base
,
size_t
size
,
...
...
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