From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.0 required=3.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D0CB1C282CA for ; Tue, 12 Feb 2019 15:14:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8CE79217D9 for ; Tue, 12 Feb 2019 15:14:47 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.b="Ic+LF/+R" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730538AbfBLPOg (ORCPT ); Tue, 12 Feb 2019 10:14:36 -0500 Received: from mail-wr1-f65.google.com ([209.85.221.65]:43365 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730390AbfBLPOa (ORCPT ); Tue, 12 Feb 2019 10:14:30 -0500 Received: by mail-wr1-f65.google.com with SMTP id r2so3049966wrv.10 for ; Tue, 12 Feb 2019 07:14:27 -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=KcipALzLGN9ADimv2gmiw8vXQG9zUG5C+CzkQJqZk+o=; b=Ic+LF/+R4pbWCrs8ouXmpodxYVPrTjLi889BrNn550QcxrBBlO67hT/kiuz6KRJxZv IftwQzjLyVPQrVWQ0ptLpBCg0k9436EMdZJ3BVI/+FiGV/7j7RtoteNJDVKAE0kgYIoG ocQVxJxjW6h7lQ2maGVv4V32kkAZBX89/u3HFm4s+MxlyMBpdhgEH5wz1qwI6aaQQ7Qu fU+xjPTdovNWY5BsIQUUrEuR/bgwlG8LvpLGg2QsoOvXWOvz27lteyBu22ooInTRoA2u LmuRFYS1tVd/OSPp7d5WIlYpkm+8fHDVJw5+ddAbPcdD63bIfpxnGcpdtfnssC6mqxV0 lw/w== 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=KcipALzLGN9ADimv2gmiw8vXQG9zUG5C+CzkQJqZk+o=; b=ZC8LmwbHV13luVEFn46YOvgc7gmbxJnTY44vG3mN0esdmDl2By5onCnu2GihF7O3qS e8D9+6Bis0O/IIPyAEGdoJBfF4vj/B86a6leVhtwnNoFLVKGDtsw95Gv+62OiGs5doKF Q2Vxprqb7GuhIAO6qeRRKoyFLPEEOypoLOnzGu19G1FByzC8cTm6sDsd/OhTEylzV5xb ZOHKtypeYZ+Vj4V4DG3fdc8Ey4XNNiVb4TUfBh71L61sKHO/svPA6MbVlQsdUAHaSR8e 8Ae+1a4r+oM7qjzpFDrYQt+YypzKMLl5QbHSJwNDy6L9sjLsJ4mW8xBPmvHe5NsEYnOh 7k2g== X-Gm-Message-State: AHQUAua/7hwWTSoqWBswr9jTkJosH1YvK7kX9lvut0ykIgE1/7pONrql bwKKKwbh0I4MVg+hDWvJfPVwSA== X-Google-Smtp-Source: AHgI3IY+mjREMc0CThzuKYYhTKn22zcgXsMNLHGItL6ezLiyy4hcjMulQLGKcwSX+UYwb78naJ500w== X-Received: by 2002:adf:8122:: with SMTP id 31mr3337473wrm.48.1549984466884; Tue, 12 Feb 2019 07:14:26 -0800 (PST) Received: from bender.baylibre.local (lmontsouris-657-1-212-31.w90-63.abo.wanadoo.fr. [90.63.244.31]) by smtp.gmail.com with ESMTPSA id c1sm1589515wmb.14.2019.02.12.07.14.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 12 Feb 2019 07:14:25 -0800 (PST) From: Neil Armstrong To: gregkh@linuxfoundation.org, hminas@synopsys.com, balbi@kernel.org, kishon@ti.com Cc: Neil Armstrong , linux-amlogic@lists.infradead.org, linux-usb@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 6/8] phy: amlogic: Add Amlogic G12A USB3 + PCIE Combo PHY Driver Date: Tue, 12 Feb 2019 16:14:11 +0100 Message-Id: <20190212151413.24632-7-narmstrong@baylibre.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190212151413.24632-1-narmstrong@baylibre.com> References: <20190212151413.24632-1-narmstrong@baylibre.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This adds support for the shared USB3 + PCIE PHY found in the Amlogic G12A SoC Family. It supports USB3 Host mode or PCIE 2.0 mode, depending on the layout of the board. Selection is done by the #phy-cells, making the mode static and exclusive. Signed-off-by: Neil Armstrong --- drivers/phy/amlogic/Kconfig | 12 + drivers/phy/amlogic/Makefile | 1 + .../phy/amlogic/phy-meson-g12a-usb3-pcie.c | 414 ++++++++++++++++++ 3 files changed, 427 insertions(+) create mode 100644 drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig index 78d6e194dce9..7ccb9a756aba 100644 --- a/drivers/phy/amlogic/Kconfig +++ b/drivers/phy/amlogic/Kconfig @@ -48,3 +48,15 @@ config PHY_MESON_G12A_USB2 Enable this to support the Meson USB2 PHYs found in Meson G12A SoCs. If unsure, say N. + +config PHY_MESON_G12A_USB3_PCIE + tristate "Meson G12A USB3+PCIE Combo PHY drivers" + default ARCH_MESON + depends on OF && (ARCH_MESON || COMPILE_TEST) + depends on USB_SUPPORT + select GENERIC_PHY + select REGMAP_MMIO + help + Enable this to support the Meson USB3 + PCIE Combi PHY found + in Meson G12A SoCs. + If unsure, say N. diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile index 7d4d10f5a6b3..fdd008e1b19b 100644 --- a/drivers/phy/amlogic/Makefile +++ b/drivers/phy/amlogic/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o obj-$(CONFIG_PHY_MESON_GXL_USB2) += phy-meson-gxl-usb2.o obj-$(CONFIG_PHY_MESON_G12A_USB2) += phy-meson-g12a-usb2.o obj-$(CONFIG_PHY_MESON_GXL_USB3) += phy-meson-gxl-usb3.o +obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE) += phy-meson-g12a-usb3-pcie.o diff --git a/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c b/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c new file mode 100644 index 000000000000..59eae98928e9 --- /dev/null +++ b/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c @@ -0,0 +1,414 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Amlogic G12A USB3 + PCIE Combo PHY driver + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved + * Copyright (C) 2019 BayLibre, SAS + * Author: Neil Armstrong + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PHY_R0 0x00 + #define PHY_R0_PCIE_POWER_STATE GENMASK(4, 0) + #define PHY_R0_PCIE_USB3_SWITCH GENMASK(6, 5) + +#define PHY_R1 0x04 + #define PHY_R1_PHY_TX1_TERM_OFFSET GENMASK(4, 0) + #define PHY_R1_PHY_TX0_TERM_OFFSET GENMASK(9, 5) + #define PHY_R1_PHY_RX1_EQ GENMASK(12, 10) + #define PHY_R1_PHY_RX0_EQ GENMASK(15, 13) + #define PHY_R1_PHY_LOS_LEVEL GENMASK(20, 16) + #define PHY_R1_PHY_LOS_BIAS GENMASK(23, 21) + #define PHY_R1_PHY_REF_CLKDIV2 BIT(24) + #define PHY_R1_PHY_MPLL_MULTIPLIER GENMASK(31, 25) + +#define PHY_R2 0x08 + #define PHY_R2_PCS_TX_DEEMPH_GEN2_6DB GENMASK(5, 0) + #define PHY_R2_PCS_TX_DEEMPH_GEN2_3P5DB GENMASK(11, 6) + #define PHY_R2_PCS_TX_DEEMPH_GEN1 GENMASK(17, 12) + #define PHY_R2_PHY_TX_VBOOST_LVL GENMASK(20, 18) + +#define PHY_R4 0x10 + #define PHY_R4_PHY_CR_WRITE BIT(0) + #define PHY_R4_PHY_CR_READ BIT(1) + #define PHY_R4_PHY_CR_DATA_IN GENMASK(17, 2) + #define PHY_R4_PHY_CR_CAP_DATA BIT(18) + #define PHY_R4_PHY_CR_CAP_ADDR BIT(19) + +#define PHY_R5 0x14 + #define PHY_R5_PHY_CR_DATA_OUT GENMASK(15, 0) + #define PHY_R5_PHY_CR_ACK BIT(16) + #define PHY_R5_PHY_BS_OUT BIT(17) + +struct phy_g12a_usb3_pcie_priv { + struct regmap *regmap; + struct regmap *regmap_cr; + struct clk *clk_ref; + struct reset_control *reset; + struct phy *phy; + unsigned int mode; +}; + +static const struct regmap_config phy_g12a_usb3_pcie_regmap_conf = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = PHY_R5, +}; + +static int phy_g12a_usb3_pcie_cr_bus_addr(struct phy_g12a_usb3_pcie_priv *priv, + unsigned int addr) +{ + unsigned int val, reg; + int ret; + + reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, addr); + + regmap_write(priv->regmap, PHY_R4, reg); + regmap_write(priv->regmap, PHY_R4, reg); + + regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_ADDR); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + regmap_write(priv->regmap, PHY_R4, reg); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + !(val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + return 0; +} + +static int phy_g12a_usb3_pcie_cr_bus_read(void *context, unsigned int addr, + unsigned int *data) +{ + struct phy_g12a_usb3_pcie_priv *priv = context; + unsigned int val; + int ret; + + ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr); + if (ret) + return ret; + + regmap_write(priv->regmap, PHY_R4, 0); + regmap_write(priv->regmap, PHY_R4, PHY_R4_PHY_CR_READ); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + *data = FIELD_GET(PHY_R5_PHY_CR_DATA_OUT, val); + + regmap_write(priv->regmap, PHY_R4, 0); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + !(val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + return 0; +} + +static int phy_g12a_usb3_pcie_cr_bus_write(void *context, unsigned int addr, + unsigned int data) +{ + struct phy_g12a_usb3_pcie_priv *priv = context; + unsigned int val, reg; + int ret; + + ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr); + if (ret) + return ret; + + reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, data); + + regmap_write(priv->regmap, PHY_R4, reg); + regmap_write(priv->regmap, PHY_R4, reg); + + regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_DATA); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + regmap_write(priv->regmap, PHY_R4, reg); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK) == 0, + 5, 1000); + if (ret) + return ret; + + regmap_write(priv->regmap, PHY_R4, reg); + + regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_WRITE); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + regmap_write(priv->regmap, PHY_R4, reg); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK) == 0, + 5, 1000); + if (ret) + return ret; + + return 0; +} + +static const struct regmap_config phy_g12a_usb3_pcie_cr_regmap_conf = { + .reg_bits = 16, + .val_bits = 16, + .reg_read = phy_g12a_usb3_pcie_cr_bus_read, + .reg_write = phy_g12a_usb3_pcie_cr_bus_write, + .max_register = 0xffff, + .fast_io = true, +}; + +static int phy_g12a_usb3_init(struct phy *phy) +{ + struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy); + int data, ret; + + /* Switch PHY to USB3 */ + regmap_update_bits(priv->regmap, PHY_R0, + PHY_R0_PCIE_USB3_SWITCH, + PHY_R0_PCIE_USB3_SWITCH); + + /* + * WORKAROUND: There is SSPHY suspend bug due to + * which USB enumerates + * in HS mode instead of SS mode. Workaround it by asserting + * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus + * mode + */ + ret = regmap_update_bits(priv->regmap_cr, 0x102d, BIT(7), BIT(7)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap_cr, 0x1010, 0xff0, 20); + if (ret) + return ret; + + /* + * Fix RX Equalization setting as follows + * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 + * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 + * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3 + * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 + */ + ret = regmap_read(priv->regmap_cr, 0x1006, &data); + if (ret) + return ret; + + data &= ~BIT(6); + data |= BIT(7); + data &= ~(0x7 << 8); + data |= (0x3 << 8); + data |= (1 << 11); + ret = regmap_write(priv->regmap_cr, 0x1006, data); + if (ret) + return ret; + + /* + * Set EQ and TX launch amplitudes as follows + * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22 + * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127 + * LANE0.TX_OVRD_DRV_LO.EN set to 1. + */ + ret = regmap_read(priv->regmap_cr, 0x1002, &data); + if (ret) + return ret; + + data &= ~0x3f80; + data |= (0x16 << 7); + data &= ~0x7f; + data |= (0x7f | BIT(14)); + ret = regmap_write(priv->regmap_cr, 0x1002, data); + if (ret) + return ret; + + /* + * MPLL_LOOP_CTL.PROP_CNTRL = 8 + */ + ret = regmap_update_bits(priv->regmap_cr, 0x30, 0xf << 4, 8 << 4); + if (ret) + return ret; + + regmap_update_bits(priv->regmap, PHY_R2, + PHY_R2_PHY_TX_VBOOST_LVL, + FIELD_PREP(PHY_R2_PHY_TX_VBOOST_LVL, 0x4)); + + regmap_update_bits(priv->regmap, PHY_R1, + PHY_R1_PHY_LOS_BIAS | PHY_R1_PHY_LOS_LEVEL, + FIELD_PREP(PHY_R1_PHY_LOS_BIAS, 4) | + FIELD_PREP(PHY_R1_PHY_LOS_LEVEL, 9)); + + return 0; +} + +static int phy_g12a_usb3_pcie_init(struct phy *phy) +{ + struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy); + int ret; + + ret = reset_control_reset(priv->reset); + if (ret) + return ret; + + if (priv->mode == PHY_TYPE_USB3) + return phy_g12a_usb3_init(phy); + + /* Power UP PCIE */ + regmap_update_bits(priv->regmap, PHY_R0, + PHY_R0_PCIE_POWER_STATE, + FIELD_PREP(PHY_R0_PCIE_POWER_STATE, 0x1c)); + + return 0; +} + +static int phy_g12a_usb3_pcie_exit(struct phy *phy) +{ + struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy); + int ret; + + return reset_control_reset(priv->reset); +} + +static struct phy *phy_g12a_usb3_pcie_xlate(struct device *dev, + struct of_phandle_args *args) +{ + struct phy_g12a_usb3_pcie_priv *priv = dev_get_drvdata(dev); + unsigned int mode; + + if (args->args_count < 1) { + dev_err(dev, "invalid number of arguments\n"); + return ERR_PTR(-EINVAL); + } + + mode = args->args[0]; + + if (mode != PHY_TYPE_USB3 && mode != PHY_TYPE_PCIE) { + dev_err(dev, "invalid phy mode select argument\n"); + return ERR_PTR(-EINVAL); + } + + priv->mode = mode; + + return priv->phy; +} + +static const struct phy_ops phy_g12a_usb3_pcie_ops = { + .init = phy_g12a_usb3_pcie_init, + .exit = phy_g12a_usb3_pcie_exit, + .owner = THIS_MODULE, +}; + +static int phy_g12a_usb3_pcie_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct phy_g12a_usb3_pcie_priv *priv; + struct resource *res; + struct phy_provider *phy_provider; + void __iomem *base; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + 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_g12a_usb3_pcie_regmap_conf); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + priv->regmap_cr = devm_regmap_init(dev, NULL, priv, + &phy_g12a_usb3_pcie_cr_regmap_conf); + if (IS_ERR(priv->regmap_cr)) + return PTR_ERR(priv->regmap_cr); + + priv->clk_ref = devm_clk_get(dev, "ref_clk"); + if (IS_ERR(priv->clk_ref)) + return PTR_ERR(priv->clk_ref); + + ret = clk_prepare_enable(priv->clk_ref); + if (ret) + goto err_disable_clk_ref; + + priv->reset = devm_reset_control_array_get(dev, false, false); + if (IS_ERR(priv->reset)) + return PTR_ERR(priv->reset); + + priv->phy = devm_phy_create(dev, np, &phy_g12a_usb3_pcie_ops); + if (IS_ERR(priv->phy)) { + ret = PTR_ERR(priv->phy); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to create PHY\n"); + + return ret; + } + + phy_set_drvdata(priv->phy, priv); + dev_set_drvdata(dev, priv); + + phy_provider = devm_of_phy_provider_register(dev, + phy_g12a_usb3_pcie_xlate); + + return PTR_ERR_OR_ZERO(phy_provider); + +err_disable_clk_ref: + clk_disable_unprepare(priv->clk_ref); + + return ret; +} + +static const struct of_device_id phy_g12a_usb3_pcie_of_match[] = { + { .compatible = "amlogic,g12a-usb3-pcie-phy", }, + { }, +}; +MODULE_DEVICE_TABLE(of, phy_g12a_usb3_pcie_of_match); + +static struct platform_driver phy_g12a_usb3_pcie_driver = { + .probe = phy_g12a_usb3_pcie_probe, + .driver = { + .name = "phy-g12a-usb3-pcie", + .of_match_table = phy_g12a_usb3_pcie_of_match, + }, +}; +module_platform_driver(phy_g12a_usb3_pcie_driver); + +MODULE_AUTHOR("Neil Armstrong "); +MODULE_DESCRIPTION("Amlogic G12A USB3 + PCIE Combo PHY driver"); +MODULE_LICENSE("GPL v2"); -- 2.20.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [6/8] phy: amlogic: Add Amlogic G12A USB3 + PCIE Combo PHY Driver From: Neil Armstrong Message-Id: <20190212151413.24632-7-narmstrong@baylibre.com> Date: Tue, 12 Feb 2019 16:14:11 +0100 To: gregkh@linuxfoundation.org, hminas@synopsys.com, balbi@kernel.org, kishon@ti.com Cc: Neil Armstrong , linux-amlogic@lists.infradead.org, linux-usb@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org List-ID: VGhpcyBhZGRzIHN1cHBvcnQgZm9yIHRoZSBzaGFyZWQgVVNCMyArIFBDSUUgUEhZIGZvdW5kIGlu IHRoZQpBbWxvZ2ljIEcxMkEgU29DIEZhbWlseS4KCkl0IHN1cHBvcnRzIFVTQjMgSG9zdCBtb2Rl IG9yIFBDSUUgMi4wIG1vZGUsIGRlcGVuZGluZyBvbiB0aGUgbGF5b3V0IG9mCnRoZSBib2FyZC4K ClNlbGVjdGlvbiBpcyBkb25lIGJ5IHRoZSAjcGh5LWNlbGxzLCBtYWtpbmcgdGhlIG1vZGUgc3Rh dGljIGFuZCBleGNsdXNpdmUuCgpTaWduZWQtb2ZmLWJ5OiBOZWlsIEFybXN0cm9uZyA8bmFybXN0 cm9uZ0BiYXlsaWJyZS5jb20+Ci0tLQogZHJpdmVycy9waHkvYW1sb2dpYy9LY29uZmlnICAgICAg ICAgICAgICAgICAgIHwgIDEyICsKIGRyaXZlcnMvcGh5L2FtbG9naWMvTWFrZWZpbGUgICAgICAg ICAgICAgICAgICB8ICAgMSArCiAuLi4vcGh5L2FtbG9naWMvcGh5LW1lc29uLWcxMmEtdXNiMy1w Y2llLmMgICAgfCA0MTQgKysrKysrKysrKysrKysrKysrCiAzIGZpbGVzIGNoYW5nZWQsIDQyNyBp bnNlcnRpb25zKCspCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9waHkvYW1sb2dpYy9waHkt bWVzb24tZzEyYS11c2IzLXBjaWUuYwoKZGlmZiAtLWdpdCBhL2RyaXZlcnMvcGh5L2FtbG9naWMv S2NvbmZpZyBiL2RyaXZlcnMvcGh5L2FtbG9naWMvS2NvbmZpZwppbmRleCA3OGQ2ZTE5NGRjZTku LjdjY2I5YTc1NmFiYSAxMDA2NDQKLS0tIGEvZHJpdmVycy9waHkvYW1sb2dpYy9LY29uZmlnCisr KyBiL2RyaXZlcnMvcGh5L2FtbG9naWMvS2NvbmZpZwpAQCAtNDgsMyArNDgsMTUgQEAgY29uZmln IFBIWV9NRVNPTl9HMTJBX1VTQjIKIAkgIEVuYWJsZSB0aGlzIHRvIHN1cHBvcnQgdGhlIE1lc29u IFVTQjIgUEhZcyBmb3VuZCBpbiBNZXNvbgogCSAgRzEyQSBTb0NzLgogCSAgSWYgdW5zdXJlLCBz YXkgTi4KKworY29uZmlnIFBIWV9NRVNPTl9HMTJBX1VTQjNfUENJRQorCXRyaXN0YXRlICJNZXNv biBHMTJBIFVTQjMrUENJRSBDb21ibyBQSFkgZHJpdmVycyIKKwlkZWZhdWx0IEFSQ0hfTUVTT04K KwlkZXBlbmRzIG9uIE9GICYmIChBUkNIX01FU09OIHx8IENPTVBJTEVfVEVTVCkKKwlkZXBlbmRz IG9uIFVTQl9TVVBQT1JUCisJc2VsZWN0IEdFTkVSSUNfUEhZCisJc2VsZWN0IFJFR01BUF9NTUlP CisJaGVscAorCSAgRW5hYmxlIHRoaXMgdG8gc3VwcG9ydCB0aGUgTWVzb24gVVNCMyArIFBDSUUg Q29tYmkgUEhZIGZvdW5kCisJICBpbiBNZXNvbiBHMTJBIFNvQ3MuCisJICBJZiB1bnN1cmUsIHNh eSBOLgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9waHkvYW1sb2dpYy9NYWtlZmlsZSBiL2RyaXZlcnMv cGh5L2FtbG9naWMvTWFrZWZpbGUKaW5kZXggN2Q0ZDEwZjVhNmIzLi5mZGQwMDhlMWIxOWIgMTAw NjQ0Ci0tLSBhL2RyaXZlcnMvcGh5L2FtbG9naWMvTWFrZWZpbGUKKysrIGIvZHJpdmVycy9waHkv YW1sb2dpYy9NYWtlZmlsZQpAQCAtMiwzICsyLDQgQEAgb2JqLSQoQ09ORklHX1BIWV9NRVNPTjhC X1VTQjIpCQkrPSBwaHktbWVzb244Yi11c2IyLm8KIG9iai0kKENPTkZJR19QSFlfTUVTT05fR1hM X1VTQjIpCSs9IHBoeS1tZXNvbi1neGwtdXNiMi5vCiBvYmotJChDT05GSUdfUEhZX01FU09OX0cx MkFfVVNCMikJKz0gcGh5LW1lc29uLWcxMmEtdXNiMi5vCiBvYmotJChDT05GSUdfUEhZX01FU09O X0dYTF9VU0IzKQkrPSBwaHktbWVzb24tZ3hsLXVzYjMubworb2JqLSQoQ09ORklHX1BIWV9NRVNP Tl9HMTJBX1VTQjNfUENJRSkJKz0gcGh5LW1lc29uLWcxMmEtdXNiMy1wY2llLm8KZGlmZiAtLWdp dCBhL2RyaXZlcnMvcGh5L2FtbG9naWMvcGh5LW1lc29uLWcxMmEtdXNiMy1wY2llLmMgYi9kcml2 ZXJzL3BoeS9hbWxvZ2ljL3BoeS1tZXNvbi1nMTJhLXVzYjMtcGNpZS5jCm5ldyBmaWxlIG1vZGUg MTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwMC4uNTllYWU5ODkyOGU5Ci0tLSAvZGV2L251bGwKKysr IGIvZHJpdmVycy9waHkvYW1sb2dpYy9waHktbWVzb24tZzEyYS11c2IzLXBjaWUuYwpAQCAtMCww ICsxLDQxNCBAQAorLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAKKy8qCisgKiBB bWxvZ2ljIEcxMkEgVVNCMyArIFBDSUUgQ29tYm8gUEhZIGRyaXZlcgorICoKKyAqIENvcHlyaWdo dCAoQykgMjAxNyBBbWxvZ2ljLCBJbmMuIEFsbCByaWdodHMgcmVzZXJ2ZWQKKyAqIENvcHlyaWdo dCAoQykgMjAxOSBCYXlMaWJyZSwgU0FTCisgKiBBdXRob3I6IE5laWwgQXJtc3Ryb25nIDxuYXJt c3Ryb25nQGJheWxpYnJlLmNvbT4KKyAqLworCisjaW5jbHVkZSA8bGludXgvYml0ZmllbGQuaD4K KyNpbmNsdWRlIDxsaW51eC9iaXRvcHMuaD4KKyNpbmNsdWRlIDxsaW51eC9jbGsuaD4KKyNpbmNs dWRlIDxsaW51eC9tb2R1bGUuaD4KKyNpbmNsdWRlIDxsaW51eC9vZl9kZXZpY2UuaD4KKyNpbmNs dWRlIDxsaW51eC9waHkvcGh5Lmg+CisjaW5jbHVkZSA8bGludXgvcmVnbWFwLmg+CisjaW5jbHVk ZSA8bGludXgvcmVzZXQuaD4KKyNpbmNsdWRlIDxsaW51eC9wbGF0Zm9ybV9kZXZpY2UuaD4KKyNp bmNsdWRlIDxkdC1iaW5kaW5ncy9waHkvcGh5Lmg+CisKKyNkZWZpbmUgUEhZX1IwCQkJCQkJCTB4 MDAKKwkjZGVmaW5lIFBIWV9SMF9QQ0lFX1BPV0VSX1NUQVRFCQkJCUdFTk1BU0soNCwgMCkKKwkj ZGVmaW5lIFBIWV9SMF9QQ0lFX1VTQjNfU1dJVENICQkJCUdFTk1BU0soNiwgNSkKKworI2RlZmlu ZSBQSFlfUjEJCQkJCQkJMHgwNAorCSNkZWZpbmUgUEhZX1IxX1BIWV9UWDFfVEVSTV9PRkZTRVQJ CQlHRU5NQVNLKDQsIDApCisJI2RlZmluZSBQSFlfUjFfUEhZX1RYMF9URVJNX09GRlNFVAkJCUdF Tk1BU0soOSwgNSkKKwkjZGVmaW5lIFBIWV9SMV9QSFlfUlgxX0VRCQkJCUdFTk1BU0soMTIsIDEw KQorCSNkZWZpbmUgUEhZX1IxX1BIWV9SWDBfRVEJCQkJR0VOTUFTSygxNSwgMTMpCisJI2RlZmlu ZSBQSFlfUjFfUEhZX0xPU19MRVZFTAkJCQlHRU5NQVNLKDIwLCAxNikKKwkjZGVmaW5lIFBIWV9S MV9QSFlfTE9TX0JJQVMJCQkJR0VOTUFTSygyMywgMjEpCisJI2RlZmluZSBQSFlfUjFfUEhZX1JF Rl9DTEtESVYyCQkJCUJJVCgyNCkKKwkjZGVmaW5lIFBIWV9SMV9QSFlfTVBMTF9NVUxUSVBMSUVS CQkJR0VOTUFTSygzMSwgMjUpCisKKyNkZWZpbmUgUEhZX1IyCQkJCQkJCTB4MDgKKwkjZGVmaW5l IFBIWV9SMl9QQ1NfVFhfREVFTVBIX0dFTjJfNkRCCQkJR0VOTUFTSyg1LCAwKQorCSNkZWZpbmUg UEhZX1IyX1BDU19UWF9ERUVNUEhfR0VOMl8zUDVEQgkJCUdFTk1BU0soMTEsIDYpCisJI2RlZmlu ZSBQSFlfUjJfUENTX1RYX0RFRU1QSF9HRU4xCQkJR0VOTUFTSygxNywgMTIpCisJI2RlZmluZSBQ SFlfUjJfUEhZX1RYX1ZCT09TVF9MVkwJCQlHRU5NQVNLKDIwLCAxOCkKKworI2RlZmluZSBQSFlf UjQJCQkJCQkJMHgxMAorCSNkZWZpbmUgUEhZX1I0X1BIWV9DUl9XUklURQkJCQlCSVQoMCkKKwkj ZGVmaW5lIFBIWV9SNF9QSFlfQ1JfUkVBRAkJCQlCSVQoMSkKKwkjZGVmaW5lIFBIWV9SNF9QSFlf Q1JfREFUQV9JTgkJCQlHRU5NQVNLKDE3LCAyKQorCSNkZWZpbmUgUEhZX1I0X1BIWV9DUl9DQVBf REFUQQkJCQlCSVQoMTgpCisJI2RlZmluZSBQSFlfUjRfUEhZX0NSX0NBUF9BRERSCQkJCUJJVCgx OSkKKworI2RlZmluZSBQSFlfUjUJCQkJCQkJMHgxNAorCSNkZWZpbmUgUEhZX1I1X1BIWV9DUl9E QVRBX09VVAkJCQlHRU5NQVNLKDE1LCAwKQorCSNkZWZpbmUgUEhZX1I1X1BIWV9DUl9BQ0sJCQkJ QklUKDE2KQorCSNkZWZpbmUgUEhZX1I1X1BIWV9CU19PVVQJCQkJQklUKDE3KQorCitzdHJ1Y3Qg cGh5X2cxMmFfdXNiM19wY2llX3ByaXYgeworCXN0cnVjdCByZWdtYXAJCSpyZWdtYXA7CisJc3Ry dWN0IHJlZ21hcAkJKnJlZ21hcF9jcjsKKwlzdHJ1Y3QgY2xrCQkqY2xrX3JlZjsKKwlzdHJ1Y3Qg cmVzZXRfY29udHJvbAkqcmVzZXQ7CisJc3RydWN0IHBoeQkJKnBoeTsKKwl1bnNpZ25lZCBpbnQJ CW1vZGU7Cit9OworCitzdGF0aWMgY29uc3Qgc3RydWN0IHJlZ21hcF9jb25maWcgcGh5X2cxMmFf dXNiM19wY2llX3JlZ21hcF9jb25mID0geworCS5yZWdfYml0cyA9IDgsCisJLnZhbF9iaXRzID0g MzIsCisJLnJlZ19zdHJpZGUgPSA0LAorCS5tYXhfcmVnaXN0ZXIgPSBQSFlfUjUsCit9OworCitz dGF0aWMgaW50IHBoeV9nMTJhX3VzYjNfcGNpZV9jcl9idXNfYWRkcihzdHJ1Y3QgcGh5X2cxMmFf dXNiM19wY2llX3ByaXYgKnByaXYsCisJCQkJCSAgdW5zaWduZWQgaW50IGFkZHIpCit7CisJdW5z aWduZWQgaW50IHZhbCwgcmVnOworCWludCByZXQ7CisKKwlyZWcgPSBGSUVMRF9QUkVQKFBIWV9S NF9QSFlfQ1JfREFUQV9JTiwgYWRkcik7CisKKwlyZWdtYXBfd3JpdGUocHJpdi0+cmVnbWFwLCBQ SFlfUjQsIHJlZyk7CisJcmVnbWFwX3dyaXRlKHByaXYtPnJlZ21hcCwgUEhZX1I0LCByZWcpOwor CisJcmVnbWFwX3dyaXRlKHByaXYtPnJlZ21hcCwgUEhZX1I0LCByZWcgfCBQSFlfUjRfUEhZX0NS X0NBUF9BRERSKTsKKworCXJldCA9IHJlZ21hcF9yZWFkX3BvbGxfdGltZW91dChwcml2LT5yZWdt YXAsIFBIWV9SNSwgdmFsLAorCQkJCSAgICAgICAodmFsICYgUEhZX1I1X1BIWV9DUl9BQ0spLAor CQkJCSAgICAgICA1LCAxMDAwKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJcmVnbWFw X3dyaXRlKHByaXYtPnJlZ21hcCwgUEhZX1I0LCByZWcpOworCisJcmV0ID0gcmVnbWFwX3JlYWRf cG9sbF90aW1lb3V0KHByaXYtPnJlZ21hcCwgUEhZX1I1LCB2YWwsCisJCQkJICAgICAgICEodmFs ICYgUEhZX1I1X1BIWV9DUl9BQ0spLAorCQkJCSAgICAgICA1LCAxMDAwKTsKKwlpZiAocmV0KQor CQlyZXR1cm4gcmV0OworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgcGh5X2cxMmFfdXNi M19wY2llX2NyX2J1c19yZWFkKHZvaWQgKmNvbnRleHQsIHVuc2lnbmVkIGludCBhZGRyLAorCQkJ CQkgIHVuc2lnbmVkIGludCAqZGF0YSkKK3sKKwlzdHJ1Y3QgcGh5X2cxMmFfdXNiM19wY2llX3By aXYgKnByaXYgPSBjb250ZXh0OworCXVuc2lnbmVkIGludCB2YWw7CisJaW50IHJldDsKKworCXJl dCA9IHBoeV9nMTJhX3VzYjNfcGNpZV9jcl9idXNfYWRkcihwcml2LCBhZGRyKTsKKwlpZiAocmV0 KQorCQlyZXR1cm4gcmV0OworCisJcmVnbWFwX3dyaXRlKHByaXYtPnJlZ21hcCwgUEhZX1I0LCAw KTsKKwlyZWdtYXBfd3JpdGUocHJpdi0+cmVnbWFwLCBQSFlfUjQsIFBIWV9SNF9QSFlfQ1JfUkVB RCk7CisKKwlyZXQgPSByZWdtYXBfcmVhZF9wb2xsX3RpbWVvdXQocHJpdi0+cmVnbWFwLCBQSFlf UjUsIHZhbCwKKwkJCQkgICAgICAgKHZhbCAmIFBIWV9SNV9QSFlfQ1JfQUNLKSwKKwkJCQkgICAg ICAgNSwgMTAwMCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCSpkYXRhID0gRklFTERf R0VUKFBIWV9SNV9QSFlfQ1JfREFUQV9PVVQsIHZhbCk7CisKKwlyZWdtYXBfd3JpdGUocHJpdi0+ cmVnbWFwLCBQSFlfUjQsIDApOworCisJcmV0ID0gcmVnbWFwX3JlYWRfcG9sbF90aW1lb3V0KHBy aXYtPnJlZ21hcCwgUEhZX1I1LCB2YWwsCisJCQkJICAgICAgICEodmFsICYgUEhZX1I1X1BIWV9D Ul9BQ0spLAorCQkJCSAgICAgICA1LCAxMDAwKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0Owor CisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgcGh5X2cxMmFfdXNiM19wY2llX2NyX2J1c193 cml0ZSh2b2lkICpjb250ZXh0LCB1bnNpZ25lZCBpbnQgYWRkciwKKwkJCQkJICAgdW5zaWduZWQg aW50IGRhdGEpCit7CisJc3RydWN0IHBoeV9nMTJhX3VzYjNfcGNpZV9wcml2ICpwcml2ID0gY29u dGV4dDsKKwl1bnNpZ25lZCBpbnQgdmFsLCByZWc7CisJaW50IHJldDsKKworCXJldCA9IHBoeV9n MTJhX3VzYjNfcGNpZV9jcl9idXNfYWRkcihwcml2LCBhZGRyKTsKKwlpZiAocmV0KQorCQlyZXR1 cm4gcmV0OworCisJcmVnID0gRklFTERfUFJFUChQSFlfUjRfUEhZX0NSX0RBVEFfSU4sIGRhdGEp OworCisJcmVnbWFwX3dyaXRlKHByaXYtPnJlZ21hcCwgUEhZX1I0LCByZWcpOworCXJlZ21hcF93 cml0ZShwcml2LT5yZWdtYXAsIFBIWV9SNCwgcmVnKTsKKworCXJlZ21hcF93cml0ZShwcml2LT5y ZWdtYXAsIFBIWV9SNCwgcmVnIHwgUEhZX1I0X1BIWV9DUl9DQVBfREFUQSk7CisKKwlyZXQgPSBy ZWdtYXBfcmVhZF9wb2xsX3RpbWVvdXQocHJpdi0+cmVnbWFwLCBQSFlfUjUsIHZhbCwKKwkJCQkg ICAgICAgKHZhbCAmIFBIWV9SNV9QSFlfQ1JfQUNLKSwKKwkJCQkgICAgICAgNSwgMTAwMCk7CisJ aWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCXJlZ21hcF93cml0ZShwcml2LT5yZWdtYXAsIFBI WV9SNCwgcmVnKTsKKworCXJldCA9IHJlZ21hcF9yZWFkX3BvbGxfdGltZW91dChwcml2LT5yZWdt YXAsIFBIWV9SNSwgdmFsLAorCQkJCSAgICAgICAodmFsICYgUEhZX1I1X1BIWV9DUl9BQ0spID09 IDAsCisJCQkJICAgICAgIDUsIDEwMDApOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwly ZWdtYXBfd3JpdGUocHJpdi0+cmVnbWFwLCBQSFlfUjQsIHJlZyk7CisKKwlyZWdtYXBfd3JpdGUo cHJpdi0+cmVnbWFwLCBQSFlfUjQsIHJlZyB8IFBIWV9SNF9QSFlfQ1JfV1JJVEUpOworCisJcmV0 ID0gcmVnbWFwX3JlYWRfcG9sbF90aW1lb3V0KHByaXYtPnJlZ21hcCwgUEhZX1I1LCB2YWwsCisJ CQkJICAgICAgICh2YWwgJiBQSFlfUjVfUEhZX0NSX0FDSyksCisJCQkJICAgICAgIDUsIDEwMDAp OworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwlyZWdtYXBfd3JpdGUocHJpdi0+cmVnbWFw LCBQSFlfUjQsIHJlZyk7CisKKwlyZXQgPSByZWdtYXBfcmVhZF9wb2xsX3RpbWVvdXQocHJpdi0+ cmVnbWFwLCBQSFlfUjUsIHZhbCwKKwkJCQkgICAgICAgKHZhbCAmIFBIWV9SNV9QSFlfQ1JfQUNL KSA9PSAwLAorCQkJCSAgICAgICA1LCAxMDAwKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0Owor CisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgcmVnbWFwX2NvbmZpZyBwaHlf ZzEyYV91c2IzX3BjaWVfY3JfcmVnbWFwX2NvbmYgPSB7CisJLnJlZ19iaXRzID0gMTYsCisJLnZh bF9iaXRzID0gMTYsCisJLnJlZ19yZWFkID0gcGh5X2cxMmFfdXNiM19wY2llX2NyX2J1c19yZWFk LAorCS5yZWdfd3JpdGUgPSBwaHlfZzEyYV91c2IzX3BjaWVfY3JfYnVzX3dyaXRlLAorCS5tYXhf cmVnaXN0ZXIgPSAweGZmZmYsCisJLmZhc3RfaW8gPSB0cnVlLAorfTsKKworc3RhdGljIGludCBw aHlfZzEyYV91c2IzX2luaXQoc3RydWN0IHBoeSAqcGh5KQoreworCXN0cnVjdCBwaHlfZzEyYV91 c2IzX3BjaWVfcHJpdiAqcHJpdiA9IHBoeV9nZXRfZHJ2ZGF0YShwaHkpOworCWludCBkYXRhLCBy ZXQ7CisKKwkvKiBTd2l0Y2ggUEhZIHRvIFVTQjMgKi8KKwlyZWdtYXBfdXBkYXRlX2JpdHMocHJp di0+cmVnbWFwLCBQSFlfUjAsCisJCQkgICBQSFlfUjBfUENJRV9VU0IzX1NXSVRDSCwKKwkJCSAg IFBIWV9SMF9QQ0lFX1VTQjNfU1dJVENIKTsKKworCS8qCisJICogV09SS0FST1VORDogVGhlcmUg aXMgU1NQSFkgc3VzcGVuZCBidWcgZHVlIHRvCisJICogd2hpY2ggVVNCIGVudW1lcmF0ZXMKKwkg KiBpbiBIUyBtb2RlIGluc3RlYWQgb2YgU1MgbW9kZS4gV29ya2Fyb3VuZCBpdCBieSBhc3NlcnRp bmcKKwkgKiBMQU5FMC5UWF9BTFRfQkxPQ0suRU5fQUxUX0JVUyB0byBlbmFibGUgVFggdG8gdXNl IGFsdCBidXMKKwkgKiBtb2RlCisJICovCisJcmV0ID0gcmVnbWFwX3VwZGF0ZV9iaXRzKHByaXYt PnJlZ21hcF9jciwgMHgxMDJkLCBCSVQoNyksIEJJVCg3KSk7CisJaWYgKHJldCkKKwkJcmV0dXJu IHJldDsKKworCXJldCA9IHJlZ21hcF91cGRhdGVfYml0cyhwcml2LT5yZWdtYXBfY3IsIDB4MTAx MCwgMHhmZjAsIDIwKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJLyoKKwkgKiBGaXgg UlggRXF1YWxpemF0aW9uIHNldHRpbmcgYXMgZm9sbG93cworCSAqIExBTkUwLlJYX09WUkRfSU5f SEkuIFJYX0VRX0VOIHNldCB0byAwCisJICogTEFORTAuUlhfT1ZSRF9JTl9ISS5SWF9FUV9FTl9P VlJEIHNldCB0byAxCisJICogTEFORTAuUlhfT1ZSRF9JTl9ISS5SWF9FUSBzZXQgdG8gMworCSAq IExBTkUwLlJYX09WUkRfSU5fSEkuUlhfRVFfT1ZSRCBzZXQgdG8gMQorCSAqLworCXJldCA9IHJl Z21hcF9yZWFkKHByaXYtPnJlZ21hcF9jciwgMHgxMDA2LCAmZGF0YSk7CisJaWYgKHJldCkKKwkJ cmV0dXJuIHJldDsKKworCWRhdGEgJj0gfkJJVCg2KTsKKwlkYXRhIHw9IEJJVCg3KTsKKwlkYXRh ICY9IH4oMHg3IDw8IDgpOworCWRhdGEgfD0gKDB4MyA8PCA4KTsKKwlkYXRhIHw9ICgxIDw8IDEx KTsKKwlyZXQgPSByZWdtYXBfd3JpdGUocHJpdi0+cmVnbWFwX2NyLCAweDEwMDYsIGRhdGEpOwor CWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwkvKgorCSAqIFNldCBFUSBhbmQgVFggbGF1bmNo IGFtcGxpdHVkZXMgYXMgZm9sbG93cworCSAqIExBTkUwLlRYX09WUkRfRFJWX0xPLlBSRUVNUEgg c2V0IHRvIDIyCisJICogTEFORTAuVFhfT1ZSRF9EUlZfTE8uQU1QTElUVURFIHNldCB0byAxMjcK KwkgKiBMQU5FMC5UWF9PVlJEX0RSVl9MTy5FTiBzZXQgdG8gMS4KKwkgKi8KKwlyZXQgPSByZWdt YXBfcmVhZChwcml2LT5yZWdtYXBfY3IsIDB4MTAwMiwgJmRhdGEpOworCWlmIChyZXQpCisJCXJl dHVybiByZXQ7CisKKwlkYXRhICY9IH4weDNmODA7CisJZGF0YSB8PSAoMHgxNiA8PCA3KTsKKwlk YXRhICY9IH4weDdmOworCWRhdGEgfD0gKDB4N2YgfCBCSVQoMTQpKTsKKwlyZXQgPSByZWdtYXBf d3JpdGUocHJpdi0+cmVnbWFwX2NyLCAweDEwMDIsIGRhdGEpOworCWlmIChyZXQpCisJCXJldHVy biByZXQ7CisKKwkvKgorCSAqIE1QTExfTE9PUF9DVEwuUFJPUF9DTlRSTCA9IDgKKwkgKi8KKwly ZXQgPSByZWdtYXBfdXBkYXRlX2JpdHMocHJpdi0+cmVnbWFwX2NyLCAweDMwLCAweGYgPDwgNCwg OCA8PCA0KTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJcmVnbWFwX3VwZGF0ZV9iaXRz KHByaXYtPnJlZ21hcCwgUEhZX1IyLAorCQkJUEhZX1IyX1BIWV9UWF9WQk9PU1RfTFZMLAorCQkJ RklFTERfUFJFUChQSFlfUjJfUEhZX1RYX1ZCT09TVF9MVkwsIDB4NCkpOworCisJcmVnbWFwX3Vw ZGF0ZV9iaXRzKHByaXYtPnJlZ21hcCwgUEhZX1IxLAorCQkJUEhZX1IxX1BIWV9MT1NfQklBUyB8 IFBIWV9SMV9QSFlfTE9TX0xFVkVMLAorCQkJRklFTERfUFJFUChQSFlfUjFfUEhZX0xPU19CSUFT LCA0KSB8CisJCQlGSUVMRF9QUkVQKFBIWV9SMV9QSFlfTE9TX0xFVkVMLCA5KSk7CisKKwlyZXR1 cm4gMDsKK30KKworc3RhdGljIGludCBwaHlfZzEyYV91c2IzX3BjaWVfaW5pdChzdHJ1Y3QgcGh5 ICpwaHkpCit7CisJc3RydWN0IHBoeV9nMTJhX3VzYjNfcGNpZV9wcml2ICpwcml2ID0gcGh5X2dl dF9kcnZkYXRhKHBoeSk7CisJaW50IHJldDsKKworCXJldCA9IHJlc2V0X2NvbnRyb2xfcmVzZXQo cHJpdi0+cmVzZXQpOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwlpZiAocHJpdi0+bW9k ZSA9PSBQSFlfVFlQRV9VU0IzKQorCQlyZXR1cm4gcGh5X2cxMmFfdXNiM19pbml0KHBoeSk7CisK KwkvKiBQb3dlciBVUCBQQ0lFICovCisJcmVnbWFwX3VwZGF0ZV9iaXRzKHByaXYtPnJlZ21hcCwg UEhZX1IwLAorCQkJICAgUEhZX1IwX1BDSUVfUE9XRVJfU1RBVEUsCisJCQkgICBGSUVMRF9QUkVQ KFBIWV9SMF9QQ0lFX1BPV0VSX1NUQVRFLCAweDFjKSk7CisKKwlyZXR1cm4gMDsKK30KKworc3Rh dGljIGludCBwaHlfZzEyYV91c2IzX3BjaWVfZXhpdChzdHJ1Y3QgcGh5ICpwaHkpCit7CisJc3Ry dWN0IHBoeV9nMTJhX3VzYjNfcGNpZV9wcml2ICpwcml2ID0gcGh5X2dldF9kcnZkYXRhKHBoeSk7 CisJaW50IHJldDsKKworCXJldHVybiByZXNldF9jb250cm9sX3Jlc2V0KHByaXYtPnJlc2V0KTsK K30KKworc3RhdGljIHN0cnVjdCBwaHkgKnBoeV9nMTJhX3VzYjNfcGNpZV94bGF0ZShzdHJ1Y3Qg ZGV2aWNlICpkZXYsCisJCQkJCSAgICBzdHJ1Y3Qgb2ZfcGhhbmRsZV9hcmdzICphcmdzKQorewor CXN0cnVjdCBwaHlfZzEyYV91c2IzX3BjaWVfcHJpdiAqcHJpdiA9IGRldl9nZXRfZHJ2ZGF0YShk ZXYpOworCXVuc2lnbmVkIGludCBtb2RlOworCisJaWYgKGFyZ3MtPmFyZ3NfY291bnQgPCAxKSB7 CisJCWRldl9lcnIoZGV2LCAiaW52YWxpZCBudW1iZXIgb2YgYXJndW1lbnRzXG4iKTsKKwkJcmV0 dXJuIEVSUl9QVFIoLUVJTlZBTCk7CisJfQorCisJbW9kZSA9IGFyZ3MtPmFyZ3NbMF07CisKKwlp ZiAobW9kZSAhPSBQSFlfVFlQRV9VU0IzICYmIG1vZGUgIT0gUEhZX1RZUEVfUENJRSkgeworCQlk ZXZfZXJyKGRldiwgImludmFsaWQgcGh5IG1vZGUgc2VsZWN0IGFyZ3VtZW50XG4iKTsKKwkJcmV0 dXJuIEVSUl9QVFIoLUVJTlZBTCk7CisJfQorCisJcHJpdi0+bW9kZSA9IG1vZGU7CisKKwlyZXR1 cm4gcHJpdi0+cGh5OworfQorCitzdGF0aWMgY29uc3Qgc3RydWN0IHBoeV9vcHMgcGh5X2cxMmFf dXNiM19wY2llX29wcyA9IHsKKwkuaW5pdAkJPSBwaHlfZzEyYV91c2IzX3BjaWVfaW5pdCwKKwku ZXhpdAkJPSBwaHlfZzEyYV91c2IzX3BjaWVfZXhpdCwKKwkub3duZXIJCT0gVEhJU19NT0RVTEUs Cit9OworCitzdGF0aWMgaW50IHBoeV9nMTJhX3VzYjNfcGNpZV9wcm9iZShzdHJ1Y3QgcGxhdGZv cm1fZGV2aWNlICpwZGV2KQoreworCXN0cnVjdCBkZXZpY2UgKmRldiA9ICZwZGV2LT5kZXY7CisJ c3RydWN0IGRldmljZV9ub2RlICpucCA9IGRldi0+b2Zfbm9kZTsKKwlzdHJ1Y3QgcGh5X2cxMmFf dXNiM19wY2llX3ByaXYgKnByaXY7CisJc3RydWN0IHJlc291cmNlICpyZXM7CisJc3RydWN0IHBo eV9wcm92aWRlciAqcGh5X3Byb3ZpZGVyOworCXZvaWQgX19pb21lbSAqYmFzZTsKKwlpbnQgcmV0 OworCisJcHJpdiA9IGRldm1fa3phbGxvYyhkZXYsIHNpemVvZigqcHJpdiksIEdGUF9LRVJORUwp OworCWlmICghcHJpdikKKwkJcmV0dXJuIC1FTk9NRU07CisKKwlyZXMgPSBwbGF0Zm9ybV9nZXRf cmVzb3VyY2UocGRldiwgSU9SRVNPVVJDRV9NRU0sIDApOworCWJhc2UgPSBkZXZtX2lvcmVtYXBf cmVzb3VyY2UoZGV2LCByZXMpOworCWlmIChJU19FUlIoYmFzZSkpCisJCXJldHVybiBQVFJfRVJS KGJhc2UpOworCisJcHJpdi0+cmVnbWFwID0gZGV2bV9yZWdtYXBfaW5pdF9tbWlvKGRldiwgYmFz ZSwKKwkJCQkJICAgICAmcGh5X2cxMmFfdXNiM19wY2llX3JlZ21hcF9jb25mKTsKKwlpZiAoSVNf RVJSKHByaXYtPnJlZ21hcCkpCisJCXJldHVybiBQVFJfRVJSKHByaXYtPnJlZ21hcCk7CisKKwlw cml2LT5yZWdtYXBfY3IgPSBkZXZtX3JlZ21hcF9pbml0KGRldiwgTlVMTCwgcHJpdiwKKwkJCQkJ ICAgJnBoeV9nMTJhX3VzYjNfcGNpZV9jcl9yZWdtYXBfY29uZik7CisJaWYgKElTX0VSUihwcml2 LT5yZWdtYXBfY3IpKQorCQlyZXR1cm4gUFRSX0VSUihwcml2LT5yZWdtYXBfY3IpOworCisJcHJp di0+Y2xrX3JlZiA9IGRldm1fY2xrX2dldChkZXYsICJyZWZfY2xrIik7CisJaWYgKElTX0VSUihw cml2LT5jbGtfcmVmKSkKKwkJcmV0dXJuIFBUUl9FUlIocHJpdi0+Y2xrX3JlZik7CisKKwlyZXQg PSBjbGtfcHJlcGFyZV9lbmFibGUocHJpdi0+Y2xrX3JlZik7CisJaWYgKHJldCkKKwkJZ290byBl cnJfZGlzYWJsZV9jbGtfcmVmOworCisJcHJpdi0+cmVzZXQgPSBkZXZtX3Jlc2V0X2NvbnRyb2xf YXJyYXlfZ2V0KGRldiwgZmFsc2UsIGZhbHNlKTsKKwlpZiAoSVNfRVJSKHByaXYtPnJlc2V0KSkK KwkJcmV0dXJuIFBUUl9FUlIocHJpdi0+cmVzZXQpOworCisJcHJpdi0+cGh5ID0gZGV2bV9waHlf Y3JlYXRlKGRldiwgbnAsICZwaHlfZzEyYV91c2IzX3BjaWVfb3BzKTsKKwlpZiAoSVNfRVJSKHBy aXYtPnBoeSkpIHsKKwkJcmV0ID0gUFRSX0VSUihwcml2LT5waHkpOworCQlpZiAocmV0ICE9IC1F UFJPQkVfREVGRVIpCisJCQlkZXZfZXJyKGRldiwgImZhaWxlZCB0byBjcmVhdGUgUEhZXG4iKTsK KworCQlyZXR1cm4gcmV0OworCX0KKworCXBoeV9zZXRfZHJ2ZGF0YShwcml2LT5waHksIHByaXYp OworCWRldl9zZXRfZHJ2ZGF0YShkZXYsIHByaXYpOworCisJcGh5X3Byb3ZpZGVyID0gZGV2bV9v Zl9waHlfcHJvdmlkZXJfcmVnaXN0ZXIoZGV2LAorCQkJCQkJICAgICBwaHlfZzEyYV91c2IzX3Bj aWVfeGxhdGUpOworCisJcmV0dXJuIFBUUl9FUlJfT1JfWkVSTyhwaHlfcHJvdmlkZXIpOworCitl cnJfZGlzYWJsZV9jbGtfcmVmOgorCWNsa19kaXNhYmxlX3VucHJlcGFyZShwcml2LT5jbGtfcmVm KTsKKworCXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgb2ZfZGV2aWNlX2lk IHBoeV9nMTJhX3VzYjNfcGNpZV9vZl9tYXRjaFtdID0geworCXsgLmNvbXBhdGlibGUgPSAiYW1s b2dpYyxnMTJhLXVzYjMtcGNpZS1waHkiLCB9LAorCXsgfSwKK307CitNT0RVTEVfREVWSUNFX1RB QkxFKG9mLCBwaHlfZzEyYV91c2IzX3BjaWVfb2ZfbWF0Y2gpOworCitzdGF0aWMgc3RydWN0IHBs YXRmb3JtX2RyaXZlciBwaHlfZzEyYV91c2IzX3BjaWVfZHJpdmVyID0geworCS5wcm9iZQk9IHBo eV9nMTJhX3VzYjNfcGNpZV9wcm9iZSwKKwkuZHJpdmVyCT0geworCQkubmFtZQkJPSAicGh5LWcx MmEtdXNiMy1wY2llIiwKKwkJLm9mX21hdGNoX3RhYmxlCT0gcGh5X2cxMmFfdXNiM19wY2llX29m X21hdGNoLAorCX0sCit9OworbW9kdWxlX3BsYXRmb3JtX2RyaXZlcihwaHlfZzEyYV91c2IzX3Bj aWVfZHJpdmVyKTsKKworTU9EVUxFX0FVVEhPUigiTmVpbCBBcm1zdHJvbmcgPG5hcm1zdHJvbmdA YmF5bGlicmUuY29tPiIpOworTU9EVUxFX0RFU0NSSVBUSU9OKCJBbWxvZ2ljIEcxMkEgVVNCMyAr IFBDSUUgQ29tYm8gUEhZIGRyaXZlciIpOworTU9EVUxFX0xJQ0VOU0UoIkdQTCB2MiIpOwo= From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.0 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2F641C282CA for ; Tue, 12 Feb 2019 15:16:17 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id EA0222075C for ; Tue, 12 Feb 2019 15:16:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="iqZ/yH7T"; 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="Ic+LF/+R" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org EA0222075C 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-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=6bwJqFZcGiZ1bPeAnnlAZoKQk4fcv8l1rsWty1Mh3Wg=; b=iqZ/yH7TT0IPA2 oePYg/pOUYDLcAQ3wJfqq6b98wbkTehsdcKE1XCKdO3xVbpCuFQxL7nbKQF2McYEJvK8tzwsh9nQp KwbyczWQER5J5WzEW4CTpT3q/g3E2Q3BwYVc+njzEdlbUV1NTRtSLheg/ma/zdO21FISJTyAXnL1W bXenkVeJE1kml/voJHhZayolWf0CcJvw19o31p/WQvTOMYJnWyavPBcsXEEmcgRusONUQXbZtz038 bfTMCe44KJQfFH0lIgNu2JXjPUc29kZjmLQ7YPuQOmzcGMzoc1VnTLKibpv1mvF50K0FWJwC+K787 HflXaefnXvaKlIAcoUlw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gtZnA-0000yq-9E; Tue, 12 Feb 2019 15:16:12 +0000 Received: from mail-wr1-x443.google.com ([2a00:1450:4864:20::443]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gtZlU-0006ZP-Iv for linux-arm-kernel@lists.infradead.org; Tue, 12 Feb 2019 15:14:40 +0000 Received: by mail-wr1-x443.google.com with SMTP id q18so3064396wrx.9 for ; Tue, 12 Feb 2019 07:14:28 -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=KcipALzLGN9ADimv2gmiw8vXQG9zUG5C+CzkQJqZk+o=; b=Ic+LF/+R4pbWCrs8ouXmpodxYVPrTjLi889BrNn550QcxrBBlO67hT/kiuz6KRJxZv IftwQzjLyVPQrVWQ0ptLpBCg0k9436EMdZJ3BVI/+FiGV/7j7RtoteNJDVKAE0kgYIoG ocQVxJxjW6h7lQ2maGVv4V32kkAZBX89/u3HFm4s+MxlyMBpdhgEH5wz1qwI6aaQQ7Qu fU+xjPTdovNWY5BsIQUUrEuR/bgwlG8LvpLGg2QsoOvXWOvz27lteyBu22ooInTRoA2u LmuRFYS1tVd/OSPp7d5WIlYpkm+8fHDVJw5+ddAbPcdD63bIfpxnGcpdtfnssC6mqxV0 lw/w== 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=KcipALzLGN9ADimv2gmiw8vXQG9zUG5C+CzkQJqZk+o=; b=UK7Evd5hWDQpQUV/6NKgZRrDRcVqWFMcysGYyC95Ku8BsXDZplSAJkMRlE83QpC5g/ VGg+pWbh+bDvKMRg5CZMkJ4Y5sfzjJvZupNx78vL45/ALwo/diuzYoLPoU2GanzU/qPW aT3LU4gXdXJfJA1F8LIxhSi5alT8azGALbnpnTY5Dwn17q6ACVbentZV3CbatKA0rtoR KGbDF+2J/uoX1xOv5Ar+LrLFz6/WXTFNXrB8Z/JLGEuFDYd266xdfXssP0AZSut+pyJc aCx1dTnwrx98OapIxKLOcQuzW4LcOQfRWLNf3OwM7fGP9eR3SprORtszp9JC7nEdzyqO WOIA== X-Gm-Message-State: AHQUAuYK8gBpB6ZKRhNPPUi/xequudf7ZO45Ad29VSiYFsDCJl+OLJo1 dDShtV5rIpFqjkiFJUvjQmoVGw== X-Google-Smtp-Source: AHgI3IY+mjREMc0CThzuKYYhTKn22zcgXsMNLHGItL6ezLiyy4hcjMulQLGKcwSX+UYwb78naJ500w== X-Received: by 2002:adf:8122:: with SMTP id 31mr3337473wrm.48.1549984466884; Tue, 12 Feb 2019 07:14:26 -0800 (PST) Received: from bender.baylibre.local (lmontsouris-657-1-212-31.w90-63.abo.wanadoo.fr. [90.63.244.31]) by smtp.gmail.com with ESMTPSA id c1sm1589515wmb.14.2019.02.12.07.14.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 12 Feb 2019 07:14:25 -0800 (PST) From: Neil Armstrong To: gregkh@linuxfoundation.org, hminas@synopsys.com, balbi@kernel.org, kishon@ti.com Subject: [PATCH 6/8] phy: amlogic: Add Amlogic G12A USB3 + PCIE Combo PHY Driver Date: Tue, 12 Feb 2019 16:14:11 +0100 Message-Id: <20190212151413.24632-7-narmstrong@baylibre.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190212151413.24632-1-narmstrong@baylibre.com> References: <20190212151413.24632-1-narmstrong@baylibre.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190212_071429_278639_1E3019BF X-CRM114-Status: GOOD ( 20.95 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-amlogic@lists.infradead.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Neil Armstrong Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org This adds support for the shared USB3 + PCIE PHY found in the Amlogic G12A SoC Family. It supports USB3 Host mode or PCIE 2.0 mode, depending on the layout of the board. Selection is done by the #phy-cells, making the mode static and exclusive. Signed-off-by: Neil Armstrong --- drivers/phy/amlogic/Kconfig | 12 + drivers/phy/amlogic/Makefile | 1 + .../phy/amlogic/phy-meson-g12a-usb3-pcie.c | 414 ++++++++++++++++++ 3 files changed, 427 insertions(+) create mode 100644 drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig index 78d6e194dce9..7ccb9a756aba 100644 --- a/drivers/phy/amlogic/Kconfig +++ b/drivers/phy/amlogic/Kconfig @@ -48,3 +48,15 @@ config PHY_MESON_G12A_USB2 Enable this to support the Meson USB2 PHYs found in Meson G12A SoCs. If unsure, say N. + +config PHY_MESON_G12A_USB3_PCIE + tristate "Meson G12A USB3+PCIE Combo PHY drivers" + default ARCH_MESON + depends on OF && (ARCH_MESON || COMPILE_TEST) + depends on USB_SUPPORT + select GENERIC_PHY + select REGMAP_MMIO + help + Enable this to support the Meson USB3 + PCIE Combi PHY found + in Meson G12A SoCs. + If unsure, say N. diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile index 7d4d10f5a6b3..fdd008e1b19b 100644 --- a/drivers/phy/amlogic/Makefile +++ b/drivers/phy/amlogic/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o obj-$(CONFIG_PHY_MESON_GXL_USB2) += phy-meson-gxl-usb2.o obj-$(CONFIG_PHY_MESON_G12A_USB2) += phy-meson-g12a-usb2.o obj-$(CONFIG_PHY_MESON_GXL_USB3) += phy-meson-gxl-usb3.o +obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE) += phy-meson-g12a-usb3-pcie.o diff --git a/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c b/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c new file mode 100644 index 000000000000..59eae98928e9 --- /dev/null +++ b/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c @@ -0,0 +1,414 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Amlogic G12A USB3 + PCIE Combo PHY driver + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved + * Copyright (C) 2019 BayLibre, SAS + * Author: Neil Armstrong + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PHY_R0 0x00 + #define PHY_R0_PCIE_POWER_STATE GENMASK(4, 0) + #define PHY_R0_PCIE_USB3_SWITCH GENMASK(6, 5) + +#define PHY_R1 0x04 + #define PHY_R1_PHY_TX1_TERM_OFFSET GENMASK(4, 0) + #define PHY_R1_PHY_TX0_TERM_OFFSET GENMASK(9, 5) + #define PHY_R1_PHY_RX1_EQ GENMASK(12, 10) + #define PHY_R1_PHY_RX0_EQ GENMASK(15, 13) + #define PHY_R1_PHY_LOS_LEVEL GENMASK(20, 16) + #define PHY_R1_PHY_LOS_BIAS GENMASK(23, 21) + #define PHY_R1_PHY_REF_CLKDIV2 BIT(24) + #define PHY_R1_PHY_MPLL_MULTIPLIER GENMASK(31, 25) + +#define PHY_R2 0x08 + #define PHY_R2_PCS_TX_DEEMPH_GEN2_6DB GENMASK(5, 0) + #define PHY_R2_PCS_TX_DEEMPH_GEN2_3P5DB GENMASK(11, 6) + #define PHY_R2_PCS_TX_DEEMPH_GEN1 GENMASK(17, 12) + #define PHY_R2_PHY_TX_VBOOST_LVL GENMASK(20, 18) + +#define PHY_R4 0x10 + #define PHY_R4_PHY_CR_WRITE BIT(0) + #define PHY_R4_PHY_CR_READ BIT(1) + #define PHY_R4_PHY_CR_DATA_IN GENMASK(17, 2) + #define PHY_R4_PHY_CR_CAP_DATA BIT(18) + #define PHY_R4_PHY_CR_CAP_ADDR BIT(19) + +#define PHY_R5 0x14 + #define PHY_R5_PHY_CR_DATA_OUT GENMASK(15, 0) + #define PHY_R5_PHY_CR_ACK BIT(16) + #define PHY_R5_PHY_BS_OUT BIT(17) + +struct phy_g12a_usb3_pcie_priv { + struct regmap *regmap; + struct regmap *regmap_cr; + struct clk *clk_ref; + struct reset_control *reset; + struct phy *phy; + unsigned int mode; +}; + +static const struct regmap_config phy_g12a_usb3_pcie_regmap_conf = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = PHY_R5, +}; + +static int phy_g12a_usb3_pcie_cr_bus_addr(struct phy_g12a_usb3_pcie_priv *priv, + unsigned int addr) +{ + unsigned int val, reg; + int ret; + + reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, addr); + + regmap_write(priv->regmap, PHY_R4, reg); + regmap_write(priv->regmap, PHY_R4, reg); + + regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_ADDR); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + regmap_write(priv->regmap, PHY_R4, reg); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + !(val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + return 0; +} + +static int phy_g12a_usb3_pcie_cr_bus_read(void *context, unsigned int addr, + unsigned int *data) +{ + struct phy_g12a_usb3_pcie_priv *priv = context; + unsigned int val; + int ret; + + ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr); + if (ret) + return ret; + + regmap_write(priv->regmap, PHY_R4, 0); + regmap_write(priv->regmap, PHY_R4, PHY_R4_PHY_CR_READ); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + *data = FIELD_GET(PHY_R5_PHY_CR_DATA_OUT, val); + + regmap_write(priv->regmap, PHY_R4, 0); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + !(val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + return 0; +} + +static int phy_g12a_usb3_pcie_cr_bus_write(void *context, unsigned int addr, + unsigned int data) +{ + struct phy_g12a_usb3_pcie_priv *priv = context; + unsigned int val, reg; + int ret; + + ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr); + if (ret) + return ret; + + reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, data); + + regmap_write(priv->regmap, PHY_R4, reg); + regmap_write(priv->regmap, PHY_R4, reg); + + regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_DATA); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + regmap_write(priv->regmap, PHY_R4, reg); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK) == 0, + 5, 1000); + if (ret) + return ret; + + regmap_write(priv->regmap, PHY_R4, reg); + + regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_WRITE); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + regmap_write(priv->regmap, PHY_R4, reg); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK) == 0, + 5, 1000); + if (ret) + return ret; + + return 0; +} + +static const struct regmap_config phy_g12a_usb3_pcie_cr_regmap_conf = { + .reg_bits = 16, + .val_bits = 16, + .reg_read = phy_g12a_usb3_pcie_cr_bus_read, + .reg_write = phy_g12a_usb3_pcie_cr_bus_write, + .max_register = 0xffff, + .fast_io = true, +}; + +static int phy_g12a_usb3_init(struct phy *phy) +{ + struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy); + int data, ret; + + /* Switch PHY to USB3 */ + regmap_update_bits(priv->regmap, PHY_R0, + PHY_R0_PCIE_USB3_SWITCH, + PHY_R0_PCIE_USB3_SWITCH); + + /* + * WORKAROUND: There is SSPHY suspend bug due to + * which USB enumerates + * in HS mode instead of SS mode. Workaround it by asserting + * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus + * mode + */ + ret = regmap_update_bits(priv->regmap_cr, 0x102d, BIT(7), BIT(7)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap_cr, 0x1010, 0xff0, 20); + if (ret) + return ret; + + /* + * Fix RX Equalization setting as follows + * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 + * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 + * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3 + * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 + */ + ret = regmap_read(priv->regmap_cr, 0x1006, &data); + if (ret) + return ret; + + data &= ~BIT(6); + data |= BIT(7); + data &= ~(0x7 << 8); + data |= (0x3 << 8); + data |= (1 << 11); + ret = regmap_write(priv->regmap_cr, 0x1006, data); + if (ret) + return ret; + + /* + * Set EQ and TX launch amplitudes as follows + * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22 + * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127 + * LANE0.TX_OVRD_DRV_LO.EN set to 1. + */ + ret = regmap_read(priv->regmap_cr, 0x1002, &data); + if (ret) + return ret; + + data &= ~0x3f80; + data |= (0x16 << 7); + data &= ~0x7f; + data |= (0x7f | BIT(14)); + ret = regmap_write(priv->regmap_cr, 0x1002, data); + if (ret) + return ret; + + /* + * MPLL_LOOP_CTL.PROP_CNTRL = 8 + */ + ret = regmap_update_bits(priv->regmap_cr, 0x30, 0xf << 4, 8 << 4); + if (ret) + return ret; + + regmap_update_bits(priv->regmap, PHY_R2, + PHY_R2_PHY_TX_VBOOST_LVL, + FIELD_PREP(PHY_R2_PHY_TX_VBOOST_LVL, 0x4)); + + regmap_update_bits(priv->regmap, PHY_R1, + PHY_R1_PHY_LOS_BIAS | PHY_R1_PHY_LOS_LEVEL, + FIELD_PREP(PHY_R1_PHY_LOS_BIAS, 4) | + FIELD_PREP(PHY_R1_PHY_LOS_LEVEL, 9)); + + return 0; +} + +static int phy_g12a_usb3_pcie_init(struct phy *phy) +{ + struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy); + int ret; + + ret = reset_control_reset(priv->reset); + if (ret) + return ret; + + if (priv->mode == PHY_TYPE_USB3) + return phy_g12a_usb3_init(phy); + + /* Power UP PCIE */ + regmap_update_bits(priv->regmap, PHY_R0, + PHY_R0_PCIE_POWER_STATE, + FIELD_PREP(PHY_R0_PCIE_POWER_STATE, 0x1c)); + + return 0; +} + +static int phy_g12a_usb3_pcie_exit(struct phy *phy) +{ + struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy); + int ret; + + return reset_control_reset(priv->reset); +} + +static struct phy *phy_g12a_usb3_pcie_xlate(struct device *dev, + struct of_phandle_args *args) +{ + struct phy_g12a_usb3_pcie_priv *priv = dev_get_drvdata(dev); + unsigned int mode; + + if (args->args_count < 1) { + dev_err(dev, "invalid number of arguments\n"); + return ERR_PTR(-EINVAL); + } + + mode = args->args[0]; + + if (mode != PHY_TYPE_USB3 && mode != PHY_TYPE_PCIE) { + dev_err(dev, "invalid phy mode select argument\n"); + return ERR_PTR(-EINVAL); + } + + priv->mode = mode; + + return priv->phy; +} + +static const struct phy_ops phy_g12a_usb3_pcie_ops = { + .init = phy_g12a_usb3_pcie_init, + .exit = phy_g12a_usb3_pcie_exit, + .owner = THIS_MODULE, +}; + +static int phy_g12a_usb3_pcie_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct phy_g12a_usb3_pcie_priv *priv; + struct resource *res; + struct phy_provider *phy_provider; + void __iomem *base; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + 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_g12a_usb3_pcie_regmap_conf); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + priv->regmap_cr = devm_regmap_init(dev, NULL, priv, + &phy_g12a_usb3_pcie_cr_regmap_conf); + if (IS_ERR(priv->regmap_cr)) + return PTR_ERR(priv->regmap_cr); + + priv->clk_ref = devm_clk_get(dev, "ref_clk"); + if (IS_ERR(priv->clk_ref)) + return PTR_ERR(priv->clk_ref); + + ret = clk_prepare_enable(priv->clk_ref); + if (ret) + goto err_disable_clk_ref; + + priv->reset = devm_reset_control_array_get(dev, false, false); + if (IS_ERR(priv->reset)) + return PTR_ERR(priv->reset); + + priv->phy = devm_phy_create(dev, np, &phy_g12a_usb3_pcie_ops); + if (IS_ERR(priv->phy)) { + ret = PTR_ERR(priv->phy); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to create PHY\n"); + + return ret; + } + + phy_set_drvdata(priv->phy, priv); + dev_set_drvdata(dev, priv); + + phy_provider = devm_of_phy_provider_register(dev, + phy_g12a_usb3_pcie_xlate); + + return PTR_ERR_OR_ZERO(phy_provider); + +err_disable_clk_ref: + clk_disable_unprepare(priv->clk_ref); + + return ret; +} + +static const struct of_device_id phy_g12a_usb3_pcie_of_match[] = { + { .compatible = "amlogic,g12a-usb3-pcie-phy", }, + { }, +}; +MODULE_DEVICE_TABLE(of, phy_g12a_usb3_pcie_of_match); + +static struct platform_driver phy_g12a_usb3_pcie_driver = { + .probe = phy_g12a_usb3_pcie_probe, + .driver = { + .name = "phy-g12a-usb3-pcie", + .of_match_table = phy_g12a_usb3_pcie_of_match, + }, +}; +module_platform_driver(phy_g12a_usb3_pcie_driver); + +MODULE_AUTHOR("Neil Armstrong "); +MODULE_DESCRIPTION("Amlogic G12A USB3 + PCIE Combo PHY driver"); +MODULE_LICENSE("GPL v2"); -- 2.20.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.0 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id ACD90C282C4 for ; Tue, 12 Feb 2019 15:16:10 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 70CBA2075C for ; Tue, 12 Feb 2019 15:16:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="mgY5cX3+"; 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="Ic+LF/+R" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 70CBA2075C 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+linux-amlogic=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=xPLSt4Hxlp1Pf8EzH0uoCCJchFLIO/rnDxLlW+rtm1k=; b=mgY5cX3+vie6k5 XKbLVdzqzMMwN/JBojY3DobE2jPRJxdhdere7P2wNW1ULA8DW0hLIjh8HamlPqiXBoBpzMRR9U4Bn SVkbmqjLmBITSAAJsnFqbdTluEetbfFjeQ+TnhHK7dcUcpZMdPjfFvY1t8YOlEgFhwF2YSwtc64jI hEutayl/1/k9mnH6qDwzqMJiZf44XS1MydjjPAy+AvMUEHDM4g7NYdEIyzTDEaiHI8pVy3UAok2oP /ZOCl+BVxhQdC/6DTXfdSVI6TDa1ThRXo0m+oYnXjgXxqDHSELgawWPqN4RXxzOnHqrPy3hJez6XK O4zpJ4D2+TBTVqwPJWHQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gtZn3-0000ty-5q; Tue, 12 Feb 2019 15:16:05 +0000 Received: from mail-wr1-x442.google.com ([2a00:1450:4864:20::442]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gtZlU-0006ZY-JB for linux-amlogic@lists.infradead.org; Tue, 12 Feb 2019 15:14:39 +0000 Received: by mail-wr1-x442.google.com with SMTP id v16so3039891wrn.11 for ; Tue, 12 Feb 2019 07:14:28 -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=KcipALzLGN9ADimv2gmiw8vXQG9zUG5C+CzkQJqZk+o=; b=Ic+LF/+R4pbWCrs8ouXmpodxYVPrTjLi889BrNn550QcxrBBlO67hT/kiuz6KRJxZv IftwQzjLyVPQrVWQ0ptLpBCg0k9436EMdZJ3BVI/+FiGV/7j7RtoteNJDVKAE0kgYIoG ocQVxJxjW6h7lQ2maGVv4V32kkAZBX89/u3HFm4s+MxlyMBpdhgEH5wz1qwI6aaQQ7Qu fU+xjPTdovNWY5BsIQUUrEuR/bgwlG8LvpLGg2QsoOvXWOvz27lteyBu22ooInTRoA2u LmuRFYS1tVd/OSPp7d5WIlYpkm+8fHDVJw5+ddAbPcdD63bIfpxnGcpdtfnssC6mqxV0 lw/w== 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=KcipALzLGN9ADimv2gmiw8vXQG9zUG5C+CzkQJqZk+o=; b=N1MrcYzcH73/tlKMM2hGQb1h4HeX2QZTYISTp0UV4WunoSk6ateKKRPOOX2NiUVQfY 5vDAGBEjqsZLBxhXAvgBkIJDgJiBS2PpTp46McjICF70H29TNFEt2t8tG8cZKoL2GYn8 XbLca9ynHHVhtOmCedmcUTQl8mPYnsxSHtfnu/HZpwkxtwW2UB8faM6r89Y0Pk9LcaP1 s6w1Hi1BYQbF1dFmHIyhahJMuHngrfe2KCaevWesPvxoTJSdrYP38vEvc45LcLEK2AQ5 M4NIjrHaWIyG14tX5kRwixQmuckEhOUHPG64QTrfUQgo4hkEECa4b4oKeFkh1TugW7Do U+ig== X-Gm-Message-State: AHQUAubQzD69DB2RDIxi/B41xpNcePzHg44A/mgUBSeXiXYDJ1/hM/7f XgpV2aqz2+KyegJ3ECHm2SKLpw== X-Google-Smtp-Source: AHgI3IY+mjREMc0CThzuKYYhTKn22zcgXsMNLHGItL6ezLiyy4hcjMulQLGKcwSX+UYwb78naJ500w== X-Received: by 2002:adf:8122:: with SMTP id 31mr3337473wrm.48.1549984466884; Tue, 12 Feb 2019 07:14:26 -0800 (PST) Received: from bender.baylibre.local (lmontsouris-657-1-212-31.w90-63.abo.wanadoo.fr. [90.63.244.31]) by smtp.gmail.com with ESMTPSA id c1sm1589515wmb.14.2019.02.12.07.14.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 12 Feb 2019 07:14:25 -0800 (PST) From: Neil Armstrong To: gregkh@linuxfoundation.org, hminas@synopsys.com, balbi@kernel.org, kishon@ti.com Subject: [PATCH 6/8] phy: amlogic: Add Amlogic G12A USB3 + PCIE Combo PHY Driver Date: Tue, 12 Feb 2019 16:14:11 +0100 Message-Id: <20190212151413.24632-7-narmstrong@baylibre.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190212151413.24632-1-narmstrong@baylibre.com> References: <20190212151413.24632-1-narmstrong@baylibre.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190212_071429_321473_39EC14B9 X-CRM114-Status: GOOD ( 19.37 ) X-BeenThere: linux-amlogic@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-amlogic@lists.infradead.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Neil Armstrong Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-amlogic" Errors-To: linux-amlogic-bounces+linux-amlogic=archiver.kernel.org@lists.infradead.org This adds support for the shared USB3 + PCIE PHY found in the Amlogic G12A SoC Family. It supports USB3 Host mode or PCIE 2.0 mode, depending on the layout of the board. Selection is done by the #phy-cells, making the mode static and exclusive. Signed-off-by: Neil Armstrong --- drivers/phy/amlogic/Kconfig | 12 + drivers/phy/amlogic/Makefile | 1 + .../phy/amlogic/phy-meson-g12a-usb3-pcie.c | 414 ++++++++++++++++++ 3 files changed, 427 insertions(+) create mode 100644 drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig index 78d6e194dce9..7ccb9a756aba 100644 --- a/drivers/phy/amlogic/Kconfig +++ b/drivers/phy/amlogic/Kconfig @@ -48,3 +48,15 @@ config PHY_MESON_G12A_USB2 Enable this to support the Meson USB2 PHYs found in Meson G12A SoCs. If unsure, say N. + +config PHY_MESON_G12A_USB3_PCIE + tristate "Meson G12A USB3+PCIE Combo PHY drivers" + default ARCH_MESON + depends on OF && (ARCH_MESON || COMPILE_TEST) + depends on USB_SUPPORT + select GENERIC_PHY + select REGMAP_MMIO + help + Enable this to support the Meson USB3 + PCIE Combi PHY found + in Meson G12A SoCs. + If unsure, say N. diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile index 7d4d10f5a6b3..fdd008e1b19b 100644 --- a/drivers/phy/amlogic/Makefile +++ b/drivers/phy/amlogic/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o obj-$(CONFIG_PHY_MESON_GXL_USB2) += phy-meson-gxl-usb2.o obj-$(CONFIG_PHY_MESON_G12A_USB2) += phy-meson-g12a-usb2.o obj-$(CONFIG_PHY_MESON_GXL_USB3) += phy-meson-gxl-usb3.o +obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE) += phy-meson-g12a-usb3-pcie.o diff --git a/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c b/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c new file mode 100644 index 000000000000..59eae98928e9 --- /dev/null +++ b/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c @@ -0,0 +1,414 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Amlogic G12A USB3 + PCIE Combo PHY driver + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved + * Copyright (C) 2019 BayLibre, SAS + * Author: Neil Armstrong + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PHY_R0 0x00 + #define PHY_R0_PCIE_POWER_STATE GENMASK(4, 0) + #define PHY_R0_PCIE_USB3_SWITCH GENMASK(6, 5) + +#define PHY_R1 0x04 + #define PHY_R1_PHY_TX1_TERM_OFFSET GENMASK(4, 0) + #define PHY_R1_PHY_TX0_TERM_OFFSET GENMASK(9, 5) + #define PHY_R1_PHY_RX1_EQ GENMASK(12, 10) + #define PHY_R1_PHY_RX0_EQ GENMASK(15, 13) + #define PHY_R1_PHY_LOS_LEVEL GENMASK(20, 16) + #define PHY_R1_PHY_LOS_BIAS GENMASK(23, 21) + #define PHY_R1_PHY_REF_CLKDIV2 BIT(24) + #define PHY_R1_PHY_MPLL_MULTIPLIER GENMASK(31, 25) + +#define PHY_R2 0x08 + #define PHY_R2_PCS_TX_DEEMPH_GEN2_6DB GENMASK(5, 0) + #define PHY_R2_PCS_TX_DEEMPH_GEN2_3P5DB GENMASK(11, 6) + #define PHY_R2_PCS_TX_DEEMPH_GEN1 GENMASK(17, 12) + #define PHY_R2_PHY_TX_VBOOST_LVL GENMASK(20, 18) + +#define PHY_R4 0x10 + #define PHY_R4_PHY_CR_WRITE BIT(0) + #define PHY_R4_PHY_CR_READ BIT(1) + #define PHY_R4_PHY_CR_DATA_IN GENMASK(17, 2) + #define PHY_R4_PHY_CR_CAP_DATA BIT(18) + #define PHY_R4_PHY_CR_CAP_ADDR BIT(19) + +#define PHY_R5 0x14 + #define PHY_R5_PHY_CR_DATA_OUT GENMASK(15, 0) + #define PHY_R5_PHY_CR_ACK BIT(16) + #define PHY_R5_PHY_BS_OUT BIT(17) + +struct phy_g12a_usb3_pcie_priv { + struct regmap *regmap; + struct regmap *regmap_cr; + struct clk *clk_ref; + struct reset_control *reset; + struct phy *phy; + unsigned int mode; +}; + +static const struct regmap_config phy_g12a_usb3_pcie_regmap_conf = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = PHY_R5, +}; + +static int phy_g12a_usb3_pcie_cr_bus_addr(struct phy_g12a_usb3_pcie_priv *priv, + unsigned int addr) +{ + unsigned int val, reg; + int ret; + + reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, addr); + + regmap_write(priv->regmap, PHY_R4, reg); + regmap_write(priv->regmap, PHY_R4, reg); + + regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_ADDR); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + regmap_write(priv->regmap, PHY_R4, reg); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + !(val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + return 0; +} + +static int phy_g12a_usb3_pcie_cr_bus_read(void *context, unsigned int addr, + unsigned int *data) +{ + struct phy_g12a_usb3_pcie_priv *priv = context; + unsigned int val; + int ret; + + ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr); + if (ret) + return ret; + + regmap_write(priv->regmap, PHY_R4, 0); + regmap_write(priv->regmap, PHY_R4, PHY_R4_PHY_CR_READ); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + *data = FIELD_GET(PHY_R5_PHY_CR_DATA_OUT, val); + + regmap_write(priv->regmap, PHY_R4, 0); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + !(val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + return 0; +} + +static int phy_g12a_usb3_pcie_cr_bus_write(void *context, unsigned int addr, + unsigned int data) +{ + struct phy_g12a_usb3_pcie_priv *priv = context; + unsigned int val, reg; + int ret; + + ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr); + if (ret) + return ret; + + reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, data); + + regmap_write(priv->regmap, PHY_R4, reg); + regmap_write(priv->regmap, PHY_R4, reg); + + regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_DATA); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + regmap_write(priv->regmap, PHY_R4, reg); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK) == 0, + 5, 1000); + if (ret) + return ret; + + regmap_write(priv->regmap, PHY_R4, reg); + + regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_WRITE); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK), + 5, 1000); + if (ret) + return ret; + + regmap_write(priv->regmap, PHY_R4, reg); + + ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, + (val & PHY_R5_PHY_CR_ACK) == 0, + 5, 1000); + if (ret) + return ret; + + return 0; +} + +static const struct regmap_config phy_g12a_usb3_pcie_cr_regmap_conf = { + .reg_bits = 16, + .val_bits = 16, + .reg_read = phy_g12a_usb3_pcie_cr_bus_read, + .reg_write = phy_g12a_usb3_pcie_cr_bus_write, + .max_register = 0xffff, + .fast_io = true, +}; + +static int phy_g12a_usb3_init(struct phy *phy) +{ + struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy); + int data, ret; + + /* Switch PHY to USB3 */ + regmap_update_bits(priv->regmap, PHY_R0, + PHY_R0_PCIE_USB3_SWITCH, + PHY_R0_PCIE_USB3_SWITCH); + + /* + * WORKAROUND: There is SSPHY suspend bug due to + * which USB enumerates + * in HS mode instead of SS mode. Workaround it by asserting + * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus + * mode + */ + ret = regmap_update_bits(priv->regmap_cr, 0x102d, BIT(7), BIT(7)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap_cr, 0x1010, 0xff0, 20); + if (ret) + return ret; + + /* + * Fix RX Equalization setting as follows + * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 + * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 + * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3 + * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 + */ + ret = regmap_read(priv->regmap_cr, 0x1006, &data); + if (ret) + return ret; + + data &= ~BIT(6); + data |= BIT(7); + data &= ~(0x7 << 8); + data |= (0x3 << 8); + data |= (1 << 11); + ret = regmap_write(priv->regmap_cr, 0x1006, data); + if (ret) + return ret; + + /* + * Set EQ and TX launch amplitudes as follows + * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22 + * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127 + * LANE0.TX_OVRD_DRV_LO.EN set to 1. + */ + ret = regmap_read(priv->regmap_cr, 0x1002, &data); + if (ret) + return ret; + + data &= ~0x3f80; + data |= (0x16 << 7); + data &= ~0x7f; + data |= (0x7f | BIT(14)); + ret = regmap_write(priv->regmap_cr, 0x1002, data); + if (ret) + return ret; + + /* + * MPLL_LOOP_CTL.PROP_CNTRL = 8 + */ + ret = regmap_update_bits(priv->regmap_cr, 0x30, 0xf << 4, 8 << 4); + if (ret) + return ret; + + regmap_update_bits(priv->regmap, PHY_R2, + PHY_R2_PHY_TX_VBOOST_LVL, + FIELD_PREP(PHY_R2_PHY_TX_VBOOST_LVL, 0x4)); + + regmap_update_bits(priv->regmap, PHY_R1, + PHY_R1_PHY_LOS_BIAS | PHY_R1_PHY_LOS_LEVEL, + FIELD_PREP(PHY_R1_PHY_LOS_BIAS, 4) | + FIELD_PREP(PHY_R1_PHY_LOS_LEVEL, 9)); + + return 0; +} + +static int phy_g12a_usb3_pcie_init(struct phy *phy) +{ + struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy); + int ret; + + ret = reset_control_reset(priv->reset); + if (ret) + return ret; + + if (priv->mode == PHY_TYPE_USB3) + return phy_g12a_usb3_init(phy); + + /* Power UP PCIE */ + regmap_update_bits(priv->regmap, PHY_R0, + PHY_R0_PCIE_POWER_STATE, + FIELD_PREP(PHY_R0_PCIE_POWER_STATE, 0x1c)); + + return 0; +} + +static int phy_g12a_usb3_pcie_exit(struct phy *phy) +{ + struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy); + int ret; + + return reset_control_reset(priv->reset); +} + +static struct phy *phy_g12a_usb3_pcie_xlate(struct device *dev, + struct of_phandle_args *args) +{ + struct phy_g12a_usb3_pcie_priv *priv = dev_get_drvdata(dev); + unsigned int mode; + + if (args->args_count < 1) { + dev_err(dev, "invalid number of arguments\n"); + return ERR_PTR(-EINVAL); + } + + mode = args->args[0]; + + if (mode != PHY_TYPE_USB3 && mode != PHY_TYPE_PCIE) { + dev_err(dev, "invalid phy mode select argument\n"); + return ERR_PTR(-EINVAL); + } + + priv->mode = mode; + + return priv->phy; +} + +static const struct phy_ops phy_g12a_usb3_pcie_ops = { + .init = phy_g12a_usb3_pcie_init, + .exit = phy_g12a_usb3_pcie_exit, + .owner = THIS_MODULE, +}; + +static int phy_g12a_usb3_pcie_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct phy_g12a_usb3_pcie_priv *priv; + struct resource *res; + struct phy_provider *phy_provider; + void __iomem *base; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + 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_g12a_usb3_pcie_regmap_conf); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + priv->regmap_cr = devm_regmap_init(dev, NULL, priv, + &phy_g12a_usb3_pcie_cr_regmap_conf); + if (IS_ERR(priv->regmap_cr)) + return PTR_ERR(priv->regmap_cr); + + priv->clk_ref = devm_clk_get(dev, "ref_clk"); + if (IS_ERR(priv->clk_ref)) + return PTR_ERR(priv->clk_ref); + + ret = clk_prepare_enable(priv->clk_ref); + if (ret) + goto err_disable_clk_ref; + + priv->reset = devm_reset_control_array_get(dev, false, false); + if (IS_ERR(priv->reset)) + return PTR_ERR(priv->reset); + + priv->phy = devm_phy_create(dev, np, &phy_g12a_usb3_pcie_ops); + if (IS_ERR(priv->phy)) { + ret = PTR_ERR(priv->phy); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to create PHY\n"); + + return ret; + } + + phy_set_drvdata(priv->phy, priv); + dev_set_drvdata(dev, priv); + + phy_provider = devm_of_phy_provider_register(dev, + phy_g12a_usb3_pcie_xlate); + + return PTR_ERR_OR_ZERO(phy_provider); + +err_disable_clk_ref: + clk_disable_unprepare(priv->clk_ref); + + return ret; +} + +static const struct of_device_id phy_g12a_usb3_pcie_of_match[] = { + { .compatible = "amlogic,g12a-usb3-pcie-phy", }, + { }, +}; +MODULE_DEVICE_TABLE(of, phy_g12a_usb3_pcie_of_match); + +static struct platform_driver phy_g12a_usb3_pcie_driver = { + .probe = phy_g12a_usb3_pcie_probe, + .driver = { + .name = "phy-g12a-usb3-pcie", + .of_match_table = phy_g12a_usb3_pcie_of_match, + }, +}; +module_platform_driver(phy_g12a_usb3_pcie_driver); + +MODULE_AUTHOR("Neil Armstrong "); +MODULE_DESCRIPTION("Amlogic G12A USB3 + PCIE Combo PHY driver"); +MODULE_LICENSE("GPL v2"); -- 2.20.1 _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic