All of lore.kernel.org
 help / color / mirror / Atom feed
From: Drew Fustini <drew@beagleboard.org>
To: Michael Walle <michael@walle.cc>
Cc: Linus Walleij <linus.walleij@linaro.org>,
	Rob Herring <robh+dt@kernel.org>,
	Bartosz Golaszewski <bgolaszewski@baylibre.com>,
	Paul Walmsley <paul.walmsley@sifive.com>,
	Palmer Dabbelt <palmer@dabbelt.com>,
	Michael Zhu <michael.zhu@starfivetech.com>,
	Geert Uytterhoeven <geert@linux-m68k.org>,
	Fu Wei <tekkamanninja@gmail.com>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	"open list:GPIO SUBSYSTEM" <linux-gpio@vger.kernel.org>,
	linux-riscv <linux-riscv@lists.infradead.org>,
	"open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS" 
	<devicetree@vger.kernel.org>,
	Emil Renner Berthing <kernel@esmil.dk>,
	Huan Feng <huan.feng@starfivetech.com>
Subject: Re: [RFC PATH 2/2] gpio: starfive-jh7100: Add StarFive JH7100 GPIO driver
Date: Mon, 26 Jul 2021 22:28:51 -0700	[thread overview]
Message-ID: <20210727052851.GA3147871@x1> (raw)
In-Reply-To: <dad13b899b69436acc1804b7c3438639@walle.cc>

On Mon, Jul 26, 2021 at 09:21:31AM +0200, Michael Walle wrote:
> Hi Drew, Hi Linus,
> 
> Am 2021-07-26 09:11, schrieb Drew Fustini:
> > On Fri, Jul 23, 2021 at 11:04:41PM +0200, Linus Walleij wrote:
> > > On Thu, Jul 1, 2021 at 8:39 AM Michael Walle <michael@walle.cc> wrote:
> > > > Am 2021-07-01 02:20, schrieb Drew Fustini:
> > > > > Add GPIO driver for the StarFive JH7100 SoC [1] used on the
> > > > > BeagleV Starlight JH7100 board [2].
> > > > >
> > > > > [1] https://github.com/starfive-tech/beaglev_doc/
> > > > > [2] https://github.com/beagleboard/beaglev-starlight
> > > > >
> > > > > Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> > > > > Signed-off-by: Huan Feng <huan.feng@starfivetech.com>
> > > > > Signed-off-by: Drew Fustini <drew@beagleboard.org>
> > > >
> > > > Could this driver use GPIO_REGMAP and REGMAP_IRQ? See
> > > > drivers/gpio/gpio-sl28cpld.c for an example.
> > > 
> > > To me it looks just memory-mapped?
> > > 
> > > Good old gpio-mmio.c (select GPIO_GENERIC) should
> > > suffice I think.
> 
> But that doesn't mean gpio-regmap can't be used, no? Or what are
> the advantages of gpio-mmio?
> 
> > > Drew please look at drivers/gpio/gpio-ftgpio010.c for an example
> > > of GPIO_GENERIC calling bgpio_init() in probe().
> > 
> > Thank you for the suggestion. However, I am not sure that will work for
> > this SoC.
> > 
> > The GPIO registers are described in section 12 of JH7100 datasheet [1]
> > and I don't think they fit the expectation of gpio-mmio.c because there
> > is a seperate register for each GPIO line for output data value and
> > output enable.
> > 
> > There are 64 output data config registers which are 4 bytes wide. There
> > are 64 output enable config registers which are 4 bytes wide too. Output
> > data and output enable registers for a given GPIO pad are contiguous.
> > GPIO0_DOUT_CFG is 0x50 and GPIO0_DOEN_CFG is 0x54 while GPIO1_DOUT_CFG
> > is 0x58 and GPIO1_DOEN_CFG is 0x5C. The stride between GPIO pads is
> > effectively 8, which yields the formula: GPIOn_DOUT_CFG is 0x50+8n.
> > Similarly, GPIO0_DOEN_CFG is 0x54 and thus GPIOn_DOEN_CFG is 0x54+8n.
> > 
> > However, GPIO input data does use just one bit for each line. GPIODIN_0
> > at 0x48 covers GPIO[31:0] and GPIODIN_1 at 0x4c covers GPIO[63:32].
> 
> I'd say, that should work with the .reg_mask_xlate of the gpio-regmap.
> 
> -michael

