[PATCH 1/4] usb: typec: ucsi: ccg: add get_fw_info function
From: Ajay Gupta Function is to get the details of ccg firmware and device version. It will be useful in debugging and also during firmware update. Signed-off-by: Ajay Gupta Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/ucsi_ccg.c | 66 ++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c index de8a43bdff68..3884fb41c72e 100644 --- a/drivers/usb/typec/ucsi/ucsi_ccg.c +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c @@ -17,15 +17,54 @@ #include #include "ucsi.h" +enum enum_fw_mode { + BOOT, /* bootloader */ + FW1,/* FW partition-1 (contains secondary fw) */ + FW2,/* FW partition-2 (contains primary fw) */ + FW_INVALID, +}; + +struct ccg_dev_info { +#define CCG_DEVINFO_FWMODE_SHIFT (0) +#define CCG_DEVINFO_FWMODE_MASK (0x3 << CCG_DEVINFO_FWMODE_SHIFT) +#define CCG_DEVINFO_PDPORTS_SHIFT (2) +#define CCG_DEVINFO_PDPORTS_MASK (0x3 << CCG_DEVINFO_PDPORTS_SHIFT) + u8 mode; + u8 bl_mode; + __le16 silicon_id; + __le16 bl_last_row; +} __packed; + +struct version_format { + __le16 build; + u8 patch; + u8 ver; +#define CCG_VERSION_MIN_SHIFT (0) +#define CCG_VERSION_MIN_MASK (0xf << CCG_VERSION_MIN_SHIFT) +#define CCG_VERSION_MAJ_SHIFT (4) +#define CCG_VERSION_MAJ_MASK (0xf << CCG_VERSION_MAJ_SHIFT) +} __packed; + +struct version_info { + struct version_format base; + struct version_format app; +}; + struct ucsi_ccg { struct device *dev; struct ucsi *ucsi; struct ucsi_ppm ppm; struct i2c_client *client; + struct ccg_dev_info info; + /* version info for boot, primary and secondary */ + struct version_info version[FW2 + 1]; }; -#define CCGX_RAB_INTR_REG 0x06 -#define CCGX_RAB_UCSI_CONTROL 0x39 +#define CCGX_RAB_DEVICE_MODE 0x +#define CCGX_RAB_INTR_REG 0x0006 +#define CCGX_RAB_READ_ALL_VER 0x0010 +#define CCGX_RAB_READ_FW2_VER 0x0020 +#define CCGX_RAB_UCSI_CONTROL 0x0039 #define CCGX_RAB_UCSI_CONTROL_STARTBIT(0) #define CCGX_RAB_UCSI_CONTROL_STOP BIT(1) #define CCGX_RAB_UCSI_DATA_BLOCK(offset) (0xf000 | ((offset) & 0xff)) @@ -220,6 +259,23 @@ static irqreturn_t ccg_irq_handler(int irq, void *data) return IRQ_HANDLED; } +static int get_fw_info(struct ucsi_ccg *uc) +{ + int err; + + err = ccg_read(uc, CCGX_RAB_READ_ALL_VER, (u8 *)(&uc->version), + sizeof(uc->version)); + if (err < 0) + return err; + + err = ccg_read(uc, CCGX_RAB_DEVICE_MODE, (u8 *)(&uc->info), + sizeof(uc->info)); + if (err < 0) + return err; + + return 0; +} + static int ucsi_ccg_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -248,6 +304,12 @@ static int ucsi_ccg_probe(struct i2c_client *client, return status; } + status = get_fw_info(uc); + if (status < 0) { + dev_err(uc->dev, "get_fw_info failed - %d\n", status); + return status; + } + status = devm_request_threaded_irq(dev, client->irq, NULL, ccg_irq_handler, IRQF_ONESHOT | IRQF_TRIGGER_HIGH, -- 2.20.1
[PATCH 2/4] usb: typec: ucsi: ccg: add firmware flashing support
From: Ajay Gupta CCGx has two copies of the firmware in addition to the bootloader. If the device is running FW1, FW2 can be updated with the new version. Dual firmware mode allows the CCG device to stay in a PD contract and support USB PD and Type-C functionality while a firmware update is in progress. First we read the currently flashed firmware version of both primary and secondary firmware and then compare it with version of firmware file to determine if flashing is required. Command framework is added to support sending commands to CCGx controller. We wait for response after sending the command and then read the response from RAB_RESPONSE register. Below commands are supported, - ENTER_FLASHING - RESET - PDPORT_ENABLE - JUMP_TO_BOOT - FLASH_ROW_RW - VALIDATE_FW Command specific mutex lock is also added to sync between driver and user threads. PD port number information is added which is required while sending PD_PORT_ENABLE command Signed-off-by: Ajay Gupta Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/ucsi_ccg.c | 828 +- 1 file changed, 815 insertions(+), 13 deletions(-) diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c index 3884fb41c72e..5508beec08e3 100644 --- a/drivers/usb/typec/ucsi/ucsi_ccg.c +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c @@ -9,6 +9,7 @@ */ #include #include +#include #include #include #include @@ -24,6 +25,73 @@ enum enum_fw_mode { FW_INVALID, }; +#define CCGX_RAB_DEVICE_MODE 0x +#define CCGX_RAB_INTR_REG 0x0006 +#define DEV_INT BIT(0) +#define PORT0_INT BIT(1) +#define PORT1_INT BIT(2) +#define UCSI_READ_INT BIT(7) +#define CCGX_RAB_JUMP_TO_BOOT 0x0007 +#define TO_BOOT 'J' +#define TO_ALT_FW 'A' +#define CCGX_RAB_RESET_REQ 0x0008 +#define RESET_SIG 'R' +#define CMD_RESET_I2C 0x0 +#define CMD_RESET_DEV 0x1 +#define CCGX_RAB_ENTER_FLASHING0x000A +#define FLASH_ENTER_SIG 'P' +#define CCGX_RAB_VALIDATE_FW 0x000B +#define CCGX_RAB_FLASH_ROW_RW 0x000C +#define FLASH_SIG 'F' +#define FLASH_RD_CMD 0x0 +#define FLASH_WR_CMD 0x1 +#define FLASH_FWCT1_WR_CMD0x2 +#define FLASH_FWCT2_WR_CMD0x3 +#define FLASH_FWCT_SIG_WR_CMD 0x4 +#define CCGX_RAB_READ_ALL_VER 0x0010 +#define CCGX_RAB_READ_FW2_VER 0x0020 +#define CCGX_RAB_UCSI_CONTROL 0x0039 +#define CCGX_RAB_UCSI_CONTROL_STARTBIT(0) +#define CCGX_RAB_UCSI_CONTROL_STOP BIT(1) +#define CCGX_RAB_UCSI_DATA_BLOCK(offset) (0xf000 | ((offset) & 0xff)) +#define REG_FLASH_RW_MEM0x0200 +#define DEV_REG_IDXCCGX_RAB_DEVICE_MODE +#define CCGX_RAB_PDPORT_ENABLE 0x002C +#define PDPORT_1 BIT(0) +#define PDPORT_2 BIT(1) +#define CCGX_RAB_RESPONSE 0x007E +#define ASYNC_EVENT BIT(7) + +/* CCGx events & async msg codes */ +#define RESET_COMPLETE 0x80 +#define EVENT_INDEXRESET_COMPLETE +#define PORT_CONNECT_DET 0x84 +#define PORT_DISCONNECT_DET0x85 +#define ROLE_SWAP_COMPELETE0x87 + +/* ccg firmware */ +#define CYACD_LINE_SIZE 527 +#define CCG4_ROW_SIZE 256 +#define FW1_METADATA_ROW0x1FF +#define FW2_METADATA_ROW0x1FE +#define FW_CFG_TABLE_SIG_SIZE 256 + +static int secondary_fw_min_ver = 41; + +enum enum_flash_mode { + SECONDARY_BL, /* update secondary using bootloader */ + PRIMARY,/* update primary using secondary */ + SECONDARY, /* update secondary using primary */ + FLASH_NOT_NEEDED, /* update not required */ + FLASH_INVALID, +}; + +static const char * const ccg_fw_names[] = { + "ccg_boot.cyacd", + "ccg_primary.cyacd", + "ccg_secondary.cyacd" +}; + struct ccg_dev_info { #define CCG_DEVINFO_FWMODE_SHIFT (0) #define CCG_DEVINFO_FWMODE_MASK (0x3 << CCG_DEVINFO_FWMODE_SHIFT) @@ -50,6 +118,50 @@ struct version_info { struct version_format app; }; +struct fw_config_table { + u32 identity; + u16 table_size; + u8 fwct_version; + u8 is_key_change; + u8 guid[16]; + struct version_format base; + struct version_format app; + u8 primary_fw_digest[32]; + u32 key_exp_length; + u8 key_modulus[256]; + u8 key_exp[4]; +}; + +/* CCGx response codes */ +enum ccg_res
[PATCH 4/4] usb: typec: ucsi: Support for DisplayPort alt mode
This makes it possible to bind a driver to a DisplayPort alt mode adapter devices. The driver attempts to cope with the limitations of UCSI by "emulating" behaviour and attempting to guess things when ever possible in order to satisfy the requirements the standard DisplayPort alt mode driver has. Tested-by: Ajay Gupta Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/Makefile | 15 +- drivers/usb/typec/ucsi/displayport.c | 297 +++ drivers/usb/typec/ucsi/ucsi.c| 21 +- drivers/usb/typec/ucsi/ucsi.h| 21 ++ 4 files changed, 346 insertions(+), 8 deletions(-) create mode 100644 drivers/usb/typec/ucsi/displayport.c diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile index 2f4900b26210..b35e15a1f02c 100644 --- a/drivers/usb/typec/ucsi/Makefile +++ b/drivers/usb/typec/ucsi/Makefile @@ -1,12 +1,15 @@ # SPDX-License-Identifier: GPL-2.0 -CFLAGS_trace.o := -I$(src) +CFLAGS_trace.o := -I$(src) -obj-$(CONFIG_TYPEC_UCSI) += typec_ucsi.o +obj-$(CONFIG_TYPEC_UCSI) += typec_ucsi.o -typec_ucsi-y := ucsi.o +typec_ucsi-y := ucsi.o -typec_ucsi-$(CONFIG_TRACING) += trace.o +typec_ucsi-$(CONFIG_TRACING) += trace.o -obj-$(CONFIG_UCSI_ACPI)+= ucsi_acpi.o +ifneq ($(CONFIG_TYPEC_DP_ALTMODE),) + typec_ucsi-y+= displayport.o +endif -obj-$(CONFIG_UCSI_CCG) += ucsi_ccg.o +obj-$(CONFIG_UCSI_ACPI)+= ucsi_acpi.o +obj-$(CONFIG_UCSI_CCG) += ucsi_ccg.o diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c new file mode 100644 index ..2964103a6fc6 --- /dev/null +++ b/drivers/usb/typec/ucsi/displayport.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * UCSI DisplayPort Alternate Mode Support + * + * Copyright (C) 2018, Intel Corporation + * Author: Heikki Krogerus + */ + +#include +#include + +#include "ucsi.h" + +#define UCSI_CMD_SET_NEW_CAM(_con_num_, _enter_, _cam_, _am_) \ +(UCSI_SET_NEW_CAM | ((_con_num_) << 16) | ((_enter_) << 23) | \ + ((_cam_) << 24) | ((u64)(_am_) << 32)) + +struct ucsi_dp { + struct typec_displayport_data data; + struct ucsi_connector *con; + struct typec_altmode *alt; + struct work_struct work; + int offset; + + bool override; + bool initialized; + + u32 header; + u32 *vdo_data; + u8 vdo_size; +}; + +/* + * Note. Alternate mode control is optional feature in UCSI. It means that even + * if the system supports alternate modes, the OS may not be aware of them. + * + * In most cases however, the OS will be able to see the supported alternate + * modes, but it may still not be able to configure them, not even enter or exit + * them. That is because UCSI defines alt mode details and alt mode "overriding" + * as separate options. + * + * In case alt mode details are supported, but overriding is not, the driver + * will still display the supported pin assignments and configuration, but any + * changes the user attempts to do will lead into failure with return value of + * -EOPNOTSUPP. + */ + +static int ucsi_displayport_enter(struct typec_altmode *alt) +{ + struct ucsi_dp *dp = typec_altmode_get_drvdata(alt); + + mutex_lock(&dp->con->lock); + + if (!dp->override && dp->initialized) { + const struct typec_altmode *p = typec_altmode_get_partner(alt); + + dev_warn(&p->dev, +"firmware doesn't support alternate mode overriding\n"); + mutex_unlock(&dp->con->lock); + return -EOPNOTSUPP; + } + + /* +* We can't send the New CAM command yet to the PPM as it needs the +* configuration value as well. Pretending that we have now entered the +* mode, and letting the alt mode driver continue. +*/ + + dp->header = VDO(USB_TYPEC_DP_SID, 1, CMD_ENTER_MODE); + dp->header |= VDO_OPOS(USB_TYPEC_DP_MODE); + dp->header |= VDO_CMDT(CMDT_RSP_ACK); + + dp->vdo_data = NULL; + dp->vdo_size = 1; + + schedule_work(&dp->work); + + mutex_unlock(&dp->con->lock); + + return 0; +} + +static int ucsi_displayport_exit(struct typec_altmode *alt) +{ + struct ucsi_dp *dp = typec_altmode_get_drvdata(alt); + struct ucsi_control ctrl; + int ret = 0; + + mutex_lock(&dp->con->lock); + + if (!dp->override) { + const struct typec_altmode *p = typec_altmode_get_partner(alt); + + dev_warn(&p->dev, +"firmware doesn't support alternate mode overriding\n"); + ret = -EOPNOTSUPP; + goto out_unlock; + } + + ctrl.raw_cmd = UCSI_CMD_SET_NEW_CAM(dp->con->num, 0, dp->offset, 0); + ret = ucsi_send_command(dp->con->uc
[PATCH 0/4] usb: typec: ucsi: Remaining changes for v5.2
Hi Greg, Here are the remaining patches from me and Ajay for the UCSI driver. I took the liberty of collecting them for you, and resending everything together. There are two patches from Ajay adding support for firmware upgrading with the Cypress CCGx controllers [1], and two patches from me enabling DisplayPort alt mode with the UCSI driver [2]. [1] https://marc.info/?l=linux-usb&m=154957412422108&w=2 [2] https://www.spinics.net/lists/linux-usb/msg178192.html Let us know if there if you want anything to be changed. thanks, -- heikki Ajay Gupta (2): usb: typec: ucsi: ccg: add get_fw_info function usb: typec: ucsi: ccg: add firmware flashing support Heikki Krogerus (2): usb: typec: ucsi: Preliminary support for alternate modes usb: typec: ucsi: Support for DisplayPort alt mode drivers/usb/typec/ucsi/Makefile | 15 +- drivers/usb/typec/ucsi/displayport.c | 297 + drivers/usb/typec/ucsi/trace.c | 12 + drivers/usb/typec/ucsi/trace.h | 26 + drivers/usb/typec/ucsi/ucsi.c| 371 +-- drivers/usb/typec/ucsi/ucsi.h| 93 +++ drivers/usb/typec/ucsi/ucsi_ccg.c| 884 ++- 7 files changed, 1617 insertions(+), 81 deletions(-) create mode 100644 drivers/usb/typec/ucsi/displayport.c -- 2.20.1
[PATCH 3/4] usb: typec: ucsi: Preliminary support for alternate modes
With UCSI the alternate modes, just like everything else related to USB Type-C connectors, are handled in firmware. The operating system can see the status and is allowed to request certain things, for example entering and exiting the modes, but the support for alternate modes is very limited in UCSI. The feature is also optional, which means that even when the platform supports alternate modes, the operating system may not be even made aware of them. UCSI does not support direct VDM reading or writing. Instead, alternate modes can be entered and exited using a single custom command which takes also an optional SVID specific configuration value as parameter. That means every supported alternate mode has to be handled separately in UCSI driver. This commit does not include support for any specific alternate mode. The discovered alternate modes are now registered, but binding a driver to an alternate mode will not be possible until support for that alternate mode is added to the UCSI driver. Tested-by: Ajay Gupta Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/trace.c | 12 ++ drivers/usb/typec/ucsi/trace.h | 26 +++ drivers/usb/typec/ucsi/ucsi.c | 354 +++-- drivers/usb/typec/ucsi/ucsi.h | 72 +++ 4 files changed, 399 insertions(+), 65 deletions(-) diff --git a/drivers/usb/typec/ucsi/trace.c b/drivers/usb/typec/ucsi/trace.c index ffa3b4c3f338..1dabafb74320 100644 --- a/drivers/usb/typec/ucsi/trace.c +++ b/drivers/usb/typec/ucsi/trace.c @@ -60,3 +60,15 @@ const char *ucsi_cci_str(u32 cci) return ""; } + +static const char * const ucsi_recipient_strs[] = { + [UCSI_RECIPIENT_CON]= "port", + [UCSI_RECIPIENT_SOP]= "partner", + [UCSI_RECIPIENT_SOP_P] = "plug (prime)", + [UCSI_RECIPIENT_SOP_PP] = "plug (double prime)", +}; + +const char *ucsi_recipient_str(u8 recipient) +{ + return ucsi_recipient_strs[recipient]; +} diff --git a/drivers/usb/typec/ucsi/trace.h b/drivers/usb/typec/ucsi/trace.h index 5e2906df2db7..783ec9c72055 100644 --- a/drivers/usb/typec/ucsi/trace.h +++ b/drivers/usb/typec/ucsi/trace.h @@ -7,6 +7,7 @@ #define __UCSI_TRACE_H #include +#include const char *ucsi_cmd_str(u64 raw_cmd); const char *ucsi_ack_str(u8 ack); @@ -134,6 +135,31 @@ DEFINE_EVENT(ucsi_log_connector_status, ucsi_register_port, TP_ARGS(port, status) ); +DECLARE_EVENT_CLASS(ucsi_log_register_altmode, + TP_PROTO(u8 recipient, struct typec_altmode *alt), + TP_ARGS(recipient, alt), + TP_STRUCT__entry( + __field(u8, recipient) + __field(u16, svid) + __field(u8, mode) + __field(u32, vdo) + ), + TP_fast_assign( + __entry->recipient = recipient; + __entry->svid = alt->svid; + __entry->mode = alt->mode; + __entry->vdo = alt->vdo; + ), + TP_printk("%s alt mode: svid %04x, mode %d vdo %x", + ucsi_recipient_str(__entry->recipient), __entry->svid, + __entry->mode, __entry->vdo) +); + +DEFINE_EVENT(ucsi_log_register_altmode, ucsi_register_altmode, + TP_PROTO(u8 recipient, struct typec_altmode *alt), + TP_ARGS(recipient, alt) +); + #endif /* __UCSI_TRACE_H */ /* This part must be outside protection */ diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 8d0a6fe748bd..11d1884322c2 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include "ucsi.h" #include "trace.h" @@ -45,22 +45,6 @@ enum ucsi_status { UCSI_ERROR, }; -struct ucsi_connector { - int num; - - struct ucsi *ucsi; - struct work_struct work; - struct completion complete; - - struct typec_port *port; - struct typec_partner *partner; - - struct typec_capability typec_cap; - - struct ucsi_connector_status status; - struct ucsi_connector_capability cap; -}; - struct ucsi { struct device *dev; struct ucsi_ppm *ppm; @@ -238,8 +222,200 @@ static int ucsi_run_command(struct ucsi *ucsi, struct ucsi_control *ctrl, return ret; } +int ucsi_send_command(struct ucsi *ucsi, struct ucsi_control *ctrl, + void *retval, size_t size) +{ + int ret; + + mutex_lock(&ucsi->ppm_lock); + ret = ucsi_run_command(ucsi, ctrl, retval, size); + mutex_unlock(&ucsi->ppm_lock); + + return ret; +} + /* -- */ +void ucsi_altmode_update_active(struct ucsi_connector *con) +{ + const struct typec_altmode *altmode = NULL; + struct ucsi_control ctrl; + int ret; + u8 cur; + int i; + + UCSI_CMD_GET_CURRENT_CAM(ctrl, con->num); + ret = ucsi_run_command(con->ucsi, &ctrl, &cur, sizeof(cur));
Re: [PATCH v2 0/5] usb: dwc2: Improve gadget phy init
On 4/5/2019 5:36 PM, Jules Maselbas wrote: > Hi, > > Theses patches tries to clean a bit dwc2's phy initialization and > fix an issue in gadget mode where the utmi phy width is set > regardless of utmi being used or not. > > I believe that when using ulpi a phy width of 8 bits must be used, > but this wasn't the case as the variable phyif was set by default > to 16 bits. > > In this second patch-set version the last two patches are optionnal, > from my point of view they are not essential for me but I hope they > can improve this driver. > > Best regards, > Jules > --- > Changes in v2: >- Changed patches order >- dwc2_init_fs_ls_pclk_sel is now declared in core.h (to be used in hcd.c) >- Fix patch `Replace phyif with phy_utmi_width` (wrong value set to usbcfg) >- Add check for utmi phy type in patch `Replace phyif with phy_utmi_width` > > --- > Jules Maselbas (5): >usb: dwc2: Move UTMI_PHY_DATA defines closer >usb: dwc2: gadget: Remove duplicated phy init >usb: dwc2: gadget: Replace phyif with phy_utmi_width >usb: dwc2: Move phy init into core >usb: dwc2: gadget: Move gadget phy init into core phy init > > drivers/usb/dwc2/core.c | 199 > drivers/usb/dwc2/core.h | 4 +- > drivers/usb/dwc2/gadget.c | 36 ++- > drivers/usb/dwc2/hcd.c | 190 -- > drivers/usb/dwc2/hw.h | 6 +- > drivers/usb/dwc2/platform.c | 5 +- > 6 files changed, 213 insertions(+), 227 deletions(-) > Acked-by: Minas Harutyunyan
Re: lan78xx: About 8000 usb interrupts per second when idle
On Tue, 9 Apr 2019 09:28:16 + Minas Harutyunyan wrote: > > Hi Stefan, > > > Hi Minas, > > > > Am 09.04.19 um 08:54 schrieb Jisheng Zhang: > >> On Mon, 8 Apr 2019 16:05:51 +0800 Jisheng Zhang wrote: > >> > >>> Hi Stefan, > >>> > >>> On Mon, 8 Apr 2019 09:57:14 +0200 Stefan Wahren wrote: > >>> > > Hi Jisheng, > > > thanks for sending this patch. I already reported this issue > last year [1], but Microchip wasn't able to provide a fix. > > I will give it a try. > > > The second one: 8000 usb interrupts per second when idle. > > This is abnormal. any idea? Is it due to the lan78xx? > Does this downstream patch [2] improve your situation? > >>> Thanks a lot. Will try the patch tonight. > >> I tried this patch, it doesn't help. One more observation: if I > >> ifconfig eth0 down, I can still get 8000 usb interrupts per second. > >> Not sure whether this is usb issue or not. > > > > Jisheng reports a lot of USB interrupts while the lan78xx driver on > > Raspberry Pi 3B+ is in idle. > > > > Any suggestions to narrow this down? > > dwc2 in host mode enable SOF interrupts if any periodic EP are in use. > So, 8000 interrupts per second is expectant behavior. Makes sense. 8 microframes each 1ms, so 8*1000 = 8000 interrupts/s
Re: lan78xx: About 8000 usb interrupts per second when idle
On Mi, 2019-04-10 at 09:37 +, Jisheng Zhang wrote: > On Tue, 9 Apr 2019 09:28:16 + Minas Harutyunyan wrote: Hi, > > dwc2 in host mode enable SOF interrupts if any periodic EP are in use. > > So, 8000 interrupts per second is expectant behavior. > > Makes sense. 8 microframes each 1ms, so 8*1000 = 8000 interrupts/s The remedy for that would be using autosuspend. That just tells us that support for autosuspend is not optional. Regards Oliver
Re: [PATCH 2/4] usb: typec: ucsi: ccg: add firmware flashing support
Hi Heikki, I love your patch! Perhaps something to improve: [auto build test WARNING on usb/usb-testing] [also build test WARNING on v5.1-rc4 next-20190410] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Heikki-Krogerus/usb-typec-ucsi-Remaining-changes-for-v5-2/20190410-221455 base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing reproduce: # apt-get install sparse make ARCH=x86_64 allmodconfig make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' sparse warnings: (new ones prefixed by >>) drivers/usb/typec/ucsi/ucsi_ccg.c:212:24: sparse: expression using sizeof(void) drivers/usb/typec/ucsi/ucsi_ccg.c:212:24: sparse: expression using sizeof(void) >> drivers/usb/typec/ucsi/ucsi_ccg.c:690:16: sparse: restricted __le16 degrades >> to integer drivers/usb/typec/ucsi/ucsi_ccg.c:698:24: sparse: restricted __le16 degrades to integer drivers/usb/typec/ucsi/ucsi_ccg.c:735:26: sparse: restricted __le16 degrades to integer drivers/usb/typec/ucsi/ucsi_ccg.c:737:33: sparse: restricted __le16 degrades to integer drivers/usb/typec/ucsi/ucsi_ccg.c:777:37: sparse: restricted __le16 degrades to integer vim +690 drivers/usb/typec/ucsi/ucsi_ccg.c 680 681 static bool ccg_check_vendor_version(struct ucsi_ccg *uc, 682 struct version_format *app, 683 struct fw_config_table *fw_cfg) 684 { 685 struct device *dev = uc->dev; 686 687 /* Check if the fw build is for supported vendors. 688 * Add all supported vendors here. 689 */ > 690 if (app->build != (('n' << 8) | 'v')) { 691 dev_info(dev, "current fw is not from supported vendor\n"); 692 return false; 693 } 694 695 /* Check if the new fw build is for supported vendors 696 * Add all supported vendors here. 697 */ 698 if (fw_cfg->app.build != (('n' << 8) | 'v')) { 699 dev_info(dev, "new fw is not from supported vendor\n"); 700 return false; 701 } 702 return true; 703 } 704 --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
[PATCH 2/2] usb: typec: Add driver for NVIDIA Alt Modes
From: Ajay Gupta Latest NVIDIA GPUs support VirtualLink device. Since USBIF has not assigned a Standard ID (SID) for VirtualLink so using NVIDA VID 0x955 as SVID. Signed-off-by: Ajay Gupta --- drivers/usb/typec/altmodes/Kconfig | 10 +++ drivers/usb/typec/altmodes/Makefile | 2 ++ drivers/usb/typec/altmodes/nvidia.c | 44 + drivers/usb/typec/ucsi/ucsi.c | 4 ++- include/linux/usb/typec_dp.h| 5 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/typec/altmodes/nvidia.c diff --git a/drivers/usb/typec/altmodes/Kconfig b/drivers/usb/typec/altmodes/Kconfig index ef2226eb7a33..187690fd1a5b 100644 --- a/drivers/usb/typec/altmodes/Kconfig +++ b/drivers/usb/typec/altmodes/Kconfig @@ -12,4 +12,14 @@ config TYPEC_DP_ALTMODE To compile this driver as a module, choose M here: the module will be called typec_displayport. +config TYPEC_NVIDIA_ALTMODE + tristate "NVIDIA Alternate Mode driver" + depends on TYPEC_DP_ALTMODE + help + Latest NVIDIA GPUs support VirtualLink devices. Select this + to enable support for VirtualLink devices with NVIDIA GPUs. + + To compile this driver as a module, choose M here: the + module will be called typec_displayport. + endmenu diff --git a/drivers/usb/typec/altmodes/Makefile b/drivers/usb/typec/altmodes/Makefile index eda8456f1c92..45717548b396 100644 --- a/drivers/usb/typec/altmodes/Makefile +++ b/drivers/usb/typec/altmodes/Makefile @@ -2,3 +2,5 @@ obj-$(CONFIG_TYPEC_DP_ALTMODE) += typec_displayport.o typec_displayport-y:= displayport.o +obj-$(CONFIG_TYPEC_NVIDIA_ALTMODE) += typec_nvidia.o +typec_nvidia-y := nvidia.o diff --git a/drivers/usb/typec/altmodes/nvidia.c b/drivers/usb/typec/altmodes/nvidia.c new file mode 100644 index ..c36769736405 --- /dev/null +++ b/drivers/usb/typec/altmodes/nvidia.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 NVIDIA Corporation. All rights reserved. + * + * NVIDIA USB Type-C Alt Mode Driver + */ +#include +#include +#include +#include "displayport.h" + +static int nvidia_altmode_probe(struct typec_altmode *alt) +{ + if (alt->svid == USB_TYPEC_NVIDIA_VLINK_SID) + return dp_altmode_probe(alt); + else + return -ENOTSUPP; +} + +static void nvidia_altmode_remove(struct typec_altmode *alt) +{ + if (alt->svid == USB_TYPEC_NVIDIA_VLINK_SID) + dp_altmode_remove(alt); +} + +static const struct typec_device_id nvidia_typec_id[] = { + { USB_TYPEC_NVIDIA_VLINK_SID, TYPEC_ANY_MODE }, + { }, +}; +MODULE_DEVICE_TABLE(typec, nvidia_typec_id); + +static struct typec_altmode_driver nvidia_altmode_driver = { + .id_table = nvidia_typec_id, + .probe = nvidia_altmode_probe, + .remove = nvidia_altmode_remove, + .driver = { + .name = "typec_nvidia", + .owner = THIS_MODULE, + }, +}; +module_typec_altmode_driver(nvidia_altmode_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("NVIDIA USB Type-C Alt Mode Driver"); diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 46feae074d8f..a8c8e66621ec 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -306,6 +306,7 @@ static int ucsi_register_altmode(struct ucsi_connector *con, switch (desc->svid) { case USB_TYPEC_DP_SID: + case USB_TYPEC_NVIDIA_VLINK_SID: alt = ucsi_register_displayport(con, override, i, desc); break; default: @@ -424,7 +425,8 @@ static void ucsi_unregister_altmodes(struct ucsi_connector *con, u8 recipient) while (adev[i]) { if (recipient == UCSI_RECIPIENT_SOP && - adev[i]->svid == USB_TYPEC_DP_SID) { + (adev[i]->svid == USB_TYPEC_DP_SID || + adev[i]->svid == USB_TYPEC_NVIDIA_VLINK_SID)) { pdev = typec_altmode_get_partner(adev[i]); ucsi_displayport_remove_partner((void *)pdev); } diff --git a/include/linux/usb/typec_dp.h b/include/linux/usb/typec_dp.h index 7fa12ef8d09a..fc4c7edb2e8a 100644 --- a/include/linux/usb/typec_dp.h +++ b/include/linux/usb/typec_dp.h @@ -5,6 +5,11 @@ #include #define USB_TYPEC_DP_SID 0xff01 +/* USB IF has not assigned a Standard ID (SID) for VirtualLink, + * so the manufacturers of VirtualLink adapters use their Vendor + * IDs as the SVID. + */ +#define USB_TYPEC_NVIDIA_VLINK_SID 0x955 /* NVIDIA VirtualLink */ #define USB_TYPEC_DP_MODE 1 /* -- 2.17.1
[PATCH 1/2] usb: typec: displayport: Export probe and remove functions
From: Heikki Krogerus VirtualLink standard extends the DisplayPort Alt Mode by utilizing also the USB 2 pins on the USB Type-C connector. It uses the same messages as DisplayPort, but not the DP SVID. At the time of writing, USB IF has not assigned a Standard ID (SID) for VirtualLink, so the manufacturers of VirtualLink adapters use their Vendor IDs as the SVID. Since the SVID specific communication is exactly the same as with DisplayPort alternate mode, there is no need to implement separate driver for VirtualLink. We'll handle the current VirtualLink adapters with probe drivers, and once there is SVID assigned for it, we add it to the displayport alt mode driver. To support probing drivers, exporting the probe and remove functions, and also changing the DP_HEADER helper macro to use the SVID of the alternate mode device instead of the DisplayPort alt mode SVID. [Fixed two warnings from checkpatch.pl script -Ajay] Signed-off-by: Heikki Krogerus Signed-off-by: Ajay Gupta Tested-by: Ajay Gupta --- drivers/usb/typec/altmodes/displayport.c | 12 +++- drivers/usb/typec/altmodes/displayport.h | 8 2 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 drivers/usb/typec/altmodes/displayport.h diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index 610d790bc9be..bbf317c838d3 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -14,7 +14,7 @@ #include #include -#define DP_HEADER(cmd) (VDO(USB_TYPEC_DP_SID, 1, cmd) | \ +#define DP_HEADER(_dp, cmd)(VDO((_dp)->alt->svid, 1, cmd) | \ VDO_OPOS(USB_TYPEC_DP_MODE)) enum { @@ -155,7 +155,7 @@ static int dp_altmode_configured(struct dp_altmode *dp) static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf) { - u32 header = DP_HEADER(DP_CMD_CONFIGURE); + u32 header = DP_HEADER(dp, DP_CMD_CONFIGURE); int ret; ret = typec_altmode_notify(dp->alt, TYPEC_STATE_SAFE, &dp->data); @@ -193,7 +193,7 @@ static void dp_altmode_work(struct work_struct *work) dev_err(&dp->alt->dev, "failed to enter mode\n"); break; case DP_STATE_UPDATE: - header = DP_HEADER(DP_CMD_STATUS_UPDATE); + header = DP_HEADER(dp, DP_CMD_STATUS_UPDATE); vdo = 1; ret = typec_altmode_vdm(dp->alt, header, &vdo, 2); if (ret) @@ -507,7 +507,7 @@ static const struct attribute_group dp_altmode_group = { .attrs = dp_altmode_attrs, }; -static int dp_altmode_probe(struct typec_altmode *alt) +int dp_altmode_probe(struct typec_altmode *alt) { const struct typec_altmode *port = typec_altmode_get_partner(alt); struct dp_altmode *dp; @@ -545,14 +545,16 @@ static int dp_altmode_probe(struct typec_altmode *alt) return 0; } +EXPORT_SYMBOL_GPL(dp_altmode_probe); -static void dp_altmode_remove(struct typec_altmode *alt) +void dp_altmode_remove(struct typec_altmode *alt) { struct dp_altmode *dp = typec_altmode_get_drvdata(alt); sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group); cancel_work_sync(&dp->work); } +EXPORT_SYMBOL_GPL(dp_altmode_remove); static const struct typec_device_id dp_typec_id[] = { { USB_TYPEC_DP_SID, USB_TYPEC_DP_MODE }, diff --git a/drivers/usb/typec/altmodes/displayport.h b/drivers/usb/typec/altmodes/displayport.h new file mode 100644 index ..e120364da9fd --- /dev/null +++ b/drivers/usb/typec/altmodes/displayport.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#if IS_ENABLED(CONFIG_TYPEC_DP_ALTMODE) +int dp_altmode_probe(struct typec_altmode *alt); +void dp_altmode_remove(struct typec_altmode *alt); +#else +int dp_altmode_probe(struct typec_altmode *alt) { return -ENOTSUPP; } +void dp_altmode_remove(struct typec_altmode *alt) { } +#endif /* CONFIG_TYPEC_DP_ALTMODE */ -- 2.17.1
[PATCH 0/2] Add VirtualLink display altmode support
Hi Heikki, Please help review these two changes which adds support for VirtualLink display altmode devices using NVIDIA GPU. You had shared the first patch during our offline discussion. The second patch adds NVIDIA display altmode driver. This set is created against latest Linus's kernel and patches at [1] forwarded to Greg from you. [1] https://marc.info/?l=linux-usb&m=155488414908414&w=2 Thanks Ajay Ajay Gupta (1): usb: typec: Add driver for NVIDIA Alt Modes Heikki Krogerus (1): usb: typec: displayport: Export probe and remove functions drivers/usb/typec/altmodes/Kconfig | 10 ++ drivers/usb/typec/altmodes/Makefile | 2 ++ drivers/usb/typec/altmodes/displayport.c | 12 --- drivers/usb/typec/altmodes/displayport.h | 8 + drivers/usb/typec/altmodes/nvidia.c | 44 drivers/usb/typec/ucsi/ucsi.c| 4 ++- include/linux/usb/typec_dp.h | 5 +++ 7 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 drivers/usb/typec/altmodes/displayport.h create mode 100644 drivers/usb/typec/altmodes/nvidia.c -- 2.17.1
Re: Kernel oops when using multiple V4L cameras on ODroid-C2 meson: 9600004f in dwc2_unmap_urb_for_dma+0x1c/0x28
Hi Minas, Thanks for your reply. I did some more playing with this, and found that I can cause kernel oops and reboot even with just one camera and by just probing it with v4l2-ctl. for each in `ls -1 /dev/video* /dev/v4l/by-id/* /dev/v4l/by-path/*`; do echo "scan: $each" v4l2-ctl --device $each --all | grep "H264" | grep "Pixel Format" done scan: /dev/v4l/by-id/usb-Sonix_Technology_Co.__Ltd._H264_USB_Camera_SN0001-video-index0 Message from syslogd@localhost at Apr 11 06:54:09 ... kernel:[ 142.777649] Internal error: Oops: 964f [#1] PREEMPT SMP I have attached the regdump output as a file captured just before running the v4l2-ctl command. Also, this is the output from dmesg --follow: [ 134.163768] usb 1-1.2: reset high-speed USB device number 3 using dwc2 [ 136.891628] usb 1-1.2: reset high-speed USB device number 3 using dwc2 [ 139.619463] usb 1-1.2: reset high-speed USB device number 3 using dwc2 [ 142.595299] usb 1-1.2: reset high-speed USB device number 3 using dwc2 [ 142.777478] Unable to handle kernel write to read-only memory at virtual address 80007e354ffe [ 142.777527] Mem abort info: [ 142.777538] ESR = 0x964f [ 142.777548] Exception class = DABT (current EL), IL = 32 bits [ 142.777556] SET = 0, FnV = 0 [ 142.777564] EA = 0, S1PTW = 0 [ 142.777571] Data abort info: [ 142.777579] ISV = 0, ISS = 0x004f [ 142.777594] CM = 0, WnR = 1 [ 142.777609] swapper pgtable: 4k pages, 48-bit VAs, pgdp = a5dbde96 [ 142.777626] [80007e354ffe] pgd=7fffa003, pud=7fe08003, pmd=7fc16003, pte=00e07e354793 [ 142.777649] Internal error: Oops: 964f [#1] PREEMPT SMP I hope this is helpful, thanks for your help! regards, Wayne On 4/5/19 1:56 AM, Minas Harutyunyan wrote: Hi Wayne, On 4/4/2019 10:27 PM, Wayne Piekarski wrote: Hi everyone, I have three USB H.264 cameras connected to an ODroid-C2 running a latest Armbian nightly build, with what appears to be kernel 5.0.5. When trying to access these cameras via V4L, I immediately get a kernel oops and the device reboots. It appears as though the problem occurs in dwc2_unmap_urb_for_dma+0x1c/0x28 which is in drivers/usb/dwc2. I'm not a kernel developer so not sure what other information I can provide apart from the oops dump. I can provide other information if needed. Could you please provide register dump (debugfs: regdump) before start playing and provide verbose debug log after start playing till oops. Which is speed of your camera? Did you connected directly to root hub? Thanks, Minas thanks! [ 204.624452] Internal error: Oops: 964f [#1] PREEMPT SMP [ 204.635515] Modules linked in: snd_soc_hdmi_codec dw_hdmi_i2s_audio dw_hdmi_cec meson_vdec uvcvideo videobuf2_dma_contig videobuf2_vmalloc v4l2_mem2mem videobuf2_memops lz4hc videobuf2_v4l2 lz4hc_compress ao_cec videobuf2_common meson_dw_hdmi meson_rng meson_ir dw_hdmi meson_drm rng_core rc_core videodev drm_kms_helper cec snd_soc_meson_aiu_spdif snd_soc_meson_aiu_i2s drm media meson_canvas snd_soc_meson_audio_core meson_gxbb_wdt drm_panel_orientation_quirks zram snd_usb_audio snd_soc_simple_card snd_hwdep snd_usbmidi_lib snd_soc_simple_card_utils snd_soc_core snd_rawmidi snd_seq_device snd_pcm_dmaengine snd_pcm snd_timer snd scpi_hwmon soundcore ip_tables x_tables realtek [ 204.728202] CPU: 2 PID: 0 Comm: swapper/2 Tainted: G W 5.0.5-meson64 #5.77.190401 [ 204.745037] Hardware name: Hardkernel ODROID-C2 (DT) [ 204.758748] pstate: 8005 (Nzcv daif -PAN -UAO) [ 204.772475] pc : __memcpy+0xa0/0x180 [ 204.786168] lr : dwc2_free_dma_aligned_buffer+0x78/0x80 [ 204.799988] sp : 10013da0 [ 204.813726] x29: 10013da0 x28: [ 204.827504] x27: 0038 x26: 10e960c0 [ 204.841198] x25: 0101 x24: 0020 [ 204.854820] x23: 10e9d000 x22: 80006b378594 [ 204.868394] x21: x20: 80006a124f79 [ 204.881902] x19: 80007e6f1800 x18: 0098090c [ 204.895494] x17: x16: [ 204.909050] x15: 014d x14: 0400 [ 204.922531] x13: x12: 0001 [ 204.935862] x11: 0047f7f9 x10: 0040 [ 204.948999] x9 : 0002 x8 : 10eb82a0 [ 204.962085] x7 : 0002 x6 : 80006a124f79 [ 204.975122] x5 : x4 : 00800200 [ 204.988041] x3 : 01f4 x2 : 0002 [ 205.000822] x1 : 80007edbf202 x0 : 80006a124f79 [ 205.013627] Process swapper/2 (pid: 0, stack limit = 0x35e14788) [ 205.027581] Call trace: [ 205.040442] __memcpy+0xa0/0x180 [ 205.053332] dwc2_unmap_urb_for_dma+0x1c/0x28 [ 205.066319] unmap_urb_for_dma+0x18/0x28 [ 205.079213] __usb_hcd_giveback_urb+0x38/0xe0 [ 205.092009] usb_giveback_urb_bh+0xac/0x108 [ 205.104753] tasklet_action_common.isra.2+0x7c/0x168 [ 205.117479] tasklet_action+0x24/0x30 [ 205.