diff mbox

[RFC,1/7] pinctrl: sh-pfc: r8a7790: Implement voltage switching for SDHI

Message ID 1455913003-6140-2-git-send-email-wsa@the-dreams.de (mailing list archive)
State New, archived
Headers show

Commit Message

Wolfram Sang Feb. 19, 2016, 8:16 p.m. UTC
From: Wolfram Sang <wsa+renesas@sang-engineering.com>

All the SHDIs can operate with either 3.3V or 1.8V signals, depending
on negotiation with the card.

Implement the {get,set}_io_voltage operations and set the related
capability flag for the associated pins.

Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Cc: Ulrich Hecht <ulrich.hecht@gmail.com>
---

The get/set-functions introduced here are the same for all Gen2, except for
the pin-sanity checks at the beginning. Somehow a generic function might be
nice for consistency reasons (I don't care so much about the code savings).
But not sure if it is worth the hazzle.

@Uli, Geert: Since bias support is probably similar, what do you think? Does
it make sense to add gen{2,3}.c?


 drivers/pinctrl/sh-pfc/core.c        |  2 +-
 drivers/pinctrl/sh-pfc/core.h        |  1 +
 drivers/pinctrl/sh-pfc/pfc-r8a7790.c | 60 +++++++++++++++++++++++++++++++++++-
 3 files changed, 61 insertions(+), 2 deletions(-)

Comments

Geert Uytterhoeven Feb. 29, 2016, 10:53 a.m. UTC | #1
Hi Wolfram,

On Fri, Feb 19, 2016 at 9:16 PM, Wolfram Sang <wsa@the-dreams.de> wrote:
> From: Wolfram Sang <wsa+renesas@sang-engineering.com>
>
> All the SHDIs can operate with either 3.3V or 1.8V signals, depending
> on negotiation with the card.
>
> Implement the {get,set}_io_voltage operations and set the related
> capability flag for the associated pins.
>
> Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>

Shouldn't the "From" line have Ben's authorship, too?
You can list your modifications in "[...]".

> Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>

Thanks!

> Cc: Ulrich Hecht <ulrich.hecht@gmail.com>
> ---
>
> The get/set-functions introduced here are the same for all Gen2, except for
> the pin-sanity checks at the beginning. Somehow a generic function might be
> nice for consistency reasons (I don't care so much about the code savings).
> But not sure if it is worth the hazzle.
>
> @Uli, Geert: Since bias support is probably similar, what do you think? Does
> it make sense to add gen{2,3}.c?

It's up to you.
We can always consolidate later.

>  drivers/pinctrl/sh-pfc/core.c        |  2 +-
>  drivers/pinctrl/sh-pfc/core.h        |  1 +
>  drivers/pinctrl/sh-pfc/pfc-r8a7790.c | 60 +++++++++++++++++++++++++++++++++++-
>  3 files changed, 61 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
> index 181ea98a63b7ab..315f9db9f5affe 100644
> --- a/drivers/pinctrl/sh-pfc/core.c
> +++ b/drivers/pinctrl/sh-pfc/core.c
> @@ -88,7 +88,7 @@ static int sh_pfc_map_resources(struct sh_pfc *pfc,
>         return 0;
>  }
>
> -static void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc, u32 reg)
> +void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc, u32 reg)

You don't need to make sh_pfc_phys_to_virt() non-static...

>  {
>         struct sh_pfc_window *window;
>         phys_addr_t address = reg;
> diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h
> index 62f53b22ae8500..ca041a753a2521 100644
> --- a/drivers/pinctrl/sh-pfc/core.h
> +++ b/drivers/pinctrl/sh-pfc/core.h
> @@ -59,6 +59,7 @@ int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc);
>  int sh_pfc_register_pinctrl(struct sh_pfc *pfc);
>  int sh_pfc_unregister_pinctrl(struct sh_pfc *pfc);
>
> +void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc, u32 address);

... and declare it...