Thanks, yes, I think trying to figure out how .reg_mask_xlate would need
to work this SoC.  I believe these are the only two implementations.

From drivers/gpio/gpio-regmap.c:

  static int gpio_regmap_simple_xlate(struct gpio_regmap *gpio,
				      unsigned int base, unsigned int offset,
				      unsigned int *reg, unsigned int *mask)
  {
	  unsigned int line = offset % gpio->ngpio_per_reg;
	  unsigned int stride = offset / gpio->ngpio_per_reg;

	  *reg = base + stride * gpio->reg_stride;
	  *mask = BIT(line);

	  return 0;
  }

From drivers/pinctrl/bcm/pinctrl-bcm63xx.c:

  static int bcm63xx_reg_mask_xlate(struct gpio_regmap *gpio,
				    unsigned int base, unsigned int offset,
				    unsigned int *reg, unsigned int *mask)
  {
	  unsigned int line = offset % BCM63XX_BANK_GPIOS;
	  unsigned int stride = offset / BCM63XX_BANK_GPIOS;

	  *reg = base - stride * BCM63XX_BANK_SIZE;
	  *mask = BIT(line);

	  return 0;
  }

Let's say a driver calls gpio_regmap_set(chip, 0, 5) to set line 5 to
value 1.

I believe this would result in call to:

  gpio->reg_mask_xlate(gpio, gpio->reg_set_base, 5, &reg, &mask)

Then this would be called to set the register:

  regmap_update_bits(gpio->regmap, reg, mask, mask);

From datasheet section 12 [1], there are 64 output data registers which
are 4 bytes wide. There are 64 output enable registers which are also 4
bytes wide too. Output data and output enable registers for a GPIO line
are contiguous. Thus GPIO0_DOUT_CFG is 0x50 and GPIO0_DOEN_CFG is 0x54.
The forumla is GPIOn_DOUT_CFG is 0x50+8n and GPIOn_DOEN_CFG is 0x54+8n.
Thus for GPIO line 5:

  GPIO5_DOUT_CFG is 0x50 + 0x28 = 0x78
  GPIO5_DOEN_CFG is 0x54 + 0x28 = 0x7C

Enable GPIO line 5 as output by writing 0x1 to 0x7C and set output value
to 1 by writing 1 to 0x7C.

Using gpio_regmap_simple_xlate() as a template, I am thinking through
xlate for this gpio controller:


static int gpio_regmap_starfive_xlate(struct gpio_regmap *gpio,
				      unsigned int base, unsigned int offset,
				      unsigned int *reg, unsigned int *mask)
{
	// reg_set_base is passed as base
	// let reg_set_base = 0x50 (GPIO0_DOUT_CFG)
	// let gpio->reg_stride = 8
	// let offest = 5 (for gpio line 5)

	*reg = base + offset * gpio->reg_stride;
	// *reg = base:0x50 + offset:0x5 * reg_stride:0x8
	// *reg = 0x50 + 0x28
	// *reg=  0x78

	// Each gpio line has a full register, not just a bit. To output
	// a digital 1, then GPIO5_DOUT_CFG would be 0x1. To output
	// digital 0, GPIO5_DOUT_CFG would be 0x0. Thus I think the mask
	// should be the least significant bit.
	*mask = BIT(1);

	return 0;
}

Let's walk through what would happen if gpio_regmap_set() was the
caller:

