From: Patrice Chotard <patrice.chot...@st.com> This is the generic phy driver for the picoPHY ports used by USB2 and USB3 Host controllers available on STiH407 SoC families.
Signed-off-by: Patrice Chotard <patrice.chot...@st.com> --- v2: replace bitfield_replace() by clrsetbits_le32() configs/stih410-b2260_defconfig | 1 + drivers/usb/Kconfig | 4 ++ drivers/usb/phy/Kconfig | 11 +++ drivers/usb/phy/Makefile | 1 + drivers/usb/phy/sti_phy_usb.c | 153 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 170 insertions(+) create mode 100644 drivers/usb/phy/Kconfig create mode 100644 drivers/usb/phy/sti_phy_usb.c diff --git a/configs/stih410-b2260_defconfig b/configs/stih410-b2260_defconfig index 4e6942f..d3cfdca 100644 --- a/configs/stih410-b2260_defconfig +++ b/configs/stih410-b2260_defconfig @@ -17,6 +17,7 @@ CONFIG_CMD_FS_GENERIC=y CONFIG_OF_CONTROL=y CONFIG_REGMAP=y CONFIG_SYSCON=y +CONFIG_MISC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_STI=y CONFIG_PINCTRL=y diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index da3ec2f..e30c9d6 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -94,4 +94,8 @@ endif source "drivers/usb/gadget/Kconfig" +comment "USB PHY" + +source "drivers/usb/phy/Kconfig" + endif diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig new file mode 100644 index 0000000..1a86c6e --- /dev/null +++ b/drivers/usb/phy/Kconfig @@ -0,0 +1,11 @@ +menu "USB PHY drivers" + +config STI_PHY_USB + bool "STMicroelectronics USB2 picoPHY driver for STiH407 family" + default n + 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/usb/phy/Makefile b/drivers/usb/phy/Makefile index 4e548c2..b50fb5a 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_TWL4030_USB) += twl4030.o obj-$(CONFIG_OMAP_USB_PHY) += omap_usb_phy.o obj-$(CONFIG_ROCKCHIP_USB2_PHY) += rockchip_usb2_phy.o +obj-$(CONFIG_STI_PHY_USB) += sti_phy_usb.o diff --git a/drivers/usb/phy/sti_phy_usb.c b/drivers/usb/phy/sti_phy_usb.c new file mode 100644 index 0000000..59b0b47 --- /dev/null +++ b/drivers/usb/phy/sti_phy_usb.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2017 + * Patrice Chotard <patrice.chot...@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 <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_phy_usb { + struct regmap *regmap; + struct reset_ctl global_ctl; + struct reset_ctl port_ctl; + int param; + int ctrl; +}; + +static int sti_phy_usb_deassert(struct sti_phy_usb *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 void sti_phy_usb_init(struct sti_phy_usb *phy) +{ + 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); +} + +int sti_phy_usb_probe(struct udevice *dev) +{ + struct sti_phy_usb *priv = dev_get_priv(dev); + struct udevice *syscon; + struct fdtdec_phandle_args syscfg_phandle; + u32 cells[PHYPARAM_NB]; + int ret, count; + + /* get corresponding syscon phandle */ + ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset, + "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_of_offset(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, + "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; + } + + sti_phy_usb_init(priv); + + return sti_phy_usb_deassert(priv); +} + +static const struct udevice_id sti_phy_usb_ids[] = { + { .compatible = "st,stih407-usb2-phy" }, + { } +}; + +U_BOOT_DRIVER(sti_phy_usb) = { + .name = "sti_phy_usb", + .id = UCLASS_MISC, + .of_match = sti_phy_usb_ids, + .probe = sti_phy_usb_probe, + .priv_auto_alloc_size = sizeof(struct sti_phy_usb), +}; -- 1.9.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot