From patchwork Wed Nov 4 13:47:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neil Armstrong X-Patchwork-Id: 11880653 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4A17415E6 for ; Wed, 4 Nov 2020 13:48:02 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0826222280 for ; Wed, 4 Nov 2020 13:48:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="Dr3SZDJ/"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.b="jSLbyaxP" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0826222280 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-amlogic-bounces+patchwork-linux-amlogic=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=jK/gxXalV3ci2HE5w7qxQy31ehVwpVIn8Ru48tBADs4=; b=Dr3SZDJ/O/680UU9I/YJhMcVM PsBIwhOSKRkAAQMDa5/JdkDui2ByYxNffAzzim2E1vEBvZQWe/C938xje99ld8M7Eou+4IPCYXCwf PcOrU7VhgMiOHUGrudMIsDEtDL+8pAENDxMM7yKsUxQERQDT1kv+Fev6bUncqS1fqvgXTzu1Knf9Q KftIuDibwtQSk7xOBGHlW6R96KQwteOLzwSpGNccE4KT/HhkIL1bA8Om9VMbVhB2pC5w0ujLCMryD t5eDCNOHFPvzSE7irdI33fMQTIgGw0ixiWZPlT5LTp009oylLiwTVs9oex9AYQLCPHnqclDuXu+mL c6t06gCTA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kaJ8f-0005ij-K1; Wed, 04 Nov 2020 13:47:49 +0000 Received: from mail-wr1-x432.google.com ([2a00:1450:4864:20::432]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kaJ8T-0005dJ-Gt for linux-amlogic@lists.infradead.org; Wed, 04 Nov 2020 13:47:41 +0000 Received: by mail-wr1-x432.google.com with SMTP id b8so22131093wrn.0 for ; Wed, 04 Nov 2020 05:47:37 -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=X+jktKSyt59M1RlyoUXQDUiIneqQcY7EbqJCiazlG1Y=; b=jSLbyaxPZKd2BfEHQR+i4qkHFQUDYYmpFXx9Tdpbb6vvPC8oadefWz+kr1x3IG/Sol buywHZChF4DsZQBoxnVS/DQevkehD78cB4ATtgFrnTxucRvG6Blre6vq3Qm59B3+TR13 kAm37d9G9T2frIkEP0MnEo7NnyDMDBIz+N1KeaZon53e/bcE1yL/ZQPBuDlpA9W7uxxB u6XNTSAr/zs1Hj84MneZSTDYs18M5AQZD7yKIl1s1WBeWymzqxV9PZgY01Q0IPdldRKf 8/UIeV+H9Qb1XCs7yln5l1elr9mWLJdG8sGKenoA5MD5hSarooBJqbpZOQctZoNpkyfh yiWg== 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=X+jktKSyt59M1RlyoUXQDUiIneqQcY7EbqJCiazlG1Y=; b=ep7de2ynjMNSILlPqjJALl4WiZuhyC+mVGG3jl781sIWucWeJC04HMBz0VokbKOkQw fd9lcMEVzLe5j0Ae3W+nSuHnHJPrM+Mm/eCPvXukEqKj6UIPH425yu8gCGC+UWCPImeL Wu1DxkhkRmYOw0XM1WRT8Q4vwfqDsam84BFarpy20CbZsxd2a33Hdx0lTJKglzCjX97W E+kRP7WtCkZKhIznSvCrtDQ8dsrO/1hgnFT0IJqLAc18dv8xuhgDjkMjqBdTDyw9HGUQ unxHB35xHjDTEFoy+RojJtGlaUpDvlRF6KK6k3/vShrTPulXkFvOiIHqbytIFb7Jk7os NHlA== X-Gm-Message-State: AOAM532AWpf0cSfOmYu5BsE6jwRSpwnV2X4oj4PLtcAwnUXrvKx7LG0L cBRfVkp8ybDztNEc6KuuDwC/tw== X-Google-Smtp-Source: ABdhPJyBiSSrZ7n/5ZV3G5rqUJ4D+BkannbQm+zSCpWf0KcWLXfH8q7e/EMH258OINRXL5jKjXL9dw== X-Received: by 2002:adf:8562:: with SMTP id 89mr31867445wrh.214.1604497655706; Wed, 04 Nov 2020 05:47:35 -0800 (PST) Received: from localhost.localdomain ([2a01:e35:2ec0:82b0:3d8d:fb08:21c9:faa3]) by smtp.gmail.com with ESMTPSA id 30sm2759586wrs.84.2020.11.04.05.47.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Nov 2020 05:47:34 -0800 (PST) From: Neil Armstrong To: devicetree@vger.kernel.org, kishon@ti.com Subject: [PATCH v3 1/2] dt-bindings: phy: add Amlogic AXG MIPI D-PHY bindings Date: Wed, 4 Nov 2020 14:47:29 +0100 Message-Id: <20201104134730.1545875-2-narmstrong@baylibre.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201104134730.1545875-1-narmstrong@baylibre.com> References: <20201104134730.1545875-1-narmstrong@baylibre.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201104_084737_678132_2B17D9A3 X-CRM114-Status: GOOD ( 14.22 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:432 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-BeenThere: linux-amlogic@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Rob Herring , linux-amlogic@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Neil Armstrong Sender: "linux-amlogic" Errors-To: linux-amlogic-bounces+patchwork-linux-amlogic=patchwork.kernel.org@lists.infradead.org The Amlogic AXg SoCs embeds a MIPI D-PHY to communicate with DSI panels, this adds the bindings. This D-PHY depends on a separate analog PHY. Signed-off-by: Neil Armstrong Reviewed-by: Rob Herring --- .../bindings/phy/amlogic,axg-mipi-dphy.yaml | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/amlogic,axg-mipi-dphy.yaml diff --git a/Documentation/devicetree/bindings/phy/amlogic,axg-mipi-dphy.yaml b/Documentation/devicetree/bindings/phy/amlogic,axg-mipi-dphy.yaml new file mode 100644 index 000000000000..be485f500887 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/amlogic,axg-mipi-dphy.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright 2020 BayLibre, SAS +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/phy/amlogic,axg-mipi-dphy.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Amlogic AXG MIPI D-PHY + +maintainers: + - Neil Armstrong + +properties: + compatible: + enum: + - amlogic,axg-mipi-dphy + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: pclk + + resets: + maxItems: 1 + + reset-names: + items: + - const: phy + + "#phy-cells": + const: 0 + + phys: + maxItems: 1 + + phy-names: + items: + - const: analog + +required: + - compatible + - reg + - clocks + - clock-names + - resets + - reset-names + - phys + - phy-names + - "#phy-cells" + +additionalProperties: false + +examples: + - | + phy@ff640000 { + compatible = "amlogic,axg-mipi-dphy"; + reg = <0xff640000 0x100>; + clocks = <&clk_mipi_dsi_phy>; + clock-names = "pclk"; + resets = <&reset_phy>; + reset-names = "phy"; + phys = <&mipi_pcie_analog_dphy>; + phy-names = "analog"; + #phy-cells = <0>; + }; From patchwork Wed Nov 4 13:47:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neil Armstrong X-Patchwork-Id: 11880655 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2BAB6921 for ; Wed, 4 Nov 2020 13:48:05 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C540921556 for ; Wed, 4 Nov 2020 13:48:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="uibp6o2f"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.b="XbErgI1L" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C540921556 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-amlogic-bounces+patchwork-linux-amlogic=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=PeSVmcUPBYfK/kebIbBJCKHDlZ0madPiYcEGkKLtCbc=; b=uibp6o2fAn9Zv354mGOM1zJaW w4lchD9XRqvHsa+hOyzOXiVs1GkiPIcjrpUAt5jCAjQvQ3OBSE2xMeXTI6l1H33apBmoJDvnK7eDC SC/JNL9AJL4I+n71Sp5OecOPZqy6GZVTJvkP/eQ44495niK3cW6QzgOeYauEVELZFN4cbx+UDq6yz Nwn8Svj0Mx03nvZFO3mjVfwkHrCLTdTmO8jl59EEWYxEFfZwO2tOXOotHsZJfWhF+DRgfLjhYIgFu JDgZpJ6/TqWTYf5Q3D89AApZUf0OUbLxa3KMwbbFtEoCATmQhJX2JIddnd9EjS6ZMMtq9r+BiOr1C jxWMYq7Vg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kaJ8i-0005k6-Ep; Wed, 04 Nov 2020 13:47:52 +0000 Received: from mail-wm1-x343.google.com ([2a00:1450:4864:20::343]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kaJ8U-0005eU-J7 for linux-amlogic@lists.infradead.org; Wed, 04 Nov 2020 13:47:43 +0000 Received: by mail-wm1-x343.google.com with SMTP id c9so2383139wml.5 for ; Wed, 04 Nov 2020 05:47:38 -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=04yWtbVQojNmzNh9sbSaFaPd7hDLCG+6GyyXEhNhYZk=; b=XbErgI1LHIaSSZn5ITnUcJn0ItlKrhIjYWk5aJ/ynplCBus1CRRGARUZ5cmR28xNlx e3sdKtD1eTrXsyB0pjNPcA7xNIVlONIwulLcY8CmwnIKU4GtogwWuL878OWPQ3Z6LSjb ncIptZb9O7hn29dQ3jNMedXWMNlWRKYO783hoHayYTRZS7LuCILs1J6q1BnqPTXp5R+e 1WGGA2W+6ZUkG17pkCOxmAnn4I828ZvOeCvGwUkLq2e3rC+a0EuZR1jCUQhcOkGba04N Po6O0OEGml0d4cgTwOUSnKhsGH1cRHF6PHVbXUg6cy43zZuZeRbjgxOo6yWHXyqp5BsH UFlw== 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=04yWtbVQojNmzNh9sbSaFaPd7hDLCG+6GyyXEhNhYZk=; b=fgRqhDOz8PgfJtT1k/wM4y7QNujY6Brh2GVmCZGZ01ZTMLSpHTdstEJsyZP7wCn2PJ tOmyOBTXD1ESrsbI2GlqSYGAwoZwzmGSsQrwwbfXurwzBPVgt3zby9DxCY3KgrZLiTQC j7qqORZu3rZV1Ofl8owgAuZfjLezV+SVdtZdmyRccWkALkb9oAATl88mqqHx10mCfKqf XERGSFFQrsO945HrqpCuH4WA7u2Fc18/58xYbM2pbOlUfSjBK6Invv0aFsZYai4jikDZ 8To3de4NGnjEQ0f9uKpk3cK8nsSkM434Mldp/uxFMeY2aZ8dYUCwTAG2WsA4HVTGIS5d oJ8w== X-Gm-Message-State: AOAM532iR6z5YFwBSZ5tocmX6InTW6pJQ5c2TxqVc+zwzoHKWHsYcenR UEEPgS/pUyIPcXg9NHrh8hoD5Q== X-Google-Smtp-Source: ABdhPJx/24eHrTiYy24MRkp5uZ0yS8i/K4SRgVjijbgN1T6Zds55VoWc+8uzScT0V1a1XVs++DXccg== X-Received: by 2002:a7b:c94d:: with SMTP id i13mr4666088wml.130.1604497657199; Wed, 04 Nov 2020 05:47:37 -0800 (PST) Received: from localhost.localdomain ([2a01:e35:2ec0:82b0:3d8d:fb08:21c9:faa3]) by smtp.gmail.com with ESMTPSA id 30sm2759586wrs.84.2020.11.04.05.47.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Nov 2020 05:47:36 -0800 (PST) From: Neil Armstrong To: kishon@ti.com Subject: [PATCH v3 2/2] phy: amlogic: Add AXG MIPI D-PHY driver Date: Wed, 4 Nov 2020 14:47:30 +0100 Message-Id: <20201104134730.1545875-3-narmstrong@baylibre.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201104134730.1545875-1-narmstrong@baylibre.com> References: <20201104134730.1545875-1-narmstrong@baylibre.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201104_084738_774693_B9C0071C X-CRM114-Status: GOOD ( 25.17 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:343 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-BeenThere: linux-amlogic@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-amlogic@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Neil Armstrong Sender: "linux-amlogic" Errors-To: linux-amlogic-bounces+patchwork-linux-amlogic=patchwork.kernel.org@lists.infradead.org The Amlogic AXG SoCs embeds a MIPI D-PHY used to communicate with DSI panels. Signed-off-by: Neil Armstrong --- drivers/phy/amlogic/Kconfig | 12 + drivers/phy/amlogic/Makefile | 1 + drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c | 413 ++++++++++++++++++ 3 files changed, 426 insertions(+) create mode 100644 drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig index 617cf073e9aa..99e8a4c7f1f3 100644 --- a/drivers/phy/amlogic/Kconfig +++ b/drivers/phy/amlogic/Kconfig @@ -70,3 +70,15 @@ config PHY_MESON_AXG_MIPI_PCIE_ANALOG Enable this to support the Meson MIPI + PCIE analog PHY found in Meson AXG SoCs. If unsure, say N. + +config PHY_MESON_AXG_MIPI_DPHY + tristate "Meson AXG MIPI DPHY driver" + default ARCH_MESON + depends on OF && (ARCH_MESON || COMPILE_TEST) + select GENERIC_PHY + select REGMAP_MMIO + select GENERIC_PHY_MIPI_DPHY + help + Enable this to support the Meson MIPI DPHY found in Meson AXG + SoCs. + If unsure, say N. diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile index 99702a45e9be..8fa07fbd0d92 100644 --- a/drivers/phy/amlogic/Makefile +++ b/drivers/phy/amlogic/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_PHY_MESON_G12A_USB2) += phy-meson-g12a-usb2.o obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE) += phy-meson-g12a-usb3-pcie.o obj-$(CONFIG_PHY_MESON_AXG_PCIE) += phy-meson-axg-pcie.o obj-$(CONFIG_PHY_MESON_AXG_MIPI_PCIE_ANALOG) += phy-meson-axg-mipi-pcie-analog.o +obj-$(CONFIG_PHY_MESON_AXG_MIPI_DPHY) += phy-meson-axg-mipi-dphy.o diff --git a/drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c b/drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c new file mode 100644 index 000000000000..cd2332bf0e31 --- /dev/null +++ b/drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c @@ -0,0 +1,413 @@ +// 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 + +/* [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 + +struct phy_meson_axg_mipi_dphy_priv { + struct device *dev; + struct regmap *regmap; + struct clk *clk; + struct reset_control *reset; + struct phy *analog; + struct phy_configure_opts_mipi_dphy config; +}; + +static const struct regmap_config phy_meson_axg_mipi_dphy_regmap_conf = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = MIPI_DSI_TEST_CTRL1, +}; + +static int phy_meson_axg_mipi_dphy_init(struct phy *phy) +{ + struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy); + int ret; + + ret = phy_init(priv->analog); + if (ret) + return ret; + + ret = reset_control_reset(priv->reset); + if (ret) + return ret; + + return 0; +} + +static int phy_meson_axg_mipi_dphy_configure(struct phy *phy, + union phy_configure_opts *opts) +{ + struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy); + int ret; + + ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy); + if (ret) + return ret; + + ret = phy_configure(priv->analog, opts); + if (ret) + return ret; + + memcpy(&priv->config, opts, sizeof(priv->config)); + + return 0; +} + +static int phy_meson_axg_mipi_dphy_power_on(struct phy *phy) +{ + struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy); + int ret; + unsigned long temp; + + ret = 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 phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy); + + regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xf); + regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31)); + + phy_power_off(priv->analog); + + return 0; +} + +static int phy_meson_axg_mipi_dphy_exit(struct phy *phy) +{ + struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy); + int ret; + + ret = phy_exit(priv->analog); + if (ret) + return ret; + + return reset_control_reset(priv->reset); +} + +static const struct phy_ops phy_meson_axg_mipi_dphy_ops = { + .configure = phy_meson_axg_mipi_dphy_configure, + .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, + .owner = THIS_MODULE, +}; + +static int phy_meson_axg_mipi_dphy_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct phy_provider *phy_provider; + struct resource *res; + struct phy_meson_axg_mipi_dphy_priv *priv; + struct phy *phy; + void __iomem *base; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + platform_set_drvdata(pdev, priv); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + priv->regmap = devm_regmap_init_mmio(dev, base, + &phy_meson_axg_mipi_dphy_regmap_conf); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + priv->clk = devm_clk_get(dev, "pclk"); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + + priv->reset = devm_reset_control_get(dev, "phy"); + if (IS_ERR(priv->reset)) + return PTR_ERR(priv->reset); + + priv->analog = devm_phy_get(dev, "analog"); + if (IS_ERR(priv->analog)) + return PTR_ERR(priv->analog); + + ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; + + ret = reset_control_deassert(priv->reset); + if (ret) + return ret; + + phy = devm_phy_create(dev, NULL, &phy_meson_axg_mipi_dphy_ops); + if (IS_ERR(phy)) { + ret = PTR_ERR(phy); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to create PHY\n"); + + return ret; + } + + phy_set_drvdata(phy, priv); + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static const struct of_device_id phy_meson_axg_mipi_dphy_of_match[] = { + { .compatible = "amlogic,axg-mipi-dphy", }, + { }, +}; +MODULE_DEVICE_TABLE(of, phy_meson_axg_mipi_dphy_of_match); + +static struct platform_driver phy_meson_axg_mipi_dphy_driver = { + .probe = phy_meson_axg_mipi_dphy_probe, + .driver = { + .name = "phy-meson-axg-mipi-dphy", + .of_match_table = phy_meson_axg_mipi_dphy_of_match, + }, +}; +module_platform_driver(phy_meson_axg_mipi_dphy_driver); + +MODULE_AUTHOR("Neil Armstrong "); +MODULE_DESCRIPTION("Meson AXG MIPI DPHY driver"); +MODULE_LICENSE("GPL v2");