devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andrew Lunn <andrew@lunn.ch>
To: Pantelis Antoniou <pantelis.antoniou@konsulko.com>,
	David Miller <davem@davemloft.net>
Cc: Lee Jones <lee.jones@linaro.org>,
	Linus Walleij <linus.walleij@linaro.org>,
	Alexandre Courbot <gnurou@gmail.com>,
	Rob Herring <robh+dt@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Frank Rowand <frowand.list@gmail.com>,
	Wolfram Sang <wsa@the-dreams.de>,
	David Woodhouse <dwmw2@infradead.org>,
	Brian Norris <computersforpeace@gmail.com>,
	Florian Fainelli <f.fainelli@gmail.com>,
	Wim Van Sebroeck <wim@iguana.be>, Peter Rosin <peda@axentia.se>,
	Debjit Ghosh <dghosh@juniper.net>,
	Georgi Vlaev <gvlaev@juniper.net>,
	Guenter Roeck <linux@roeck-us.net>,
	Maryam Seraj <mseraj@juniper.net>,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org,
	linux-mtd@lists.infradead.org, linux-watchdog@vger.
Subject: Re: [PATCH 09/10] net: phy: Add MDIO driver for Juniper's SAM FPGA
Date: Fri, 7 Oct 2016 23:13:26 +0200	[thread overview]
Message-ID: <20161007211326.GB10197@lunn.ch> (raw)
In-Reply-To: <1475853518-22264-10-git-send-email-pantelis.antoniou@konsulko.com>

On Fri, Oct 07, 2016 at 06:18:37PM +0300, Pantelis Antoniou wrote:
> From: Georgi Vlaev <gvlaev@juniper.net>
> 
> Add driver for the MDIO IP block present in Juniper's
> SAM FPGA.
> 
> This driver supports only Clause 45 of the 802.3 spec.
> 
> Note that due to the fact that there are no drivers for
> Broadcom/Avago retimers on 10/40Ge path that are controlled
> from the MDIO interface there is a method to have direct
> access to registers via a debugfs interface.

This seems to be the wrong solution. Why not write those drivers?

Controlling stuff from user space is generally frowned up. So i expect
DaveM will NACK this patch. Please remove all the debugfs stuff.

> +static int mdio_sam_stat_wait(struct mii_bus *bus, u32 wait_mask)
> +{
> +	struct mdio_sam_data *data = bus->priv;
> +	unsigned long timeout;
> +	u32 stat;
> +
> +	timeout = jiffies + msecs_to_jiffies(MDIO_RDY_TMO);
> +	do {
> +		stat = ioread32(data->base + MDIO_STATUS);
> +		if (stat & wait_mask)
> +			return 0;
> +
> +		usleep_range(50, 100);
> +	} while (time_before(jiffies, timeout));
> +
> +	return -EBUSY;

I've recently had to fix a loop like this in another
driver. usleep_range(50, 100) can sleep for a lot longer. If it sleeps
for MDIO_RDY_TMO you exit out with -EBUSY after a single iteration,
which is not what you want. It is better to make a fixed number of
iterations rather than a timeout.

> +}
> +
> +static int mdio_sam_read(struct mii_bus *bus, int phy_id, int regnum)
> +{
> +	struct mdio_sam_data *data = bus->priv;
> +	u32 command, res;
> +	int ret;
> +
> +	/* mdiobus_read holds the bus->mdio_lock mutex */
> +
> +	if (!(regnum & MII_ADDR_C45))
> +		return -ENXIO;
> +
> +	ret = mdio_sam_stat_wait(bus, STAT_REG_RDY);
> +	if (ret < 0)
> +		return ret;
> +
> +	command = regnum & 0x1fffff; /* regnum = (dev_id << 16) | reg */
> +	command |= ((phy_id & 0x1f) << 21);
> +
> +	iowrite32(command, data->base + MDIO_CMD1);
> +	ioread32(data->base + MDIO_CMD1);


> +	iowrite32(CMD2_READ | CMD2_ENABLE, data->base + MDIO_CMD2);
> +	ioread32(data->base + MDIO_CMD2);

Why do you need to read the values back? Hardware bug?

> +	iowrite32(TBL_CMD_REG_GO, data->base + MDIO_TBL_CMD);
> +	ioread32(data->base + MDIO_TBL_CMD);

Although not wrong, most drivers use writel().

> +
> +	usleep_range(50, 100);
> +
> +	ret = mdio_sam_stat_wait(bus, (STAT_REG_DONE | STAT_REG_ERR));

Do you really need a wait before calling mdio_sam_stat_wait()? Isn't
that what it is supposed to do, wait...

> +	if (ret < 0)
> +		return ret;
> +
> +	res = ioread32(data->base + MDIO_RESULT);
> +
> +	if (res & RES_ERROR || !(res & RES_SUCCESS))
> +		return -EIO;
> +
> +	return (res & 0xffff);
> +}
> +
> +static int mdio_sam_write(struct mii_bus *bus, int phy_id, int regnum, u16 val)
> +{
> +	struct mdio_sam_data *data = bus->priv;
> +	u32 command;
> +	int ret;
> +
> +	/* mdiobus_write holds the bus->mdio_lock mutex */
> +
> +	if (!(regnum & MII_ADDR_C45))
> +		return -ENXIO;
> +
> +	ret = mdio_sam_stat_wait(bus, STAT_REG_RDY);
> +	if (ret < 0)
> +		return ret;
> +
> +	command = regnum & 0x1fffff; /* regnum = (dev_id << 16) | reg */
> +	command |= ((phy_id & 0x1f) << 21);
> +
> +	iowrite32(command, data->base + MDIO_CMD1);
> +	ioread32(data->base + MDIO_CMD1);
> +	iowrite32(CMD2_ENABLE | val, data->base + MDIO_CMD2);
> +	ioread32(data->base + MDIO_CMD2);
> +	iowrite32(TBL_CMD_REG_GO, data->base + MDIO_TBL_CMD);
> +	ioread32(data->base + MDIO_TBL_CMD);
> +
> +	usleep_range(50, 100);
> +
> +	ret = mdio_sam_stat_wait(bus, (STAT_REG_DONE | STAT_REG_ERR));
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static int mdio_sam_reset(struct mii_bus *bus)
> +{
> +	struct mdio_sam_data *data = bus->priv;
> +
> +	iowrite32(TBL_CMD_SOFT_RESET, data->base + MDIO_TBL_CMD);
> +	ioread32(data->base + MDIO_TBL_CMD);
> +	mdelay(10);
> +	iowrite32(0, data->base + MDIO_TBL_CMD);
> +	ioread32(data->base + MDIO_TBL_CMD);
> +
> +	/* zero tables */
> +	memset_io(data->base + MDIO_CMD1, 0, 0x1000);
> +	memset_io(data->base + MDIO_PRI_CMD1, 0, 0x1000);

What tables?

> +
> +	return 0;
> +}
> +
> +static int mdio_sam_of_register_bus(struct platform_device *pdev,
> +				    struct device_node *np, void __iomem *base)
> +{
> +	struct mii_bus *bus;
> +	struct mdio_sam_data *data;
> +	u32 reg;
> +	int ret;
> +
> +	bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*data));
> +	if (!bus)
> +		return -ENOMEM;
> +
> +	/* bus offset */
> +	ret = of_property_read_u32(np, "reg", &reg);
> +	if (ret)
> +		return -ENODEV;
> +
> +	data = bus->priv;
> +	data->base = base + reg;
> +
> +	bus->parent = &pdev->dev;
> +	bus->name = "mdio-sam";
> +	bus->read = mdio_sam_read;
> +	bus->write = mdio_sam_write;
> +	bus->reset = mdio_sam_reset;
> +	snprintf(bus->id, MII_BUS_ID_SIZE, "mdiosam-%x-%x", pdev->id, reg);
> +
> +	ret = of_mdiobus_register(bus, np);
> +	if (ret < 0)
> +		return ret;
> +#ifdef CONFIG_DEBUG_FS
> +	ret = mdio_sam_debugfs_init(bus);
> +	if (ret < 0)
> +		goto err_unregister;
> +#endif
> +	ret = device_create_bin_file(&bus->dev, &bin_attr_raw_io);
> +	if (ret)
> +		goto err_debugfs;
> +
> +	return 0;
> +
> +err_debugfs:
> +#ifdef CONFIG_DEBUG_FS
> +	mdio_sam_debugfs_remove(bus);
> +#endif
> +err_unregister:
> +	mdiobus_unregister(bus);
> +
> +	return ret;
> +}
> +
> +static int mdio_sam_of_unregister_bus(struct device_node *np)
> +{
> +	struct mii_bus *bus;
> +
> +	bus = of_mdio_find_bus(np);
> +	if (bus) {
> +		device_remove_bin_file(&bus->dev, &bin_attr_raw_io);
> +#ifdef CONFIG_DEBUG_FS
> +		mdio_sam_debugfs_remove(bus);
> +#endif
> +		mdiobus_unregister(bus);
> +	}
> +	return 0;
> +}
> +
> +static int mdio_sam_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np;
> +	struct resource *res;
> +	void __iomem *base;
> +	int ret;
> +
> +	if (!pdev->dev.of_node)
> +		return -ENODEV;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	base = devm_ioremap_nocache(&pdev->dev, res->start,
> +				    resource_size(res));

Why nocache?

> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	for_each_available_child_of_node(pdev->dev.of_node, np) {
> +		ret = mdio_sam_of_register_bus(pdev, np, base);
> +		if (ret)
> +			goto err;
> +	}

This is odd. There does not seem to be any shared resources. So you
should really have one MDIO bus as one device in the device tree.



       Andrew

> +
> +	return 0;
> +err:
> +	/* roll back everything */
> +	for_each_available_child_of_node(pdev->dev.of_node, np)
> +		mdio_sam_of_unregister_bus(np);
> +
> +	return ret;
> +}
> +
> +static int mdio_sam_remove(struct platform_device *pdev)
> +{
> +	struct device_node *np;
> +
> +	for_each_available_child_of_node(pdev->dev.of_node, np)
> +		mdio_sam_of_unregister_bus(np);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id mdio_sam_of_match[] = {
> +	{ .compatible = "jnx,mdio-sam" },
> +	{  }
> +};
> +MODULE_DEVICE_TABLE(of, mdio_sam_of_match);
> +
> +static struct platform_driver mdio_sam_driver = {
> +	.probe = mdio_sam_probe,
> +	.remove = mdio_sam_remove,
> +	.driver = {
> +		.name = "mdio-sam",
> +		.owner = THIS_MODULE,
> +		.of_match_table = mdio_sam_of_match,
> +	},
> +};
> +
> +module_platform_driver(mdio_sam_driver);
> +
> +MODULE_ALIAS("platform:mdio-sam");
> +MODULE_AUTHOR("Georgi Vlaev <gvlaev@juniper.net>");
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("Juniper Networks SAM MDIO bus driver");
> -- 
> 1.9.1
> 

  reply	other threads:[~2016-10-07 21:13 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-07 15:18 [PATCH 00/10] Introduce Juniper SAM FPGA driver Pantelis Antoniou
2016-10-07 15:18 ` [PATCH 01/10] mfd: Add Juniper SAM FPGA MFD driver Pantelis Antoniou
2016-10-07 15:18 ` [PATCH 04/10] i2c: i2c-sam: Add device tree bindings Pantelis Antoniou
2016-10-10 19:54   ` Rob Herring
2016-10-11  7:13     ` Peter Rosin
2016-10-07 15:18 ` [PATCH 05/10] gpio: Introduce SAM gpio driver Pantelis Antoniou
2016-10-20 23:06   ` Linus Walleij
2016-10-07 15:18 ` [PATCH 06/10] gpio: sam: Document bindings of SAM FPGA GPIO block Pantelis Antoniou
2016-10-10 20:03   ` Rob Herring
2016-10-17 19:01     ` Pantelis Antoniou
2016-10-07 15:18 ` [PATCH 07/10] mtd: Add SAM Flash driver Pantelis Antoniou
2016-10-07 15:18 ` [PATCH 08/10] mtd: flash-sam: Bindings for Juniper's SAM FPGA flash Pantelis Antoniou
     [not found]   ` <1475853518-22264-9-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
2016-10-10 20:07     ` Rob Herring
2016-10-17 19:03       ` Pantelis Antoniou
2016-10-07 15:18 ` [PATCH 09/10] net: phy: Add MDIO driver for Juniper's SAM FPGA Pantelis Antoniou
2016-10-07 21:13   ` Andrew Lunn [this message]
2016-10-08 16:30     ` Georgi Vlaev
     [not found] ` <1475853518-22264-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
2016-10-07 15:18   ` [PATCH 02/10] mfd: sam: Add documentation for the " Pantelis Antoniou
2016-10-10 19:47     ` Rob Herring
2016-10-07 15:18   ` [PATCH 03/10] i2c: Juniper SAM I2C driver Pantelis Antoniou
2016-10-07 15:18   ` [PATCH 10/10] net: mdio-sam: Add device tree documentation for SAM MDIO Pantelis Antoniou
     [not found]     ` <1475853518-22264-11-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
2016-10-10  8:50       ` Florian Fainelli
2016-10-10 14:53     ` Peter Rosin

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=20161007211326.GB10197@lunn.ch \
    --to=andrew@lunn.ch \
    --cc=computersforpeace@gmail.com \
    --cc=davem@davemloft.net \
    --cc=devicetree@vger.kernel.org \
    --cc=dghosh@juniper.net \
    --cc=dwmw2@infradead.org \
    --cc=f.fainelli@gmail.com \
    --cc=frowand.list@gmail.com \
    --cc=gnurou@gmail.com \
    --cc=gvlaev@juniper.net \
    --cc=lee.jones@linaro.org \
    --cc=linus.walleij@linaro.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=linux-watchdog@vger. \
    --cc=linux@roeck-us.net \
    --cc=mark.rutland@arm.com \
    --cc=mseraj@juniper.net \
    --cc=pantelis.antoniou@konsulko.com \
    --cc=peda@axentia.se \
    --cc=robh+dt@kernel.org \
    --cc=wim@iguana.be \
    --cc=wsa@the-dreams.de \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).