Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp178661yba; Fri, 19 Apr 2019 23:42:25 -0700 (PDT) X-Google-Smtp-Source: APXvYqyF4QY8+2bGAW/dNRytpGmqUqtubq8vDXKX2/csBNvBDswDKZLOby02sWOR1OCkSt7aY0uA X-Received: by 2002:a17:902:294b:: with SMTP id g69mr8059191plb.57.1555742545233; Fri, 19 Apr 2019 23:42:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1555742545; cv=none; d=google.com; s=arc-20160816; b=hPjKFv5aZMKUwx9VsiIE9ulIgZ7VjfiIsay8me36CH4IOq4tueZZLjByahLLuOwULf MBkzr0Fk29P0CXBZ26F5TBIMIyhfT8FiBqt8JgzM5EbghquoNASVnAPGVGJekpbQ2cTn QldhKYbxnGro/kxUErUx3V8KZZLsXeMzthuwrFDXiStetSg01KYcDexmj9SzV220Gjro +uJj40qifRT3HyDiKqrQEbYNg1u/lSpqU8aafSQ7E7iVIAC1beUNvwv5ZIlNaINquJBz X0XjV4yM1SlojOyGHpphaatXYTx9o1hyfG0+iB4w5i52RXRZAN0Tf40dfWVfOas9Q5Te YuYg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from; bh=YYSPagbumx4NaZBi3hMENBWGV8GtJao9Q4e9rc4DcBM=; b=Fv/qZQ5z2c/Lg5PGNZq0vTwrnbcpqmgXXKmwUTdhMaORs/YJjA695cItNPMD6EO56Q yMEnIhdmLhGf9LdKZREkgI49DvDnXforhZPb5817saLSCwSDuVIRnUSwMU5bGIWakKSz FE60OgVr0CnbEaKIeG1Osy61gaJQYBhawDdeWsYk/eX1wMDLjcYrxfDDi4PtfERSegUZ hJHkYtIqJnD7E1PQ89DgGYMjoROKzcdrvXt3GB2TtqarjD+/Gf1PBkL+i1CQ81LGMybC GRG9OiisqdR9SAChO0DgdpIP5OnakhJAtsq7JcPh9ipxZJufmfZAWdZQ3ansiY4KSU8y G+Aw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id k69si6812353pgd.265.2019.04.19.23.42.07; Fri, 19 Apr 2019 23:42:25 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728115AbfDTGkr (ORCPT + 99 others); Sat, 20 Apr 2019 02:40:47 -0400 Received: from szxga04-in.huawei.com ([45.249.212.190]:6669 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727969AbfDTGkm (ORCPT ); Sat, 20 Apr 2019 02:40:42 -0400 Received: from DGGEMS410-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 5986A55EC1D272F3C9C2; Sat, 20 Apr 2019 14:40:39 +0800 (CST) Received: from vm100-107-113-134.huawei.com (100.107.113.134) by DGGEMS410-HUB.china.huawei.com (10.3.19.210) with Microsoft SMTP Server id 14.3.408.0; Sat, 20 Apr 2019 14:40:33 +0800 From: Yu Chen To: , , CC: , , , , , , , , , , , , , , Yu Chen , Chunfeng Yun , Andy Shevchenko , Arnd Bergmann , Greg Kroah-Hartman , Binghui Wang , Heikki Krogerus Subject: [PATCH v6 11/13] hikey960: Support usb functionality of Hikey960 Date: Sat, 20 Apr 2019 14:40:17 +0800 Message-ID: <20190420064019.57522-12-chenyu56@huawei.com> X-Mailer: git-send-email 2.15.0-rc2 In-Reply-To: <20190420064019.57522-1-chenyu56@huawei.com> References: <20190420064019.57522-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 Cc: Chunfeng Yun Cc: Andy Shevchenko Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: John Stultz Cc: Binghui Wang Cc: Heikki Krogerus Signed-off-by: Yu Chen --- v1: * Using gpiod API with the gpios. * Removing registering usb role switch. * Registering usb role switch notifier. v2: * Fix license declaration. * Add configuration of gpio direction. * Remove some log print. v3: * Remove property of "typec_vbus_enable_val". * Remove gpiod_direction_output and set initial value of gpio by * devm_gpiod_get. v4: * Remove 'linux/of.h' and add 'linux/mod_devicetable.h'. * Remove unused 'root' of_node. * Remove unuseful NULL check return by 'devm_gpiod_get'. * Use 'devm_gpiod_get_optional' to get optional gpio. --- --- drivers/misc/Kconfig | 6 ++ drivers/misc/Makefile | 1 + drivers/misc/hisi_hikey_usb.c | 162 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 drivers/misc/hisi_hikey_usb.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 42ab8ec92a04..3b3f610b80c2 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -532,6 +532,12 @@ config PVPANIC a paravirtualized device provided by QEMU; it lets a virtual machine (guest) communicate panic events to the host. +config HISI_HIKEY_USB + tristate "USB functionality of HiSilicon Hikey Platform" + depends on OF && GPIOLIB + 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 d5b7d3404dc7..1c6c108d3a0c 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -61,3 +61,4 @@ obj-$(CONFIG_OCXL) += ocxl/ obj-y += cardreader/ obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_HABANA_AI) += habanalabs/ +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..a3bb46266f04 --- /dev/null +++ b/drivers/misc/hisi_hikey_usb.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Support for usb functionality of Hikey series boards + * based on Hisilicon Kirin Soc. + * + * Copyright (C) 2017-2018 Hilisicon Electronics Co., Ltd. + * http://www.huawei.com + * + * Authors: Yu Chen + */ + +#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 TYPEC_VBUS_POWER_ON 1 +#define TYPEC_VBUS_POWER_OFF 0 + +struct hisi_hikey_usb { + struct gpio_desc *otg_switch; + struct gpio_desc *typec_vbus; + struct gpio_desc *hub_vbus; + + struct usb_role_switch *role_sw; + struct notifier_block nb; +}; + +static void hub_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, int value) +{ + gpiod_set_value_cansleep(hisi_hikey_usb->hub_vbus, value); +} + +static void usb_switch_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, + int switch_to) +{ + gpiod_set_value_cansleep(hisi_hikey_usb->otg_switch, switch_to); +} + +static void usb_typec_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, + int value) +{ + gpiod_set_value_cansleep(hisi_hikey_usb->typec_vbus, value); +} + +static int hisi_hikey_role_switch(struct notifier_block *nb, + unsigned long state, void *data) +{ + struct hisi_hikey_usb *hisi_hikey_usb; + + hisi_hikey_usb = container_of(nb, struct hisi_hikey_usb, nb); + + switch (state) { + case USB_ROLE_NONE: + usb_typec_power_ctrl(hisi_hikey_usb, TYPEC_VBUS_POWER_OFF); + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_HUB); + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_ON); + break; + case USB_ROLE_HOST: + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC); + usb_typec_power_ctrl(hisi_hikey_usb, TYPEC_VBUS_POWER_ON); + break; + case USB_ROLE_DEVICE: + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_OFF); + usb_typec_power_ctrl(hisi_hikey_usb, TYPEC_VBUS_POWER_OFF); + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC); + break; + default: + break; + } + + return 0; +} + +static int hisi_hikey_usb_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + 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; + + hisi_hikey_usb->nb.notifier_call = hisi_hikey_role_switch; + + hisi_hikey_usb->typec_vbus = devm_gpiod_get(dev, "typec-vbus", + GPIOD_OUT_LOW); + if (IS_ERR(hisi_hikey_usb->typec_vbus)) + return PTR_ERR(hisi_hikey_usb->typec_vbus); + + hisi_hikey_usb->otg_switch = devm_gpiod_get(dev, "otg-switch", + GPIOD_OUT_HIGH); + if (IS_ERR(hisi_hikey_usb->otg_switch)) + return PTR_ERR(hisi_hikey_usb->otg_switch); + + /* hub-vdd33-en is optional */ + hisi_hikey_usb->hub_vbus = devm_gpiod_get_optional(dev, "hub-vdd33-en", + GPIOD_OUT_HIGH); + if (IS_ERR(hisi_hikey_usb->hub_vbus)) + return PTR_ERR(hisi_hikey_usb->hub_vbus); + + hisi_hikey_usb->role_sw = usb_role_switch_get(dev); + if (!hisi_hikey_usb->role_sw) + return -EPROBE_DEFER; + if (IS_ERR(hisi_hikey_usb->role_sw)) + return PTR_ERR(hisi_hikey_usb->role_sw); + + ret = usb_role_switch_register_notifier(hisi_hikey_usb->role_sw, + &hisi_hikey_usb->nb); + if (ret) { + usb_role_switch_put(hisi_hikey_usb->role_sw); + return ret; + } + + platform_set_drvdata(pdev, hisi_hikey_usb); + + return 0; +} + +static int hisi_hikey_usb_remove(struct platform_device *pdev) +{ + struct hisi_hikey_usb *hisi_hikey_usb = platform_get_drvdata(pdev); + + usb_role_switch_unregister_notifier(hisi_hikey_usb->role_sw, + &hisi_hikey_usb->nb); + + usb_role_switch_put(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 = 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