From patchwork Tue Dec 29 13:58:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neil Armstrong X-Patchwork-Id: 1421209 X-Patchwork-Delegate: narmstrong@baylibre.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.a=rsa-sha256 header.s=20150623 header.b=RATw2YmH; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4D4wys3w9lz9sVq for ; Wed, 30 Dec 2020 00:59:48 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 9609B825BF; Tue, 29 Dec 2020 14:59:40 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.b="RATw2YmH"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 445CE82496; Tue, 29 Dec 2020 14:59:25 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id CE2A5824DE for ; Tue, 29 Dec 2020 14:59:07 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=narmstrong@baylibre.com Received: by mail-wr1-x436.google.com with SMTP id a12so14712122wrv.8 for ; Tue, 29 Dec 2020 05:59:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=+h3LSWGKq+fQ7Uy3epFoH7GXkRmBmGRwCMjftZSusg0=; b=RATw2YmHsDnLIYUohNI5W3Xmydrtn1X6twx5O+Yv79KISvq9Qmha9DSHJA4BZ2LrC+ 3R/rBxeJSs7/uGd5JJoIYVouExIkewL0VpTbs9CP1cGqKtEurNLjS7YBJ130cRAyKrp6 ey6kni6j/tqv1L0qWppm3tnPydPCAmviU5DmaFsrYggdll4OsNstbvvZN1UDPI+FBLc7 bXHs3POFiBnFqlIwzEl90p7mEEje0MpPWCQ36KELdQSjRIkUqDB2nUQYAVjnQ3J4ikMk dGnkk1LqumWwBfk7TNuerFRYTb01aAt6pw/G2OD+VCeAklAYrjy8sCDUa7Whca7zipHP eKLA== 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=+h3LSWGKq+fQ7Uy3epFoH7GXkRmBmGRwCMjftZSusg0=; b=n36uiFEHpQOKRetyvFEtFONnvE3lmZ8eOq47kkh00G1GDuuuzCsLip057jwIy0YyLe x7gHcIpEaCZp2g0ZoYSu/MqhOLvu8M7L0n4Gg8vlGvhvbZ8BjCA8rMeSLQ5zke1Nm2Y5 Q4Hwe1fJVKSRH952r7XzBvcolvZTBMkmD1uDWpRvGy1HZSDmt16aDy32uOGMB8xDqLPL +xbmMT3YBthfLe6i0gMO8jNsh2B7ZC7VBjTxo4GZGBpyrpMOJapsju4LgwrqqlXz5XAa NR/UEq/I5dAt8P6OEMhsC7R+CIm9nSxijagQk3qtsxgIKFX6mA9Y9+0ngh9CIt6J9VGM LY6w== X-Gm-Message-State: AOAM530YhxGd4VTnEjW/qFM1ocy89peJFvKVqrLLPKO8BrDpKvg9jEUV WdNVOJgwDPx/spu1MHqvOmvW45nil8NAkg== X-Google-Smtp-Source: ABdhPJxsJ+To8BJWeSRIgRhx7qcD8/RPRlqhqOs06E0ixvgdIZmXR8RkwRpzxTscyHKrOKiel3V3/g== X-Received: by 2002:adf:f684:: with SMTP id v4mr57068694wrp.387.1609250346473; Tue, 29 Dec 2020 05:59:06 -0800 (PST) Received: from localhost.localdomain ([2a01:e35:2ec0:82b0:2464:c563:b017:7ce1]) by smtp.gmail.com with ESMTPSA id z22sm3666950wml.1.2020.12.29.05.59.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Dec 2020 05:59:05 -0800 (PST) From: Neil Armstrong To: u-boot@lists.denx.de, sjg@chromium.org Cc: u-boot-amlogic@groups.io, Neil Armstrong Subject: [PATCH 1/4] phy: dphy: Add configuration helpers Date: Tue, 29 Dec 2020 14:58:58 +0100 Message-Id: <20201229135901.30090-2-narmstrong@baylibre.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201229135901.30090-1-narmstrong@baylibre.com> References: <20201229135901.30090-1-narmstrong@baylibre.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean The MIPI D-PHY spec defines default values and boundaries for most of the parameters it defines. Introduce helpers to help drivers get meaningful values based on their current parameters, and validate the boundaries of these parameters if needed. These helpers and header are taken from Linux commit 9123e3a74ec7 ("Linux 5.9-rc1"). Signed-off-by: Neil Armstrong --- drivers/phy/Kconfig | 5 + drivers/phy/Makefile | 1 + drivers/phy/phy-core-mipi-dphy.c | 161 ++++++++++++++++++ include/phy-mipi-dphy.h | 284 +++++++++++++++++++++++++++++++ 4 files changed, 451 insertions(+) create mode 100644 drivers/phy/phy-core-mipi-dphy.c create mode 100644 include/phy-mipi-dphy.h diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index d12a6b02ad..8d9da17b53 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -59,6 +59,11 @@ config SPL_NOP_PHY This is useful when a driver uses the PHY framework but no real PHY hardware exists. +config MIPI_DPHY_HELPERS + bool "MIPI D-PHY support helpers" + help + Provides a number of helpers a core functions for MIPI D-PHY drivers. + config BCM6318_USBH_PHY bool "BCM6318 USBH PHY support" depends on PHY && ARCH_BMIPS diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 45a7fe5b56..9024002822 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_$(SPL_)PHY) += phy-uclass.o obj-$(CONFIG_$(SPL_)NOP_PHY) += nop-phy.o +obj-$(CONFIG_MIPI_DPHY_HELPERS) += phy-core-mipi-dphy.o obj-$(CONFIG_BCM6318_USBH_PHY) += bcm6318-usbh-phy.o obj-$(CONFIG_BCM6348_USBH_PHY) += bcm6348-usbh-phy.o obj-$(CONFIG_BCM6358_USBH_PHY) += bcm6358-usbh-phy.o diff --git a/drivers/phy/phy-core-mipi-dphy.c b/drivers/phy/phy-core-mipi-dphy.c new file mode 100644 index 0000000000..ba5f648612 --- /dev/null +++ b/drivers/phy/phy-core-mipi-dphy.c @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2013 NVIDIA Corporation + * Copyright (C) 2018 Cadence Design Systems Inc. + */ + +#include +#include + +#include + +#define PSEC_PER_SEC 1000000000000LL + +/* + * Minimum D-PHY timings based on MIPI D-PHY specification. Derived + * from the valid ranges specified in Section 6.9, Table 14, Page 41 + * of the D-PHY specification (v2.1). + */ +int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, + unsigned int bpp, + unsigned int lanes, + struct phy_configure_opts_mipi_dphy *cfg) +{ + unsigned long long hs_clk_rate; + unsigned long long ui; + + if (!cfg) + return -EINVAL; + + hs_clk_rate = pixel_clock * bpp; + do_div(hs_clk_rate, lanes); + + ui = ALIGN(PSEC_PER_SEC, hs_clk_rate); + do_div(ui, hs_clk_rate); + + cfg->clk_miss = 0; + cfg->clk_post = 60000 + 52 * ui; + cfg->clk_pre = 8000; + cfg->clk_prepare = 38000; + cfg->clk_settle = 95000; + cfg->clk_term_en = 0; + cfg->clk_trail = 60000; + cfg->clk_zero = 262000; + cfg->d_term_en = 0; + cfg->eot = 0; + cfg->hs_exit = 100000; + cfg->hs_prepare = 40000 + 4 * ui; + cfg->hs_zero = 105000 + 6 * ui; + cfg->hs_settle = 85000 + 6 * ui; + cfg->hs_skip = 40000; + + /* + * The MIPI D-PHY specification (Section 6.9, v1.2, Table 14, Page 40) + * contains this formula as: + * + * T_HS-TRAIL = max(n * 8 * ui, 60 + n * 4 * ui) + * + * where n = 1 for forward-direction HS mode and n = 4 for reverse- + * direction HS mode. There's only one setting and this function does + * not parameterize on anything other that ui, so this code will + * assumes that reverse-direction HS mode is supported and uses n = 4. + */ + cfg->hs_trail = max(4 * 8 * ui, 60000 + 4 * 4 * ui); + + cfg->init = 100; + cfg->lpx = 60000; + cfg->ta_get = 5 * cfg->lpx; + cfg->ta_go = 4 * cfg->lpx; + cfg->ta_sure = 2 * cfg->lpx; + cfg->wakeup = 1000; + + cfg->hs_clk_rate = hs_clk_rate; + cfg->lanes = lanes; + + return 0; +} + +/* + * Validate D-PHY configuration according to MIPI D-PHY specification + * (v1.2, Section Section 6.9 "Global Operation Timing Parameters"). + */ +int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg) +{ + unsigned long long ui; + + if (!cfg) + return -EINVAL; + + ui = ALIGN(PSEC_PER_SEC, cfg->hs_clk_rate); + do_div(ui, cfg->hs_clk_rate); + + if (cfg->clk_miss > 60000) + return -EINVAL; + + if (cfg->clk_post < (60000 + 52 * ui)) + return -EINVAL; + + if (cfg->clk_pre < 8000) + return -EINVAL; + + if (cfg->clk_prepare < 38000 || cfg->clk_prepare > 95000) + return -EINVAL; + + if (cfg->clk_settle < 95000 || cfg->clk_settle > 300000) + return -EINVAL; + + if (cfg->clk_term_en > 38000) + return -EINVAL; + + if (cfg->clk_trail < 60000) + return -EINVAL; + + if ((cfg->clk_prepare + cfg->clk_zero) < 300000) + return -EINVAL; + + if (cfg->d_term_en > (35000 + 4 * ui)) + return -EINVAL; + + if (cfg->eot > (105000 + 12 * ui)) + return -EINVAL; + + if (cfg->hs_exit < 100000) + return -EINVAL; + + if (cfg->hs_prepare < (40000 + 4 * ui) || + cfg->hs_prepare > (85000 + 6 * ui)) + return -EINVAL; + + if ((cfg->hs_prepare + cfg->hs_zero) < (145000 + 10 * ui)) + return -EINVAL; + + if ((cfg->hs_settle < (85000 + 6 * ui)) || + (cfg->hs_settle > (145000 + 10 * ui))) + return -EINVAL; + + if (cfg->hs_skip < 40000 || cfg->hs_skip > (55000 + 4 * ui)) + return -EINVAL; + + if (cfg->hs_trail < max(8 * ui, 60000 + 4 * ui)) + return -EINVAL; + + if (cfg->init < 100) + return -EINVAL; + + if (cfg->lpx < 50000) + return -EINVAL; + + if (cfg->ta_get != (5 * cfg->lpx)) + return -EINVAL; + + if (cfg->ta_go != (4 * cfg->lpx)) + return -EINVAL; + + if (cfg->ta_sure < cfg->lpx || cfg->ta_sure > (2 * cfg->lpx)) + return -EINVAL; + + if (cfg->wakeup < 1000) + return -EINVAL; + + return 0; +} diff --git a/include/phy-mipi-dphy.h b/include/phy-mipi-dphy.h new file mode 100644 index 0000000000..a877ffee84 --- /dev/null +++ b/include/phy-mipi-dphy.h @@ -0,0 +1,284 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018 Cadence Design Systems Inc. + */ + +#ifndef __PHY_MIPI_DPHY_H_ +#define __PHY_MIPI_DPHY_H_ + +/** + * struct phy_configure_opts_mipi_dphy - MIPI D-PHY configuration set + * + * This structure is used to represent the configuration state of a + * MIPI D-PHY phy. + */ +struct phy_configure_opts_mipi_dphy { + /** + * @clk_miss: + * + * Timeout, in picoseconds, for receiver to detect absence of + * Clock transitions and disable the Clock Lane HS-RX. + * + * Maximum value: 60000 ps + */ + unsigned int clk_miss; + + /** + * @clk_post: + * + * Time, in picoseconds, that the transmitter continues to + * send HS clock after the last associated Data Lane has + * transitioned to LP Mode. Interval is defined as the period + * from the end of @hs_trail to the beginning of @clk_trail. + * + * Minimum value: 60000 ps + 52 * @hs_clk_rate period in ps + */ + unsigned int clk_post; + + /** + * @clk_pre: + * + * Time, in UI, that the HS clock shall be driven by + * the transmitter prior to any associated Data Lane beginning + * the transition from LP to HS mode. + * + * Minimum value: 8 UI + */ + unsigned int clk_pre; + + /** + * @clk_prepare: + * + * Time, in picoseconds, that the transmitter drives the Clock + * Lane LP-00 Line state immediately before the HS-0 Line + * state starting the HS transmission. + * + * Minimum value: 38000 ps + * Maximum value: 95000 ps + */ + unsigned int clk_prepare; + + /** + * @clk_settle: + * + * Time interval, in picoseconds, during which the HS receiver + * should ignore any Clock Lane HS transitions, starting from + * the beginning of @clk_prepare. + * + * Minimum value: 95000 ps + * Maximum value: 300000 ps + */ + unsigned int clk_settle; + + /** + * @clk_term_en: + * + * Time, in picoseconds, for the Clock Lane receiver to enable + * the HS line termination. + * + * Maximum value: 38000 ps + */ + unsigned int clk_term_en; + + /** + * @clk_trail: + * + * Time, in picoseconds, that the transmitter drives the HS-0 + * state after the last payload clock bit of a HS transmission + * burst. + * + * Minimum value: 60000 ps + */ + unsigned int clk_trail; + + /** + * @clk_zero: + * + * Time, in picoseconds, that the transmitter drives the HS-0 + * state prior to starting the Clock. + */ + unsigned int clk_zero; + + /** + * @d_term_en: + * + * Time, in picoseconds, for the Data Lane receiver to enable + * the HS line termination. + * + * Maximum value: 35000 ps + 4 * @hs_clk_rate period in ps + */ + unsigned int d_term_en; + + /** + * @eot: + * + * Transmitted time interval, in picoseconds, from the start + * of @hs_trail or @clk_trail, to the start of the LP- 11 + * state following a HS burst. + * + * Maximum value: 105000 ps + 12 * @hs_clk_rate period in ps + */ + unsigned int eot; + + /** + * @hs_exit: + * + * Time, in picoseconds, that the transmitter drives LP-11 + * following a HS burst. + * + * Minimum value: 100000 ps + */ + unsigned int hs_exit; + + /** + * @hs_prepare: + * + * Time, in picoseconds, that the transmitter drives the Data + * Lane LP-00 Line state immediately before the HS-0 Line + * state starting the HS transmission. + * + * Minimum value: 40000 ps + 4 * @hs_clk_rate period in ps + * Maximum value: 85000 ps + 6 * @hs_clk_rate period in ps + */ + unsigned int hs_prepare; + + /** + * @hs_settle: + * + * Time interval, in picoseconds, during which the HS receiver + * shall ignore any Data Lane HS transitions, starting from + * the beginning of @hs_prepare. + * + * Minimum value: 85000 ps + 6 * @hs_clk_rate period in ps + * Maximum value: 145000 ps + 10 * @hs_clk_rate period in ps + */ + unsigned int hs_settle; + + /** + * @hs_skip: + * + * Time interval, in picoseconds, during which the HS-RX + * should ignore any transitions on the Data Lane, following a + * HS burst. The end point of the interval is defined as the + * beginning of the LP-11 state following the HS burst. + * + * Minimum value: 40000 ps + * Maximum value: 55000 ps + 4 * @hs_clk_rate period in ps + */ + unsigned int hs_skip; + + /** + * @hs_trail: + * + * Time, in picoseconds, that the transmitter drives the + * flipped differential state after last payload data bit of a + * HS transmission burst + * + * Minimum value: max(8 * @hs_clk_rate period in ps, + * 60000 ps + 4 * @hs_clk_rate period in ps) + */ + unsigned int hs_trail; + + /** + * @hs_zero: + * + * Time, in picoseconds, that the transmitter drives the HS-0 + * state prior to transmitting the Sync sequence. + */ + unsigned int hs_zero; + + /** + * @init: + * + * Time, in microseconds for the initialization period to + * complete. + * + * Minimum value: 100 us + */ + unsigned int init; + + /** + * @lpx: + * + * Transmitted length, in picoseconds, of any Low-Power state + * period. + * + * Minimum value: 50000 ps + */ + unsigned int lpx; + + /** + * @ta_get: + * + * Time, in picoseconds, that the new transmitter drives the + * Bridge state (LP-00) after accepting control during a Link + * Turnaround. + * + * Value: 5 * @lpx + */ + unsigned int ta_get; + + /** + * @ta_go: + * + * Time, in picoseconds, that the transmitter drives the + * Bridge state (LP-00) before releasing control during a Link + * Turnaround. + * + * Value: 4 * @lpx + */ + unsigned int ta_go; + + /** + * @ta_sure: + * + * Time, in picoseconds, that the new transmitter waits after + * the LP-10 state before transmitting the Bridge state + * (LP-00) during a Link Turnaround. + * + * Minimum value: @lpx + * Maximum value: 2 * @lpx + */ + unsigned int ta_sure; + + /** + * @wakeup: + * + * Time, in microseconds, that a transmitter drives a Mark-1 + * state prior to a Stop state in order to initiate an exit + * from ULPS. + * + * Minimum value: 1000 us + */ + unsigned int wakeup; + + /** + * @hs_clk_rate: + * + * Clock rate, in Hertz, of the high-speed clock. + */ + unsigned long hs_clk_rate; + + /** + * @lp_clk_rate: + * + * Clock rate, in Hertz, of the low-power clock. + */ + unsigned long lp_clk_rate; + + /** + * @lanes: + * + * Number of active, consecutive, data lanes, starting from + * lane 0, used for the transmissions. + */ + unsigned char lanes; +}; + +int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, + unsigned int bpp, + unsigned int lanes, + struct phy_configure_opts_mipi_dphy *cfg); +int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg); + +#endif /* __PHY_MIPI_DPHY_H_ */ From patchwork Tue Dec 29 13:58:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Neil Armstrong X-Patchwork-Id: 1421211 X-Patchwork-Delegate: narmstrong@baylibre.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.a=rsa-sha256 header.s=20150623 header.b=v0Q5Qq5x; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4D4wz53vLNz9sVv for ; Wed, 30 Dec 2020 01:00:01 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id D02B28257D; Tue, 29 Dec 2020 14:59:43 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.b="v0Q5Qq5x"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id E7B33825AB; Tue, 29 Dec 2020 14:59:29 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 034A082564 for ; Tue, 29 Dec 2020 14:59:09 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=narmstrong@baylibre.com Received: by mail-wr1-x42e.google.com with SMTP id t30so14765351wrb.0 for ; Tue, 29 Dec 2020 05:59:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MxmSo4YEIYtoXatpN2gwm7qBDJ/g/oXY9prnXg4jdO8=; b=v0Q5Qq5xl3iK1hZsw2mlslCB1B/WvaSnLt2vtV/36iowb2/D3Le9P/JcZNfw8H62Mb A871jfHDN06dF87BZWTfzkKHmLPTnCdGUwFahP9iHIhfRAO0ZNgh90vjxmh7o3STtXKl KiFGoV/GxhZJd914J2CBFBn6yl/j+RSIluN/UPS6Ae5BZbXcASSMtCmnmYiVXg/mUHQx tDrCovO3vMaSA05HNwsToRC2PumtH+OIT5LGOf4mEa3fzQ44d5CGZAJ7mpwpTBuQ/KmJ Ut637JnNBIm27X03JW7XeYx0bqx9QC4P6wKPQO7ZgYBYEsCY8ijfhDJymWy/dN0lCEM/ R4Xw== 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=MxmSo4YEIYtoXatpN2gwm7qBDJ/g/oXY9prnXg4jdO8=; b=Otd04x3Q5S/SKJxhtafOixXjfLnenoC30CV6B/jrJ+INrsRUhbi5lsr2adInEDu1iE HNpR+PMdkchcvaF52lteJLtZtkjKATACwexSmgPGnpxFJ6VCchywDstaDTXlqaOkkIA6 sdPkE2j7OOoX4m/WT7IGlqQaKCY2qIfVtywoIcY7K9bJ/8cibAGWsCxrHWY41zJQbRYK EpF+nTsU1KF6apcKNmIGU9V+hDfzCCG/PWDKof/mJXRXdyr2H1rw7HNLBEvTS3+yk5zo 2SvuqAll6zzXPUVS8+my0Fxejl+FN1Lb88p5V+ATYfEb1EzchXx6pVp0DzBRWDDQCe9P jqLQ== X-Gm-Message-State: AOAM533xUyEZ2cr3T3HVwjc7qQr2lYk2eX+a3CqBEVPQd046eGHmrWm2 Jru3iCGENunhC0EPy6ENb+b+VEGyFfVCIA== X-Google-Smtp-Source: ABdhPJyWFIgd5h5twKbesnMTmluw/lPGrvyQS6Plrjz1sWNGIXoz9c4zx6ECnSo1Hghgd3i5u6hBrw== X-Received: by 2002:a5d:558a:: with SMTP id i10mr56982634wrv.363.1609250348172; Tue, 29 Dec 2020 05:59:08 -0800 (PST) Received: from localhost.localdomain ([2a01:e35:2ec0:82b0:2464:c563:b017:7ce1]) by smtp.gmail.com with ESMTPSA id z22sm3666950wml.1.2020.12.29.05.59.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Dec 2020 05:59:07 -0800 (PST) From: Neil Armstrong To: u-boot@lists.denx.de, sjg@chromium.org Cc: u-boot-amlogic@groups.io, Neil Armstrong Subject: [PATCH 2/4] generic-phy: add configure op Date: Tue, 29 Dec 2020 14:58:59 +0100 Message-Id: <20201229135901.30090-3-narmstrong@baylibre.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201229135901.30090-1-narmstrong@baylibre.com> References: <20201229135901.30090-1-narmstrong@baylibre.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean Add the PHY configure op callback to the generic PHY uclass to permit configuring the PHY. It's useful for MIPI DSI PHYs to setup the link timings. Signed-off-by:Neil Armstrong Signed-off-by: Neil Armstrong --- drivers/phy/phy-uclass.c | 11 +++++++++++ include/generic-phy.h | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c index ef03e3a502..43ffbcee0f 100644 --- a/drivers/phy/phy-uclass.c +++ b/drivers/phy/phy-uclass.c @@ -204,6 +204,17 @@ int generic_phy_power_off(struct phy *phy) return ret; } +int generic_phy_configure(struct phy *phy, void *params) +{ + struct phy_ops const *ops; + + if (!generic_phy_valid(phy)) + return 0; + ops = phy_dev_ops(phy->dev); + + return ops->configure ? ops->configure(phy, params) : 0; +} + int generic_phy_get_bulk(struct udevice *dev, struct phy_bulk *bulk) { int i, ret, count; diff --git a/include/generic-phy.h b/include/generic-phy.h index 5ab34cda03..a17d900e4b 100644 --- a/include/generic-phy.h +++ b/include/generic-phy.h @@ -122,6 +122,20 @@ struct phy_ops { * @return 0 if OK, or a negative error code */ int (*power_off)(struct phy *phy); + + /** + * configure - configure a PHY device + * + * @phy: PHY port to be configured + * @params: PHY Parameters, underlying data is specific to the PHY function + * + * During runtime, the PHY may need to be configured for it's main function. + * This function configures the PHY for it's main function following + * power_on/off() after beeing initialized. + * + * @return 0 if OK, or a negative error code + */ + int (*configure)(struct phy *phy, void *params); }; /** @@ -183,6 +197,15 @@ int generic_phy_power_on(struct phy *phy); */ int generic_phy_power_off(struct phy *phy); +/** + * generic_phy_configure() - configure a PHY device + * + * @phy: PHY port to be configured + * @params: PHY Parameters, underlying data is specific to the PHY function + * @return 0 if OK, or a negative error code + */ +int generic_phy_configure(struct phy *phy, void *params); + /** * generic_phy_get_by_index() - Get a PHY device by integer index. From patchwork Tue Dec 29 13:59:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Neil Armstrong X-Patchwork-Id: 1421213 X-Patchwork-Delegate: narmstrong@baylibre.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.a=rsa-sha256 header.s=20150623 header.b=rAKoO1KB; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4D4wzh5ll2z9sVq for ; Wed, 30 Dec 2020 01:00:32 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id A668682614; Tue, 29 Dec 2020 15:00:04 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.b="rAKoO1KB"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 719408257D; Tue, 29 Dec 2020 14:59:33 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 1A31182570 for ; Tue, 29 Dec 2020 14:59:11 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=narmstrong@baylibre.com Received: by mail-wr1-x435.google.com with SMTP id m5so14700807wrx.9 for ; Tue, 29 Dec 2020 05:59:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pYPZmiUIFlLhR+Y/B9yZJJAwsy5uN5WpFZ3/cC2HAHw=; b=rAKoO1KBxfCl0Ht8Zeu7mRv8Dm6+oUgVj5fOCyCsXMuZ8ZIvz+BeQ5IPyeFr0MZsrb 80PIATiqBwxakBqZi/oapIiztLGG+8dAfIMIc8tYDLbmErVJ5TtrpIkO4xSF4I0gW6lo xpfpv69/xjQy0PgROw3kGpKPd3NF6bdlt9n46jc5iN7ZE5Znad90f1g1MztQgTzseCOs Tay/vfMI+KPry7/baAza998Elg5QLtH7an04NCBKGKdz2VpwOZ7H731TMrc8AWyXn0Z3 xuLHmFqd+IiGg/Py5snE3Y+BW6LTtKwsXVKkiqbKWikWU7r68hReXJDxbQCpcvPuT9b8 Pzmg== 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=pYPZmiUIFlLhR+Y/B9yZJJAwsy5uN5WpFZ3/cC2HAHw=; b=tcMGJeqKXEIZz+gevR2zNtzO8SmaMylt4GUypr7+pj26lVr4YX89Ndkgst0UqhEHTw nhKxcywJcssHlxugGgUP4KDVGCffe+Itw4BGQgrk+BH7v3saVmXlsaSrqvuy8pWTiUCQ OZhbAI01CrpHzkoTQFsu1dpAxS/XctMdTiyfhDgGA5ljmhBglb7+1K10dJyCueanTPeA bLEMMKGYVOSBVjtOSyr3NRyduw/ovXJCOJmm8GMxbBG+mi5qH4y3x/JZeAc/ybBzboLC 2c0/z2Nu+9e6CU+ZU7HQR4ymXFCv/qERTpc7BnuoQbdQ2uLEX0bQ2sjmNYodBWeU2/23 qr0w== X-Gm-Message-State: AOAM531pLPlYvHQ2I+DugkGPVbcOFmhNWGsc1jLkqXdQf7mJCFPDvrkd xJkOMVcLsijrbA7+l7ZMKZ9VXB8QT9axuw== X-Google-Smtp-Source: ABdhPJwCtkjZmlFVJxHBHkI28oxusxPPyfnuD94ZQLuCy+dTHjhm/kLX7aKhHSxN5rbZ/86Bef4xmA== X-Received: by 2002:a5d:6a88:: with SMTP id s8mr56571205wru.118.1609250349697; Tue, 29 Dec 2020 05:59:09 -0800 (PST) Received: from localhost.localdomain ([2a01:e35:2ec0:82b0:2464:c563:b017:7ce1]) by smtp.gmail.com with ESMTPSA id z22sm3666950wml.1.2020.12.29.05.59.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Dec 2020 05:59:09 -0800 (PST) From: Neil Armstrong To: u-boot@lists.denx.de, sjg@chromium.org Cc: u-boot-amlogic@groups.io, Neil Armstrong Subject: [PATCH 3/4] phy: Add Amlogic AXG MIPI D-PHY driver Date: Tue, 29 Dec 2020 14:59:00 +0100 Message-Id: <20201229135901.30090-4-narmstrong@baylibre.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201229135901.30090-1-narmstrong@baylibre.com> References: <20201229135901.30090-1-narmstrong@baylibre.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean The Amlogic AXG SoCs embeds a MIPI D-PHY used to communicate with DSI panels. This D-PHY depends on a separate analog PHY. Signed-off-by:Neil Armstrong Signed-off-by: Neil Armstrong --- drivers/phy/Kconfig | 9 + drivers/phy/Makefile | 1 + drivers/phy/meson-axg-mipi-dphy.c | 393 ++++++++++++++++++++++++++++++ 3 files changed, 403 insertions(+) create mode 100644 drivers/phy/meson-axg-mipi-dphy.c diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 8d9da17b53..00d77eef08 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -196,6 +196,15 @@ config MESON_G12A_USB_PHY This is the generic phy driver for the Amlogic Meson G12A USB2 and USB3 PHYS. +config MESON_AXG_MIPI_DPHY + bool "Amlogic Meson AXG MIPI D-PHY" + depends on PHY && ARCH_MESON && MESON_AXG + select MIPI_DPHY_HELPERS + imply REGMAP + help + This is the generic phy driver for the Amlogic Meson AXG + MIPI D-PHY. + config MSM8916_USB_PHY bool "Qualcomm MSM8916 USB PHY support" depends on PHY diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 9024002822..b2fd2d06f6 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o obj-$(CONFIG_MESON_GXBB_USB_PHY) += meson-gxbb-usb2.o obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o obj-$(CONFIG_MESON_G12A_USB_PHY) += meson-g12a-usb2.o meson-g12a-usb3-pcie.o +obj-$(CONFIG_MESON_AXG_MIPI_DPHY) += meson-axg-mipi-dphy.o obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o obj-$(CONFIG_KEYSTONE_USB_PHY) += keystone-usb-phy.o diff --git a/drivers/phy/meson-axg-mipi-dphy.c b/drivers/phy/meson-axg-mipi-dphy.c new file mode 100644 index 0000000000..8b2469793d --- /dev/null +++ b/drivers/phy/meson-axg-mipi-dphy.c @@ -0,0 +1,393 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Meson AXG MIPI DPHY driver + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved + * Copyright (C) 2020 BayLibre, SAS + * Author: Neil Armstrong + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* [31] soft reset for the phy. + * 1: reset. 0: dessert the reset. + * [30] clock lane soft reset. + * [29] data byte lane 3 soft reset. + * [28] data byte lane 2 soft reset. + * [27] data byte lane 1 soft reset. + * [26] data byte lane 0 soft reset. + * [25] mipi dsi pll clock selection. + * 1: clock from fixed 850Mhz clock source. 0: from VID2 PLL. + * [12] mipi HSbyteclk enable. + * [11] mipi divider clk selection. + * 1: select the mipi DDRCLKHS from clock divider. + * 0: from PLL clock. + * [10] mipi clock divider control. + * 1: /4. 0: /2. + * [9] mipi divider output enable. + * [8] mipi divider counter enable. + * [7] PLL clock enable. + * [5] LPDT data endian. + * 1 = transfer the high bit first. 0 : transfer the low bit first. + * [4] HS data endian. + * [3] force data byte lane in stop mode. + * [2] force data byte lane 0 in receiver mode. + * [1] write 1 to sync the txclkesc input. the internal logic have to + * use txclkesc to decide Txvalid and Txready. + * [0] enalbe the MIPI DPHY TxDDRClk. + */ +#define MIPI_DSI_PHY_CTRL 0x0 + +/* [31] clk lane tx_hs_en control selection. + * 1: from register. 0: use clk lane state machine. + * [30] register bit for clock lane tx_hs_en. + * [29] clk lane tx_lp_en contrl selection. + * 1: from register. 0: from clk lane state machine. + * [28] register bit for clock lane tx_lp_en. + * [27] chan0 tx_hs_en control selection. + * 1: from register. 0: from chan0 state machine. + * [26] register bit for chan0 tx_hs_en. + * [25] chan0 tx_lp_en control selection. + * 1: from register. 0: from chan0 state machine. + * [24] register bit from chan0 tx_lp_en. + * [23] chan0 rx_lp_en control selection. + * 1: from register. 0: from chan0 state machine. + * [22] register bit from chan0 rx_lp_en. + * [21] chan0 contention detection enable control selection. + * 1: from register. 0: from chan0 state machine. + * [20] register bit from chan0 contention dectection enable. + * [19] chan1 tx_hs_en control selection. + * 1: from register. 0: from chan0 state machine. + * [18] register bit for chan1 tx_hs_en. + * [17] chan1 tx_lp_en control selection. + * 1: from register. 0: from chan0 state machine. + * [16] register bit from chan1 tx_lp_en. + * [15] chan2 tx_hs_en control selection. + * 1: from register. 0: from chan0 state machine. + * [14] register bit for chan2 tx_hs_en. + * [13] chan2 tx_lp_en control selection. + * 1: from register. 0: from chan0 state machine. + * [12] register bit from chan2 tx_lp_en. + * [11] chan3 tx_hs_en control selection. + * 1: from register. 0: from chan0 state machine. + * [10] register bit for chan3 tx_hs_en. + * [9] chan3 tx_lp_en control selection. + * 1: from register. 0: from chan0 state machine. + * [8] register bit from chan3 tx_lp_en. + * [4] clk chan power down. this bit is also used as the power down + * of the whole MIPI_DSI_PHY. + * [3] chan3 power down. + * [2] chan2 power down. + * [1] chan1 power down. + * [0] chan0 power down. + */ +#define MIPI_DSI_CHAN_CTRL 0x4 + +/* [24] rx turn watch dog triggered. + * [23] rx esc watchdog triggered. + * [22] mbias ready. + * [21] txclkesc synced and ready. + * [20:17] clk lane state. {mbias_ready, tx_stop, tx_ulps, tx_hs_active} + * [16:13] chan3 state{0, tx_stop, tx_ulps, tx_hs_active} + * [12:9] chan2 state.{0, tx_stop, tx_ulps, tx_hs_active} + * [8:5] chan1 state. {0, tx_stop, tx_ulps, tx_hs_active} + * [4:0] chan0 state. {TX_STOP, tx_ULPS, hs_active, direction, rxulpsesc} + */ +#define MIPI_DSI_CHAN_STS 0x8 + +/* [31:24] TCLK_PREPARE. + * [23:16] TCLK_ZERO. + * [15:8] TCLK_POST. + * [7:0] TCLK_TRAIL. + */ +#define MIPI_DSI_CLK_TIM 0xc + +/* [31:24] THS_PREPARE. + * [23:16] THS_ZERO. + * [15:8] THS_TRAIL. + * [7:0] THS_EXIT. + */ +#define MIPI_DSI_HS_TIM 0x10 + +/* [31:24] tTA_GET. + * [23:16] tTA_GO. + * [15:8] tTA_SURE. + * [7:0] tLPX. + */ +#define MIPI_DSI_LP_TIM 0x14 + +/* wait time to MIPI DIS analog ready. */ +#define MIPI_DSI_ANA_UP_TIM 0x18 + +/* TINIT. */ +#define MIPI_DSI_INIT_TIM 0x1c + +/* TWAKEUP. */ +#define MIPI_DSI_WAKEUP_TIM 0x20 + +/* when in RxULPS check state, after the the logic enable the analog, + * how long we should wait to check the lP state . + */ +#define MIPI_DSI_LPOK_TIM 0x24 + +/* Watchdog for RX low power state no finished. */ +#define MIPI_DSI_LP_WCHDOG 0x28 + +/* tMBIAS, after send power up signals to analog, + * how long we should wait for analog powered up. + */ +#define MIPI_DSI_ANA_CTRL 0x2c + +/* [31:8] reserved for future. + * [7:0] tCLK_PRE. + */ +#define MIPI_DSI_CLK_TIM1 0x30 + +/* watchdog for turn around waiting time. */ +#define MIPI_DSI_TURN_WCHDOG 0x34 + +/* When in RxULPS state, how frequency we should to check + * if the TX side out of ULPS state. + */ +#define MIPI_DSI_ULPS_CHECK 0x38 +#define MIPI_DSI_TEST_CTRL0 0x3c +#define MIPI_DSI_TEST_CTRL1 0x40 + +#define NSEC_PER_MSEC 1000000L + +struct phy_meson_axg_mipi_dphy_priv { + struct regmap *regmap; +#if CONFIG_IS_ENABLED(CLK) + struct clk clk; +#endif + struct reset_ctl reset; + struct phy analog; + struct phy_configure_opts_mipi_dphy config; +}; + +static int phy_meson_axg_mipi_dphy_configure(struct phy *phy, void *params) +{ + struct udevice *dev = phy->dev; + struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev); + struct phy_configure_opts_mipi_dphy *config = params; + int ret; + + ret = phy_mipi_dphy_config_validate(config); + if (ret) + return ret; + + ret = generic_phy_configure(&priv->analog, config); + if (ret) + return ret; + + memcpy(&priv->config, config, sizeof(priv->config)); + + return 0; +} + +static int phy_meson_axg_mipi_dphy_power_on(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev); + unsigned long temp; + int ret; + + ret = generic_phy_power_on(&priv->analog); + if (ret) + return ret; + + /* enable phy clock */ + regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL, 0x1); + regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL, + BIT(0) | /* enable the DSI PLL clock . */ + BIT(7) | /* enable pll clock which connected to DDR clock path */ + BIT(8)); /* enable the clock divider counter */ + + /* enable the divider clock out */ + regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(9), BIT(9)); + + /* enable the byte clock generation. */ + regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(12), BIT(12)); + regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), BIT(31)); + regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), 0); + + /* Calculate lanebyteclk period in ps */ + temp = (1000000 * 100) / (priv->config.hs_clk_rate / 1000); + temp = temp * 8 * 10; + + regmap_write(priv->regmap, MIPI_DSI_CLK_TIM, + DIV_ROUND_UP(priv->config.clk_trail, temp) | + (DIV_ROUND_UP(priv->config.clk_post + + priv->config.hs_trail, temp) << 8) | + (DIV_ROUND_UP(priv->config.clk_zero, temp) << 16) | + (DIV_ROUND_UP(priv->config.clk_prepare, temp) << 24)); + regmap_write(priv->regmap, MIPI_DSI_CLK_TIM1, + DIV_ROUND_UP(priv->config.clk_pre, temp)); + + regmap_write(priv->regmap, MIPI_DSI_HS_TIM, + DIV_ROUND_UP(priv->config.hs_exit, temp) | + (DIV_ROUND_UP(priv->config.hs_trail, temp) << 8) | + (DIV_ROUND_UP(priv->config.hs_zero, temp) << 16) | + (DIV_ROUND_UP(priv->config.hs_prepare, temp) << 24)); + + regmap_write(priv->regmap, MIPI_DSI_LP_TIM, + DIV_ROUND_UP(priv->config.lpx, temp) | + (DIV_ROUND_UP(priv->config.ta_sure, temp) << 8) | + (DIV_ROUND_UP(priv->config.ta_go, temp) << 16) | + (DIV_ROUND_UP(priv->config.ta_get, temp) << 24)); + + regmap_write(priv->regmap, MIPI_DSI_ANA_UP_TIM, 0x0100); + regmap_write(priv->regmap, MIPI_DSI_INIT_TIM, + DIV_ROUND_UP(priv->config.init * NSEC_PER_MSEC, temp)); + regmap_write(priv->regmap, MIPI_DSI_WAKEUP_TIM, + DIV_ROUND_UP(priv->config.wakeup * NSEC_PER_MSEC, temp)); + regmap_write(priv->regmap, MIPI_DSI_LPOK_TIM, 0x7C); + regmap_write(priv->regmap, MIPI_DSI_ULPS_CHECK, 0x927C); + regmap_write(priv->regmap, MIPI_DSI_LP_WCHDOG, 0x1000); + regmap_write(priv->regmap, MIPI_DSI_TURN_WCHDOG, 0x1000); + + /* Powerup the analog circuit */ + switch (priv->config.lanes) { + case 1: + regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xe); + break; + case 2: + regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xc); + break; + case 3: + regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0x8); + break; + case 4: + default: + regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0); + break; + } + + /* Trigger a sync active for esc_clk */ + regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(1), BIT(1)); + + return 0; +} + +static int phy_meson_axg_mipi_dphy_power_off(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev); + + regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xf); + regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31)); + + return generic_phy_power_off(&priv->analog); +} + +static int phy_meson_axg_mipi_dphy_init(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev); + int ret; + + ret = generic_phy_init(&priv->analog); + if (ret) + return ret; + + ret = reset_assert(&priv->reset); + udelay(1); + ret |= reset_deassert(&priv->reset); + if (ret) + return ret; + + return 0; +} + +static int phy_meson_axg_mipi_dphy_exit(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev); + int ret; + + ret = generic_phy_exit(&priv->analog); + if (ret) + return ret; + + return reset_assert(&priv->reset); +} + +struct phy_ops meson_axg_mipi_dphy_ops = { + .init = phy_meson_axg_mipi_dphy_init, + .exit = phy_meson_axg_mipi_dphy_exit, + .power_on = phy_meson_axg_mipi_dphy_power_on, + .power_off = phy_meson_axg_mipi_dphy_power_off, + .configure = phy_meson_axg_mipi_dphy_configure, +}; + +int meson_axg_mipi_dphy_probe(struct udevice *dev) +{ + struct phy_meson_axg_mipi_dphy_priv *priv = dev_get_priv(dev); + int ret; + + ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap); + if (ret) + return ret; + + ret = generic_phy_get_by_index(dev, 0, &priv->analog); + if (ret) + return ret; + + ret = reset_get_by_index(dev, 0, &priv->reset); + if (ret == -ENOTSUPP) + return 0; + else if (ret) + return ret; + + ret = reset_deassert(&priv->reset); + if (ret) { + reset_release_all(&priv->reset, 1); + return ret; + } + +#if CONFIG_IS_ENABLED(CLK) + ret = clk_get_by_index(dev, 0, &priv->clk); + if (ret < 0) + return ret; + + ret = clk_enable(&priv->clk); + if (ret && ret != -ENOSYS && ret != -ENOTSUPP) { + pr_err("failed to enable PHY clock\n"); + clk_free(&priv->clk); + return ret; + } +#endif + + return 0; +} + +static const struct udevice_id meson_axg_mipi_dphy_ids[] = { + { .compatible = "amlogic,axg-mipi-dphy" }, + { } +}; + +U_BOOT_DRIVER(meson_axg_mipi_dphy) = { + .name = "meson_axg_mipi_dphy", + .id = UCLASS_PHY, + .of_match = meson_axg_mipi_dphy_ids, + .probe = meson_axg_mipi_dphy_probe, + .ops = &meson_axg_mipi_dphy_ops, + .priv_auto_alloc_size = sizeof(struct phy_meson_axg_mipi_dphy_priv), +}; From patchwork Tue Dec 29 13:59:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neil Armstrong X-Patchwork-Id: 1421212 X-Patchwork-Delegate: narmstrong@baylibre.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.a=rsa-sha256 header.s=20150623 header.b=t6NBDXxL; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4D4wzc0F52z9sVq for ; Wed, 30 Dec 2020 01:00:27 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 7EF8C825D8; Tue, 29 Dec 2020 14:59:56 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.b="t6NBDXxL"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 63F758259D; Tue, 29 Dec 2020 14:59:31 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 393058257D for ; Tue, 29 Dec 2020 14:59:12 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=narmstrong@baylibre.com Received: by mail-wr1-x429.google.com with SMTP id i9so14740373wrc.4 for ; Tue, 29 Dec 2020 05:59:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=NBWh7OY3b66Tlf7qAD5uTFXQ3f7A+qC63D1MRfLh/B4=; b=t6NBDXxLIYVNl+jlo/r1tl+yVNiW2caCk9KA7eiuzTqZVgmNoljPi/9TybXsjuLQrv W5OHRy2CZsKmOxKZfJaycdbzrf/ViguIpGFa9rmYL7B9KAHKV3u48Hvn162pWqXJj6sO ILe+6Qvau2t4HB34v9GSQiFlq9FG3wQAOQ6wrV2TrKyuNLK7Ge6CA3LlvxAJTKhaRTg3 OCClP4UGB7nqkg08IlE+ohhaN8VmgYO5eeuNKkaTVkJUIzYGU1OGwrT0ZyBS+fE2f1rD 6w0lEWxX7ahmPi8FwN/+J3DkO/DxO2WjaSE2t9+yUnwh7u75HYBWY97LI0J1VsEbzo5+ SeBw== 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=NBWh7OY3b66Tlf7qAD5uTFXQ3f7A+qC63D1MRfLh/B4=; b=LXB8TqWeoc1Rh12adCcdFKya3s2aP04NDAPbrmbGeIeF8hg0LvTz9muyngm5Y0xlsf drDKa4NDqMx7Jo7I5GpZFHW1lEZiyDXQ8ucgDyovtVdZ2NEX7WO9Kj0nh4semq3qwyMq iFOo2AMwoH2fUiBAbh8jt7gb+eWX+qHzv2YiOdWjuh9h17VEEKtJXHqawB1Z4ekqNXLt 1xh2IUHpG+RHOstX4a2TMEoQGypBgr2HcSWjXgVrtb6heMJE6uzaN19SedM5AcrNrday REx7DVR5wLrNUI9wi0cggxMGjePzG2PjKHsMolESgGu1t3fJaWRMa3fHoyEB0wK77xaK P+Bw== X-Gm-Message-State: AOAM530SPg6nTOMFMfZy4E0NKXx5gswQmZwu/9ySfV7SbyxavKWKo6vo GnO2ml6jA21qfFudCJ8j/E5FftimJUIoxA== X-Google-Smtp-Source: ABdhPJzukFY1cc2seWe1eGNtGgvpzSgXN3SPyBtXg55eDgFpwBkt7Rbaod6uhMA5NTULJQVTuccMGw== X-Received: by 2002:a5d:674c:: with SMTP id l12mr55234266wrw.399.1609250351140; Tue, 29 Dec 2020 05:59:11 -0800 (PST) Received: from localhost.localdomain ([2a01:e35:2ec0:82b0:2464:c563:b017:7ce1]) by smtp.gmail.com with ESMTPSA id z22sm3666950wml.1.2020.12.29.05.59.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Dec 2020 05:59:10 -0800 (PST) From: Neil Armstrong To: u-boot@lists.denx.de, sjg@chromium.org Cc: u-boot-amlogic@groups.io, Neil Armstrong Subject: [PATCH 4/4] phy: Add Amlogic AXG MIPI PCIe Analog PHY driver Date: Tue, 29 Dec 2020 14:59:01 +0100 Message-Id: <20201229135901.30090-5-narmstrong@baylibre.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201229135901.30090-1-narmstrong@baylibre.com> References: <20201229135901.30090-1-narmstrong@baylibre.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean The Amlogic AXG MIPI + PCIe Analog PHY provides function for both PCIe and MIPI DSI at the same time, and provides the Analog part of MIPI DSI transmission and Analog part of the PCIe lines. Signed-off-by: Neil Armstrong --- drivers/phy/Kconfig | 9 + drivers/phy/Makefile | 1 + drivers/phy/meson-axg-mipi-pcie-analog.c | 233 +++++++++++++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 drivers/phy/meson-axg-mipi-pcie-analog.c diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 00d77eef08..e64802e8f3 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -205,6 +205,15 @@ config MESON_AXG_MIPI_DPHY This is the generic phy driver for the Amlogic Meson AXG MIPI D-PHY. +config MESON_AXG_MIPI_PCIE_ANALOG_PHY + bool "Amlogic Meson AXG MIPI PCIe Analog PHY" + depends on PHY && ARCH_MESON && MESON_AXG + select MIPI_DPHY_HELPERS + imply REGMAP + help + This is the generic phy driver for the Amlogic Meson AXG + MIPI PCIe Analog PHY. + config MSM8916_USB_PHY bool "Qualcomm MSM8916 USB PHY support" depends on PHY diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index b2fd2d06f6..8daf9f6089 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_MESON_GXBB_USB_PHY) += meson-gxbb-usb2.o obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o obj-$(CONFIG_MESON_G12A_USB_PHY) += meson-g12a-usb2.o meson-g12a-usb3-pcie.o obj-$(CONFIG_MESON_AXG_MIPI_DPHY) += meson-axg-mipi-dphy.o +obj-$(CONFIG_MESON_AXG_MIPI_PCIE_ANALOG_PHY) += meson-axg-mipi-pcie-analog.o obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o obj-$(CONFIG_KEYSTONE_USB_PHY) += keystone-usb-phy.o diff --git a/drivers/phy/meson-axg-mipi-pcie-analog.c b/drivers/phy/meson-axg-mipi-pcie-analog.c new file mode 100644 index 0000000000..276e6004e5 --- /dev/null +++ b/drivers/phy/meson-axg-mipi-pcie-analog.c @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Amlogic AXG MIPI + PCIE analog PHY driver + * + * Copyright (C) 2019 Remi Pommarel + * Copyright (C) 2020 BayLibre, SAS + * Author: Neil Armstrong + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define HHI_MIPI_CNTL0 0x00 +#define HHI_MIPI_CNTL0_COMMON_BLOCK GENMASK(31, 28) +#define HHI_MIPI_CNTL0_ENABLE BIT(29) +#define HHI_MIPI_CNTL0_BANDGAP BIT(26) +#define HHI_MIPI_CNTL0_DIF_REF_CTL1 GENMASK(25, 16) +#define HHI_MIPI_CNTL0_DIF_REF_CTL0 GENMASK(15, 0) + +#define HHI_MIPI_CNTL1 0x04 +#define HHI_MIPI_CNTL1_CH0_CML_PDR_EN BIT(12) +#define HHI_MIPI_CNTL1_LP_ABILITY GENMASK(5, 4) +#define HHI_MIPI_CNTL1_LP_RESISTER BIT(3) +#define HHI_MIPI_CNTL1_INPUT_SETTING BIT(2) +#define HHI_MIPI_CNTL1_INPUT_SEL BIT(1) +#define HHI_MIPI_CNTL1_PRBS7_EN BIT(0) + +#define HHI_MIPI_CNTL2 0x08 +#define HHI_MIPI_CNTL2_CH_PU GENMASK(31, 25) +#define HHI_MIPI_CNTL2_CH_CTL GENMASK(24, 19) +#define HHI_MIPI_CNTL2_CH0_DIGDR_EN BIT(18) +#define HHI_MIPI_CNTL2_CH_DIGDR_EN BIT(17) +#define HHI_MIPI_CNTL2_LPULPS_EN BIT(16) +#define HHI_MIPI_CNTL2_CH_EN GENMASK(15, 11) +#define HHI_MIPI_CNTL2_CH0_LP_CTL GENMASK(10, 1) + +#define DSI_LANE_0 (1 << 4) +#define DSI_LANE_1 (1 << 3) +#define DSI_LANE_CLK (1 << 2) +#define DSI_LANE_2 (1 << 1) +#define DSI_LANE_3 (1 << 0) +#define DSI_LANE_MASK (0x1F) + +struct phy_meson_axg_mipi_pcie_analog_priv { + struct regmap *regmap; + struct phy_configure_opts_mipi_dphy config; + bool dsi_configured; + bool dsi_enabled; + bool powered; +}; + +static void phy_bandgap_enable(struct phy_meson_axg_mipi_pcie_analog_priv *priv) +{ + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP); + + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE); +} + +static void phy_bandgap_disable(struct phy_meson_axg_mipi_pcie_analog_priv *priv) +{ + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_BANDGAP, 0); + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_ENABLE, 0); +} + +static void phy_dsi_analog_enable(struct phy_meson_axg_mipi_pcie_analog_priv *priv) +{ + u32 reg; + + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_DIF_REF_CTL1, + FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0x1b8)); + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + BIT(31), BIT(31)); + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_DIF_REF_CTL0, + FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL0, 0x8)); + + regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x001e); + + regmap_write(priv->regmap, HHI_MIPI_CNTL2, + (0x26e0 << 16) | (0x459 << 0)); + + reg = DSI_LANE_CLK; + switch (priv->config.lanes) { + case 4: + reg |= DSI_LANE_3; + fallthrough; + case 3: + reg |= DSI_LANE_2; + fallthrough; + case 2: + reg |= DSI_LANE_1; + fallthrough; + case 1: + reg |= DSI_LANE_0; + break; + default: + reg = 0; + } + + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL2, + HHI_MIPI_CNTL2_CH_EN, + FIELD_PREP(HHI_MIPI_CNTL2_CH_EN, reg)); + + priv->dsi_enabled = true; +} + +static void phy_dsi_analog_disable(struct phy_meson_axg_mipi_pcie_analog_priv *priv) +{ + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_DIF_REF_CTL1, + FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0)); + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, BIT(31), 0); + regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, + HHI_MIPI_CNTL0_DIF_REF_CTL1, 0); + + regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x6); + + regmap_write(priv->regmap, HHI_MIPI_CNTL2, 0x00200000); + + priv->dsi_enabled = false; +} + +static int phy_meson_axg_mipi_pcie_analog_configure(struct phy *phy, void *params) +{ + struct udevice *dev = phy->dev; + struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev); + struct phy_configure_opts_mipi_dphy *config = params; + int ret; + + ret = phy_mipi_dphy_config_validate(config); + if (ret) + return ret; + + memcpy(&priv->config, config, sizeof(priv->config)); + + priv->dsi_configured = true; + + /* If PHY was already powered on, setup the DSI analog part */ + if (priv->powered) { + /* If reconfiguring, disable & reconfigure */ + if (priv->dsi_enabled) + phy_dsi_analog_disable(priv); + + udelay(100); + + phy_dsi_analog_enable(priv); + } + + return 0; +} + +static int phy_meson_axg_mipi_pcie_analog_power_on(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev); + + phy_bandgap_enable(priv); + + if (priv->dsi_configured) + phy_dsi_analog_enable(priv); + + priv->powered = true; + + return 0; +} + +static int phy_meson_axg_mipi_pcie_analog_power_off(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev); + + phy_bandgap_disable(priv); + + if (priv->dsi_enabled) + phy_dsi_analog_disable(priv); + + priv->powered = false; + + return 0; +} + +struct phy_ops meson_axg_mipi_pcie_analog_ops = { + .power_on = phy_meson_axg_mipi_pcie_analog_power_on, + .power_off = phy_meson_axg_mipi_pcie_analog_power_off, + .configure = phy_meson_axg_mipi_pcie_analog_configure, +}; + +int meson_axg_mipi_pcie_analog_probe(struct udevice *dev) +{ + struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev); + + priv->regmap = syscon_node_to_regmap(dev_get_parent(dev)->node); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + return 0; +} + +static const struct udevice_id meson_axg_mipi_pcie_analog_ids[] = { + { .compatible = "amlogic,axg-mipi-pcie-analog-phy" }, + { } +}; + +U_BOOT_DRIVER(meson_axg_mipi_pcie_analog) = { + .name = "meson_axg_mipi_pcie_analog", + .id = UCLASS_PHY, + .of_match = meson_axg_mipi_pcie_analog_ids, + .probe = meson_axg_mipi_pcie_analog_probe, + .ops = &meson_axg_mipi_pcie_analog_ops, + .priv_auto_alloc_size = sizeof(struct phy_meson_axg_mipi_pcie_analog_priv), +};