Commit 37f071ec authored by Asmaa Mnebhi's avatar Asmaa Mnebhi Committed by Wolfram Sang

i2c: mlxbf: Fix frequency calculation

The i2c-mlxbf.c driver is currently broken because there is a bug
in the calculation of the frequency. core_f, core_r and core_od
are components read from hardware registers and are used to
compute the frequency used to compute different timing parameters.
The shifting mechanism used to get core_f, core_r and core_od is
wrong. Use FIELD_GET to mask and shift the bitfields properly.

Fixes: b5b5b320 (i2c: mlxbf: I2C SMBus driver for Mellanox BlueField SoC)
Reviewed-by: default avatarKhalil Blaiech <kblaiech@nvidia.com>
Signed-off-by: default avatarAsmaa Mnebhi <asmaa@nvidia.com>
Signed-off-by: default avatarWolfram Sang <wsa@kernel.org>
parent de24aceb
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
*/ */
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -63,13 +64,14 @@ ...@@ -63,13 +64,14 @@
*/ */
#define MLXBF_I2C_TYU_PLL_OUT_FREQ (400 * 1000 * 1000) #define MLXBF_I2C_TYU_PLL_OUT_FREQ (400 * 1000 * 1000)
/* Reference clock for Bluefield - 156 MHz. */ /* Reference clock for Bluefield - 156 MHz. */
#define MLXBF_I2C_PLL_IN_FREQ (156 * 1000 * 1000) #define MLXBF_I2C_PLL_IN_FREQ 156250000ULL
/* Constant used to determine the PLL frequency. */ /* Constant used to determine the PLL frequency. */
#define MLNXBF_I2C_COREPLL_CONST 16384 #define MLNXBF_I2C_COREPLL_CONST 16384ULL
#define MLXBF_I2C_FREQUENCY_1GHZ 1000000000ULL
/* PLL registers. */ /* PLL registers. */
#define MLXBF_I2C_CORE_PLL_REG0 0x0
#define MLXBF_I2C_CORE_PLL_REG1 0x4 #define MLXBF_I2C_CORE_PLL_REG1 0x4
#define MLXBF_I2C_CORE_PLL_REG2 0x8 #define MLXBF_I2C_CORE_PLL_REG2 0x8
...@@ -181,22 +183,15 @@ ...@@ -181,22 +183,15 @@
#define MLXBF_I2C_COREPLL_FREQ MLXBF_I2C_TYU_PLL_OUT_FREQ #define MLXBF_I2C_COREPLL_FREQ MLXBF_I2C_TYU_PLL_OUT_FREQ
/* Core PLL TYU configuration. */ /* Core PLL TYU configuration. */
#define MLXBF_I2C_COREPLL_CORE_F_TYU_MASK GENMASK(12, 0) #define MLXBF_I2C_COREPLL_CORE_F_TYU_MASK GENMASK(15, 3)
#define MLXBF_I2C_COREPLL_CORE_OD_TYU_MASK GENMASK(3, 0) #define MLXBF_I2C_COREPLL_CORE_OD_TYU_MASK GENMASK(19, 16)
#define MLXBF_I2C_COREPLL_CORE_R_TYU_MASK GENMASK(5, 0) #define MLXBF_I2C_COREPLL_CORE_R_TYU_MASK GENMASK(25, 20)
#define MLXBF_I2C_COREPLL_CORE_F_TYU_SHIFT 3
#define MLXBF_I2C_COREPLL_CORE_OD_TYU_SHIFT 16
#define MLXBF_I2C_COREPLL_CORE_R_TYU_SHIFT 20
/* Core PLL YU configuration. */ /* Core PLL YU configuration. */
#define MLXBF_I2C_COREPLL_CORE_F_YU_MASK GENMASK(25, 0) #define MLXBF_I2C_COREPLL_CORE_F_YU_MASK GENMASK(25, 0)
#define MLXBF_I2C_COREPLL_CORE_OD_YU_MASK GENMASK(3, 0) #define MLXBF_I2C_COREPLL_CORE_OD_YU_MASK GENMASK(3, 0)
#define MLXBF_I2C_COREPLL_CORE_R_YU_MASK GENMASK(5, 0) #define MLXBF_I2C_COREPLL_CORE_R_YU_MASK GENMASK(31, 26)
#define MLXBF_I2C_COREPLL_CORE_F_YU_SHIFT 0
#define MLXBF_I2C_COREPLL_CORE_OD_YU_SHIFT 1
#define MLXBF_I2C_COREPLL_CORE_R_YU_SHIFT 26
/* Core PLL frequency. */ /* Core PLL frequency. */
static u64 mlxbf_i2c_corepll_frequency; static u64 mlxbf_i2c_corepll_frequency;
...@@ -479,8 +474,6 @@ static struct mutex mlxbf_i2c_bus_lock; ...@@ -479,8 +474,6 @@ static struct mutex mlxbf_i2c_bus_lock;
#define MLXBF_I2C_MASK_8 GENMASK(7, 0) #define MLXBF_I2C_MASK_8 GENMASK(7, 0)
#define MLXBF_I2C_MASK_16 GENMASK(15, 0) #define MLXBF_I2C_MASK_16 GENMASK(15, 0)
#define MLXBF_I2C_FREQUENCY_1GHZ 1000000000
/* /*
* Function to poll a set of bits at a specific address; it checks whether * Function to poll a set of bits at a specific address; it checks whether
* the bits are equal to zero when eq_zero is set to 'true', and not equal * the bits are equal to zero when eq_zero is set to 'true', and not equal
...@@ -1410,24 +1403,19 @@ static int mlxbf_i2c_init_master(struct platform_device *pdev, ...@@ -1410,24 +1403,19 @@ static int mlxbf_i2c_init_master(struct platform_device *pdev,
return 0; return 0;
} }
static u64 mlxbf_calculate_freq_from_tyu(struct mlxbf_i2c_resource *corepll_res) static u64 mlxbf_i2c_calculate_freq_from_tyu(struct mlxbf_i2c_resource *corepll_res)
{ {
u64 core_frequency, pad_frequency; u64 core_frequency;
u8 core_od, core_r; u8 core_od, core_r;
u32 corepll_val; u32 corepll_val;
u16 core_f; u16 core_f;
pad_frequency = MLXBF_I2C_PLL_IN_FREQ;
corepll_val = readl(corepll_res->io + MLXBF_I2C_CORE_PLL_REG1); corepll_val = readl(corepll_res->io + MLXBF_I2C_CORE_PLL_REG1);
/* Get Core PLL configuration bits. */ /* Get Core PLL configuration bits. */
core_f = rol32(corepll_val, MLXBF_I2C_COREPLL_CORE_F_TYU_SHIFT) & core_f = FIELD_GET(MLXBF_I2C_COREPLL_CORE_F_TYU_MASK, corepll_val);
MLXBF_I2C_COREPLL_CORE_F_TYU_MASK; core_od = FIELD_GET(MLXBF_I2C_COREPLL_CORE_OD_TYU_MASK, corepll_val);
core_od = rol32(corepll_val, MLXBF_I2C_COREPLL_CORE_OD_TYU_SHIFT) & core_r = FIELD_GET(MLXBF_I2C_COREPLL_CORE_R_TYU_MASK, corepll_val);
MLXBF_I2C_COREPLL_CORE_OD_TYU_MASK;
core_r = rol32(corepll_val, MLXBF_I2C_COREPLL_CORE_R_TYU_SHIFT) &
MLXBF_I2C_COREPLL_CORE_R_TYU_MASK;
/* /*
* Compute PLL output frequency as follow: * Compute PLL output frequency as follow:
...@@ -1439,31 +1427,26 @@ static u64 mlxbf_calculate_freq_from_tyu(struct mlxbf_i2c_resource *corepll_res) ...@@ -1439,31 +1427,26 @@ static u64 mlxbf_calculate_freq_from_tyu(struct mlxbf_i2c_resource *corepll_res)
* Where PLL_OUT_FREQ and PLL_IN_FREQ refer to CoreFrequency * Where PLL_OUT_FREQ and PLL_IN_FREQ refer to CoreFrequency
* and PadFrequency, respectively. * and PadFrequency, respectively.
*/ */
core_frequency = pad_frequency * (++core_f); core_frequency = MLXBF_I2C_PLL_IN_FREQ * (++core_f);
core_frequency /= (++core_r) * (++core_od); core_frequency /= (++core_r) * (++core_od);
return core_frequency; return core_frequency;
} }
static u64 mlxbf_calculate_freq_from_yu(struct mlxbf_i2c_resource *corepll_res) static u64 mlxbf_i2c_calculate_freq_from_yu(struct mlxbf_i2c_resource *corepll_res)
{ {
u32 corepll_reg1_val, corepll_reg2_val; u32 corepll_reg1_val, corepll_reg2_val;
u64 corepll_frequency, pad_frequency; u64 corepll_frequency;
u8 core_od, core_r; u8 core_od, core_r;
u32 core_f; u32 core_f;
pad_frequency = MLXBF_I2C_PLL_IN_FREQ;
corepll_reg1_val = readl(corepll_res->io + MLXBF_I2C_CORE_PLL_REG1); corepll_reg1_val = readl(corepll_res->io + MLXBF_I2C_CORE_PLL_REG1);
corepll_reg2_val = readl(corepll_res->io + MLXBF_I2C_CORE_PLL_REG2); corepll_reg2_val = readl(corepll_res->io + MLXBF_I2C_CORE_PLL_REG2);
/* Get Core PLL configuration bits */ /* Get Core PLL configuration bits */
core_f = rol32(corepll_reg1_val, MLXBF_I2C_COREPLL_CORE_F_YU_SHIFT) & core_f = FIELD_GET(MLXBF_I2C_COREPLL_CORE_F_YU_MASK, corepll_reg1_val);
MLXBF_I2C_COREPLL_CORE_F_YU_MASK; core_r = FIELD_GET(MLXBF_I2C_COREPLL_CORE_R_YU_MASK, corepll_reg1_val);
core_r = rol32(corepll_reg1_val, MLXBF_I2C_COREPLL_CORE_R_YU_SHIFT) & core_od = FIELD_GET(MLXBF_I2C_COREPLL_CORE_OD_YU_MASK, corepll_reg2_val);
MLXBF_I2C_COREPLL_CORE_R_YU_MASK;
core_od = rol32(corepll_reg2_val, MLXBF_I2C_COREPLL_CORE_OD_YU_SHIFT) &
MLXBF_I2C_COREPLL_CORE_OD_YU_MASK;
/* /*
* Compute PLL output frequency as follow: * Compute PLL output frequency as follow:
...@@ -1475,7 +1458,7 @@ static u64 mlxbf_calculate_freq_from_yu(struct mlxbf_i2c_resource *corepll_res) ...@@ -1475,7 +1458,7 @@ static u64 mlxbf_calculate_freq_from_yu(struct mlxbf_i2c_resource *corepll_res)
* Where PLL_OUT_FREQ and PLL_IN_FREQ refer to CoreFrequency * Where PLL_OUT_FREQ and PLL_IN_FREQ refer to CoreFrequency
* and PadFrequency, respectively. * and PadFrequency, respectively.
*/ */
corepll_frequency = (pad_frequency * core_f) / MLNXBF_I2C_COREPLL_CONST; corepll_frequency = (MLXBF_I2C_PLL_IN_FREQ * core_f) / MLNXBF_I2C_COREPLL_CONST;
corepll_frequency /= (++core_r) * (++core_od); corepll_frequency /= (++core_r) * (++core_od);
return corepll_frequency; return corepll_frequency;
...@@ -2183,14 +2166,14 @@ static struct mlxbf_i2c_chip_info mlxbf_i2c_chip[] = { ...@@ -2183,14 +2166,14 @@ static struct mlxbf_i2c_chip_info mlxbf_i2c_chip[] = {
[1] = &mlxbf_i2c_corepll_res[MLXBF_I2C_CHIP_TYPE_1], [1] = &mlxbf_i2c_corepll_res[MLXBF_I2C_CHIP_TYPE_1],
[2] = &mlxbf_i2c_gpio_res[MLXBF_I2C_CHIP_TYPE_1] [2] = &mlxbf_i2c_gpio_res[MLXBF_I2C_CHIP_TYPE_1]
}, },
.calculate_freq = mlxbf_calculate_freq_from_tyu .calculate_freq = mlxbf_i2c_calculate_freq_from_tyu
}, },
[MLXBF_I2C_CHIP_TYPE_2] = { [MLXBF_I2C_CHIP_TYPE_2] = {
.type = MLXBF_I2C_CHIP_TYPE_2, .type = MLXBF_I2C_CHIP_TYPE_2,
.shared_res = { .shared_res = {
[0] = &mlxbf_i2c_corepll_res[MLXBF_I2C_CHIP_TYPE_2] [0] = &mlxbf_i2c_corepll_res[MLXBF_I2C_CHIP_TYPE_2]
}, },
.calculate_freq = mlxbf_calculate_freq_from_yu .calculate_freq = mlxbf_i2c_calculate_freq_from_yu
} }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment