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
d611d7ea
Commit
d611d7ea
authored
3 years ago
by
Krzysztof Kozlowski
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-v5.16/renesas-rpc' into mem-ctrl-next
parents
4ed2f354
4a26df8e
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
126 additions
and
36 deletions
+126
-36
Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
...evicetree/bindings/memory-controllers/renesas,rpc-if.yaml
+1
-0
drivers/memory/Kconfig
drivers/memory/Kconfig
+1
-0
drivers/memory/renesas-rpc-if.c
drivers/memory/renesas-rpc-if.c
+123
-36
include/memory/renesas-rpc-if.h
include/memory/renesas-rpc-if.h
+1
-0
No files found.
Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
View file @
d611d7ea
...
...
@@ -33,6 +33,7 @@ properties:
-
renesas,r8a77970-rpc-if
# R-Car V3M
-
renesas,r8a77980-rpc-if
# R-Car V3H
-
renesas,r8a77995-rpc-if
# R-Car D3
-
renesas,r8a779a0-rpc-if
# R-Car V3U
-
const
:
renesas,rcar-gen3-rpc-if
# a generic R-Car gen3 or RZ/G2 device
reg
:
...
...
This diff is collapsed.
Click to expand it.
drivers/memory/Kconfig
View file @
d611d7ea
...
...
@@ -210,6 +210,7 @@ config RENESAS_RPCIF
tristate "Renesas RPC-IF driver"
depends on ARCH_RENESAS || COMPILE_TEST
select REGMAP_MMIO
select RESET_CONTROLLER
help
This supports Renesas R-Car Gen3 or RZ/G2 RPC-IF which provides
either SPI host or HyperFlash. You'll have to select individual
...
...
This diff is collapsed.
Click to expand it.
drivers/memory/renesas-rpc-if.c
View file @
d611d7ea
...
...
@@ -160,10 +160,61 @@ static const struct regmap_access_table rpcif_volatile_table = {
.
n_yes_ranges
=
ARRAY_SIZE
(
rpcif_volatile_ranges
),
};
/*
* Custom accessor functions to ensure SMRDR0 and SMWDR0 are always accessed
* with proper width. Requires SMENR_SPIDE to be correctly set before!
*/
static
int
rpcif_reg_read
(
void
*
context
,
unsigned
int
reg
,
unsigned
int
*
val
)
{
struct
rpcif
*
rpc
=
context
;
if
(
reg
==
RPCIF_SMRDR0
||
reg
==
RPCIF_SMWDR0
)
{
u32
spide
=
readl
(
rpc
->
base
+
RPCIF_SMENR
)
&
RPCIF_SMENR_SPIDE
(
0xF
);
if
(
spide
==
0x8
)
{
*
val
=
readb
(
rpc
->
base
+
reg
);
return
0
;
}
else
if
(
spide
==
0xC
)
{
*
val
=
readw
(
rpc
->
base
+
reg
);
return
0
;
}
else
if
(
spide
!=
0xF
)
{
return
-
EILSEQ
;
}
}
*
val
=
readl
(
rpc
->
base
+
reg
);
return
0
;
}
static
int
rpcif_reg_write
(
void
*
context
,
unsigned
int
reg
,
unsigned
int
val
)
{
struct
rpcif
*
rpc
=
context
;
if
(
reg
==
RPCIF_SMRDR0
||
reg
==
RPCIF_SMWDR0
)
{
u32
spide
=
readl
(
rpc
->
base
+
RPCIF_SMENR
)
&
RPCIF_SMENR_SPIDE
(
0xF
);
if
(
spide
==
0x8
)
{
writeb
(
val
,
rpc
->
base
+
reg
);
return
0
;
}
else
if
(
spide
==
0xC
)
{
writew
(
val
,
rpc
->
base
+
reg
);
return
0
;
}
else
if
(
spide
!=
0xF
)
{
return
-
EILSEQ
;
}
}
writel
(
val
,
rpc
->
base
+
reg
);
return
0
;
}
static
const
struct
regmap_config
rpcif_regmap_config
=
{
.
reg_bits
=
32
,
.
val_bits
=
32
,
.
reg_stride
=
4
,
.
reg_read
=
rpcif_reg_read
,
.
reg_write
=
rpcif_reg_write
,
.
fast_io
=
true
,
.
max_register
=
RPCIF_PHYINT
,
.
volatile_table
=
&
rpcif_volatile_table
,
...
...
@@ -173,17 +224,15 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
resource
*
res
;
void
__iomem
*
base
;
rpc
->
dev
=
dev
;
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"regs"
);
base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
base
))
return
PTR_ERR
(
base
);
rpc
->
base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
rpc
->
base
))
return
PTR_ERR
(
rpc
->
base
);
rpc
->
regmap
=
devm_regmap_init_mmio
(
&
pdev
->
dev
,
base
,
&
rpcif_regmap_config
);
rpc
->
regmap
=
devm_regmap_init
(
&
pdev
->
dev
,
NULL
,
rpc
,
&
rpcif_regmap_config
);
if
(
IS_ERR
(
rpc
->
regmap
))
{
dev_err
(
&
pdev
->
dev
,
"failed to init regmap for rpcif, error %ld
\n
"
,
...
...
@@ -354,20 +403,16 @@ void rpcif_prepare(struct rpcif *rpc, const struct rpcif_op *op, u64 *offs,
nbytes
=
op
->
data
.
nbytes
;
rpc
->
xferlen
=
nbytes
;
rpc
->
enable
|=
RPCIF_SMENR_SPIDE
(
rpcif_bits_set
(
rpc
,
nbytes
))
|
RPCIF_SMENR_SPIDB
(
rpcif_bit_size
(
op
->
data
.
buswidth
));
rpc
->
enable
|=
RPCIF_SMENR_SPIDB
(
rpcif_bit_size
(
op
->
data
.
buswidth
));
}
}
EXPORT_SYMBOL
(
rpcif_prepare
);
int
rpcif_manual_xfer
(
struct
rpcif
*
rpc
)
{
u32
smenr
,
smcr
,
pos
=
0
,
max
=
4
;
u32
smenr
,
smcr
,
pos
=
0
,
max
=
rpc
->
bus_size
==
2
?
8
:
4
;
int
ret
=
0
;
if
(
rpc
->
bus_size
==
2
)
max
=
8
;
pm_runtime_get_sync
(
rpc
->
dev
);
regmap_update_bits
(
rpc
->
regmap
,
RPCIF_PHYCNT
,
...
...
@@ -378,37 +423,36 @@ int rpcif_manual_xfer(struct rpcif *rpc)
regmap_write
(
rpc
->
regmap
,
RPCIF_SMOPR
,
rpc
->
option
);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMDMCR
,
rpc
->
dummy
);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMDRENR
,
rpc
->
ddr
);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMADR
,
rpc
->
smadr
);
smenr
=
rpc
->
enable
;
switch
(
rpc
->
dir
)
{
case
RPCIF_DATA_OUT
:
while
(
pos
<
rpc
->
xferlen
)
{
u32
nbytes
=
rpc
->
xferlen
-
pos
;
u32
data
[
2
];
u32
bytes_left
=
rpc
->
xferlen
-
pos
;
u32
nbytes
,
data
[
2
];
smcr
=
rpc
->
smcr
|
RPCIF_SMCR_SPIE
;
if
(
nbytes
>
max
)
{
nbytes
=
max
;
/* nbytes may only be 1, 2, 4, or 8 */
nbytes
=
bytes_left
>=
max
?
max
:
(
1
<<
ilog2
(
bytes_left
));
if
(
bytes_left
>
nbytes
)
smcr
|=
RPCIF_SMCR_SSLKP
;
}
smenr
|=
RPCIF_SMENR_SPIDE
(
rpcif_bits_set
(
rpc
,
nbytes
));
regmap_write
(
rpc
->
regmap
,
RPCIF_SMENR
,
smenr
);
memcpy
(
data
,
rpc
->
buffer
+
pos
,
nbytes
);
if
(
nbytes
>
4
)
{
if
(
nbytes
==
8
)
{
regmap_write
(
rpc
->
regmap
,
RPCIF_SMWDR1
,
data
[
0
]);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMWDR0
,
data
[
1
]);
}
else
if
(
nbytes
>
2
)
{
}
else
{
regmap_write
(
rpc
->
regmap
,
RPCIF_SMWDR0
,
data
[
0
]);
}
else
{
regmap_write
(
rpc
->
regmap
,
RPCIF_SMWDR0
,
data
[
0
]
<<
16
);
}
regmap_write
(
rpc
->
regmap
,
RPCIF_SMADR
,
rpc
->
smadr
+
pos
);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMENR
,
smenr
);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMCR
,
smcr
);
ret
=
wait_msg_xfer_end
(
rpc
);
if
(
ret
)
...
...
@@ -448,14 +492,16 @@ int rpcif_manual_xfer(struct rpcif *rpc)
break
;
}
while
(
pos
<
rpc
->
xferlen
)
{
u32
nbytes
=
rpc
->
xferlen
-
pos
;
u32
data
[
2
];
u32
bytes_left
=
rpc
->
xferlen
-
pos
;
u32
nbytes
,
data
[
2
];
if
(
nbytes
>
max
)
nbytes
=
max
;
/* nbytes may only be 1, 2, 4, or 8 */
nbytes
=
bytes_left
>=
max
?
max
:
(
1
<<
ilog2
(
bytes_left
))
;
regmap_write
(
rpc
->
regmap
,
RPCIF_SMADR
,
rpc
->
smadr
+
pos
);
smenr
&=
~
RPCIF_SMENR_SPIDE
(
0xF
);
smenr
|=
RPCIF_SMENR_SPIDE
(
rpcif_bits_set
(
rpc
,
nbytes
));
regmap_write
(
rpc
->
regmap
,
RPCIF_SMENR
,
smenr
);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMCR
,
rpc
->
smcr
|
RPCIF_SMCR_SPIE
);
...
...
@@ -463,18 +509,14 @@ int rpcif_manual_xfer(struct rpcif *rpc)
if
(
ret
)
goto
err_out
;
if
(
nbytes
>
4
)
{
if
(
nbytes
==
8
)
{
regmap_read
(
rpc
->
regmap
,
RPCIF_SMRDR1
,
&
data
[
0
]);
regmap_read
(
rpc
->
regmap
,
RPCIF_SMRDR0
,
&
data
[
1
]);
}
else
if
(
nbytes
>
2
)
{
regmap_read
(
rpc
->
regmap
,
RPCIF_SMRDR0
,
&
data
[
0
]);
}
else
{
}
else
{
regmap_read
(
rpc
->
regmap
,
RPCIF_SMRDR0
,
&
data
[
0
]);
data
[
0
]
>>=
16
;
}
memcpy
(
rpc
->
buffer
+
pos
,
data
,
nbytes
);
...
...
@@ -502,6 +544,48 @@ int rpcif_manual_xfer(struct rpcif *rpc)
}
EXPORT_SYMBOL
(
rpcif_manual_xfer
);
static
void
memcpy_fromio_readw
(
void
*
to
,
const
void
__iomem
*
from
,
size_t
count
)
{
const
int
maxw
=
(
IS_ENABLED
(
CONFIG_64BIT
))
?
8
:
4
;
u8
buf
[
2
];
if
(
count
&&
((
unsigned
long
)
from
&
1
))
{
*
(
u16
*
)
buf
=
__raw_readw
((
void
__iomem
*
)((
unsigned
long
)
from
&
~
1
));
*
(
u8
*
)
to
=
buf
[
1
];
from
++
;
to
++
;
count
--
;
}
while
(
count
>=
2
&&
!
IS_ALIGNED
((
unsigned
long
)
from
,
maxw
))
{
*
(
u16
*
)
to
=
__raw_readw
(
from
);
from
+=
2
;
to
+=
2
;
count
-=
2
;
}
while
(
count
>=
maxw
)
{
#ifdef CONFIG_64BIT
*
(
u64
*
)
to
=
__raw_readq
(
from
);
#else
*
(
u32
*
)
to
=
__raw_readl
(
from
);
#endif
from
+=
maxw
;
to
+=
maxw
;
count
-=
maxw
;
}
while
(
count
>=
2
)
{
*
(
u16
*
)
to
=
__raw_readw
(
from
);
from
+=
2
;
to
+=
2
;
count
-=
2
;
}
if
(
count
)
{
*
(
u16
*
)
buf
=
__raw_readw
(
from
);
*
(
u8
*
)
to
=
buf
[
0
];
}
}
ssize_t
rpcif_dirmap_read
(
struct
rpcif
*
rpc
,
u64
offs
,
size_t
len
,
void
*
buf
)
{
loff_t
from
=
offs
&
(
RPCIF_DIRMAP_SIZE
-
1
);
...
...
@@ -523,7 +607,10 @@ ssize_t rpcif_dirmap_read(struct rpcif *rpc, u64 offs, size_t len, void *buf)
regmap_write
(
rpc
->
regmap
,
RPCIF_DRDMCR
,
rpc
->
dummy
);
regmap_write
(
rpc
->
regmap
,
RPCIF_DRDRENR
,
rpc
->
ddr
);
memcpy_fromio
(
buf
,
rpc
->
dirmap
+
from
,
len
);
if
(
rpc
->
bus_size
==
2
)
memcpy_fromio_readw
(
buf
,
rpc
->
dirmap
+
from
,
len
);
else
memcpy_fromio
(
buf
,
rpc
->
dirmap
+
from
,
len
);
pm_runtime_put
(
rpc
->
dev
);
...
...
This diff is collapsed.
Click to expand it.
include/memory/renesas-rpc-if.h
View file @
d611d7ea
...
...
@@ -59,6 +59,7 @@ struct rpcif_op {
struct
rpcif
{
struct
device
*
dev
;
void
__iomem
*
base
;
void
__iomem
*
dirmap
;
struct
regmap
*
regmap
;
struct
reset_control
*
rstc
;
...
...
This diff is collapsed.
Click to expand it.
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