From patchwork Tue Jul 16 20:52:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josua Mayer X-Patchwork-Id: 13734912 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EA151C3DA59 for ; Tue, 16 Jul 2024 20:54:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:MIME-Version:Cc:To: In-Reply-To:References:Message-Id:Content-Transfer-Encoding:Content-Type: Subject:Date:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=bnO1br3YbOnp05EKB+1CCxppNWloB0QOTZNpNYg4YjU=; b=zC0kmoSzFAelppdw0wIX/kDIE4 wLPsSV49tGWGgmkVtoSScttg2nPo0o+QgKxVd53ldv2H6vdA/cEXXKpXD8/yG2wdhsNAMkda0o3kb SV68g+3drjGCbIrqU+331ZpS9GRyI9qxp8RM8awLyGQB5+8ew6YWPGcNwlXKRw5V8KXStn0cxSubI 1L7Jscs72zIomfxZFuvX3sgD7WQ1+ds8KXxFvU3ReGBTbjtKyonZEGUTHjY89m357oovKoMJ52myF 9VjFJUx1LVQLYs4M4njkyk+Jg/AV6L95Dgy2DoSzqSOosYif8dnoSYsb/KFeX1vPzKNfCkKDav2gI uoqzB04g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sTpBa-0000000Bk0O-08u7; Tue, 16 Jul 2024 20:54:10 +0000 Received: from mail-northeuropeazlp170120003.outbound.protection.outlook.com ([2a01:111:f403:c200::3] helo=DU2PR03CU002.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sTpAR-0000000BjXu-1fta; Tue, 16 Jul 2024 20:53:02 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=hLFV+kO6hUFNLOgqv4sejJEmBsJBXUw3qaPdCy8blBNWOLuL2TVuYR3voPta1V9sZr2d5iNdFi7rUiTaMU9qhXqoDM9EDqjCVcy2oXOqG/9+bRupUzvxcNZQASBN5oZMd5zbOybQR3nHmi8gDvEAod/OkrXx1ooM28sLrRIRfvWoU2yVe3pEYNyinGU/uTJypRnj1zGTFzIPMjAmdOKLIU59vqJr7MFiDQETSgi2xD9Dp+LWiY5pdKt4mPxuMEtIuk6c0IuTbvosxPjWj7QLCVbcRw7n7okucgQsmuO4KLWfw3alS1Srutfrh4GAI15hGKMsz1MToWnH8bn020jX5Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=bnO1br3YbOnp05EKB+1CCxppNWloB0QOTZNpNYg4YjU=; b=hU3A8Dijw3Uv1BJYUz9iSt/mb7OrTYe8Xlj0UFAVVHbBXQt0NPDinGOvnnf2jrbmY8xamBkl1MtnfrNPANDrnC0Cs/bfIT+2Mt0yuLdFCDjjngkff6evygE6df9/4uK52UY2zsruJd+Am1eYjs5r8SR8zb809bgVoArNqShMXBIbESDG66X5M1Yb7dr/8Shra1gkZkETXHtMun35bzpdU1Kwr8+R9fBJ4xmC9mOdMsRaVhI7RisVryUiJIMaX0UtrD/1+HCYB+4pjPy6JJsqUvDNq2ZsXSw2lSFMuEmNiaj+7q9PdQObDi1OzCrKcI1+Uo+fLBgwU4k/QzYvlmZICg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=solid-run.com; dmarc=pass action=none header.from=solid-run.com; dkim=pass header.d=solid-run.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=solidrn.onmicrosoft.com; s=selector1-solidrn-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=bnO1br3YbOnp05EKB+1CCxppNWloB0QOTZNpNYg4YjU=; b=KO696+jaQZte5Zb9y/NN6R5JZnvlLNuDN2skmlteYIRvu1PYdfes9faCpjie/5qf+jJIEQbrIC5Lh5TzPRH5oscAnK1vCxrJ0Ez2rwD+2dyW51MoWAw0ltj+D4VtfMIma++F6Kyurl2vZyroEZx8iYV0lWv+PzNuOYS3F2BsMhA= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=solid-run.com; Received: from AM9PR04MB7586.eurprd04.prod.outlook.com (2603:10a6:20b:2d5::17) by AM8PR04MB7907.eurprd04.prod.outlook.com (2603:10a6:20b:237::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7762.29; Tue, 16 Jul 2024 20:52:45 +0000 Received: from AM9PR04MB7586.eurprd04.prod.outlook.com ([fe80::c04e:8a97:516c:5529]) by AM9PR04MB7586.eurprd04.prod.outlook.com ([fe80::c04e:8a97:516c:5529%3]) with mapi id 15.20.7762.027; Tue, 16 Jul 2024 20:52:45 +0000 From: Josua Mayer Date: Tue, 16 Jul 2024 22:52:39 +0200 Subject: [PATCH RFC v2 3/4] phy: mvebu-cp110-utmi: add support for armada-380 utmi phys Message-Id: <20240716-a38x-utmi-phy-v2-3-dae3a9c6ca3e@solid-run.com> References: <20240716-a38x-utmi-phy-v2-0-dae3a9c6ca3e@solid-run.com> In-Reply-To: <20240716-a38x-utmi-phy-v2-0-dae3a9c6ca3e@solid-run.com> To: Vinod Koul , Kishon Vijay Abraham I , Andrew Lunn , Gregory Clement , Sebastian Hesselbarth , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Yazan Shhady , linux-phy@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, Josua Mayer X-Mailer: b4 0.12.4 X-ClientProxiedBy: FR0P281CA0125.DEUP281.PROD.OUTLOOK.COM (2603:10a6:d10:97::20) To AM9PR04MB7586.eurprd04.prod.outlook.com (2603:10a6:20b:2d5::17) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AM9PR04MB7586:EE_|AM8PR04MB7907:EE_ X-MS-Office365-Filtering-Correlation-Id: 97650bb0-a8ef-41bc-02ee-08dca5d93e5b X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|52116014|1800799024|376014|7416014|38350700014; X-Microsoft-Antispam-Message-Info: =?utf-8?q?XfWk3X2Wdlgem2jUqpL9yNOTTseHdX0?= =?utf-8?q?1CS3A+Xik279Y+WvlPiRAfonoBFLfMJulRZ/rBd1P+0BEJDcD4zAQif6VeRwOt9Yv?= =?utf-8?q?fu/BC/JhsfICdTFoGUA9ZYgd17JpVDts4dbqcTOWyRuXBsm6KE6EB2UVFLUPWWFiP?= =?utf-8?q?mswlIVHMm8CXNavgx12Qmo89rOUUsEElr9ANeXZh0K0d1PFPpoKZnpQyp+r4UiY2x?= =?utf-8?q?gNbsmzNYAbOP5v60dh9DTUaohipyco1rkXl3q6ft034H6mn9BOqZvKwi2J/a3sPPk?= =?utf-8?q?4gkp5Fs9ZBqRRzl+t5rhGlP+u1a/2XD131r2q/OiUWNU5miJABq7tAZz9inlml2c5?= =?utf-8?q?eyZOfcUQB+MZzpPABLLTJ//0vM7uK1sqivVGkh4ru5CwSCjeesjJ0edCq2YsdYdxX?= =?utf-8?q?SFv0QAVIGoMgTUZ2w5HkDfTOsnhrSxge2T5H62LVNaQoe5y5jQchtqdB71AWwywXG?= =?utf-8?q?5QU3YPD3ofFCZtf3XaPsgNDNppf/NyLbWRhfWgSqUOOVx2nDuuZvASBoblLVbyMwK?= =?utf-8?q?lCqHCG7H+sKOmp/EUXnZX9E5PITvtfvURtVJlIzjL9gUHDvSa/z3Y7Dz9lPDeGduU?= =?utf-8?q?ZXLkC5wRq9VtihrrYT3VmlVP9pQySlBJehNHwabx1c3qJ3IdZFz+Pqq6Z+ZrbjkTZ?= =?utf-8?q?MCbOT9G3RW314A7KWsluXjGrNMBRdGeIiLUVPqNJIsHBcdBW7QCbM07dPRJ3sgkrx?= =?utf-8?q?95+Ed59tEfEx7yRZZnewSzsV5YMVKAy79ioH7d4trExmIkJA8hLtgHn6ECAxyXHp9?= =?utf-8?q?c2oNA40UqxL1qgnhvVS8n2xbk91guHMbsrxsGjG+LSr1tsdDuabiEZgxScjnVPRVB?= =?utf-8?q?Irz8DGBLxIwqK3De2gbSXy+Uo56480phbt696zPReUllxVM1xLF3fBj3aKVgVjKal?= =?utf-8?q?0EaWTwBGscysl15SYWgK1MPD+2GOxHhAZ6hUQVml4KJ9ihvUQmLiFZtIRiLbbyrf8?= =?utf-8?q?6+EmD0pHbIr1jmgD/Je8Kh8O9JvGx0qmrzcSsqaQWBdI20KwDAWiqID3mAGqHB72r?= =?utf-8?q?MtK68mGm5bJLzLo6a9qeEN8PKT+q3XT4T32sNqF8MvLr0OF8J1wCw5Z64Kn3AJFAq?= =?utf-8?q?Qna4O8AfMhLn6JGPCs+wa3gQBKAwX5dSsHpdOsHGWB6M77etUrDz6nKbfR+enfFiH?= =?utf-8?q?Tbv0+zxiKJSQ5k+s0R5boELpAuqv2EY2Crklk61pECOz79O1luXI1UD5aCSjTBXT8?= =?utf-8?q?H+mG8uGKrItBuy8zM9zRUyJRSwqHUXz0FGwm5E1q1BrOCS8zqkgIG/ZQnjY2sOUvX?= =?utf-8?q?GUM1g1E/y1BzhuHzE6CMEnCCkSltvF7dsD8i/Do9sdzcAqVTTK8SlRwcGM1yGdxgY?= =?utf-8?q?ljmGrBMuHlslRGDKhYW+l2PQ6nKV3Av6ZA=3D=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:AM9PR04MB7586.eurprd04.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(52116014)(1800799024)(376014)(7416014)(38350700014);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?q?v5et9+o9Big6h8A4a/gUpCnA4l8a?= =?utf-8?q?UhQNc0k4MfXneU1Qgo38qncv+Z4B7MhzTzvOyECPh7Wz7zkR4EHwpheB8bMZXRopo?= =?utf-8?q?Q4V/pmbxMqS3x5ryREmuVrxKKeCGVW0aKxDAcFQW6OpXAJ7T8H3Gl51ayudkF9MY7?= =?utf-8?q?En/qF1EbZBjMOINaVT4knxYwJx5uK6e+9BtKrIhjglpkWfrm3Go81uX/3o1Xt5NUk?= =?utf-8?q?y+hqxFWsKJQAt3OAmL5/MIf000cqxee7XaGfQv+Bo5pQNIeL6JbVoYeWZQoDqrdkb?= =?utf-8?q?7lCmMbje5YCqMY5Bcepps1YIaVu+CE/MqisHEdhuna88XPRuvgoGCJf+3vQtWFa3L?= =?utf-8?q?LArl6zd/qWYaLuZadLEStHVCEPjQyfjS6XzbNoNxiQHsyIvQtqWqo7Hal6MGwROXG?= =?utf-8?q?mX4PcLcy98Jxd/kwEQQf31qF/KrcqHxfof3wpuNudpD4vIrtHOw0GMo+wcf3hDO28?= =?utf-8?q?RSr4QDY0tr2PpfrcvRoViWPMPZFENdp7jyLM+3rKZwcotRlYBB6yeQ4ZnSdkm48K0?= =?utf-8?q?21fv5a+xuW8B052VbFAgCzN2gnWx08nUVdrYj57r/IPhzyrYVFJr9hI/WNdGJ6TO+?= =?utf-8?q?FI72SYq2gnKeztH7mVhYM2E0LVkXBsR2U2eoXiIrhy5NqXmcgl2kpVTlAVGthruRU?= =?utf-8?q?DXQWfrRSz/1uZZBJwGWXL658gNjDCmKUr0Z3fipJP6rUjZYkO0t/Y1C7H49eoUNTO?= =?utf-8?q?negnf1mv4bK1O/By138pYTpWZcz3pKC7g5/T356J1hbwDcBHFiVnOcbWmOWIe5syd?= =?utf-8?q?ML6PFHt1eQ0znC3O2IfmJbVWj4KzQoJPaSeuD76gUvI/NQ4ES3VVi3o4d9iRdTREw?= =?utf-8?q?/CCcgXxvzAC8J8YDs7aWODxRW1UgUoV3W1X0cta/mO4o+p5FCSb83JNIjGyaRnlVT?= =?utf-8?q?58pDyHqBc4udPq8AojAUljoo6nbZ6Xgs/FCcrjJZeIzv0V4IshrxEzSsXllmU6x1A?= =?utf-8?q?iCRkkkQWmfm6eLzoIYjeHLeVai5Bv1p3z7y3EISPAwSsO2M6AIC2q/OPXWYRzdx86?= =?utf-8?q?cEoR0G7LEorPtxt24a72QmvfcA9DiHsgHKhuoMDDkuGA6+Zl78aLImhaWY4qVVVKl?= =?utf-8?q?iRAKuvRZBOZvthIdZ+CGMeOT/vGQ71UPHAxme8Lz1XDt26RSJfSVkeRjyAR2+ScEn?= =?utf-8?q?BXA86rHXcGj4zyanAUH5tWdZhqXmPX4uOoMoSC2BIY3RzWluZrlYkb1iTR7oh+EdI?= =?utf-8?q?2wGtaukdQ2kMlEYeg1w4V70oOBkqoFH+ZDGsa5w7rGD2Id8e9FpqFuiLbTz43fMqv?= =?utf-8?q?dw5JoIkOVFT+q/HSUcqvZ7SvzfK4PLE4tQ2VkqJqJkWZb8pQJ4FPlq0qvRNv0AGv8?= =?utf-8?q?psrjt8fvGV4kgyTF0v12VuphquIuLGOmT85+g0Mr4FhVvXjROIVbZve1gY1pWH8Dz?= =?utf-8?q?jFg2OSRPNWPVYSBBVloSLGDLu3VCM/1m8Mu/A4vxdgUJroTM3vBas7Yel1LJcyTLO?= =?utf-8?q?8G0bRi2gN6T4iyUgNrFE/3Q3/6t3YRJ/+qw7PHYsLfOAuU0IZviYuyKZidqnl/Y+y?= =?utf-8?q?llEj0ANx4r2S?= X-OriginatorOrg: solid-run.com X-MS-Exchange-CrossTenant-Network-Message-Id: 97650bb0-a8ef-41bc-02ee-08dca5d93e5b X-MS-Exchange-CrossTenant-AuthSource: AM9PR04MB7586.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Jul 2024 20:52:45.3013 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a4a8aaf3-fd27-4e27-add2-604707ce5b82 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: XrkBbRHKZcrRQFdjuEHa+pwbj3F9R3msoLO3ORidYNxwUzi5gkJxejLUeLI5wr1kkheBlqXd5CRSTaK6H8b1Qw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM8PR04MB7907 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240716_135259_514716_47BDFA0C X-CRM114-Status: GOOD ( 16.08 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Armada 380 has smilar USB-2.0 PHYs as CP-110. The differences are: - register base addresses - gap between port registers - number of ports: 388 has three, cp110 two - device-mode mux has bit refers to different ports - syscon register's base address (offsets identical) - armada-8k uses syscon for various drivers, a38x not Differentiation uses of_match_data with distinct compatible strings. Add support for Armada 380 PHYs by partially restructuting the driver: - Port register pointers are moved to the per-port private data. - Add armada-38x-specific compatible string and store enum value in of_match_data for differentiation. - Add support for optional regs usb-cfg and utmi-cfg replacing syscon. Signed-off-by: Josua Mayer --- drivers/phy/marvell/phy-mvebu-cp110-utmi.c | 209 +++++++++++++++++++++++------ 1 file changed, 166 insertions(+), 43 deletions(-) diff --git a/drivers/phy/marvell/phy-mvebu-cp110-utmi.c b/drivers/phy/marvell/phy-mvebu-cp110-utmi.c index 4922a5f3327d..4341923e85bc 100644 --- a/drivers/phy/marvell/phy-mvebu-cp110-utmi.c +++ b/drivers/phy/marvell/phy-mvebu-cp110-utmi.c @@ -19,7 +19,7 @@ #include #include -#define UTMI_PHY_PORTS 2 +#define UTMI_PHY_PORTS 3 /* CP110 UTMI register macro definetions */ #define SYSCON_USB_CFG_REG 0x420 @@ -76,32 +76,44 @@ #define PLL_LOCK_DELAY_US 10000 #define PLL_LOCK_TIMEOUT_US 1000000 -#define PORT_REGS(p) ((p)->priv->regs + (p)->id * 0x1000) +enum mvebu_cp110_utmi_type { + /* 0 is reserved to avoid clashing with NULL */ + A380_UTMI = 1, + CP110_UTMI = 2, +}; + +struct mvebu_cp110_utmi_port; /** * struct mvebu_cp110_utmi - PHY driver data * - * @regs: PHY registers + * @regs_usb: USB configuration register * @syscon: Regmap with system controller registers * @dev: device driver handle * @ops: phy ops + * @ports: phy object for each port */ struct mvebu_cp110_utmi { - void __iomem *regs; + void __iomem *regs_usb; struct regmap *syscon; struct device *dev; const struct phy_ops *ops; + struct mvebu_cp110_utmi_port *ports[UTMI_PHY_PORTS]; }; /** * struct mvebu_cp110_utmi_port - PHY port data * + * @regs: PHY registers + * @regs_cfg: PHY config register * @priv: PHY driver data * @id: PHY port ID * @dr_mode: PHY connection: USB_DR_MODE_HOST or USB_DR_MODE_PERIPHERAL */ struct mvebu_cp110_utmi_port { struct mvebu_cp110_utmi *priv; + void __iomem *regs; + void __iomem *regs_cfg; u32 id; enum usb_dr_mode dr_mode; }; @@ -118,47 +130,47 @@ static void mvebu_cp110_utmi_port_setup(struct mvebu_cp110_utmi_port *port) * The crystal used for all platform boards is now 25MHz. * See the functional specification for details. */ - reg = readl(PORT_REGS(port) + UTMI_PLL_CTRL_REG); + reg = readl(port->regs + UTMI_PLL_CTRL_REG); reg &= ~(PLL_REFDIV_MASK | PLL_FBDIV_MASK | PLL_SEL_LPFR_MASK); reg |= (PLL_REFDIV_VAL << PLL_REFDIV_OFFSET) | (PLL_FBDIV_VAL << PLL_FBDIV_OFFSET); - writel(reg, PORT_REGS(port) + UTMI_PLL_CTRL_REG); + writel(reg, port->regs + UTMI_PLL_CTRL_REG); /* Impedance Calibration Threshold Setting */ - reg = readl(PORT_REGS(port) + UTMI_CAL_CTRL_REG); + reg = readl(port->regs + UTMI_CAL_CTRL_REG); reg &= ~IMPCAL_VTH_MASK; reg |= IMPCAL_VTH_VAL << IMPCAL_VTH_OFFSET; - writel(reg, PORT_REGS(port) + UTMI_CAL_CTRL_REG); + writel(reg, port->regs + UTMI_CAL_CTRL_REG); /* Set LS TX driver strength coarse control */ - reg = readl(PORT_REGS(port) + UTMI_TX_CH_CTRL_REG); + reg = readl(port->regs + UTMI_TX_CH_CTRL_REG); reg &= ~TX_AMP_MASK; reg |= TX_AMP_VAL << TX_AMP_OFFSET; - writel(reg, PORT_REGS(port) + UTMI_TX_CH_CTRL_REG); + writel(reg, port->regs + UTMI_TX_CH_CTRL_REG); /* Disable SQ and enable analog squelch detect */ - reg = readl(PORT_REGS(port) + UTMI_RX_CH_CTRL0_REG); + reg = readl(port->regs + UTMI_RX_CH_CTRL0_REG); reg &= ~SQ_DET_EN; reg |= SQ_ANA_DTC_SEL; - writel(reg, PORT_REGS(port) + UTMI_RX_CH_CTRL0_REG); + writel(reg, port->regs + UTMI_RX_CH_CTRL0_REG); /* * Set External squelch calibration number and * enable the External squelch calibration */ - reg = readl(PORT_REGS(port) + UTMI_RX_CH_CTRL1_REG); + reg = readl(port->regs + UTMI_RX_CH_CTRL1_REG); reg &= ~SQ_AMP_CAL_MASK; reg |= (SQ_AMP_CAL_VAL << SQ_AMP_CAL_OFFSET) | SQ_AMP_CAL_EN; - writel(reg, PORT_REGS(port) + UTMI_RX_CH_CTRL1_REG); + writel(reg, port->regs + UTMI_RX_CH_CTRL1_REG); /* * Set Control VDAT Reference Voltage - 0.325V and * Control VSRC Reference Voltage - 0.6V */ - reg = readl(PORT_REGS(port) + UTMI_CHGDTC_CTRL_REG); + reg = readl(port->regs + UTMI_CHGDTC_CTRL_REG); reg &= ~(VDAT_MASK | VSRC_MASK); reg |= (VDAT_VAL << VDAT_OFFSET) | (VSRC_VAL << VSRC_OFFSET); - writel(reg, PORT_REGS(port) + UTMI_CHGDTC_CTRL_REG); + writel(reg, port->regs + UTMI_CHGDTC_CTRL_REG); } static int mvebu_cp110_utmi_phy_power_off(struct phy *phy) @@ -166,22 +178,38 @@ static int mvebu_cp110_utmi_phy_power_off(struct phy *phy) struct mvebu_cp110_utmi_port *port = phy_get_drvdata(phy); struct mvebu_cp110_utmi *utmi = port->priv; int i; + int reg; /* Power down UTMI PHY port */ - regmap_clear_bits(utmi->syscon, SYSCON_UTMI_CFG_REG(port->id), - UTMI_PHY_CFG_PU_MASK); + if (!IS_ERR(port->regs_cfg)) { + reg = readl(port->regs_cfg); + reg &= ~(UTMI_PHY_CFG_PU_MASK); + writel(reg, port->regs_cfg); + } else + regmap_clear_bits(utmi->syscon, SYSCON_UTMI_CFG_REG(port->id), + UTMI_PHY_CFG_PU_MASK); for (i = 0; i < UTMI_PHY_PORTS; i++) { - int test = regmap_test_bits(utmi->syscon, - SYSCON_UTMI_CFG_REG(i), - UTMI_PHY_CFG_PU_MASK); + if (!utmi->ports[i]) + continue; + + if (!IS_ERR(utmi->ports[i]->regs_cfg)) + reg = readl(utmi->ports[i]->regs_cfg); + else + regmap_read(utmi->syscon, SYSCON_UTMI_CFG_REG(i), ®); + int test = reg & UTMI_PHY_CFG_PU_MASK; /* skip PLL shutdown if there are active UTMI PHY ports */ if (test != 0) return 0; } /* PLL Power down if all UTMI PHYs are down */ - regmap_clear_bits(utmi->syscon, SYSCON_USB_CFG_REG, USB_CFG_PLL_MASK); + if (!IS_ERR(utmi->regs_usb)) { + reg = readl(utmi->regs_usb); + reg &= ~(USB_CFG_PLL_MASK); + writel(reg, utmi->regs_usb); + } else + regmap_clear_bits(utmi->syscon, SYSCON_USB_CFG_REG, USB_CFG_PLL_MASK); return 0; } @@ -191,8 +219,15 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy) struct mvebu_cp110_utmi_port *port = phy_get_drvdata(phy); struct mvebu_cp110_utmi *utmi = port->priv; struct device *dev = &phy->dev; + const void *match; + enum mvebu_cp110_utmi_type type; int ret; u32 reg; + u32 sel; + + match = device_get_match_data(utmi->dev); + if (match) + type = (enum mvebu_cp110_utmi_type)(uintptr_t)match; /* It is necessary to power off UTMI before configuration */ ret = mvebu_cp110_utmi_phy_power_off(phy); @@ -208,16 +243,45 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy) * to UTMI0 or to UTMI1 PHY port, but not to both. */ if (port->dr_mode == USB_DR_MODE_PERIPHERAL) { - regmap_update_bits(utmi->syscon, SYSCON_USB_CFG_REG, - USB_CFG_DEVICE_EN_MASK | USB_CFG_DEVICE_MUX_MASK, - USB_CFG_DEVICE_EN_MASK | - (port->id << USB_CFG_DEVICE_MUX_OFFSET)); + switch (type) { + case A380_UTMI: + /* + * A380 muxes between ports 0/2: + * - 0: Device mode on Port 2 + * - 1: Device mode on Port 0 + */ + if (port->id == 1) + return -EINVAL; + sel = !!(port->id == 0); + break; + case CP110_UTMI: + /* + * CP110 muxes between ports 0/1: + * - 0: Device mode on Port 0 + * - 1: Device mode on Port 1 + */ + sel = port->id; + break; + default: + return -EINVAL; + } + if (!IS_ERR(utmi->regs_usb)) { + reg = readl(utmi->regs_usb); + reg &= ~(USB_CFG_DEVICE_EN_MASK | USB_CFG_DEVICE_MUX_MASK); + reg |= USB_CFG_DEVICE_EN_MASK; + reg |= (sel << USB_CFG_DEVICE_MUX_OFFSET); + writel(reg, utmi->regs_usb); + } else + regmap_update_bits(utmi->syscon, SYSCON_USB_CFG_REG, + USB_CFG_DEVICE_EN_MASK | USB_CFG_DEVICE_MUX_MASK, + USB_CFG_DEVICE_EN_MASK | + (sel << USB_CFG_DEVICE_MUX_OFFSET)); } /* Set Test suspendm mode and enable Test UTMI select */ - reg = readl(PORT_REGS(port) + UTMI_CTRL_STATUS0_REG); + reg = readl(port->regs + UTMI_CTRL_STATUS0_REG); reg |= SUSPENDM | TEST_SEL; - writel(reg, PORT_REGS(port) + UTMI_CTRL_STATUS0_REG); + writel(reg, port->regs + UTMI_CTRL_STATUS0_REG); /* Wait for UTMI power down */ mdelay(1); @@ -226,16 +290,21 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy) mvebu_cp110_utmi_port_setup(port); /* Power UP UTMI PHY */ - regmap_set_bits(utmi->syscon, SYSCON_UTMI_CFG_REG(port->id), - UTMI_PHY_CFG_PU_MASK); + if (!IS_ERR(port->regs_cfg)) { + reg = readl(port->regs_cfg); + reg |= UTMI_PHY_CFG_PU_MASK; + writel(reg, port->regs_cfg); + } else + regmap_set_bits(utmi->syscon, SYSCON_UTMI_CFG_REG(port->id), + UTMI_PHY_CFG_PU_MASK); /* Disable Test UTMI select */ - reg = readl(PORT_REGS(port) + UTMI_CTRL_STATUS0_REG); + reg = readl(port->regs + UTMI_CTRL_STATUS0_REG); reg &= ~TEST_SEL; - writel(reg, PORT_REGS(port) + UTMI_CTRL_STATUS0_REG); + writel(reg, port->regs + UTMI_CTRL_STATUS0_REG); /* Wait for impedance calibration */ - ret = readl_poll_timeout(PORT_REGS(port) + UTMI_CAL_CTRL_REG, reg, + ret = readl_poll_timeout(port->regs + UTMI_CAL_CTRL_REG, reg, reg & IMPCAL_DONE, PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US); if (ret) { @@ -244,7 +313,7 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy) } /* Wait for PLL calibration */ - ret = readl_poll_timeout(PORT_REGS(port) + UTMI_CAL_CTRL_REG, reg, + ret = readl_poll_timeout(port->regs + UTMI_CAL_CTRL_REG, reg, reg & PLLCAL_DONE, PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US); if (ret) { @@ -253,7 +322,7 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy) } /* Wait for PLL ready */ - ret = readl_poll_timeout(PORT_REGS(port) + UTMI_PLL_CTRL_REG, reg, + ret = readl_poll_timeout(port->regs + UTMI_PLL_CTRL_REG, reg, reg & PLL_RDY, PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US); if (ret) { @@ -262,7 +331,12 @@ static int mvebu_cp110_utmi_phy_power_on(struct phy *phy) } /* PLL Power up */ - regmap_set_bits(utmi->syscon, SYSCON_USB_CFG_REG, USB_CFG_PLL_MASK); + if (!IS_ERR(utmi->regs_usb)) { + reg = readl(utmi->regs_usb); + reg |= USB_CFG_PLL_MASK; + writel(reg, utmi->regs_usb); + } else + regmap_set_bits(utmi->syscon, SYSCON_USB_CFG_REG, USB_CFG_PLL_MASK); return 0; } @@ -274,7 +348,8 @@ static const struct phy_ops mvebu_cp110_utmi_phy_ops = { }; static const struct of_device_id mvebu_cp110_utmi_of_match[] = { - { .compatible = "marvell,cp110-utmi-phy" }, + { .compatible = "marvell,a38x-utmi-phy", .data = (void *)A380_UTMI }, + { .compatible = "marvell,cp110-utmi-phy", .data = (void *)CP110_UTMI }, {}, }; MODULE_DEVICE_TABLE(of, mvebu_cp110_utmi_of_match); @@ -285,6 +360,10 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev) struct mvebu_cp110_utmi *utmi; struct phy_provider *provider; struct device_node *child; + void __iomem *regs_utmi; + void __iomem *regs_utmi_cfg; + const void *match; + enum mvebu_cp110_utmi_type type; u32 usb_devices = 0; utmi = devm_kzalloc(dev, sizeof(*utmi), GFP_KERNEL); @@ -293,18 +372,44 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev) utmi->dev = dev; + match = device_get_match_data(dev); + if (match) + type = (enum mvebu_cp110_utmi_type)(uintptr_t)match; + + /* Get UTMI memory region */ + regs_utmi = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs_utmi)) { + dev_err(dev, "Failed to map utmi regs\n"); + return PTR_ERR(regs_utmi); + } + + /* Get usb config region */ + utmi->regs_usb = devm_platform_ioremap_resource_byname(pdev, "usb-cfg"); + if (IS_ERR(utmi->regs_usb) && PTR_ERR(utmi->regs_usb) != -EINVAL) { + dev_err(dev, "Failed to map usb config regs\n"); + return PTR_ERR(utmi->regs_usb); + } + + /* Get utmi config region */ + regs_utmi_cfg = devm_platform_ioremap_resource_byname(pdev, "utmi-cfg"); + if (IS_ERR(regs_utmi_cfg) && PTR_ERR(regs_utmi_cfg) != -EINVAL) { + dev_err(dev, "Failed to map usb config regs\n"); + return PTR_ERR(regs_utmi_cfg); + } + /* Get system controller region */ utmi->syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "marvell,system-controller"); - if (IS_ERR(utmi->syscon)) { - dev_err(dev, "Missing UTMI system controller\n"); + if (IS_ERR(utmi->syscon) && PTR_ERR(utmi->syscon) != -ENODEV) { + dev_err(dev, "Failed to get system controller\n"); return PTR_ERR(utmi->syscon); } - /* Get UTMI memory region */ - utmi->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(utmi->regs)) - return PTR_ERR(utmi->regs); + if (IS_ERR(utmi->syscon) && + (IS_ERR(utmi->regs_usb) || IS_ERR(regs_utmi_cfg))) { + dev_err(dev, "Missing utmi system controller or config regs"); + return -EINVAL; + } for_each_available_child_of_node(dev->of_node, child) { struct mvebu_cp110_utmi_port *port; @@ -326,6 +431,24 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev) return -ENOMEM; } + utmi->ports[port_id] = port; + + /* Get port memory region */ + switch (type) { + case A380_UTMI: + port->regs = regs_utmi + port_id * 0x1000; + break; + case CP110_UTMI: + port->regs = regs_utmi + port_id * 0x2000; + break; + default: + return -EINVAL; + } + + /* assign utmi cfg reg */ + if (!IS_ERR(regs_utmi_cfg)) + port->regs_cfg = regs_utmi_cfg + port_id * 4; + port->dr_mode = of_usb_get_dr_mode_by_phy(child, -1); if ((port->dr_mode != USB_DR_MODE_HOST) && (port->dr_mode != USB_DR_MODE_PERIPHERAL)) {