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
Oct 10, 2021
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:
...
@@ -33,6 +33,7 @@ properties:
-
renesas,r8a77970-rpc-if
# R-Car V3M
-
renesas,r8a77970-rpc-if
# R-Car V3M
-
renesas,r8a77980-rpc-if
# R-Car V3H
-
renesas,r8a77980-rpc-if
# R-Car V3H
-
renesas,r8a77995-rpc-if
# R-Car D3
-
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
-
const
:
renesas,rcar-gen3-rpc-if
# a generic R-Car gen3 or RZ/G2 device
reg
:
reg
:
...
...
drivers/memory/Kconfig
View file @
d611d7ea
...
@@ -210,6 +210,7 @@ config RENESAS_RPCIF
...
@@ -210,6 +210,7 @@ config RENESAS_RPCIF
tristate "Renesas RPC-IF driver"
tristate "Renesas RPC-IF driver"
depends on ARCH_RENESAS || COMPILE_TEST
depends on ARCH_RENESAS || COMPILE_TEST
select REGMAP_MMIO
select REGMAP_MMIO
select RESET_CONTROLLER
help
help
This supports Renesas R-Car Gen3 or RZ/G2 RPC-IF which provides
This supports Renesas R-Car Gen3 or RZ/G2 RPC-IF which provides
either SPI host or HyperFlash. You'll have to select individual
either SPI host or HyperFlash. You'll have to select individual
...
...
drivers/memory/renesas-rpc-if.c
View file @
d611d7ea
...
@@ -160,10 +160,61 @@ static const struct regmap_access_table rpcif_volatile_table = {
...
@@ -160,10 +160,61 @@ static const struct regmap_access_table rpcif_volatile_table = {
.
n_yes_ranges
=
ARRAY_SIZE
(
rpcif_volatile_ranges
),
.
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
=
{
static
const
struct
regmap_config
rpcif_regmap_config
=
{
.
reg_bits
=
32
,
.
reg_bits
=
32
,
.
val_bits
=
32
,
.
val_bits
=
32
,
.
reg_stride
=
4
,
.
reg_stride
=
4
,
.
reg_read
=
rpcif_reg_read
,
.
reg_write
=
rpcif_reg_write
,
.
fast_io
=
true
,
.
fast_io
=
true
,
.
max_register
=
RPCIF_PHYINT
,
.
max_register
=
RPCIF_PHYINT
,
.
volatile_table
=
&
rpcif_volatile_table
,
.
volatile_table
=
&
rpcif_volatile_table
,
...
@@ -173,17 +224,15 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
...
@@ -173,17 +224,15 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
{
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
resource
*
res
;
struct
resource
*
res
;
void
__iomem
*
base
;
rpc
->
dev
=
dev
;
rpc
->
dev
=
dev
;
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"regs"
);
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"regs"
);
base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
rpc
->
base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
base
))
if
(
IS_ERR
(
rpc
->
base
))
return
PTR_ERR
(
base
);
return
PTR_ERR
(
rpc
->
base
);
rpc
->
regmap
=
devm_regmap_init_mmio
(
&
pdev
->
dev
,
base
,
rpc
->
regmap
=
devm_regmap_init
(
&
pdev
->
dev
,
NULL
,
rpc
,
&
rpcif_regmap_config
);
&
rpcif_regmap_config
);
if
(
IS_ERR
(
rpc
->
regmap
))
{
if
(
IS_ERR
(
rpc
->
regmap
))
{
dev_err
(
&
pdev
->
dev
,
dev_err
(
&
pdev
->
dev
,
"failed to init regmap for rpcif, error %ld
\n
"
,
"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,
...
@@ -354,20 +403,16 @@ void rpcif_prepare(struct rpcif *rpc, const struct rpcif_op *op, u64 *offs,
nbytes
=
op
->
data
.
nbytes
;
nbytes
=
op
->
data
.
nbytes
;
rpc
->
xferlen
=
nbytes
;
rpc
->
xferlen
=
nbytes
;
rpc
->
enable
|=
RPCIF_SMENR_SPIDE
(
rpcif_bits_set
(
rpc
,
nbytes
))
|
rpc
->
enable
|=
RPCIF_SMENR_SPIDB
(
rpcif_bit_size
(
op
->
data
.
buswidth
));
RPCIF_SMENR_SPIDB
(
rpcif_bit_size
(
op
->
data
.
buswidth
));
}
}
}
}
EXPORT_SYMBOL
(
rpcif_prepare
);
EXPORT_SYMBOL
(
rpcif_prepare
);
int
rpcif_manual_xfer
(
struct
rpcif
*
rpc
)
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
;
int
ret
=
0
;
if
(
rpc
->
bus_size
==
2
)
max
=
8
;
pm_runtime_get_sync
(
rpc
->
dev
);
pm_runtime_get_sync
(
rpc
->
dev
);
regmap_update_bits
(
rpc
->
regmap
,
RPCIF_PHYCNT
,
regmap_update_bits
(
rpc
->
regmap
,
RPCIF_PHYCNT
,
...
@@ -378,37 +423,36 @@ int rpcif_manual_xfer(struct rpcif *rpc)
...
@@ -378,37 +423,36 @@ int rpcif_manual_xfer(struct rpcif *rpc)
regmap_write
(
rpc
->
regmap
,
RPCIF_SMOPR
,
rpc
->
option
);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMOPR
,
rpc
->
option
);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMDMCR
,
rpc
->
dummy
);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMDMCR
,
rpc
->
dummy
);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMDRENR
,
rpc
->
ddr
);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMDRENR
,
rpc
->
ddr
);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMADR
,
rpc
->
smadr
);
smenr
=
rpc
->
enable
;
smenr
=
rpc
->
enable
;
switch
(
rpc
->
dir
)
{
switch
(
rpc
->
dir
)
{
case
RPCIF_DATA_OUT
:
case
RPCIF_DATA_OUT
:
while
(
pos
<
rpc
->
xferlen
)
{
while
(
pos
<
rpc
->
xferlen
)
{
u32
nbytes
=
rpc
->
xferlen
-
pos
;
u32
bytes_left
=
rpc
->
xferlen
-
pos
;
u32
data
[
2
];
u32
nbytes
,
data
[
2
];
smcr
=
rpc
->
smcr
|
RPCIF_SMCR_SPIE
;
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
;
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
);
memcpy
(
data
,
rpc
->
buffer
+
pos
,
nbytes
);
if
(
nbytes
>
4
)
{
if
(
nbytes
==
8
)
{
regmap_write
(
rpc
->
regmap
,
RPCIF_SMWDR1
,
regmap_write
(
rpc
->
regmap
,
RPCIF_SMWDR1
,
data
[
0
]);
data
[
0
]);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMWDR0
,
regmap_write
(
rpc
->
regmap
,
RPCIF_SMWDR0
,
data
[
1
]);
data
[
1
]);
}
else
if
(
nbytes
>
2
)
{
}
else
{
regmap_write
(
rpc
->
regmap
,
RPCIF_SMWDR0
,
regmap_write
(
rpc
->
regmap
,
RPCIF_SMWDR0
,
data
[
0
]);
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
);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMCR
,
smcr
);
ret
=
wait_msg_xfer_end
(
rpc
);
ret
=
wait_msg_xfer_end
(
rpc
);
if
(
ret
)
if
(
ret
)
...
@@ -448,14 +492,16 @@ int rpcif_manual_xfer(struct rpcif *rpc)
...
@@ -448,14 +492,16 @@ int rpcif_manual_xfer(struct rpcif *rpc)
break
;
break
;
}
}
while
(
pos
<
rpc
->
xferlen
)
{
while
(
pos
<
rpc
->
xferlen
)
{
u32
nbytes
=
rpc
->
xferlen
-
pos
;
u32
bytes_left
=
rpc
->
xferlen
-
pos
;
u32
data
[
2
];
u32
nbytes
,
data
[
2
];
if
(
nbytes
>
max
)
/* nbytes may only be 1, 2, 4, or 8 */
nbytes
=
max
;
nbytes
=
bytes_left
>=
max
?
max
:
(
1
<<
ilog2
(
bytes_left
))
;
regmap_write
(
rpc
->
regmap
,
RPCIF_SMADR
,
regmap_write
(
rpc
->
regmap
,
RPCIF_SMADR
,
rpc
->
smadr
+
pos
);
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_SMENR
,
smenr
);
regmap_write
(
rpc
->
regmap
,
RPCIF_SMCR
,
regmap_write
(
rpc
->
regmap
,
RPCIF_SMCR
,
rpc
->
smcr
|
RPCIF_SMCR_SPIE
);
rpc
->
smcr
|
RPCIF_SMCR_SPIE
);
...
@@ -463,18 +509,14 @@ int rpcif_manual_xfer(struct rpcif *rpc)
...
@@ -463,18 +509,14 @@ int rpcif_manual_xfer(struct rpcif *rpc)
if
(
ret
)
if
(
ret
)
goto
err_out
;
goto
err_out
;
if
(
nbytes
>
4
)
{
if
(
nbytes
==
8
)
{
regmap_read
(
rpc
->
regmap
,
RPCIF_SMRDR1
,
regmap_read
(
rpc
->
regmap
,
RPCIF_SMRDR1
,
&
data
[
0
]);
&
data
[
0
]);
regmap_read
(
rpc
->
regmap
,
RPCIF_SMRDR0
,
regmap_read
(
rpc
->
regmap
,
RPCIF_SMRDR0
,
&
data
[
1
]);
&
data
[
1
]);
}
else
if
(
nbytes
>
2
)
{
}
else
{
regmap_read
(
rpc
->
regmap
,
RPCIF_SMRDR0
,
&
data
[
0
]);
}
else
{
regmap_read
(
rpc
->
regmap
,
RPCIF_SMRDR0
,
regmap_read
(
rpc
->
regmap
,
RPCIF_SMRDR0
,
&
data
[
0
]);
&
data
[
0
]);
data
[
0
]
>>=
16
;
}
}
memcpy
(
rpc
->
buffer
+
pos
,
data
,
nbytes
);
memcpy
(
rpc
->
buffer
+
pos
,
data
,
nbytes
);
...
@@ -502,6 +544,48 @@ int rpcif_manual_xfer(struct rpcif *rpc)
...
@@ -502,6 +544,48 @@ int rpcif_manual_xfer(struct rpcif *rpc)
}
}
EXPORT_SYMBOL
(
rpcif_manual_xfer
);
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
)
ssize_t
rpcif_dirmap_read
(
struct
rpcif
*
rpc
,
u64
offs
,
size_t
len
,
void
*
buf
)
{
{
loff_t
from
=
offs
&
(
RPCIF_DIRMAP_SIZE
-
1
);
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)
...
@@ -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_DRDMCR
,
rpc
->
dummy
);
regmap_write
(
rpc
->
regmap
,
RPCIF_DRDRENR
,
rpc
->
ddr
);
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
);
pm_runtime_put
(
rpc
->
dev
);
...
...
include/memory/renesas-rpc-if.h
View file @
d611d7ea
...
@@ -59,6 +59,7 @@ struct rpcif_op {
...
@@ -59,6 +59,7 @@ struct rpcif_op {
struct
rpcif
{
struct
rpcif
{
struct
device
*
dev
;
struct
device
*
dev
;
void
__iomem
*
base
;
void
__iomem
*
dirmap
;
void
__iomem
*
dirmap
;
struct
regmap
*
regmap
;
struct
regmap
*
regmap
;
struct
reset_control
*
rstc
;
struct
reset_control
*
rstc
;
...
...
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