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=-8.8 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 3E5A4C46475 for ; Sat, 27 Oct 2018 10:00:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id EFE582086E for ; Sat, 27 Oct 2018 10:00:10 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org EFE582086E 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 S1728583AbeJ0Ska (ORCPT ); Sat, 27 Oct 2018 14:40:30 -0400 Received: from szxga07-in.huawei.com ([45.249.212.35]:46204 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728434AbeJ0Sk3 (ORCPT ); Sat, 27 Oct 2018 14:40:29 -0400 Received: from DGGEMS406-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 586D043BDF76D; Sat, 27 Oct 2018 17:59:57 +0800 (CST) Received: from vm100-107-113-134.huawei.com (100.107.113.134) by DGGEMS406-HUB.china.huawei.com (10.3.19.206) with Microsoft SMTP Server id 14.3.408.0; Sat, 27 Oct 2018 17:59:52 +0800 From: Yu Chen To: , , CC: , , Yu Chen , Arnd Bergmann , Greg Kroah-Hartman , John Stultz , "Binghui Wang" Subject: [PATCH 07/10] hikey960: Support usb functionality of Hikey960 Date: Sat, 27 Oct 2018 17:58:17 +0800 Message-ID: <20181027095820.40056-8-chenyu56@huawei.com> X-Mailer: git-send-email 2.15.0-rc2 In-Reply-To: <20181027095820.40056-1-chenyu56@huawei.com> References: <20181027095820.40056-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 usb hub power on and typeC port event of HiKey960 board: 1)DP&DM switching between usb hub and typeC port base on typeC port state 2)Control power of usb hub on Hikey960 3)Control vbus of typeC port 4)Handle typeC port event to switch data role Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: John Stultz Cc: Binghui Wang Signed-off-by: Yu Chen --- drivers/misc/Kconfig | 7 + drivers/misc/Makefile | 1 + drivers/misc/hisi_hikey_usb.c | 319 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 327 insertions(+) create mode 100644 drivers/misc/hisi_hikey_usb.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 3726eacdf65d..8e04fc87b685 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -513,6 +513,13 @@ config MISC_RTSX tristate default MISC_RTSX_PCI || MISC_RTSX_USB +config HISI_HIKEY_USB + tristate "USB functionality of HiSilicon Hikey Platform" + depends on GPIOLIB + default n + help + If you say yes here you get support for usb functionality of HiSilicon Hikey Platform. + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index af22bbc3d00c..387dd302815c 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -58,3 +58,4 @@ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o obj-$(CONFIG_OCXL) += ocxl/ obj-$(CONFIG_MISC_RTSX) += cardreader/ +obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o diff --git a/drivers/misc/hisi_hikey_usb.c b/drivers/misc/hisi_hikey_usb.c new file mode 100644 index 000000000000..4965719c99ae --- /dev/null +++ b/drivers/misc/hisi_hikey_usb.c @@ -0,0 +1,319 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * hisi_hikey_usb.c + * + * Copyright (c) Hisilicon Tech. Co., Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + +#define DEVICE_DRIVER_NAME "hisi_hikey_usb" + +#define HUB_VBUS_POWER_ON 1 +#define HUB_VBUS_POWER_OFF 0 +#define USB_SWITCH_TO_HUB 1 +#define USB_SWITCH_TO_TYPEC 0 + +#define INVALID_GPIO_VALUE (-1) + +struct hisi_hikey_usb { + int otg_switch_gpio; + int typec_vbus_gpio; + int typec_vbus_enable_val; + int hub_vbus_gpio; + + struct extcon_dev *edev; + struct usb_role_switch *role_sw; +}; + +static const unsigned int usb_extcon_cable[] = { + EXTCON_USB, + EXTCON_USB_HOST, + EXTCON_NONE, +}; + +static void hub_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, int value) +{ + int gpio = hisi_hikey_usb->hub_vbus_gpio; + + if (gpio_is_valid(gpio)) + gpio_set_value(gpio, value); +} + +static void usb_switch_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, + int switch_to) +{ + int gpio = hisi_hikey_usb->otg_switch_gpio; + const char *switch_to_str = (switch_to == USB_SWITCH_TO_HUB) ? + "hub" : "typec"; + + if (!gpio_is_valid(gpio)) { + pr_err("%s: otg_switch_gpio is err\n", __func__); + return; + } + + if (gpio_get_value(gpio) == switch_to) { + pr_info("%s: already switch to %s\n", __func__, switch_to_str); + return; + } + + gpio_direction_output(gpio, switch_to); + pr_info("%s: switch to %s\n", __func__, switch_to_str); +} + +static void usb_typec_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, + int value) +{ + int gpio = hisi_hikey_usb->typec_vbus_gpio; + + if (!gpio_is_valid(gpio)) { + pr_err("%s: typec power gpio is err\n", __func__); + return; + } + + if (gpio_get_value(gpio) == value) { + pr_info("%s: typec power no change\n", __func__); + return; + } + + gpio_direction_output(gpio, value); + pr_info("%s: set typec vbus gpio to %d\n", __func__, value); +} + +static int extcon_hisi_pd_set_role(struct device *dev, enum usb_role role) +{ + struct hisi_hikey_usb *hisi_hikey_usb = dev_get_drvdata(dev); + + dev_info(dev, "%s:set usb role to %d\n", __func__, role); + switch (role) { + case USB_ROLE_NONE: + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_HUB); + usb_typec_power_ctrl(hisi_hikey_usb, + !hisi_hikey_usb->typec_vbus_enable_val); + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_ON); + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, false); + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST, + true); + break; + case USB_ROLE_HOST: + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC); + usb_typec_power_ctrl(hisi_hikey_usb, + hisi_hikey_usb->typec_vbus_enable_val); + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, false); + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST, + true); + break; + case USB_ROLE_DEVICE: + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_OFF); + usb_typec_power_ctrl(hisi_hikey_usb, + hisi_hikey_usb->typec_vbus_enable_val); + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC); + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST, + false); + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, true); + break; + } + + return 0; +} + +static enum usb_role extcon_hisi_pd_get_role(struct device *dev) +{ + struct hisi_hikey_usb *hisi_hikey_usb = dev_get_drvdata(dev); + + return usb_role_switch_get_role(hisi_hikey_usb->role_sw); +} + +static const struct usb_role_switch_desc sw_desc = { + .set = extcon_hisi_pd_set_role, + .get = extcon_hisi_pd_get_role, + .allow_userspace_control = true, +}; + +static int hisi_hikey_usb_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *root = dev->of_node; + struct hisi_hikey_usb *hisi_hikey_usb; + int ret; + + hisi_hikey_usb = devm_kzalloc(dev, sizeof(*hisi_hikey_usb), GFP_KERNEL); + if (!hisi_hikey_usb) + return -ENOMEM; + + dev_set_name(dev, "hisi_hikey_usb"); + + hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE; + hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE; + hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE; + + hisi_hikey_usb->hub_vbus_gpio = of_get_named_gpio(root, + "hub_vdd33_en_gpio", 0); + if (!gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) { + pr_err("%s: hub_vbus_gpio is err\n", __func__); + return hisi_hikey_usb->hub_vbus_gpio; + } + + ret = gpio_request(hisi_hikey_usb->hub_vbus_gpio, "hub_vbus_int_gpio"); + if (ret) { + pr_err("%s: request hub_vbus_gpio err\n", __func__); + hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE; + return ret; + } + + ret = gpio_direction_output(hisi_hikey_usb->hub_vbus_gpio, + HUB_VBUS_POWER_ON); + if (ret) { + pr_err("%s: power on hub vbus err\n", __func__); + goto free_gpio1; + } + + hisi_hikey_usb->typec_vbus_gpio = of_get_named_gpio(root, + "typc_vbus_int_gpio,typec-gpios", 0); + if (!gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) { + pr_err("%s: typec_vbus_gpio is err\n", __func__); + ret = hisi_hikey_usb->typec_vbus_gpio; + goto free_gpio1; + } + + ret = gpio_request(hisi_hikey_usb->typec_vbus_gpio, + "typc_vbus_int_gpio"); + if (ret) { + pr_err("%s: request typec_vbus_gpio err\n", __func__); + hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE; + goto free_gpio1; + } + + ret = of_property_read_u32(root, "typc_vbus_enable_val", + &hisi_hikey_usb->typec_vbus_enable_val); + if (ret) { + pr_err("%s: typc_vbus_enable_val can't get\n", __func__); + goto free_gpio2; + } + + hisi_hikey_usb->typec_vbus_enable_val = + !!hisi_hikey_usb->typec_vbus_enable_val; + + ret = gpio_direction_output(hisi_hikey_usb->typec_vbus_gpio, + hisi_hikey_usb->typec_vbus_enable_val); + if (ret) { + pr_err("%s: power on typec vbus err", __func__); + goto free_gpio2; + } + + if (of_device_is_compatible(root, "hisilicon,hikey960_usb")) { + hisi_hikey_usb->otg_switch_gpio = of_get_named_gpio(root, + "otg_gpio", 0); + if (!gpio_is_valid(hisi_hikey_usb->otg_switch_gpio)) { + pr_info("%s: otg_switch_gpio is err\n", __func__); + goto free_gpio2; + } + + ret = gpio_request(hisi_hikey_usb->otg_switch_gpio, + "otg_switch_gpio"); + if (ret) { + hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE; + pr_err("%s: request typec_vbus_gpio err\n", __func__); + goto free_gpio2; + } + } + + hisi_hikey_usb->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable); + if (IS_ERR(hisi_hikey_usb->edev)) { + dev_err(dev, "failed to allocate extcon device\n"); + goto free_gpio2; + } + + ret = devm_extcon_dev_register(dev, hisi_hikey_usb->edev); + if (ret < 0) { + dev_err(dev, "failed to register extcon device\n"); + goto free_gpio2; + } + extcon_set_state(hisi_hikey_usb->edev, EXTCON_USB_HOST, true); + + hisi_hikey_usb->role_sw = usb_role_switch_register(dev, &sw_desc); + if (IS_ERR(hisi_hikey_usb->role_sw)) + goto free_gpio2; + + platform_set_drvdata(pdev, hisi_hikey_usb); + + return 0; + +free_gpio2: + if (gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) { + gpio_free(hisi_hikey_usb->typec_vbus_gpio); + hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE; + } + +free_gpio1: + if (gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) { + gpio_free(hisi_hikey_usb->hub_vbus_gpio); + hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE; + } + + return ret; +} + +static int hisi_hikey_usb_remove(struct platform_device *pdev) +{ + struct hisi_hikey_usb *hisi_hikey_usb = platform_get_drvdata(pdev); + + if (gpio_is_valid(hisi_hikey_usb->otg_switch_gpio)) { + gpio_free(hisi_hikey_usb->otg_switch_gpio); + hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE; + } + + if (gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) { + gpio_free(hisi_hikey_usb->typec_vbus_gpio); + hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE; + } + + if (gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) { + gpio_free(hisi_hikey_usb->hub_vbus_gpio); + hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE; + } + + usb_role_switch_unregister(hisi_hikey_usb->role_sw); + + return 0; +} + +static const struct of_device_id id_table_hisi_hikey_usb[] = { + {.compatible = "hisilicon,gpio_hubv1"}, + {.compatible = "hisilicon,hikey960_usb"}, + {} +}; + +static struct platform_driver hisi_hikey_usb_driver = { + .probe = hisi_hikey_usb_probe, + .remove = hisi_hikey_usb_remove, + .driver = { + .name = DEVICE_DRIVER_NAME, + .of_match_table = of_match_ptr(id_table_hisi_hikey_usb), + + }, +}; + +module_platform_driver(hisi_hikey_usb_driver); + +MODULE_AUTHOR("Yu Chen "); +MODULE_DESCRIPTION("Driver Support for USB functionality of Hikey"); +MODULE_LICENSE("GPL v2"); -- 2.15.0-rc2 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Yu Chen Subject: [PATCH 07/10] hikey960: Support usb functionality of Hikey960 Date: Sat, 27 Oct 2018 17:58:17 +0800 Message-ID: <20181027095820.40056-8-chenyu56@huawei.com> References: <20181027095820.40056-1-chenyu56@huawei.com> Mime-Version: 1.0 Content-Type: text/plain Return-path: In-Reply-To: <20181027095820.40056-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 , Arnd Bergmann , Greg Kroah-Hartman , John Stultz , Binghui Wang List-Id: devicetree@vger.kernel.org This driver handles usb hub power on and typeC port event of HiKey960 board: 1)DP&DM switching between usb hub and typeC port base on typeC port state 2)Control power of usb hub on Hikey960 3)Control vbus of typeC port 4)Handle typeC port event to switch data role Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: John Stultz Cc: Binghui Wang Signed-off-by: Yu Chen --- drivers/misc/Kconfig | 7 + drivers/misc/Makefile | 1 + drivers/misc/hisi_hikey_usb.c | 319 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 327 insertions(+) create mode 100644 drivers/misc/hisi_hikey_usb.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 3726eacdf65d..8e04fc87b685 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -513,6 +513,13 @@ config MISC_RTSX tristate default MISC_RTSX_PCI || MISC_RTSX_USB +config HISI_HIKEY_USB + tristate "USB functionality of HiSilicon Hikey Platform" + depends on GPIOLIB + default n + help + If you say yes here you get support for usb functionality of HiSilicon Hikey Platform. + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index af22bbc3d00c..387dd302815c 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -58,3 +58,4 @@ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o obj-$(CONFIG_OCXL) += ocxl/ obj-$(CONFIG_MISC_RTSX) += cardreader/ +obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o diff --git a/drivers/misc/hisi_hikey_usb.c b/drivers/misc/hisi_hikey_usb.c new file mode 100644 index 000000000000..4965719c99ae --- /dev/null +++ b/drivers/misc/hisi_hikey_usb.c @@ -0,0 +1,319 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * hisi_hikey_usb.c + * + * Copyright (c) Hisilicon Tech. Co., Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + +#define DEVICE_DRIVER_NAME "hisi_hikey_usb" + +#define HUB_VBUS_POWER_ON 1 +#define HUB_VBUS_POWER_OFF 0 +#define USB_SWITCH_TO_HUB 1 +#define USB_SWITCH_TO_TYPEC 0 + +#define INVALID_GPIO_VALUE (-1) + +struct hisi_hikey_usb { + int otg_switch_gpio; + int typec_vbus_gpio; + int typec_vbus_enable_val; + int hub_vbus_gpio; + + struct extcon_dev *edev; + struct usb_role_switch *role_sw; +}; + +static const unsigned int usb_extcon_cable[] = { + EXTCON_USB, + EXTCON_USB_HOST, + EXTCON_NONE, +}; + +static void hub_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, int value) +{ + int gpio = hisi_hikey_usb->hub_vbus_gpio; + + if (gpio_is_valid(gpio)) + gpio_set_value(gpio, value); +} + +static void usb_switch_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, + int switch_to) +{ + int gpio = hisi_hikey_usb->otg_switch_gpio; + const char *switch_to_str = (switch_to == USB_SWITCH_TO_HUB) ? + "hub" : "typec"; + + if (!gpio_is_valid(gpio)) { + pr_err("%s: otg_switch_gpio is err\n", __func__); + return; + } + + if (gpio_get_value(gpio) == switch_to) { + pr_info("%s: already switch to %s\n", __func__, switch_to_str); + return; + } + + gpio_direction_output(gpio, switch_to); + pr_info("%s: switch to %s\n", __func__, switch_to_str); +} + +static void usb_typec_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, + int value) +{ + int gpio = hisi_hikey_usb->typec_vbus_gpio; + + if (!gpio_is_valid(gpio)) { + pr_err("%s: typec power gpio is err\n", __func__); + return; + } + + if (gpio_get_value(gpio) == value) { + pr_info("%s: typec power no change\n", __func__); + return; + } + + gpio_direction_output(gpio, value); + pr_info("%s: set typec vbus gpio to %d\n", __func__, value); +} + +static int extcon_hisi_pd_set_role(struct device *dev, enum usb_role role) +{ + struct hisi_hikey_usb *hisi_hikey_usb = dev_get_drvdata(dev); + + dev_info(dev, "%s:set usb role to %d\n", __func__, role); + switch (role) { + case USB_ROLE_NONE: + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_HUB); + usb_typec_power_ctrl(hisi_hikey_usb, + !hisi_hikey_usb->typec_vbus_enable_val); + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_ON); + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, false); + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST, + true); + break; + case USB_ROLE_HOST: + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC); + usb_typec_power_ctrl(hisi_hikey_usb, + hisi_hikey_usb->typec_vbus_enable_val); + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, false); + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST, + true); + break; + case USB_ROLE_DEVICE: + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_OFF); + usb_typec_power_ctrl(hisi_hikey_usb, + hisi_hikey_usb->typec_vbus_enable_val); + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC); + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST, + false); + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, true); + break; + } + + return 0; +} + +static enum usb_role extcon_hisi_pd_get_role(struct device *dev) +{ + struct hisi_hikey_usb *hisi_hikey_usb = dev_get_drvdata(dev); + + return usb_role_switch_get_role(hisi_hikey_usb->role_sw); +} + +static const struct usb_role_switch_desc sw_desc = { + .set = extcon_hisi_pd_set_role, + .get = extcon_hisi_pd_get_role, + .allow_userspace_control = true, +}; + +static int hisi_hikey_usb_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *root = dev->of_node; + struct hisi_hikey_usb *hisi_hikey_usb; + int ret; + + hisi_hikey_usb = devm_kzalloc(dev, sizeof(*hisi_hikey_usb), GFP_KERNEL); + if (!hisi_hikey_usb) + return -ENOMEM; + + dev_set_name(dev, "hisi_hikey_usb"); + + hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE; + hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE; + hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE; + + hisi_hikey_usb->hub_vbus_gpio = of_get_named_gpio(root, + "hub_vdd33_en_gpio", 0); + if (!gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) { + pr_err("%s: hub_vbus_gpio is err\n", __func__); + return hisi_hikey_usb->hub_vbus_gpio; + } + + ret = gpio_request(hisi_hikey_usb->hub_vbus_gpio, "hub_vbus_int_gpio"); + if (ret) { + pr_err("%s: request hub_vbus_gpio err\n", __func__); + hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE; + return ret; + } + + ret = gpio_direction_output(hisi_hikey_usb->hub_vbus_gpio, + HUB_VBUS_POWER_ON); + if (ret) { + pr_err("%s: power on hub vbus err\n", __func__); + goto free_gpio1; + } + + hisi_hikey_usb->typec_vbus_gpio = of_get_named_gpio(root, + "typc_vbus_int_gpio,typec-gpios", 0); + if (!gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) { + pr_err("%s: typec_vbus_gpio is err\n", __func__); + ret = hisi_hikey_usb->typec_vbus_gpio; + goto free_gpio1; + } + + ret = gpio_request(hisi_hikey_usb->typec_vbus_gpio, + "typc_vbus_int_gpio"); + if (ret) { + pr_err("%s: request typec_vbus_gpio err\n", __func__); + hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE; + goto free_gpio1; + } + + ret = of_property_read_u32(root, "typc_vbus_enable_val", + &hisi_hikey_usb->typec_vbus_enable_val); + if (ret) { + pr_err("%s: typc_vbus_enable_val can't get\n", __func__); + goto free_gpio2; + } + + hisi_hikey_usb->typec_vbus_enable_val = + !!hisi_hikey_usb->typec_vbus_enable_val; + + ret = gpio_direction_output(hisi_hikey_usb->typec_vbus_gpio, + hisi_hikey_usb->typec_vbus_enable_val); + if (ret) { + pr_err("%s: power on typec vbus err", __func__); + goto free_gpio2; + } + + if (of_device_is_compatible(root, "hisilicon,hikey960_usb")) { + hisi_hikey_usb->otg_switch_gpio = of_get_named_gpio(root, + "otg_gpio", 0); + if (!gpio_is_valid(hisi_hikey_usb->otg_switch_gpio)) { + pr_info("%s: otg_switch_gpio is err\n", __func__); + goto free_gpio2; + } + + ret = gpio_request(hisi_hikey_usb->otg_switch_gpio, + "otg_switch_gpio"); + if (ret) { + hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE; + pr_err("%s: request typec_vbus_gpio err\n", __func__); + goto free_gpio2; + } + } + + hisi_hikey_usb->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable); + if (IS_ERR(hisi_hikey_usb->edev)) { + dev_err(dev, "failed to allocate extcon device\n"); + goto free_gpio2; + } + + ret = devm_extcon_dev_register(dev, hisi_hikey_usb->edev); + if (ret < 0) { + dev_err(dev, "failed to register extcon device\n"); + goto free_gpio2; + } + extcon_set_state(hisi_hikey_usb->edev, EXTCON_USB_HOST, true); + + hisi_hikey_usb->role_sw = usb_role_switch_register(dev, &sw_desc); + if (IS_ERR(hisi_hikey_usb->role_sw)) + goto free_gpio2; + + platform_set_drvdata(pdev, hisi_hikey_usb); + + return 0; + +free_gpio2: + if (gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) { + gpio_free(hisi_hikey_usb->typec_vbus_gpio); + hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE; + } + +free_gpio1: + if (gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) { + gpio_free(hisi_hikey_usb->hub_vbus_gpio); + hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE; + } + + return ret; +} + +static int hisi_hikey_usb_remove(struct platform_device *pdev) +{ + struct hisi_hikey_usb *hisi_hikey_usb = platform_get_drvdata(pdev); + + if (gpio_is_valid(hisi_hikey_usb->otg_switch_gpio)) { + gpio_free(hisi_hikey_usb->otg_switch_gpio); + hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE; + } + + if (gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) { + gpio_free(hisi_hikey_usb->typec_vbus_gpio); + hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE; + } + + if (gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) { + gpio_free(hisi_hikey_usb->hub_vbus_gpio); + hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE; + } + + usb_role_switch_unregister(hisi_hikey_usb->role_sw); + + return 0; +} + +static const struct of_device_id id_table_hisi_hikey_usb[] = { + {.compatible = "hisilicon,gpio_hubv1"}, + {.compatible = "hisilicon,hikey960_usb"}, + {} +}; + +static struct platform_driver hisi_hikey_usb_driver = { + .probe = hisi_hikey_usb_probe, + .remove = hisi_hikey_usb_remove, + .driver = { + .name = DEVICE_DRIVER_NAME, + .of_match_table = of_match_ptr(id_table_hisi_hikey_usb), + + }, +}; + +module_platform_driver(hisi_hikey_usb_driver); + +MODULE_AUTHOR("Yu Chen "); +MODULE_DESCRIPTION("Driver Support for USB functionality of Hikey"); +MODULE_LICENSE("GPL v2"); -- 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: [07/10] hikey960: Support usb functionality of Hikey960 From: Yu Chen Message-Id: <20181027095820.40056-8-chenyu56@huawei.com> Date: Sat, 27 Oct 2018 17:58:17 +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 , Arnd Bergmann , Greg Kroah-Hartman , John Stultz , Binghui Wang List-ID: VGhpcyBkcml2ZXIgaGFuZGxlcyB1c2IgaHViIHBvd2VyIG9uIGFuZCB0eXBlQyBwb3J0IGV2ZW50 IG9mIEhpS2V5OTYwIGJvYXJkOgoxKURQJkRNIHN3aXRjaGluZyBiZXR3ZWVuIHVzYiBodWIgYW5k IHR5cGVDIHBvcnQgYmFzZSBvbiB0eXBlQyBwb3J0CnN0YXRlCjIpQ29udHJvbCBwb3dlciBvZiB1 c2IgaHViIG9uIEhpa2V5OTYwCjMpQ29udHJvbCB2YnVzIG9mIHR5cGVDIHBvcnQKNClIYW5kbGUg dHlwZUMgcG9ydCBldmVudCB0byBzd2l0Y2ggZGF0YSByb2xlCgpDYzogQXJuZCBCZXJnbWFubiA8 YXJuZEBhcm5kYi5kZT4KQ2M6IEdyZWcgS3JvYWgtSGFydG1hbiA8Z3JlZ2toQGxpbnV4Zm91bmRh dGlvbi5vcmc+CkNjOiBKb2huIFN0dWx0eiA8am9obi5zdHVsdHpAbGluYXJvLm9yZz4KQ2M6IEJp bmdodWkgV2FuZyA8d2FuZ2JpbmdodWlAaGlzaWxpY29uLmNvbT4KU2lnbmVkLW9mZi1ieTogWXUg Q2hlbiA8Y2hlbnl1NTZAaHVhd2VpLmNvbT4KLS0tCiBkcml2ZXJzL21pc2MvS2NvbmZpZyAgICAg ICAgICB8ICAgNyArCiBkcml2ZXJzL21pc2MvTWFrZWZpbGUgICAgICAgICB8ICAgMSArCiBkcml2 ZXJzL21pc2MvaGlzaV9oaWtleV91c2IuYyB8IDMxOSArKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysrKysKIDMgZmlsZXMgY2hhbmdlZCwgMzI3IGluc2VydGlvbnMoKykKIGNy ZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21pc2MvaGlzaV9oaWtleV91c2IuYwoKZGlmZiAtLWdp dCBhL2RyaXZlcnMvbWlzYy9LY29uZmlnIGIvZHJpdmVycy9taXNjL0tjb25maWcKaW5kZXggMzcy NmVhY2RmNjVkLi44ZTA0ZmM4N2I2ODUgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvbWlzYy9LY29uZmln CisrKyBiL2RyaXZlcnMvbWlzYy9LY29uZmlnCkBAIC01MTMsNiArNTEzLDEzIEBAIGNvbmZpZyBN SVNDX1JUU1gKIAl0cmlzdGF0ZQogCWRlZmF1bHQgTUlTQ19SVFNYX1BDSSB8fCBNSVNDX1JUU1hf VVNCCiAKK2NvbmZpZyBISVNJX0hJS0VZX1VTQgorCXRyaXN0YXRlICJVU0IgZnVuY3Rpb25hbGl0 eSBvZiBIaVNpbGljb24gSGlrZXkgUGxhdGZvcm0iCisJZGVwZW5kcyBvbiBHUElPTElCCisJZGVm YXVsdCBuCisJaGVscAorCSAgSWYgeW91IHNheSB5ZXMgaGVyZSB5b3UgZ2V0IHN1cHBvcnQgZm9y IHVzYiBmdW5jdGlvbmFsaXR5IG9mIEhpU2lsaWNvbiBIaWtleSBQbGF0Zm9ybS4KKwogc291cmNl ICJkcml2ZXJzL21pc2MvYzJwb3J0L0tjb25maWciCiBzb3VyY2UgImRyaXZlcnMvbWlzYy9lZXBy b20vS2NvbmZpZyIKIHNvdXJjZSAiZHJpdmVycy9taXNjL2NiNzEwL0tjb25maWciCmRpZmYgLS1n aXQgYS9kcml2ZXJzL21pc2MvTWFrZWZpbGUgYi9kcml2ZXJzL21pc2MvTWFrZWZpbGUKaW5kZXgg YWYyMmJiYzNkMDBjLi4zODdkZDMwMjgxNWMgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvbWlzYy9NYWtl ZmlsZQorKysgYi9kcml2ZXJzL21pc2MvTWFrZWZpbGUKQEAgLTU4LDMgKzU4LDQgQEAgb2JqLSQo Q09ORklHX0FTUEVFRF9MUENfU05PT1ApCSs9IGFzcGVlZC1scGMtc25vb3Aubwogb2JqLSQoQ09O RklHX1BDSV9FTkRQT0lOVF9URVNUKQkrPSBwY2lfZW5kcG9pbnRfdGVzdC5vCiBvYmotJChDT05G SUdfT0NYTCkJCSs9IG9jeGwvCiBvYmotJChDT05GSUdfTUlTQ19SVFNYKQkJKz0gY2FyZHJlYWRl ci8KK29iai0kKENPTkZJR19ISVNJX0hJS0VZX1VTQikJKz0gaGlzaV9oaWtleV91c2IubwpkaWZm IC0tZ2l0IGEvZHJpdmVycy9taXNjL2hpc2lfaGlrZXlfdXNiLmMgYi9kcml2ZXJzL21pc2MvaGlz aV9oaWtleV91c2IuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMDAuLjQ5 NjU3MTljOTlhZQotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZlcnMvbWlzYy9oaXNpX2hpa2V5X3Vz Yi5jCkBAIC0wLDAgKzEsMzE5IEBACisvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIu MCsKKy8qCisgKiBoaXNpX2hpa2V5X3VzYi5jCisgKgorICogQ29weXJpZ2h0IChjKSBIaXNpbGlj b24gVGVjaC4gQ28uLCBMdGQuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCisgKgorICogVGhpcyBwcm9n cmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2Rp ZnkKKyAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vu c2UgYXMgcHVibGlzaGVkIGJ5CisgKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRo ZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvcgorICogKGF0IHlvdXIgb3B0aW9uKSBhbnkg bGF0ZXIgdmVyc2lvbi4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhl IGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKKyAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5U WTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCisgKiBNRVJDSEFOVEFCSUxJ VFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCisgKiBHTlUg R2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgorICoKKyAqLworCisjaW5j bHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVkZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVk ZSA8bGludXgvc2xhYi5oPgorI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPgorI2lu Y2x1ZGUgPGxpbnV4L2dwaW8uaD4KKyNpbmNsdWRlIDxsaW51eC9vZl9ncGlvLmg+CisjaW5jbHVk ZSA8bGludXgvZXh0Y29uLXByb3ZpZGVyLmg+CisjaW5jbHVkZSA8bGludXgvdXNiL3JvbGUuaD4K KworI2RlZmluZSBERVZJQ0VfRFJJVkVSX05BTUUgImhpc2lfaGlrZXlfdXNiIgorCisjZGVmaW5l IEhVQl9WQlVTX1BPV0VSX09OIDEKKyNkZWZpbmUgSFVCX1ZCVVNfUE9XRVJfT0ZGIDAKKyNkZWZp bmUgVVNCX1NXSVRDSF9UT19IVUIgMQorI2RlZmluZSBVU0JfU1dJVENIX1RPX1RZUEVDIDAKKwor I2RlZmluZSBJTlZBTElEX0dQSU9fVkFMVUUgKC0xKQorCitzdHJ1Y3QgaGlzaV9oaWtleV91c2Ig eworCWludCBvdGdfc3dpdGNoX2dwaW87CisJaW50IHR5cGVjX3ZidXNfZ3BpbzsKKwlpbnQgdHlw ZWNfdmJ1c19lbmFibGVfdmFsOworCWludCBodWJfdmJ1c19ncGlvOworCisJc3RydWN0IGV4dGNv bl9kZXYgKmVkZXY7CisJc3RydWN0IHVzYl9yb2xlX3N3aXRjaCAqcm9sZV9zdzsKK307CisKK3N0 YXRpYyBjb25zdCB1bnNpZ25lZCBpbnQgdXNiX2V4dGNvbl9jYWJsZVtdID0geworCUVYVENPTl9V U0IsCisJRVhUQ09OX1VTQl9IT1NULAorCUVYVENPTl9OT05FLAorfTsKKworc3RhdGljIHZvaWQg aHViX3Bvd2VyX2N0cmwoc3RydWN0IGhpc2lfaGlrZXlfdXNiICpoaXNpX2hpa2V5X3VzYiwgaW50 IHZhbHVlKQoreworCWludCBncGlvID0gaGlzaV9oaWtleV91c2ItPmh1Yl92YnVzX2dwaW87CisK KwlpZiAoZ3Bpb19pc192YWxpZChncGlvKSkKKwkJZ3Bpb19zZXRfdmFsdWUoZ3BpbywgdmFsdWUp OworfQorCitzdGF0aWMgdm9pZCB1c2Jfc3dpdGNoX2N0cmwoc3RydWN0IGhpc2lfaGlrZXlfdXNi ICpoaXNpX2hpa2V5X3VzYiwKKwkJaW50IHN3aXRjaF90bykKK3sKKwlpbnQgZ3BpbyA9IGhpc2lf aGlrZXlfdXNiLT5vdGdfc3dpdGNoX2dwaW87CisJY29uc3QgY2hhciAqc3dpdGNoX3RvX3N0ciA9 IChzd2l0Y2hfdG8gPT0gVVNCX1NXSVRDSF9UT19IVUIpID8KKwkJImh1YiIgOiAidHlwZWMiOwor CisJaWYgKCFncGlvX2lzX3ZhbGlkKGdwaW8pKSB7CisJCXByX2VycigiJXM6IG90Z19zd2l0Y2hf Z3BpbyBpcyBlcnJcbiIsIF9fZnVuY19fKTsKKwkJcmV0dXJuOworCX0KKworCWlmIChncGlvX2dl dF92YWx1ZShncGlvKSA9PSBzd2l0Y2hfdG8pIHsKKwkJcHJfaW5mbygiJXM6IGFscmVhZHkgc3dp dGNoIHRvICVzXG4iLCBfX2Z1bmNfXywgc3dpdGNoX3RvX3N0cik7CisJCXJldHVybjsKKwl9CisK KwlncGlvX2RpcmVjdGlvbl9vdXRwdXQoZ3Bpbywgc3dpdGNoX3RvKTsKKwlwcl9pbmZvKCIlczog c3dpdGNoIHRvICVzXG4iLCBfX2Z1bmNfXywgc3dpdGNoX3RvX3N0cik7Cit9CisKK3N0YXRpYyB2 b2lkIHVzYl90eXBlY19wb3dlcl9jdHJsKHN0cnVjdCBoaXNpX2hpa2V5X3VzYiAqaGlzaV9oaWtl eV91c2IsCisJCWludCB2YWx1ZSkKK3sKKwlpbnQgZ3BpbyA9IGhpc2lfaGlrZXlfdXNiLT50eXBl Y192YnVzX2dwaW87CisKKwlpZiAoIWdwaW9faXNfdmFsaWQoZ3BpbykpIHsKKwkJcHJfZXJyKCIl czogdHlwZWMgcG93ZXIgZ3BpbyBpcyBlcnJcbiIsIF9fZnVuY19fKTsKKwkJcmV0dXJuOworCX0K KworCWlmIChncGlvX2dldF92YWx1ZShncGlvKSA9PSB2YWx1ZSkgeworCQlwcl9pbmZvKCIlczog dHlwZWMgcG93ZXIgbm8gY2hhbmdlXG4iLCBfX2Z1bmNfXyk7CisJCXJldHVybjsKKwl9CisKKwln cGlvX2RpcmVjdGlvbl9vdXRwdXQoZ3BpbywgdmFsdWUpOworCXByX2luZm8oIiVzOiBzZXQgdHlw ZWMgdmJ1cyBncGlvIHRvICVkXG4iLCBfX2Z1bmNfXywgdmFsdWUpOworfQorCitzdGF0aWMgaW50 IGV4dGNvbl9oaXNpX3BkX3NldF9yb2xlKHN0cnVjdCBkZXZpY2UgKmRldiwgZW51bSB1c2Jfcm9s ZSByb2xlKQoreworCXN0cnVjdCBoaXNpX2hpa2V5X3VzYiAqaGlzaV9oaWtleV91c2IgPSBkZXZf Z2V0X2RydmRhdGEoZGV2KTsKKworCWRldl9pbmZvKGRldiwgIiVzOnNldCB1c2Igcm9sZSB0byAl ZFxuIiwgX19mdW5jX18sIHJvbGUpOworCXN3aXRjaCAocm9sZSkgeworCWNhc2UgVVNCX1JPTEVf Tk9ORToKKwkJdXNiX3N3aXRjaF9jdHJsKGhpc2lfaGlrZXlfdXNiLCBVU0JfU1dJVENIX1RPX0hV Qik7CisJCXVzYl90eXBlY19wb3dlcl9jdHJsKGhpc2lfaGlrZXlfdXNiLAorCQkJCSFoaXNpX2hp a2V5X3VzYi0+dHlwZWNfdmJ1c19lbmFibGVfdmFsKTsKKwkJaHViX3Bvd2VyX2N0cmwoaGlzaV9o aWtleV91c2IsIEhVQl9WQlVTX1BPV0VSX09OKTsKKwkJZXh0Y29uX3NldF9zdGF0ZV9zeW5jKGhp c2lfaGlrZXlfdXNiLT5lZGV2LCBFWFRDT05fVVNCLCBmYWxzZSk7CisJCWV4dGNvbl9zZXRfc3Rh dGVfc3luYyhoaXNpX2hpa2V5X3VzYi0+ZWRldiwgRVhUQ09OX1VTQl9IT1NULAorCQkJCXRydWUp OworCQlicmVhazsKKwljYXNlIFVTQl9ST0xFX0hPU1Q6CisJCXVzYl9zd2l0Y2hfY3RybChoaXNp X2hpa2V5X3VzYiwgVVNCX1NXSVRDSF9UT19UWVBFQyk7CisJCXVzYl90eXBlY19wb3dlcl9jdHJs KGhpc2lfaGlrZXlfdXNiLAorCQkJCWhpc2lfaGlrZXlfdXNiLT50eXBlY192YnVzX2VuYWJsZV92 YWwpOworCQlleHRjb25fc2V0X3N0YXRlX3N5bmMoaGlzaV9oaWtleV91c2ItPmVkZXYsIEVYVENP Tl9VU0IsIGZhbHNlKTsKKwkJZXh0Y29uX3NldF9zdGF0ZV9zeW5jKGhpc2lfaGlrZXlfdXNiLT5l ZGV2LCBFWFRDT05fVVNCX0hPU1QsCisJCQkJdHJ1ZSk7CisJCWJyZWFrOworCWNhc2UgVVNCX1JP TEVfREVWSUNFOgorCQlodWJfcG93ZXJfY3RybChoaXNpX2hpa2V5X3VzYiwgSFVCX1ZCVVNfUE9X RVJfT0ZGKTsKKwkJdXNiX3R5cGVjX3Bvd2VyX2N0cmwoaGlzaV9oaWtleV91c2IsCisJCQkJaGlz aV9oaWtleV91c2ItPnR5cGVjX3ZidXNfZW5hYmxlX3ZhbCk7CisJCXVzYl9zd2l0Y2hfY3RybCho aXNpX2hpa2V5X3VzYiwgVVNCX1NXSVRDSF9UT19UWVBFQyk7CisJCWV4dGNvbl9zZXRfc3RhdGVf c3luYyhoaXNpX2hpa2V5X3VzYi0+ZWRldiwgRVhUQ09OX1VTQl9IT1NULAorCQkJCWZhbHNlKTsK KwkJZXh0Y29uX3NldF9zdGF0ZV9zeW5jKGhpc2lfaGlrZXlfdXNiLT5lZGV2LCBFWFRDT05fVVNC LCB0cnVlKTsKKwkJYnJlYWs7CisJfQorCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBlbnVtIHVz Yl9yb2xlIGV4dGNvbl9oaXNpX3BkX2dldF9yb2xlKHN0cnVjdCBkZXZpY2UgKmRldikKK3sKKwlz dHJ1Y3QgaGlzaV9oaWtleV91c2IgKmhpc2lfaGlrZXlfdXNiID0gZGV2X2dldF9kcnZkYXRhKGRl dik7CisKKwlyZXR1cm4gdXNiX3JvbGVfc3dpdGNoX2dldF9yb2xlKGhpc2lfaGlrZXlfdXNiLT5y b2xlX3N3KTsKK30KKworc3RhdGljIGNvbnN0IHN0cnVjdCB1c2Jfcm9sZV9zd2l0Y2hfZGVzYyBz d19kZXNjID0geworCS5zZXQgPSBleHRjb25faGlzaV9wZF9zZXRfcm9sZSwKKwkuZ2V0ID0gZXh0 Y29uX2hpc2lfcGRfZ2V0X3JvbGUsCisJLmFsbG93X3VzZXJzcGFjZV9jb250cm9sID0gdHJ1ZSwK K307CisKK3N0YXRpYyBpbnQgaGlzaV9oaWtleV91c2JfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2Rl dmljZSAqcGRldikKK3sKKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSAmcGRldi0+ZGV2OworCXN0cnVj dCBkZXZpY2Vfbm9kZSAqcm9vdCA9IGRldi0+b2Zfbm9kZTsKKwlzdHJ1Y3QgaGlzaV9oaWtleV91 c2IgKmhpc2lfaGlrZXlfdXNiOworCWludCByZXQ7CisKKwloaXNpX2hpa2V5X3VzYiA9IGRldm1f a3phbGxvYyhkZXYsIHNpemVvZigqaGlzaV9oaWtleV91c2IpLCBHRlBfS0VSTkVMKTsKKwlpZiAo IWhpc2lfaGlrZXlfdXNiKQorCQlyZXR1cm4gLUVOT01FTTsKKworCWRldl9zZXRfbmFtZShkZXYs ICJoaXNpX2hpa2V5X3VzYiIpOworCisJaGlzaV9oaWtleV91c2ItPmh1Yl92YnVzX2dwaW8gPSBJ TlZBTElEX0dQSU9fVkFMVUU7CisJaGlzaV9oaWtleV91c2ItPm90Z19zd2l0Y2hfZ3BpbyA9IElO VkFMSURfR1BJT19WQUxVRTsKKwloaXNpX2hpa2V5X3VzYi0+dHlwZWNfdmJ1c19ncGlvID0gSU5W QUxJRF9HUElPX1ZBTFVFOworCisJaGlzaV9oaWtleV91c2ItPmh1Yl92YnVzX2dwaW8gPSBvZl9n ZXRfbmFtZWRfZ3Bpbyhyb290LAorCQkJImh1Yl92ZGQzM19lbl9ncGlvIiwgMCk7CisJaWYgKCFn cGlvX2lzX3ZhbGlkKGhpc2lfaGlrZXlfdXNiLT5odWJfdmJ1c19ncGlvKSkgeworCQlwcl9lcnIo IiVzOiBodWJfdmJ1c19ncGlvIGlzIGVyclxuIiwgX19mdW5jX18pOworCQlyZXR1cm4gaGlzaV9o aWtleV91c2ItPmh1Yl92YnVzX2dwaW87CisJfQorCisJcmV0ID0gZ3Bpb19yZXF1ZXN0KGhpc2lf aGlrZXlfdXNiLT5odWJfdmJ1c19ncGlvLCAiaHViX3ZidXNfaW50X2dwaW8iKTsKKwlpZiAocmV0 KSB7CisJCXByX2VycigiJXM6IHJlcXVlc3QgaHViX3ZidXNfZ3BpbyBlcnJcbiIsIF9fZnVuY19f KTsKKwkJaGlzaV9oaWtleV91c2ItPmh1Yl92YnVzX2dwaW8gPSBJTlZBTElEX0dQSU9fVkFMVUU7 CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0ID0gZ3Bpb19kaXJlY3Rpb25fb3V0cHV0KGhpc2lf aGlrZXlfdXNiLT5odWJfdmJ1c19ncGlvLAorCQkJSFVCX1ZCVVNfUE9XRVJfT04pOworCWlmIChy ZXQpIHsKKwkJcHJfZXJyKCIlczogcG93ZXIgb24gaHViIHZidXMgZXJyXG4iLCBfX2Z1bmNfXyk7 CisJCWdvdG8gZnJlZV9ncGlvMTsKKwl9CisKKwloaXNpX2hpa2V5X3VzYi0+dHlwZWNfdmJ1c19n cGlvID0gb2ZfZ2V0X25hbWVkX2dwaW8ocm9vdCwKKwkJInR5cGNfdmJ1c19pbnRfZ3Bpbyx0eXBl Yy1ncGlvcyIsIDApOworCWlmICghZ3Bpb19pc192YWxpZChoaXNpX2hpa2V5X3VzYi0+dHlwZWNf dmJ1c19ncGlvKSkgeworCQlwcl9lcnIoIiVzOiB0eXBlY192YnVzX2dwaW8gaXMgZXJyXG4iLCBf X2Z1bmNfXyk7CisJCXJldCA9IGhpc2lfaGlrZXlfdXNiLT50eXBlY192YnVzX2dwaW87CisJCWdv dG8gZnJlZV9ncGlvMTsKKwl9CisKKwlyZXQgPSBncGlvX3JlcXVlc3QoaGlzaV9oaWtleV91c2It PnR5cGVjX3ZidXNfZ3BpbywKKwkJCSJ0eXBjX3ZidXNfaW50X2dwaW8iKTsKKwlpZiAocmV0KSB7 CisJCXByX2VycigiJXM6IHJlcXVlc3QgdHlwZWNfdmJ1c19ncGlvIGVyclxuIiwgX19mdW5jX18p OworCQloaXNpX2hpa2V5X3VzYi0+dHlwZWNfdmJ1c19ncGlvID0gSU5WQUxJRF9HUElPX1ZBTFVF OworCQlnb3RvIGZyZWVfZ3BpbzE7CisJfQorCisJcmV0ID0gb2ZfcHJvcGVydHlfcmVhZF91MzIo cm9vdCwgInR5cGNfdmJ1c19lbmFibGVfdmFsIiwKKwkJCQkgICAmaGlzaV9oaWtleV91c2ItPnR5 cGVjX3ZidXNfZW5hYmxlX3ZhbCk7CisJaWYgKHJldCkgeworCQlwcl9lcnIoIiVzOiB0eXBjX3Zi dXNfZW5hYmxlX3ZhbCBjYW4ndCBnZXRcbiIsIF9fZnVuY19fKTsKKwkJZ290byBmcmVlX2dwaW8y OworCX0KKworCWhpc2lfaGlrZXlfdXNiLT50eXBlY192YnVzX2VuYWJsZV92YWwgPQorCQkhIWhp c2lfaGlrZXlfdXNiLT50eXBlY192YnVzX2VuYWJsZV92YWw7CisKKwlyZXQgPSBncGlvX2RpcmVj dGlvbl9vdXRwdXQoaGlzaV9oaWtleV91c2ItPnR5cGVjX3ZidXNfZ3BpbywKKwkJCQkgICAgaGlz aV9oaWtleV91c2ItPnR5cGVjX3ZidXNfZW5hYmxlX3ZhbCk7CisJaWYgKHJldCkgeworCQlwcl9l cnIoIiVzOiBwb3dlciBvbiB0eXBlYyB2YnVzIGVyciIsIF9fZnVuY19fKTsKKwkJZ290byBmcmVl X2dwaW8yOworCX0KKworCWlmIChvZl9kZXZpY2VfaXNfY29tcGF0aWJsZShyb290LCAiaGlzaWxp Y29uLGhpa2V5OTYwX3VzYiIpKSB7CisJCWhpc2lfaGlrZXlfdXNiLT5vdGdfc3dpdGNoX2dwaW8g PSBvZl9nZXRfbmFtZWRfZ3Bpbyhyb290LAorCQkJCSJvdGdfZ3BpbyIsIDApOworCQlpZiAoIWdw aW9faXNfdmFsaWQoaGlzaV9oaWtleV91c2ItPm90Z19zd2l0Y2hfZ3BpbykpIHsKKwkJCXByX2lu Zm8oIiVzOiBvdGdfc3dpdGNoX2dwaW8gaXMgZXJyXG4iLCBfX2Z1bmNfXyk7CisJCQlnb3RvIGZy ZWVfZ3BpbzI7CisJCX0KKworCQlyZXQgPSBncGlvX3JlcXVlc3QoaGlzaV9oaWtleV91c2ItPm90 Z19zd2l0Y2hfZ3BpbywKKwkJCQkib3RnX3N3aXRjaF9ncGlvIik7CisJCWlmIChyZXQpIHsKKwkJ CWhpc2lfaGlrZXlfdXNiLT5vdGdfc3dpdGNoX2dwaW8gPSBJTlZBTElEX0dQSU9fVkFMVUU7CisJ CQlwcl9lcnIoIiVzOiByZXF1ZXN0IHR5cGVjX3ZidXNfZ3BpbyBlcnJcbiIsIF9fZnVuY19fKTsK KwkJCWdvdG8gZnJlZV9ncGlvMjsKKwkJfQorCX0KKworCWhpc2lfaGlrZXlfdXNiLT5lZGV2ID0g ZGV2bV9leHRjb25fZGV2X2FsbG9jYXRlKGRldiwgdXNiX2V4dGNvbl9jYWJsZSk7CisJaWYgKElT X0VSUihoaXNpX2hpa2V5X3VzYi0+ZWRldikpIHsKKwkJZGV2X2VycihkZXYsICJmYWlsZWQgdG8g YWxsb2NhdGUgZXh0Y29uIGRldmljZVxuIik7CisJCWdvdG8gZnJlZV9ncGlvMjsKKwl9CisKKwly ZXQgPSBkZXZtX2V4dGNvbl9kZXZfcmVnaXN0ZXIoZGV2LCBoaXNpX2hpa2V5X3VzYi0+ZWRldik7 CisJaWYgKHJldCA8IDApIHsKKwkJZGV2X2VycihkZXYsICJmYWlsZWQgdG8gcmVnaXN0ZXIgZXh0 Y29uIGRldmljZVxuIik7CisJCWdvdG8gZnJlZV9ncGlvMjsKKwl9CisJZXh0Y29uX3NldF9zdGF0 ZShoaXNpX2hpa2V5X3VzYi0+ZWRldiwgRVhUQ09OX1VTQl9IT1NULCB0cnVlKTsKKworCWhpc2lf aGlrZXlfdXNiLT5yb2xlX3N3ID0gdXNiX3JvbGVfc3dpdGNoX3JlZ2lzdGVyKGRldiwgJnN3X2Rl c2MpOworCWlmIChJU19FUlIoaGlzaV9oaWtleV91c2ItPnJvbGVfc3cpKQorCQlnb3RvIGZyZWVf Z3BpbzI7CisKKwlwbGF0Zm9ybV9zZXRfZHJ2ZGF0YShwZGV2LCBoaXNpX2hpa2V5X3VzYik7CisK KwlyZXR1cm4gMDsKKworZnJlZV9ncGlvMjoKKwlpZiAoZ3Bpb19pc192YWxpZChoaXNpX2hpa2V5 X3VzYi0+dHlwZWNfdmJ1c19ncGlvKSkgeworCQlncGlvX2ZyZWUoaGlzaV9oaWtleV91c2ItPnR5 cGVjX3ZidXNfZ3Bpbyk7CisJCWhpc2lfaGlrZXlfdXNiLT50eXBlY192YnVzX2dwaW8gPSBJTlZB TElEX0dQSU9fVkFMVUU7CisJfQorCitmcmVlX2dwaW8xOgorCWlmIChncGlvX2lzX3ZhbGlkKGhp c2lfaGlrZXlfdXNiLT5odWJfdmJ1c19ncGlvKSkgeworCQlncGlvX2ZyZWUoaGlzaV9oaWtleV91 c2ItPmh1Yl92YnVzX2dwaW8pOworCQloaXNpX2hpa2V5X3VzYi0+aHViX3ZidXNfZ3BpbyA9IElO VkFMSURfR1BJT19WQUxVRTsKKwl9CisKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgaW50ICBo aXNpX2hpa2V5X3VzYl9yZW1vdmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKK3sKKwlz dHJ1Y3QgaGlzaV9oaWtleV91c2IgKmhpc2lfaGlrZXlfdXNiID0gcGxhdGZvcm1fZ2V0X2RydmRh dGEocGRldik7CisKKwlpZiAoZ3Bpb19pc192YWxpZChoaXNpX2hpa2V5X3VzYi0+b3RnX3N3aXRj aF9ncGlvKSkgeworCQlncGlvX2ZyZWUoaGlzaV9oaWtleV91c2ItPm90Z19zd2l0Y2hfZ3Bpbyk7 CisJCWhpc2lfaGlrZXlfdXNiLT5vdGdfc3dpdGNoX2dwaW8gPSBJTlZBTElEX0dQSU9fVkFMVUU7 CisJfQorCisJaWYgKGdwaW9faXNfdmFsaWQoaGlzaV9oaWtleV91c2ItPnR5cGVjX3ZidXNfZ3Bp bykpIHsKKwkJZ3Bpb19mcmVlKGhpc2lfaGlrZXlfdXNiLT50eXBlY192YnVzX2dwaW8pOworCQlo aXNpX2hpa2V5X3VzYi0+dHlwZWNfdmJ1c19ncGlvID0gSU5WQUxJRF9HUElPX1ZBTFVFOworCX0K KworCWlmIChncGlvX2lzX3ZhbGlkKGhpc2lfaGlrZXlfdXNiLT5odWJfdmJ1c19ncGlvKSkgewor CQlncGlvX2ZyZWUoaGlzaV9oaWtleV91c2ItPmh1Yl92YnVzX2dwaW8pOworCQloaXNpX2hpa2V5 X3VzYi0+aHViX3ZidXNfZ3BpbyA9IElOVkFMSURfR1BJT19WQUxVRTsKKwl9CisKKwl1c2Jfcm9s ZV9zd2l0Y2hfdW5yZWdpc3RlcihoaXNpX2hpa2V5X3VzYi0+cm9sZV9zdyk7CisKKwlyZXR1cm4g MDsKK30KKworc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQgaWRfdGFibGVfaGlzaV9o aWtleV91c2JbXSA9IHsKKwl7LmNvbXBhdGlibGUgPSAiaGlzaWxpY29uLGdwaW9faHVidjEifSwK Kwl7LmNvbXBhdGlibGUgPSAiaGlzaWxpY29uLGhpa2V5OTYwX3VzYiJ9LAorCXt9Cit9OworCitz dGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciAgaGlzaV9oaWtleV91c2JfZHJpdmVyID0gewor CS5wcm9iZSA9IGhpc2lfaGlrZXlfdXNiX3Byb2JlLAorCS5yZW1vdmUgPSBoaXNpX2hpa2V5X3Vz Yl9yZW1vdmUsCisJLmRyaXZlciA9IHsKKwkJLm5hbWUgPSBERVZJQ0VfRFJJVkVSX05BTUUsCisJ CS5vZl9tYXRjaF90YWJsZSA9IG9mX21hdGNoX3B0cihpZF90YWJsZV9oaXNpX2hpa2V5X3VzYiks CisKKwl9LAorfTsKKworbW9kdWxlX3BsYXRmb3JtX2RyaXZlcihoaXNpX2hpa2V5X3VzYl9kcml2 ZXIpOworCitNT0RVTEVfQVVUSE9SKCJZdSBDaGVuIDxjaGVueXU1NkBodWF3ZWkuY29tPiIpOwor TU9EVUxFX0RFU0NSSVBUSU9OKCJEcml2ZXIgU3VwcG9ydCBmb3IgVVNCIGZ1bmN0aW9uYWxpdHkg b2YgSGlrZXkiKTsKK01PRFVMRV9MSUNFTlNFKCJHUEwgdjIiKTsK