diff mbox

[U-Boot,v7,04/10] usb: phy: Add STi USB2 PHY

Message ID 1496318714-21960-5-git-send-email-patrice.chotard@st.com
State Superseded
Headers show

Commit Message

Patrice CHOTARD June 1, 2017, 12:05 p.m. UTC
From: Patrice Chotard <patrice.chotard@st.com>

This is the generic phy driver for the picoPHY ports
used by USB2/1.1 controllers. It is found on STiH407 SoC
family from STMicroelectronics.

Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Reviewed-by: Marek Vasut <marex@denx.de>
---
v7:	_ replace fdtdec_parse_phandle_with_args() by dev_read_phandle_with_args() 
	_ replace uclass_get_device_by_of_offset() by uclass_get_device_by_ofnode()

v6:	_ none

v5:	_ add Reviewed-by: Marek Vasut <marex@denx.de>

v4:	_ update to use the new PHY uclass currently available on dm-next branch

v3: 	_ convert driver to USB PHY uclass

v2:	_ replace bitfield_replace() by clrsetbits_le32()

 doc/device-tree-bindings/phy/phy-stih407-usb.txt |  24 +++
 drivers/phy/Kconfig                              |   8 +
 drivers/phy/Makefile                             |   1 +
 drivers/phy/sti_usb_phy.c                        | 181 +++++++++++++++++++++++
 4 files changed, 214 insertions(+)
 create mode 100644 doc/device-tree-bindings/phy/phy-stih407-usb.txt
 create mode 100644 drivers/phy/sti_usb_phy.c

Comments

Simon Glass June 2, 2017, 2:56 a.m. UTC | #1
On 1 June 2017 at 06:05,  <patrice.chotard@st.com> wrote:
> From: Patrice Chotard <patrice.chotard@st.com>
>
> This is the generic phy driver for the picoPHY ports
> used by USB2/1.1 controllers. It is found on STiH407 SoC
> family from STMicroelectronics.
>
> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
> Reviewed-by: Marek Vasut <marex@denx.de>
> ---
> v7:     _ replace fdtdec_parse_phandle_with_args() by dev_read_phandle_with_args()
>         _ replace uclass_get_device_by_of_offset() by uclass_get_device_by_ofnode()
>
> v6:     _ none
>
> v5:     _ add Reviewed-by: Marek Vasut <marex@denx.de>
>
> v4:     _ update to use the new PHY uclass currently available on dm-next branch
>
> v3:     _ convert driver to USB PHY uclass
>
> v2:     _ replace bitfield_replace() by clrsetbits_le32()
>
>  doc/device-tree-bindings/phy/phy-stih407-usb.txt |  24 +++
>  drivers/phy/Kconfig                              |   8 +
>  drivers/phy/Makefile                             |   1 +
>  drivers/phy/sti_usb_phy.c                        | 181 +++++++++++++++++++++++
>  4 files changed, 214 insertions(+)
>  create mode 100644 doc/device-tree-bindings/phy/phy-stih407-usb.txt
>  create mode 100644 drivers/phy/sti_usb_phy.c
>

Reviewed-by: Simon Glass <sjg@chromium.org>
Marek Vasut June 3, 2017, 6:08 a.m. UTC | #2
On 06/01/2017 02:05 PM, patrice.chotard@st.com wrote:
> From: Patrice Chotard <patrice.chotard@st.com>
> 
> This is the generic phy driver for the picoPHY ports
> used by USB2/1.1 controllers. It is found on STiH407 SoC
> family from STMicroelectronics.
> 
> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
> Reviewed-by: Marek Vasut <marex@denx.de>
> ---
> v7:	_ replace fdtdec_parse_phandle_with_args() by dev_read_phandle_with_args() 
> 	_ replace uclass_get_device_by_of_offset() by uclass_get_device_by_ofnode()
> 

You should drop RB if you do significant changes.

