Re: [Milbeaut PATCH v0.4 2/2] mmc: sdhci_f_sdh30: Add support for Milbeaut M10V host controller

2019-04-12 Thread orito.takao

Hi

Thank you for you comment.

> On Tue, 26 Mar 2019 at 05:56, Takao Orito  wrote:
> >
> > SD Host controller on Milbeaut is consist of two controller parts.
> > One is core controller F_SDH30, this is similar to sdhci-fujitsu
> > controller.
> > Another is bridge controller.
> > This bridge controller is not compatible with sdhci-fujitsu controller.
> > This is special for Milbeaut series. This has some functions.
> > For example, reset control, clock enable/select for SDR50/25/12, set
> > property of SD physical pins, retuning control, set capabilityies.
> >
> > This bridge controller requires special procedures at reset or clock
> > enablement or change for further tuning of clock.
> >
> > This new driver uses GPIO descriptor from platform data to switch
> > the power.
> >
> > Signed-off-by: Takao Orito 
> 
> Looks like you should add a new variant driver instead of extending
> sdhci_f_sdh30.c.
> 
> If there are some registers bits or some other minor things that you
> want to share among these variants, you can always do that via a
> header file.

Ok, I see.
I will think to prepare a new variant driver with new common header file
to be shared with sdhci_f_sdh30.c

Thanks
Orito

> 
> Kind regards
> Uffe
> 
> > ---
> >  drivers/mmc/host/sdhci_f_sdh30.c | 324 
> > +++
> >  1 file changed, 296 insertions(+), 28 deletions(-)
> >
> > diff --git a/drivers/mmc/host/sdhci_f_sdh30.c 
> > b/drivers/mmc/host/sdhci_f_sdh30.c
> > index 485f759..994bafd 100644
> > --- a/drivers/mmc/host/sdhci_f_sdh30.c
> > +++ b/drivers/mmc/host/sdhci_f_sdh30.c
> > @@ -11,12 +11,15 @@
> >   */
> >
> >  #include 
> > -#include 
> > +#include 
> >  #include 
> > +#include 
> > +#include 
> > +#include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> > -#include 
> >
> >  #include "sdhci-pltfm.h"
> >
> > @@ -43,14 +46,55 @@
> >
> >  #define F_SDH30_CMD_DAT_DELAY  0x200
> >
> > +/* milbeaut bridge controller register */
> > +#define MLB_SOFT_RESET 0x0200
> > +#define  MLB_SOFT_RESET_RSTX   BIT(0)
> > +
> > +#define MLB_WP_CD_LED_SET  0x0210
> > +#define  MLB_WP_CD_LED_SET_LED_INV  BIT(2)
> > +
> > +#define MLB_CR_SET 0x0220
> > +#define  MLB_CR_SET_CR_TOCLKUNIT   BIT(24)
> > +#define  MLB_CR_SET_CR_TOCLKFREQ_SFT   (16)
> > +#define  MLB_CR_SET_CR_TOCLKFREQ_MASK  (0x3F << 
> > MLB_CR_SET_CR_TOCLKFREQ_SFT)
> > +#define  MLB_CR_SET_CR_BCLKFREQ_SFT(8)
> > +#define  MLB_CR_SET_CR_BCLKFREQ_MASK   (0xFF << MLB_CR_SET_CR_BCLKFREQ_SFT)
> > +#define  MLB_CR_SET_CR_RTUNTIMER_SFT   (4)
> > +#define  MLB_CR_SET_CR_RTUNTIMER_MASK  (0xF << MLB_CR_SET_CR_RTUNTIMER_SFT)
> > +
> > +#define MLB_SD_TOCLK_I_DIV 16
> > +#define MLB_TOCLKFREQ_UNIT_THRES   1600
> > +#define MLB_CAL_TOCLKFREQ_MHZ(rate)(rate / MLB_SD_TOCLK_I_DIV / 
> > 100)
> > +#define MLB_CAL_TOCLKFREQ_KHZ(rate)(rate / MLB_SD_TOCLK_I_DIV / 1000)
> > +#define MLB_TOCLKFREQ_MAX  63
> > +#define MLB_TOCLKFREQ_MIN   1
> > +
> > +#define MLB_SD_BCLK_I_DIV  4
> > +#define MLB_CAL_BCLKFREQ(rate) (rate / MLB_SD_BCLK_I_DIV / 100)
> > +#define MLB_BCLKFREQ_MAX   255
> > +#define MLB_BCLKFREQ_MIN 1
> > +
> > +#define MLB_CDR_SET0x0230
> > +#define MLB_CDR_SET_CLK2POW16  3
> > +
> >  #define F_SDH30_MIN_CLOCK  40
> >
> > +struct f_sdh30_config {
> > +   void (*reset)(struct sdhci_host *host, u8 mask);
> > +   void (*init)(struct sdhci_host *host);
> > +   void (*quirk_init)(struct sdhci_host *host);
> > +   void (*prepare_power)(struct sdhci_host *host, unsigned char mode,
> > +unsigned short vdd);
> > +};
> > +
> >  struct f_sdhost_priv {
> > struct clk *clk_iface;
> > struct clk *clk;
> > u32 vendor_hs200;
> > struct device *dev;
> > bool enable_cmd_dat_delay;
> > +   struct gpio_desc *power_gpio;
> > +   struct f_sdh30_config *config;
> >  };
> >
> >  static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host)
> > @@ -86,7 +130,46 @@ static unsigned int sdhci_f_sdh30_get_min_clock(struct 
> > sdhci_host *host)
> > return F_SDH30_MIN_CLOCK;
> >  }
> >
> > -static void sdhci_f_sdh30_reset(struct sdhci_host *host, u8 mask)
> > +static void sdhci_milbeaut_reset(struct sdhci_host *host, u8 mask)
> > +{
> > +   struct f_sdhost_priv *priv = sdhci_priv(host);
> > +   u16 clk;
> > +   u32 ctl;
> > +   ktime_t timeout;
> > +
> > +   clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
> > +   clk = (clk & ~SDHCI_CLOCK_CARD_EN) | SDHCI_CLOCK_INT_EN;
> > +   sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
> > +
> > +   sdhci_reset(host, mask);
> > +
> > +   clk |= SDHCI_CLOCK_CARD_EN;
> > +   sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
> > +
> > +   timeout = ktime_add_ms(ktime_get(), 10);
> > +   while (1) {
> > +   bool timedout = 

Re: [Milbeaut PATCH v0.4 2/2] mmc: sdhci_f_sdh30: Add support for Milbeaut M10V host controller

2019-04-11 Thread Ulf Hansson
On Tue, 26 Mar 2019 at 05:56, Takao Orito  wrote:
>
> SD Host controller on Milbeaut is consist of two controller parts.
> One is core controller F_SDH30, this is similar to sdhci-fujitsu
> controller.
> Another is bridge controller.
> This bridge controller is not compatible with sdhci-fujitsu controller.
> This is special for Milbeaut series. This has some functions.
> For example, reset control, clock enable/select for SDR50/25/12, set
> property of SD physical pins, retuning control, set capabilityies.
>
> This bridge controller requires special procedures at reset or clock
> enablement or change for further tuning of clock.
>
> This new driver uses GPIO descriptor from platform data to switch
> the power.
>
> Signed-off-by: Takao Orito 

Looks like you should add a new variant driver instead of extending
sdhci_f_sdh30.c.

If there are some registers bits or some other minor things that you
want to share among these variants, you can always do that via a
header file.

Kind regards
Uffe

> ---
>  drivers/mmc/host/sdhci_f_sdh30.c | 324 
> +++
>  1 file changed, 296 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci_f_sdh30.c 
> b/drivers/mmc/host/sdhci_f_sdh30.c
> index 485f759..994bafd 100644
> --- a/drivers/mmc/host/sdhci_f_sdh30.c
> +++ b/drivers/mmc/host/sdhci_f_sdh30.c
> @@ -11,12 +11,15 @@
>   */
>
>  #include 
> -#include 
> +#include 
>  #include 
> +#include 
> +#include 
> +#include 
>  #include 
>  #include 
> +#include 
>  #include 
> -#include 
>
>  #include "sdhci-pltfm.h"
>
> @@ -43,14 +46,55 @@
>
>  #define F_SDH30_CMD_DAT_DELAY  0x200
>
> +/* milbeaut bridge controller register */
> +#define MLB_SOFT_RESET 0x0200
> +#define  MLB_SOFT_RESET_RSTX   BIT(0)
> +
> +#define MLB_WP_CD_LED_SET  0x0210
> +#define  MLB_WP_CD_LED_SET_LED_INV  BIT(2)
> +
> +#define MLB_CR_SET 0x0220
> +#define  MLB_CR_SET_CR_TOCLKUNIT   BIT(24)
> +#define  MLB_CR_SET_CR_TOCLKFREQ_SFT   (16)
> +#define  MLB_CR_SET_CR_TOCLKFREQ_MASK  (0x3F << MLB_CR_SET_CR_TOCLKFREQ_SFT)
> +#define  MLB_CR_SET_CR_BCLKFREQ_SFT(8)
> +#define  MLB_CR_SET_CR_BCLKFREQ_MASK   (0xFF << MLB_CR_SET_CR_BCLKFREQ_SFT)
> +#define  MLB_CR_SET_CR_RTUNTIMER_SFT   (4)
> +#define  MLB_CR_SET_CR_RTUNTIMER_MASK  (0xF << MLB_CR_SET_CR_RTUNTIMER_SFT)
> +
> +#define MLB_SD_TOCLK_I_DIV 16
> +#define MLB_TOCLKFREQ_UNIT_THRES   1600
> +#define MLB_CAL_TOCLKFREQ_MHZ(rate)(rate / MLB_SD_TOCLK_I_DIV / 100)
> +#define MLB_CAL_TOCLKFREQ_KHZ(rate)(rate / MLB_SD_TOCLK_I_DIV / 1000)
> +#define MLB_TOCLKFREQ_MAX  63
> +#define MLB_TOCLKFREQ_MIN   1
> +
> +#define MLB_SD_BCLK_I_DIV  4
> +#define MLB_CAL_BCLKFREQ(rate) (rate / MLB_SD_BCLK_I_DIV / 100)
> +#define MLB_BCLKFREQ_MAX   255
> +#define MLB_BCLKFREQ_MIN 1
> +
> +#define MLB_CDR_SET0x0230
> +#define MLB_CDR_SET_CLK2POW16  3
> +
>  #define F_SDH30_MIN_CLOCK  40
>
> +struct f_sdh30_config {
> +   void (*reset)(struct sdhci_host *host, u8 mask);
> +   void (*init)(struct sdhci_host *host);
> +   void (*quirk_init)(struct sdhci_host *host);
> +   void (*prepare_power)(struct sdhci_host *host, unsigned char mode,
> +unsigned short vdd);
> +};
> +
>  struct f_sdhost_priv {
> struct clk *clk_iface;
> struct clk *clk;
> u32 vendor_hs200;
> struct device *dev;
> bool enable_cmd_dat_delay;
> +   struct gpio_desc *power_gpio;
> +   struct f_sdh30_config *config;
>  };
>
>  static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host)
> @@ -86,7 +130,46 @@ static unsigned int sdhci_f_sdh30_get_min_clock(struct 
> sdhci_host *host)
> return F_SDH30_MIN_CLOCK;
>  }
>
> -static void sdhci_f_sdh30_reset(struct sdhci_host *host, u8 mask)
> +static void sdhci_milbeaut_reset(struct sdhci_host *host, u8 mask)
> +{
> +   struct f_sdhost_priv *priv = sdhci_priv(host);
> +   u16 clk;
> +   u32 ctl;
> +   ktime_t timeout;
> +
> +   clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
> +   clk = (clk & ~SDHCI_CLOCK_CARD_EN) | SDHCI_CLOCK_INT_EN;
> +   sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
> +
> +   sdhci_reset(host, mask);
> +
> +   clk |= SDHCI_CLOCK_CARD_EN;
> +   sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
> +
> +   timeout = ktime_add_ms(ktime_get(), 10);
> +   while (1) {
> +   bool timedout = ktime_after(ktime_get(), timeout);
> +
> +   clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
> +   if (clk & SDHCI_CLOCK_INT_STABLE)
> +   break;
> +   if (timedout) {
> +   pr_err("%s: Internal clock never stabilised.\n",
> +   mmc_hostname(host->mmc));
> +   sdhci_dumpregs(host);
> +   return;
> +

[Milbeaut PATCH v0.4 2/2] mmc: sdhci_f_sdh30: Add support for Milbeaut M10V host controller

2019-03-25 Thread Takao Orito
SD Host controller on Milbeaut is consist of two controller parts.
One is core controller F_SDH30, this is similar to sdhci-fujitsu
controller.
Another is bridge controller.
This bridge controller is not compatible with sdhci-fujitsu controller.
This is special for Milbeaut series. This has some functions.
For example, reset control, clock enable/select for SDR50/25/12, set
property of SD physical pins, retuning control, set capabilityies.

This bridge controller requires special procedures at reset or clock
enablement or change for further tuning of clock.

This new driver uses GPIO descriptor from platform data to switch
the power.

Signed-off-by: Takao Orito 
---
 drivers/mmc/host/sdhci_f_sdh30.c | 324 +++
 1 file changed, 296 insertions(+), 28 deletions(-)

diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c
index 485f759..994bafd 100644
--- a/drivers/mmc/host/sdhci_f_sdh30.c
+++ b/drivers/mmc/host/sdhci_f_sdh30.c
@@ -11,12 +11,15 @@
  */
 
 #include 
-#include 
+#include 
 #include 
+#include 
+#include 
+#include 
 #include 
 #include 
+#include 
 #include 
-#include 
 
 #include "sdhci-pltfm.h"
 
@@ -43,14 +46,55 @@
 
 #define F_SDH30_CMD_DAT_DELAY  0x200
 
+/* milbeaut bridge controller register */
+#define MLB_SOFT_RESET 0x0200
+#define  MLB_SOFT_RESET_RSTX   BIT(0)
+
+#define MLB_WP_CD_LED_SET  0x0210
+#define  MLB_WP_CD_LED_SET_LED_INV  BIT(2)
+
+#define MLB_CR_SET 0x0220
+#define  MLB_CR_SET_CR_TOCLKUNIT   BIT(24)
+#define  MLB_CR_SET_CR_TOCLKFREQ_SFT   (16)
+#define  MLB_CR_SET_CR_TOCLKFREQ_MASK  (0x3F << MLB_CR_SET_CR_TOCLKFREQ_SFT)
+#define  MLB_CR_SET_CR_BCLKFREQ_SFT(8)
+#define  MLB_CR_SET_CR_BCLKFREQ_MASK   (0xFF << MLB_CR_SET_CR_BCLKFREQ_SFT)
+#define  MLB_CR_SET_CR_RTUNTIMER_SFT   (4)
+#define  MLB_CR_SET_CR_RTUNTIMER_MASK  (0xF << MLB_CR_SET_CR_RTUNTIMER_SFT)
+
+#define MLB_SD_TOCLK_I_DIV 16
+#define MLB_TOCLKFREQ_UNIT_THRES   1600
+#define MLB_CAL_TOCLKFREQ_MHZ(rate)(rate / MLB_SD_TOCLK_I_DIV / 100)
+#define MLB_CAL_TOCLKFREQ_KHZ(rate)(rate / MLB_SD_TOCLK_I_DIV / 1000)
+#define MLB_TOCLKFREQ_MAX  63
+#define MLB_TOCLKFREQ_MIN   1
+
+#define MLB_SD_BCLK_I_DIV  4
+#define MLB_CAL_BCLKFREQ(rate) (rate / MLB_SD_BCLK_I_DIV / 100)
+#define MLB_BCLKFREQ_MAX   255
+#define MLB_BCLKFREQ_MIN 1
+
+#define MLB_CDR_SET0x0230
+#define MLB_CDR_SET_CLK2POW16  3
+
 #define F_SDH30_MIN_CLOCK  40
 
+struct f_sdh30_config {
+   void (*reset)(struct sdhci_host *host, u8 mask);
+   void (*init)(struct sdhci_host *host);
+   void (*quirk_init)(struct sdhci_host *host);
+   void (*prepare_power)(struct sdhci_host *host, unsigned char mode,
+unsigned short vdd);
+};
+
 struct f_sdhost_priv {
struct clk *clk_iface;
struct clk *clk;
u32 vendor_hs200;
struct device *dev;
bool enable_cmd_dat_delay;
+   struct gpio_desc *power_gpio;
+   struct f_sdh30_config *config;
 };
 
 static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host)
@@ -86,7 +130,46 @@ static unsigned int sdhci_f_sdh30_get_min_clock(struct 
sdhci_host *host)
return F_SDH30_MIN_CLOCK;
 }
 
-static void sdhci_f_sdh30_reset(struct sdhci_host *host, u8 mask)
+static void sdhci_milbeaut_reset(struct sdhci_host *host, u8 mask)
+{
+   struct f_sdhost_priv *priv = sdhci_priv(host);
+   u16 clk;
+   u32 ctl;
+   ktime_t timeout;
+
+   clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+   clk = (clk & ~SDHCI_CLOCK_CARD_EN) | SDHCI_CLOCK_INT_EN;
+   sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+   sdhci_reset(host, mask);
+
+   clk |= SDHCI_CLOCK_CARD_EN;
+   sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+   timeout = ktime_add_ms(ktime_get(), 10);
+   while (1) {
+   bool timedout = ktime_after(ktime_get(), timeout);
+
+   clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+   if (clk & SDHCI_CLOCK_INT_STABLE)
+   break;
+   if (timedout) {
+   pr_err("%s: Internal clock never stabilised.\n",
+   mmc_hostname(host->mmc));
+   sdhci_dumpregs(host);
+   return;
+   }
+   udelay(10);
+   }
+
+   if (priv->enable_cmd_dat_delay) {
+   ctl = sdhci_readl(host, F_SDH30_ESD_CONTROL);
+   ctl |= F_SDH30_CMD_DAT_DELAY;
+   sdhci_writel(host, ctl, F_SDH30_ESD_CONTROL);
+   }
+}
+
+static void sdhci_mb86s70_reset(struct sdhci_host *host, u8 mask)
 {
struct f_sdhost_priv *priv = sdhci_priv(host);
u32 ctl;
@@ -103,6 +186,51 @@ static void sdhci_f_sdh30_reset(struct sdhci_host *host, 
u8 mask)
}
 }
 
+static void sdhci_f_sdh30_reset(struct