>  u32 sh_pfc_read_raw_reg(void __iomem *mapped_reg, unsigned int reg_width);
>  void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned int reg_width,
>                           u32 data);
> diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
> index 0f4d48f9400ba0..ed51d67609050d 100644
> --- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
> +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c

> @@ -4691,6 +4696,53 @@ static const char * const vin3_groups[] = {
>         "vin3_clk",
>  };
>
> +#define IOCTRL6 0xe606008c

... if you use 0x8c here...

> +static int r8a7790_get_io_voltage(struct sh_pfc *pfc, unsigned int pin)
> +{
> +       void __iomem *reg;
> +       u32 data, mask;
> +
> +       if (WARN(pin < RCAR_GP_PIN(3, 0) || pin > RCAR_GP_PIN(3, 31), "invalid pin %#x", pin))
> +               return -EINVAL;
> +
> +       reg = sh_pfc_phys_to_virt(pfc, IOCTRL6);

... and use "pfc->windows->virt + IOCTRL6" here and in
r8a7790_set_io_voltage(), cfr. r8a7778_pinmux_get_bias().

> +       data = ioread32(reg);
> +
> +       /* Bits in IOCTRL6 are numbered in opposite order to pins */
> +       mask = 0x80000000 >> (pin & 0x1f);
> +
> +       return (data & mask) ? 3300 : 1800;
> +}

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Wolfram Sang Feb. 29, 2016, 11:37 a.m. UTC | #2
> Shouldn't the "From" line have Ben's authorship, too?

I considered the changes to this patch significant enough to take over
ownership. Even more so with the changes you suggested.

> > @Uli, Geert: Since bias support is probably similar, what do you think? Does
> > it make sense to add gen{2,3}.c?
> 
> It's up to you.
> We can always consolidate later.

Then let's start like this and see later if consolidation is really needed.

> > @@ -4691,6 +4696,53 @@ static const char * const vin3_groups[] = {
> >         "vin3_clk",
> >  };
> >
> > +#define IOCTRL6 0xe606008c
> 
> ... if you use 0x8c here...
> 
> > +static int r8a7790_get_io_voltage(struct sh_pfc *pfc, unsigned int pin)
> > +{
> > +       void __iomem *reg;
> > +       u32 data, mask;
> > +
> > +       if (WARN(pin < RCAR_GP_PIN(3, 0) || pin > RCAR_GP_PIN(3, 31), "invalid pin %#x", pin))
> > +               return -EINVAL;
> > +
> > +       reg = sh_pfc_phys_to_virt(pfc, IOCTRL6);
> 
> ... and use "pfc->windows->virt + IOCTRL6" here and in
> r8a7790_set_io_voltage(), cfr. r8a7778_pinmux_get_bias().

I see. I thought sh_pfc_phys_to_virt was more correct because it
iterates over all possible windows. But yeah, we can probably live with
the simpler approach on Gen2/3. Will change.

Thanks for the review,

   Wolfram
Wolfram Sang March 1, 2016, 1:42 p.m. UTC | #3
> ... and use "pfc->windows->virt + IOCTRL6" here and in
> r8a7790_set_io_voltage(), cfr. r8a7778_pinmux_get_bias().

This would mean I need to do something like this for unlocking:

	iowrite32(~data, pfc->windows->virt); /* unlock reg */

I hope this is okay, too.

Note: The new fast SDXC card I got produces timeouts. I want to
investigate first before resending this series.
diff mbox

Patch

diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
index 181ea98a63b7ab..315f9db9f5affe 100644
--- a/drivers/pinctrl/sh-pfc/core.c
+++ b/drivers/pinctrl/sh-pfc/core.c
@@ -88,7 +88,7 @@  static int sh_pfc_map_resources(struct sh_pfc *pfc,
 	return 0;
 }
 
-static void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc, u32 reg)
+void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc, u32 reg)
 {
 	struct sh_pfc_window *window;
 	phys_addr_t address = reg;
diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h
index 62f53b22ae8500..ca041a753a2521 100644
--- a/drivers/pinctrl/sh-pfc/core.h
+++ b/drivers/pinctrl/sh-pfc/core.h
@@ -59,6 +59,7 @@  int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc);
 int sh_pfc_register_pinctrl(struct sh_pfc *pfc);
 int sh_pfc_unregister_pinctrl(struct sh_pfc *pfc);
 