static void gpio_regmap_set(struct gpio_chip *chip, unsigned int offset,
			    int val)
{
	// for gpio line, offset = 5
	// if want to set line 5 high, then val = 1
	struct gpio_regmap *gpio = gpiochip_get_data(chip);

	// reg_set_base would be set to 0x50 (GPIO0_DOUT_CFG)
	unsigned int base = gpio_regmap_addr(gpio->reg_set_base);
	unsigned int reg, mask;

	gpio->reg_mask_xlate(gpio, base /* 0x50 */, offset /* 5 */, &reg, &mask);
	if (val) /* if val is 1 */
		regmap_update_bits(gpio->regmap, reg, mask, mask);
		// if mask returned was 0x1, then this would set the
		// bit 0 in GPIO5_DOUT_CFG
	else /* if val is 0 */
		regmap_update_bits(gpio->regmap, reg, mask, 0);
		// if mask returned was 0x1, then this would clear
		// bit 0 in GPIO5_DOUT_CFG
}

Now for the output enable register GPIO5_DOEN_CFG, the output driver is
active low so 0x0 is actually enables output where as 0x1 disables
output.  Thus maybe I need to add logic like:


static int gpio_regmap_starfive_xlate(struct gpio_regmap *gpio,
				      unsigned int base, unsigned int offset,
				      unsigned int *reg, unsigned int *mask)
{
	<snip>
	if (base == GPIO0_DOUT_CFG)
		*mask = 0x1U;
	else if (base == GPIO0_DOEN_CFG)
		*bit = ~(0x1U);

	return 0;
}

What do you think of that approach?

Are there any other examples of regmap xlate that I missed?

Thanks,
Drew

[1] https://github.com/starfive-tech/beaglev_doc/blob/main/JH7100%20Data%20Sheet%20V01.01.04-EN%20(4-21-2021).pdf

WARNING: multiple messages have this Message-ID (diff)
From: Drew Fustini <drew@beagleboard.org>
To: Michael Walle <michael@walle.cc>
Cc: Linus Walleij <linus.walleij@linaro.org>,
	Rob Herring <robh+dt@kernel.org>,
	Bartosz Golaszewski <bgolaszewski@baylibre.com>,
	Paul Walmsley <paul.walmsley@sifive.com>,
	Palmer Dabbelt <palmer@dabbelt.com>,
	Michael Zhu <michael.zhu@starfivetech.com>,
	Geert Uytterhoeven <geert@linux-m68k.org>,
	Fu Wei <tekkamanninja@gmail.com>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	"open list:GPIO SUBSYSTEM" <linux-gpio@vger.kernel.org>,
	linux-riscv <linux-riscv@lists.infradead.org>,
	"open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS"
	<devicetree@vger.kernel.org>,
	Emil Renner Berthing <kernel@esmil.dk>,
	Huan Feng <huan.feng@starfivetech.com>
Subject: Re: [RFC PATH 2/2] gpio: starfive-jh7100: Add StarFive JH7100 GPIO driver
Date: Mon, 26 Jul 2021 22:28:51 -0700	[thread overview]
Message-ID: <20210727052851.GA3147871@x1> (raw)
In-Reply-To: <dad13b899b69436acc1804b7c3438639@walle.cc>

