Hi, On Friday 06 July 2018 09:08 PM, Icenowy Zheng wrote: > Allwinner H6 SoC contains a USB3 PHY (with USB2 DP/DM lines also > controlled). > > Add a driver for it. > > The register operations in this driver is mainly extracted from the BSP > USB3 driver. > > Signed-off-by: Icenowy Zheng <icen...@aosc.io> > --- > Changes in v2: > - Splitted out the DT binding. > > drivers/phy/allwinner/Kconfig | 13 ++ > drivers/phy/allwinner/Makefile | 1 + > drivers/phy/allwinner/phy-sun50i-usb3.c | 194 ++++++++++++++++++++++++ > 3 files changed, 208 insertions(+) > create mode 100644 drivers/phy/allwinner/phy-sun50i-usb3.c > > diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig > index cdc1e745ba47..cf373bcee034 100644 > --- a/drivers/phy/allwinner/Kconfig > +++ b/drivers/phy/allwinner/Kconfig > @@ -29,3 +29,16 @@ config PHY_SUN9I_USB > sun9i SoCs. > > This driver controls each individual USB 2 host PHY. > + > +config PHY_SUN50I_USB3 > + tristate "Allwinner sun50i SoC USB3 PHY driver" > + depends on ARCH_SUNXI && HAS_IOMEM && OF > + depends on RESET_CONTROLLER > + depends on USB_SUPPORT > + select USB_COMMON
Doesn't look like this driver depends on USB_SUPPORT. > + select GENERIC_PHY > + help > + Enable this to support the USB3.0-capable transceiver that is > + part of some Allwinner sun50i SoCs. > + > + This driver controls each individual USB 2+3 host PHY combo. > diff --git a/drivers/phy/allwinner/Makefile b/drivers/phy/allwinner/Makefile > index 8605529c01a1..a8d01e9073c2 100644 > --- a/drivers/phy/allwinner/Makefile > +++ b/drivers/phy/allwinner/Makefile > @@ -1,2 +1,3 @@ > obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o > obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o > +obj-$(CONFIG_PHY_SUN50I_USB3) += phy-sun50i-usb3.o > diff --git a/drivers/phy/allwinner/phy-sun50i-usb3.c > b/drivers/phy/allwinner/phy-sun50i-usb3.c > new file mode 100644 > index 000000000000..226c99c2d664 > --- /dev/null > +++ b/drivers/phy/allwinner/phy-sun50i-usb3.c > @@ -0,0 +1,194 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Allwinner sun50i(H6) USB 3.0 phy driver > + * > + * Copyright (C) 2017 Icenowy Zheng <icen...@aosc.io> > + * > + * Based on phy-sun9i-usb.c, which is: > + * > + * Copyright (C) 2014-2015 Chen-Yu Tsai <w...@csie.org> > + * > + * Based on code from Allwinner BSP, which is: > + * > + * Copyright (c) 2010-2015 Allwinner Technology Co., Ltd. Does the BSP also use GPL license? > + */ > + > +#include <linux/clk.h> > +#include <linux/err.h> > +#include <linux/io.h> > +#include <linux/module.h> > +#include <linux/phy/phy.h> > +#include <linux/usb/of.h> > +#include <linux/platform_device.h> > +#include <linux/reset.h> > + > +/* Interface Status and Control Registers */ > +#define SUNXI_ISCR 0x00 > +#define SUNXI_PIPE_CLOCK_CONTROL 0x14 > +#define SUNXI_PHY_TUNE_LOW 0x18 > +#define SUNXI_PHY_TUNE_HIGH 0x1c > +#define SUNXI_PHY_EXTERNAL_CONTROL 0x20 > + > +/* USB2.0 Interface Status and Control Register */ > +#define SUNXI_ISCR_FORCE_VBUS (3 << 12) > + > +/* PIPE Clock Control Register */ > +#define SUNXI_PCC_PIPE_CLK_OPEN (1 << 6) > + > +/* PHY External Control Register */ > +#define SUNXI_PEC_EXTERN_VBUS (3 << 1) > +#define SUNXI_PEC_SSC_EN (1 << 24) > +#define SUNXI_PEC_REF_SSP_EN (1 << 26) > + > +/* PHY Tune High Register */ > +#define SUNXI_TX_DEEMPH_3P5DB(n) ((n) << 19) > +#define SUNXI_TX_DEEMPH_3P5DB_MASK GENMASK(24, 19) > +#define SUNXI_TX_DEEMPH_6DB(n) ((n) << 13) > +#define SUNXI_TX_DEEMPH_6GB_MASK GENMASK(18, 13) > +#define SUNXI_TX_SWING_FULL(n) ((n) << 6) > +#define SUNXI_TX_SWING_FULL_MASK GENMASK(12, 6) > +#define SUNXI_LOS_BIAS(n) ((n) << 3) > +#define SUNXI_LOS_BIAS_MASK GENMASK(5, 3) > +#define SUNXI_TXVBOOSTLVL(n) ((n) << 0) > +#define SUNXI_TXVBOOSTLVL_MASK GENMASK(0, 2) > + > +struct sun50i_usb3_phy { > + struct phy *phy; > + void __iomem *regs; > + struct reset_control *reset; > + struct clk *clk; > +}; > + > +static void sun50i_usb3_phy_open(struct sun50i_usb3_phy *phy) > +{ > + u32 val; > + > + val = readl(phy->regs + SUNXI_PHY_EXTERNAL_CONTROL); > + val |= SUNXI_PEC_EXTERN_VBUS; > + val |= SUNXI_PEC_SSC_EN | SUNXI_PEC_REF_SSP_EN; > + writel(val, phy->regs + SUNXI_PHY_EXTERNAL_CONTROL); > + > + val = readl(phy->regs + SUNXI_PIPE_CLOCK_CONTROL); > + val |= SUNXI_PCC_PIPE_CLK_OPEN; > + writel(val, phy->regs + SUNXI_PIPE_CLOCK_CONTROL); > + > + val = readl(phy->regs + SUNXI_ISCR); > + val |= SUNXI_ISCR_FORCE_VBUS; > + writel(val, phy->regs + SUNXI_ISCR); > + > + /* > + * All the magic numbers written to the PHY_TUNE_{LOW_HIGH} > + * registers are directly taken from the BSP USB3 driver from > + * Allwiner. %s/Allwiner/Allwinner/ > + */ > + writel(0x0047fc87, phy->regs + SUNXI_PHY_TUNE_LOW); PHY_TUNE_LOW should also configure individual parameters like how you've done below for PHY_TUNE_HIGH. Thanks Kishon