i2c-fixes for v7.3-rc5

- qcom-geni: select the correct source clock table entry
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQScDfrjQa34uOld1VLaeAVmJtMtbgUCarjo1AAKCRDaeAVmJtMt
 bkwAAP9RaXfP3wNy+pcmfLXGDO1T3aG0ae4IdBQaGLAyvifmQAEA7Mlqctd1/6fY
 GpCVypBnha4BFoqhtV456RMnZHs2KgU=
 =0TbV
 -----END PGP SIGNATURE-----

Merge tag 'i2c-fixes-7.3-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux

Pull i2c fix from Andi Shyti:

 - qcom-geni: select the correct source clock table entry

* tag 'i2c-fixes-7.3-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux:
  i2c: qcom-geni: Fix hardcoded clock index in SE_GENI_CLK_SEL
This commit is contained in:
Linus Torvalds 2026-09-27 09:26:10 -07:00
commit 64d34cef2a

View File

@ -82,6 +82,9 @@ enum geni_i2c_err_code {
#define XFER_TIMEOUT HZ
#define RST_TIMEOUT HZ
#define GENI_SE_CLK_32MHZ (32 * HZ_PER_MHZ)
#define GENI_SE_CLK_19P2MHZ 19200000UL
struct geni_i2c_desc {
bool no_dma_support;
unsigned int tx_fifo_depth;
@ -127,6 +130,7 @@ struct geni_i2c_dev {
spinlock_t lock;
u32 clk_freq_out;
const struct geni_i2c_clk_fld *clk_fld;
u32 clk_idx;
void *dma_buf;
size_t xfer_len;
dma_addr_t dma_addr;
@ -197,19 +201,44 @@ static const struct geni_i2c_clk_fld geni_i2c_clk_map_32mhz[] = {
static int geni_i2c_clk_map_idx(struct geni_i2c_dev *gi2c)
{
const struct geni_i2c_clk_fld *itr;
unsigned long res_freq;
if (clk_get_rate(gi2c->se.clk) == 32 * HZ_PER_MHZ)
/*
* Frequency counter tables are calibrated for a specific source
* clock frequency and are not valid for any multiple of it
* (e.g. 64 MHz, 128 MHz).
* Use exact=true and verify res_freq matches req_freq literally
* to reject harmonics: a 64 MHz clock that divides evenly to
* 32 MHz would pass exact matching but produce double the intended
* I2C frequency with these counter values.
*/
if (!geni_se_clk_freq_match(&gi2c->se, GENI_SE_CLK_32MHZ,
&gi2c->clk_idx, &res_freq, true) &&
res_freq == GENI_SE_CLK_32MHZ) {
itr = geni_i2c_clk_map_32mhz;
else
} else if (!geni_se_clk_freq_match(&gi2c->se, GENI_SE_CLK_19P2MHZ,
&gi2c->clk_idx, &res_freq, true) &&
res_freq == GENI_SE_CLK_19P2MHZ) {
itr = geni_i2c_clk_map_19p2mhz;
} else {
dev_err(gi2c->se.dev,
"Unsupported SE source clock: must be exactly 32 MHz or 19.2 MHz\n");
return -EINVAL;
}
while (itr->clk_freq_out != 0) {
if (itr->clk_freq_out == gi2c->clk_freq_out) {
gi2c->clk_fld = itr;
dev_dbg(gi2c->se.dev,
"I2C clk selected: freq: %u Hz, clk_idx: %u\n",
gi2c->clk_freq_out, gi2c->clk_idx);
return 0;
}
itr++;
}
dev_err(gi2c->se.dev, "Unsupported I2C output frequency %u Hz\n", gi2c->clk_freq_out);
return -EINVAL;
}
@ -219,7 +248,7 @@ static int qcom_geni_i2c_conf(struct geni_se *se, unsigned long freq)
const struct geni_i2c_clk_fld *itr = gi2c->clk_fld;
u32 val;
writel_relaxed(0, gi2c->se.base + SE_GENI_CLK_SEL);
writel_relaxed(gi2c->clk_idx, gi2c->se.base + SE_GENI_CLK_SEL);
val = (itr->clk_div << CLK_DIV_SHFT) | SER_CLK_EN;
writel_relaxed(val, gi2c->se.base + GENI_SER_M_CLK_CFG);
@ -1111,8 +1140,7 @@ static int geni_i2c_resources_init(struct geni_se *se)
ret = geni_i2c_clk_map_idx(gi2c);
if (ret)
return dev_err_probe(gi2c->se.dev, ret, "Invalid clk frequency %d Hz\n",
gi2c->clk_freq_out);
return ret;
return geni_icc_set_bw_ab(&gi2c->se, GENI_DEFAULT_BW, GENI_DEFAULT_BW,
Bps_to_icc(gi2c->clk_freq_out));