mbox series

[v4,0/4] Add dw_mmc support for rk3576

Message ID 20240822212418.982927-1-detlev.casanova@collabora.com
Headers show
Series Add dw_mmc support for rk3576 | expand

Message

Detlev Casanova Aug. 22, 2024, 9:15 p.m. UTC
The SD card controller on the rk3576 SoC stores the phase settings into
the dw_mmc controller, so the code has to be adapted to implement that.

Although the feature can be detected through the USRID register value, the
decision to use it is based on the compatible.

The compatible for rk3576 is added in its own group of compatible to mark
that all devices compatible with rk3576 have internal phase settings and
don't have the ciu-drive and ciu-sample clocks.

Changes since v3:
- Remove internal phase auto detection
- Set compatible in own block, with own dt_parse function
- Add internal_phase variable
- Use function to set clock parameters based on internal_phase variable
  instead of multiple ifs
- Use different commit for skipping phases higher than 270

Changes since v2:
- Drop rockchip,v2-tuning and use compatible-based detection
- Fix coding style

Changes since v1:
- Renamed use-v2-tuning to v2-tuning
- Rewrite v2-tuning description as the hardware feature

Detlev.

Detlev Casanova (2):
  dt-bindings: mmc: Add support for rk3576 dw-mshc
  mmc: dw_mmc-rockchip: Add support for rk3576 SoCs

Shawn Lin (2):
  mmc: dw_mmc-rockchip: Add internal phase support
  mmc: dw_mmc-rockchip: Skip all phases bigger than 270 degrees

 .../bindings/mmc/rockchip-dw-mshc.yaml        |   2 +
 drivers/mmc/host/dw_mmc-rockchip.c            | 220 ++++++++++++++++--
 2 files changed, 207 insertions(+), 15 deletions(-)

Comments

Dragan Simic Aug. 23, 2024, 5:41 a.m. UTC | #1
Hello Detlev,

Please see a comment below.

On 2024-08-22 23:15, Detlev Casanova wrote:
> From: Shawn Lin <shawn.lin@rock-chips.com>
> 
> Some Rockchip devices put the phase settings into the dw_mmc 
> controller.
> 
> When the feature is present, the ciu-drive and ciu-sample clocks are
> not used and the phase configuration is done directly through the mmc
> controller.
> 
> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
> Acked-by: Shawn Lin <shawn.lin@rock-chips.com>
> ---
>  drivers/mmc/host/dw_mmc-rockchip.c | 171 +++++++++++++++++++++++++++--
>  1 file changed, 160 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/mmc/host/dw_mmc-rockchip.c
> b/drivers/mmc/host/dw_mmc-rockchip.c
> index b07190ba4b7a..2748f9bf2691 100644
> --- a/drivers/mmc/host/dw_mmc-rockchip.c
> +++ b/drivers/mmc/host/dw_mmc-rockchip.c
> @@ -15,7 +15,17 @@
>  #include "dw_mmc.h"
>  #include "dw_mmc-pltfm.h"
> 
> -#define RK3288_CLKGEN_DIV	2
> +#define RK3288_CLKGEN_DIV		2
> +#define SDMMC_TIMING_CON0		0x130
> +#define SDMMC_TIMING_CON1		0x134
> +#define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
> +#define ROCKCHIP_MMC_DEGREE_MASK	0x3
> +#define ROCKCHIP_MMC_DEGREE_OFFSET	1
> +#define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
> +#define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << 
> ROCKCHIP_MMC_DELAYNUM_OFFSET)
> +#define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC	60
> +#define HIWORD_UPDATE(val, mask, shift) \
> +		((val) << (shift) | (mask) << ((shift) + 16))
> 
>  static const unsigned int freqs[] = { 100000, 200000, 300000, 400000 
> };
> 
> @@ -24,8 +34,143 @@ struct dw_mci_rockchip_priv_data {
>  	struct clk		*sample_clk;
>  	int			default_sample_phase;
>  	int			num_phases;
> +	int			internal_phase;
>  };

It might be good to declare internal_phase as "unsigned int 
internal_phase:1",
i.e. as a bit field, which isn't going to save some memory in this 
particular
case, but it would show additional attention to detail.
Krzysztof Kozlowski Aug. 23, 2024, 7:36 a.m. UTC | #2
On Thu, Aug 22, 2024 at 05:15:31PM -0400, Detlev Casanova wrote:
> Add the compatible string for rockchip,rk3576-dw-mshc in its own new
> block, for devices that have internal pahse settings instead of external

typo: phase

> clocks.
> 
> Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
> ---
>  Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml | 2 ++

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

Best regards,
Krzysztof
Detlev Casanova Aug. 23, 2024, 1:34 p.m. UTC | #3
Hi Dragan,

