Skip to content

Commit

Permalink
drivers: i2c: thunderx: octeontx2 clock divisor logic changes
Browse files Browse the repository at this point in the history
Handle changes to clock divisor logic for OcteonTX2 SoC family using
subsystem ID and using default reference clock source as 100MHz.

Signed-off-by: Suneel Garapati <sgarapati@marvell.com>
Signed-off-by: Piyush Malgujar <pmalgujar@marvell.com>
  • Loading branch information
Piyush Malgujar authored and intel-lab-lkp committed May 11, 2022
1 parent ef736ba commit 56654d2
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 3 deletions.
24 changes: 21 additions & 3 deletions drivers/i2c/busses/i2c-octeon-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>

#include "i2c-octeon-core.h"

Expand Down Expand Up @@ -658,7 +659,16 @@ int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
void octeon_i2c_set_clock(struct octeon_i2c *i2c)
{
int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff;
int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000;
/* starting value on search for lowest diff */
const int huge_delta = 1000000;
/*
* Find divisors to produce target frequency, start with large delta
* to cover wider range of divisors, note thp = TCLK half period.
*/
int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = huge_delta;

if (octeon_i2c_is_otx2(to_pci_dev(i2c->dev)))
thp = 0x3;

for (ndiv_idx = 0; ndiv_idx < 8 && delta_hz != 0; ndiv_idx++) {
/*
Expand All @@ -672,17 +682,25 @@ void octeon_i2c_set_clock(struct octeon_i2c *i2c)
*/
tclk = i2c->twsi_freq * (mdiv_idx + 1) * 10;
tclk *= (1 << ndiv_idx);
thp_base = (i2c->sys_freq / (tclk * 2)) - 1;
if (octeon_i2c_is_otx2(to_pci_dev(i2c->dev)))
thp_base = (i2c->sys_freq / tclk) - 2;
else
thp_base = (i2c->sys_freq / (tclk * 2)) - 1;

for (inc = 0; inc <= 1; inc++) {
thp_idx = thp_base + inc;
if (thp_idx < 5 || thp_idx > 0xff)
continue;

foscl = i2c->sys_freq / (2 * (thp_idx + 1));
if (octeon_i2c_is_otx2(to_pci_dev(i2c->dev)))
foscl = i2c->sys_freq / (thp_idx + 2);
else
foscl = i2c->sys_freq /
(2 * (thp_idx + 1));
foscl = foscl / (1 << ndiv_idx);
foscl = foscl / (mdiv_idx + 1) / 10;
diff = abs(foscl - i2c->twsi_freq);
/* Use it if smaller diff from target */
if (diff < delta_hz) {
delta_hz = diff;
thp = thp_idx;
Expand Down
14 changes: 14 additions & 0 deletions drivers/i2c/busses/i2c-octeon-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,20 @@ static inline void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data)
octeon_i2c_writeq_flush(data, i2c->twsi_base + TWSI_INT(i2c));
}

#define PCI_SUBSYS_DEVID_9XXX 0xB
/**
* octeon_i2c_is_otx2 - check for chip ID
* @pdev: PCI dev structure
*
* Returns TRUE if OcteonTX2, FALSE otherwise.
*/
static inline bool octeon_i2c_is_otx2(struct pci_dev *pdev)
{
u32 chip_id = (pdev->subsystem_device >> 12) & 0xF;

return (chip_id == PCI_SUBSYS_DEVID_9XXX);
}

/* Prototypes */
irqreturn_t octeon_i2c_isr(int irq, void *dev_id);
int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
Expand Down
6 changes: 6 additions & 0 deletions drivers/i2c/busses/i2c-thunderx-pcidrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,12 @@ static int thunder_i2c_probe_pci(struct pci_dev *pdev,
if (ret)
goto error;

/*
* For OcteonTX2 chips, set reference frequency to 100MHz
* as refclk_src in TWSI_MODE register defaults to 100MHz.
*/
if (octeon_i2c_is_otx2(pdev))
i2c->sys_freq = 100000000;
octeon_i2c_set_clock(i2c);

i2c->adap = thunderx_i2c_ops;
Expand Down

0 comments on commit 56654d2

Please sign in to comment.