Skip to content

Commit

Permalink
i2c: pasemi: Add IRQ support for Apple Silicon
Browse files Browse the repository at this point in the history
This is the first time I'm interacting with the Linux mailing lists, so
please don't eviscerate me *too much* if I get the formatting wrong.
Of course I'm always willing to take criticism and improve my formatting
in the future.

This patch adds support for IRQs to the PASemi I2C controller driver.
This will allow for faster performing I2C transactions on Apple Silicon
hardware, as previously, the driver was forced to poll the SMSTA register
for a set amount of time.

With this patchset the driver on Apple silicon hardware will instead wait
for an interrupt which will signal the completion of the I2C transaction.
The timeout value for this completion will be the same as the current
amount of time the I2C driver polls for.

This will result in some performance improvement since the driver will be
waiting for less time than it does right now on Apple Silicon hardware.

The patch right now will only enable IRQs for Apple Silicon I2C chips,
and only if it's able to successfully request the IRQ from the kernel.

=== Testing ===

This patch has been tested on both the mainline Linux kernel tree and
the Asahi branch (https://github.com/AsahiLinux/linux.git) on both an
M1 and M2 MacBook Air, and it compiles successfully as both a module and
built-in to the kernel itself. The patch in both trees successfully boots
to userspace without any hitch.

I do not have PASemi hardware on hand unfortunately, so I'm unable to test
the impact of this patch on old PASemi hardware. This is also why I've
elected to do the IRQ request and enablement on the Apple platform driver
and not in the common file, as I'm not sure if PASemi hardware supports
IRQs.

I also fixed a quick checkpatch warning on line 303. "i ++" is now "i++".

Any and all critiques of the patch would be well appreciated.

Signed-off-by: Arminder Singh <arminders208@outlook.com>
  • Loading branch information
amarioguy authored and intel-lab-lkp committed Aug 20, 2022
1 parent 568035b commit 98584b2
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 5 deletions.
29 changes: 24 additions & 5 deletions drivers/i2c/busses/i2c-pasemi-core.c
Expand Up @@ -21,6 +21,7 @@
#define REG_MTXFIFO 0x00
#define REG_MRXFIFO 0x04
#define REG_SMSTA 0x14
#define REG_IMASK 0x18
#define REG_CTL 0x1c
#define REG_REV 0x28

Expand Down Expand Up @@ -80,14 +81,21 @@ static int pasemi_smb_waitready(struct pasemi_smbus *smbus)
{
int timeout = 10;
unsigned int status;
unsigned int bitmask = SMSTA_XEN | SMSTA_MTN;

status = reg_read(smbus, REG_SMSTA);

while (!(status & SMSTA_XEN) && timeout--) {
msleep(1);
if (smbus->use_irq) {
reinit_completion(&smbus->irq_completion);
reg_write(smbus, REG_IMASK, bitmask);
wait_for_completion_timeout(&smbus->irq_completion, msecs_to_jiffies(10));
status = reg_read(smbus, REG_SMSTA);
} else {
while (!(status & SMSTA_XEN) && timeout--) {
msleep(1);
status = reg_read(smbus, REG_SMSTA);
}
}


/* Got NACK? */
if (status & SMSTA_MTN)
return -ENXIO;
Expand Down Expand Up @@ -300,7 +308,7 @@ static int pasemi_smb_xfer(struct i2c_adapter *adapter,
case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_BLOCK_PROC_CALL:
data->block[0] = len;
for (i = 1; i <= len; i ++) {
for (i = 1; i <= len; i++) {
rd = RXFIFO_RD(smbus);
if (rd & MRXFIFO_EMPTY) {
err = -ENODATA;
Expand Down Expand Up @@ -348,6 +356,8 @@ int pasemi_i2c_common_probe(struct pasemi_smbus *smbus)
if (smbus->hw_rev != PASEMI_HW_REV_PCI)
smbus->hw_rev = reg_read(smbus, REG_REV);

reg_write(smbus, REG_IMASK, 0);

pasemi_reset(smbus);

error = devm_i2c_add_adapter(smbus->dev, &smbus->adapter);
Expand All @@ -356,3 +366,12 @@ int pasemi_i2c_common_probe(struct pasemi_smbus *smbus)

return 0;
}

irqreturn_t pasemi_irq_handler(int irq, void *dev_id)
{
struct pasemi_smbus *smbus = (struct pasemi_smbus *)dev_id;

reg_write(smbus, REG_IMASK, 0);
complete(&smbus->irq_completion);
return IRQ_HANDLED;
}
5 changes: 5 additions & 0 deletions drivers/i2c/busses/i2c-pasemi-core.h
Expand Up @@ -7,6 +7,7 @@
#include <linux/i2c-smbus.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/completion.h>

#define PASEMI_HW_REV_PCI -1

Expand All @@ -16,6 +17,10 @@ struct pasemi_smbus {
void __iomem *ioaddr;
unsigned int clk_div;
int hw_rev;
int use_irq;
struct completion irq_completion;
};

int pasemi_i2c_common_probe(struct pasemi_smbus *smbus);

irqreturn_t pasemi_irq_handler(int irq, void *dev_id);
8 changes: 8 additions & 0 deletions drivers/i2c/busses/i2c-pasemi-platform.c
Expand Up @@ -49,6 +49,7 @@ static int pasemi_platform_i2c_probe(struct platform_device *pdev)
struct pasemi_smbus *smbus;
u32 frequency;
int error;
int irq_num;

data = devm_kzalloc(dev, sizeof(struct pasemi_platform_i2c_data),
GFP_KERNEL);
Expand Down Expand Up @@ -82,6 +83,13 @@ static int pasemi_platform_i2c_probe(struct platform_device *pdev)
if (error)
goto out_clk_disable;

smbus->use_irq = 0;
init_completion(&smbus->irq_completion);
irq_num = platform_get_irq(pdev, 0);
error = request_irq(irq_num, pasemi_irq_handler, 0, "pasemi_apple_i2c", (void *)smbus);

if (!error)
smbus->use_irq = 1;
platform_set_drvdata(pdev, data);

return 0;
Expand Down

0 comments on commit 98584b2

Please sign in to comment.