On Friday, 23 August 2024 01:41:44 EDT Dragan Simic wrote:
> Hello Detlev,
> 
> Please see a comment below.
> 
> On 2024-08-22 23:15, Detlev Casanova wrote:
> > From: Shawn Lin <shawn.lin@rock-chips.com>
> > 
> > Some Rockchip devices put the phase settings into the dw_mmc
> > controller.
> > 
> > When the feature is present, the ciu-drive and ciu-sample clocks are
> > not used and the phase configuration is done directly through the mmc
> > controller.
> > 
> > Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> > Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
> > Acked-by: Shawn Lin <shawn.lin@rock-chips.com>
> > ---
> > 
> >  drivers/mmc/host/dw_mmc-rockchip.c | 171 +++++++++++++++++++++++++++--
> >  1 file changed, 160 insertions(+), 11 deletions(-)
> > 
> > diff --git a/drivers/mmc/host/dw_mmc-rockchip.c
> > b/drivers/mmc/host/dw_mmc-rockchip.c
> > index b07190ba4b7a..2748f9bf2691 100644
> > --- a/drivers/mmc/host/dw_mmc-rockchip.c
> > +++ b/drivers/mmc/host/dw_mmc-rockchip.c
> > @@ -15,7 +15,17 @@
> > 
> >  #include "dw_mmc.h"
> >  #include "dw_mmc-pltfm.h"
> > 
> > -#define RK3288_CLKGEN_DIV	2
> > +#define RK3288_CLKGEN_DIV		2
> > +#define SDMMC_TIMING_CON0		0x130
> > +#define SDMMC_TIMING_CON1		0x134
> > +#define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
> > +#define ROCKCHIP_MMC_DEGREE_MASK	0x3
> > +#define ROCKCHIP_MMC_DEGREE_OFFSET	1
> > +#define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
> > +#define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff <<
> > ROCKCHIP_MMC_DELAYNUM_OFFSET)
> > +#define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC	60
> > +#define HIWORD_UPDATE(val, mask, shift) \
> > +		((val) << (shift) | (mask) << ((shift) + 16))
> > 
> >  static const unsigned int freqs[] = { 100000, 200000, 300000, 400000
> > 
> > };
> > 
> > @@ -24,8 +34,143 @@ struct dw_mci_rockchip_priv_data {
> > 
> >  	struct clk		*sample_clk;
> >  	int			default_sample_phase;
> >  	int			num_phases;
> > 
> > +	int			internal_phase;
> > 
> >  };
> 
> It might be good to declare internal_phase as "unsigned int
> internal_phase:1",
> i.e. as a bit field, which isn't going to save some memory in this
> particular
> case, but it would show additional attention to detail.

In that case, I would go with a bool instead of int, that makes things even 
clearer.
Dragan Simic Aug. 26, 2024, 2:39 p.m. UTC | #4
Hello Detlev,

On 2024-08-23 15:34, Detlev Casanova wrote:
> On Friday, 23 August 2024 01:41:44 EDT Dragan Simic wrote:
>> Hello Detlev,
>> 
>> Please see a comment below.
>> 
>> On 2024-08-22 23:15, Detlev Casanova wrote:
>> > From: Shawn Lin <shawn.lin@rock-chips.com>
>> >
>> > Some Rockchip devices put the phase settings into the dw_mmc
>> > controller.
>> >
>> > When the feature is present, the ciu-drive and ciu-sample clocks are
>> > not used and the phase configuration is done directly through the mmc
>> > controller.
>> >
>> > Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
>> > Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
>> > Acked-by: Shawn Lin <shawn.lin@rock-chips.com>
>> > ---
>> >
>> >  drivers/mmc/host/dw_mmc-rockchip.c | 171 +++++++++++++++++++++++++++--
>> >  1 file changed, 160 insertions(+), 11 deletions(-)
>> >
>> > diff --git a/drivers/mmc/host/dw_mmc-rockchip.c
>> > b/drivers/mmc/host/dw_mmc-rockchip.c
>> > index b07190ba4b7a..2748f9bf2691 100644
>> > --- a/drivers/mmc/host/dw_mmc-rockchip.c
>> > +++ b/drivers/mmc/host/dw_mmc-rockchip.c
>> > @@ -15,7 +15,17 @@
>> >
>> >  #include "dw_mmc.h"
>> >  #include "dw_mmc-pltfm.h"
>> >
>> > -#define RK3288_CLKGEN_DIV	2
>> > +#define RK3288_CLKGEN_DIV		2
>> > +#define SDMMC_TIMING_CON0		0x130
>> > +#define SDMMC_TIMING_CON1		0x134
>> > +#define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
>> > +#define ROCKCHIP_MMC_DEGREE_MASK	0x3
>> > +#define ROCKCHIP_MMC_DEGREE_OFFSET	1
>> > +#define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
>> > +#define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff <<
>> > ROCKCHIP_MMC_DELAYNUM_OFFSET)
>> > +#define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC	60
>> > +#define HIWORD_UPDATE(val, mask, shift) \
>> > +		((val) << (shift) | (mask) << ((shift) + 16))
>> >
>> >  static const unsigned int freqs[] = { 100000, 200000, 300000, 400000
>> >
>> > };
>> >
>> > @@ -24,8 +34,143 @@ struct dw_mci_rockchip_priv_data {
>> >
>> >  	struct clk		*sample_clk;
>> >  	int			default_sample_phase;
>> >  	int			num_phases;
>> >
>> > +	int			internal_phase;
>> >
>> >  };
>> 
>> It might be good to declare internal_phase as "unsigned int
>> internal_phase:1",
>> i.e. as a bit field, which isn't going to save some memory in this
>> particular
>> case, but it would show additional attention to detail.
> 
> In that case, I would go with a bool instead of int, that makes things
> even clearer.

My suggestion to use "unsigned int internal_phase:1" actually takes
inspiration from the ASoC code, in which such bit fields are used
quite a lot, even when using them actually doesn't save space.

In this particular case, using plain bool would make sense, but I
still think that using an "unsigned int internal_phase:1" bit field
would fit better, because it would show the intention to possibly
save a bit of RAM at some point.  OTOH, I don't think that using
bool with such bit fields would actually work cleanly, because bool
actually resolves to int that's a signed type.
Detlev Casanova Aug. 26, 2024, 6:44 p.m. UTC | #5
On Monday, 26 August 2024 10:39:58 EDT Dragan Simic wrote:
> Hello Detlev,
> 
> On 2024-08-23 15:34, Detlev Casanova wrote:
> > On Friday, 23 August 2024 01:41:44 EDT Dragan Simic wrote:
> >> Hello Detlev,
> >> 
> >> Please see a comment below.
> >> 
> >> On 2024-08-22 23:15, Detlev Casanova wrote:
> >> > From: Shawn Lin <shawn.lin@rock-chips.com>
> >> > 
> >> > Some Rockchip devices put the phase settings into the dw_mmc
> >> > controller.
> >> > 
> >> > When the feature is present, the ciu-drive and ciu-sample clocks are
> >> > not used and the phase configuration is done directly through the mmc
> >> > controller.
> >> > 
> >> > Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> >> > Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
> >> > Acked-by: Shawn Lin <shawn.lin@rock-chips.com>
> >> > ---
> >> > 
> >> >  drivers/mmc/host/dw_mmc-rockchip.c | 171 +++++++++++++++++++++++++++--
> >> >  1 file changed, 160 insertions(+), 11 deletions(-)
> >> > 
> >> > diff --git a/drivers/mmc/host/dw_mmc-rockchip.c
> >> > b/drivers/mmc/host/dw_mmc-rockchip.c
> >> > index b07190ba4b7a..2748f9bf2691 100644
> >> > --- a/drivers/mmc/host/dw_mmc-rockchip.c
> >> > +++ b/drivers/mmc/host/dw_mmc-rockchip.c
> >> > @@ -15,7 +15,17 @@
> >> > 
> >> >  #include "dw_mmc.h"
> >> >  #include "dw_mmc-pltfm.h"
> >> > 
> >> > -#define RK3288_CLKGEN_DIV	2
> >> > +#define RK3288_CLKGEN_DIV		2
> >> > +#define SDMMC_TIMING_CON0		0x130
> >> > +#define SDMMC_TIMING_CON1		0x134
> >> > +#define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
> >> > +#define ROCKCHIP_MMC_DEGREE_MASK	0x3
> >> > +#define ROCKCHIP_MMC_DEGREE_OFFSET	1
> >> > +#define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
> >> > +#define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff <<
> >> > ROCKCHIP_MMC_DELAYNUM_OFFSET)
> >> > +#define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC	60
> >> > +#define HIWORD_UPDATE(val, mask, shift) \
> >> > +		((val) << (shift) | (mask) << ((shift) + 16))
> >> > 
> >> >  static const unsigned int freqs[] = { 100000, 200000, 300000, 400000
> >> > 
> >> > };
> >> > 
> >> > @@ -24,8 +34,143 @@ struct dw_mci_rockchip_priv_data {
> >> > 
> >> >  	struct clk		*sample_clk;
> >> >  	int			default_sample_phase;
> >> >  	int			num_phases;
> >> > 
> >> > +	int			internal_phase;
> >> > 
> >> >  };
> >> 
> >> It might be good to declare internal_phase as "unsigned int
> >> internal_phase:1",
> >> i.e. as a bit field, which isn't going to save some memory in this
> >> particular
> >> case, but it would show additional attention to detail.
> > 
> > In that case, I would go with a bool instead of int, that makes things
> > even clearer.
> 
> My suggestion to use "unsigned int internal_phase:1" actually takes
> inspiration from the ASoC code, in which such bit fields are used
> quite a lot, even when using them actually doesn't save space.
> 
> In this particular case, using plain bool would make sense, but I
> still think that using an "unsigned int internal_phase:1" bit field
> would fit better, because it would show the intention to possibly
> save a bit of RAM at some point.  OTOH, I don't think that using
> bool with such bit fields would actually work cleanly, because bool
> actually resolves to int that's a signed type.

I wouldn't use bool with a bit field of course. I've always considered using 
bit fileds only for structs that must have a certain format, like a header 
format definition.

For me, it is better to use "bool internal_phase" so that it is obvious that 
the feature can be on or off when reading the code.

When using bit fields with a struct that is not marked as "__packed", I 
immediately think that there could be a bug there and wonder why the bit field 
is used, not really thinking "the dev wanted to show they cared about memory 
usage".
But I guess that is all about preferences. In the end, it won't change how it 
works.

Detlev.