From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ziyuan Xu Date: Thu, 14 Jul 2016 14:52:32 +0800 Subject: [U-Boot] [PATCH v4 1/4] usb: rockchip-phy: implement USB2.0 phy control In-Reply-To: <1468479155-1796-1-git-send-email-xzy.xu@rock-chips.com> References: <1468479155-1796-1-git-send-email-xzy.xu@rock-chips.com> Message-ID: <1468479155-1796-2-git-send-email-xzy.xu@rock-chips.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de From: Xu Ziyuan So far, Rockchip SoCs have two kinds of USB2.0 phy, such as Synopsys and Innosilicon. This patch applys dwc2 usb driver framework to implement phy_init() and phy_off() methods for Synopsys phy on Rockchip platform. Signed-off-by: Ziyuan Xu --- Changes in v4: - Implement a mechanism to be compatible with more Rockchip SoCs - Rename rockchip_usb_syno_phy.c to rockchip_usb2_phy.c Changes in v3: - Make UOC_CON registers to be unfixed which should be got from DT Changes in v2: - Rename rk3288_usb_phy.c to rockchip_usb_syno_phy.c - Rework the behaviour in otg_phy_init() and otg_phy_off() drivers/usb/phy/Makefile | 1 + drivers/usb/phy/rockchip_usb2_phy.c | 107 ++++++++++++++++++++++++++++++++++++ include/usb/dwc2_udc.h | 2 + 3 files changed, 110 insertions(+) create mode 100644 drivers/usb/phy/rockchip_usb2_phy.c diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 93d147e..4e548c2 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -7,3 +7,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 diff --git a/drivers/usb/phy/rockchip_usb2_phy.c b/drivers/usb/phy/rockchip_usb2_phy.c new file mode 100644 index 0000000..1958478 --- /dev/null +++ b/drivers/usb/phy/rockchip_usb2_phy.c @@ -0,0 +1,107 @@ +/* + * Copyright 2016 Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#include "../gadget/dwc2_udc_otg_priv.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define BIT_WRITEABLE_SHIFT 16 + +struct usb2phy_reg { + unsigned int offset; + unsigned int bitend; + unsigned int bitstart; + unsigned int disable; + unsigned int enable; +}; + +/** + * struct rockchip_usb2_phy_cfg: usb-phy port configuration + * @port_reset: usb otg per-port reset register + * @soft_con: software control usb otg register + * @suspend: phy suspend register + */ +struct rockchip_usb2_phy_cfg { + struct usb2phy_reg port_reset; + struct usb2phy_reg soft_con; + struct usb2phy_reg suspend; +}; + +struct rockchip_usb2_phy_dt_id { + char compatible[128]; + const void *data; +}; + +static const struct rockchip_usb2_phy_cfg rk3288_pdata = { + .port_reset = {0x00, 12, 12, 0, 1}, + .soft_con = {0x08, 2, 2, 0, 1}, + .suspend = {0x0c, 5, 0, 0x01, 0x2A}, +}; + +static struct rockchip_usb2_phy_dt_id rockchip_usb2_phy_dt_ids[] = { + { .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata }, + {} +}; + +static void property_enable(struct dwc2_plat_otg_data *pdata, + const struct usb2phy_reg *reg, bool en) +{ + unsigned int val, mask, tmp; + + tmp = en ? reg->enable : reg->disable; + mask = GENMASK(reg->bitend, reg->bitstart); + val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); + + writel(val, pdata->regs_phy + reg->offset); +} + + +void otg_phy_init(struct dwc2_udc *dev) +{ + struct dwc2_plat_otg_data *pdata = dev->pdata; + struct rockchip_usb2_phy_cfg *phy_cfg = NULL; + struct rockchip_usb2_phy_dt_id *of_id; + int i; + + for (i = 0; i < ARRAY_SIZE(rockchip_usb2_phy_dt_ids); i++) { + of_id = &rockchip_usb2_phy_dt_ids[i]; + if (fdt_node_check_compatible(gd->fdt_blob, pdata->phy_of_node, + of_id->compatible) == 0) { + phy_cfg = (struct rockchip_usb2_phy_cfg *)of_id->data; + break; + } + } + if (!phy_cfg) { + debug("Can't find device platform data\n"); + + hang(); + return; + } + pdata->priv = phy_cfg; + /* disable software control */ + property_enable(pdata, &phy_cfg->soft_con, false); + + /* reset otg port */ + property_enable(pdata, &phy_cfg->port_reset, true); + mdelay(1); + property_enable(pdata, &phy_cfg->port_reset, false); + udelay(1); +} + +void otg_phy_off(struct dwc2_udc *dev) +{ + struct dwc2_plat_otg_data *pdata = dev->pdata; + struct rockchip_usb2_phy_cfg *phy_cfg = pdata->priv; + + /* enable software control */ + property_enable(pdata, &phy_cfg->soft_con, true); + /* enter suspend */ + property_enable(pdata, &phy_cfg->suspend, true); +} diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h index 302e9a3..3ce43f8 100644 --- a/include/usb/dwc2_udc.h +++ b/include/usb/dwc2_udc.h @@ -12,6 +12,8 @@ #define PHY0_SLEEP (1 << 5) struct dwc2_plat_otg_data { + void *priv; + int phy_of_node; int (*phy_control)(int on); unsigned int regs_phy; unsigned int regs_otg; -- 1.9.1