+void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc, u32 address);
 u32 sh_pfc_read_raw_reg(void __iomem *mapped_reg, unsigned int reg_width);
 void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned int reg_width,
 			  u32 data);
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
index 0f4d48f9400ba0..ed51d67609050d 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
@@ -21,16 +21,21 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/io.h>
 #include <linux/kernel.h>
 
 #include "core.h"
 #include "sh_pfc.h"
 
+/*
+ * All pins assigned to GPIO bank 3 can be used for SD interfaces in
+ * which case they support both 3.3V and 1.8V signalling.
+ */
 #define CPU_ALL_PORT(fn, sfx)						\
 	PORT_GP_32(0, fn, sfx),						\
 	PORT_GP_30(1, fn, sfx),						\
 	PORT_GP_30(2, fn, sfx),						\
-	PORT_GP_32(3, fn, sfx),						\
+	PORT_GP_CFG_32(3, fn, sfx, SH_PFC_PIN_CFG_IO_VOLTAGE),		\
 	PORT_GP_32(4, fn, sfx),						\
 	PORT_GP_32(5, fn, sfx)
 
@@ -4691,6 +4696,53 @@  static const char * const vin3_groups[] = {
 	"vin3_clk",
 };
 
+#define IOCTRL6 0xe606008c
+
+static int r8a7790_get_io_voltage(struct sh_pfc *pfc, unsigned int pin)
+{
+	void __iomem *reg;
+	u32 data, mask;
+
+	if (WARN(pin < RCAR_GP_PIN(3, 0) || pin > RCAR_GP_PIN(3, 31), "invalid pin %#x", pin))
+		return -EINVAL;
+
+	reg = sh_pfc_phys_to_virt(pfc, IOCTRL6);
+	data = ioread32(reg);
+
+	/* Bits in IOCTRL6 are numbered in opposite order to pins */
+	mask = 0x80000000 >> (pin & 0x1f);
+
+	return (data & mask) ? 3300 : 1800;
+}
+
+static int r8a7790_set_io_voltage(struct sh_pfc *pfc, unsigned int pin, u16 mV)
+{
+	void __iomem *reg;
+	u32 data, mask;
+
+	if (WARN(pin < RCAR_GP_PIN(3, 0) || pin > RCAR_GP_PIN(3, 31), "invalid pin %#x", pin))
+		return -EINVAL;
+
+	if (mV != 1800 && mV != 3300)
+		return -EINVAL;
+
+	reg = sh_pfc_phys_to_virt(pfc, IOCTRL6);
+	data = ioread32(reg);
+
+	/* Bits in IOCTRL6 are numbered in opposite order to pins */
+	mask = 0x80000000 >> (pin & 0x1f);
+
+	if (mV == 3300)
+		data |= mask;
+	else
+		data &= ~mask;
+
+	iowrite32(~data, sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg));
+	iowrite32(data, reg);
+
+	return 0;
+}
+
 static const struct sh_pfc_function pinmux_functions[] = {
 	SH_PFC_FUNCTION(audio_clk),
 	SH_PFC_FUNCTION(avb),
@@ -5690,8 +5742,14 @@  static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ },
 };
 
+static const struct sh_pfc_soc_operations pinmux_ops = {
+	.get_io_voltage = r8a7790_get_io_voltage,
+	.set_io_voltage = r8a7790_set_io_voltage,
+};
+
 const struct sh_pfc_soc_info r8a7790_pinmux_info = {
 	.name = "r8a77900_pfc",
+	.ops = &pinmux_ops,
 	.unlock_reg = 0xe6060000, /* PMMR */
 
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },