From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from layka.disroot.org (layka.disroot.org [178.21.23.139]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 363FE3C4565; Mon, 20 Apr 2026 19:20:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.21.23.139 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776712825; cv=none; b=snT41Bnta513XLVc9bXZ4f9f0eTIP0oDTwYqo6Sci9rpgrIemL5g34GUjTSgQ6uEkgAFYz3IhcF7ukKuSqUwwKGxCRv5AycO4UP0VWqeTwiHBrIujqlOpDqry+LuYAKskYlkBIxzfPuz3gkVLg9Mp65PnDtnVcmwguh9/i7l35Y= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776712825; c=relaxed/simple; bh=daxptYU8HlXdVQlCPKqv2iutTKO/3+o3g3ChmcjZbdM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cSdScJBNl5EPdXfqdLlyn+BkzENmtxRHTSE3rJrVGHikIx0JSiOv30wJBcXYUJFjmcYUqRhdugrLXmMUAS/QX/jnYhpJGl3f7H9PIFvdvPOBJKdFjeyimpqHk5MIKUv0R+ZYYQTCTkRZ1JaPslsqNJTJ9OV5OEnHFdmRWxe+q3w= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org; spf=pass smtp.mailfrom=disroot.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b=Qp6iPuhQ; arc=none smtp.client-ip=178.21.23.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=disroot.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b="Qp6iPuhQ" Received: from mail01.disroot.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id B3BDD26F19; Mon, 20 Apr 2026 21:20:20 +0200 (CEST) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 0wy79rXnQk12; Mon, 20 Apr 2026 21:20:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1776712820; bh=daxptYU8HlXdVQlCPKqv2iutTKO/3+o3g3ChmcjZbdM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Qp6iPuhQlcNn3ZmHa0O6KenLeV8byoVcD1/vX/NC4KCkw7Y2aE30Rdk1WLls9YHq2 6ch8lhJSGNGT+AOsQy63FUNkP4FF+/GlqSfU/x9GBxH3X8RFQ93CWAnUECPA32sWX1 QK/A8r8cUxjOEccrTEcx28XYk5R7ylMNvKHMxdbrPO0p9Jt9mEvLVoY/ea/8QyollO XP6ymdq/+Gy3duksC/cfhyi4M2Wz9zGaM6cc4izFKBAl6KVXyR7J6n0IYLkcAD74t1 HDFs9x23mtjYnSUywwuRtC6lgdcdx/zxudouWCZ5FFy0m2MadruDPFkfIS7yeWUlV2 ZkNHifJnJrSgg== From: Rustam Adilov To: Vinod Koul , Neil Armstrong , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Stanley Chang , linux-phy@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Rustam Adilov , Michael Zavertkin Subject: [PATCH v5 5/6] phy: realtek: usb2: add support for RTL9607C USB2 PHY Date: Tue, 21 Apr 2026 00:19:40 +0500 Message-ID: <20260420191941.81834-6-adilov@disroot.org> In-Reply-To: <20260420191941.81834-1-adilov@disroot.org> References: <20260420191941.81834-1-adilov@disroot.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Add support for the usb2 phy of RTL9607C series based SoCs. Add the macros and phy config struct for rtl9607. RTL9607C requires to clear a "force host disconnect" bit in the specific register (which is at an offset from reg_wrap_vstatus) before proceeding with phy parameter writes. Since it belongs into the vstatus register region, it doesn't need bytes swapping. Add the bool variable to the driver data struct and hide this whole procedure under the if statement that checks this new variable. Add the appropriate little endian read and write functions for rtl9607 and assign them to its phy config struct. As mentioned earlier, the readl/writel are native endian on MIPS arch if SWAP_IO_SPACE is not enabled. Since enabling SWAP_IO_SPACE results in boot hang on RTL9607C machine, wrapping le32 around readl/writel should be a good compromise, but swab32 could be also work. Co-developed-by: Michael Zavertkin Signed-off-by: Michael Zavertkin Signed-off-by: Rustam Adilov --- drivers/phy/realtek/phy-rtk-usb2.c | 57 ++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c index aaa07a69224a..7671f8a9ff61 100644 --- a/drivers/phy/realtek/phy-rtk-usb2.c +++ b/drivers/phy/realtek/phy-rtk-usb2.c @@ -26,6 +26,12 @@ #define PHY_VCTRL_SHIFT 8 #define PHY_REG_DATA_MASK 0xff +#define PHY_9607_VSTS_BUSY BIT(17) +#define PHY_9607_NEW_REG_REQ BIT(13) + +#define PHY_9607_FORCE_DISCONNECT_REG 0x10 +#define PHY_9607_FORCE_DISCONNECT_BIT BIT(5) + #define GET_LOW_NIBBLE(addr) ((addr) & 0x0f) #define GET_HIGH_NIBBLE(addr) (((addr) & 0xf0) >> 4) @@ -109,6 +115,7 @@ struct phy_cfg { u32 (*read)(void __iomem *reg); void (*write)(u32 val, void __iomem *reg); + bool force_host_disconnect; }; struct phy_parameter { @@ -146,6 +153,18 @@ static void rtk_usb2phy_write(u32 val, void __iomem *reg) writel(val, reg); } +static u32 rtk_usb2phy_read_le(void __iomem *reg) +{ + return le32_to_cpu(readl(reg)); +} + +static void rtk_usb2phy_write_le(u32 val, void __iomem *reg) +{ + u32 tmp = cpu_to_le32(val); + + writel(tmp, reg); +} + /* mapping 0xE0 to 0 ... 0xE7 to 7, 0xF0 to 8 ,,, 0xF7 to 15 */ static inline int page_addr_to_array_index(u8 addr) { @@ -600,6 +619,16 @@ static int do_rtk_phy_init(struct rtk_phy *rtk_phy, int index) goto do_toggle; } + if (phy_cfg->force_host_disconnect) { + /* disable force-host-disconnect */ + u32 temp = readl(phy_reg->reg_wrap_vstatus + PHY_9607_FORCE_DISCONNECT_REG); + + temp &= ~PHY_9607_FORCE_DISCONNECT_BIT; + writel(temp, phy_reg->reg_wrap_vstatus + PHY_9607_FORCE_DISCONNECT_REG); + + msleep(10); + } + /* Set page 0 */ phy_data_page = phy_cfg->page0; rtk_phy_set_page(phy_reg, 0); @@ -1374,6 +1403,33 @@ static const struct phy_cfg rtd1315e_phy_cfg = { .write = rtk_usb2phy_write, }; +static const struct phy_cfg rtl9607_phy_cfg = { + .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE, + .page0 = { [0] = {0xe0, 0x95}, + [4] = {0xe4, 0x6a}, + [12] = {0xf3, 0x31}, }, + .page1_size = MAX_USB_PHY_PAGE1_DATA_SIZE, + .page1 = { [0] = {0xe0, 0x26}, }, + .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE, + .page2 = { [7] = {0xe7, 0x33}, }, + .num_phy = 1, + .check_efuse_version = CHECK_EFUSE_V2, + .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE, + .dc_driving_mask = 0x1f, + .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE, + .dc_disconnect_mask = 0xf, + .usb_dc_disconnect_at_page0 = true, + .do_toggle = true, + .driving_updated_for_dev_dis = 0x8, + .is_double_sensitivity_mode = true, + .vstatus_offset = 0xc, + .vstatus_busy = PHY_9607_VSTS_BUSY, + .new_reg_req = PHY_9607_NEW_REG_REQ, + .read = rtk_usb2phy_read_le, + .write = rtk_usb2phy_write_le, + .force_host_disconnect = true, +}; + static const struct of_device_id usbphy_rtk_dt_match[] = { { .compatible = "realtek,rtd1295-usb2phy", .data = &rtd1295_phy_cfg }, { .compatible = "realtek,rtd1312c-usb2phy", .data = &rtd1312c_phy_cfg }, @@ -1384,6 +1440,7 @@ static const struct of_device_id usbphy_rtk_dt_match[] = { { .compatible = "realtek,rtd1395-usb2phy-2port", .data = &rtd1395_phy_cfg_2port }, { .compatible = "realtek,rtd1619-usb2phy", .data = &rtd1619_phy_cfg }, { .compatible = "realtek,rtd1619b-usb2phy", .data = &rtd1619b_phy_cfg }, + { .compatible = "realtek,rtl9607-usb2phy", .data = &rtl9607_phy_cfg }, {}, }; MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match); -- 2.53.0