From nobody Fri Sep 25 10:37:07 2026 Received: from mail-pj2-f13.google.com (mail-pj2-f13.google.com [74.125.227.141]) (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 D685D3446AD for ; Mon, 14 Sep 2026 03:19:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789355973; cv=none; b=A8lFxWdbRY0Vz652GSf8+rR8c7FEFjFSJY2Pkq4dgOCUVuSXEpzipvys0GjkD33LTf1h40fxMdCg/rTwHH/n5KjmAtMBpfyZUIVNJ4XCyVLhJpk3Ps0xAl/hbmf5vdioCAKMaAAiU4eD9OTiABCnpfHuwO/70bmHWmTHoDy5ouU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789355973; c=relaxed/simple; bh=cIwC0oC0HqkbdEbqtI2pH3Cw4jfxhvxzji3+pSjEakI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=c9Gsg18JkVe5lG+Mjc1H5kc1w3EGfoMLpNLvtddTHOiHB8INGZVd8qJbvJ0ub6NrDyBGWnMyUZZm1+8F5AyiKiyPSTGPvGFUhXVKoalNPWtEJpZ3fX6HsgXpEAehGg2qjbYfvE7+R5YYdgRE3sfxNPWiXinkWjgi3/mZUENMRF8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=VqoWb/NR; arc=none smtp.client-ip=74.125.227.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VqoWb/NR" Received: by mail-pj2-f13.google.com with SMTP id d9443c01a7336-2d747eb79f7so9446585ad.1 for ; Sun, 13 Sep 2026 20:19:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789355950; x=1789960750; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=GVUZrYg+XX3ftKTmbZ6y3GjBx4YY/KKIzTtukvscq4w=; b=VqoWb/NRL7mXUIeoFo5okq2TrDHUV3QeXS9v3DhInvgRFOdpFho7AB21v1M4Nfg9uw yfIFhARQE2QkwpdnOy357OZKV8Tg5XN10QBpwCjlfWU1mBaXO+Sm91lt04yXtkCGsH9j gCqTC6zksN6Z8C9o5bT2+WkZj8jS6eWa9g7NMcySjHzFZ8v3yzJxVO4ZQL2UPgRb7zX4 mS+fbDffl7EBF7dfo/1HRT9rkuP6+dyVzFpifFnOeJPs32/wkMnGhx0w3Kza5DJSn1vv 4myqmFttFOIYNg4pZt3Z3M+c8Y1GvgBCljumG8+sTQQ7WDFVfj8eS1o2ZtWUy3PlZZJf BwKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789355950; x=1789960750; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=GVUZrYg+XX3ftKTmbZ6y3GjBx4YY/KKIzTtukvscq4w=; b=pdWVmNwV9dQCBqw+qQUWi15U5bhjHZfBT23h22i8R4552McBgNAHBZe4DjkF3t8/ku ijMYjDgMJmWK9t+Mp+vLxsYFlpb2LhPRiHmebkjzr5emY3XKWuJKIVi5jeOB3Nf8UIYQ +Ot33zRZDWmvt/0k0uxoGi+uFCjtxx5JCJg71pRt4IQS1dotXk4WFd3b0DPTKnzpgMTY 08Bt6d7rsILmOQ3TlSh9syBBjmqads93D/Un7r8wXIhnM6AKAf8Zdw4vwwaXBh7CRHsW lO+LrJYVQ/KZrjSbWixdvQTIqHnQUtMiTVjfZ/ZCy7KdB1Ekg4asDas6jbhTzf3mq3z4 jdiQ== X-Forwarded-Encrypted: i=1; AKwUvBw88u8MJyUACl0XZFmWQyUb7BEvh4EFVSuCghYIhlGPhFnEgAjxK0qwxvcHo01jM73awN+Yl6b0yT83ZQQ=@vger.kernel.org X-Gm-Message-State: AFuF++nmy1Ej5Tc98Adsa3oFN9MjfWV1fO4XzXMv6o1a3oHm4d2VnNYl D1DF9siROOrlRRWcDTglJDJ4Z4zVqyx1SK5OVMsVpKsCQpmeZcHGIezT X-Gm-Gg: AYBFou0WPQnwVEwLD7xZTkezfuVOT9GVuvDucvoAV+5t4KtD4sC6/FSCVFmvFpmgax4 Tz/rDrLfOHh5eVCB6KgRVwg1rxyCh7uNBsqr6d8NZ1D9fmbOv4Q3opuGOY7b6SxPiI6S0IbYvp3 pikR0wsGkW40PUAp4lbU6+8l218ytRR7LomZD11mPnR8/QpHK5fwizcwZI/5JQzm2sS139jFE7Y ypwjbQ9rlxXD/gIQVx2OddGhQz5QVNYyh0Uy2QpPYmHEUP0j0PXNhKIcfgOVV6zcKxsM+wCDOZy 3YZ3m3MOINWUDNHIb0lX3C/HthH8fnxnWiX7OFEh0fhTPjIqLR3p0JlpX9Kd3DcNJYYdt4dXQvO 1QIp87JiXLMQllxxWpYAuu/urrjNou5iEdA3JZHa6PauAxcJknpEuXO7NMTd16E3DcSJ6J6pIAV Wuz2R8IsgPlvN4ERJxlRMIEguiHJlgNg4/qBhul6ORMXMuAMzBQcx2hvEZ/sxZIWI/tFqExWivJ fyEvAKaXHzl1FntcAim8zWxta+L+tftzYjEXXwjVb22w87cV9CbCUe44Bisf6E= X-Received: by 2002:a17:902:d582:b0:2ca:1479:d9dc with SMTP id d9443c01a7336-2dd6c6db2e8mr18390955ad.12.1789355949721; Sun, 13 Sep 2026 20:19:09 -0700 (PDT) Received: from localhost.localdomain (60-250-196-139.hinet-ip.hinet.net. [60.250.196.139]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2dd2cfc2d3bsm41355145ad.48.2026.09.13.20.19.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:19:09 -0700 (PDT) From: Joey Lu To: Vinod Koul , Neil Armstrong Cc: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Arnd Bergmann , Catalin Marinas , Jacky Huang , Shan-Chun Hung , Hui-Ping Chen , Joey Lu , linux-phy@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Joey Lu , Krzysztof Kozlowski Subject: [PATCH v5 1/3] dt-bindings: phy: nuvoton,ma35d1-usb2-phy: extend for dual-port and OTG Date: Mon, 14 Sep 2026 11:18:57 +0800 Message-ID: <20260914031859.385224-2-a0987203069@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260914031859.385224-1-a0987203069@gmail.com> References: <20260914031859.385224-1-a0987203069@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The MA35D1 exposes two USB PHY ports (PHY0 and PHY1) managed by the same hardware block (USBPMISCR register in the system-management syscon). PHY0 is shared between the DWC2 gadget controller and EHCI0/OHCI0 through an automatic hardware mux that follows the USB ID pin; PHY1 is dedicated to EHCI1/OHCI1. Because both ports share the same register topology a single binding and driver should cover both. Changing '#phy-cells' from const: 0 to enum: [0, 1] lets consumers name the port they need while preserving backward compatibility: boards already using '#phy-cells =3D <0>' continue to validate and function unchanged. The two new optional properties: - nuvoton,rcalcode: the resistor calibration trim code is determined at board design time to match the PCB trace impedance. - nuvoton,oc-active-high: the over-current detect polarity depends on the choice of VBUS power switch. Signed-off-by: Joey Lu Reviewed-by: Krzysztof Kozlowski --- .../bindings/phy/nuvoton,ma35d1-usb2-phy.yaml | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/phy/nuvoton,ma35d1-usb2-phy.= yaml b/Documentation/devicetree/bindings/phy/nuvoton,ma35d1-usb2-phy.yaml index fff858c909a0..1bd22dd0e5fc 100644 --- a/Documentation/devicetree/bindings/phy/nuvoton,ma35d1-usb2-phy.yaml +++ b/Documentation/devicetree/bindings/phy/nuvoton,ma35d1-usb2-phy.yaml @@ -8,6 +8,18 @@ title: Nuvoton MA35D1 USB2 phy =20 maintainers: - Hui-Ping Chen + - Joey Lu + +description: + USB 2.0 PHY for the Nuvoton MA35D1 SoC. The PHY node is a standalone + platform device that accesses the USB PHY control registers inside the + system-management syscon block via the nuvoton,sys phandle. + + PHY0 is the OTG port whose signals are routed to either the DWC2 gadget + controller or the EHCI0/OHCI0 host controller by a hardware mux that + follows the USB ID pin automatically. + + PHY1 is a dedicated host-only port used by EHCI1/OHCI1. =20 properties: compatible: @@ -15,7 +27,12 @@ properties: - nuvoton,ma35d1-usb2-phy =20 "#phy-cells": - const: 0 + enum: [0, 1] + description: + When 0, the node exposes PHY0 only and consumers reference it + with no cell argument. When 1, the single cell selects the port, + with 0 for the OTG port (USB0, shared with DWC2 gadget controller) + and 1 for the host-only port (USB1). =20 clocks: maxItems: 1 @@ -23,7 +40,29 @@ properties: nuvoton,sys: $ref: /schemas/types.yaml#/definitions/phandle description: - phandle to syscon for checking the PHY clock status. + Phandle to the system-management syscon node providing access to the + USB PHY control registers. + + nuvoton,rcalcode: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 2 + maxItems: 2 + items: + minimum: 0 + maximum: 15 + description: + Resistor calibration trim codes for PHY0 and PHY1 respectively. + Each 4-bit value is written to the RCALCODE field in USBPMISCR and + adjusts the PHY's internal termination resistance. Both entries must + be supplied when this property is present; when absent the hardware + reset default is used for each port. + + nuvoton,oc-active-high: + type: boolean + description: + When present, the over-current detect input from the VBUS power swit= ch + is treated as active-high. The default (property absent) is active-l= ow. + This setting is shared by both USB host ports. =20 required: - compatible @@ -42,4 +81,5 @@ examples: clocks =3D <&clk USBD_GATE>; nuvoton,sys =3D <&sys>; #phy-cells =3D <0>; + nuvoton,rcalcode =3D <7 7>; }; --=20 2.43.0 From nobody Fri Sep 25 10:37:07 2026 Received: from mail-pl1-f169.google.com (mail-pl1-f169.google.com [209.85.214.169]) (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 707653515E7 for ; Mon, 14 Sep 2026 03:19:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789355967; cv=none; b=T393s7w6x4zeJ97fQmDwmm9o0/UahMrpAH94WU4X+EOHmI+c7oRhFo2ahifG/8p6JiyV2yJ7lTcrSDmRHfoZDhgEcna4YP3MDXPwvEGewZ3Tu4ZuEJhqK/rd/QG+Hkw7aMRrLCne7dwCQPJHJlqfjciCcfDE7T9VRIEupBUAkdE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789355967; c=relaxed/simple; bh=axsBfJKc8oG5HoXuwFL3eDZHYWq1TE3XvrLzqiJRRJE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QBPWyOSK14NP+N6Ha0yHn/MD4VnYoHR0uYnjEjRyZZcBdwyaP9JtIuKM1nxYVge4iK1pYGGXk7Zkj5ptLVJL5TgpOsAr5/b7qPYzG46Jh8KeXeebbdkrixTW/NZzESdSRzqv4Gi1J5Ols13ry9ZWtspj6QC26kTFfSK+BByJ/Cc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=dUlUw/zT; arc=none smtp.client-ip=209.85.214.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dUlUw/zT" Received: by mail-pl1-f169.google.com with SMTP id d9443c01a7336-2caced6038eso26206025ad.0 for ; Sun, 13 Sep 2026 20:19:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789355953; x=1789960753; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=0lFtXijizYAouWVN9+dy0kDOQ2hTGkK/90hktZxmu1c=; b=dUlUw/zTShJ4Yog0a9olOUfWcAEDQ6LsE7nktclyzH7LJBjioIFumqPUk4V0ED7jaY fsolDRmcLVpITl6EhnLXF6GIBAaTsR9Orf/uikgu8dZchlQei8vSIZXmqngxHGi4n0E7 yh/vwVaCUWzgJCBy5wwyxOJ6ar9s1e8BIaK4176qpQcsO8EyjbWkAQjOVNUty17T4J6K K3anA8ugksma00exYWluX2tkb89pCBJi4Xwy8cU0K6IIUREcCvzdWvzfa9AGAkdKOMMI pekZ3vNbPX2Drm0iWSfdevcgRXkHO1YWdNp39knI+kKqXjN2ByNc9Db1E6hcuhubgmKe cVHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789355953; x=1789960753; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=0lFtXijizYAouWVN9+dy0kDOQ2hTGkK/90hktZxmu1c=; b=RTwhU0BcxVJRGdCw5jg+UAJ2v3/msUaMBtqG00VChtT/g/qzyL+y+NeHq+RySxRFjo 0GN8UY/sJBwj5P8TObkqJ3DlRpYSI1GCqi+xIpgaz+j1gcvjp9AQMOyhxxPvVWw1NY1J tQeU7gpG2WabdV2b4rVtuYTOofRRUIwpUN7heqrxmkh33afZTCxXQcjJiyNpHTdaz8EZ ZxQHGXWe4ZO2pFJTwFHGQkTIPby/+WkmiIXf2EXjvKYiUuE0omHHtHw9PoUITOBAZ8gT iffvFfs6ywSXvAHPmhSo8QiP1BYlfpuzAa7ES+Rr51j/zcd19SOVAwVartizI3LFnioy K1Fg== X-Forwarded-Encrypted: i=1; AKwUvBwmUqS2Ljw6LlnD4hjyUrpILFbQ7bDrOLyMNywZEAV7PSGNNjC4gz3va/D/Lv1PIRSBUMviSba91oGVKUY=@vger.kernel.org X-Gm-Message-State: AFuF++mFae+zDPOwPC4O5kTokAe/ZoDcmuqPlhsmQ94EyvFj63Y19EyV NkS2M+qrFq+/WTWlH1bvJ8s0hlLwbqJc9YF6+/L/hJ7odqNbUoeqiZa1 X-Gm-Gg: AYBFou1oXdioEMe5oSFlZtcuCMdXj3yvmvCXkmQsCFx5fLgcuGNHX65QT6YBa7G9LMx k58TtHMMWF5KojNkDTj9YpIClumeO/LUiFFTTXj/S2i/Iqf4+5OQwKMXBYgHy/wLXSikSjWcADF 25TlCG/ae8Xefg5d/jbr79kRl51xTOhH9n6nzwHrLwX1Fuw7J+yAhIVwhh6TwFwZ0j29xqs8tFC 39JRE0agjsIiirp+BAnuZi3QPOkuIW2ISBIbIgL40GDlf0HkmhqnUUkz0QlNMzXRQ2TFYV/Jl5B EoCnrkJrkeie9tlAzL16GPaHMx8IoJr5CdfDTzp1MjxfJAGqgleIDAB3F5NQMWUJAPFqIzeiyYE aR6G1v5/Vkkp3nx8u0V00/5ONY/z6VjqYJ/2cJpfFhZ49no6DbjgN1eXRX9WGmxeKpSnER8t5H9 mn/NZdwV1m4CqjQZW9PYJGfWfvrCx31KnvH3V8TvQLUi1RzVW8VH+PgsfO+tilRaMfPRKyeIVYR QFB3r2rCS3zKhhhSp5c2cWdNJU3oJ24w5T4/UYrgF1riNVjk1yAwTS1y0JokNw= X-Received: by 2002:a17:903:38d0:b0:2cf:6e5d:23e9 with SMTP id d9443c01a7336-2dd5f16b17bmr58734135ad.14.1789355953180; Sun, 13 Sep 2026 20:19:13 -0700 (PDT) Received: from localhost.localdomain (60-250-196-139.hinet-ip.hinet.net. [60.250.196.139]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2dd2cfc2d3bsm41355145ad.48.2026.09.13.20.19.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:19:12 -0700 (PDT) From: Joey Lu To: Vinod Koul , Neil Armstrong Cc: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Arnd Bergmann , Catalin Marinas , Jacky Huang , Shan-Chun Hung , Hui-Ping Chen , Joey Lu , linux-phy@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Joey Lu Subject: [PATCH v5 2/3] arm64: dts: nuvoton: ma35d1: add USB controllers and dual-port PHY node Date: Mon, 14 Sep 2026 11:18:58 +0800 Message-ID: <20260914031859.385224-3-a0987203069@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260914031859.385224-1-a0987203069@gmail.com> References: <20260914031859.385224-1-a0987203069@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add the USB subsystem nodes for the MA35D1 SoC and boards: - usb_phy: standalone PHY node with #phy-cells =3D <1>, covering both the OTG port (PHY0, index 0) and the host-only port (PHY1, index 1). Uses nuvoton,sys phandle and HUSBH0_GATE clock per the binding. - usb (DWC2 gadget, USB0): phys =3D <&usb_phy 0>, dr_mode =3D peripheral. - ehci0/ohci0 (USB0 host): phys =3D <&usb_phy 0>, companion pairing. - ehci1/ohci1 (USB1 host): phys =3D <&usb_phy 1>. Board files (ma35d1-som-256m.dts, ma35d1-iot-512m.dts) add pinctrl for VBUSVLD, PWREN and OVC signals and enable all USB nodes. Signed-off-by: Joey Lu --- .../boot/dts/nuvoton/ma35d1-iot-512m.dts | 36 ++++++++++ .../boot/dts/nuvoton/ma35d1-som-256m.dts | 36 ++++++++++ arch/arm64/boot/dts/nuvoton/ma35d1.dtsi | 65 +++++++++++++++++++ 3 files changed, 137 insertions(+) diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts b/arch/arm64/b= oot/dts/nuvoton/ma35d1-iot-512m.dts index 78534d613486..0a068abda6e0 100644 --- a/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts +++ b/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts @@ -97,6 +97,16 @@ pinctrl_uart14: uart14-pins { power-source =3D <1>; }; }; + + hsusb { + pinctrl_hsusb: hsusb-pins { + nuvoton,pins =3D <5 15 1>, /* VBUSVLD */ + <11 12 9>, /* PWREN */ + <11 13 9>; /* OVC */ + bias-disable; + power-source =3D <1>; + }; + }; }; =20 &uart0 { @@ -151,3 +161,29 @@ eth_phy1: ethernet-phy@1 { reg =3D <1>; }; }; + +&usb_phy { + pinctrl-names =3D "default"; + pinctrl-0 =3D <&pinctrl_hsusb>; + status =3D "okay"; +}; + +&usb { + status =3D "okay"; +}; + +&ehci0 { + status =3D "okay"; +}; + +&ehci1 { + status =3D "okay"; +}; + +&ohci0 { + status =3D "okay"; +}; + +&ohci1 { + status =3D "okay"; +}; diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts b/arch/arm64/b= oot/dts/nuvoton/ma35d1-som-256m.dts index a029b660e8dc..7f1e6d2a1fc2 100644 --- a/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts +++ b/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts @@ -100,6 +100,16 @@ pinctrl_uart16: uart16-pins { power-source =3D <1>; }; }; + + hsusb { + pinctrl_hsusb: hsusb-pins { + nuvoton,pins =3D <5 15 1>, /* VBUSVLD */ + <11 12 9>, /* PWREN */ + <11 13 9>; /* OVC */ + bias-disable; + power-source =3D <1>; + }; + }; }; =20 &uart0 { @@ -153,3 +163,29 @@ eth_phy1: ethernet-phy@1 { reg =3D <1>; }; }; + +&usb_phy { + pinctrl-names =3D "default"; + pinctrl-0 =3D <&pinctrl_hsusb>; + status =3D "okay"; +}; + +&usb { + status =3D "okay"; +}; + +&ehci0 { + status =3D "okay"; +}; + +&ehci1 { + status =3D "okay"; +}; + +&ohci0 { + status =3D "okay"; +}; + +&ohci1 { + status =3D "okay"; +}; diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi b/arch/arm64/boot/dts/= nuvoton/ma35d1.dtsi index 7228ad4735b5..72a1659207fa 100644 --- a/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi +++ b/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi @@ -76,6 +76,14 @@ IRQ_TYPE_LEVEL_LOW)>, /* Virtual */ interrupt-parent =3D <&gic>; }; =20 + usb_phy: usb-phy { + compatible =3D "nuvoton,ma35d1-usb2-phy"; + clocks =3D <&clk HUSBH0_GATE>; + nuvoton,sys =3D <&sys>; + #phy-cells =3D <1>; + status =3D "disabled"; + }; + soc { compatible =3D "simple-bus"; #address-cells =3D <2>; @@ -431,5 +439,62 @@ mdio1: mdio { #size-cells =3D <0>; }; }; + + usb: usb@40200000 { + compatible =3D "snps,dwc2"; + reg =3D <0x0 0x40200000 0x0 0x1000>; + interrupts =3D ; + clocks =3D <&clk USBD_GATE>; + clock-names =3D "otg"; + phys =3D <&usb_phy 0>; + phy-names =3D "usb2-phy"; + dr_mode =3D "peripheral"; + g-np-tx-fifo-size =3D <16>; + g-rx-fifo-size =3D <0x100>; + g-tx-fifo-size =3D <256 256 64 64 64 32 32 32>; + status =3D "disabled"; + }; + + ehci0: usb@40140000 { + compatible =3D "generic-ehci"; + reg =3D <0x0 0x40140000 0x0 0x1000>; + interrupts =3D ; + clocks =3D <&clk HUSBH0_GATE>; + phys =3D <&usb_phy 0>; + phy-names =3D "usb"; + companion =3D <&ohci0>; + status =3D "disabled"; + }; + + ehci1: usb@401c0000 { + compatible =3D "generic-ehci"; + reg =3D <0x0 0x401c0000 0x0 0x1000>; + interrupts =3D ; + clocks =3D <&clk HUSBH1_GATE>; + phys =3D <&usb_phy 1>; + phy-names =3D "usb"; + companion =3D <&ohci1>; + status =3D "disabled"; + }; + + ohci0: usb@40150000 { + compatible =3D "generic-ohci"; + reg =3D <0x0 0x40150000 0x0 0x1000>; + interrupts =3D ; + clocks =3D <&clk HUSBH0_GATE>; + phys =3D <&usb_phy 0>; + phy-names =3D "usb"; + status =3D "disabled"; + }; + + ohci1: usb@401d0000 { + compatible =3D "generic-ohci"; + reg =3D <0x0 0x401d0000 0x0 0x1000>; + interrupts =3D ; + clocks =3D <&clk HUSBH1_GATE>; + phys =3D <&usb_phy 1>; + phy-names =3D "usb"; + status =3D "disabled"; + }; }; }; --=20 2.43.0 From nobody Fri Sep 25 10:37:07 2026 Received: from mail-pj2-f13.google.com (mail-pj2-f13.google.com [74.125.227.141]) (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 89A18348C4B for ; Mon, 14 Sep 2026 03:19:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789355970; cv=none; b=ZdWLpPjhEjFWG3VwVxdEQnjO7xtOSQZ7nsGv1I9jFKbzjyeHgiI7LPvZZUayOoW7UfwCazWfU4yurKBjMaPhOpqYVcXeTT3BlMGCSgkegJ1lGlrR54EasfdYXtrEdXlKIpqEamWY+1n3a16h6RZPnihauN5M6YymwAodpgwRvB4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789355970; c=relaxed/simple; bh=1BxE5gIGu1prh9otjFD2YEZ87CHMHskKJ5D9eLd1z1I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ctlDzepzgkFOtjzk5HUqbd7z2+vHb8Wmq6UKaEg7CPuLLZbpFNwQmlmVNIm4oI37UAQtKFOg3DQT9Qc4+gGiSn7mR9UCeRg10tBxwaXGAK+0lX7THEddE/q1JsmgQjVEFDqKlt6lk/WIDW6Zjh97ZTzmHcSRQbQLlVTR1EOzr14= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=GAmi70Rr; arc=none smtp.client-ip=74.125.227.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="GAmi70Rr" Received: by mail-pj2-f13.google.com with SMTP id d9443c01a7336-2d8fb334ddcso16654735ad.0 for ; Sun, 13 Sep 2026 20:19:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789355957; x=1789960757; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=OtN5FPSKCGNs5pMa1pYq9igP2vP81fNP/piE94f5ogU=; b=GAmi70RrKmsf6u+TjrqWwamH9NQMWYUHTGvyv5Nde0jUdyNZYkfd2hNGjueP8rWJ/f Lf7qfYu5mBT4GVQWwiDNoeo1gqYgdL2gL+vJhvoU9oToxsQhUDndB/0bYrIKV+lGTFY1 l+E0gy6xg92NNnYl0r4QBff+8QUmz8PPTAGu6lnlFikqsfzP3Lz9oF0VvMroxplozSAj pQNxcqDzWZI5e9i4IfqjbCyNvAaXVedw3xyQB4zYh2eQ1GehS44vFRWQ5DY1NM+7iToG sFqMSphv7IYuzCLoqSIfqAED6AZu7AWX/JsAHhsUy8eGmxU7ppu30xWM7uEDZ293PoiN C5zg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789355957; x=1789960757; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=OtN5FPSKCGNs5pMa1pYq9igP2vP81fNP/piE94f5ogU=; b=QT2A/5CpdhUShELCAPSwt/WK/6/bGFPX1TK9JXSBTjPDg1W5n8FF8gMAg4dtdI2uMl PafHRMNzsn2pTWfyhZ7jGRO49M9CdjdbhbAIF00n142L4O3agAcRB8wIH4JJ6DhRpMaL YuBJfnodUMX9V8qp55wVTw/QJw7cDjs0t6tUMh+OUXZ8iV05KL3Iw6grLnqDhwtgj2Zz EgFzfdgCVSzuYXwWwo2QZkpo/8n/cmrJXpaeASGu6roaJqfOHcz2P8BmiBjGr67Zj+6Z ezBFq/cRUCh/tEPepUMg6QgaMoTOgpWxr2/4s00P6YDpy/stht6ct6tlkYsUrvbkF3Cc ayRQ== X-Forwarded-Encrypted: i=1; AKwUvByiqPkpBTfZCRvLWRFktU6O6WXMmt+EqBpUYuHEUBIUjVLBcZ/pYN3UXcUlPw2OOH/5ST87lwxvjonZoqY=@vger.kernel.org X-Gm-Message-State: AFuF++mxsE5Vl+UWgdCTvFxOLx/KiDxZs6mLF4AAhbOWrTlvG/SEXxI6 dxBg6tMJ6fKwnARs0h+bhp6KB3frK9S+3ND91hcUZxxq8lN8mMrks+uqgR4YSg== X-Gm-Gg: AYBFou3iu3a2/mjNL9R9/v0o8iadhLdYw8D4CAykpP8SFKrJcJU0MymmyJZqDIlHNiD 5C0gg4ObtLqmjM3zRflLDlIrjxtAR20htxc761fx+LgjW0scMhrAoqEDr0YRGCwI6Qn75E+83RY 4bQwt+QH3N3jLLRwR7wEtAVSGDv+xi/7nTmpB27ckjj1bAEqaLRC+DNyP0MxH8PCqABKA+qPEH8 VqXoWbCFhlRuRRnVwNxhf5/p/h6Sc3PptAv5zCBoUwywL1i1PtqdvYK2D5nT92bmqRiD8of0V6r jLdk/MctmQLe2tvgLNvxgu/zYP1UF8dl2I5yyhBxewFLWrXdIgHosUHAy1qmkQu+PP+EPFGcrFX N7bcsunGlSWVdzsJlP1anWweyeIRl2fW4gYLTxCvnkQuhXH8HnatSJCBgicQvMQwhD9dMQDcuc2 b1EVKWEoKQEX6AfLORlIa/C8fHO6YuZmHYxwq0LqJEal4utepp/d5uYOVU5hQdQ4TpEKyCZWMvV jSiOf3+wsEcv7ApJoXBxbpipLE5upPUP6zFt+wnIFlcuHnFGFE7erOCMoIP9e4= X-Received: by 2002:a17:903:2cd:b0:2c9:bf82:dd11 with SMTP id d9443c01a7336-2dd6c5d60f0mr16116055ad.7.1789355957164; Sun, 13 Sep 2026 20:19:17 -0700 (PDT) Received: from localhost.localdomain (60-250-196-139.hinet-ip.hinet.net. [60.250.196.139]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2dd2cfc2d3bsm41355145ad.48.2026.09.13.20.19.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 20:19:16 -0700 (PDT) From: Joey Lu To: Vinod Koul , Neil Armstrong Cc: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Arnd Bergmann , Catalin Marinas , Jacky Huang , Shan-Chun Hung , Hui-Ping Chen , Joey Lu , linux-phy@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Joey Lu Subject: [PATCH v5 3/3] phy: nuvoton: phy-ma35d1-usb2: extend to dual-port with OTG support Date: Mon, 14 Sep 2026 11:18:59 +0800 Message-ID: <20260914031859.385224-4-a0987203069@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260914031859.385224-1-a0987203069@gmail.com> References: <20260914031859.385224-1-a0987203069@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" PHY0 and PHY1 use the same power-on/reset sequence in USBPMISCR, with PHY1 control bits shifted 16 positions relative to PHY0. A separate driver for PHY1 would duplicate this logic, so the existing driver is extended to manage both ports. The original driver polled only DEVCKSTB after releasing PHY0 from reset. When USB0 operates in host mode (USB ID pin floating or tied high) only HSTCKSTB and CK12MSTB assert; DEVCKSTB never sets. Polling exclusively for DEVCKSTB in host mode causes a 1 ms timeout on every phy_init() call from the EHCI driver. The init callback is changed to accept either host-mode or device-mode clock stability, whichever asserts first. The power_on and power_off callbacks are replaced by a single init callback that handles PHY reset and clock-stable polling, because there is no PHY-specific clock gate on MA35D1; the PHY analog block derives its reference from the HXT crystal. A read-only USB role switch is registered for PHY0 to expose the USB0 role to userspace via the standard role-switch sysfs interface. The .set callback returns -EOPNOTSUPP because the hardware mux is fully automatic with no software override path. When CONFIG_USB_ROLE_SWITCH is not enabled, the registration returns -ENODEV and the driver skips the role switch gracefully without failing probe. Two new optional device-tree properties are implemented: - nuvoton,rcalcode: writes per-port 4-bit resistor calibration trim codes to the RCALCODE field in USBPMISCR. - nuvoton,oc-active-high: sets the UHOVRCURH bit in MISCFCR0 to treat the over-current detect input as active-high. Signed-off-by: Joey Lu --- drivers/phy/nuvoton/phy-ma35d1-usb2.c | 284 +++++++++++++++++++------- 1 file changed, 210 insertions(+), 74 deletions(-) diff --git a/drivers/phy/nuvoton/phy-ma35d1-usb2.c b/drivers/phy/nuvoton/ph= y-ma35d1-usb2.c index 9a459b700ed4..2c60be0ee50f 100644 --- a/drivers/phy/nuvoton/phy-ma35d1-usb2.c +++ b/drivers/phy/nuvoton/phy-ma35d1-usb2.c @@ -1,11 +1,16 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2024 Nuvoton Technology Corp. + * Nuvoton MA35D1 USB 2.0 PHY driver + * + * Supports PHY0 (USB0 OTG port, shared between DWC2 gadget and EHCI0/OHCI= 0) + * and PHY1 (USB1 host-only port, used by EHCI1/OHCI1). The hardware mux on + * PHY0 switches automatically via the USB ID pin. + * + * Copyright (C) 2026 Nuvoton Technology Corp. */ #include #include #include -#include #include #include #include @@ -13,131 +18,262 @@ #include #include #include +#include =20 -/* USB PHY Miscellaneous Control Register */ -#define MA35_SYS_REG_USBPMISCR 0x60 -#define PHY0POR BIT(0) /* PHY Power-On Reset Control Bit */ -#define PHY0SUSPEND BIT(1) /* PHY Suspend; 0: suspend, 1: operaion */ -#define PHY0COMN BIT(2) /* PHY Common Block Power-Down Control */ -#define PHY0DEVCKSTB BIT(10) /* PHY 60 MHz UTMI clock stable bit */ +#define MA35_SYS_PWRONOTP 0x04 +#define PWRONOTP_USBP0ID BIT(16) + +#define MA35_SYS_USBPMISCR 0x60 +#define USBPMISCR_PHY_POR(n) BIT(0 + (n) * 16) +#define USBPMISCR_PHY_SUSPEND(n) BIT(1 + (n) * 16) +#define USBPMISCR_PHY_COMN(n) BIT(2 + (n) * 16) +#define USBPMISCR_PHY_HSTCKSTB(n) BIT(8 + (n) * 16) +#define USBPMISCR_PHY_CK12MSTB(n) BIT(9 + (n) * 16) +#define USBPMISCR_PHY_DEVCKSTB(n) BIT(10 + (n) * 16) +/* Mask for control bits (POR, SUSPEND, COMN) */ +#define USBPMISCR_PHY_CTL_MASK(n) (0x7u << ((n) * 16)) +/* Host-mode ready */ +#define USBPMISCR_PHY_HOST_READY(n) (USBPMISCR_PHY_SUSPEND(n) | \ + USBPMISCR_PHY_HSTCKSTB(n) | \ + USBPMISCR_PHY_CK12MSTB(n)) +/* Device-mode ready */ +#define USBPMISCR_PHY_DEV_READY(n) (USBPMISCR_PHY_SUSPEND(n) | \ + USBPMISCR_PHY_DEVCKSTB(n)) +/* RCALCODE: 4-bit resistor trim */ +#define USBPMISCR_RCAL_SHIFT(n) (12 + (n) * 16) +#define USBPMISCR_RCAL_MASK(n) GENMASK(USBPMISCR_RCAL_SHIFT(n) + 3, \ + USBPMISCR_RCAL_SHIFT(n)) + +#define MA35_SYS_MISCFCR0 0x70 +/* USB host over-current detect polarity (shared, both ports) */ +#define MISCFCR0_UHOVRCURH BIT(12) + +#define MA35_PHY_NUM 2 + +struct ma35_phy_port { + struct phy *phy; + unsigned int idx; +}; =20 struct ma35_usb_phy { - struct clk *clk; struct device *dev; struct regmap *sysreg; + struct ma35_phy_port port[MA35_PHY_NUM]; + struct usb_role_switch *role_sw; }; =20 -static int ma35_usb_phy_power_on(struct phy *phy) +static int ma35_usb_phy_init(struct phy *phy) { - struct ma35_usb_phy *p_phy =3D phy_get_drvdata(phy); + struct ma35_phy_port *port =3D phy_get_drvdata(phy); + struct ma35_usb_phy *p =3D container_of(port - port->idx, + struct ma35_usb_phy, port[0]); + unsigned int n =3D port->idx; unsigned int val; int ret; =20 - ret =3D clk_prepare_enable(p_phy->clk); - if (ret < 0) { - dev_err(p_phy->dev, "Failed to enable PHY clock: %d\n", ret); - return ret; - } + regmap_read(p->sysreg, MA35_SYS_USBPMISCR, &val); =20 - regmap_read(p_phy->sysreg, MA35_SYS_REG_USBPMISCR, &val); - if (val & PHY0SUSPEND) { - /* - * USB PHY0 is in operation mode already - * make sure USB PHY 60 MHz UTMI Interface Clock ready - */ - ret =3D regmap_read_poll_timeout(p_phy->sysreg, MA35_SYS_REG_USBPMISCR, = val, - val & PHY0DEVCKSTB, 10, 1000); - if (ret =3D=3D 0) - return 0; - } + if (val & USBPMISCR_PHY_SUSPEND(n)) + return 0; =20 - /* - * reset USB PHY0. - * wait until USB PHY0 60 MHz UTMI Interface Clock ready - */ - regmap_update_bits(p_phy->sysreg, MA35_SYS_REG_USBPMISCR, 0x7, (PHY0POR |= PHY0SUSPEND)); + regmap_update_bits(p->sysreg, MA35_SYS_USBPMISCR, + USBPMISCR_PHY_CTL_MASK(n), + USBPMISCR_PHY_POR(n) | USBPMISCR_PHY_SUSPEND(n)); udelay(20); =20 - /* make USB PHY0 enter operation mode */ - regmap_update_bits(p_phy->sysreg, MA35_SYS_REG_USBPMISCR, 0x7, PHY0SUSPEN= D); + regmap_update_bits(p->sysreg, MA35_SYS_USBPMISCR, + USBPMISCR_PHY_CTL_MASK(n), + USBPMISCR_PHY_SUSPEND(n)); =20 - /* make sure USB PHY 60 MHz UTMI Interface Clock ready */ - ret =3D regmap_read_poll_timeout(p_phy->sysreg, MA35_SYS_REG_USBPMISCR, v= al, - val & PHY0DEVCKSTB, 10, 1000); - if (ret =3D=3D -ETIMEDOUT) { - dev_err(p_phy->dev, "Check PHY clock, Timeout: %d\n", ret); - clk_disable_unprepare(p_phy->clk); + if (n =3D=3D 0) { + ret =3D regmap_read_poll_timeout(p->sysreg, MA35_SYS_USBPMISCR, + val, + ((val & USBPMISCR_PHY_HOST_READY(0)) =3D=3D + USBPMISCR_PHY_HOST_READY(0)) || + ((val & USBPMISCR_PHY_DEV_READY(0)) =3D=3D + USBPMISCR_PHY_DEV_READY(0)), + 10, 1000); + } else { + ret =3D regmap_read_poll_timeout(p->sysreg, MA35_SYS_USBPMISCR, + val, + (val & USBPMISCR_PHY_HOST_READY(n)) =3D=3D + USBPMISCR_PHY_HOST_READY(n), + 10, 1000); + } + + if (ret) { + dev_err(p->dev, "USB PHY%u clock not stable (USBPMISCR=3D0x%08x)\n", + n, val); return ret; } =20 return 0; } =20 -static int ma35_usb_phy_power_off(struct phy *phy) +static const struct phy_ops ma35_usb_phy_ops =3D { + .init =3D ma35_usb_phy_init, + .owner =3D THIS_MODULE, +}; + +static int ma35_role_sw_set(struct usb_role_switch *sw, enum usb_role role) +{ + return -EOPNOTSUPP; +} + +static enum usb_role ma35_role_sw_get(struct usb_role_switch *sw) +{ + struct ma35_usb_phy *p =3D usb_role_switch_get_drvdata(sw); + u32 val; + + regmap_read(p->sysreg, MA35_SYS_PWRONOTP, &val); + + return (val & PWRONOTP_USBP0ID) ? USB_ROLE_HOST : USB_ROLE_DEVICE; +} + +static int ma35_role_switch_init(struct platform_device *pdev, + struct ma35_usb_phy *p) { - struct ma35_usb_phy *p_phy =3D phy_get_drvdata(phy); + struct usb_role_switch_desc sw_desc =3D {0}; + + sw_desc.set =3D ma35_role_sw_set; + sw_desc.get =3D ma35_role_sw_get; + sw_desc.allow_userspace_control =3D true; + sw_desc.driver_data =3D p; + sw_desc.fwnode =3D dev_fwnode(&pdev->dev); + + p->role_sw =3D usb_role_switch_register(&pdev->dev, &sw_desc); + if (IS_ERR(p->role_sw)) { + if (PTR_ERR(p->role_sw) =3D=3D -ENODEV) { + p->role_sw =3D NULL; + return 0; + } + return dev_err_probe(&pdev->dev, PTR_ERR(p->role_sw), + "failed to register role switch\n"); + } =20 - clk_disable_unprepare(p_phy->clk); return 0; } =20 -static const struct phy_ops ma35_usb_phy_ops =3D { - .power_on =3D ma35_usb_phy_power_on, - .power_off =3D ma35_usb_phy_power_off, - .owner =3D THIS_MODULE, -}; +static void ma35_role_switch_exit(struct ma35_usb_phy *p) +{ + if (p->role_sw) { + usb_role_switch_unregister(p->role_sw); + p->role_sw =3D NULL; + } +} + +static struct phy *ma35_usb_phy_xlate(struct device *dev, + const struct of_phandle_args *args) +{ + struct ma35_usb_phy *p =3D dev_get_drvdata(dev); + unsigned int idx; + + if (args->args_count =3D=3D 0) + idx =3D 0; + else + idx =3D args->args[0]; + + if (idx >=3D MA35_PHY_NUM) + return ERR_PTR(-EINVAL); + + return p->port[idx].phy; +} =20 static int ma35_usb_phy_probe(struct platform_device *pdev) { struct phy_provider *provider; - struct ma35_usb_phy *p_phy; - struct phy *phy; + struct ma35_usb_phy *p; + struct clk *clk; + int n, ret; + u32 code; =20 - p_phy =3D devm_kzalloc(&pdev->dev, sizeof(*p_phy), GFP_KERNEL); - if (!p_phy) + p =3D devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); + if (!p) return -ENOMEM; =20 - p_phy->dev =3D &pdev->dev; - platform_set_drvdata(pdev, p_phy); + p->dev =3D &pdev->dev; + platform_set_drvdata(pdev, p); + + p->sysreg =3D syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "nuvoton,sys"); + if (IS_ERR(p->sysreg)) + return dev_err_probe(&pdev->dev, PTR_ERR(p->sysreg), + "failed to get SYS regmap\n"); =20 - p_phy->sysreg =3D syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "nuv= oton,sys"); - if (IS_ERR(p_phy->sysreg)) - return dev_err_probe(&pdev->dev, PTR_ERR(p_phy->sysreg), - "Failed to get SYS registers\n"); + clk =3D devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(clk), + "failed to get clock\n"); =20 - p_phy->clk =3D of_clk_get(pdev->dev.of_node, 0); - if (IS_ERR(p_phy->clk)) - return dev_err_probe(&pdev->dev, PTR_ERR(p_phy->clk), - "failed to find usb_phy clock\n"); + for (n =3D 0; n < MA35_PHY_NUM; n++) { + if (of_property_read_u32_index(pdev->dev.of_node, + "nuvoton,rcalcode", n, &code)) + continue; =20 - phy =3D devm_phy_create(&pdev->dev, NULL, &ma35_usb_phy_ops); - if (IS_ERR(phy)) - return dev_err_probe(&pdev->dev, PTR_ERR(phy), "Failed to create PHY\n"); + if (code > 15) + return dev_err_probe(&pdev->dev, -EINVAL, + "rcalcode[%d] %u out of range (0-15)\n", + n, code); =20 - phy_set_drvdata(phy, p_phy); + regmap_update_bits(p->sysreg, MA35_SYS_USBPMISCR, + USBPMISCR_RCAL_MASK(n), + code << USBPMISCR_RCAL_SHIFT(n)); + } + + if (of_property_read_bool(pdev->dev.of_node, "nuvoton,oc-active-high")) + regmap_update_bits(p->sysreg, MA35_SYS_MISCFCR0, + MISCFCR0_UHOVRCURH, MISCFCR0_UHOVRCURH); + + for (n =3D 0; n < MA35_PHY_NUM; n++) { + p->port[n].idx =3D n; + + p->port[n].phy =3D devm_phy_create(&pdev->dev, pdev->dev.of_node, + &ma35_usb_phy_ops); + if (IS_ERR(p->port[n].phy)) + return dev_err_probe(&pdev->dev, PTR_ERR(p->port[n].phy), + "failed to create PHY%d\n", n); + + phy_set_drvdata(p->port[n].phy, &p->port[n]); + } + + ret =3D ma35_role_switch_init(pdev, p); + if (ret) + return ret; =20 - provider =3D devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlat= e); - if (IS_ERR(provider)) + provider =3D devm_of_phy_provider_register(&pdev->dev, ma35_usb_phy_xlate= ); + if (IS_ERR(provider)) { + ma35_role_switch_exit(p); return dev_err_probe(&pdev->dev, PTR_ERR(provider), - "Failed to register PHY provider\n"); + "failed to register PHY provider\n"); + } + return 0; } =20 +static void ma35_usb_phy_remove(struct platform_device *pdev) +{ + struct ma35_usb_phy *p =3D platform_get_drvdata(pdev); + + ma35_role_switch_exit(p); +} + static const struct of_device_id ma35_usb_phy_of_match[] =3D { - { .compatible =3D "nuvoton,ma35d1-usb2-phy", }, - { }, + { .compatible =3D "nuvoton,ma35d1-usb2-phy" }, + { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, ma35_usb_phy_of_match); =20 static struct platform_driver ma35_usb_phy_driver =3D { .probe =3D ma35_usb_phy_probe, - .driver =3D { - .name =3D "ma35d1-usb2-phy", - .of_match_table =3D ma35_usb_phy_of_match, + .remove =3D ma35_usb_phy_remove, + .driver =3D { + .name =3D "ma35d1-usb2-phy", + .of_match_table =3D ma35_usb_phy_of_match, }, }; module_platform_driver(ma35_usb_phy_driver); =20 MODULE_DESCRIPTION("Nuvoton ma35d1 USB2.0 PHY driver"); MODULE_AUTHOR("Hui-Ping Chen "); +MODULE_AUTHOR("Joey Lu "); MODULE_LICENSE("GPL"); --=20 2.43.0