Message ID | 20240828112058.479753-1-parth105105@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | usb: typec: tcpci: support edge irq | expand |
On Wed, Aug 28, 2024 at 01:20:58PM +0200, Parth Pancholi wrote: > From: Emanuele Ghidoli <emanuele.ghidoli@toradex.com> > > TCPCI USB PHY - PTN5110 could be used with SOCs that only support > the edge-triggered GPIO interrupts such as TI's K3 device AM69. > Move the interrupt configuration to the firmware which would > allow to accommodate edge triggered interrupts for such SOCs. > In order to support the edge interrupts, register irq line in advance > and keep track of occurrence during port registering. > > When the edge interrupts are used, it is observed that some of the > interrupts are missed when tcpci_irq() is serving the current > interrupt. Therefore, check the status register at the end of > tcpci_irq() and re-run the function if the status is not clear > i.e. pending interrupt. > > Signed-off-by: Emanuele Ghidoli <emanuele.ghidoli@toradex.com> > Signed-off-by: Parth Pancholi <parth.pancholi@toradex.com> > --- > drivers/usb/typec/tcpm/tcpci.c | 32 +++++++++++++++++++++++--------- > 1 file changed, 23 insertions(+), 9 deletions(-) > > diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c > index a2651a2a7f2e..4537c1d97e8f 100644 > --- a/drivers/usb/typec/tcpm/tcpci.c > +++ b/drivers/usb/typec/tcpm/tcpci.c ... > @@ -915,18 +923,24 @@ static int tcpci_probe(struct i2c_client *client) > > chip->data.set_orientation = err; > > - chip->tcpci = tcpci_register_port(&client->dev, &chip->data); > - if (IS_ERR(chip->tcpci)) > - return PTR_ERR(chip->tcpci); > - > err = devm_request_threaded_irq(&client->dev, client->irq, NULL, > _tcpci_irq, > - IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_LOW, > + IRQF_SHARED | IRQF_ONESHOT, > dev_name(&client->dev), chip); > - if (err < 0) { > - tcpci_unregister_port(chip->tcpci); > + if (err < 0) > return err; > - } > + > + /* > + * Disable irq while registering port. If irq is configured as an edge > + * irq this allow to keep track and process the irq as soon as it is enabled. > + */ > + disable_irq(client->irq); > + > + chip->tcpci = tcpci_register_port(&client->dev, &chip->data); > + if (IS_ERR(chip->tcpci)) > + return PTR_ERR(chip->tcpci); > + > + enable_irq(client->irq); If I undestand this correctly, if tcpci_register_port() fails the irq stays disabled. disable_irq(client->irq); chip->tcpci = tcpci_register_port(&client->dev, &chip->data); enable_irq(client->irq); return PTR_ERR_OR_ZERO(chip->tcpci); maybe? Francesco
diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index a2651a2a7f2e..4537c1d97e8f 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -707,10 +707,13 @@ irqreturn_t tcpci_irq(struct tcpci *tcpci) { u16 status; int ret; + int irq_ret; unsigned int raw; tcpci_read16(tcpci, TCPC_ALERT, &status); + irq_ret = status & tcpci->alert_mask; +process_status: /* * Clear alert status for everything except RX_STATUS, which shouldn't * be cleared until we have successfully retrieved message. @@ -783,7 +786,12 @@ irqreturn_t tcpci_irq(struct tcpci *tcpci) else if (status & TCPC_ALERT_TX_FAILED) tcpm_pd_transmit_complete(tcpci->port, TCPC_TX_FAILED); - return IRQ_RETVAL(status & tcpci->alert_mask); + tcpci_read16(tcpci, TCPC_ALERT, &status); + + if (status & tcpci->alert_mask) + goto process_status; + + return IRQ_RETVAL(irq_ret); } EXPORT_SYMBOL_GPL(tcpci_irq); @@ -915,18 +923,24 @@ static int tcpci_probe(struct i2c_client *client) chip->data.set_orientation = err; - chip->tcpci = tcpci_register_port(&client->dev, &chip->data); - if (IS_ERR(chip->tcpci)) - return PTR_ERR(chip->tcpci); - err = devm_request_threaded_irq(&client->dev, client->irq, NULL, _tcpci_irq, - IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_LOW, + IRQF_SHARED | IRQF_ONESHOT, dev_name(&client->dev), chip); - if (err < 0) { - tcpci_unregister_port(chip->tcpci); + if (err < 0) return err; - } + + /* + * Disable irq while registering port. If irq is configured as an edge + * irq this allow to keep track and process the irq as soon as it is enabled. + */ + disable_irq(client->irq); + + chip->tcpci = tcpci_register_port(&client->dev, &chip->data); + if (IS_ERR(chip->tcpci)) + return PTR_ERR(chip->tcpci); + + enable_irq(client->irq); return 0; }