> 
> v5:	_ add Reviewed-by: Marek Vasut <marex@denx.de>
> 
> v4:	_ update to use the new PHY uclass currently available on dm-next branch
> 
> v3: 	_ convert driver to USB PHY uclass
> 
> v2:	_ replace bitfield_replace() by clrsetbits_le32()
> 
>  doc/device-tree-bindings/phy/phy-stih407-usb.txt |  24 +++
>  drivers/phy/Kconfig                              |   8 +
>  drivers/phy/Makefile                             |   1 +
>  drivers/phy/sti_usb_phy.c                        | 181 +++++++++++++++++++++++
>  4 files changed, 214 insertions(+)
>  create mode 100644 doc/device-tree-bindings/phy/phy-stih407-usb.txt
>  create mode 100644 drivers/phy/sti_usb_phy.c
> 
> diff --git a/doc/device-tree-bindings/phy/phy-stih407-usb.txt b/doc/device-tree-bindings/phy/phy-stih407-usb.txt
> new file mode 100644
> index 0000000..de6a706
> --- /dev/null
> +++ b/doc/device-tree-bindings/phy/phy-stih407-usb.txt
> @@ -0,0 +1,24 @@
> +ST STiH407 USB PHY controller
> +
> +This file documents the dt bindings for the usb picoPHY driver which is the PHY for both USB2 and USB3
> +host controllers (when controlling usb2/1.1 devices) available on STiH407 SoC family from STMicroelectronics.
> +
> +Required properties:
> +- compatible		: should be "st,stih407-usb2-phy"
> +- st,syscfg		: phandle of sysconfig bank plus integer array containing phyparam and phyctrl register offsets
> +- resets		: list of phandle and reset specifier pairs. There should be two entries, one
> +			  for the whole phy and one for the port
> +- reset-names		: list of reset signal names. Should be "global" and "port"
> +See: Documentation/devicetree/bindings/reset/st,sti-powerdown.txt
> +See: Documentation/devicetree/bindings/reset/reset.txt
> +
> +Example:
> +
> +usb2_picophy0: usbpicophy@f8 {

This example uses address, but has no reg property ?

> +	compatible	= "st,stih407-usb2-phy";
> +	#phy-cells	= <0>;
> +	st,syscfg	= <&syscfg_core 0x100 0xf4>;
> +	resets		= <&softreset STIH407_PICOPHY_SOFTRESET>,
> +			  <&picophyreset STIH407_PICOPHY0_RESET>;
> +	reset-names	= "global", "port";
> +};
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index a91a694..4330b36 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -59,4 +59,12 @@ config SPL_PIPE3_PHY
>  	  This PHY is found on omap devices supporting SATA such as dra7, am57x
>  	  and omap5
>  
> +config STI_USB_PHY
> +	bool "STMicroelectronics USB2 picoPHY driver for STiH407 family"
> +	depends on PHY && ARCH_STI
> +	help
> +	  This is the generic phy driver for the picoPHY ports
> +	  used by USB2 and USB3 Host controllers available on
> +	  STiH407 SoC families.
> +
>  endmenu
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index 6ce96d2..22d92d3 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -8,3 +8,4 @@
>  obj-$(CONFIG_$(SPL_)PHY) += phy-uclass.o
>  obj-$(CONFIG_PHY_SANDBOX) += sandbox-phy.o
>  obj-$(CONFIG_$(SPL_)PIPE3_PHY) += ti-pipe3-phy.o
> +obj-$(CONFIG_STI_USB_PHY) += sti_usb_phy.o
> diff --git a/drivers/phy/sti_usb_phy.c b/drivers/phy/sti_usb_phy.c
> new file mode 100644
> index 0000000..0e0b1c0
> --- /dev/null
> +++ b/drivers/phy/sti_usb_phy.c
> @@ -0,0 +1,181 @@
> +/*
> + * Copyright (c) 2017
> + * Patrice Chotard <patrice.chotard@st.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <bitfield.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <fdtdec.h>
> +#include <generic-phy.h>
> +#include <libfdt.h>
> +#include <regmap.h>
> +#include <reset-uclass.h>
> +#include <syscon.h>
> +#include <wait_bit.h>
> +
> +#include <linux/bitops.h>
> +#include <linux/compat.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* Default PHY_SEL and REFCLKSEL configuration */
> +#define STIH407_USB_PICOPHY_CTRL_PORT_CONF	0x6
> +
> +/* ports parameters overriding */
> +#define STIH407_USB_PICOPHY_PARAM_DEF		0x39a4dc
> +
> +#define PHYPARAM_REG	1
> +#define PHYCTRL_REG	2
> +#define PHYPARAM_NB	3
> +
> +struct sti_usb_phy {
> +	struct regmap *regmap;
> +	struct reset_ctl global_ctl;
> +	struct reset_ctl port_ctl;
> +	int param;
> +	int ctrl;
> +};
> +
> +static int sti_usb_phy_deassert(struct sti_usb_phy *phy)
> +{
> +	int ret;
> +
> +	ret = reset_deassert(&phy->global_ctl);
> +	if (ret < 0) {
> +		error("PHY global deassert failed: %d", ret);
> +		return ret;
> +	}
> +
> +	ret = reset_deassert(&phy->port_ctl);
> +	if (ret < 0)
> +		error("PHY port deassert failed: %d", ret);
> +
> +	return ret;
> +}
> +
> +static int sti_usb_phy_init(struct phy *usb_phy)
> +{
> +	struct udevice *dev = usb_phy->dev;
> +	struct sti_usb_phy *phy = dev_get_priv(dev);
> +	void __iomem *reg;
> +
> +	/* set ctrl picophy value */
> +	reg = (void __iomem *)phy->regmap->base + phy->ctrl;
> +	/* CTRL_PORT mask is 0x1f */
> +	clrsetbits_le32(reg, 0x1f, STIH407_USB_PICOPHY_CTRL_PORT_CONF);
> +
> +	/* set ports parameters overriding */
> +	reg = (void __iomem *)phy->regmap->base + phy->param;
> +	/* PARAM_DEF mask is 0xffffffff */
> +	clrsetbits_le32(reg, 0xffffffff, STIH407_USB_PICOPHY_PARAM_DEF);
> +
> +	return sti_usb_phy_deassert(phy);
> +}
> +
> +static int sti_usb_phy_exit(struct phy *usb_phy)
> +{
> +	struct udevice *dev = usb_phy->dev;
> +	struct sti_usb_phy *phy = dev_get_priv(dev);
> +	int ret;
> +
> +	ret = reset_assert(&phy->port_ctl);
> +	if (ret < 0) {
> +		error("PHY port assert failed: %d", ret);
> +		return ret;
> +	}
> +
> +	ret = reset_assert(&phy->global_ctl);
> +	if (ret < 0)
> +		error("PHY global assert failed: %d", ret);
> +
> +	return ret;
> +}
> +
> +struct phy_ops sti_usb_phy_ops = {
> +	.init = sti_usb_phy_init,
> +	.exit = sti_usb_phy_exit,
> +};
> +
> +int sti_usb_phy_probe(struct udevice *dev)
> +{
> +	struct sti_usb_phy *priv = dev_get_priv(dev);
> +	struct udevice *syscon;
> +	struct ofnode_phandle_args syscfg_phandle;
> +	u32 cells[PHYPARAM_NB];
> +	int ret, count;
> +
> +	/* get corresponding syscon phandle */
> +	ret = dev_read_phandle_with_args(dev, "st,syscfg", NULL, 0, 0,
> +					 &syscfg_phandle);
> +
> +	if (ret < 0) {
> +		error("Can't get syscfg phandle: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = uclass_get_device_by_ofnode(UCLASS_SYSCON, syscfg_phandle.node,
> +					  &syscon);
> +	if (ret) {
> +		error("unable to find syscon device (%d)\n", ret);
> +		return ret;
> +	}
> +
> +	priv->regmap = syscon_get_regmap(syscon);
> +	if (!priv->regmap) {
> +		error("unable to find regmap\n");
> +		return -ENODEV;
> +	}
> +
> +	/* get phy param offset */
> +	count = fdtdec_get_int_array_count(gd->fdt_blob, dev_of_offset(dev),
> +					   "st,syscfg", cells,
> +					   ARRAY_SIZE(cells));
> +
> +	if (count < 0) {
> +		error("Bad PHY st,syscfg property %d\n", count);
> +		return -EINVAL;
> +	}
> +
> +	if (count > PHYPARAM_NB) {
> +		error("Unsupported PHY param count %d\n", count);
> +		return -EINVAL;
> +	}
> +
> +	priv->param = cells[PHYPARAM_REG];
> +	priv->ctrl = cells[PHYCTRL_REG];
> +
> +	/* get global reset control */
> +	ret = reset_get_by_name(dev, "global", &priv->global_ctl);
> +	if (ret) {
> +		error("can't get global reset for %s (%d)", dev->name, ret);
> +		return ret;
> +	}
> +
> +	/* get port reset control */
> +	ret = reset_get_by_name(dev, "port", &priv->port_ctl);
> +	if (ret) {
> +		error("can't get port reset for %s (%d)", dev->name, ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct udevice_id sti_usb_phy_ids[] = {
> +	{ .compatible = "st,stih407-usb2-phy" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(sti_usb_phy) = {
> +	.name = "sti_usb_phy",
> +	.id = UCLASS_PHY,
> +	.of_match = sti_usb_phy_ids,
> +	.probe = sti_usb_phy_probe,
> +	.ops = &sti_usb_phy_ops,
> +	.priv_auto_alloc_size = sizeof(struct sti_usb_phy),
> +};
>
Patrice CHOTARD June 5, 2017, 6:58 a.m. UTC | #3
Hi Marek

On 06/03/2017 08:08 AM, Marek Vasut wrote:
> On 06/01/2017 02:05 PM, patrice.chotard@st.com wrote:

>> From: Patrice Chotard <patrice.chotard@st.com>

>>

>> This is the generic phy driver for the picoPHY ports

>> used by USB2/1.1 controllers. It is found on STiH407 SoC

>> family from STMicroelectronics.

>>

>> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>

>> Reviewed-by: Marek Vasut <marex@denx.de>

>> ---

>> v7:	_ replace fdtdec_parse_phandle_with_args() by dev_read_phandle_with_args()

>> 	_ replace uclass_get_device_by_of_offset() by uclass_get_device_by_ofnode()

>>

> 

> You should drop RB if you do significant changes.

> 

>>

>> v5:	_ add Reviewed-by: Marek Vasut <marex@denx.de>

>>

>> v4:	_ update to use the new PHY uclass currently available on dm-next branch

>>

>> v3: 	_ convert driver to USB PHY uclass

>>

>> v2:	_ replace bitfield_replace() by clrsetbits_le32()

>>

>>   doc/device-tree-bindings/phy/phy-stih407-usb.txt |  24 +++

>>   drivers/phy/Kconfig                              |   8 +

>>   drivers/phy/Makefile                             |   1 +

>>   drivers/phy/sti_usb_phy.c                        | 181 +++++++++++++++++++++++

>>   4 files changed, 214 insertions(+)

>>   create mode 100644 doc/device-tree-bindings/phy/phy-stih407-usb.txt

>>   create mode 100644 drivers/phy/sti_usb_phy.c

>>

>> diff --git a/doc/device-tree-bindings/phy/phy-stih407-usb.txt b/doc/device-tree-bindings/phy/phy-stih407-usb.txt

>> new file mode 100644

>> index 0000000..de6a706

>> --- /dev/null

>> +++ b/doc/device-tree-bindings/phy/phy-stih407-usb.txt

>> @@ -0,0 +1,24 @@

>> +ST STiH407 USB PHY controller

>> +

>> +This file documents the dt bindings for the usb picoPHY driver which is the PHY for both USB2 and USB3

>> +host controllers (when controlling usb2/1.1 devices) available on STiH407 SoC family from STMicroelectronics.

>> +

>> +Required properties:

>> +- compatible		: should be "st,stih407-usb2-phy"

>> +- st,syscfg		: phandle of sysconfig bank plus integer array containing phyparam and phyctrl register offsets

>> +- resets		: list of phandle and reset specifier pairs. There should be two entries, one

>> +			  for the whole phy and one for the port

>> +- reset-names		: list of reset signal names. Should be "global" and "port"

>> +See: Documentation/devicetree/bindings/reset/st,sti-powerdown.txt

>> +See: Documentation/devicetree/bindings/reset/reset.txt

>> +

>> +Example:

>> +

>> +usb2_picophy0: usbpicophy@f8 {

> 

> This example uses address, but has no reg property ?


Agree, but following advices from Arnd Bergman about not mixing address 
space and sysconfig registers int the reg property, the reg property was 
removed.

For more details, see https://patches.linaro.org/patch/44081/

> 

>> +	compatible	= "st,stih407-usb2-phy";

>> +	#phy-cells	= <0>;

>> +	st,syscfg	= <&syscfg_core 0x100 0xf4>;

>> +	resets		= <&softreset STIH407_PICOPHY_SOFTRESET>,

>> +			  <&picophyreset STIH407_PICOPHY0_RESET>;

>> +	reset-names	= "global", "port";

>> +};

>> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig

>> index a91a694..4330b36 100644

>> --- a/drivers/phy/Kconfig

>> +++ b/drivers/phy/Kconfig

>> @@ -59,4 +59,12 @@ config SPL_PIPE3_PHY

>>   	  This PHY is found on omap devices supporting SATA such as dra7, am57x

>>   	  and omap5

>>   

>> +config STI_USB_PHY

>> +	bool "STMicroelectronics USB2 picoPHY driver for STiH407 family"

>> +	depends on PHY && ARCH_STI

>> +	help

>> +	  This is the generic phy driver for the picoPHY ports

>> +	  used by USB2 and USB3 Host controllers available on

>> +	  STiH407 SoC families.

>> +

>>   endmenu

>> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile

>> index 6ce96d2..22d92d3 100644

>> --- a/drivers/phy/Makefile

>> +++ b/drivers/phy/Makefile

>> @@ -8,3 +8,4 @@

>>   obj-$(CONFIG_$(SPL_)PHY) += phy-uclass.o

>>   obj-$(CONFIG_PHY_SANDBOX) += sandbox-phy.o

>>   obj-$(CONFIG_$(SPL_)PIPE3_PHY) += ti-pipe3-phy.o

>> +obj-$(CONFIG_STI_USB_PHY) += sti_usb_phy.o

>> diff --git a/drivers/phy/sti_usb_phy.c b/drivers/phy/sti_usb_phy.c

>> new file mode 100644

>> index 0000000..0e0b1c0

>> --- /dev/null

>> +++ b/drivers/phy/sti_usb_phy.c

>> @@ -0,0 +1,181 @@

>> +/*

>> + * Copyright (c) 2017

>> + * Patrice Chotard <patrice.chotard@st.com>

>> + *

>> + * SPDX-License-Identifier:	GPL-2.0+

>> + */

>> +

>> +#include <common.h>

>> +#include <asm/io.h>

>> +#include <bitfield.h>

>> +#include <dm.h>

>> +#include <errno.h>

>> +#include <fdtdec.h>

>> +#include <generic-phy.h>

>> +#include <libfdt.h>

>> +#include <regmap.h>

>> +#include <reset-uclass.h>

>> +#include <syscon.h>

>> +#include <wait_bit.h>

>> +

>> +#include <linux/bitops.h>

>> +#include <linux/compat.h>

>> +

>> +DECLARE_GLOBAL_DATA_PTR;

>> +

>> +/* Default PHY_SEL and REFCLKSEL configuration */

>> +#define STIH407_USB_PICOPHY_CTRL_PORT_CONF	0x6

>> +

>> +/* ports parameters overriding */

>> +#define STIH407_USB_PICOPHY_PARAM_DEF		0x39a4dc

>> +

>> +#define PHYPARAM_REG	1

>> +#define PHYCTRL_REG	2

>> +#define PHYPARAM_NB	3

>> +

>> +struct sti_usb_phy {

>> +	struct regmap *regmap;

>> +	struct reset_ctl global_ctl;

>> +	struct reset_ctl port_ctl;

>> +	int param;

>> +	int ctrl;

>> +};

>> +

>> +static int sti_usb_phy_deassert(struct sti_usb_phy *phy)

>> +{

>> +	int ret;

>> +

>> +	ret = reset_deassert(&phy->global_ctl);

>> +	if (ret < 0) {

>> +		error("PHY global deassert failed: %d", ret);

>> +		return ret;

>> +	}

>> +

>> +	ret = reset_deassert(&phy->port_ctl);

>> +	if (ret < 0)

>> +		error("PHY port deassert failed: %d", ret);

>> +

>> +	return ret;

>> +}

>> +

>> +static int sti_usb_phy_init(struct phy *usb_phy)

>> +{

>> +	struct udevice *dev = usb_phy->dev;

>> +	struct sti_usb_phy *phy = dev_get_priv(dev);

>> +	void __iomem *reg;

>> +

>> +	/* set ctrl picophy value */

>> +	reg = (void __iomem *)phy->regmap->base + phy->ctrl;

>> +	/* CTRL_PORT mask is 0x1f */

>> +	clrsetbits_le32(reg, 0x1f, STIH407_USB_PICOPHY_CTRL_PORT_CONF);

>> +

>> +	/* set ports parameters overriding */

>> +	reg = (void __iomem *)phy->regmap->base + phy->param;

>> +	/* PARAM_DEF mask is 0xffffffff */

>> +	clrsetbits_le32(reg, 0xffffffff, STIH407_USB_PICOPHY_PARAM_DEF);

>> +

>> +	return sti_usb_phy_deassert(phy);

>> +}

>> +

>> +static int sti_usb_phy_exit(struct phy *usb_phy)

>> +{

>> +	struct udevice *dev = usb_phy->dev;

>> +	struct sti_usb_phy *phy = dev_get_priv(dev);

>> +	int ret;

>> +

>> +	ret = reset_assert(&phy->port_ctl);

>> +	if (ret < 0) {

>> +		error("PHY port assert failed: %d", ret);

>> +		return ret;

>> +	}

>> +

>> +	ret = reset_assert(&phy->global_ctl);

>> +	if (ret < 0)

>> +		error("PHY global assert failed: %d", ret);

>> +

>> +	return ret;

>> +}

>> +

>> +struct phy_ops sti_usb_phy_ops = {

>> +	.init = sti_usb_phy_init,

>> +	.exit = sti_usb_phy_exit,

>> +};

>> +

>> +int sti_usb_phy_probe(struct udevice *dev)

>> +{

>> +	struct sti_usb_phy *priv = dev_get_priv(dev);

>> +	struct udevice *syscon;

>> +	struct ofnode_phandle_args syscfg_phandle;

>> +	u32 cells[PHYPARAM_NB];

>> +	int ret, count;

>> +

>> +	/* get corresponding syscon phandle */

>> +	ret = dev_read_phandle_with_args(dev, "st,syscfg", NULL, 0, 0,

>> +					 &syscfg_phandle);

>> +

>> +	if (ret < 0) {

>> +		error("Can't get syscfg phandle: %d\n", ret);

>> +		return ret;

>> +	}

>> +

>> +	ret = uclass_get_device_by_ofnode(UCLASS_SYSCON, syscfg_phandle.node,

>> +					  &syscon);

>> +	if (ret) {

>> +		error("unable to find syscon device (%d)\n", ret);

>> +		return ret;

>> +	}

>> +

>> +	priv->regmap = syscon_get_regmap(syscon);

>> +	if (!priv->regmap) {

>> +		error("unable to find regmap\n");

>> +		return -ENODEV;

>> +	}

>> +

>> +	/* get phy param offset */

>> +	count = fdtdec_get_int_array_count(gd->fdt_blob, dev_of_offset(dev),

>> +					   "st,syscfg", cells,

>> +					   ARRAY_SIZE(cells));

>> +

>> +	if (count < 0) {

>> +		error("Bad PHY st,syscfg property %d\n", count);

>> +		return -EINVAL;

>> +	}

>> +

>> +	if (count > PHYPARAM_NB) {

>> +		error("Unsupported PHY param count %d\n", count);

>> +		return -EINVAL;

>> +	}

>> +

>> +	priv->param = cells[PHYPARAM_REG];

>> +	priv->ctrl = cells[PHYCTRL_REG];

>> +

>> +	/* get global reset control */

>> +	ret = reset_get_by_name(dev, "global", &priv->global_ctl);

>> +	if (ret) {

>> +		error("can't get global reset for %s (%d)", dev->name, ret);

>> +		return ret;

>> +	}

>> +

>> +	/* get port reset control */

>> +	ret = reset_get_by_name(dev, "port", &priv->port_ctl);

>> +	if (ret) {

>> +		error("can't get port reset for %s (%d)", dev->name, ret);

>> +		return ret;

>> +	}

>> +

>> +	return 0;

>> +}

>> +

>> +static const struct udevice_id sti_usb_phy_ids[] = {

>> +	{ .compatible = "st,stih407-usb2-phy" },

>> +	{ }

>> +};

>> +

>> +U_BOOT_DRIVER(sti_usb_phy) = {

>> +	.name = "sti_usb_phy",

>> +	.id = UCLASS_PHY,

>> +	.of_match = sti_usb_phy_ids,

>> +	.probe = sti_usb_phy_probe,

>> +	.ops = &sti_usb_phy_ops,

>> +	.priv_auto_alloc_size = sizeof(struct sti_usb_phy),

>> +};

>>

> 

>
Marek Vasut June 5, 2017, 11:21 a.m. UTC | #4
On 06/05/2017 08:58 AM, Patrice CHOTARD wrote:
> Hi Marek
> 
> On 06/03/2017 08:08 AM, Marek Vasut wrote:
>> On 06/01/2017 02:05 PM, patrice.chotard@st.com wrote:
>>> From: Patrice Chotard <patrice.chotard@st.com>
>>>
>>> This is the generic phy driver for the picoPHY ports
>>> used by USB2/1.1 controllers. It is found on STiH407 SoC
>>> family from STMicroelectronics.
>>>
>>> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
>>> Reviewed-by: Marek Vasut <marex@denx.de>
>>> ---
>>> v7:	_ replace fdtdec_parse_phandle_with_args() by dev_read_phandle_with_args()
>>> 	_ replace uclass_get_device_by_of_offset() by uclass_get_device_by_ofnode()
>>>
>>
>> You should drop RB if you do significant changes.
>>
>>>
>>> v5:	_ add Reviewed-by: Marek Vasut <marex@denx.de>
>>>
>>> v4:	_ update to use the new PHY uclass currently available on dm-next branch
>>>
>>> v3: 	_ convert driver to USB PHY uclass
>>>
>>> v2:	_ replace bitfield_replace() by clrsetbits_le32()
>>>
>>>   doc/device-tree-bindings/phy/phy-stih407-usb.txt |  24 +++
>>>   drivers/phy/Kconfig                              |   8 +
>>>   drivers/phy/Makefile                             |   1 +
>>>   drivers/phy/sti_usb_phy.c                        | 181 +++++++++++++++++++++++
>>>   4 files changed, 214 insertions(+)
>>>   create mode 100644 doc/device-tree-bindings/phy/phy-stih407-usb.txt
>>>   create mode 100644 drivers/phy/sti_usb_phy.c
>>>
>>> diff --git a/doc/device-tree-bindings/phy/phy-stih407-usb.txt b/doc/device-tree-bindings/phy/phy-stih407-usb.txt
>>> new file mode 100644
>>> index 0000000..de6a706
>>> --- /dev/null
>>> +++ b/doc/device-tree-bindings/phy/phy-stih407-usb.txt
>>> @@ -0,0 +1,24 @@
>>> +ST STiH407 USB PHY controller
>>> +
>>> +This file documents the dt bindings for the usb picoPHY driver which is the PHY for both USB2 and USB3
>>> +host controllers (when controlling usb2/1.1 devices) available on STiH407 SoC family from STMicroelectronics.
>>> +
>>> +Required properties:
>>> +- compatible		: should be "st,stih407-usb2-phy"
>>> +- st,syscfg		: phandle of sysconfig bank plus integer array containing phyparam and phyctrl register offsets
>>> +- resets		: list of phandle and reset specifier pairs. There should be two entries, one
>>> +			  for the whole phy and one for the port
>>> +- reset-names		: list of reset signal names. Should be "global" and "port"
>>> +See: Documentation/devicetree/bindings/reset/st,sti-powerdown.txt
>>> +See: Documentation/devicetree/bindings/reset/reset.txt
>>> +
>>> +Example:
>>> +
>>> +usb2_picophy0: usbpicophy@f8 {
>>
>> This example uses address, but has no reg property ?
> 
> Agree, but following advices from Arnd Bergman about not mixing address 
> space and sysconfig registers int the reg property, the reg property was 
> removed.
> 
> For more details, see https://patches.linaro.org/patch/44081/

Then you should remove it from usbpicophy@f8 too .

[...]
Patrice CHOTARD June 6, 2017, 7:16 a.m. UTC | #5
Hi Marek

On 06/05/2017 01:21 PM, Marek Vasut wrote:
> On 06/05/2017 08:58 AM, Patrice CHOTARD wrote:

>> Hi Marek

>>

>> On 06/03/2017 08:08 AM, Marek Vasut wrote:

>>> On 06/01/2017 02:05 PM, patrice.chotard@st.com wrote:

>>>> From: Patrice Chotard <patrice.chotard@st.com>

>>>>

>>>> This is the generic phy driver for the picoPHY ports

>>>> used by USB2/1.1 controllers. It is found on STiH407 SoC

>>>> family from STMicroelectronics.

>>>>

>>>> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>

>>>> Reviewed-by: Marek Vasut <marex@denx.de>

>>>> ---

>>>> v7:	_ replace fdtdec_parse_phandle_with_args() by dev_read_phandle_with_args()

>>>> 	_ replace uclass_get_device_by_of_offset() by uclass_get_device_by_ofnode()

>>>>

>>>

>>> You should drop RB if you do significant changes.

>>>

>>>>

>>>> v5:	_ add Reviewed-by: Marek Vasut <marex@denx.de>

>>>>

>>>> v4:	_ update to use the new PHY uclass currently available on dm-next branch

>>>>

>>>> v3: 	_ convert driver to USB PHY uclass

>>>>

>>>> v2:	_ replace bitfield_replace() by clrsetbits_le32()

>>>>

>>>>    doc/device-tree-bindings/phy/phy-stih407-usb.txt |  24 +++

>>>>    drivers/phy/Kconfig                              |   8 +

>>>>    drivers/phy/Makefile                             |   1 +

>>>>    drivers/phy/sti_usb_phy.c                        | 181 +++++++++++++++++++++++

>>>>    4 files changed, 214 insertions(+)

>>>>    create mode 100644 doc/device-tree-bindings/phy/phy-stih407-usb.txt

>>>>    create mode 100644 drivers/phy/sti_usb_phy.c

>>>>

>>>> diff --git a/doc/device-tree-bindings/phy/phy-stih407-usb.txt b/doc/device-tree-bindings/phy/phy-stih407-usb.txt

>>>> new file mode 100644

>>>> index 0000000..de6a706

>>>> --- /dev/null

>>>> +++ b/doc/device-tree-bindings/phy/phy-stih407-usb.txt

>>>> @@ -0,0 +1,24 @@

>>>> +ST STiH407 USB PHY controller

>>>> +

>>>> +This file documents the dt bindings for the usb picoPHY driver which is the PHY for both USB2 and USB3

>>>> +host controllers (when controlling usb2/1.1 devices) available on STiH407 SoC family from STMicroelectronics.

>>>> +

>>>> +Required properties:

>>>> +- compatible		: should be "st,stih407-usb2-phy"

>>>> +- st,syscfg		: phandle of sysconfig bank plus integer array containing phyparam and phyctrl register offsets

>>>> +- resets		: list of phandle and reset specifier pairs. There should be two entries, one

>>>> +			  for the whole phy and one for the port

>>>> +- reset-names		: list of reset signal names. Should be "global" and "port"

>>>> +See: Documentation/devicetree/bindings/reset/st,sti-powerdown.txt

>>>> +See: Documentation/devicetree/bindings/reset/reset.txt

>>>> +

>>>> +Example:

>>>> +

>>>> +usb2_picophy0: usbpicophy@f8 {

>>>

>>> This example uses address, but has no reg property ?

>>

>> Agree, but following advices from Arnd Bergman about not mixing address

>> space and sysconfig registers int the reg property, the reg property was

>> removed.

>>

>> For more details, see https://patches.linaro.org/patch/44081/

> 

> Then you should remove it from usbpicophy@f8 too .


Ok

> 

> [...]

>
diff mbox

Patch

diff --git a/doc/device-tree-bindings/phy/phy-stih407-usb.txt b/doc/device-tree-bindings/phy/phy-stih407-usb.txt
new file mode 100644
index 0000000..de6a706
--- /dev/null
+++ b/doc/device-tree-bindings/phy/phy-stih407-usb.txt
@@ -0,0 +1,24 @@ 
+ST STiH407 USB PHY controller
+
+This file documents the dt bindings for the usb picoPHY driver which is the PHY for both USB2 and USB3
+host controllers (when controlling usb2/1.1 devices) available on STiH407 SoC family from STMicroelectronics.
+
+Required properties:
+- compatible		: should be "st,stih407-usb2-phy"
+- st,syscfg		: phandle of sysconfig bank plus integer array containing phyparam and phyctrl register offsets
+- resets		: list of phandle and reset specifier pairs. There should be two entries, one
+			  for the whole phy and one for the port
+- reset-names		: list of reset signal names. Should be "global" and "port"
+See: Documentation/devicetree/bindings/reset/st,sti-powerdown.txt
+See: Documentation/devicetree/bindings/reset/reset.txt
+
+Example:
+
+usb2_picophy0: usbpicophy@f8 {
+	compatible	= "st,stih407-usb2-phy";
+	#phy-cells	= <0>;
+	st,syscfg	= <&syscfg_core 0x100 0xf4>;
+	resets		= <&softreset STIH407_PICOPHY_SOFTRESET>,
+			  <&picophyreset STIH407_PICOPHY0_RESET>;
+	reset-names	= "global", "port";
+};
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index a91a694..4330b36 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -59,4 +59,12 @@  config SPL_PIPE3_PHY
 	  This PHY is found on omap devices supporting SATA such as dra7, am57x
 	  and omap5
 
+config STI_USB_PHY
+	bool "STMicroelectronics USB2 picoPHY driver for STiH407 family"
+	depends on PHY && ARCH_STI
+	help
+	  This is the generic phy driver for the picoPHY ports
+	  used by USB2 and USB3 Host controllers available on
+	  STiH407 SoC families.
+
 endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 6ce96d2..22d92d3 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -8,3 +8,4 @@ 
 obj-$(CONFIG_$(SPL_)PHY) += phy-uclass.o
 obj-$(CONFIG_PHY_SANDBOX) += sandbox-phy.o
 obj-$(CONFIG_$(SPL_)PIPE3_PHY) += ti-pipe3-phy.o
+obj-$(CONFIG_STI_USB_PHY) += sti_usb_phy.o
diff --git a/drivers/phy/sti_usb_phy.c b/drivers/phy/sti_usb_phy.c
new file mode 100644
index 0000000..0e0b1c0
--- /dev/null
+++ b/drivers/phy/sti_usb_phy.c
@@ -0,0 +1,181 @@ 
+/*
+ * Copyright (c) 2017
+ * Patrice Chotard <patrice.chotard@st.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <bitfield.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <generic-phy.h>
+#include <libfdt.h>
+#include <regmap.h>
+#include <reset-uclass.h>
+#include <syscon.h>
+#include <wait_bit.h>
+
+#include <linux/bitops.h>
+#include <linux/compat.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Default PHY_SEL and REFCLKSEL configuration */
+#define STIH407_USB_PICOPHY_CTRL_PORT_CONF	0x6
+
+/* ports parameters overriding */
+#define STIH407_USB_PICOPHY_PARAM_DEF		0x39a4dc
+
+#define PHYPARAM_REG	1
+#define PHYCTRL_REG	2
+#define PHYPARAM_NB	3
+
+struct sti_usb_phy {
+	struct regmap *regmap;
+	struct reset_ctl global_ctl;
+	struct reset_ctl port_ctl;
+	int param;
+	int ctrl;
+};
+
+static int sti_usb_phy_deassert(struct sti_usb_phy *phy)
+{
+	int ret;
+
+	ret = reset_deassert(&phy->global_ctl);
+	if (ret < 0) {
+		error("PHY global deassert failed: %d", ret);
+		return ret;
+	}
+
+	ret = reset_deassert(&phy->port_ctl);
+	if (ret < 0)
+		error("PHY port deassert failed: %d", ret);
+
+	return ret;
+}
+
+static int sti_usb_phy_init(struct phy *usb_phy)
+{
+	struct udevice *dev = usb_phy->dev;
+	struct sti_usb_phy *phy = dev_get_priv(dev);
+	void __iomem *reg;
+
+	/* set ctrl picophy value */
+	reg = (void __iomem *)phy->regmap->base + phy->ctrl;
+	/* CTRL_PORT mask is 0x1f */
+	clrsetbits_le32(reg, 0x1f, STIH407_USB_PICOPHY_CTRL_PORT_CONF);
+
+	/* set ports parameters overriding */
+	reg = (void __iomem *)phy->regmap->base + phy->param;
+	/* PARAM_DEF mask is 0xffffffff */
+	clrsetbits_le32(reg, 0xffffffff, STIH407_USB_PICOPHY_PARAM_DEF);
+
+	return sti_usb_phy_deassert(phy);
+}
+
+static int sti_usb_phy_exit(struct phy *usb_phy)
+{
+	struct udevice *dev = usb_phy->dev;
+	struct sti_usb_phy *phy = dev_get_priv(dev);
+	int ret;
+
+	ret = reset_assert(&phy->port_ctl);
+	if (ret < 0) {
+		error("PHY port assert failed: %d", ret);
+		return ret;
+	}
+
+	ret = reset_assert(&phy->global_ctl);
+	if (ret < 0)
+		error("PHY global assert failed: %d", ret);
+
+	return ret;
+}
+
+struct phy_ops sti_usb_phy_ops = {
+	.init = sti_usb_phy_init,
+	.exit = sti_usb_phy_exit,
+};
+
+int sti_usb_phy_probe(struct udevice *dev)
+{
+	struct sti_usb_phy *priv = dev_get_priv(dev);
+	struct udevice *syscon;
+	struct ofnode_phandle_args syscfg_phandle;
+	u32 cells[PHYPARAM_NB];
+	int ret, count;
+
+	/* get corresponding syscon phandle */
+	ret = dev_read_phandle_with_args(dev, "st,syscfg", NULL, 0, 0,
+					 &syscfg_phandle);
+
+	if (ret < 0) {
+		error("Can't get syscfg phandle: %d\n", ret);
+		return ret;
+	}
+
+	ret = uclass_get_device_by_ofnode(UCLASS_SYSCON, syscfg_phandle.node,
+					  &syscon);
+	if (ret) {
+		error("unable to find syscon device (%d)\n", ret);
+		return ret;
+	}
+
+	priv->regmap = syscon_get_regmap(syscon);
+	if (!priv->regmap) {
+		error("unable to find regmap\n");
+		return -ENODEV;
+	}
+
+	/* get phy param offset */
+	count = fdtdec_get_int_array_count(gd->fdt_blob, dev_of_offset(dev),
+					   "st,syscfg", cells,
+					   ARRAY_SIZE(cells));
+
+	if (count < 0) {
+		error("Bad PHY st,syscfg property %d\n", count);
+		return -EINVAL;
+	}
+
+	if (count > PHYPARAM_NB) {
+		error("Unsupported PHY param count %d\n", count);
+		return -EINVAL;
+	}
+
+	priv->param = cells[PHYPARAM_REG];
+	priv->ctrl = cells[PHYCTRL_REG];
+
+	/* get global reset control */
+	ret = reset_get_by_name(dev, "global", &priv->global_ctl);
+	if (ret) {
+		error("can't get global reset for %s (%d)", dev->name, ret);
+		return ret;
+	}
+
+	/* get port reset control */
+	ret = reset_get_by_name(dev, "port", &priv->port_ctl);
+	if (ret) {
+		error("can't get port reset for %s (%d)", dev->name, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct udevice_id sti_usb_phy_ids[] = {
+	{ .compatible = "st,stih407-usb2-phy" },
+	{ }
+};
+
+U_BOOT_DRIVER(sti_usb_phy) = {
+	.name = "sti_usb_phy",
+	.id = UCLASS_PHY,
+	.of_match = sti_usb_phy_ids,
+	.probe = sti_usb_phy_probe,
+	.ops = &sti_usb_phy_ops,
+	.priv_auto_alloc_size = sizeof(struct sti_usb_phy),
+};