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=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 D145DC64EB4 for ; Mon, 3 Dec 2018 03:45:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 97B7521473 for ; Mon, 3 Dec 2018 03:45:43 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 97B7521473 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=huawei.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725849AbeLCDpo (ORCPT ); Sun, 2 Dec 2018 22:45:44 -0500 Received: from szxga07-in.huawei.com ([45.249.212.35]:46562 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725819AbeLCDpo (ORCPT ); Sun, 2 Dec 2018 22:45:44 -0500 Received: from DGGEMS412-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 60D362CE44876; Mon, 3 Dec 2018 11:45:37 +0800 (CST) Received: from vm100-107-113-134.huawei.com (100.107.113.134) by DGGEMS412-HUB.china.huawei.com (10.3.19.212) with Microsoft SMTP Server id 14.3.408.0; Mon, 3 Dec 2018 11:45:31 +0800 From: Yu Chen To: , , CC: , , Yu Chen , Felipe Balbi , Greg Kroah-Hartman , "David S. Miller" , "Mauro Carvalho Chehab" , Andrew Morton , Arnd Bergmann , John Stultz , Binghui Wang Subject: [PATCH v1 04/12] usb: dwc3: dwc3-hisi: Add code for dwc3 of Hisilicon Soc Platform Date: Mon, 3 Dec 2018 11:45:07 +0800 Message-ID: <20181203034515.91412-5-chenyu56@huawei.com> X-Mailer: git-send-email 2.15.0-rc2 In-Reply-To: <20181203034515.91412-1-chenyu56@huawei.com> References: <20181203034515.91412-1-chenyu56@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [100.107.113.134] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This driver handles the poweron and shutdown of dwc3 core on Hisilicon Soc Platform. Cc: Felipe Balbi Cc: Greg Kroah-Hartman Cc: "David S. Miller" Cc: Mauro Carvalho Chehab Cc: Andrew Morton Cc: Arnd Bergmann Cc: John Stultz Cc: Binghui Wang Signed-off-by: Yu Chen --- MAINTAINERS | 8 ++ drivers/usb/dwc3/Kconfig | 8 ++ drivers/usb/dwc3/Makefile | 1 + drivers/usb/dwc3/dwc3-hisi.c | 335 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 352 insertions(+) create mode 100644 drivers/usb/dwc3/dwc3-hisi.c diff --git a/MAINTAINERS b/MAINTAINERS index 6c3fbbb361f8..1b6b3026804c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15465,6 +15465,14 @@ L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/roles/intel-xhci-usb-role-switch.c +USB IP DRIVER FOR HISILICON KIRIN +M: Yu Chen +M: Binghui Wang +L: linux-usb@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/usb/dwc3-hisi.txt +F: drivers/usb/dwc3/dwc3-hisi.c + USB ISP116X DRIVER M: Olav Kongas L: linux-usb@vger.kernel.org diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 1a0404fda596..09d105a2b53a 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -123,4 +123,12 @@ config USB_DWC3_QCOM for peripheral mode support. Say 'Y' or 'M' if you have one such device. +config USB_DWC3_HISI + tristate "HiSilicon Kirin Platforms" + depends on ((ARCH_HISI && ARM64) || COMPILE_TEST) && OF + default USB_DWC3 + help + Support USB2/3 functionality in HiSilicon Kirin platforms. + Say 'Y' or 'M' if you have one such device. + endif diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 6e3ef6144e5d..15781455e3f0 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -50,3 +50,4 @@ obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o obj-$(CONFIG_USB_DWC3_OF_SIMPLE) += dwc3-of-simple.o obj-$(CONFIG_USB_DWC3_ST) += dwc3-st.o obj-$(CONFIG_USB_DWC3_QCOM) += dwc3-qcom.o +obj-$(CONFIG_USB_DWC3_HISI) += dwc3-hisi.o diff --git a/drivers/usb/dwc3/dwc3-hisi.c b/drivers/usb/dwc3/dwc3-hisi.c new file mode 100644 index 000000000000..6e9787d420a7 --- /dev/null +++ b/drivers/usb/dwc3/dwc3-hisi.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: GPL-2.0+ +/** + * dwc3-hisi.c - Support for dwc3 platform devices on HiSilicon platforms + * + * Copyright (C) 2017-2018 Hilisicon Electronics Co., Ltd. + * http://www.huawei.com + * + * Authors: Yu Chen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct dwc3_hisi { + struct device *dev; + struct clk **clks; + int num_clocks; + struct reset_control **rstcs; + int num_rstcs; +}; + +struct dwc3_hisi *g_dwc3_hisi; + +static int dwc3_hisi_init_clks(struct dwc3_hisi *dwc3_hisi, + struct device_node *np) +{ + struct device *dev = dwc3_hisi->dev; + int i; + + dwc3_hisi->num_clocks = of_clk_get_parent_count(np); + if (!dwc3_hisi->num_clocks) + return -ENOENT; + + dwc3_hisi->clks = devm_kcalloc(dev, dwc3_hisi->num_clocks, + sizeof(struct clk *), GFP_KERNEL); + if (!dwc3_hisi->clks) + return -ENOMEM; + + for (i = 0; i < dwc3_hisi->num_clocks; i++) { + struct clk *clk; + + clk = of_clk_get(np, i); + if (IS_ERR(clk)) { + while (--i >= 0) + clk_put(dwc3_hisi->clks[i]); + + return PTR_ERR(clk); + } + + dwc3_hisi->clks[i] = clk; + } + + return 0; +} + +static int dwc3_hisi_enable_clks(struct dwc3_hisi *dwc3_hisi) +{ + int i; + int ret; + + for (i = 0; i < dwc3_hisi->num_clocks; i++) { + ret = clk_prepare_enable(dwc3_hisi->clks[i]); + if (ret < 0) { + while (--i >= 0) + clk_disable_unprepare(dwc3_hisi->clks[i]); + + return ret; + } + } + + return 0; +} + +static void dwc3_hisi_disable_clks(struct dwc3_hisi *dwc3_hisi) +{ + int i; + + for (i = 0; i < dwc3_hisi->num_clocks; i++) + clk_disable_unprepare(dwc3_hisi->clks[i]); +} + +static int dwc3_hisi_get_rstcs(struct dwc3_hisi *dwc3_hisi, + struct device_node *np) +{ + struct device *dev = dwc3_hisi->dev; + int i; + + dwc3_hisi->num_rstcs = of_count_phandle_with_args(np, + "resets", "#reset-cells"); + if (!dwc3_hisi->num_rstcs) + return -ENOENT; + + dwc3_hisi->rstcs = devm_kcalloc(dev, dwc3_hisi->num_rstcs, + sizeof(struct reset_control *), GFP_KERNEL); + if (!dwc3_hisi->rstcs) + return -ENOMEM; + + for (i = 0; i < dwc3_hisi->num_rstcs; i++) { + struct reset_control *rstc; + + rstc = of_reset_control_get_shared_by_index(np, i); + if (IS_ERR(rstc)) { + while (--i >= 0) + reset_control_put(dwc3_hisi->rstcs[i]); + return PTR_ERR(rstc); + } + + dwc3_hisi->rstcs[i] = rstc; + } + + return 0; +} + +static int dwc3_hisi_reset_control_assert(struct dwc3_hisi *dwc3_hisi) +{ + int i, ret; + + for (i = dwc3_hisi->num_rstcs - 1; i >= 0 ; i--) { + ret = reset_control_assert(dwc3_hisi->rstcs[i]); + if (ret) { + while (--i >= 0) + reset_control_deassert(dwc3_hisi->rstcs[i]); + return ret; + } + udelay(10); + } + + return 0; +} + +static int dwc3_hisi_reset_control_deassert(struct dwc3_hisi *dwc3_hisi) +{ + int i, ret; + + for (i = 0; i < dwc3_hisi->num_rstcs; i++) { + ret = reset_control_deassert(dwc3_hisi->rstcs[i]); + if (ret) { + while (--i >= 0) + reset_control_assert(dwc3_hisi->rstcs[i]); + return ret; + } + udelay(10); + } + + return 0; +} + +static int dwc3_hisi_probe(struct platform_device *pdev) +{ + struct dwc3_hisi *dwc3_hisi; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + + int ret; + int i; + + dwc3_hisi = devm_kzalloc(dev, sizeof(*dwc3_hisi), GFP_KERNEL); + if (!dwc3_hisi) + return -ENOMEM; + + platform_set_drvdata(pdev, dwc3_hisi); + dwc3_hisi->dev = dev; + + ret = dwc3_hisi_init_clks(dwc3_hisi, np); + if (ret) { + dev_err(dev, "could not get clocks\n"); + return ret; + } + + ret = dwc3_hisi_enable_clks(dwc3_hisi); + if (ret) { + dev_err(dev, "could not enable clocks\n"); + goto err_put_clks; + } + + ret = dwc3_hisi_get_rstcs(dwc3_hisi, np); + if (ret) { + dev_err(dev, "could not get reset controllers\n"); + goto err_disable_clks; + } + ret = dwc3_hisi_reset_control_deassert(dwc3_hisi); + if (ret) { + dev_err(dev, "reset control deassert failed\n"); + goto err_put_rstcs; + } + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + + ret = of_platform_populate(np, NULL, NULL, dev); + if (ret) { + dev_err(dev, "failed to add dwc3 core\n"); + goto err_reset_assert; + } + + dev_err(dev, "finish dwc3 hisi probe\n"); + + g_dwc3_hisi = dwc3_hisi; + return 0; + +err_reset_assert: + ret = dwc3_hisi_reset_control_assert(dwc3_hisi); + if (ret) + dev_err(dev, "reset control assert failed\n"); +err_put_rstcs: + for (i = 0; i < dwc3_hisi->num_rstcs; i++) + reset_control_put(dwc3_hisi->rstcs[i]); +err_disable_clks: + dwc3_hisi_disable_clks(dwc3_hisi); +err_put_clks: + for (i = 0; i < dwc3_hisi->num_clocks; i++) + clk_put(dwc3_hisi->clks[i]); + + return ret; +} + +static int dwc3_hisi_remove(struct platform_device *pdev) +{ + struct dwc3_hisi *dwc3_hisi = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + int i, ret; + + of_platform_depopulate(dev); + + ret = dwc3_hisi_reset_control_assert(dwc3_hisi); + if (ret) { + dev_err(dev, "reset control assert failed\n"); + return ret; + } + + for (i = 0; i < dwc3_hisi->num_clocks; i++) { + clk_disable_unprepare(dwc3_hisi->clks[i]); + clk_put(dwc3_hisi->clks[i]); + } + + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int dwc3_hisi_suspend(struct device *dev) +{ + struct dwc3_hisi *dwc3_hisi = dev_get_drvdata(dev); + int ret; + + dev_info(dev, "%s\n", __func__); + + ret = dwc3_hisi_reset_control_assert(dwc3_hisi); + if (ret) { + dev_err(dev, "reset control assert failed\n"); + return ret; + } + + dwc3_hisi_disable_clks(dwc3_hisi); + + pinctrl_pm_select_default_state(dev); + + return 0; +} + +static int dwc3_hisi_resume(struct device *dev) +{ + struct dwc3_hisi *dwc3_hisi = dev_get_drvdata(dev); + int ret; + + dev_info(dev, "%s\n", __func__); + pinctrl_pm_select_default_state(dev); + + ret = dwc3_hisi_enable_clks(dwc3_hisi); + if (ret) { + dev_err(dev, "could not enable clocks\n"); + return ret; + } + + ret = dwc3_hisi_reset_control_deassert(dwc3_hisi); + if (ret) { + dev_err(dev, "reset control deassert failed\n"); + return ret; + } + + /* Wait for clock stable */ + msleep(100); + + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +static SIMPLE_DEV_PM_OPS(dwc3_hisi_dev_pm_ops, + dwc3_hisi_suspend, dwc3_hisi_resume); + +static const struct of_device_id dwc3_hisi_match[] = { + { .compatible = "hisilicon,hi3660-dwc3" }, + { /* sentinel */ }, +}; + +MODULE_DEVICE_TABLE(of, dwc3_hisi_match); + +static struct platform_driver dwc3_hisi_driver = { + .probe = dwc3_hisi_probe, + .remove = dwc3_hisi_remove, + .driver = { + .name = "usb-hisi-dwc3", + .of_match_table = dwc3_hisi_match, + .pm = &dwc3_hisi_dev_pm_ops, + }, +}; + +module_platform_driver(dwc3_hisi_driver); + +MODULE_AUTHOR("Yu Chen "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("DesignWare USB3 HiSilicon Glue Layer"); -- 2.15.0-rc2 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Yu Chen Subject: [PATCH v1 04/12] usb: dwc3: dwc3-hisi: Add code for dwc3 of Hisilicon Soc Platform Date: Mon, 3 Dec 2018 11:45:07 +0800 Message-ID: <20181203034515.91412-5-chenyu56@huawei.com> References: <20181203034515.91412-1-chenyu56@huawei.com> Mime-Version: 1.0 Content-Type: text/plain Return-path: In-Reply-To: <20181203034515.91412-1-chenyu56@huawei.com> Sender: linux-kernel-owner@vger.kernel.org To: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Cc: suzhuangluan@hisilicon.com, kongfei@hisilicon.com, Yu Chen , Felipe Balbi , Greg Kroah-Hartman , "David S. Miller" , Mauro Carvalho Chehab , Andrew Morton , Arnd Bergmann , John Stultz , Binghui Wang List-Id: devicetree@vger.kernel.org This driver handles the poweron and shutdown of dwc3 core on Hisilicon Soc Platform. Cc: Felipe Balbi Cc: Greg Kroah-Hartman Cc: "David S. Miller" Cc: Mauro Carvalho Chehab Cc: Andrew Morton Cc: Arnd Bergmann Cc: John Stultz Cc: Binghui Wang Signed-off-by: Yu Chen --- MAINTAINERS | 8 ++ drivers/usb/dwc3/Kconfig | 8 ++ drivers/usb/dwc3/Makefile | 1 + drivers/usb/dwc3/dwc3-hisi.c | 335 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 352 insertions(+) create mode 100644 drivers/usb/dwc3/dwc3-hisi.c diff --git a/MAINTAINERS b/MAINTAINERS index 6c3fbbb361f8..1b6b3026804c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15465,6 +15465,14 @@ L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/roles/intel-xhci-usb-role-switch.c +USB IP DRIVER FOR HISILICON KIRIN +M: Yu Chen +M: Binghui Wang +L: linux-usb@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/usb/dwc3-hisi.txt +F: drivers/usb/dwc3/dwc3-hisi.c + USB ISP116X DRIVER M: Olav Kongas L: linux-usb@vger.kernel.org diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 1a0404fda596..09d105a2b53a 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -123,4 +123,12 @@ config USB_DWC3_QCOM for peripheral mode support. Say 'Y' or 'M' if you have one such device. +config USB_DWC3_HISI + tristate "HiSilicon Kirin Platforms" + depends on ((ARCH_HISI && ARM64) || COMPILE_TEST) && OF + default USB_DWC3 + help + Support USB2/3 functionality in HiSilicon Kirin platforms. + Say 'Y' or 'M' if you have one such device. + endif diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 6e3ef6144e5d..15781455e3f0 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -50,3 +50,4 @@ obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o obj-$(CONFIG_USB_DWC3_OF_SIMPLE) += dwc3-of-simple.o obj-$(CONFIG_USB_DWC3_ST) += dwc3-st.o obj-$(CONFIG_USB_DWC3_QCOM) += dwc3-qcom.o +obj-$(CONFIG_USB_DWC3_HISI) += dwc3-hisi.o diff --git a/drivers/usb/dwc3/dwc3-hisi.c b/drivers/usb/dwc3/dwc3-hisi.c new file mode 100644 index 000000000000..6e9787d420a7 --- /dev/null +++ b/drivers/usb/dwc3/dwc3-hisi.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: GPL-2.0+ +/** + * dwc3-hisi.c - Support for dwc3 platform devices on HiSilicon platforms + * + * Copyright (C) 2017-2018 Hilisicon Electronics Co., Ltd. + * http://www.huawei.com + * + * Authors: Yu Chen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct dwc3_hisi { + struct device *dev; + struct clk **clks; + int num_clocks; + struct reset_control **rstcs; + int num_rstcs; +}; + +struct dwc3_hisi *g_dwc3_hisi; + +static int dwc3_hisi_init_clks(struct dwc3_hisi *dwc3_hisi, + struct device_node *np) +{ + struct device *dev = dwc3_hisi->dev; + int i; + + dwc3_hisi->num_clocks = of_clk_get_parent_count(np); + if (!dwc3_hisi->num_clocks) + return -ENOENT; + + dwc3_hisi->clks = devm_kcalloc(dev, dwc3_hisi->num_clocks, + sizeof(struct clk *), GFP_KERNEL); + if (!dwc3_hisi->clks) + return -ENOMEM; + + for (i = 0; i < dwc3_hisi->num_clocks; i++) { + struct clk *clk; + + clk = of_clk_get(np, i); + if (IS_ERR(clk)) { + while (--i >= 0) + clk_put(dwc3_hisi->clks[i]); + + return PTR_ERR(clk); + } + + dwc3_hisi->clks[i] = clk; + } + + return 0; +} + +static int dwc3_hisi_enable_clks(struct dwc3_hisi *dwc3_hisi) +{ + int i; + int ret; + + for (i = 0; i < dwc3_hisi->num_clocks; i++) { + ret = clk_prepare_enable(dwc3_hisi->clks[i]); + if (ret < 0) { + while (--i >= 0) + clk_disable_unprepare(dwc3_hisi->clks[i]); + + return ret; + } + } + + return 0; +} + +static void dwc3_hisi_disable_clks(struct dwc3_hisi *dwc3_hisi) +{ + int i; + + for (i = 0; i < dwc3_hisi->num_clocks; i++) + clk_disable_unprepare(dwc3_hisi->clks[i]); +} + +static int dwc3_hisi_get_rstcs(struct dwc3_hisi *dwc3_hisi, + struct device_node *np) +{ + struct device *dev = dwc3_hisi->dev; + int i; + + dwc3_hisi->num_rstcs = of_count_phandle_with_args(np, + "resets", "#reset-cells"); + if (!dwc3_hisi->num_rstcs) + return -ENOENT; + + dwc3_hisi->rstcs = devm_kcalloc(dev, dwc3_hisi->num_rstcs, + sizeof(struct reset_control *), GFP_KERNEL); + if (!dwc3_hisi->rstcs) + return -ENOMEM; + + for (i = 0; i < dwc3_hisi->num_rstcs; i++) { + struct reset_control *rstc; + + rstc = of_reset_control_get_shared_by_index(np, i); + if (IS_ERR(rstc)) { + while (--i >= 0) + reset_control_put(dwc3_hisi->rstcs[i]); + return PTR_ERR(rstc); + } + + dwc3_hisi->rstcs[i] = rstc; + } + + return 0; +} + +static int dwc3_hisi_reset_control_assert(struct dwc3_hisi *dwc3_hisi) +{ + int i, ret; + + for (i = dwc3_hisi->num_rstcs - 1; i >= 0 ; i--) { + ret = reset_control_assert(dwc3_hisi->rstcs[i]); + if (ret) { + while (--i >= 0) + reset_control_deassert(dwc3_hisi->rstcs[i]); + return ret; + } + udelay(10); + } + + return 0; +} + +static int dwc3_hisi_reset_control_deassert(struct dwc3_hisi *dwc3_hisi) +{ + int i, ret; + + for (i = 0; i < dwc3_hisi->num_rstcs; i++) { + ret = reset_control_deassert(dwc3_hisi->rstcs[i]); + if (ret) { + while (--i >= 0) + reset_control_assert(dwc3_hisi->rstcs[i]); + return ret; + } + udelay(10); + } + + return 0; +} + +static int dwc3_hisi_probe(struct platform_device *pdev) +{ + struct dwc3_hisi *dwc3_hisi; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + + int ret; + int i; + + dwc3_hisi = devm_kzalloc(dev, sizeof(*dwc3_hisi), GFP_KERNEL); + if (!dwc3_hisi) + return -ENOMEM; + + platform_set_drvdata(pdev, dwc3_hisi); + dwc3_hisi->dev = dev; + + ret = dwc3_hisi_init_clks(dwc3_hisi, np); + if (ret) { + dev_err(dev, "could not get clocks\n"); + return ret; + } + + ret = dwc3_hisi_enable_clks(dwc3_hisi); + if (ret) { + dev_err(dev, "could not enable clocks\n"); + goto err_put_clks; + } + + ret = dwc3_hisi_get_rstcs(dwc3_hisi, np); + if (ret) { + dev_err(dev, "could not get reset controllers\n"); + goto err_disable_clks; + } + ret = dwc3_hisi_reset_control_deassert(dwc3_hisi); + if (ret) { + dev_err(dev, "reset control deassert failed\n"); + goto err_put_rstcs; + } + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + + ret = of_platform_populate(np, NULL, NULL, dev); + if (ret) { + dev_err(dev, "failed to add dwc3 core\n"); + goto err_reset_assert; + } + + dev_err(dev, "finish dwc3 hisi probe\n"); + + g_dwc3_hisi = dwc3_hisi; + return 0; + +err_reset_assert: + ret = dwc3_hisi_reset_control_assert(dwc3_hisi); + if (ret) + dev_err(dev, "reset control assert failed\n"); +err_put_rstcs: + for (i = 0; i < dwc3_hisi->num_rstcs; i++) + reset_control_put(dwc3_hisi->rstcs[i]); +err_disable_clks: + dwc3_hisi_disable_clks(dwc3_hisi); +err_put_clks: + for (i = 0; i < dwc3_hisi->num_clocks; i++) + clk_put(dwc3_hisi->clks[i]); + + return ret; +} + +static int dwc3_hisi_remove(struct platform_device *pdev) +{ + struct dwc3_hisi *dwc3_hisi = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + int i, ret; + + of_platform_depopulate(dev); + + ret = dwc3_hisi_reset_control_assert(dwc3_hisi); + if (ret) { + dev_err(dev, "reset control assert failed\n"); + return ret; + } + + for (i = 0; i < dwc3_hisi->num_clocks; i++) { + clk_disable_unprepare(dwc3_hisi->clks[i]); + clk_put(dwc3_hisi->clks[i]); + } + + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int dwc3_hisi_suspend(struct device *dev) +{ + struct dwc3_hisi *dwc3_hisi = dev_get_drvdata(dev); + int ret; + + dev_info(dev, "%s\n", __func__); + + ret = dwc3_hisi_reset_control_assert(dwc3_hisi); + if (ret) { + dev_err(dev, "reset control assert failed\n"); + return ret; + } + + dwc3_hisi_disable_clks(dwc3_hisi); + + pinctrl_pm_select_default_state(dev); + + return 0; +} + +static int dwc3_hisi_resume(struct device *dev) +{ + struct dwc3_hisi *dwc3_hisi = dev_get_drvdata(dev); + int ret; + + dev_info(dev, "%s\n", __func__); + pinctrl_pm_select_default_state(dev); + + ret = dwc3_hisi_enable_clks(dwc3_hisi); + if (ret) { + dev_err(dev, "could not enable clocks\n"); + return ret; + } + + ret = dwc3_hisi_reset_control_deassert(dwc3_hisi); + if (ret) { + dev_err(dev, "reset control deassert failed\n"); + return ret; + } + + /* Wait for clock stable */ + msleep(100); + + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +static SIMPLE_DEV_PM_OPS(dwc3_hisi_dev_pm_ops, + dwc3_hisi_suspend, dwc3_hisi_resume); + +static const struct of_device_id dwc3_hisi_match[] = { + { .compatible = "hisilicon,hi3660-dwc3" }, + { /* sentinel */ }, +}; + +MODULE_DEVICE_TABLE(of, dwc3_hisi_match); + +static struct platform_driver dwc3_hisi_driver = { + .probe = dwc3_hisi_probe, + .remove = dwc3_hisi_remove, + .driver = { + .name = "usb-hisi-dwc3", + .of_match_table = dwc3_hisi_match, + .pm = &dwc3_hisi_dev_pm_ops, + }, +}; + +module_platform_driver(dwc3_hisi_driver); + +MODULE_AUTHOR("Yu Chen "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("DesignWare USB3 HiSilicon Glue Layer"); -- 2.15.0-rc2 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: [v1,04/12] usb: dwc3: dwc3-hisi: Add code for dwc3 of Hisilicon Soc Platform From: Yu Chen Message-Id: <20181203034515.91412-5-chenyu56@huawei.com> Date: Mon, 3 Dec 2018 11:45:07 +0800 To: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Cc: suzhuangluan@hisilicon.com, kongfei@hisilicon.com, Yu Chen , Felipe Balbi , Greg Kroah-Hartman , "David S. Miller" , Mauro Carvalho Chehab , Andrew Morton , Arnd Bergmann , John Stultz , Binghui Wang List-ID: VGhpcyBkcml2ZXIgaGFuZGxlcyB0aGUgcG93ZXJvbiBhbmQgc2h1dGRvd24gb2YgZHdjMyBjb3Jl Cm9uIEhpc2lsaWNvbiBTb2MgUGxhdGZvcm0uCgpDYzogRmVsaXBlIEJhbGJpIDxiYWxiaUBrZXJu ZWwub3JnPgpDYzogR3JlZyBLcm9haC1IYXJ0bWFuIDxncmVna2hAbGludXhmb3VuZGF0aW9uLm9y Zz4KQ2M6ICJEYXZpZCBTLiBNaWxsZXIiIDxkYXZlbUBkYXZlbWxvZnQubmV0PgpDYzogTWF1cm8g Q2FydmFsaG8gQ2hlaGFiIDxtY2hlaGFiK3NhbXN1bmdAa2VybmVsLm9yZz4KQ2M6IEFuZHJldyBN b3J0b24gPGFrcG1AbGludXgtZm91bmRhdGlvbi5vcmc+CkNjOiBBcm5kIEJlcmdtYW5uIDxhcm5k QGFybmRiLmRlPgpDYzogSm9obiBTdHVsdHogPGpvaG4uc3R1bHR6QGxpbmFyby5vcmc+CkNjOiBC aW5naHVpIFdhbmcgPHdhbmdiaW5naHVpQGhpc2lsaWNvbi5jb20+ClNpZ25lZC1vZmYtYnk6IFl1 IENoZW4gPGNoZW55dTU2QGh1YXdlaS5jb20+Ci0tLQogTUFJTlRBSU5FUlMgICAgICAgICAgICAg ICAgICB8ICAgOCArKwogZHJpdmVycy91c2IvZHdjMy9LY29uZmlnICAgICB8ICAgOCArKwogZHJp dmVycy91c2IvZHdjMy9NYWtlZmlsZSAgICB8ICAgMSArCiBkcml2ZXJzL3VzYi9kd2MzL2R3YzMt aGlzaS5jIHwgMzM1ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysK IDQgZmlsZXMgY2hhbmdlZCwgMzUyIGluc2VydGlvbnMoKykKIGNyZWF0ZSBtb2RlIDEwMDY0NCBk cml2ZXJzL3VzYi9kd2MzL2R3YzMtaGlzaS5jCgpkaWZmIC0tZ2l0IGEvTUFJTlRBSU5FUlMgYi9N QUlOVEFJTkVSUwppbmRleCA2YzNmYmJiMzYxZjguLjFiNmIzMDI2ODA0YyAxMDA2NDQKLS0tIGEv TUFJTlRBSU5FUlMKKysrIGIvTUFJTlRBSU5FUlMKQEAgLTE1NDY1LDYgKzE1NDY1LDE0IEBAIEw6 CWxpbnV4LXVzYkB2Z2VyLmtlcm5lbC5vcmcKIFM6CU1haW50YWluZWQKIEY6CWRyaXZlcnMvdXNi L3JvbGVzL2ludGVsLXhoY2ktdXNiLXJvbGUtc3dpdGNoLmMKIAorVVNCIElQIERSSVZFUiBGT1Ig SElTSUxJQ09OIEtJUklOCitNOglZdSBDaGVuIDxjaGVueXU1NkBodWF3ZWkuY29tPgorTToJQmlu Z2h1aSBXYW5nIDx3YW5nYmluZ2h1aUBoaXNpbGljb24uY29tPgorTDoJbGludXgtdXNiQHZnZXIu a2VybmVsLm9yZworUzoJTWFpbnRhaW5lZAorRjoJRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2Jp bmRpbmdzL3VzYi9kd2MzLWhpc2kudHh0CitGOglkcml2ZXJzL3VzYi9kd2MzL2R3YzMtaGlzaS5j CisKIFVTQiBJU1AxMTZYIERSSVZFUgogTToJT2xhdiBLb25nYXMgPG9rQGFydGVjZGVzaWduLmVl PgogTDoJbGludXgtdXNiQHZnZXIua2VybmVsLm9yZwpkaWZmIC0tZ2l0IGEvZHJpdmVycy91c2Iv ZHdjMy9LY29uZmlnIGIvZHJpdmVycy91c2IvZHdjMy9LY29uZmlnCmluZGV4IDFhMDQwNGZkYTU5 Ni4uMDlkMTA1YTJiNTNhIDEwMDY0NAotLS0gYS9kcml2ZXJzL3VzYi9kd2MzL0tjb25maWcKKysr IGIvZHJpdmVycy91c2IvZHdjMy9LY29uZmlnCkBAIC0xMjMsNCArMTIzLDEyIEBAIGNvbmZpZyBV U0JfRFdDM19RQ09NCiAJICBmb3IgcGVyaXBoZXJhbCBtb2RlIHN1cHBvcnQuCiAJICBTYXkgJ1kn IG9yICdNJyBpZiB5b3UgaGF2ZSBvbmUgc3VjaCBkZXZpY2UuCiAKK2NvbmZpZyBVU0JfRFdDM19I SVNJCisJdHJpc3RhdGUgIkhpU2lsaWNvbiBLaXJpbiBQbGF0Zm9ybXMiCisJZGVwZW5kcyBvbiAo KEFSQ0hfSElTSSAmJiBBUk02NCkgfHwgQ09NUElMRV9URVNUKSAmJiBPRgorCWRlZmF1bHQgVVNC X0RXQzMKKwloZWxwCisJICBTdXBwb3J0IFVTQjIvMyBmdW5jdGlvbmFsaXR5IGluIEhpU2lsaWNv biBLaXJpbiBwbGF0Zm9ybXMuCisJICBTYXkgJ1knIG9yICdNJyBpZiB5b3UgaGF2ZSBvbmUgc3Vj aCBkZXZpY2UuCisKIGVuZGlmCmRpZmYgLS1naXQgYS9kcml2ZXJzL3VzYi9kd2MzL01ha2VmaWxl IGIvZHJpdmVycy91c2IvZHdjMy9NYWtlZmlsZQppbmRleCA2ZTNlZjYxNDRlNWQuLjE1NzgxNDU1 ZTNmMCAxMDA2NDQKLS0tIGEvZHJpdmVycy91c2IvZHdjMy9NYWtlZmlsZQorKysgYi9kcml2ZXJz L3VzYi9kd2MzL01ha2VmaWxlCkBAIC01MCwzICs1MCw0IEBAIG9iai0kKENPTkZJR19VU0JfRFdD M19LRVlTVE9ORSkJCSs9IGR3YzMta2V5c3RvbmUubwogb2JqLSQoQ09ORklHX1VTQl9EV0MzX09G X1NJTVBMRSkJKz0gZHdjMy1vZi1zaW1wbGUubwogb2JqLSQoQ09ORklHX1VTQl9EV0MzX1NUKQkJ Kz0gZHdjMy1zdC5vCiBvYmotJChDT05GSUdfVVNCX0RXQzNfUUNPTSkJCSs9IGR3YzMtcWNvbS5v CitvYmotJChDT05GSUdfVVNCX0RXQzNfSElTSSkJCSs9IGR3YzMtaGlzaS5vCmRpZmYgLS1naXQg YS9kcml2ZXJzL3VzYi9kd2MzL2R3YzMtaGlzaS5jIGIvZHJpdmVycy91c2IvZHdjMy9kd2MzLWhp c2kuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMDAuLjZlOTc4N2Q0MjBh NwotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZlcnMvdXNiL2R3YzMvZHdjMy1oaXNpLmMKQEAgLTAs MCArMSwzMzUgQEAKKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wKworLyoqCisg KiBkd2MzLWhpc2kuYyAtIFN1cHBvcnQgZm9yIGR3YzMgcGxhdGZvcm0gZGV2aWNlcyBvbiBIaVNp bGljb24gcGxhdGZvcm1zCisgKgorICogQ29weXJpZ2h0IChDKSAyMDE3LTIwMTggSGlsaXNpY29u IEVsZWN0cm9uaWNzIENvLiwgTHRkLgorICoJCWh0dHA6Ly93d3cuaHVhd2VpLmNvbQorICoKKyAq IEF1dGhvcnM6IFl1IENoZW4gPGNoZW55dTU2QGh1YXdlaS5jb20+CisgKgorICogVGhpcyBwcm9n cmFtIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2Rp ZnkKKyAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vu c2UgdmVyc2lvbiAyICBvZgorICogdGhlIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVl IFNvZnR3YXJlIEZvdW5kYXRpb24uCisgKgorICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVk IGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCisgKiBidXQgV0lUSE9VVCBBTlkg V0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgorICogTUVSQ0hB TlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQor ICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KKyAqLworCisj aW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVkZSA8bGludXgva2VybmVsLmg+CisjaW5j bHVkZSA8bGludXgvc2xhYi5oPgorI2luY2x1ZGUgPGxpbnV4L29mLmg+CisjaW5jbHVkZSA8bGlu dXgvb2ZfcGxhdGZvcm0uaD4KKyNpbmNsdWRlIDxsaW51eC9wbV9ydW50aW1lLmg+CisjaW5jbHVk ZSA8bGludXgvY2xrLmg+CisjaW5jbHVkZSA8bGludXgvY2xrLXByb3ZpZGVyLmg+CisjaW5jbHVk ZSA8bGludXgvcmVnbWFwLmg+CisjaW5jbHVkZSA8bGludXgvcmVzZXQuaD4KKyNpbmNsdWRlIDxs aW51eC9leHRjb24uaD4KKyNpbmNsdWRlIDxsaW51eC9yZWd1bGF0b3IvY29uc3VtZXIuaD4KKyNp bmNsdWRlIDxsaW51eC9waW5jdHJsL2NvbnN1bWVyLmg+CisKK3N0cnVjdCBkd2MzX2hpc2kgewor CXN0cnVjdCBkZXZpY2UJCSpkZXY7CisJc3RydWN0IGNsawkJKipjbGtzOworCWludAkJCW51bV9j bG9ja3M7CisJc3RydWN0IHJlc2V0X2NvbnRyb2wJKipyc3RjczsKKwlpbnQJCQludW1fcnN0Y3M7 Cit9OworCitzdHJ1Y3QgZHdjM19oaXNpICpnX2R3YzNfaGlzaTsKKworc3RhdGljIGludCBkd2Mz X2hpc2lfaW5pdF9jbGtzKHN0cnVjdCBkd2MzX2hpc2kgKmR3YzNfaGlzaSwKKwkJc3RydWN0IGRl dmljZV9ub2RlICpucCkKK3sKKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSBkd2MzX2hpc2ktPmRldjsK KwlpbnQgaTsKKworCWR3YzNfaGlzaS0+bnVtX2Nsb2NrcyA9IG9mX2Nsa19nZXRfcGFyZW50X2Nv dW50KG5wKTsKKwlpZiAoIWR3YzNfaGlzaS0+bnVtX2Nsb2NrcykKKwkJcmV0dXJuIC1FTk9FTlQ7 CisKKwlkd2MzX2hpc2ktPmNsa3MgPSBkZXZtX2tjYWxsb2MoZGV2LCBkd2MzX2hpc2ktPm51bV9j bG9ja3MsCisJCQlzaXplb2Yoc3RydWN0IGNsayAqKSwgR0ZQX0tFUk5FTCk7CisJaWYgKCFkd2Mz X2hpc2ktPmNsa3MpCisJCXJldHVybiAtRU5PTUVNOworCisJZm9yIChpID0gMDsgaSA8IGR3YzNf aGlzaS0+bnVtX2Nsb2NrczsgaSsrKSB7CisJCXN0cnVjdCBjbGsJKmNsazsKKworCQljbGsgPSBv Zl9jbGtfZ2V0KG5wLCBpKTsKKwkJaWYgKElTX0VSUihjbGspKSB7CisJCQl3aGlsZSAoLS1pID49 IDApCisJCQkJY2xrX3B1dChkd2MzX2hpc2ktPmNsa3NbaV0pOworCisJCQlyZXR1cm4gUFRSX0VS UihjbGspOworCQl9CisKKwkJZHdjM19oaXNpLT5jbGtzW2ldID0gY2xrOworCX0KKworCXJldHVy biAwOworfQorCitzdGF0aWMgaW50IGR3YzNfaGlzaV9lbmFibGVfY2xrcyhzdHJ1Y3QgZHdjM19o aXNpICpkd2MzX2hpc2kpCit7CisJaW50IGk7CisJaW50IHJldDsKKworCWZvciAoaSA9IDA7IGkg PCBkd2MzX2hpc2ktPm51bV9jbG9ja3M7IGkrKykgeworCQlyZXQgPSBjbGtfcHJlcGFyZV9lbmFi bGUoZHdjM19oaXNpLT5jbGtzW2ldKTsKKwkJaWYgKHJldCA8IDApIHsKKwkJCXdoaWxlICgtLWkg Pj0gMCkKKwkJCQljbGtfZGlzYWJsZV91bnByZXBhcmUoZHdjM19oaXNpLT5jbGtzW2ldKTsKKwor CQkJcmV0dXJuIHJldDsKKwkJfQorCX0KKworCXJldHVybiAwOworfQorCitzdGF0aWMgdm9pZCBk d2MzX2hpc2lfZGlzYWJsZV9jbGtzKHN0cnVjdCBkd2MzX2hpc2kgKmR3YzNfaGlzaSkKK3sKKwlp bnQgaTsKKworCWZvciAoaSA9IDA7IGkgPCBkd2MzX2hpc2ktPm51bV9jbG9ja3M7IGkrKykKKwkJ Y2xrX2Rpc2FibGVfdW5wcmVwYXJlKGR3YzNfaGlzaS0+Y2xrc1tpXSk7Cit9CisKK3N0YXRpYyBp bnQgZHdjM19oaXNpX2dldF9yc3RjcyhzdHJ1Y3QgZHdjM19oaXNpICpkd2MzX2hpc2ksCisJCXN0 cnVjdCBkZXZpY2Vfbm9kZSAqbnApCit7CisJc3RydWN0IGRldmljZSAqZGV2ID0gZHdjM19oaXNp LT5kZXY7CisJaW50IGk7CisKKwlkd2MzX2hpc2ktPm51bV9yc3RjcyA9IG9mX2NvdW50X3BoYW5k bGVfd2l0aF9hcmdzKG5wLAorCQkJInJlc2V0cyIsICIjcmVzZXQtY2VsbHMiKTsKKwlpZiAoIWR3 YzNfaGlzaS0+bnVtX3JzdGNzKQorCQlyZXR1cm4gLUVOT0VOVDsKKworCWR3YzNfaGlzaS0+cnN0 Y3MgPSBkZXZtX2tjYWxsb2MoZGV2LCBkd2MzX2hpc2ktPm51bV9yc3RjcywKKwkJCXNpemVvZihz dHJ1Y3QgcmVzZXRfY29udHJvbCAqKSwgR0ZQX0tFUk5FTCk7CisJaWYgKCFkd2MzX2hpc2ktPnJz dGNzKQorCQlyZXR1cm4gLUVOT01FTTsKKworCWZvciAoaSA9IDA7IGkgPCBkd2MzX2hpc2ktPm51 bV9yc3RjczsgaSsrKSB7CisJCXN0cnVjdCByZXNldF9jb250cm9sICpyc3RjOworCisJCXJzdGMg PSBvZl9yZXNldF9jb250cm9sX2dldF9zaGFyZWRfYnlfaW5kZXgobnAsIGkpOworCQlpZiAoSVNf RVJSKHJzdGMpKSB7CisJCQl3aGlsZSAoLS1pID49IDApCisJCQkJcmVzZXRfY29udHJvbF9wdXQo ZHdjM19oaXNpLT5yc3Rjc1tpXSk7CisJCQlyZXR1cm4gUFRSX0VSUihyc3RjKTsKKwkJfQorCisJ CWR3YzNfaGlzaS0+cnN0Y3NbaV0gPSByc3RjOworCX0KKworCXJldHVybiAwOworfQorCitzdGF0 aWMgaW50IGR3YzNfaGlzaV9yZXNldF9jb250cm9sX2Fzc2VydChzdHJ1Y3QgZHdjM19oaXNpICpk d2MzX2hpc2kpCit7CisJaW50IGksIHJldDsKKworCWZvciAoaSA9IGR3YzNfaGlzaS0+bnVtX3Jz dGNzIC0gMTsgaSA+PSAwIDsgaS0tKSB7CisJCXJldCA9IHJlc2V0X2NvbnRyb2xfYXNzZXJ0KGR3 YzNfaGlzaS0+cnN0Y3NbaV0pOworCQlpZiAocmV0KSB7CisJCQl3aGlsZSAoLS1pID49IDApCisJ CQkJcmVzZXRfY29udHJvbF9kZWFzc2VydChkd2MzX2hpc2ktPnJzdGNzW2ldKTsKKwkJCXJldHVy biByZXQ7CisJCX0KKwkJdWRlbGF5KDEwKTsKKwl9CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGlj IGludCBkd2MzX2hpc2lfcmVzZXRfY29udHJvbF9kZWFzc2VydChzdHJ1Y3QgZHdjM19oaXNpICpk d2MzX2hpc2kpCit7CisJaW50IGksIHJldDsKKworCWZvciAoaSA9IDA7IGkgPCBkd2MzX2hpc2kt Pm51bV9yc3RjczsgaSsrKSB7CisJCXJldCA9IHJlc2V0X2NvbnRyb2xfZGVhc3NlcnQoZHdjM19o aXNpLT5yc3Rjc1tpXSk7CisJCWlmIChyZXQpIHsKKwkJCXdoaWxlICgtLWkgPj0gMCkKKwkJCQly ZXNldF9jb250cm9sX2Fzc2VydChkd2MzX2hpc2ktPnJzdGNzW2ldKTsKKwkJCXJldHVybiByZXQ7 CisJCX0KKwkJdWRlbGF5KDEwKTsKKwl9CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBk d2MzX2hpc2lfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKK3sKKwlzdHJ1Y3Qg ZHdjM19oaXNpCSpkd2MzX2hpc2k7CisJc3RydWN0IGRldmljZQkJKmRldiA9ICZwZGV2LT5kZXY7 CisJc3RydWN0IGRldmljZV9ub2RlCSpucCA9IGRldi0+b2Zfbm9kZTsKKworCWludAkJCXJldDsK KwlpbnQJCQlpOworCisJZHdjM19oaXNpID0gZGV2bV9remFsbG9jKGRldiwgc2l6ZW9mKCpkd2Mz X2hpc2kpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIWR3YzNfaGlzaSkKKwkJcmV0dXJuIC1FTk9NRU07 CisKKwlwbGF0Zm9ybV9zZXRfZHJ2ZGF0YShwZGV2LCBkd2MzX2hpc2kpOworCWR3YzNfaGlzaS0+ ZGV2ID0gZGV2OworCisJcmV0ID0gZHdjM19oaXNpX2luaXRfY2xrcyhkd2MzX2hpc2ksIG5wKTsK KwlpZiAocmV0KSB7CisJCWRldl9lcnIoZGV2LCAiY291bGQgbm90IGdldCBjbG9ja3NcbiIpOwor CQlyZXR1cm4gcmV0OworCX0KKworCXJldCA9IGR3YzNfaGlzaV9lbmFibGVfY2xrcyhkd2MzX2hp c2kpOworCWlmIChyZXQpIHsKKwkJZGV2X2VycihkZXYsICJjb3VsZCBub3QgZW5hYmxlIGNsb2Nr c1xuIik7CisJCWdvdG8gZXJyX3B1dF9jbGtzOworCX0KKworCXJldCA9IGR3YzNfaGlzaV9nZXRf cnN0Y3MoZHdjM19oaXNpLCBucCk7CisJaWYgKHJldCkgeworCQlkZXZfZXJyKGRldiwgImNvdWxk IG5vdCBnZXQgcmVzZXQgY29udHJvbGxlcnNcbiIpOworCQlnb3RvIGVycl9kaXNhYmxlX2Nsa3M7 CisJfQorCXJldCA9IGR3YzNfaGlzaV9yZXNldF9jb250cm9sX2RlYXNzZXJ0KGR3YzNfaGlzaSk7 CisJaWYgKHJldCkgeworCQlkZXZfZXJyKGRldiwgInJlc2V0IGNvbnRyb2wgZGVhc3NlcnQgZmFp bGVkXG4iKTsKKwkJZ290byBlcnJfcHV0X3JzdGNzOworCX0KKworCXBtX3J1bnRpbWVfc2V0X2Fj dGl2ZShkZXYpOworCXBtX3J1bnRpbWVfZW5hYmxlKGRldik7CisJcG1fcnVudGltZV9nZXRfc3lu YyhkZXYpOworCisJcmV0ID0gb2ZfcGxhdGZvcm1fcG9wdWxhdGUobnAsIE5VTEwsIE5VTEwsIGRl dik7CisJaWYgKHJldCkgeworCQlkZXZfZXJyKGRldiwgImZhaWxlZCB0byBhZGQgZHdjMyBjb3Jl XG4iKTsKKwkJZ290byBlcnJfcmVzZXRfYXNzZXJ0OworCX0KKworCWRldl9lcnIoZGV2LCAiZmlu aXNoIGR3YzMgaGlzaSBwcm9iZVxuIik7CisKKwlnX2R3YzNfaGlzaSA9IGR3YzNfaGlzaTsKKwly ZXR1cm4gMDsKKworZXJyX3Jlc2V0X2Fzc2VydDoKKwlyZXQgPSBkd2MzX2hpc2lfcmVzZXRfY29u dHJvbF9hc3NlcnQoZHdjM19oaXNpKTsKKwlpZiAocmV0KQorCQlkZXZfZXJyKGRldiwgInJlc2V0 IGNvbnRyb2wgYXNzZXJ0IGZhaWxlZFxuIik7CitlcnJfcHV0X3JzdGNzOgorCWZvciAoaSA9IDA7 IGkgPCBkd2MzX2hpc2ktPm51bV9yc3RjczsgaSsrKQorCQlyZXNldF9jb250cm9sX3B1dChkd2Mz X2hpc2ktPnJzdGNzW2ldKTsKK2Vycl9kaXNhYmxlX2Nsa3M6CisJZHdjM19oaXNpX2Rpc2FibGVf Y2xrcyhkd2MzX2hpc2kpOworZXJyX3B1dF9jbGtzOgorCWZvciAoaSA9IDA7IGkgPCBkd2MzX2hp c2ktPm51bV9jbG9ja3M7IGkrKykKKwkJY2xrX3B1dChkd2MzX2hpc2ktPmNsa3NbaV0pOworCisJ cmV0dXJuIHJldDsKK30KKworc3RhdGljIGludCBkd2MzX2hpc2lfcmVtb3ZlKHN0cnVjdCBwbGF0 Zm9ybV9kZXZpY2UgKnBkZXYpCit7CisJc3RydWN0IGR3YzNfaGlzaQkqZHdjM19oaXNpID0gcGxh dGZvcm1fZ2V0X2RydmRhdGEocGRldik7CisJc3RydWN0IGRldmljZQkJKmRldiA9ICZwZGV2LT5k ZXY7CisJaW50CQkJaSwgcmV0OworCisJb2ZfcGxhdGZvcm1fZGVwb3B1bGF0ZShkZXYpOworCisJ cmV0ID0gZHdjM19oaXNpX3Jlc2V0X2NvbnRyb2xfYXNzZXJ0KGR3YzNfaGlzaSk7CisJaWYgKHJl dCkgeworCQlkZXZfZXJyKGRldiwgInJlc2V0IGNvbnRyb2wgYXNzZXJ0IGZhaWxlZFxuIik7CisJ CXJldHVybiByZXQ7CisJfQorCisJZm9yIChpID0gMDsgaSA8IGR3YzNfaGlzaS0+bnVtX2Nsb2Nr czsgaSsrKSB7CisJCWNsa19kaXNhYmxlX3VucHJlcGFyZShkd2MzX2hpc2ktPmNsa3NbaV0pOwor CQljbGtfcHV0KGR3YzNfaGlzaS0+Y2xrc1tpXSk7CisJfQorCisJcG1fcnVudGltZV9wdXRfc3lu YyhkZXYpOworCXBtX3J1bnRpbWVfZGlzYWJsZShkZXYpOworCisJcmV0dXJuIDA7Cit9CisKKyNp ZmRlZiBDT05GSUdfUE1fU0xFRVAKK3N0YXRpYyBpbnQgZHdjM19oaXNpX3N1c3BlbmQoc3RydWN0 IGRldmljZSAqZGV2KQoreworCXN0cnVjdCBkd2MzX2hpc2kgKmR3YzNfaGlzaSA9IGRldl9nZXRf ZHJ2ZGF0YShkZXYpOworCWludCByZXQ7CisKKwlkZXZfaW5mbyhkZXYsICIlc1xuIiwgX19mdW5j X18pOworCisJcmV0ID0gZHdjM19oaXNpX3Jlc2V0X2NvbnRyb2xfYXNzZXJ0KGR3YzNfaGlzaSk7 CisJaWYgKHJldCkgeworCQlkZXZfZXJyKGRldiwgInJlc2V0IGNvbnRyb2wgYXNzZXJ0IGZhaWxl ZFxuIik7CisJCXJldHVybiByZXQ7CisJfQorCisJZHdjM19oaXNpX2Rpc2FibGVfY2xrcyhkd2Mz X2hpc2kpOworCisJcGluY3RybF9wbV9zZWxlY3RfZGVmYXVsdF9zdGF0ZShkZXYpOworCisJcmV0 dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgZHdjM19oaXNpX3Jlc3VtZShzdHJ1Y3QgZGV2aWNlICpk ZXYpCit7CisJc3RydWN0IGR3YzNfaGlzaSAqZHdjM19oaXNpID0gZGV2X2dldF9kcnZkYXRhKGRl dik7CisJaW50IHJldDsKKworCWRldl9pbmZvKGRldiwgIiVzXG4iLCBfX2Z1bmNfXyk7CisJcGlu Y3RybF9wbV9zZWxlY3RfZGVmYXVsdF9zdGF0ZShkZXYpOworCisJcmV0ID0gZHdjM19oaXNpX2Vu YWJsZV9jbGtzKGR3YzNfaGlzaSk7CisJaWYgKHJldCkgeworCQlkZXZfZXJyKGRldiwgImNvdWxk IG5vdCBlbmFibGUgY2xvY2tzXG4iKTsKKwkJcmV0dXJuIHJldDsKKwl9CisKKwlyZXQgPSBkd2Mz X2hpc2lfcmVzZXRfY29udHJvbF9kZWFzc2VydChkd2MzX2hpc2kpOworCWlmIChyZXQpIHsKKwkJ ZGV2X2VycihkZXYsICJyZXNldCBjb250cm9sIGRlYXNzZXJ0IGZhaWxlZFxuIik7CisJCXJldHVy biByZXQ7CisJfQorCisJLyogV2FpdCBmb3IgY2xvY2sgc3RhYmxlICovCisJbXNsZWVwKDEwMCk7 CisKKwlyZXR1cm4gMDsKK30KKyNlbmRpZiAvKiBDT05GSUdfUE1fU0xFRVAgKi8KKworc3RhdGlj IFNJTVBMRV9ERVZfUE1fT1BTKGR3YzNfaGlzaV9kZXZfcG1fb3BzLAorCQlkd2MzX2hpc2lfc3Vz cGVuZCwgZHdjM19oaXNpX3Jlc3VtZSk7CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgb2ZfZGV2aWNl X2lkIGR3YzNfaGlzaV9tYXRjaFtdID0geworCXsgLmNvbXBhdGlibGUgPSAiaGlzaWxpY29uLGhp MzY2MC1kd2MzIiB9LAorCXsgLyogc2VudGluZWwgKi8gfSwKK307CisKK01PRFVMRV9ERVZJQ0Vf VEFCTEUob2YsIGR3YzNfaGlzaV9tYXRjaCk7CisKK3N0YXRpYyBzdHJ1Y3QgcGxhdGZvcm1fZHJp dmVyIGR3YzNfaGlzaV9kcml2ZXIgPSB7CisJLnByb2JlID0gZHdjM19oaXNpX3Byb2JlLAorCS5y ZW1vdmUgPSBkd2MzX2hpc2lfcmVtb3ZlLAorCS5kcml2ZXIgPSB7CisJCS5uYW1lID0gInVzYi1o aXNpLWR3YzMiLAorCQkub2ZfbWF0Y2hfdGFibGUgPSBkd2MzX2hpc2lfbWF0Y2gsCisJCS5wbSA9 ICZkd2MzX2hpc2lfZGV2X3BtX29wcywKKwl9LAorfTsKKworbW9kdWxlX3BsYXRmb3JtX2RyaXZl cihkd2MzX2hpc2lfZHJpdmVyKTsKKworTU9EVUxFX0FVVEhPUigiWXUgQ2hlbiA8Y2hlbnl1NTZA aHVhd2VpLmNvbT4iKTsKK01PRFVMRV9MSUNFTlNFKCJHUEwgdjIiKTsKK01PRFVMRV9ERVNDUklQ VElPTigiRGVzaWduV2FyZSBVU0IzIEhpU2lsaWNvbiBHbHVlIExheWVyIik7Cg==