Received: by 2002:ac0:946b:0:0:0:0:0 with SMTP id j40csp3062958imj; Mon, 18 Feb 2019 18:53:14 -0800 (PST) X-Google-Smtp-Source: AHgI3IY7J2OuaooKh2Hcx3F5XcrJhQE0U2lWUQXYBf0zEsBMrn5T60ey9pCnBc9+e+cBdfSuAW+M X-Received: by 2002:a63:160d:: with SMTP id w13mr21343841pgl.85.1550544794067; Mon, 18 Feb 2019 18:53:14 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1550544794; cv=none; d=google.com; s=arc-20160816; b=S9+Jy+TkSXPF2TXLu5g2Nat4xKbdF3IfZIt/Fslqv9kM2DtroGFeq2rrZgTBLTpsbK ifT65asBHTbpi5RPiMjj0hy4CTyvc0qP4GSGcUkGIhAfMPFi35EejDmozLX5IwqRV217 MtnL7Gp/KPNP95+dT0OiLc7IDkq6/GBrzcassIdvvpMUo1WBVD+EZUz5JJofkfFhHuQS rDskFGFSS9f8wc8FUEg2l6dd0O7kqPgiF3Vbc68MUbxbNPYZpeCDwFwtbFrhy3tjVzri PN95ctIdJBktKEeOiOHzOjr5iG8m0TZCYignRTNWrMDWXj8RZQ1U8Tt4c0E+6tv3gWFd 7XCA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:content-transfer-encoding :references:in-reply-to:date:cc:to:from:subject:message-id; bh=gDNx15oH5qwIXdW653A4lkyD8ALBM6KImFPTqyKwz/0=; b=x6VX9xdYps/K9N/2ife32jTKm6/ua+K4CmiR877z1uJyaooTQpUTNaY2YCIoMRln1H CdmSsnD3FWr+ipGSkNw5p/CXUU+hbm3g08XKtZeWa+R7LNE1rMyNf+XFquWMIzzWSqwY 9p8HTV9ONYYb2eA0IFEad8wu68hqSTkptWSr/4WKqsiXCfuyugxSdDEOO8R7ahqXV3FO Z0YhV/X1GLofycgnVvRBGDyjQBEaaCFp0vHCoJE+YUVwabbObsFfohH30TbpN67M8KHH hny0BMjlkoFvMb3ZGga/RlMhDSEFWIQ9y+raaNuLYSIciZBSex+A52VpT8oO/OenE9oR E/Rg== 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 x6si13940640pgp.367.2019.02.18.18.52.59; Mon, 18 Feb 2019 18:53:14 -0800 (PST) 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 S1727137AbfBSCuZ (ORCPT + 99 others); Mon, 18 Feb 2019 21:50:25 -0500 Received: from mailgw02.mediatek.com ([1.203.163.81]:23395 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1725801AbfBSCuY (ORCPT ); Mon, 18 Feb 2019 21:50:24 -0500 X-UUID: 2878306887ac4fe6b3135b99dc669019-20190219 X-UUID: 2878306887ac4fe6b3135b99dc669019-20190219 Received: from mtkcas35.mediatek.inc [(172.27.4.250)] by mailgw02.mediatek.com (envelope-from ) (mailgw01.mediatek.com ESMTP with TLS) with ESMTP id 922748648; Tue, 19 Feb 2019 10:50:17 +0800 Received: from MTKCAS36.mediatek.inc (172.27.4.186) by MTKMBS32N2.mediatek.inc (172.27.4.72) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Tue, 19 Feb 2019 10:50:16 +0800 Received: from [10.17.3.153] (10.17.3.153) by MTKCAS36.mediatek.inc (172.27.4.170) with Microsoft SMTP Server id 15.0.1395.4 via Frontend Transport; Tue, 19 Feb 2019 10:50:15 +0800 Message-ID: <1550544615.2210.27.camel@mhfsdcap03> Subject: Re: [PATCH v2 08/10] hikey960: Support usb functionality of Hikey960 From: Chunfeng Yun To: Yu Chen CC: , , , , , , , , , , , , , , , , , Andy Shevchenko , Arnd Bergmann , "Greg Kroah-Hartman" , Binghui Wang , Heikki Krogerus Date: Tue, 19 Feb 2019 10:50:15 +0800 In-Reply-To: <20190218112310.17860-9-chenyu56@huawei.com> References: <20190218112310.17860-1-chenyu56@huawei.com> <20190218112310.17860-9-chenyu56@huawei.com> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.2.3-0ubuntu6 Content-Transfer-Encoding: 7bit MIME-Version: 1.0 X-MTK: N Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, On Mon, 2019-02-18 at 19:23 +0800, Yu Chen wrote: > 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: 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. > --- > --- > drivers/misc/Kconfig | 6 ++ > drivers/misc/Makefile | 1 + > drivers/misc/hisi_hikey_usb.c | 181 ++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 188 insertions(+) > create mode 100644 drivers/misc/hisi_hikey_usb.c > > diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig > index f417b06e11c5..8d8b717759e2 100644 > --- a/drivers/misc/Kconfig > +++ b/drivers/misc/Kconfig > @@ -521,6 +521,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 e39ccbbc1b3a..dc8892b13a1a 100644 > --- a/drivers/misc/Makefile > +++ b/drivers/misc/Makefile > @@ -59,3 +59,4 @@ obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o > obj-$(CONFIG_OCXL) += ocxl/ > obj-y += cardreader/ > obj-$(CONFIG_PVPANIC) += pvpanic.o > +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..70013f8e76f0 > --- /dev/null > +++ b/drivers/misc/hisi_hikey_usb.c > @@ -0,0 +1,181 @@ > +// 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 > + > +struct hisi_hikey_usb { > + struct gpio_desc *otg_switch; > + struct gpio_desc *typec_vbus; > + struct gpio_desc *hub_vbus; > + int typec_vbus_enable_val; > + > + 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, > + !hisi_hikey_usb->typec_vbus_enable_val); > + 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, > + hisi_hikey_usb->typec_vbus_enable_val); > + 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); > + break; > + default: > + break; > + } > + > + return 0; > +} > + > +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; > + > + hisi_hikey_usb->nb.notifier_call = hisi_hikey_role_switch; > + > + ret = of_property_read_u32(root, "typec-vbus-enable-val", > + &hisi_hikey_usb->typec_vbus_enable_val); > + if (ret) > + hisi_hikey_usb->typec_vbus_enable_val = 1; > + > + hisi_hikey_usb->typec_vbus = devm_gpiod_get(dev, "typec-vbus", > + hisi_hikey_usb->typec_vbus_enable_val ? > + GPIOD_OUT_LOW : GPIOD_OUT_HIGH); > + if (!hisi_hikey_usb->typec_vbus) > + return -ENOENT; > + else if (IS_ERR(hisi_hikey_usb->typec_vbus)) > + return PTR_ERR(hisi_hikey_usb->typec_vbus); > + > + gpiod_direction_output(hisi_hikey_usb->typec_vbus, > + !hisi_hikey_usb->typec_vbus_enable_val); maybe a simple way if use fixed regulator? > + > + hisi_hikey_usb->otg_switch = devm_gpiod_get(dev, "otg-switch", GPIOD_IN); > + if (!hisi_hikey_usb->otg_switch) > + return -ENOENT; > + else if (IS_ERR(hisi_hikey_usb->otg_switch)) > + return PTR_ERR(hisi_hikey_usb->otg_switch); > + > + gpiod_direction_output(hisi_hikey_usb->otg_switch, USB_SWITCH_TO_HUB); > + > + /* hub-vdd33-en is optional */ > + hisi_hikey_usb->hub_vbus = devm_gpiod_get(dev, "hub-vdd33-en", > + GPIOD_OUT_LOW); > + if (IS_ERR(hisi_hikey_usb->hub_vbus)) > + return PTR_ERR(hisi_hikey_usb->hub_vbus); > + > + gpiod_direction_output(hisi_hikey_usb->hub_vbus, HUB_VBUS_POWER_ON); ditto > + > + hisi_hikey_usb->role_sw = usb_role_switch_get(dev); > + if (!hisi_hikey_usb->role_sw) > + return -EPROBE_DEFER; > + else 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");