[U-Boot] [PATCH 1/6] mips: mscc_sgpio: Add the MSCC serial GPIO device (SIO)

Lars.Povlsen at microchip.com Lars.Povlsen at microchip.com
Thu Dec 27 12:14:05 UTC 2018


Hi Daniel!

Thank you for the input. I am about to have a new v2 ready.

Comments below.

---Lars

> -----Original Message-----
> From: Daniel Schwierzeck <daniel.schwierzeck at gmail.com>
> Sent: Thursday, December 20, 2018 21:53
> To: Lars Povlsen - M31675 <Lars.Povlsen at microchip.com>; u-
> boot at lists.denx.de
> Cc: gregory.clement at bootlin.com; Horatiu Vultur - M31836
> <Horatiu.Vultur at microchip.com>
> Subject: Re: [PATCH 1/6] mips: mscc_sgpio: Add the MSCC serial GPIO
> device (SIO)
> 
> 
> 
> Am 20.12.18 um 21:11 schrieb Lars Povlsen:
> > This add support for the the MSCC serial GPIO driver in MSCC
> > VCoreIII-based SOCs.
> >
> > By using a serial interface, the SIO controller significantly extends
> > the number of available GPIOs with a minimum number of additional pins
> > on the device. The primary purpose of the SIO controller is to connect
> > control signals from SFP modules and to act as an LED controller.
> >
> > This adds the base driver.

[snip]

> > diff --git a/drivers/gpio/mscc_sgpio.c b/drivers/gpio/mscc_sgpio.c
> > new file mode 100644
> > index 0000000000..28f60498fd
> > --- /dev/null
> > +++ b/drivers/gpio/mscc_sgpio.c
> > @@ -0,0 +1,252 @@
> > +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
> > +/*
> > + * Microsemi SoCs serial gpio driver
> > + *
> > + * Author: <lars.povlsen at microchip.com>
> > + * License: Dual MIT/GPL
> 
> this line is redundant due to the SPDX identifier

Removed.

> 
> > + * Copyright (c) 2018 Microsemi Corporation
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <asm/gpio.h>
> > +#include <asm/io.h>
> > +#include <errno.h>
> > +#include <clk.h>
> > +
> > +#define MSCC_SGPIOS_PER_BANK	32
> > +#define MSCC_SGPIO_BANK_DEPTH	4
> > +

[snip]

> > +static int mscc_sgpio_probe(struct udevice *dev)
> > +{
> > +	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
> > +	struct mscc_sgpio_priv *priv = dev_get_priv(dev);
> > +	const void *fdt = gd->fdt_blob;
> > +	int err, div_clock = 0, port, node = dev_of_offset(dev);
> > +	u32 val;
> > +	struct clk clk;
> > +
> > +	err = clk_get_by_index(dev, 0, &clk);
> > +	if (!err) {
> > +		err = clk_get_rate(&clk);
> > +		if (!IS_ERR_VALUE(err))
> > +			div_clock = err;
> > +	} else {
> > +		debug("mscc_sgpio: failed to get clock\n");
> > +		return err;
> > +	}
> > +
> > +	priv->props = (const struct mscc_sgpio_props
> *)dev_get_driver_data(dev);
> > +	priv->ports = fdtdec_get_int(fdt, node, "mscc,sgpio-ports",
> 0xFFFFFFFF);
> > +	priv->clock = fdtdec_get_int(fdt, node,
> > +				     "mscc,sgpio-frequency", 12500000);
> > +	if (priv->clock <= 0 || priv->clock > div_clock) {
> > +		printf("mscc_sgpio: Invalid frequency %d\n", priv->clock);
> > +		return -EINVAL;
> > +	}
> > +	priv->bitcount = fdtdec_get_int(fdt, node,
> > +					"mscc,sgpio-bitcount", 2);
> 
> you should use the newer DM API from include/dm/read.h which is more
> readable and you don't need to poke on gd->fdt_blob anymore. This would
> also make your driver live-tree compatible in case you want to enable
> that in the future.

Now using dev_read_u32_default() instead.

> 
> > +	if (priv->bitcount < 1 || priv->bitcount > 4) {
> > +		printf("mscc_sgpio: bit count %d\n", priv->bitcount);
> > +		return -EINVAL;
> > +	}
> > +	priv->regs = (u32 __iomem *)devfdt_get_addr(dev);
> 
> don't you need some mapping to a virtual address? Or is this mapped
> through TLB? Actually the address from device tree should be a physical
> one.

There is a 1:1 phys to virtual TLB mapping. Also, most of the other GPIO
drivers do it the same, but I added a map_physmem() call.

---Lars

> 
> > +	uc_priv->gpio_count = MSCC_SGPIOS_PER_BANK * priv->bitcount;
> > +	uc_priv->bank_name = "sgpio";
> > +
> > +	sgpio_clrsetbits(priv, REG_SIO_CONFIG, 0,
> > +			 MSCC_M_CFG_SIO_PORT_WIDTH(priv),
> > +			 MSCC_F_CFG_SIO_PORT_WIDTH(priv, priv->bitcount - 1) |
> > +			 MSCC_M_CFG_SIO_AUTO_REPEAT(priv));
> > +	val = div_clock / priv->clock;
> > +	debug("probe: div-clock = %d KHz, freq = %d KHz, div = %d\n",
> > +	      div_clock / 1000, priv->clock / 1000, val);
> > +	sgpio_clrsetbits(priv, REG_SIO_CLOCK, 0,
> > +			 MSCC_M_CLOCK_SIO_CLK_FREQ(priv),
> > +			 MSCC_F_CLOCK_SIO_CLK_FREQ(priv, val));
> > +
> > +	for (port = 0; port < 32; port++)
> > +		sgpio_writel(priv, 0, REG_PORT_CONFIG, port);
> > +	sgpio_writel(priv, priv->ports, REG_PORT_ENABLE, 0);
> > +
> > +	debug("probe: sgpio regs = %p\n", priv->regs);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct dm_gpio_ops mscc_sgpio_ops = {
> > +	.direction_input	= mscc_sgpio_direction_input,
> > +	.direction_output	= mscc_sgpio_direction_output,
> > +	.get_function		= mscc_sgpio_get_function,
> > +	.get_value		= mscc_sgpio_get_value,
> > +	.set_value		= mscc_sgpio_set_value,
> > +};
> > +
> > +static const struct udevice_id mscc_sgpio_ids[] = {
> > +	{ .compatible = "mscc,luton-sgpio", .data = (ulong)&props_luton },
> > +	{ .compatible = "mscc,ocelot-sgpio", .data = (ulong)&props_ocelot
> },
> > +	{ }
> > +};
> > +
> > +U_BOOT_DRIVER(gpio_mscc_sgpio) = {
> > +	.name			= "mscc-sgpio",
> > +	.id			= UCLASS_GPIO,
> > +	.of_match		= mscc_sgpio_ids,
> > +	.ops			= &mscc_sgpio_ops,
> > +	.probe			= mscc_sgpio_probe,
> > +	.priv_auto_alloc_size	= sizeof(struct mscc_sgpio_priv),
> > +};
> >
> 
> --
> - Daniel


More information about the U-Boot mailing list