Skip to content

Commit

Permalink
usb: typec: tcpci: support edge irq
Browse files Browse the repository at this point in the history
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>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Francesco Dolcini <francesco.dolcini@toradex.com>
Link: https://lore.kernel.org/r/20240905065328.7116-1-parth105105@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
eghidoli authored and gregkh committed Sep 11, 2024
1 parent 7793472 commit 77e8510
Showing 1 changed file with 20 additions and 10 deletions.
30 changes: 20 additions & 10 deletions drivers/usb/typec/tcpm/tcpci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -915,20 +923,22 @@ 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;
}

return 0;
/*
* 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);
enable_irq(client->irq);

return PTR_ERR_OR_ZERO(chip->tcpci);
}

static void tcpci_remove(struct i2c_client *client)
Expand Down

0 comments on commit 77e8510

Please sign in to comment.