On Mon, Jul 26, 2021 at 09:21:31AM +0200, Michael Walle wrote:
> Hi Drew, Hi Linus,
> 
> Am 2021-07-26 09:11, schrieb Drew Fustini:
> > On Fri, Jul 23, 2021 at 11:04:41PM +0200, Linus Walleij wrote:
> > > On Thu, Jul 1, 2021 at 8:39 AM Michael Walle <michael@walle.cc> wrote:
> > > > Am 2021-07-01 02:20, schrieb Drew Fustini:
> > > > > Add GPIO driver for the StarFive JH7100 SoC [1] used on the
> > > > > BeagleV Starlight JH7100 board [2].
> > > > >
> > > > > [1] https://github.com/starfive-tech/beaglev_doc/
> > > > > [2] https://github.com/beagleboard/beaglev-starlight
> > > > >
> > > > > Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> > > > > Signed-off-by: Huan Feng <huan.feng@starfivetech.com>
> > > > > Signed-off-by: Drew Fustini <drew@beagleboard.org>
> > > >
> > > > Could this driver use GPIO_REGMAP and REGMAP_IRQ? See
> > > > drivers/gpio/gpio-sl28cpld.c for an example.
> > > 
> > > To me it looks just memory-mapped?
> > > 
> > > Good old gpio-mmio.c (select GPIO_GENERIC) should
> > > suffice I think.
> 
> But that doesn't mean gpio-regmap can't be used, no? Or what are
> the advantages of gpio-mmio?
> 
> > > Drew please look at drivers/gpio/gpio-ftgpio010.c for an example
> > > of GPIO_GENERIC calling bgpio_init() in probe().
> > 
> > Thank you for the suggestion. However, I am not sure that will work for
> > this SoC.
> > 
> > The GPIO registers are described in section 12 of JH7100 datasheet [1]
> > and I don't think they fit the expectation of gpio-mmio.c because there
> > is a seperate register for each GPIO line for output data value and
> > output enable.
> > 
> > There are 64 output data config registers which are 4 bytes wide. There
> > are 64 output enable config registers which are 4 bytes wide too. Output
> > data and output enable registers for a given GPIO pad are contiguous.
> > GPIO0_DOUT_CFG is 0x50 and GPIO0_DOEN_CFG is 0x54 while GPIO1_DOUT_CFG
> > is 0x58 and GPIO1_DOEN_CFG is 0x5C. The stride between GPIO pads is
> > effectively 8, which yields the formula: GPIOn_DOUT_CFG is 0x50+8n.
> > Similarly, GPIO0_DOEN_CFG is 0x54 and thus GPIOn_DOEN_CFG is 0x54+8n.
> > 
> > However, GPIO input data does use just one bit for each line. GPIODIN_0
> > at 0x48 covers GPIO[31:0] and GPIODIN_1 at 0x4c covers GPIO[63:32].
> 
> I'd say, that should work with the .reg_mask_xlate of the gpio-regmap.
> 
> -michael

Thanks, yes, I think trying to figure out how .reg_mask_xlate would need
to work this SoC.  I believe these are the only two implementations.

From drivers/gpio/gpio-regmap.c:

  static int gpio_regmap_simple_xlate(struct gpio_regmap *gpio,
				      unsigned int base, unsigned int offset,
				      unsigned int *reg, unsigned int *mask)
  {
	  unsigned int line = offset % gpio->ngpio_per_reg;
	  unsigned int stride = offset / gpio->ngpio_per_reg;

	  *reg = base + stride * gpio->reg_stride;
	  *mask = BIT(line);

	  return 0;
  }

From drivers/pinctrl/bcm/pinctrl-bcm63xx.c:

  static int bcm63xx_reg_mask_xlate(struct gpio_regmap *gpio,
				    unsigned int base, unsigned int offset,
				    unsigned int *reg, unsigned int *mask)
  {
	  unsigned int line = offset % BCM63XX_BANK_GPIOS;
	  unsigned int stride = offset / BCM63XX_BANK_GPIOS;

	  *reg = base - stride * BCM63XX_BANK_SIZE;
	  *mask = BIT(line);

	  return 0;
  }

Let's say a driver calls gpio_regmap_set(chip, 0, 5) to set line 5 to
value 1.

I believe this would result in call to:

  gpio->reg_mask_xlate(gpio, gpio->reg_set_base, 5, &reg, &mask)

Then this would be called to set the register:

  regmap_update_bits(gpio->regmap, reg, mask, mask);

From datasheet section 12 [1], there are 64 output data registers which
are 4 bytes wide. There are 64 output enable registers which are also 4
bytes wide too. Output data and output enable registers for a GPIO line
are contiguous. Thus GPIO0_DOUT_CFG is 0x50 and GPIO0_DOEN_CFG is 0x54.
The forumla is GPIOn_DOUT_CFG is 0x50+8n and GPIOn_DOEN_CFG is 0x54+8n.
Thus for GPIO line 5:

  GPIO5_DOUT_CFG is 0x50 + 0x28 = 0x78
  GPIO5_DOEN_CFG is 0x54 + 0x28 = 0x7C

Enable GPIO line 5 as output by writing 0x1 to 0x7C and set output value
to 1 by writing 1 to 0x7C.

Using gpio_regmap_simple_xlate() as a template, I am thinking through
xlate for this gpio controller:


static int gpio_regmap_starfive_xlate(struct gpio_regmap *gpio,
				      unsigned int base, unsigned int offset,
				      unsigned int *reg, unsigned int *mask)
{
	// reg_set_base is passed as base
	// let reg_set_base = 0x50 (GPIO0_DOUT_CFG)
	// let gpio->reg_stride = 8
	// let offest = 5 (for gpio line 5)

	*reg = base + offset * gpio->reg_stride;
	// *reg = base:0x50 + offset:0x5 * reg_stride:0x8
	// *reg = 0x50 + 0x28
	// *reg=  0x78

	// Each gpio line has a full register, not just a bit. To output
	// a digital 1, then GPIO5_DOUT_CFG would be 0x1. To output
	// digital 0, GPIO5_DOUT_CFG would be 0x0. Thus I think the mask
	// should be the least significant bit.
	*mask = BIT(1);

	return 0;
}

Let's walk through what would happen if gpio_regmap_set() was the
caller:

static void gpio_regmap_set(struct gpio_chip *chip, unsigned int offset,
			    int val)
{
	// for gpio line, offset = 5
	// if want to set line 5 high, then val = 1
	struct gpio_regmap *gpio = gpiochip_get_data(chip);

	// reg_set_base would be set to 0x50 (GPIO0_DOUT_CFG)
	unsigned int base = gpio_regmap_addr(gpio->reg_set_base);
	unsigned int reg, mask;

	gpio->reg_mask_xlate(gpio, base /* 0x50 */, offset /* 5 */, &reg, &mask);
	if (val) /* if val is 1 */
		regmap_update_bits(gpio->regmap, reg, mask, mask);
		// if mask returned was 0x1, then this would set the
		// bit 0 in GPIO5_DOUT_CFG
	else /* if val is 0 */
		regmap_update_bits(gpio->regmap, reg, mask, 0);
		// if mask returned was 0x1, then this would clear
		// bit 0 in GPIO5_DOUT_CFG
}

Now for the output enable register GPIO5_DOEN_CFG, the output driver is
active low so 0x0 is actually enables output where as 0x1 disables
output.  Thus maybe I need to add logic like:


static int gpio_regmap_starfive_xlate(struct gpio_regmap *gpio,
				      unsigned int base, unsigned int offset,
				      unsigned int *reg, unsigned int *mask)
{
	<snip>
	if (base == GPIO0_DOUT_CFG)
		*mask = 0x1U;
	else if (base == GPIO0_DOEN_CFG)
		*bit = ~(0x1U);

	return 0;
}

What do you think of that approach?

Are there any other examples of regmap xlate that I missed?

Thanks,
Drew

