i2c: ls2x: Fix frequency division register access

According to the chip manual, the I2C register access type of
Loongson-2K2000/LS7A is "B", so we can only access registers in byte
form (readb()/writeb()).

Although Loongson-2K0500/Loongson-2K1000 do not have similar
constraints, register accesses in byte form also behave correctly.

Also, in hardware, the frequency division registers are defined as two
separate registers (high 8-bit and low 8-bit), so we just access them
directly as bytes.

Fixes: 015e61f0bffd ("i2c: ls2x: Add driver for Loongson-2K/LS7A I2C controller")
Co-developed-by: Hongliang Wang <wanghongliang@loongson.cn>
Signed-off-by: Hongliang Wang <wanghongliang@loongson.cn>
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
Cc: stable@vger.kernel.org # v6.3+
Reviewed-by: Andy Shevchenko <andy@kernel.org>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Link: https://lore.kernel.org/r/20250220125612.1910990-1-zhoubinbin@loongson.cn

authored by Binbin Zhou and committed by Andi Shyti 71c49ee9 dd1998e2

+12 -4
+12 -4
drivers/i2c/busses/i2c-ls2x.c
··· 10 * Rewritten for mainline by Binbin Zhou <zhoubinbin@loongson.cn> 11 */ 12 13 #include <linux/bits.h> 14 #include <linux/completion.h> 15 #include <linux/device.h> ··· 27 #include <linux/units.h> 28 29 /* I2C Registers */ 30 - #define I2C_LS2X_PRER 0x0 /* Freq Division Register(16 bits) */ 31 #define I2C_LS2X_CTR 0x2 /* Control Register */ 32 #define I2C_LS2X_TXR 0x3 /* Transport Data Register */ 33 #define I2C_LS2X_RXR 0x3 /* Receive Data Register */ ··· 95 */ 96 static void ls2x_i2c_adjust_bus_speed(struct ls2x_i2c_priv *priv) 97 { 98 struct i2c_timings *t = &priv->i2c_t; 99 struct device *dev = priv->adapter.dev.parent; 100 u32 acpi_speed = i2c_acpi_find_bus_speed(dev); ··· 107 else 108 t->bus_freq_hz = LS2X_I2C_FREQ_STD; 109 110 - /* Calculate and set i2c frequency. */ 111 - writew(LS2X_I2C_PCLK_FREQ / (5 * t->bus_freq_hz) - 1, 112 - priv->base + I2C_LS2X_PRER); 113 } 114 115 static void ls2x_i2c_init(struct ls2x_i2c_priv *priv)
··· 10 * Rewritten for mainline by Binbin Zhou <zhoubinbin@loongson.cn> 11 */ 12 13 + #include <linux/bitfield.h> 14 #include <linux/bits.h> 15 #include <linux/completion.h> 16 #include <linux/device.h> ··· 26 #include <linux/units.h> 27 28 /* I2C Registers */ 29 + #define I2C_LS2X_PRER_LO 0x0 /* Freq Division Low Byte Register */ 30 + #define I2C_LS2X_PRER_HI 0x1 /* Freq Division High Byte Register */ 31 #define I2C_LS2X_CTR 0x2 /* Control Register */ 32 #define I2C_LS2X_TXR 0x3 /* Transport Data Register */ 33 #define I2C_LS2X_RXR 0x3 /* Receive Data Register */ ··· 93 */ 94 static void ls2x_i2c_adjust_bus_speed(struct ls2x_i2c_priv *priv) 95 { 96 + u16 val; 97 struct i2c_timings *t = &priv->i2c_t; 98 struct device *dev = priv->adapter.dev.parent; 99 u32 acpi_speed = i2c_acpi_find_bus_speed(dev); ··· 104 else 105 t->bus_freq_hz = LS2X_I2C_FREQ_STD; 106 107 + /* 108 + * According to the chip manual, we can only access the registers as bytes, 109 + * otherwise the high bits will be truncated. 110 + * So set the I2C frequency with a sequential writeb() instead of writew(). 111 + */ 112 + val = LS2X_I2C_PCLK_FREQ / (5 * t->bus_freq_hz) - 1; 113 + writeb(FIELD_GET(GENMASK(7, 0), val), priv->base + I2C_LS2X_PRER_LO); 114 + writeb(FIELD_GET(GENMASK(15, 8), val), priv->base + I2C_LS2X_PRER_HI); 115 } 116 117 static void ls2x_i2c_init(struct ls2x_i2c_priv *priv)