From patchwork Mon Oct 28 18:22:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Geis X-Patchwork-Id: 11216247 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3E55A913 for ; Mon, 28 Oct 2019 18:23:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F3F1C21744 for ; Mon, 28 Oct 2019 18:23:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="aviC50bM" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2403770AbfJ1SXR (ORCPT ); Mon, 28 Oct 2019 14:23:17 -0400 Received: from mail-qt1-f196.google.com ([209.85.160.196]:40440 "EHLO mail-qt1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730690AbfJ1SXR (ORCPT ); Mon, 28 Oct 2019 14:23:17 -0400 Received: by mail-qt1-f196.google.com with SMTP id o49so15970261qta.7 for ; Mon, 28 Oct 2019 11:23:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=LruG9I7RQGDnfHPGd3HHjQJ5RwQh96UvhFS64oUHIgM=; b=aviC50bMjttD7hV/bK/TFY4uPZWk5KMpJvt88i2DNVp5mhRJfBu/hFYA+0X2g8VnHB h9iBrtySIDvUp/vmkuQT8DKDCsgHEUqmaDouGlOXkkcDS8d/0nLPXunXOzKzYUOkZOdJ B3Cw3WY9jLpI3s6sPKg7zM9R9aQpH2Xzh5lta8x1HJWpLye/0rMBWm4PEX2qv6AqaKGj T4WHohjlOLnfJq0pb+TcztMzKuIKH315cgqJVLYX5OQHyAY90BdSf63O8UR5m2HiRTQ3 RyJEM8cGSV9PzOWeteaYKWOrMMJeXWiDq0zoLS+StZMqhHCrsoct1C65d4SEOqaqcDj1 xl7g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=LruG9I7RQGDnfHPGd3HHjQJ5RwQh96UvhFS64oUHIgM=; b=tNaQ/8F7XCogSlvAYaMMI7O0+UzEkJW0crOdprNEzW0gVXXueMfN+pOnGhst/6Ga7L wiCJnhO9nnvmTYdkZs7amrXNMQa7VzSZAapHHg3aeG3K4gmZi70+ySWpQ+nImIrMs57K 7fm5bBU3JPiH3r0C9KDWFMc0NWuyCD+TH2T9la930YeRuS4KscsybA/UKW4g2ppgm6DH nwSV97ERQqsCgbEn//oFK2DVAazEGOvK+8+ImowzWKbO4LzVNbSx1LwS5JOr7Ak5MyCQ g4PcEQrBg009AcgGmptBsMMvRyaasEzBnluXxwCF6EPS63JHtm2UrPldg6PRuFWgYZFZ 7W3Q== X-Gm-Message-State: APjAAAVzdbye5Qc9t02J0Cmri4zf3wc4eLM2vfex/XgjUhzl84U7aznc nN84cUyvrVKhu3mTVa0UXEY= X-Google-Smtp-Source: APXvYqxei8KKg8AYUmMVzH5tl4R+bMGYgRoNs5rvZcpeh7ny5d9QXACvk8VGxD9E0+73+51RH1b+PQ== X-Received: by 2002:aed:3702:: with SMTP id i2mr17819316qtb.312.1572286994613; Mon, 28 Oct 2019 11:23:14 -0700 (PDT) Received: from firefly.sparksnet ([2601:153:900:a52:6f12:874c:d2b2:a9d0]) by smtp.gmail.com with ESMTPSA id x9sm5808631qkl.75.2019.10.28.11.23.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Oct 2019 11:23:12 -0700 (PDT) From: Peter Geis To: heiko@sntech.de Cc: linux-rockchip@lists.infradead.org, linux-usb@vger.kernel.org, katsuhiro@katsuster.net, robin.murphy@arm.com, Peter Geis Subject: [PATCH 1/5] phy: rockchip: add inno-usb3 phy driver Date: Mon, 28 Oct 2019 18:22:50 +0000 Message-Id: <20191028182254.30739-2-pgwipeout@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191028182254.30739-1-pgwipeout@gmail.com> References: <20191028182254.30739-1-pgwipeout@gmail.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Add the rockchip innosilicon usb3 phy driver, supporting devices such as the rk3328. Pulled from: https://github.com/FireflyTeam/kernel/blob/roc-rk3328-cc/drivers/phy/rockchip/phy-rockchip-inno-usb3.c Signed-off-by: Peter Geis --- drivers/phy/rockchip/Kconfig | 9 + drivers/phy/rockchip/Makefile | 1 + drivers/phy/rockchip/phy-rockchip-inno-usb3.c | 1107 +++++++++++++++++ 3 files changed, 1117 insertions(+) create mode 100644 drivers/phy/rockchip/phy-rockchip-inno-usb3.c diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig index c454c90cd99e..766407939d4a 100644 --- a/drivers/phy/rockchip/Kconfig +++ b/drivers/phy/rockchip/Kconfig @@ -35,6 +35,15 @@ config PHY_ROCKCHIP_INNO_USB2 help Support for Rockchip USB2.0 PHY with Innosilicon IP block. +config PHY_ROCKCHIP_INNO_USB3 + tristate "Rockchip INNO USB 3.0 PHY Driver" + depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF + depends on USB_SUPPORT + select GENERIC_PHY + select USB_PHY + help + Support for Rockchip USB 3.0 PHY with Innosilicon IP block. + config PHY_ROCKCHIP_PCIE tristate "Rockchip PCIe PHY Driver" depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile index fd21cbaf40dd..d7b3d16c19ae 100644 --- a/drivers/phy/rockchip/Makefile +++ b/drivers/phy/rockchip/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o +obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB3) += phy-rockchip-inno-usb3.o obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb3.c b/drivers/phy/rockchip/phy-rockchip-inno-usb3.c new file mode 100644 index 000000000000..31fee8f3a705 --- /dev/null +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb3.c @@ -0,0 +1,1107 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Rockchip USB 3.0 PHY with Innosilicon IP block driver + * + * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define U3PHY_PORT_NUM 2 +#define BIT_WRITEABLE_SHIFT 16 +#define SCHEDULE_DELAY (60 * HZ) + +#define U3PHY_APB_RST BIT(0) +#define U3PHY_POR_RST BIT(1) +#define U3PHY_MAC_RST BIT(2) + +struct rockchip_u3phy; +struct rockchip_u3phy_port; + +enum rockchip_u3phy_type { + U3PHY_TYPE_PIPE, + U3PHY_TYPE_UTMI, +}; + +enum rockchip_u3phy_pipe_pwr { + PIPE_PWR_P0 = 0, + PIPE_PWR_P1 = 1, + PIPE_PWR_P2 = 2, + PIPE_PWR_P3 = 3, + PIPE_PWR_MAX = 4, +}; + +enum rockchip_u3phy_rest_req { + U3_POR_RSTN = 0, + U2_POR_RSTN = 1, + PIPE_MAC_RSTN = 2, + UTMI_MAC_RSTN = 3, + PIPE_APB_RSTN = 4, + UTMI_APB_RSTN = 5, + U3PHY_RESET_MAX = 6, +}; + +enum rockchip_u3phy_utmi_state { + PHY_UTMI_HS_ONLINE = 0, + PHY_UTMI_DISCONNECT = 1, + PHY_UTMI_CONNECT = 2, + PHY_UTMI_FS_LS_ONLINE = 4, +}; + +/* + * @rvalue: reset value + * @dvalue: desired value + */ +struct u3phy_reg { + unsigned int offset; + unsigned int bitend; + unsigned int bitstart; + unsigned int rvalue; + unsigned int dvalue; +}; + +struct rockchip_u3phy_grfcfg { + struct u3phy_reg um_suspend; + struct u3phy_reg ls_det_en; + struct u3phy_reg ls_det_st; + struct u3phy_reg um_ls; + struct u3phy_reg um_hstdct; + struct u3phy_reg u2_only_ctrl; + struct u3phy_reg u3_disable; + struct u3phy_reg pp_pwr_st; + struct u3phy_reg pp_pwr_en[PIPE_PWR_MAX]; +}; + +/** + * struct rockchip_u3phy_apbcfg: usb3-phy apb configuration. + * @u2_pre_emp: usb2-phy pre-emphasis tuning. + * @u2_pre_emp_sth: usb2-phy pre-emphasis strength tuning. + * @u2_odt_tuning: usb2-phy odt 45ohm tuning. + */ +struct rockchip_u3phy_apbcfg { + unsigned int u2_pre_emp; + unsigned int u2_pre_emp_sth; + unsigned int u2_odt_tuning; +}; + +struct rockchip_u3phy_cfg { + unsigned int reg; + const struct rockchip_u3phy_grfcfg grfcfg; + + int (*phy_pipe_power)(struct rockchip_u3phy *u3phy, + struct rockchip_u3phy_port *u3phy_port, + bool on); + int (*phy_tuning)(struct rockchip_u3phy *u3phy, + struct rockchip_u3phy_port *u3phy_port, + struct device_node *child_np); +}; + +struct rockchip_u3phy_port { + struct phy *phy; + void __iomem *base; + unsigned int index; + unsigned char type; + bool suspended; + bool refclk_25m_quirk; + struct mutex mutex; /* mutex for updating register */ + struct delayed_work um_sm_work; +}; + +struct rockchip_u3phy { + struct device *dev; + struct regmap *u3phy_grf; + struct regmap *grf; + int um_ls_irq; + struct clk **clks; + int num_clocks; + struct dentry *root; + struct gpio_desc *vbus_drv_gpio; + struct reset_control *rsts[U3PHY_RESET_MAX]; + struct rockchip_u3phy_apbcfg apbcfg; + const struct rockchip_u3phy_cfg *cfgs; + struct rockchip_u3phy_port ports[U3PHY_PORT_NUM]; + struct usb_phy usb_phy; +}; + +static inline int param_write(void __iomem *base, + const struct u3phy_reg *reg, bool desired) +{ + unsigned int val, mask; + unsigned int tmp = desired ? reg->dvalue : reg->rvalue; + int ret = 0; + + mask = GENMASK(reg->bitend, reg->bitstart); + val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); + ret = regmap_write(base, reg->offset, val); + + return ret; +} + +static inline bool param_exped(void __iomem *base, + const struct u3phy_reg *reg, + unsigned int value) +{ + int ret; + unsigned int tmp, orig; + unsigned int mask = GENMASK(reg->bitend, reg->bitstart); + + ret = regmap_read(base, reg->offset, &orig); + if (ret) + return false; + + tmp = (orig & mask) >> reg->bitstart; + return tmp == value; +} + +static int rockchip_u3phy_usb2_only_show(struct seq_file *s, void *unused) +{ + struct rockchip_u3phy *u3phy = s->private; + + if (param_exped(u3phy->u3phy_grf, &u3phy->cfgs->grfcfg.u2_only_ctrl, 1)) + dev_info(u3phy->dev, "u2\n"); + else + dev_info(u3phy->dev, "u3\n"); + + return 0; +} + +static int rockchip_u3phy_usb2_only_open(struct inode *inode, + struct file *file) +{ + return single_open(file, rockchip_u3phy_usb2_only_show, + inode->i_private); +} + +static ssize_t rockchip_u3phy_usb2_only_write(struct file *file, + const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct seq_file *s = file->private_data; + struct rockchip_u3phy *u3phy = s->private; + struct rockchip_u3phy_port *u3phy_port; + char buf[32]; + u8 index; + + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + return -EFAULT; + + if (!strncmp(buf, "u3", 2) && + param_exped(u3phy->u3phy_grf, + &u3phy->cfgs->grfcfg.u2_only_ctrl, 1)) { + dev_info(u3phy->dev, "Set usb3.0 and usb2.0 mode successfully\n"); + + gpiod_set_value_cansleep(u3phy->vbus_drv_gpio, 0); + + param_write(u3phy->grf, + &u3phy->cfgs->grfcfg.u3_disable, false); + param_write(u3phy->u3phy_grf, + &u3phy->cfgs->grfcfg.u2_only_ctrl, false); + + for (index = 0; index < U3PHY_PORT_NUM; index++) { + u3phy_port = &u3phy->ports[index]; + /* enable u3 rx termimation */ + if (u3phy_port->type == U3PHY_TYPE_PIPE) + writel(0x30, u3phy_port->base + 0xd8); + } + + atomic_notifier_call_chain(&u3phy->usb_phy.notifier, 0, NULL); + + gpiod_set_value_cansleep(u3phy->vbus_drv_gpio, 1); + } else if (!strncmp(buf, "u2", 2) && + param_exped(u3phy->u3phy_grf, + &u3phy->cfgs->grfcfg.u2_only_ctrl, 0)) { + dev_info(u3phy->dev, "Set usb2.0 only mode successfully\n"); + + gpiod_set_value_cansleep(u3phy->vbus_drv_gpio, 0); + + param_write(u3phy->grf, + &u3phy->cfgs->grfcfg.u3_disable, true); + param_write(u3phy->u3phy_grf, + &u3phy->cfgs->grfcfg.u2_only_ctrl, true); + + for (index = 0; index < U3PHY_PORT_NUM; index++) { + u3phy_port = &u3phy->ports[index]; + /* disable u3 rx termimation */ + if (u3phy_port->type == U3PHY_TYPE_PIPE) + writel(0x20, u3phy_port->base + 0xd8); + } + + atomic_notifier_call_chain(&u3phy->usb_phy.notifier, 0, NULL); + + gpiod_set_value_cansleep(u3phy->vbus_drv_gpio, 1); + } else { + dev_info(u3phy->dev, "Same or illegal mode\n"); + } + + return count; +} + +static const struct file_operations rockchip_u3phy_usb2_only_fops = { + .open = rockchip_u3phy_usb2_only_open, + .write = rockchip_u3phy_usb2_only_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +int rockchip_u3phy_debugfs_init(struct rockchip_u3phy *u3phy) +{ + struct dentry *root; + struct dentry *file; + int ret; + + root = debugfs_create_dir(dev_name(u3phy->dev), NULL); + if (!root) { + ret = -ENOMEM; + goto err0; + } + + u3phy->root = root; + + file = debugfs_create_file("u3phy_mode", 0644, root, + u3phy, &rockchip_u3phy_usb2_only_fops); + if (!file) { + ret = -ENOMEM; + goto err1; + } + return 0; + +err1: + debugfs_remove_recursive(root); +err0: + return ret; +} + +static const char *get_rest_name(enum rockchip_u3phy_rest_req rst) +{ + switch (rst) { + case U2_POR_RSTN: + return "u3phy-u2-por"; + case U3_POR_RSTN: + return "u3phy-u3-por"; + case PIPE_MAC_RSTN: + return "u3phy-pipe-mac"; + case UTMI_MAC_RSTN: + return "u3phy-utmi-mac"; + case UTMI_APB_RSTN: + return "u3phy-utmi-apb"; + case PIPE_APB_RSTN: + return "u3phy-pipe-apb"; + default: + return "invalid"; + } +} + +static void rockchip_u3phy_rest_deassert(struct rockchip_u3phy *u3phy, + unsigned int flag) +{ + int rst; + + if (flag & U3PHY_APB_RST) { + dev_dbg(u3phy->dev, "deassert APB bus interface reset\n"); + for (rst = PIPE_APB_RSTN; rst <= UTMI_APB_RSTN; rst++) { + if (u3phy->rsts[rst]) + reset_control_deassert(u3phy->rsts[rst]); + } + } + + if (flag & U3PHY_POR_RST) { + usleep_range(12, 15); + dev_dbg(u3phy->dev, "deassert u2 and u3 phy power on reset\n"); + for (rst = U3_POR_RSTN; rst <= U2_POR_RSTN; rst++) { + if (u3phy->rsts[rst]) + reset_control_deassert(u3phy->rsts[rst]); + } + } + + if (flag & U3PHY_MAC_RST) { + usleep_range(1200, 1500); + dev_dbg(u3phy->dev, "deassert pipe and utmi MAC reset\n"); + for (rst = PIPE_MAC_RSTN; rst <= UTMI_MAC_RSTN; rst++) + if (u3phy->rsts[rst]) + reset_control_deassert(u3phy->rsts[rst]); + } +} + +static void rockchip_u3phy_rest_assert(struct rockchip_u3phy *u3phy) +{ + int rst; + + dev_dbg(u3phy->dev, "assert u3phy reset\n"); + for (rst = 0; rst < U3PHY_RESET_MAX; rst++) + if (u3phy->rsts[rst]) + reset_control_assert(u3phy->rsts[rst]); +} + +static int rockchip_u3phy_clk_enable(struct rockchip_u3phy *u3phy) +{ + int ret, clk; + + for (clk = 0; clk < u3phy->num_clocks && u3phy->clks[clk]; clk++) { + ret = clk_prepare_enable(u3phy->clks[clk]); + if (ret) + goto err_disable_clks; + } + return 0; + +err_disable_clks: + while (--clk >= 0) + clk_disable_unprepare(u3phy->clks[clk]); + return ret; +} + +static void rockchip_u3phy_clk_disable(struct rockchip_u3phy *u3phy) +{ + int clk; + + for (clk = u3phy->num_clocks - 1; clk >= 0; clk--) + if (u3phy->clks[clk]) + clk_disable_unprepare(u3phy->clks[clk]); +} + +static int rockchip_u3phy_init(struct phy *phy) +{ + return 0; +} + +static int rockchip_u3phy_exit(struct phy *phy) +{ + return 0; +} + +static int rockchip_u3phy_power_on(struct phy *phy) +{ + struct rockchip_u3phy_port *u3phy_port = phy_get_drvdata(phy); + struct rockchip_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); + int ret; + + dev_info(&u3phy_port->phy->dev, "u3phy %s power on\n", + (u3phy_port->type == U3PHY_TYPE_UTMI) ? "u2" : "u3"); + + if (!u3phy_port->suspended) + return 0; + + ret = rockchip_u3phy_clk_enable(u3phy); + if (ret) + return ret; + + if (u3phy_port->type == U3PHY_TYPE_UTMI) { + param_write(u3phy->u3phy_grf, + &u3phy->cfgs->grfcfg.um_suspend, false); + } else { + /* current in p2 ? */ + if (param_exped(u3phy->u3phy_grf, + &u3phy->cfgs->grfcfg.pp_pwr_st, PIPE_PWR_P2)) + goto done; + + if (u3phy->cfgs->phy_pipe_power) { + dev_dbg(u3phy->dev, "do pipe power up\n"); + u3phy->cfgs->phy_pipe_power(u3phy, u3phy_port, true); + } + + /* exit to p0 */ + param_write(u3phy->u3phy_grf, + &u3phy->cfgs->grfcfg.pp_pwr_en[PIPE_PWR_P0], true); + usleep_range(90, 100); + + /* enter to p2 from p0 */ + param_write(u3phy->u3phy_grf, + &u3phy->cfgs->grfcfg.pp_pwr_en[PIPE_PWR_P2], + false); + udelay(3); + } + +done: + u3phy_port->suspended = false; + return 0; +} + +static int rockchip_u3phy_power_off(struct phy *phy) +{ + struct rockchip_u3phy_port *u3phy_port = phy_get_drvdata(phy); + struct rockchip_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); + + dev_info(&u3phy_port->phy->dev, "u3phy %s power off\n", + (u3phy_port->type == U3PHY_TYPE_UTMI) ? "u2" : "u3"); + + if (u3phy_port->suspended) + return 0; + + if (u3phy_port->type == U3PHY_TYPE_UTMI) { + param_write(u3phy->u3phy_grf, + &u3phy->cfgs->grfcfg.um_suspend, true); + } else { + /* current in p3 ? */ + if (param_exped(u3phy->u3phy_grf, + &u3phy->cfgs->grfcfg.pp_pwr_st, PIPE_PWR_P3)) + goto done; + + /* exit to p0 */ + param_write(u3phy->u3phy_grf, + &u3phy->cfgs->grfcfg.pp_pwr_en[PIPE_PWR_P0], true); + udelay(2); + + /* enter to p3 from p0 */ + param_write(u3phy->u3phy_grf, + &u3phy->cfgs->grfcfg.pp_pwr_en[PIPE_PWR_P3], true); + udelay(6); + + if (u3phy->cfgs->phy_pipe_power) { + dev_dbg(u3phy->dev, "do pipe power down\n"); + u3phy->cfgs->phy_pipe_power(u3phy, u3phy_port, false); + } + } + +done: + rockchip_u3phy_clk_disable(u3phy); + u3phy_port->suspended = true; + return 0; +} + +static __maybe_unused +struct phy *rockchip_u3phy_xlate(struct device *dev, + struct of_phandle_args *args) +{ + struct rockchip_u3phy *u3phy = dev_get_drvdata(dev); + struct rockchip_u3phy_port *u3phy_port = NULL; + struct device_node *phy_np = args->np; + int index; + + if (args->args_count != 1) { + dev_err(dev, "invalid number of cells in 'phy' property\n"); + return ERR_PTR(-EINVAL); + } + + for (index = 0; index < U3PHY_PORT_NUM; index++) { + if (phy_np == u3phy->ports[index].phy->dev.of_node) { + u3phy_port = &u3phy->ports[index]; + break; + } + } + + if (!u3phy_port) { + dev_err(dev, "failed to find appropriate phy\n"); + return ERR_PTR(-EINVAL); + } + + return u3phy_port->phy; +} + +static struct phy_ops rockchip_u3phy_ops = { + .init = rockchip_u3phy_init, + .exit = rockchip_u3phy_exit, + .power_on = rockchip_u3phy_power_on, + .power_off = rockchip_u3phy_power_off, + .owner = THIS_MODULE, +}; + +/* + * The function manage host-phy port state and suspend/resume phy port + * to save power automatically. + * + * we rely on utmi_linestate and utmi_hostdisconnect to identify whether + * devices is disconnect or not. Besides, we do not need care it is FS/LS + * disconnected or HS disconnected, actually, we just only need get the + * device is disconnected at last through rearm the delayed work, + * to suspend the phy port in _PHY_STATE_DISCONNECT_ case. + */ +static void rockchip_u3phy_um_sm_work(struct work_struct *work) +{ + struct rockchip_u3phy_port *u3phy_port = + container_of(work, struct rockchip_u3phy_port, um_sm_work.work); + struct rockchip_u3phy *u3phy = + dev_get_drvdata(u3phy_port->phy->dev.parent); + unsigned int sh = u3phy->cfgs->grfcfg.um_hstdct.bitend - + u3phy->cfgs->grfcfg.um_hstdct.bitstart + 1; + unsigned int ul, uhd, state; + unsigned int ul_mask, uhd_mask; + int ret; + + mutex_lock(&u3phy_port->mutex); + + ret = regmap_read(u3phy->u3phy_grf, + u3phy->cfgs->grfcfg.um_ls.offset, &ul); + if (ret < 0) + goto next_schedule; + + ret = regmap_read(u3phy->u3phy_grf, + u3phy->cfgs->grfcfg.um_hstdct.offset, &uhd); + if (ret < 0) + goto next_schedule; + + uhd_mask = GENMASK(u3phy->cfgs->grfcfg.um_hstdct.bitend, + u3phy->cfgs->grfcfg.um_hstdct.bitstart); + ul_mask = GENMASK(u3phy->cfgs->grfcfg.um_ls.bitend, + u3phy->cfgs->grfcfg.um_ls.bitstart); + + /* stitch on um_ls and um_hstdct as phy state */ + state = ((uhd & uhd_mask) >> u3phy->cfgs->grfcfg.um_hstdct.bitstart) | + (((ul & ul_mask) >> u3phy->cfgs->grfcfg.um_ls.bitstart) << sh); + + switch (state) { + case PHY_UTMI_HS_ONLINE: + dev_dbg(&u3phy_port->phy->dev, "HS online\n"); + break; + case PHY_UTMI_FS_LS_ONLINE: + /* + * For FS/LS device, the online state share with connect state + * from um_ls and um_hstdct register, so we distinguish + * them via suspended flag. + * + * Plus, there are two cases, one is D- Line pull-up, and D+ + * line pull-down, the state is 4; another is D+ line pull-up, + * and D- line pull-down, the state is 2. + */ + if (!u3phy_port->suspended) { + /* D- line pull-up, D+ line pull-down */ + dev_dbg(&u3phy_port->phy->dev, "FS/LS online\n"); + break; + } + /* fall through */ + case PHY_UTMI_CONNECT: + if (u3phy_port->suspended) { + dev_dbg(&u3phy_port->phy->dev, "Connected\n"); + rockchip_u3phy_power_on(u3phy_port->phy); + u3phy_port->suspended = false; + } else { + /* D+ line pull-up, D- line pull-down */ + dev_dbg(&u3phy_port->phy->dev, "FS/LS online\n"); + } + break; + case PHY_UTMI_DISCONNECT: + if (!u3phy_port->suspended) { + dev_dbg(&u3phy_port->phy->dev, "Disconnected\n"); + rockchip_u3phy_power_off(u3phy_port->phy); + u3phy_port->suspended = true; + } + + /* + * activate the linestate detection to get the next device + * plug-in irq. + */ + param_write(u3phy->u3phy_grf, + &u3phy->cfgs->grfcfg.ls_det_st, true); + param_write(u3phy->u3phy_grf, + &u3phy->cfgs->grfcfg.ls_det_en, true); + + /* + * we don't need to rearm the delayed work when the phy port + * is suspended. + */ + mutex_unlock(&u3phy_port->mutex); + return; + default: + dev_dbg(&u3phy_port->phy->dev, "unknown phy state\n"); + break; + } + +next_schedule: + mutex_unlock(&u3phy_port->mutex); + schedule_delayed_work(&u3phy_port->um_sm_work, SCHEDULE_DELAY); +} + +static irqreturn_t rockchip_u3phy_um_ls_irq(int irq, void *data) +{ + struct rockchip_u3phy_port *u3phy_port = data; + struct rockchip_u3phy *u3phy = + dev_get_drvdata(u3phy_port->phy->dev.parent); + + if (!param_exped(u3phy->u3phy_grf, + &u3phy->cfgs->grfcfg.ls_det_st, + u3phy->cfgs->grfcfg.ls_det_st.dvalue)) + return IRQ_NONE; + + dev_dbg(u3phy->dev, "utmi linestate interrupt\n"); + mutex_lock(&u3phy_port->mutex); + + /* disable linestate detect irq and clear its status */ + param_write(u3phy->u3phy_grf, &u3phy->cfgs->grfcfg.ls_det_en, false); + param_write(u3phy->u3phy_grf, &u3phy->cfgs->grfcfg.ls_det_st, true); + + mutex_unlock(&u3phy_port->mutex); + + /* + * In this case for host phy, a new device is plugged in, meanwhile, + * if the phy port is suspended, we need rearm the work to resume it + * and mange its states; otherwise, we just return irq handled. + */ + if (u3phy_port->suspended) { + dev_dbg(u3phy->dev, "schedule utmi sm work\n"); + rockchip_u3phy_um_sm_work(&u3phy_port->um_sm_work.work); + } + + return IRQ_HANDLED; +} + +static int rockchip_u3phy_parse_dt(struct rockchip_u3phy *u3phy, + struct platform_device *pdev) + +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + int ret, i, clk; + + u3phy->um_ls_irq = platform_get_irq_byname(pdev, "linestate"); + if (u3phy->um_ls_irq < 0) { + dev_err(dev, "get utmi linestate irq failed\n"); + return -ENXIO; + } + + u3phy->vbus_drv_gpio = devm_gpiod_get_optional(dev, "vbus-drv", + GPIOD_OUT_HIGH); + + if (!u3phy->vbus_drv_gpio) { + dev_warn(&pdev->dev, "vbus_drv is not assigned\n"); + } else if (IS_ERR(u3phy->vbus_drv_gpio)) { + dev_err(&pdev->dev, "failed to get vbus_drv\n"); + return PTR_ERR(u3phy->vbus_drv_gpio); + } + + u3phy->num_clocks = of_clk_get_parent_count(np); + if (u3phy->num_clocks == 0) + dev_warn(&pdev->dev, "no clks found in dt\n"); + + u3phy->clks = devm_kcalloc(dev, u3phy->num_clocks, + sizeof(struct clk *), GFP_KERNEL); + + for (clk = 0; clk < u3phy->num_clocks; clk++) { + u3phy->clks[clk] = of_clk_get(np, clk); + if (IS_ERR(u3phy->clks[clk])) { + ret = PTR_ERR(u3phy->clks[clk]); + if (ret == -EPROBE_DEFER) + goto err_put_clks; + dev_err(&pdev->dev, "failed to get clks, %i\n", + ret); + u3phy->clks[clk] = NULL; + break; + } + } + + for (i = 0; i < U3PHY_RESET_MAX; i++) { + u3phy->rsts[i] = devm_reset_control_get(dev, get_rest_name(i)); + if (IS_ERR(u3phy->rsts[i])) { + dev_info(dev, "no %s reset control specified\n", + get_rest_name(i)); + u3phy->rsts[i] = NULL; + } + } + + return 0; + +err_put_clks: + while (--clk >= 0) + clk_put(u3phy->clks[clk]); + return ret; +} + +static int rockchip_u3phy_port_init(struct rockchip_u3phy *u3phy, + struct rockchip_u3phy_port *u3phy_port, + struct device_node *child_np) +{ + struct resource res; + struct phy *phy; + int ret; + + dev_dbg(u3phy->dev, "u3phy port initialize\n"); + + mutex_init(&u3phy_port->mutex); + u3phy_port->suspended = true; /* initial status */ + + phy = devm_phy_create(u3phy->dev, child_np, &rockchip_u3phy_ops); + if (IS_ERR(phy)) { + dev_err(u3phy->dev, "failed to create phy\n"); + return PTR_ERR(phy); + } + + u3phy_port->phy = phy; + + ret = of_address_to_resource(child_np, 0, &res); + if (ret) { + dev_err(u3phy->dev, "failed to get address resource(np-%s)\n", + child_np->name); + return ret; + } + + u3phy_port->base = devm_ioremap_resource(&u3phy_port->phy->dev, &res); + if (IS_ERR(u3phy_port->base)) { + dev_err(u3phy->dev, "failed to remap phy regs\n"); + return PTR_ERR(u3phy_port->base); + } + + if (!of_node_cmp(child_np->name, "pipe")) { + u3phy_port->type = U3PHY_TYPE_PIPE; + u3phy_port->refclk_25m_quirk = + of_property_read_bool(child_np, + "rockchip,refclk-25m-quirk"); + } else { + u3phy_port->type = U3PHY_TYPE_UTMI; + INIT_DELAYED_WORK(&u3phy_port->um_sm_work, + rockchip_u3phy_um_sm_work); + + ret = devm_request_threaded_irq(u3phy->dev, u3phy->um_ls_irq, + NULL, rockchip_u3phy_um_ls_irq, + IRQF_ONESHOT, "rockchip_u3phy", + u3phy_port); + if (ret) { + dev_err(u3phy->dev, "failed to request utmi linestate irq handle\n"); + return ret; + } + } + + if (u3phy->cfgs->phy_tuning) { + dev_dbg(u3phy->dev, "do u3phy tuning\n"); + ret = u3phy->cfgs->phy_tuning(u3phy, u3phy_port, child_np); + if (ret) + return ret; + } + + phy_set_drvdata(u3phy_port->phy, u3phy_port); + return 0; +} + +static int rockchip_u3phy_on_init(struct usb_phy *usb_phy) +{ + struct rockchip_u3phy *u3phy = + container_of(usb_phy, struct rockchip_u3phy, usb_phy); + + rockchip_u3phy_rest_deassert(u3phy, U3PHY_POR_RST | U3PHY_MAC_RST); + return 0; +} + +static void rockchip_u3phy_on_shutdown(struct usb_phy *usb_phy) +{ + struct rockchip_u3phy *u3phy = + container_of(usb_phy, struct rockchip_u3phy, usb_phy); + int rst; + + for (rst = 0; rst < U3PHY_RESET_MAX; rst++) + if (u3phy->rsts[rst] && rst != UTMI_APB_RSTN && + rst != PIPE_APB_RSTN) + reset_control_assert(u3phy->rsts[rst]); + udelay(1); +} + +static int rockchip_u3phy_on_disconnect(struct usb_phy *usb_phy, + enum usb_device_speed speed) +{ + struct rockchip_u3phy *u3phy = + container_of(usb_phy, struct rockchip_u3phy, usb_phy); + + dev_info(u3phy->dev, "%s device has disconnected\n", + (speed == USB_SPEED_SUPER) ? "U3" : "UW/U2/U1.1/U1"); + + if (speed == USB_SPEED_SUPER) + atomic_notifier_call_chain(&usb_phy->notifier, 0, NULL); + + return 0; +} + +static int rockchip_u3phy_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *child_np; + struct phy_provider *provider; + struct rockchip_u3phy *u3phy; + const struct rockchip_u3phy_cfg *phy_cfgs; + const struct of_device_id *match; + unsigned int reg[2]; + int index, ret; + + match = of_match_device(dev->driver->of_match_table, dev); + if (!match || !match->data) { + dev_err(dev, "phy-cfgs are not assigned!\n"); + return -EINVAL; + } + + u3phy = devm_kzalloc(dev, sizeof(*u3phy), GFP_KERNEL); + if (!u3phy) + return -ENOMEM; + + u3phy->u3phy_grf = + syscon_regmap_lookup_by_phandle(np, "rockchip,u3phygrf"); + if (IS_ERR(u3phy->u3phy_grf)) + return PTR_ERR(u3phy->u3phy_grf); + + u3phy->grf = + syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); + if (IS_ERR(u3phy->grf)) { + dev_err(dev, "Missing rockchip,grf property\n"); + return PTR_ERR(u3phy->grf); + } + + if (of_property_read_u32_array(np, "reg", reg, 2)) { + dev_err(dev, "the reg property is not assigned in %s node\n", + np->name); + return -EINVAL; + } + + u3phy->dev = dev; + phy_cfgs = match->data; + platform_set_drvdata(pdev, u3phy); + + /* find out a proper config which can be matched with dt. */ + index = 0; + while (phy_cfgs[index].reg) { + if (phy_cfgs[index].reg == reg[1]) { + u3phy->cfgs = &phy_cfgs[index]; + break; + } + + ++index; + } + + if (!u3phy->cfgs) { + dev_err(dev, "no phy-cfgs can be matched with %s node\n", + np->name); + return -EINVAL; + } + + ret = rockchip_u3phy_parse_dt(u3phy, pdev); + if (ret) { + dev_err(dev, "parse dt failed, ret(%d)\n", ret); + return ret; + } + + ret = rockchip_u3phy_clk_enable(u3phy); + if (ret) { + dev_err(dev, "clk enable failed, ret(%d)\n", ret); + return ret; + } + + rockchip_u3phy_rest_assert(u3phy); + rockchip_u3phy_rest_deassert(u3phy, U3PHY_APB_RST | U3PHY_POR_RST); + + index = 0; + for_each_available_child_of_node(np, child_np) { + struct rockchip_u3phy_port *u3phy_port = &u3phy->ports[index]; + + u3phy_port->index = index; + ret = rockchip_u3phy_port_init(u3phy, u3phy_port, child_np); + if (ret) { + dev_err(dev, "u3phy port init failed,ret(%d)\n", ret); + goto put_child; + } + + /* to prevent out of boundary */ + if (++index >= U3PHY_PORT_NUM) + break; + } + + provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR_OR_NULL(provider)) + goto put_child; + + rockchip_u3phy_rest_deassert(u3phy, U3PHY_MAC_RST); + rockchip_u3phy_clk_disable(u3phy); + + u3phy->usb_phy.dev = dev; + u3phy->usb_phy.init = rockchip_u3phy_on_init; + u3phy->usb_phy.shutdown = rockchip_u3phy_on_shutdown; + u3phy->usb_phy.notify_disconnect = rockchip_u3phy_on_disconnect; + usb_add_phy(&u3phy->usb_phy, USB_PHY_TYPE_USB3); + ATOMIC_INIT_NOTIFIER_HEAD(&u3phy->usb_phy.notifier); + + rockchip_u3phy_debugfs_init(u3phy); + + dev_info(dev, "Rockchip u3phy initialized successfully\n"); + return 0; + +put_child: + of_node_put(child_np); + return ret; +} + +static int rk3328_u3phy_pipe_power(struct rockchip_u3phy *u3phy, + struct rockchip_u3phy_port *u3phy_port, + bool on) +{ + unsigned int reg; + + if (on) { + reg = readl(u3phy_port->base + 0x1a8); + reg &= ~BIT(4); /* ldo power up */ + writel(reg, u3phy_port->base + 0x1a8); + + reg = readl(u3phy_port->base + 0x044); + reg &= ~BIT(4); /* bg power on */ + writel(reg, u3phy_port->base + 0x044); + + reg = readl(u3phy_port->base + 0x150); + reg |= BIT(6); /* tx bias enable */ + writel(reg, u3phy_port->base + 0x150); + + reg = readl(u3phy_port->base + 0x080); + reg &= ~BIT(2); /* tx cm power up */ + writel(reg, u3phy_port->base + 0x080); + + reg = readl(u3phy_port->base + 0x0c0); + /* tx obs enable and rx cm enable */ + reg |= (BIT(3) | BIT(4)); + writel(reg, u3phy_port->base + 0x0c0); + + udelay(1); + } else { + reg = readl(u3phy_port->base + 0x1a8); + reg |= BIT(4); /* ldo power down */ + writel(reg, u3phy_port->base + 0x1a8); + + reg = readl(u3phy_port->base + 0x044); + reg |= BIT(4); /* bg power down */ + writel(reg, u3phy_port->base + 0x044); + + reg = readl(u3phy_port->base + 0x150); + reg &= ~BIT(6); /* tx bias disable */ + writel(reg, u3phy_port->base + 0x150); + + reg = readl(u3phy_port->base + 0x080); + reg |= BIT(2); /* tx cm power down */ + writel(reg, u3phy_port->base + 0x080); + + reg = readl(u3phy_port->base + 0x0c0); + /* tx obs disable and rx cm disable */ + reg &= ~(BIT(3) | BIT(4)); + writel(reg, u3phy_port->base + 0x0c0); + } + + return 0; +} + +static int rk3328_u3phy_tuning(struct rockchip_u3phy *u3phy, + struct rockchip_u3phy_port *u3phy_port, + struct device_node *child_np) +{ + if (u3phy_port->type == U3PHY_TYPE_UTMI) { + /* + * For rk3328 SoC, pre-emphasis and pre-emphasis strength must + * be written as one fixed value as below. + * + * Dissimilarly, the odt 45ohm value should be flexibly tuninged + * for the different boards to adjust HS eye height, so its + * value can be assigned in DT in code design. + */ + + /* {bits[2:0]=111}: always enable pre-emphasis */ + u3phy->apbcfg.u2_pre_emp = 0x0f; + + /* {bits[5:3]=000}: pre-emphasis strength as the weakest */ + u3phy->apbcfg.u2_pre_emp_sth = 0x41; + + /* {bits[4:0]=10101}: odt 45ohm tuning */ + u3phy->apbcfg.u2_odt_tuning = 0xb5; + /* optional override of the odt 45ohm tuning */ + of_property_read_u32(child_np, "rockchip,odt-val-tuning", + &u3phy->apbcfg.u2_odt_tuning); + + writel(u3phy->apbcfg.u2_pre_emp, u3phy_port->base + 0x030); + writel(u3phy->apbcfg.u2_pre_emp_sth, u3phy_port->base + 0x040); + writel(u3phy->apbcfg.u2_odt_tuning, u3phy_port->base + 0x11c); + } else if (u3phy_port->type == U3PHY_TYPE_PIPE) { + if (u3phy_port->refclk_25m_quirk) { + dev_dbg(u3phy->dev, "switch to 25m refclk\n"); + /* ref clk switch to 25M */ + writel(0x64, u3phy_port->base + 0x11c); + writel(0x64, u3phy_port->base + 0x028); + writel(0x01, u3phy_port->base + 0x020); + writel(0x21, u3phy_port->base + 0x030); + writel(0x06, u3phy_port->base + 0x108); + writel(0x00, u3phy_port->base + 0x118); + } else { + /* configure for 24M ref clk */ + writel(0x80, u3phy_port->base + 0x10c); + writel(0x01, u3phy_port->base + 0x118); + writel(0x38, u3phy_port->base + 0x11c); + writel(0x83, u3phy_port->base + 0x020); + writel(0x02, u3phy_port->base + 0x108); + } + + /* Enable SSC */ + udelay(3); + writel(0x08, u3phy_port->base + 0x000); + writel(0x0c, u3phy_port->base + 0x120); + + /* Tuning Rx for compliance RJTL test */ + writel(0x70, u3phy_port->base + 0x150); + writel(0x12, u3phy_port->base + 0x0c8); + writel(0x05, u3phy_port->base + 0x148); + writel(0x08, u3phy_port->base + 0x068); + writel(0xf0, u3phy_port->base + 0x1c4); + writel(0xff, u3phy_port->base + 0x070); + writel(0x0f, u3phy_port->base + 0x06c); + writel(0xe0, u3phy_port->base + 0x060); + + /* + * Tuning Tx to increase the bias current + * used in TX driver and RX EQ, it can + * also increase the voltage of LFPS. + */ + writel(0x08, u3phy_port->base + 0x180); + } else { + dev_err(u3phy->dev, "invalid u3phy port type\n"); + return -EINVAL; + } + + return 0; +} + +static const struct rockchip_u3phy_cfg rk3328_u3phy_cfgs[] = { + { + .reg = 0xff470000, + .grfcfg = { + .um_suspend = { 0x0004, 15, 0, 0x1452, 0x15d1 }, + .u2_only_ctrl = { 0x0020, 15, 15, 0, 1 }, + .um_ls = { 0x0030, 5, 4, 0, 1 }, + .um_hstdct = { 0x0030, 7, 7, 0, 1 }, + .ls_det_en = { 0x0040, 0, 0, 0, 1 }, + .ls_det_st = { 0x0044, 0, 0, 0, 1 }, + .pp_pwr_st = { 0x0034, 14, 13, 0, 0}, + .pp_pwr_en = { {0x0020, 14, 0, 0x0014, 0x0005}, + {0x0020, 14, 0, 0x0014, 0x000d}, + {0x0020, 14, 0, 0x0014, 0x0015}, + {0x0020, 14, 0, 0x0014, 0x001d} }, + .u3_disable = { 0x04c4, 15, 0, 0x1100, 0x101}, + }, + .phy_pipe_power = rk3328_u3phy_pipe_power, + .phy_tuning = rk3328_u3phy_tuning, + }, + { /* sentinel */ } +}; + +static const struct of_device_id rockchip_u3phy_dt_match[] = { + { .compatible = "rockchip,rk3328-u3phy", .data = &rk3328_u3phy_cfgs }, + {} +}; +MODULE_DEVICE_TABLE(of, rockchip_u3phy_dt_match); + +static struct platform_driver rockchip_u3phy_driver = { + .probe = rockchip_u3phy_probe, + .driver = { + .name = "rockchip-u3phy", + .of_match_table = rockchip_u3phy_dt_match, + }, +}; +module_platform_driver(rockchip_u3phy_driver); + +MODULE_AUTHOR("Frank Wang "); +MODULE_AUTHOR("William Wu "); +MODULE_DESCRIPTION("Rockchip USB 3.0 PHY driver"); +MODULE_LICENSE("GPL v2"); From patchwork Mon Oct 28 18:22:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Geis X-Patchwork-Id: 11216249 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 89DC21515 for ; Mon, 28 Oct 2019 18:23:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 67133214B2 for ; Mon, 28 Oct 2019 18:23:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Ckbzqhhd" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2403780AbfJ1SXR (ORCPT ); Mon, 28 Oct 2019 14:23:17 -0400 Received: from mail-qt1-f196.google.com ([209.85.160.196]:36454 "EHLO mail-qt1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2391125AbfJ1SXR (ORCPT ); Mon, 28 Oct 2019 14:23:17 -0400 Received: by mail-qt1-f196.google.com with SMTP id x14so5687613qtq.3 for ; Mon, 28 Oct 2019 11:23:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=peg4X2YDLFsoUnpFAVPaYd5Gm2QFG5TrZ1ugo/dtbLU=; b=CkbzqhhdCBHymQbOsmwwdOR+mroOsit7vTupBUGMMUgRKoqNnSd269BquNMXUNKn4b Rv1l98IQKmWNDj6BqZCDY/Is+k7acGen2NGjpQhVjH4kFn8/0nfeQeSTaM40LUSW6a4L XJDcGD7PIZlmiy3YrSLOwxCJgzDI4ZgDf4DSDbmYHpouKy/FI70GWEFs7DIhRLbGkFZv xY+kssIRfYAOcvwvHQl8WRi/ZRL+CZ1m91w4LR4hLNuNUxGjrCv+H1oO+Jf6+k7VUOE7 DwdSQcmwIGgcVtwQesIXsknLYyBKAJEAVLycP93cfWS504gDmWnULb35VNHHxajwCyys OV9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=peg4X2YDLFsoUnpFAVPaYd5Gm2QFG5TrZ1ugo/dtbLU=; b=osnw9RuCoicxQSKIiZxJ4WxGukKUh9+HtWxKqFVi3xKmuQedam1Am5vX792cFVCbUp Z4dWuPh9sMbI4WJfszZo3Lx4c8LXP2F0/ghWwb7zeV9kbeQojuqssA6bJKMyIUWbTgvg lkcNhPJcT77wXzBS6rvAdxUMCb8dh0Z6Wgs55OMY32QT8iUy/Eow12iaJWxzowiI+ALj 7An8rG0IzA+u/oxvttZTIhCPAPkcBJ+91vjwi1MgxmXhQ5zbXI/e0D703SVBcJ198OyT viyIoTSZchV7qdBkIl1k86MdFqUAf+MzEL+wVewVIMA/24KR1deiLjIvN6aoYZrm81Gg nnYA== X-Gm-Message-State: APjAAAUh9rUYtCfOEWA8Ae1Iv4OSqVIQxf0pU7NOFJKDmtlYvUbWAAmm D89SdBAiqAR0iC9mcO9fIoA= X-Google-Smtp-Source: APXvYqwNKcO0LjFvNRg1Q0mjp25FutSewql7WzwxyZ+t1BtcKhVB0C+8qVlyVbEfinYvThKicEXQMw== X-Received: by 2002:ac8:93d:: with SMTP id t58mr6805313qth.217.1572286996447; Mon, 28 Oct 2019 11:23:16 -0700 (PDT) Received: from firefly.sparksnet ([2601:153:900:a52:6f12:874c:d2b2:a9d0]) by smtp.gmail.com with ESMTPSA id x9sm5808631qkl.75.2019.10.28.11.23.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Oct 2019 11:23:14 -0700 (PDT) From: Peter Geis To: heiko@sntech.de Cc: linux-rockchip@lists.infradead.org, linux-usb@vger.kernel.org, katsuhiro@katsuster.net, robin.murphy@arm.com, Peter Geis Subject: [PATCH 2/5] dt-bindings: clean up rockchip grf binding document Date: Mon, 28 Oct 2019 18:22:51 +0000 Message-Id: <20191028182254.30739-3-pgwipeout@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191028182254.30739-1-pgwipeout@gmail.com> References: <20191028182254.30739-1-pgwipeout@gmail.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Fixup some typos and inconsistencies in the grf binding. Signed-off-by: Peter Geis --- Documentation/devicetree/bindings/soc/rockchip/grf.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.txt b/Documentation/devicetree/bindings/soc/rockchip/grf.txt index d7debec26ba4..ada5435ce2c3 100644 --- a/Documentation/devicetree/bindings/soc/rockchip/grf.txt +++ b/Documentation/devicetree/bindings/soc/rockchip/grf.txt @@ -27,12 +27,12 @@ Required Properties: - "rockchip,px30-pmugrf", "syscon": for px30 - "rockchip,rk3368-pmugrf", "syscon": for rk3368 - "rockchip,rk3399-pmugrf", "syscon": for rk3399 -- compatible: SGRF should be one of the following +- compatible: SGRF should be one of the following: - "rockchip,rk3288-sgrf", "syscon": for rk3288 -- compatible: USB2PHYGRF should be one of the followings +- compatible: USB2PHYGRF should be one of the following: - "rockchip,px30-usb2phy-grf", "syscon": for px30 - "rockchip,rk3328-usb2phy-grf", "syscon": for rk3328 -- compatible: USBGRF should be one of the following +- compatible: USBGRF should be one of the following: - "rockchip,rv1108-usbgrf", "syscon": for rv1108 - reg: physical base address of the controller and length of memory mapped region. From patchwork Mon Oct 28 18:22:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Geis X-Patchwork-Id: 11216251 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0F2C31515 for ; Mon, 28 Oct 2019 18:23:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D801621744 for ; Mon, 28 Oct 2019 18:23:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="REvl8X8N" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2403806AbfJ1SXV (ORCPT ); Mon, 28 Oct 2019 14:23:21 -0400 Received: from mail-qt1-f194.google.com ([209.85.160.194]:37412 "EHLO mail-qt1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2403790AbfJ1SXV (ORCPT ); Mon, 28 Oct 2019 14:23:21 -0400 Received: by mail-qt1-f194.google.com with SMTP id g50so16008435qtb.4 for ; Mon, 28 Oct 2019 11:23:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=24mchh3lk2qW4NownaHeZFsWT5IBOkTUykvw4ymw35E=; b=REvl8X8Nwq+6+wn8Rc7S8oTuZa6YgHrp3U7vC6lGgb1xoDIbgzdkrqxXj/9rcykU/H e8MgaBCXqtzpobPHc9dSl8m76dX3DB/F5sjjpitarKbN5YLjNdHFSsencGGn8bS4zPlT F2BJI/a0AxAFsDtR1TViW6lRP3inIuWQ+LbXhqwjF5LPXwPJdbY1dHKnoxVrRfkM/sFH HpVluubNG1cdkRco7RTnXuwpOd7+poz4ZGdB4709UHFf3EMyoBDDSLHselWR0R3O1yn4 CgKy6OvIBuUjAlk+H7SHAyAmSyG8CkCGWOxh59Wh0PlXufeqMGQNgsAtTKIQCzAn5g9g l4Xw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=24mchh3lk2qW4NownaHeZFsWT5IBOkTUykvw4ymw35E=; b=dDDMxIMTrVYrV+fph5YpNIzpOa2XmYQT/pl6LPXmEV3BjwoT5NUBkURJKsAkTEHSiv IoQIGIHka9xJXXILpCAs8ppkJBO7kAPCukjb1AmoOhmbx1lv9btRJJxDLGyVl7Ip1WN7 OSmC4SG+qr+JrTNmXHiKmMMklkOTwqTxieiQxP8eGvYmBcMVqZVbDkRrBYybKWXU5sAL ex63n2VrVVUQSVxvwqKmlPwlwtRY6djc9nxQEi8/Lt6v4frarfg0qkkbQp9PPX6Zsq7+ r2WzAPt08msA2c4e2GlxQPD0nq7JeEXNPIaG926A/iD/7lPQEOOx5GeF5xCHEiVDKcOf SMnw== X-Gm-Message-State: APjAAAXeYf/T7v2EOHfa+ZX/KP162N9p3sR997OP+97cazMgdJx5/Mey SK+b/ldwLT+AKpvcpQkT9ck= X-Google-Smtp-Source: APXvYqxRaNykqiT+tC9OtDvY3KS8A3kiicGKa/kk0vtTpc5kk13xhwf/oWc5bQhooKC9Z0ZT9pJ0gQ== X-Received: by 2002:a0c:b38e:: with SMTP id t14mr8571002qve.125.1572286999718; Mon, 28 Oct 2019 11:23:19 -0700 (PDT) Received: from firefly.sparksnet ([2601:153:900:a52:6f12:874c:d2b2:a9d0]) by smtp.gmail.com with ESMTPSA id x9sm5808631qkl.75.2019.10.28.11.23.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Oct 2019 11:23:18 -0700 (PDT) From: Peter Geis To: heiko@sntech.de Cc: linux-rockchip@lists.infradead.org, linux-usb@vger.kernel.org, katsuhiro@katsuster.net, robin.murphy@arm.com, Peter Geis Subject: [PATCH 3/5] Documentation: bindings: add dt documentation for rockchip usb3 phy Date: Mon, 28 Oct 2019 18:22:52 +0000 Message-Id: <20191028182254.30739-4-pgwipeout@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191028182254.30739-1-pgwipeout@gmail.com> References: <20191028182254.30739-1-pgwipeout@gmail.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Add devicetree bindings for inno-usb3-phy. Signed-off-by: Peter Geis --- .../bindings/phy/phy-rockchip-inno-usb3.yaml | 157 ++++++++++++++++++ .../devicetree/bindings/soc/rockchip/grf.txt | 2 + .../devicetree/bindings/usb/rockchip,dwc3.txt | 9 +- 3 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb3.yaml diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb3.yaml b/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb3.yaml new file mode 100644 index 000000000000..f4f28625173a --- /dev/null +++ b/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb3.yaml @@ -0,0 +1,157 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/phy/phy-rockchip-inno-usb3.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: ROCKCHIP USB 3.0 PHY WITH INNO IP BLOCK + +maintainers: + +properties: + compatible: + enum: + - rockchip,rk3328-u3phy + + reg: + - description: the base address of the USB 3.0 PHY + + interrupts: + maxItems: 1 + + interrupt-names: + items: + - const: linestate + description: host/otg linestate interrupt + + clocks: + maxItems: 2 + + clock-names: + items: + - const: u3phy-otg + description: USB 3.0 PHY UTMI + - const: u3phy-pipe + description: USB 3.0 PHY Pipe + + resets: + maxItems: 6 + + reset-names: + items: + - const: u3phy-u2-por + description: USB 2.0 logic of USB 3.0 PHY + - const: u3phy-u3-por + description: USB 3.0 logic of USB 3.0 PHY + - const: u3phy-pipe-mac + description: USB 3.0 PHY pipe MAC + - const: u3phy-utmi-mac + description: USB 3.0 PHY utmi MAC + - const: u3phy-utmi-apb + description: USB 3.0 PHY utmi apb + - const: u3phy-pipe-apb + description: USB 3.0 PHY pipe apb + + "#phy-cells": + const: 1 + + rockchip,u3phygrf: + $ref: /schemas/types.yaml#/definitions/phandle-array + type: array + - description: phandle to the syscon managing the + "USB 3.0 PHY general register files". + + vbus-drv-gpios: + $ref: /schemas/types.yaml#/definitions/phandle-array + type: array + - description: phandle for gpio vbus supply + +required: + - compatible + - reg + - interrupts + - interrupt-names + - clocks + - clock-names + - resets + - reset-names + - "#phy-cells" + - rockchip,u3phygrf + +patternProperties: + "^u3phy_utmi@[0-9a-f]+$": + type: object + + properties: + - description: USB 2.0 utmi phy. + + rockchip,odt-val-tuning: + type: boolean + - description: specify 45ohm ODT tuning value. + + "phy-cells": + const: 0 + + required: + - reg + - "#phy-cells" + +patternProperties: + "^u3phy_pipe@[0-9a-f]+$": + type: object + + properties: + - description: USB 3.0 pipe phy. + + rockchip,refclk-25m-quirk : + + - description: phy reference clock changed to 25m quirk. + + "phy-cells": + const: 0 + + required: + - reg + - "#phy-cells" + +examples: + +usb3phy_grf: syscon@ff460000 { + compatible = "rockchip,usb3phy-grf", "syscon"; + reg = <0x0 0xff460000 0x0 0x1000>; +}; + +... + +u3phy: usb3-phy@ff470000 { + compatible = "rockchip,rk3328-u3phy"; + reg = <0x0 0xff470000 0x0 0x0>; + rockchip,u3phygrf = <&usb3phy_grf>; + interrupts = ; + interrupt-names = "linestate"; + clocks = <&cru PCLK_USB3PHY_OTG>, <&cru PCLK_USB3PHY_PIPE>; + clock-names = "u3phy-otg", "u3phy-pipe"; + resets = <&cru SRST_USB3PHY_U2>, + <&cru SRST_USB3PHY_U3>, + <&cru SRST_USB3PHY_PIPE>, + <&cru SRST_USB3OTG_UTMI>, + <&cru SRST_USB3PHY_OTG_P>, + <&cru SRST_USB3PHY_PIPE_P>; + reset-names = "u3phy-u2-por", "u3phy-u3-por", + "u3phy-pipe-mac", "u3phy-utmi-mac", + "u3phy-utmi-apb", "u3phy-pipe-apb"; + vbus-drv-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + u3phy_utmi: utmi@ff470000 { + reg = <0x0 0xff470000 0x0 0x8000>; + #phy-cells = <0>; + }; + + u3phy_pipe: pipe@ff478000 { + reg = <0x0 0xff478000 0x0 0x8000>; + #phy-cells = <0>; + }; +}; diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.txt b/Documentation/devicetree/bindings/soc/rockchip/grf.txt index ada5435ce2c3..5f2f19344cc7 100644 --- a/Documentation/devicetree/bindings/soc/rockchip/grf.txt +++ b/Documentation/devicetree/bindings/soc/rockchip/grf.txt @@ -34,6 +34,8 @@ Required Properties: - "rockchip,rk3328-usb2phy-grf", "syscon": for rk3328 - compatible: USBGRF should be one of the following: - "rockchip,rv1108-usbgrf", "syscon": for rv1108 +- compatible: USB3PHYGRF should be one of the following: + - "rockchip,u3phy-grf", "syscon" - reg: physical base address of the controller and length of memory mapped region. diff --git a/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt b/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt index c8c4b00ecb94..7ac8b748bac8 100644 --- a/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt +++ b/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt @@ -1,7 +1,9 @@ Rockchip SuperSpeed DWC3 USB SoC controller Required properties: -- compatible: should contain "rockchip,rk3399-dwc3" for rk3399 SoC +- compatible: should be one of the listed compatibles: + - "rockchip,rk3328-dwc3" , "rockchip,rk3399-dwc3" for rk3328 SoC + - "rockchip,rk3399-dwc3" for rk3399 SoC - clocks: A list of phandle + clock-specifier pairs for the clocks listed in clock-names - clock-names: Should contain the following: @@ -16,8 +18,9 @@ A child node must exist to represent the core DWC3 IP block. The name of the node is not important. The content of the node is defined in dwc3.txt. Phy documentation is provided in the following places: -Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt - USB2.0 PHY -Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt - Type-C PHY +Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt - USB2.0 PHY +Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb3.yaml - USB3.0 PHY +Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt - Type-C PHY Example device nodes: From patchwork Mon Oct 28 18:22:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Geis X-Patchwork-Id: 11216259 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 80EF51599 for ; Mon, 28 Oct 2019 18:23:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5E25421744 for ; Mon, 28 Oct 2019 18:23:25 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="L15uAcXS" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2404370AbfJ1SXY (ORCPT ); Mon, 28 Oct 2019 14:23:24 -0400 Received: from mail-qt1-f193.google.com ([209.85.160.193]:36464 "EHLO mail-qt1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2404359AbfJ1SXY (ORCPT ); Mon, 28 Oct 2019 14:23:24 -0400 Received: by mail-qt1-f193.google.com with SMTP id x14so5688115qtq.3 for ; Mon, 28 Oct 2019 11:23:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=bYdyfTTVAmyGW21ZGGqnnoD86zc6/IpuGIb/U04K8uI=; b=L15uAcXSF7j0iLmVzieZstNJpuLMz+ce+dovme+wlNu8+hx6J5j44mW5uNS+kUSiHK w29wSEu8ajENkKxD+B9Jtr8KDrzC4XdTscr0wriajfadOd1vlAkNIgVnf3bgXmDXELfS J//jn0gjTr2OFOtXrXAnYgs9mIYPy8ANRLl/hLbC0U9SPNmn5mYp9qqmn3T0TWFzpTp/ A1ParnpqahmjKuGq7aXvleStxg2D804t3/3fozxJ4gDClZWIsTnepxr5N+sgpt3kGngD mPFBA5oDkJrzgtX9psmuFe1Yy7Sqfo+cw1DhLCTWsUUyZJ+C0PuvAbth7YZxn17Sy4MM tLRw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bYdyfTTVAmyGW21ZGGqnnoD86zc6/IpuGIb/U04K8uI=; b=jyxxKEmEcjQiYjuFfcD4LE1VcYa4nrT8gQIxVjWfFEilPUN/3YdkcDe5ruppKAtyX/ i/GT4SQT6bOZCivx6IDKOLUXDocxdXKtL7BFKxfFtOwnrfEGBC2IHYKVgkXPZSnv7WEi QU3fseVFJoi5Bi+PpdNQ6r4Iyfzbp57B0ByXfTTutKY9/2bR7sgUz+NZAJcYrDIPiY5B fZE2lghLmfk+lj75UzANEgISNnbYtLkPnkILu12pdOqA36yyutiri5sLJWGarKOKvqYu SA/DjRdGCsMeMzsNgr2CKZb4AgcTP5PvStjn7BRD45i8dqOzIT+Iu5RBLTwmz+JkK19z FHlw== X-Gm-Message-State: APjAAAXLNmlZvKkp3nbSrJudN6femtdAaaa+iv++byq8cS36dbMHWIb4 v8YLaGOAiq0zpQANygW+uOA= X-Google-Smtp-Source: APXvYqyBALN0xL62K4rkfFWmGboru7kCh/giq31JFj9yvizQqCE9Z5w702lsedNOszgfmlv2cY7gWQ== X-Received: by 2002:aed:3baf:: with SMTP id r44mr16827909qte.255.1572287002822; Mon, 28 Oct 2019 11:23:22 -0700 (PDT) Received: from firefly.sparksnet ([2601:153:900:a52:6f12:874c:d2b2:a9d0]) by smtp.gmail.com with ESMTPSA id x9sm5808631qkl.75.2019.10.28.11.23.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Oct 2019 11:23:21 -0700 (PDT) From: Peter Geis To: heiko@sntech.de Cc: linux-rockchip@lists.infradead.org, linux-usb@vger.kernel.org, katsuhiro@katsuster.net, robin.murphy@arm.com, Peter Geis Subject: [PATCH 4/5] arm64: dts: rockchip: add usb3 to rk3328 devicetree Date: Mon, 28 Oct 2019 18:22:53 +0000 Message-Id: <20191028182254.30739-5-pgwipeout@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191028182254.30739-1-pgwipeout@gmail.com> References: <20191028182254.30739-1-pgwipeout@gmail.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Now that we have a proper phy driver, we can add the requisite bits to the rk3328 device tree. Added the u3drd and u3phy nodes. Signed-off-by: Peter Geis --- arch/arm64/boot/dts/rockchip/rk3328.dtsi | 72 ++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index 31cc1541f1f5..072e988ad655 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -805,6 +805,47 @@ }; }; + usb3phy_grf: syscon@ff460000 { + compatible = "rockchip,usb3phy-grf", "syscon"; + reg = <0x0 0xff460000 0x0 0x1000>; + }; + + u3phy: usb3-phy@ff470000 { + compatible = "rockchip,rk3328-u3phy"; + reg = <0x0 0xff470000 0x0 0x0>; + rockchip,u3phygrf = <&usb3phy_grf>; + rockchip,grf = <&grf>; + interrupts = ; + interrupt-names = "linestate"; + clocks = <&cru PCLK_USB3PHY_OTG>, <&cru PCLK_USB3PHY_PIPE>; + clock-names = "u3phy-otg", "u3phy-pipe"; + resets = <&cru SRST_USB3PHY_U2>, + <&cru SRST_USB3PHY_U3>, + <&cru SRST_USB3PHY_PIPE>, + <&cru SRST_USB3OTG_UTMI>, + <&cru SRST_USB3PHY_OTG_P>, + <&cru SRST_USB3PHY_PIPE_P>; + reset-names = "u3phy-u2-por", "u3phy-u3-por", + "u3phy-pipe-mac", "u3phy-utmi-mac", + "u3phy-utmi-apb", "u3phy-pipe-apb"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + u3phy_utmi: utmi@ff470000 { + reg = <0x0 0xff470000 0x0 0x8000>; + #phy-cells = <0>; + status = "disabled"; + }; + + u3phy_pipe: pipe@ff478000 { + reg = <0x0 0xff478000 0x0 0x8000>; + #phy-cells = <0>; + status = "disabled"; + }; + }; + sdmmc: dwmmc@ff500000 { compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; reg = <0x0 0xff500000 0x0 0x4000>; @@ -936,6 +977,37 @@ status = "disabled"; }; + usbdrd3: usb@ff600000 { + compatible = "rockchip,rk3328-dwc3", "rockchip,rk3399-dwc3"; + clocks = <&cru SCLK_USB3OTG_REF>, <&cru ACLK_USB3OTG>, + <&cru SCLK_USB3OTG_SUSPEND>; + clock-names = "ref", "bus_early", + "suspend"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clock-ranges; + status = "disabled"; + + usbdrd_dwc3: dwc3@ff600000 { + compatible = "snps,dwc3"; + reg = <0x0 0xff600000 0x0 0x100000>; + interrupts = ; + dr_mode = "otg"; + phys = <&u3phy_utmi>, <&u3phy_pipe>; + phy-names = "usb2-phy", "usb3-phy"; + phy_type = "utmi_wide"; + snps,dis_enblslpm_quirk; + snps,dis-u2-freeclk-exists-quirk; + snps,dis_u2_susphy_quirk; + snps,dis_u3_susphy_quirk; + snps,dis-del-phy-power-chg-quirk; + snps,dis-tx-ipgap-linecheck-quirk; + snps,xhci-trb-ent-quirk; + status = "disabled"; + }; + }; + gic: interrupt-controller@ff811000 { compatible = "arm,gic-400"; #interrupt-cells = <3>; From patchwork Mon Oct 28 18:22:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Geis X-Patchwork-Id: 11216261 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2D798913 for ; Mon, 28 Oct 2019 18:23:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0AB5E21721 for ; Mon, 28 Oct 2019 18:23:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="glavdkw8" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2404371AbfJ1SX1 (ORCPT ); Mon, 28 Oct 2019 14:23:27 -0400 Received: from mail-qk1-f196.google.com ([209.85.222.196]:39250 "EHLO mail-qk1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2404359AbfJ1SX1 (ORCPT ); Mon, 28 Oct 2019 14:23:27 -0400 Received: by mail-qk1-f196.google.com with SMTP id 15so9396927qkh.6 for ; Mon, 28 Oct 2019 11:23:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0/i6iib0QOySXmB9hMOchk2gqiCio9IrBQ0i7JtpvQ8=; b=glavdkw8cp4fn74iXdJZa7mzXJqdYB1oftGYI/YZPz1jGY0UV041SWlEIXGUV1/q+X 30QerC4L/9veoteKetM98kE2nSDT2iNTHXXBUS3WzeHmVpEPow53RBYx/uglPeax9Tio ZuHLIP4U90fPzoeWafzxK7hFF/tTisc2Mfd5fz4YI91qlBozpdSQPQVm9+QtAnRNuM+3 wXxETtJJCA43x1eDjVN1K0zrPtXA9F59ok4lV+BKCL8cQGx032AgMJBNE+Bhf6jWIAGN GUqM5ny2WjkUrr4JacM1+a1scp9EADl678RwqlTbccPNgHGMi9+bA5aHCB+VMqjwqSKC apaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0/i6iib0QOySXmB9hMOchk2gqiCio9IrBQ0i7JtpvQ8=; b=mpMvg2dWJmf8XZBRIwr1C9CdpjsRsbOYBa+H3TyUlRLUVNZ7pkm9/3F82QNMiL8nT6 xieX0AoFwxf8zlQiROPkKi2Nn8wQXf2k/ii3oB9WCFhjhphkm5VVPz/vPqgrlKGnUTpM YL8Q6QR6wo1JjcuVY01u40MOJa5aBCDv47AuYRhyLjGIAB257JULvVHir0d/dGWU3LQ2 UewmzkzCzC1HymixvGHoQ3SF58mFwqPu5PBXtfAqI4bBSoP7gib2iMQ0IZ0WRzOe9bcO YGj82CQjZG/3N7LiU6tte377lIVJEdF7wb37E/c8LcGxkaA4rUbtvlFGElNph7SdDA0A rPWg== X-Gm-Message-State: APjAAAU+wGP5ICf1pBNDsm+7YL9cfKGvvT47MEDr43P+WQGtFI9OB1pL 2344U6v5LRTOckcOXLs8RuA= X-Google-Smtp-Source: APXvYqxj9YsGeXLUuF/3NgVDL62I80DKTBCWKY3BsPDvmifn2t3iMdDCubfZHSH7GyVsSq3rLrPWIA== X-Received: by 2002:a37:78f:: with SMTP id 137mr16724495qkh.321.1572287006005; Mon, 28 Oct 2019 11:23:26 -0700 (PDT) Received: from firefly.sparksnet ([2601:153:900:a52:6f12:874c:d2b2:a9d0]) by smtp.gmail.com with ESMTPSA id x9sm5808631qkl.75.2019.10.28.11.23.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Oct 2019 11:23:24 -0700 (PDT) From: Peter Geis To: heiko@sntech.de Cc: linux-rockchip@lists.infradead.org, linux-usb@vger.kernel.org, katsuhiro@katsuster.net, robin.murphy@arm.com, Peter Geis Subject: [PATCH 5/5] arm64: dts: rockchip: enable usb3 on rk3328-roc-cc Date: Mon, 28 Oct 2019 18:22:54 +0000 Message-Id: <20191028182254.30739-6-pgwipeout@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191028182254.30739-1-pgwipeout@gmail.com> References: <20191028182254.30739-1-pgwipeout@gmail.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Enable the usb3 controller and phy on the rk3328-roc-cc device tree. Signed-off-by: Peter Geis --- .../arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts index bb40c163b05d..f300f3d0f02e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts @@ -328,6 +328,18 @@ status = "okay"; }; +&u3phy { + status = "okay"; +}; + +&u3phy_utmi { + status = "okay"; +}; + +&u3phy_pipe { + status = "okay"; +}; + &uart2 { status = "okay"; }; @@ -344,6 +356,15 @@ status = "okay"; }; +&usbdrd3 { + status = "okay"; +}; + +&usbdrd_dwc3 { + dr_mode = "host"; + status = "okay"; +}; + &vop { status = "okay"; };