From e6c013c306f0dd23b123e92037c1855e24a85dba Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Tue, 4 Aug 2020 09:20:03 -0700 Subject: MAINTAINERS: Add Tom Rix as fpga reviewer I take care of fpga kernel and userspace for Red Hat and would like help out more with the mainline kernel. Signed-off-by: Tom Rix Acked-by: Wu Hao Signed-off-by: Moritz Fischer --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index deaafb617361..2105c17b14cf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6811,6 +6811,7 @@ F: drivers/net/ethernet/nvidia/* FPGA DFL DRIVERS M: Wu Hao +R: Tom Rix L: linux-fpga@vger.kernel.org S: Maintained F: Documentation/fpga/dfl.rst @@ -6819,6 +6820,7 @@ F: include/uapi/linux/fpga-dfl.h FPGA MANAGER FRAMEWORK M: Moritz Fischer +R: Tom Rix L: linux-fpga@vger.kernel.org S: Maintained W: http://www.rocketboards.org -- cgit v1.2.3 From 9ba3a0aa09fe505540a3bdd11f0da3b8e9d73055 Mon Sep 17 00:00:00 2001 From: Xu Yilun Date: Mon, 7 Sep 2020 22:23:13 +0800 Subject: fpga: dfl: create a dfl bus type to support DFL devices A new bus type "dfl" is introduced for private features which are not initialized by DFL feature drivers (dfl-fme & dfl-afu drivers). So these private features could be handled by separate driver modules. DFL feature drivers (dfl-fme, dfl-port) will create DFL devices on enumeration. DFL drivers could be registered on this bus to match these DFL devices. They are matched by dfl type & feature_id. [mdf@kernel.org: Add missing Documentation part to MAINTAINERS file] Signed-off-by: Xu Yilun Signed-off-by: Wu Hao Signed-off-by: Matthew Gerlach Signed-off-by: Russ Weight Reviewed-by: Tom Rix Acked-by: Wu Hao Signed-off-by: Moritz Fischer --- Documentation/ABI/testing/sysfs-bus-dfl | 15 ++ MAINTAINERS | 1 + drivers/fpga/dfl.c | 265 +++++++++++++++++++++++++++++++- drivers/fpga/dfl.h | 86 +++++++++++ 4 files changed, 359 insertions(+), 8 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-dfl (limited to 'MAINTAINERS') diff --git a/Documentation/ABI/testing/sysfs-bus-dfl b/Documentation/ABI/testing/sysfs-bus-dfl new file mode 100644 index 000000000000..23543be904f2 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-dfl @@ -0,0 +1,15 @@ +What: /sys/bus/dfl/devices/dfl_dev.X/type +Date: Aug 2020 +KernelVersion: 5.10 +Contact: Xu Yilun +Description: Read-only. It returns type of DFL FIU of the device. Now DFL + supports 2 FIU types, 0 for FME, 1 for PORT. + Format: 0x%x + +What: /sys/bus/dfl/devices/dfl_dev.X/feature_id +Date: Aug 2020 +KernelVersion: 5.10 +Contact: Xu Yilun +Description: Read-only. It returns feature identifier local to its DFL FIU + type. + Format: 0x%x diff --git a/MAINTAINERS b/MAINTAINERS index 2105c17b14cf..d4b5b8b1658b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6814,6 +6814,7 @@ M: Wu Hao R: Tom Rix L: linux-fpga@vger.kernel.org S: Maintained +F: Documentation/ABI/testing/sysfs-bus-dfl F: Documentation/fpga/dfl.rst F: drivers/fpga/dfl* F: include/uapi/linux/fpga-dfl.h diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c index 52cafa22c127..b450870b75ed 100644 --- a/drivers/fpga/dfl.c +++ b/drivers/fpga/dfl.c @@ -30,12 +30,6 @@ static DEFINE_MUTEX(dfl_id_mutex); * index to dfl_chardevs table. If no chardev support just set devt_type * as one invalid index (DFL_FPGA_DEVT_MAX). */ -enum dfl_id_type { - FME_ID, /* fme id allocation and mapping */ - PORT_ID, /* port id allocation and mapping */ - DFL_ID_MAX, -}; - enum dfl_fpga_devt_type { DFL_FPGA_DEVT_FME, DFL_FPGA_DEVT_PORT, @@ -250,6 +244,247 @@ int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id) } EXPORT_SYMBOL_GPL(dfl_fpga_check_port_id); +static DEFINE_IDA(dfl_device_ida); + +static const struct dfl_device_id * +dfl_match_one_device(const struct dfl_device_id *id, struct dfl_device *ddev) +{ + if (id->type == ddev->type && id->feature_id == ddev->feature_id) + return id; + + return NULL; +} + +static int dfl_bus_match(struct device *dev, struct device_driver *drv) +{ + struct dfl_device *ddev = to_dfl_dev(dev); + struct dfl_driver *ddrv = to_dfl_drv(drv); + const struct dfl_device_id *id_entry; + + id_entry = ddrv->id_table; + if (id_entry) { + while (id_entry->feature_id) { + if (dfl_match_one_device(id_entry, ddev)) { + ddev->id_entry = id_entry; + return 1; + } + id_entry++; + } + } + + return 0; +} + +static int dfl_bus_probe(struct device *dev) +{ + struct dfl_driver *ddrv = to_dfl_drv(dev->driver); + struct dfl_device *ddev = to_dfl_dev(dev); + + return ddrv->probe(ddev); +} + +static int dfl_bus_remove(struct device *dev) +{ + struct dfl_driver *ddrv = to_dfl_drv(dev->driver); + struct dfl_device *ddev = to_dfl_dev(dev); + + if (ddrv->remove) + ddrv->remove(ddev); + + return 0; +} + +static int dfl_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct dfl_device *ddev = to_dfl_dev(dev); + + /* The type has 4 valid bits and feature_id has 12 valid bits */ + return add_uevent_var(env, "MODALIAS=dfl:t%01Xf%03X", + ddev->type, ddev->feature_id); +} + +static ssize_t +type_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct dfl_device *ddev = to_dfl_dev(dev); + + return sprintf(buf, "0x%x\n", ddev->type); +} +static DEVICE_ATTR_RO(type); + +static ssize_t +feature_id_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct dfl_device *ddev = to_dfl_dev(dev); + + return sprintf(buf, "0x%x\n", ddev->feature_id); +} +static DEVICE_ATTR_RO(feature_id); + +static struct attribute *dfl_dev_attrs[] = { + &dev_attr_type.attr, + &dev_attr_feature_id.attr, + NULL, +}; +ATTRIBUTE_GROUPS(dfl_dev); + +static struct bus_type dfl_bus_type = { + .name = "dfl", + .match = dfl_bus_match, + .probe = dfl_bus_probe, + .remove = dfl_bus_remove, + .uevent = dfl_bus_uevent, + .dev_groups = dfl_dev_groups, +}; + +static void release_dfl_dev(struct device *dev) +{ + struct dfl_device *ddev = to_dfl_dev(dev); + + if (ddev->mmio_res.parent) + release_resource(&ddev->mmio_res); + + ida_simple_remove(&dfl_device_ida, ddev->id); + kfree(ddev->irqs); + kfree(ddev); +} + +static struct dfl_device * +dfl_dev_add(struct dfl_feature_platform_data *pdata, + struct dfl_feature *feature) +{ + struct platform_device *pdev = pdata->dev; + struct resource *parent_res; + struct dfl_device *ddev; + int id, i, ret; + + ddev = kzalloc(sizeof(*ddev), GFP_KERNEL); + if (!ddev) + return ERR_PTR(-ENOMEM); + + id = ida_simple_get(&dfl_device_ida, 0, 0, GFP_KERNEL); + if (id < 0) { + dev_err(&pdev->dev, "unable to get id\n"); + kfree(ddev); + return ERR_PTR(id); + } + + /* freeing resources by put_device() after device_initialize() */ + device_initialize(&ddev->dev); + ddev->dev.parent = &pdev->dev; + ddev->dev.bus = &dfl_bus_type; + ddev->dev.release = release_dfl_dev; + ddev->id = id; + ret = dev_set_name(&ddev->dev, "dfl_dev.%d", id); + if (ret) + goto put_dev; + + ddev->type = feature_dev_id_type(pdev); + ddev->feature_id = feature->id; + ddev->cdev = pdata->dfl_cdev; + + /* add mmio resource */ + parent_res = &pdev->resource[feature->resource_index]; + ddev->mmio_res.flags = IORESOURCE_MEM; + ddev->mmio_res.start = parent_res->start; + ddev->mmio_res.end = parent_res->end; + ddev->mmio_res.name = dev_name(&ddev->dev); + ret = insert_resource(parent_res, &ddev->mmio_res); + if (ret) { + dev_err(&pdev->dev, "%s failed to claim resource: %pR\n", + dev_name(&ddev->dev), &ddev->mmio_res); + goto put_dev; + } + + /* then add irq resource */ + if (feature->nr_irqs) { + ddev->irqs = kcalloc(feature->nr_irqs, + sizeof(*ddev->irqs), GFP_KERNEL); + if (!ddev->irqs) { + ret = -ENOMEM; + goto put_dev; + } + + for (i = 0; i < feature->nr_irqs; i++) + ddev->irqs[i] = feature->irq_ctx[i].irq; + + ddev->num_irqs = feature->nr_irqs; + } + + ret = device_add(&ddev->dev); + if (ret) + goto put_dev; + + dev_dbg(&pdev->dev, "add dfl_dev: %s\n", dev_name(&ddev->dev)); + return ddev; + +put_dev: + /* calls release_dfl_dev() which does the clean up */ + put_device(&ddev->dev); + return ERR_PTR(ret); +} + +static void dfl_devs_remove(struct dfl_feature_platform_data *pdata) +{ + struct dfl_feature *feature; + + dfl_fpga_dev_for_each_feature(pdata, feature) { + if (feature->ddev) { + device_unregister(&feature->ddev->dev); + feature->ddev = NULL; + } + } +} + +static int dfl_devs_add(struct dfl_feature_platform_data *pdata) +{ + struct dfl_feature *feature; + struct dfl_device *ddev; + int ret; + + dfl_fpga_dev_for_each_feature(pdata, feature) { + if (feature->ioaddr) + continue; + + if (feature->ddev) { + ret = -EEXIST; + goto err; + } + + ddev = dfl_dev_add(pdata, feature); + if (IS_ERR(ddev)) { + ret = PTR_ERR(ddev); + goto err; + } + + feature->ddev = ddev; + } + + return 0; + +err: + dfl_devs_remove(pdata); + return ret; +} + +int __dfl_driver_register(struct dfl_driver *dfl_drv, struct module *owner) +{ + if (!dfl_drv || !dfl_drv->probe || !dfl_drv->id_table) + return -EINVAL; + + dfl_drv->drv.owner = owner; + dfl_drv->drv.bus = &dfl_bus_type; + + return driver_register(&dfl_drv->drv); +} +EXPORT_SYMBOL(__dfl_driver_register); + +void dfl_driver_unregister(struct dfl_driver *dfl_drv) +{ + driver_unregister(&dfl_drv->drv); +} +EXPORT_SYMBOL(dfl_driver_unregister); + #define is_header_feature(feature) ((feature)->id == FEATURE_ID_FIU_HEADER) /** @@ -261,12 +496,15 @@ void dfl_fpga_dev_feature_uinit(struct platform_device *pdev) struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); struct dfl_feature *feature; - dfl_fpga_dev_for_each_feature(pdata, feature) + dfl_devs_remove(pdata); + + dfl_fpga_dev_for_each_feature(pdata, feature) { if (feature->ops) { if (feature->ops->uinit) feature->ops->uinit(pdev, feature); feature->ops = NULL; } + } } EXPORT_SYMBOL_GPL(dfl_fpga_dev_feature_uinit); @@ -347,6 +585,10 @@ int dfl_fpga_dev_feature_init(struct platform_device *pdev, drv++; } + ret = dfl_devs_add(pdata); + if (ret) + goto exit; + return 0; exit: dfl_fpga_dev_feature_uinit(pdev); @@ -1284,11 +1526,17 @@ static int __init dfl_fpga_init(void) { int ret; + ret = bus_register(&dfl_bus_type); + if (ret) + return ret; + dfl_ids_init(); ret = dfl_chardev_init(); - if (ret) + if (ret) { dfl_ids_destroy(); + bus_unregister(&dfl_bus_type); + } return ret; } @@ -1626,6 +1874,7 @@ static void __exit dfl_fpga_exit(void) { dfl_chardev_uinit(); dfl_ids_destroy(); + bus_unregister(&dfl_bus_type); } module_init(dfl_fpga_init); diff --git a/drivers/fpga/dfl.h b/drivers/fpga/dfl.h index 5973769430a7..5dc758f655b7 100644 --- a/drivers/fpga/dfl.h +++ b/drivers/fpga/dfl.h @@ -236,6 +236,7 @@ struct dfl_feature_irq_ctx { * @irq_ctx: interrupt context list. * @nr_irqs: number of interrupt contexts. * @ops: ops of this sub feature. + * @ddev: ptr to the dfl device of this sub feature. * @priv: priv data of this feature. */ struct dfl_feature { @@ -246,6 +247,7 @@ struct dfl_feature { struct dfl_feature_irq_ctx *irq_ctx; unsigned int nr_irqs; const struct dfl_feature_ops *ops; + struct dfl_device *ddev; void *priv; }; @@ -514,4 +516,88 @@ long dfl_feature_ioctl_set_irq(struct platform_device *pdev, struct dfl_feature *feature, unsigned long arg); +/** + * enum dfl_id_type - define the DFL FIU types + */ +enum dfl_id_type { + FME_ID, + PORT_ID, + DFL_ID_MAX, +}; + +/** + * struct dfl_device_id - dfl device identifier + * @type: contains 4 bits DFL FIU type of the device. See enum dfl_id_type. + * @feature_id: contains 12 bits feature identifier local to its DFL FIU type. + * @driver_data: driver specific data. + */ +struct dfl_device_id { + u8 type; + u16 feature_id; + unsigned long driver_data; +}; + +/** + * struct dfl_device - represent an dfl device on dfl bus + * + * @dev: generic device interface. + * @id: id of the dfl device. + * @type: type of DFL FIU of the device. See enum dfl_id_type. + * @feature_id: 16 bits feature identifier local to its DFL FIU type. + * @mmio_res: mmio resource of this dfl device. + * @irqs: list of Linux IRQ numbers of this dfl device. + * @num_irqs: number of IRQs supported by this dfl device. + * @cdev: pointer to DFL FPGA container device this dfl device belongs to. + * @id_entry: matched id entry in dfl driver's id table. + */ +struct dfl_device { + struct device dev; + int id; + u8 type; + u16 feature_id; + struct resource mmio_res; + int *irqs; + unsigned int num_irqs; + struct dfl_fpga_cdev *cdev; + const struct dfl_device_id *id_entry; +}; + +/** + * struct dfl_driver - represent an dfl device driver + * + * @drv: driver model structure. + * @id_table: pointer to table of device IDs the driver is interested in. + * { } member terminated. + * @probe: mandatory callback for device binding. + * @remove: callback for device unbinding. + */ +struct dfl_driver { + struct device_driver drv; + const struct dfl_device_id *id_table; + + int (*probe)(struct dfl_device *dfl_dev); + void (*remove)(struct dfl_device *dfl_dev); +}; + +#define to_dfl_dev(d) container_of(d, struct dfl_device, dev) +#define to_dfl_drv(d) container_of(d, struct dfl_driver, drv) + +/* + * use a macro to avoid include chaining to get THIS_MODULE. + */ +#define dfl_driver_register(drv) \ + __dfl_driver_register(drv, THIS_MODULE) +int __dfl_driver_register(struct dfl_driver *dfl_drv, struct module *owner); +void dfl_driver_unregister(struct dfl_driver *dfl_drv); + +/* + * module_dfl_driver() - Helper macro for drivers that don't do + * anything special in module init/exit. This eliminates a lot of + * boilerplate. Each module may only use this macro once, and + * calling it replaces module_init() and module_exit(). + */ +#define module_dfl_driver(__dfl_driver) \ + module_driver(__dfl_driver, dfl_driver_register, \ + dfl_driver_unregister) + #endif /* __FPGA_DFL_H */ -- cgit v1.2.3 From 7a6ff4c4cbc3570a1ae483a833b3fb12b1a56a9d Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Thu, 10 Sep 2020 08:00:12 +0200 Subject: misc: hisi_hikey_usb: Driver to support onboard USB gpio hub on Hikey960 The HiKey960 has a fairly complex USB configuration due to it needing to support a USB-C port for host/device mode and multiple USB-A ports in host mode, all using a single USB controller. See schematics here: https://github.com/96boards/documentation/raw/master/consumer/hikey/hikey960/hardware-docs/HiKey960_Schematics.pdf This driver acts as a usb-role-switch intermediary, intercepting the role switch notifications from the tcpm code, and passing them on to the dwc3 core. In doing so, it also controls the onboard hub and power gpios in order to properly route the data lines between the USB-C port and the onboard hub to the USB-A ports. Signed-off-by: Yu Chen [jstultz: Major rework to make the driver a usb-role-switch intermediary] Signed-off-by: John Stultz Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/c263f72e1d803c18c45a69ce2c333e79a7ed89ff.1599717402.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 7 ++ drivers/misc/Kconfig | 9 ++ drivers/misc/Makefile | 1 + drivers/misc/hisi_hikey_usb.c | 205 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 222 insertions(+) create mode 100644 drivers/misc/hisi_hikey_usb.c (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index e4647c84c987..8cc25820dd8e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7861,6 +7861,13 @@ W: http://www.hisilicon.com F: Documentation/devicetree/bindings/net/hisilicon*.txt F: drivers/net/ethernet/hisilicon/ +HIKEY960 ONBOARD USB GPIO HUB DRIVER +M: John Stultz +L: linux-kernel@vger.kernel.org +S: Maintained +F: drivers/misc/hisi_hikey_usb.c +F: Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.yaml + HISILICON PMU DRIVER M: Shaokun Zhang S: Supported diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index ce136d685d14..cb5944a5fce5 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -456,6 +456,15 @@ 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 GPIO Hub on HiSilicon Hikey960 Platform" + depends on (OF && GPIOLIB) || COMPILE_TEST + help + If you say yes here this adds support for the on-board USB GPIO hub + found on the HiKey960, which is necessary to support switching + between the dual-role USB-C port and the USB-A host ports using only + one USB controller. + 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 c7bd01ac6291..2521359e8ef7 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -57,3 +57,4 @@ obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_HABANA_AI) += habanalabs/ obj-$(CONFIG_UACCE) += uacce/ obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.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..3a98a890757c --- /dev/null +++ b/drivers/misc/hisi_hikey_usb.c @@ -0,0 +1,205 @@ +// 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 +#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 *hub_role_sw; + + struct usb_role_switch *dev_role_sw; + enum usb_role role; + + struct mutex lock; + struct work_struct work; + + 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 void relay_set_role_switch(struct work_struct *work) +{ + struct hisi_hikey_usb *hisi_hikey_usb = container_of(work, + struct hisi_hikey_usb, + work); + struct usb_role_switch *sw; + enum usb_role role; + + if (!hisi_hikey_usb || !hisi_hikey_usb->dev_role_sw) + return; + + mutex_lock(&hisi_hikey_usb->lock); + switch (hisi_hikey_usb->role) { + 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: + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_OFF); + 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; + } + sw = hisi_hikey_usb->dev_role_sw; + role = hisi_hikey_usb->role; + mutex_unlock(&hisi_hikey_usb->lock); + + usb_role_switch_set_role(sw, role); +} + +static int hub_usb_role_switch_set(struct usb_role_switch *sw, enum usb_role role) +{ + struct hisi_hikey_usb *hisi_hikey_usb = usb_role_switch_get_drvdata(sw); + + if (!hisi_hikey_usb || !hisi_hikey_usb->dev_role_sw) + return -EINVAL; + + mutex_lock(&hisi_hikey_usb->lock); + hisi_hikey_usb->role = role; + mutex_unlock(&hisi_hikey_usb->lock); + + schedule_work(&hisi_hikey_usb->work); + + return 0; +} + +static int hisi_hikey_usb_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct hisi_hikey_usb *hisi_hikey_usb; + struct usb_role_switch_desc hub_role_switch = {NULL}; + + hisi_hikey_usb = devm_kzalloc(dev, sizeof(*hisi_hikey_usb), GFP_KERNEL); + if (!hisi_hikey_usb) + return -ENOMEM; + + 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->dev_role_sw = usb_role_switch_get(dev); + if (!hisi_hikey_usb->dev_role_sw) + return -EPROBE_DEFER; + if (IS_ERR(hisi_hikey_usb->dev_role_sw)) + return PTR_ERR(hisi_hikey_usb->dev_role_sw); + + + INIT_WORK(&hisi_hikey_usb->work, relay_set_role_switch); + mutex_init(&hisi_hikey_usb->lock); + + hub_role_switch.fwnode = dev_fwnode(dev); + hub_role_switch.set = hub_usb_role_switch_set; + hub_role_switch.driver_data = hisi_hikey_usb; + + hisi_hikey_usb->hub_role_sw = usb_role_switch_register(dev, + &hub_role_switch); + + if (IS_ERR(hisi_hikey_usb->hub_role_sw)) { + usb_role_switch_put(hisi_hikey_usb->dev_role_sw); + return PTR_ERR(hisi_hikey_usb->hub_role_sw); + } + + 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); + + if (hisi_hikey_usb->hub_role_sw) + usb_role_switch_unregister(hisi_hikey_usb->hub_role_sw); + + if (hisi_hikey_usb->dev_role_sw) + usb_role_switch_put(hisi_hikey_usb->dev_role_sw); + + return 0; +} + +static const struct of_device_id id_table_hisi_hikey_usb[] = { + {.compatible = "hisilicon,gpio_hubv1"}, + {} +}; +MODULE_DEVICE_TABLE(of, id_table_hisi_hikey_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"); -- cgit v1.2.3 From 2fee15c10d18a09cc9926eafeaef9750be1104b2 Mon Sep 17 00:00:00 2001 From: Mathieu Poirier Date: Wed, 16 Sep 2020 13:17:33 -0600 Subject: MAINTAINERS: Add CoreSight mailing list Add CoreSight mailing list so that people can participate in patch reviews and know what features are coming next. Signed-off-by: Mathieu Poirier Link: https://lore.kernel.org/r/20200916191737.4001561-13-mathieu.poirier@linaro.org Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 286fd7263982..54cb47e8a0b2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1746,6 +1746,7 @@ ARM/CORESIGHT FRAMEWORK AND DRIVERS M: Mathieu Poirier R: Suzuki K Poulose R: Mike Leach +L: coresight@lists.linaro.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* -- cgit v1.2.3 From e82ed736ad2d2dddf1384fc4c8a0f26021af04fe Mon Sep 17 00:00:00 2001 From: Andra Paraschiv Date: Mon, 21 Sep 2020 15:17:32 +0300 Subject: MAINTAINERS: Add entry for the Nitro Enclaves driver Add entry in the MAINTAINERS file for the Nitro Enclaves files such as the documentation, the header files, the driver itself and the user space sample. Changelog v9 -> v10 * Update commit message to include the changelog before the SoB tag(s). v8 -> v9 * Update the location of the documentation, as it has been moved to the "virt" directory. v7 -> v8 * No changes. v6 -> v7 * No changes. v5 -> v6 * No changes. v4 -> v5 * No changes. v3 -> v4 * No changes. v2 -> v3 * Update file entries to be in alphabetical order. v1 -> v2 * No changes. Reviewed-by: Alexander Graf Signed-off-by: Andra Paraschiv Link: https://lore.kernel.org/r/20200921121732.44291-19-andraprs@amazon.com Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 54cb47e8a0b2..d6b9445649e5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12304,6 +12304,19 @@ S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/lftan/nios2.git F: arch/nios2/ +NITRO ENCLAVES (NE) +M: Andra Paraschiv +M: Alexandru Vasile +M: Alexandru Ciobotaru +L: linux-kernel@vger.kernel.org +S: Supported +W: https://aws.amazon.com/ec2/nitro/nitro-enclaves/ +F: Documentation/virt/ne_overview.rst +F: drivers/virt/nitro_enclaves/ +F: include/linux/nitro_enclaves.h +F: include/uapi/linux/nitro_enclaves.h +F: samples/nitro_enclaves/ + NOHZ, DYNTICKS SUPPORT M: Frederic Weisbecker M: Thomas Gleixner -- cgit v1.2.3 From c29ce4e2b314ca21e0001cb1587e6008eb061939 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 17 Aug 2020 09:00:09 +0200 Subject: MAINTAINERS: Add entry for NXP PTN5150A CC driver Add Krzysztof Kozlowski as maintainer of NXP PTN5150A CC/extcon driver to provide review, feedback and testing. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Vijai Kumar K Signed-off-by: Chanwoo Choi --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 0d0862b19ce5..0f5cb41b3fa9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12455,6 +12455,13 @@ F: drivers/iio/gyro/fxas21002c_core.c F: drivers/iio/gyro/fxas21002c_i2c.c F: drivers/iio/gyro/fxas21002c_spi.c +NXP PTN5150A CC LOGIC AND EXTCON DRIVER +M: Krzysztof Kozlowski +L: linux-kernel@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml +F: drivers/extcon/extcon-ptn5150.c + NXP SGTL5000 DRIVER M: Fabio Estevam L: alsa-devel@alsa-project.org (moderated for non-subscribers) -- cgit v1.2.3 From c471bf4b11c7df0f0f9f42b5aeec424dc62d0c7e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 30 Sep 2020 14:10:07 +0200 Subject: MAINTAINERS: exclude char maintainers from things they do not maintain There are a number of subdirectories and files in drivers/char/ that have their own maintainers and developers and ways of getting patches to Linus. This includes random.c, IPMI, hardware random drivers, TPM drivers, and agp drivers. Instead of sending those patches to Arnd and myself, who can't do anything with them, send them to the proper developers instead. Acked-by: Arnd Bergmann Acked-by: Corey Minyard Link: https://lore.kernel.org/r/20200930121007.GA1615300@kroah.com Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index d6b9445649e5..a6f0a3ec0047 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4101,6 +4101,11 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git F: drivers/char/ F: drivers/misc/ F: include/linux/miscdevice.h +X: drivers/char/agp/ +X: drivers/char/hw_random/ +X: drivers/char/ipmi/ +X: drivers/char/random.c +X: drivers/char/tpm/ CHECKPATCH M: Andy Whitcroft -- cgit v1.2.3 From 21cb9b18edea0c3533799069abc95c9c55c8607d Mon Sep 17 00:00:00 2001 From: Bhaumik Bhatt Date: Tue, 29 Sep 2020 23:22:14 +0530 Subject: bus: mhi: core: Introduce sysfs entries for MHI Introduce sysfs entries to enable userspace clients the ability to read the serial number and the OEM PK Hash values obtained from BHI. OEMs need to read these device-specific hardware information values through userspace for factory testing purposes and cannot be exposed via degbufs as it may remain disabled for performance reasons. Also, update the documentation for ABI to include these entries. Reviewed-by: Manivannan Sadhasivam [mani: used dev_groups to manage sysfs attributes] Signed-off-by: Bhaumik Bhatt Signed-off-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20200929175218.8178-16-manivannan.sadhasivam@linaro.org Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/stable/sysfs-bus-mhi | 21 +++++++++++++++++++ MAINTAINERS | 1 + drivers/bus/mhi/core/init.c | 37 ++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 Documentation/ABI/stable/sysfs-bus-mhi (limited to 'MAINTAINERS') diff --git a/Documentation/ABI/stable/sysfs-bus-mhi b/Documentation/ABI/stable/sysfs-bus-mhi new file mode 100644 index 000000000000..ecfe7662f8d0 --- /dev/null +++ b/Documentation/ABI/stable/sysfs-bus-mhi @@ -0,0 +1,21 @@ +What: /sys/bus/mhi/devices/.../serialnumber +Date: Sept 2020 +KernelVersion: 5.10 +Contact: Bhaumik Bhatt +Description: The file holds the serial number of the client device obtained + using a BHI (Boot Host Interface) register read after at least + one attempt to power up the device has been done. If read + without having the device power on at least once, the file will + read all 0's. +Users: Any userspace application or clients interested in device info. + +What: /sys/bus/mhi/devices/.../oem_pk_hash +Date: Sept 2020 +KernelVersion: 5.10 +Contact: Bhaumik Bhatt +Description: The file holds the OEM PK Hash value of the endpoint device + obtained using a BHI (Boot Host Interface) register read after + at least one attempt to power up the device has been done. If + read without having the device power on at least once, the file + will read all 0's. +Users: Any userspace application or clients interested in device info. diff --git a/MAINTAINERS b/MAINTAINERS index a6f0a3ec0047..a7975cb55438 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11364,6 +11364,7 @@ M: Hemant Kumar L: linux-arm-msm@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/mani/mhi.git +F: Documentation/ABI/stable/sysfs-bus-mhi F: Documentation/mhi/ F: drivers/bus/mhi/ F: include/linux/mhi.h diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c index 61e5885a331a..a33665b7ee54 100644 --- a/drivers/bus/mhi/core/init.c +++ b/drivers/bus/mhi/core/init.c @@ -76,6 +76,42 @@ const char *to_mhi_pm_state_str(enum mhi_pm_state state) return mhi_pm_state_str[index]; } +static ssize_t serial_number_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct mhi_device *mhi_dev = to_mhi_device(dev); + struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; + + return snprintf(buf, PAGE_SIZE, "Serial Number: %u\n", + mhi_cntrl->serial_number); +} +static DEVICE_ATTR_RO(serial_number); + +static ssize_t oem_pk_hash_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct mhi_device *mhi_dev = to_mhi_device(dev); + struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; + int i, cnt = 0; + + for (i = 0; i < ARRAY_SIZE(mhi_cntrl->oem_pk_hash); i++) + cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, + "OEMPKHASH[%d]: 0x%x\n", i, + mhi_cntrl->oem_pk_hash[i]); + + return cnt; +} +static DEVICE_ATTR_RO(oem_pk_hash); + +static struct attribute *mhi_dev_attrs[] = { + &dev_attr_serial_number.attr, + &dev_attr_oem_pk_hash.attr, + NULL, +}; +ATTRIBUTE_GROUPS(mhi_dev); + /* MHI protocol requires the transfer ring to be aligned with ring length */ static int mhi_alloc_aligned_ring(struct mhi_controller *mhi_cntrl, struct mhi_ring *ring, @@ -1301,6 +1337,7 @@ struct bus_type mhi_bus_type = { .dev_name = "mhi", .match = mhi_match, .uevent = mhi_uevent, + .dev_groups = mhi_dev_groups, }; static int __init mhi_init(void) -- cgit v1.2.3