mirror of
https://github.com/torvalds/linux.git
synced 2026-10-23 15:32:04 +02:00
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:
commit
64d34cef2a
|
|
@ -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));
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user