diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-riic.c')
-rw-r--r-- | drivers/i2c/busses/i2c-riic.c | 54 |
1 files changed, 46 insertions, 8 deletions
diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index 23375f7fe3ad..9c164a4b9bb9 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c @@ -79,6 +79,7 @@ #define ICIER_SPIE BIT(3) #define ICSR2_NACKF BIT(4) +#define ICSR2_STOP BIT(3) #define ICBR_RESERVED GENMASK(7, 5) /* Should be 1 on writes */ @@ -102,6 +103,8 @@ enum riic_reg_list { struct riic_of_data { const u8 *regs; + const struct riic_irq_desc *irqs; + u8 num_irqs; bool fast_mode_plus; }; @@ -324,6 +327,19 @@ static irqreturn_t riic_stop_isr(int irq, void *data) return IRQ_HANDLED; } +static irqreturn_t riic_eei_isr(int irq, void *data) +{ + u8 icsr2 = riic_readb(data, RIIC_ICSR2); + + if (icsr2 & ICSR2_NACKF) + return riic_tend_isr(irq, data); + + if (icsr2 & ICSR2_STOP) + return riic_stop_isr(irq, data); + + return IRQ_NONE; +} + static u32 riic_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; @@ -495,6 +511,13 @@ static const struct riic_irq_desc riic_irqs[] = { { .res_num = 5, .isr = riic_tend_isr, .name = "riic-nack" }, }; +static const struct riic_irq_desc riic_rzt2h_irqs[] = { + { .res_num = 0, .isr = riic_eei_isr, .name = "riic-eei" }, + { .res_num = 1, .isr = riic_rdrf_isr, .name = "riic-rxi" }, + { .res_num = 2, .isr = riic_tdre_isr, .name = "riic-txi" }, + { .res_num = 3, .isr = riic_tend_isr, .name = "riic-tei" }, +}; + static int riic_i2c_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -520,21 +543,23 @@ static int riic_i2c_probe(struct platform_device *pdev) return dev_err_probe(dev, PTR_ERR(riic->rstc), "failed to acquire deasserted reset\n"); - for (i = 0; i < ARRAY_SIZE(riic_irqs); i++) { + riic->info = of_device_get_match_data(dev); + + for (i = 0; i < riic->info->num_irqs; i++) { + const struct riic_irq_desc *irq_desc; int irq; - irq = platform_get_irq(pdev, riic_irqs[i].res_num); + irq_desc = &riic->info->irqs[i]; + irq = platform_get_irq(pdev, irq_desc->res_num); if (irq < 0) return irq; - ret = devm_request_irq(dev, irq, riic_irqs[i].isr, - 0, riic_irqs[i].name, riic); + ret = devm_request_irq(dev, irq, irq_desc->isr, 0, irq_desc->name, riic); if (ret) return dev_err_probe(dev, ret, "failed to request irq %s\n", - riic_irqs[i].name); + irq_desc->name); } - riic->info = of_device_get_match_data(dev); adap = &riic->adapter; i2c_set_adapdata(adap, riic); @@ -606,11 +631,15 @@ static const u8 riic_rz_a_regs[RIIC_REG_END] = { static const struct riic_of_data riic_rz_a_info = { .regs = riic_rz_a_regs, + .irqs = riic_irqs, + .num_irqs = ARRAY_SIZE(riic_irqs), .fast_mode_plus = true, }; static const struct riic_of_data riic_rz_a1h_info = { .regs = riic_rz_a_regs, + .irqs = riic_irqs, + .num_irqs = ARRAY_SIZE(riic_irqs), }; static const u8 riic_rz_v2h_regs[RIIC_REG_END] = { @@ -630,9 +659,17 @@ static const u8 riic_rz_v2h_regs[RIIC_REG_END] = { static const struct riic_of_data riic_rz_v2h_info = { .regs = riic_rz_v2h_regs, + .irqs = riic_irqs, + .num_irqs = ARRAY_SIZE(riic_irqs), .fast_mode_plus = true, }; +static const struct riic_of_data riic_rz_t2h_info = { + .regs = riic_rz_v2h_regs, + .irqs = riic_rzt2h_irqs, + .num_irqs = ARRAY_SIZE(riic_rzt2h_irqs), +}; + static int riic_i2c_suspend(struct device *dev) { struct riic_dev *riic = dev_get_drvdata(dev); @@ -683,10 +720,11 @@ static const struct dev_pm_ops riic_i2c_pm_ops = { }; static const struct of_device_id riic_i2c_dt_ids[] = { - { .compatible = "renesas,riic-rz", .data = &riic_rz_a_info }, { .compatible = "renesas,riic-r7s72100", .data = &riic_rz_a1h_info, }, { .compatible = "renesas,riic-r9a09g057", .data = &riic_rz_v2h_info }, - { /* Sentinel */ }, + { .compatible = "renesas,riic-r9a09g077", .data = &riic_rz_t2h_info }, + { .compatible = "renesas,riic-rz", .data = &riic_rz_a_info }, + { /* Sentinel */ } }; static struct platform_driver riic_i2c_driver = { |