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
75c971dd
Commit
75c971dd
authored
Aug 15, 2022
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'spi/for-5.20' into spi-6.0
parents
568035b0
2fd92c7b
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
112 additions
and
39 deletions
+112
-39
Documentation/devicetree/bindings/spi/cdns,qspi-nor-peripheral-props.yaml
...vicetree/bindings/spi/cdns,qspi-nor-peripheral-props.yaml
+1
-1
Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml
Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml
+1
-1
Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
...ntation/devicetree/bindings/spi/spi-peripheral-props.yaml
+1
-1
MAINTAINERS
MAINTAINERS
+1
-1
drivers/spi/spi-meson-spicc.c
drivers/spi/spi-meson-spicc.c
+101
-28
drivers/spi/spi.c
drivers/spi/spi.c
+7
-7
No files found.
Documentation/devicetree/bindings/spi/cdns,qspi-nor-peripheral-props.yaml
View file @
75c971dd
...
@@ -10,7 +10,7 @@ description:
...
@@ -10,7 +10,7 @@ description:
See spi-peripheral-props.yaml for more info.
See spi-peripheral-props.yaml for more info.
maintainers
:
maintainers
:
-
Pratyush Yadav <p.yadav
@ti.com>
-
Vaishnav Achath <vaishnav.a
@ti.com>
properties
:
properties
:
# cdns,qspi-nor.yaml
# cdns,qspi-nor.yaml
...
...
Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml
View file @
75c971dd
...
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
...
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title
:
Cadence Quad SPI controller
title
:
Cadence Quad SPI controller
maintainers
:
maintainers
:
-
Pratyush Yadav <p.yadav
@ti.com>
-
Vaishnav Achath <vaishnav.a
@ti.com>
allOf
:
allOf
:
-
$ref
:
spi-controller.yaml#
-
$ref
:
spi-controller.yaml#
...
...
Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
View file @
75c971dd
...
@@ -16,7 +16,7 @@ description:
...
@@ -16,7 +16,7 @@ description:
their own separate schema that should be referenced from here.
their own separate schema that should be referenced from here.
maintainers
:
maintainers
:
-
Pratyush Yadav <p.yadav@ti.com
>
-
Mark Brown <broonie@kernel.org
>
properties
:
properties
:
reg
:
reg
:
...
...
MAINTAINERS
View file @
75c971dd
...
@@ -2178,7 +2178,7 @@ M: Jean-Marie Verdun <verdun@hpe.com>
...
@@ -2178,7 +2178,7 @@ M: Jean-Marie Verdun <verdun@hpe.com>
M: Nick Hawkins <nick.hawkins@hpe.com>
M: Nick Hawkins <nick.hawkins@hpe.com>
S: Maintained
S: Maintained
F: Documentation/devicetree/bindings/arm/hpe,gxp.yaml
F: Documentation/devicetree/bindings/arm/hpe,gxp.yaml
F: Documentation/devicetree/bindings/spi/hpe,gxp-spi.yaml
F: Documentation/devicetree/bindings/spi/hpe,gxp-spi
fi
.yaml
F: Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml
F: Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml
F: arch/arm/boot/dts/hpe-bmc*
F: arch/arm/boot/dts/hpe-bmc*
F: arch/arm/boot/dts/hpe-gxp*
F: arch/arm/boot/dts/hpe-gxp*
...
...
drivers/spi/spi-meson-spicc.c
View file @
75c971dd
...
@@ -156,6 +156,7 @@ struct meson_spicc_device {
...
@@ -156,6 +156,7 @@ struct meson_spicc_device {
void
__iomem
*
base
;
void
__iomem
*
base
;
struct
clk
*
core
;
struct
clk
*
core
;
struct
clk
*
pclk
;
struct
clk
*
pclk
;
struct
clk_divider
pow2_div
;
struct
clk
*
clk
;
struct
clk
*
clk
;
struct
spi_message
*
message
;
struct
spi_message
*
message
;
struct
spi_transfer
*
xfer
;
struct
spi_transfer
*
xfer
;
...
@@ -168,6 +169,8 @@ struct meson_spicc_device {
...
@@ -168,6 +169,8 @@ struct meson_spicc_device {
unsigned
long
xfer_remain
;
unsigned
long
xfer_remain
;
};
};
#define pow2_clk_to_spicc(_div) container_of(_div, struct meson_spicc_device, pow2_div)
static
void
meson_spicc_oen_enable
(
struct
meson_spicc_device
*
spicc
)
static
void
meson_spicc_oen_enable
(
struct
meson_spicc_device
*
spicc
)
{
{
u32
conf
;
u32
conf
;
...
@@ -421,7 +424,7 @@ static int meson_spicc_prepare_message(struct spi_master *master,
...
@@ -421,7 +424,7 @@ static int meson_spicc_prepare_message(struct spi_master *master,
{
{
struct
meson_spicc_device
*
spicc
=
spi_master_get_devdata
(
master
);
struct
meson_spicc_device
*
spicc
=
spi_master_get_devdata
(
master
);
struct
spi_device
*
spi
=
message
->
spi
;
struct
spi_device
*
spi
=
message
->
spi
;
u32
conf
=
0
;
u32
conf
=
readl_relaxed
(
spicc
->
base
+
SPICC_CONREG
)
&
SPICC_DATARATE_MASK
;
/* Store current message */
/* Store current message */
spicc
->
message
=
message
;
spicc
->
message
=
message
;
...
@@ -458,8 +461,6 @@ static int meson_spicc_prepare_message(struct spi_master *master,
...
@@ -458,8 +461,6 @@ static int meson_spicc_prepare_message(struct spi_master *master,
/* Select CS */
/* Select CS */
conf
|=
FIELD_PREP
(
SPICC_CS_MASK
,
spi
->
chip_select
);
conf
|=
FIELD_PREP
(
SPICC_CS_MASK
,
spi
->
chip_select
);
/* Default Clock rate core/4 */
/* Default 8bit word */
/* Default 8bit word */
conf
|=
FIELD_PREP
(
SPICC_BITLENGTH_MASK
,
8
-
1
);
conf
|=
FIELD_PREP
(
SPICC_BITLENGTH_MASK
,
8
-
1
);
...
@@ -476,12 +477,16 @@ static int meson_spicc_prepare_message(struct spi_master *master,
...
@@ -476,12 +477,16 @@ static int meson_spicc_prepare_message(struct spi_master *master,
static
int
meson_spicc_unprepare_transfer
(
struct
spi_master
*
master
)
static
int
meson_spicc_unprepare_transfer
(
struct
spi_master
*
master
)
{
{
struct
meson_spicc_device
*
spicc
=
spi_master_get_devdata
(
master
);
struct
meson_spicc_device
*
spicc
=
spi_master_get_devdata
(
master
);
u32
conf
=
readl_relaxed
(
spicc
->
base
+
SPICC_CONREG
)
&
SPICC_DATARATE_MASK
;
/* Disable all IRQs */
/* Disable all IRQs */
writel
(
0
,
spicc
->
base
+
SPICC_INTREG
);
writel
(
0
,
spicc
->
base
+
SPICC_INTREG
);
device_reset_optional
(
&
spicc
->
pdev
->
dev
);
device_reset_optional
(
&
spicc
->
pdev
->
dev
);
/* Set default configuration, keeping datarate field */
writel_relaxed
(
conf
,
spicc
->
base
+
SPICC_CONREG
);
return
0
;
return
0
;
}
}
...
@@ -518,14 +523,60 @@ static void meson_spicc_cleanup(struct spi_device *spi)
...
@@ -518,14 +523,60 @@ static void meson_spicc_cleanup(struct spi_device *spi)
* Clk path for G12A series:
* Clk path for G12A series:
* pclk -> pow2 fixed div -> pow2 div -> mux -> out
* pclk -> pow2 fixed div -> pow2 div -> mux -> out
* pclk -> enh fixed div -> enh div -> mux -> out
* pclk -> enh fixed div -> enh div -> mux -> out
*
* The pow2 divider is tied to the controller HW state, and the
* divider is only valid when the controller is initialized.
*
* A set of clock ops is added to make sure we don't read/set this
* clock rate while the controller is in an unknown state.
*/
*/
static
int
meson_spicc_clk_init
(
struct
meson_spicc_device
*
spicc
)
static
unsigned
long
meson_spicc_pow2_recalc_rate
(
struct
clk_hw
*
hw
,
unsigned
long
parent_rate
)
{
struct
clk_divider
*
divider
=
to_clk_divider
(
hw
);
struct
meson_spicc_device
*
spicc
=
pow2_clk_to_spicc
(
divider
);
if
(
!
spicc
->
master
->
cur_msg
||
!
spicc
->
master
->
busy
)
return
0
;
return
clk_divider_ops
.
recalc_rate
(
hw
,
parent_rate
);
}
static
int
meson_spicc_pow2_determine_rate
(
struct
clk_hw
*
hw
,
struct
clk_rate_request
*
req
)
{
struct
clk_divider
*
divider
=
to_clk_divider
(
hw
);
struct
meson_spicc_device
*
spicc
=
pow2_clk_to_spicc
(
divider
);
if
(
!
spicc
->
master
->
cur_msg
||
!
spicc
->
master
->
busy
)
return
-
EINVAL
;
return
clk_divider_ops
.
determine_rate
(
hw
,
req
);
}
static
int
meson_spicc_pow2_set_rate
(
struct
clk_hw
*
hw
,
unsigned
long
rate
,
unsigned
long
parent_rate
)
{
struct
clk_divider
*
divider
=
to_clk_divider
(
hw
);
struct
meson_spicc_device
*
spicc
=
pow2_clk_to_spicc
(
divider
);
if
(
!
spicc
->
master
->
cur_msg
||
!
spicc
->
master
->
busy
)
return
-
EINVAL
;
return
clk_divider_ops
.
set_rate
(
hw
,
rate
,
parent_rate
);
}
const
struct
clk_ops
meson_spicc_pow2_clk_ops
=
{
.
recalc_rate
=
meson_spicc_pow2_recalc_rate
,
.
determine_rate
=
meson_spicc_pow2_determine_rate
,
.
set_rate
=
meson_spicc_pow2_set_rate
,
};
static
int
meson_spicc_pow2_clk_init
(
struct
meson_spicc_device
*
spicc
)
{
{
struct
device
*
dev
=
&
spicc
->
pdev
->
dev
;
struct
device
*
dev
=
&
spicc
->
pdev
->
dev
;
struct
clk_fixed_factor
*
pow2_fixed_div
,
*
enh_fixed_div
;
struct
clk_fixed_factor
*
pow2_fixed_div
;
struct
clk_divider
*
pow2_div
,
*
enh_div
;
struct
clk_mux
*
mux
;
struct
clk_init_data
init
;
struct
clk_init_data
init
;
struct
clk
*
clk
;
struct
clk
*
clk
;
struct
clk_parent_data
parent_data
[
2
];
struct
clk_parent_data
parent_data
[
2
];
...
@@ -560,31 +611,45 @@ static int meson_spicc_clk_init(struct meson_spicc_device *spicc)
...
@@ -560,31 +611,45 @@ static int meson_spicc_clk_init(struct meson_spicc_device *spicc)
if
(
WARN_ON
(
IS_ERR
(
clk
)))
if
(
WARN_ON
(
IS_ERR
(
clk
)))
return
PTR_ERR
(
clk
);
return
PTR_ERR
(
clk
);
pow2_div
=
devm_kzalloc
(
dev
,
sizeof
(
*
pow2_div
),
GFP_KERNEL
);
if
(
!
pow2_div
)
return
-
ENOMEM
;
snprintf
(
name
,
sizeof
(
name
),
"%s#pow2_div"
,
dev_name
(
dev
));
snprintf
(
name
,
sizeof
(
name
),
"%s#pow2_div"
,
dev_name
(
dev
));
init
.
name
=
name
;
init
.
name
=
name
;
init
.
ops
=
&
clk_divider_ops
;
init
.
ops
=
&
meson_spicc_pow2_clk_ops
;
init
.
flags
=
CLK_SET_RATE_PARENT
;
/*
* Set NOCACHE here to make sure we read the actual HW value
* since we reset the HW after each transfer.
*/
init
.
flags
=
CLK_SET_RATE_PARENT
|
CLK_GET_RATE_NOCACHE
;
parent_data
[
0
].
hw
=
&
pow2_fixed_div
->
hw
;
parent_data
[
0
].
hw
=
&
pow2_fixed_div
->
hw
;
init
.
num_parents
=
1
;
init
.
num_parents
=
1
;
pow2_div
->
shift
=
16
,
spicc
->
pow2_div
.
shift
=
16
,
pow2_div
->
width
=
3
,
spicc
->
pow2_div
.
width
=
3
,
pow2_div
->
flags
=
CLK_DIVIDER_POWER_OF_TWO
,
spicc
->
pow2_div
.
flags
=
CLK_DIVIDER_POWER_OF_TWO
,
pow2_div
->
reg
=
spicc
->
base
+
SPICC_CONREG
;
spicc
->
pow2_div
.
reg
=
spicc
->
base
+
SPICC_CONREG
;
pow2_div
->
hw
.
init
=
&
init
;
spicc
->
pow2_div
.
hw
.
init
=
&
init
;
clk
=
devm_clk_register
(
dev
,
&
pow2_div
->
hw
);
spicc
->
clk
=
devm_clk_register
(
dev
,
&
spicc
->
pow2_div
.
hw
);
if
(
WARN_ON
(
IS_ERR
(
clk
)))
if
(
WARN_ON
(
IS_ERR
(
spicc
->
clk
)))
return
PTR_ERR
(
clk
);
return
PTR_ERR
(
spicc
->
clk
);
if
(
!
spicc
->
data
->
has_enhance_clk_div
)
{
return
0
;
spicc
->
clk
=
clk
;
}
return
0
;
}
static
int
meson_spicc_enh_clk_init
(
struct
meson_spicc_device
*
spicc
)
{
struct
device
*
dev
=
&
spicc
->
pdev
->
dev
;
struct
clk_fixed_factor
*
enh_fixed_div
;
struct
clk_divider
*
enh_div
;
struct
clk_mux
*
mux
;
struct
clk_init_data
init
;
struct
clk
*
clk
;
struct
clk_parent_data
parent_data
[
2
];
char
name
[
64
];
memset
(
&
init
,
0
,
sizeof
(
init
));
memset
(
&
parent_data
,
0
,
sizeof
(
parent_data
));
init
.
parent_data
=
parent_data
;
/* algorithm for enh div: rate = freq / 2 / (N + 1) */
/* algorithm for enh div: rate = freq / 2 / (N + 1) */
...
@@ -637,7 +702,7 @@ static int meson_spicc_clk_init(struct meson_spicc_device *spicc)
...
@@ -637,7 +702,7 @@ static int meson_spicc_clk_init(struct meson_spicc_device *spicc)
snprintf
(
name
,
sizeof
(
name
),
"%s#sel"
,
dev_name
(
dev
));
snprintf
(
name
,
sizeof
(
name
),
"%s#sel"
,
dev_name
(
dev
));
init
.
name
=
name
;
init
.
name
=
name
;
init
.
ops
=
&
clk_mux_ops
;
init
.
ops
=
&
clk_mux_ops
;
parent_data
[
0
].
hw
=
&
pow2_div
->
hw
;
parent_data
[
0
].
hw
=
&
spicc
->
pow2_div
.
hw
;
parent_data
[
1
].
hw
=
&
enh_div
->
hw
;
parent_data
[
1
].
hw
=
&
enh_div
->
hw
;
init
.
num_parents
=
2
;
init
.
num_parents
=
2
;
init
.
flags
=
CLK_SET_RATE_PARENT
;
init
.
flags
=
CLK_SET_RATE_PARENT
;
...
@@ -754,12 +819,20 @@ static int meson_spicc_probe(struct platform_device *pdev)
...
@@ -754,12 +819,20 @@ static int meson_spicc_probe(struct platform_device *pdev)
meson_spicc_oen_enable
(
spicc
);
meson_spicc_oen_enable
(
spicc
);
ret
=
meson_spicc_clk_init
(
spicc
);
ret
=
meson_spicc_
pow2_
clk_init
(
spicc
);
if
(
ret
)
{
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"clock registration failed
\n
"
);
dev_err
(
&
pdev
->
dev
,
"
pow2
clock registration failed
\n
"
);
goto
out_clk
;
goto
out_clk
;
}
}
if
(
spicc
->
data
->
has_enhance_clk_div
)
{
ret
=
meson_spicc_enh_clk_init
(
spicc
);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"clock registration failed
\n
"
);
goto
out_clk
;
}
}
ret
=
devm_spi_register_master
(
&
pdev
->
dev
,
master
);
ret
=
devm_spi_register_master
(
&
pdev
->
dev
,
master
);
if
(
ret
)
{
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"spi master registration failed
\n
"
);
dev_err
(
&
pdev
->
dev
,
"spi master registration failed
\n
"
);
...
...
drivers/spi/spi.c
View file @
75c971dd
...
@@ -95,7 +95,7 @@ static ssize_t driver_override_show(struct device *dev,
...
@@ -95,7 +95,7 @@ static ssize_t driver_override_show(struct device *dev,
}
}
static
DEVICE_ATTR_RW
(
driver_override
);
static
DEVICE_ATTR_RW
(
driver_override
);
static
struct
spi_statistics
*
spi_alloc_pcpu_stats
(
struct
device
*
dev
)
static
struct
spi_statistics
__percpu
*
spi_alloc_pcpu_stats
(
struct
device
*
dev
)
{
{
struct
spi_statistics
__percpu
*
pcpu_stats
;
struct
spi_statistics
__percpu
*
pcpu_stats
;
...
@@ -162,7 +162,7 @@ static struct device_attribute dev_attr_spi_device_##field = { \
...
@@ -162,7 +162,7 @@ static struct device_attribute dev_attr_spi_device_##field = { \
}
}
#define SPI_STATISTICS_SHOW_NAME(name, file, field) \
#define SPI_STATISTICS_SHOW_NAME(name, file, field) \
static ssize_t spi_statistics_##name##_show(struct spi_statistics *stat, \
static ssize_t spi_statistics_##name##_show(struct spi_statistics
__percpu
*stat, \
char *buf) \
char *buf) \
{ \
{ \
ssize_t len; \
ssize_t len; \
...
@@ -309,7 +309,7 @@ static const struct attribute_group *spi_master_groups[] = {
...
@@ -309,7 +309,7 @@ static const struct attribute_group *spi_master_groups[] = {
NULL
,
NULL
,
};
};
static
void
spi_statistics_add_transfer_stats
(
struct
spi_statistics
*
pcpu_stats
,
static
void
spi_statistics_add_transfer_stats
(
struct
spi_statistics
__percpu
*
pcpu_stats
,
struct
spi_transfer
*
xfer
,
struct
spi_transfer
*
xfer
,
struct
spi_controller
*
ctlr
)
struct
spi_controller
*
ctlr
)
{
{
...
@@ -1275,8 +1275,8 @@ static int spi_transfer_wait(struct spi_controller *ctlr,
...
@@ -1275,8 +1275,8 @@ static int spi_transfer_wait(struct spi_controller *ctlr,
struct
spi_message
*
msg
,
struct
spi_message
*
msg
,
struct
spi_transfer
*
xfer
)
struct
spi_transfer
*
xfer
)
{
{
struct
spi_statistics
*
statm
=
ctlr
->
pcpu_statistics
;
struct
spi_statistics
__percpu
*
statm
=
ctlr
->
pcpu_statistics
;
struct
spi_statistics
*
stats
=
msg
->
spi
->
pcpu_statistics
;
struct
spi_statistics
__percpu
*
stats
=
msg
->
spi
->
pcpu_statistics
;
u32
speed_hz
=
xfer
->
speed_hz
;
u32
speed_hz
=
xfer
->
speed_hz
;
unsigned
long
long
ms
;
unsigned
long
long
ms
;
...
@@ -1432,8 +1432,8 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
...
@@ -1432,8 +1432,8 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
struct
spi_transfer
*
xfer
;
struct
spi_transfer
*
xfer
;
bool
keep_cs
=
false
;
bool
keep_cs
=
false
;
int
ret
=
0
;
int
ret
=
0
;
struct
spi_statistics
*
statm
=
ctlr
->
pcpu_statistics
;
struct
spi_statistics
__percpu
*
statm
=
ctlr
->
pcpu_statistics
;
struct
spi_statistics
*
stats
=
msg
->
spi
->
pcpu_statistics
;
struct
spi_statistics
__percpu
*
stats
=
msg
->
spi
->
pcpu_statistics
;
spi_set_cs
(
msg
->
spi
,
true
,
false
);
spi_set_cs
(
msg
->
spi
,
true
,
false
);
...
...
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