[1] https://github.com/starfive-tech/beaglev_doc/blob/main/JH7100%20Data%20Sheet%20V01.01.04-EN%20(4-21-2021).pdf

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

  reply	other threads:[~2021-07-27  5:29 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-01  0:20 [RFC PATH 0/2] gpio: starfive-jh7100: Add StarFive JH7100 GPIO bindings and driver Drew Fustini
2021-07-01  0:20 ` Drew Fustini
2021-07-01  0:20 ` [RFC PATH 1/2] dt-bindings: gpio: add starfive,jh7100-gpio bindings Drew Fustini
2021-07-01  0:20   ` Drew Fustini
2021-07-01  8:34   ` Geert Uytterhoeven
2021-07-01  8:34     ` [RFC PATH 1/2] dt-bindings: gpio: add starfive, jh7100-gpio bindings Geert Uytterhoeven
2021-07-02 20:56     ` [RFC PATH 1/2] dt-bindings: gpio: add starfive,jh7100-gpio bindings Drew Fustini
2021-07-02 20:56       ` Drew Fustini
2021-07-02 21:03       ` Geert Uytterhoeven
2021-07-02 21:03         ` [RFC PATH 1/2] dt-bindings: gpio: add starfive, jh7100-gpio bindings Geert Uytterhoeven
2021-07-03  6:46         ` [RFC PATH 1/2] dt-bindings: gpio: add starfive,jh7100-gpio bindings Drew Fustini
2021-07-03  6:46           ` Drew Fustini
2021-07-03  8:49           ` Geert Uytterhoeven
2021-07-03  8:49             ` [RFC PATH 1/2] dt-bindings: gpio: add starfive, jh7100-gpio bindings Geert Uytterhoeven
2021-07-01  0:20 ` [RFC PATH 2/2] gpio: starfive-jh7100: Add StarFive JH7100 GPIO driver Drew Fustini
2021-07-01  0:20   ` Drew Fustini
2021-07-01  2:25   ` Bin Meng
2021-07-01  2:25     ` Bin Meng
2021-07-01 20:44     ` Drew Fustini
2021-07-01 20:44       ` Drew Fustini
2021-07-01  6:39   ` Michael Walle
2021-07-01  6:39     ` Michael Walle
2021-07-01 20:33     ` Drew Fustini
2021-07-01 20:33       ` Drew Fustini
2021-07-02 14:59       ` Michael Walle
2021-07-02 14:59         ` Michael Walle
2021-07-02 21:00     ` Drew Fustini
2021-07-02 21:00       ` Drew Fustini
2021-07-23 21:04     ` Linus Walleij
2021-07-23 21:04       ` Linus Walleij
2021-07-26  7:11       ` Drew Fustini
2021-07-26  7:11         ` Drew Fustini
2021-07-26  7:21         ` Michael Walle
2021-07-26  7:21           ` Michael Walle
2021-07-27  5:28           ` Drew Fustini [this message]
2021-07-27  5:28             ` Drew Fustini
2021-07-28  9:49             ` Michael Walle
2021-07-28  9:49               ` Michael Walle
2021-07-28 10:59               ` Emil Renner Berthing
2021-07-28 10:59                 ` Emil Renner Berthing
2021-07-28 11:19                 ` Michael Walle
2021-07-28 11:19                   ` Michael Walle
2021-07-28 11:21                   ` Emil Renner Berthing
2021-07-28 11:21                     ` Emil Renner Berthing
2021-07-01 18:25   ` kernel test robot
2021-07-02 16:03   ` Andy Shevchenko
2021-07-02 16:03     ` Andy Shevchenko
2021-07-02 21:06     ` Drew Fustini
2021-07-02 21:06       ` Drew Fustini
2021-07-05 13:29       ` Michael Walle
2021-07-05 13:29         ` Michael Walle
2021-07-05 14:33         ` Matti Vaittinen
2021-07-05 14:33           ` Matti Vaittinen
2021-07-15  1:49   ` Ley Foon Tan
2021-07-15  1:49     ` Ley Foon Tan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210727052851.GA3147871@x1 \
    --to=drew@beagleboard.org \
    --cc=bgolaszewski@baylibre.com \
    --cc=devicetree@vger.kernel.org \
    --cc=geert@linux-m68k.org \
    --cc=huan.feng@starfivetech.com \
    --cc=kernel@esmil.dk \
    --cc=linus.walleij@linaro.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=michael.zhu@starfivetech.com \
    --cc=michael@walle.cc \
    --cc=palmer@dabbelt.com \
    --cc=paul.walmsley@sifive.com \
    --cc=robh+dt@kernel.org \
    --cc=tekkamanninja@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.