i2c: riic: Add support for fast mode plus
authorClaudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Tue, 20 Aug 2024 10:19:15 +0000 (13:19 +0300)
committerAndi Shyti <andi.shyti@kernel.org>
Mon, 9 Sep 2024 22:34:02 +0000 (00:34 +0200)
Fast mode plus is available on most of the IP variants that RIIC driver
is working with. The exception is (according to HW manuals of the SoCs
where this IP is available) the Renesas RZ/A1H. For this, patch
introduces the struct riic_of_data::fast_mode_plus.

Fast mode plus was tested on RZ/G3S, RZ/G2{L,UL,LC}, RZ/Five by
instantiating the RIIC frequency to 1MHz and issuing i2c reads on the
fast mode plus capable devices (and the i2c clock frequency was checked on
RZ/G3S).

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
drivers/i2c/busses/i2c-riic.c

index f7293bf4b585942c6f4d4db55d6c9b3ccd044b6e..a6996f3c17110dd7ce9de67687971c8d3d3a0dad 100644 (file)
@@ -63,6 +63,8 @@
 #define ICMR3_ACKWP    0x10
 #define ICMR3_ACKBT    0x08
 
+#define ICFER_FMPE     0x80
+
 #define ICIER_TIE      0x80
 #define ICIER_TEIE     0x40
 #define ICIER_RIE      0x20
@@ -80,6 +82,7 @@ enum riic_reg_list {
        RIIC_ICCR2,
        RIIC_ICMR1,
        RIIC_ICMR3,
+       RIIC_ICFER,
        RIIC_ICSER,
        RIIC_ICIER,
        RIIC_ICSR2,
@@ -92,6 +95,7 @@ enum riic_reg_list {
 
 struct riic_of_data {
        const u8 *regs;
+       bool fast_mode_plus;
 };
 
 struct riic_dev {
@@ -311,11 +315,15 @@ static int riic_init_hw(struct riic_dev *riic)
        int total_ticks, cks, brl, brh;
        struct i2c_timings *t = &riic->i2c_t;
        struct device *dev = riic->adapter.dev.parent;
+       bool fast_mode_plus = riic->info->fast_mode_plus;
 
-       if (t->bus_freq_hz > I2C_MAX_FAST_MODE_FREQ) {
+       if ((!fast_mode_plus && t->bus_freq_hz > I2C_MAX_FAST_MODE_FREQ) ||
+           (fast_mode_plus && t->bus_freq_hz > I2C_MAX_FAST_MODE_PLUS_FREQ)) {
                dev_err(&riic->adapter.dev,
                        "unsupported bus speed (%dHz). %d max\n",
-                       t->bus_freq_hz, I2C_MAX_FAST_MODE_FREQ);
+                       t->bus_freq_hz,
+                       fast_mode_plus ? I2C_MAX_FAST_MODE_PLUS_FREQ :
+                                        I2C_MAX_FAST_MODE_FREQ);
                return -EINVAL;
        }
 
@@ -401,6 +409,9 @@ static int riic_init_hw(struct riic_dev *riic)
        riic_writeb(riic, 0, RIIC_ICSER);
        riic_writeb(riic, ICMR3_ACKWP | ICMR3_RDRFS, RIIC_ICMR3);
 
+       if (fast_mode_plus && t->bus_freq_hz > I2C_MAX_FAST_MODE_FREQ)
+               riic_clear_set_bit(riic, 0, ICFER_FMPE, RIIC_ICFER);
+
        riic_clear_set_bit(riic, ICCR1_IICRST, 0, RIIC_ICCR1);
 
        pm_runtime_mark_last_busy(dev);
@@ -527,6 +538,7 @@ static const u8 riic_rz_a_regs[RIIC_REG_END] = {
        [RIIC_ICCR2] = 0x04,
        [RIIC_ICMR1] = 0x08,
        [RIIC_ICMR3] = 0x10,
+       [RIIC_ICFER] = 0x14,
        [RIIC_ICSER] = 0x18,
        [RIIC_ICIER] = 0x1c,
        [RIIC_ICSR2] = 0x24,
@@ -538,6 +550,11 @@ 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,
+       .fast_mode_plus = true,
+};
+
+static const struct riic_of_data riic_rz_a1h_info = {
+       .regs = riic_rz_a_regs,
 };
 
 static const u8 riic_rz_v2h_regs[RIIC_REG_END] = {
@@ -545,6 +562,7 @@ static const u8 riic_rz_v2h_regs[RIIC_REG_END] = {
        [RIIC_ICCR2] = 0x01,
        [RIIC_ICMR1] = 0x02,
        [RIIC_ICMR3] = 0x04,
+       [RIIC_ICFER] = 0x05,
        [RIIC_ICSER] = 0x06,
        [RIIC_ICIER] = 0x07,
        [RIIC_ICSR2] = 0x09,
@@ -556,6 +574,7 @@ 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,
+       .fast_mode_plus = true,
 };
 
 static int riic_i2c_suspend(struct device *dev)
@@ -609,6 +628,7 @@ 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 */ },
 };