Skip to content

Commit 6d8ffbe

Browse files
Raviteja Narayanamwsakernel
authored andcommitted
i2c: xiic: Add SCL frequency configuration support
From 'clock-frequency' device tree property, configure I2C SCL frequency by calculating the timing register values according to input clock. After soft reset in reinit function, the timing registers are set to default values (configured in design tool). So, setting SCL frequency is done inside reinit function after the soft reset. This allows configuration of SCL frequency exclusively through software via device tree property, overriding the design. If the clock-frequency parameter is not specified in DT, driver doesn't configure frequency, making it backward compatible. Signed-off-by: Raviteja Narayanam <[email protected]> Signed-off-by: Manikanta Guntupalli <[email protected]> Acked-by: Michal Simek <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 9b97cd6 commit 6d8ffbe

File tree

1 file changed

+148
-0
lines changed

1 file changed

+148
-0
lines changed

drivers/i2c/busses/i2c-xiic.c

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ enum xiic_endian {
4646
BIG
4747
};
4848

49+
enum i2c_scl_freq {
50+
REG_VALUES_100KHZ = 0,
51+
REG_VALUES_400KHZ = 1,
52+
REG_VALUES_1MHZ = 2
53+
};
54+
4955
/**
5056
* struct xiic_i2c - Internal representation of the XIIC I2C bus
5157
* @dev: Pointer to device structure
@@ -66,6 +72,8 @@ enum xiic_endian {
6672
* @prev_msg_tx: Previous message is Tx
6773
* @quirks: To hold platform specific bug info
6874
* @smbus_block_read: Flag to handle block read
75+
* @input_clk: Input clock to I2C controller
76+
* @i2c_clk: I2C SCL frequency
6977
*/
7078
struct xiic_i2c {
7179
struct device *dev;
@@ -86,12 +94,37 @@ struct xiic_i2c {
8694
bool prev_msg_tx;
8795
u32 quirks;
8896
bool smbus_block_read;
97+
unsigned long input_clk;
98+
unsigned int i2c_clk;
8999
};
90100

91101
struct xiic_version_data {
92102
u32 quirks;
93103
};
94104

105+
/**
106+
* struct timing_regs - AXI I2C timing registers that depend on I2C spec
107+
* @tsusta: setup time for a repeated START condition
108+
* @tsusto: setup time for a STOP condition
109+
* @thdsta: hold time for a repeated START condition
110+
* @tsudat: setup time for data
111+
* @tbuf: bus free time between STOP and START
112+
*/
113+
struct timing_regs {
114+
unsigned int tsusta;
115+
unsigned int tsusto;
116+
unsigned int thdsta;
117+
unsigned int tsudat;
118+
unsigned int tbuf;
119+
};
120+
121+
/* Reg values in ns derived from I2C spec and AXI I2C PG for different frequencies */
122+
static const struct timing_regs timing_reg_values[] = {
123+
{ 5700, 5000, 4300, 550, 5000 }, /* Reg values for 100KHz */
124+
{ 900, 900, 900, 400, 1600 }, /* Reg values for 400KHz */
125+
{ 380, 380, 380, 170, 620 }, /* Reg values for 1MHz */
126+
};
127+
95128
#define XIIC_MSB_OFFSET 0
96129
#define XIIC_REG_OFFSET (0x100 + XIIC_MSB_OFFSET)
97130

@@ -110,6 +143,19 @@ struct xiic_version_data {
110143
#define XIIC_RFD_REG_OFFSET (0x20 + XIIC_REG_OFFSET) /* Rx FIFO Depth reg */
111144
#define XIIC_GPO_REG_OFFSET (0x24 + XIIC_REG_OFFSET) /* Output Register */
112145

146+
/*
147+
* Timing register offsets from RegisterBase. These are used only for
148+
* setting i2c clock frequency for the line.
149+
*/
150+
#define XIIC_TSUSTA_REG_OFFSET (0x28 + XIIC_REG_OFFSET) /* TSUSTA Register */
151+
#define XIIC_TSUSTO_REG_OFFSET (0x2C + XIIC_REG_OFFSET) /* TSUSTO Register */
152+
#define XIIC_THDSTA_REG_OFFSET (0x30 + XIIC_REG_OFFSET) /* THDSTA Register */
153+
#define XIIC_TSUDAT_REG_OFFSET (0x34 + XIIC_REG_OFFSET) /* TSUDAT Register */
154+
#define XIIC_TBUF_REG_OFFSET (0x38 + XIIC_REG_OFFSET) /* TBUF Register */
155+
#define XIIC_THIGH_REG_OFFSET (0x3C + XIIC_REG_OFFSET) /* THIGH Register */
156+
#define XIIC_TLOW_REG_OFFSET (0x40 + XIIC_REG_OFFSET) /* TLOW Register */
157+
#define XIIC_THDDAT_REG_OFFSET (0x44 + XIIC_REG_OFFSET) /* THDDAT Register */
158+
113159
/* Control Register masks */
114160
#define XIIC_CR_ENABLE_DEVICE_MASK 0x01 /* Device enable = 1 */
115161
#define XIIC_CR_TX_FIFO_RESET_MASK 0x02 /* Transmit FIFO reset=1 */
@@ -310,12 +356,102 @@ static int xiic_wait_tx_empty(struct xiic_i2c *i2c)
310356
return 0;
311357
}
312358

359+
/**
360+
* xiic_setclk - Sets the configured clock rate
361+
* @i2c: Pointer to the xiic device structure
362+
*
363+
* The timing register values are calculated according to the input clock
364+
* frequency and configured scl frequency. For details, please refer the
365+
* AXI I2C PG and NXP I2C Spec.
366+
* Supported frequencies are 100KHz, 400KHz and 1MHz.
367+
*
368+
* Return: 0 on success (Supported frequency selected or not configurable in SW)
369+
* -EINVAL on failure (scl frequency not supported or THIGH is 0)
370+
*/
371+
static int xiic_setclk(struct xiic_i2c *i2c)
372+
{
373+
unsigned int clk_in_mhz;
374+
unsigned int index = 0;
375+
u32 reg_val;
376+
377+
dev_dbg(i2c->adap.dev.parent,
378+
"%s entry, i2c->input_clk: %ld, i2c->i2c_clk: %d\n",
379+
__func__, i2c->input_clk, i2c->i2c_clk);
380+
381+
/* If not specified in DT, do not configure in SW. Rely only on Vivado design */
382+
if (!i2c->i2c_clk || !i2c->input_clk)
383+
return 0;
384+
385+
clk_in_mhz = DIV_ROUND_UP(i2c->input_clk, 1000000);
386+
387+
switch (i2c->i2c_clk) {
388+
case I2C_MAX_FAST_MODE_PLUS_FREQ:
389+
index = REG_VALUES_1MHZ;
390+
break;
391+
case I2C_MAX_FAST_MODE_FREQ:
392+
index = REG_VALUES_400KHZ;
393+
break;
394+
case I2C_MAX_STANDARD_MODE_FREQ:
395+
index = REG_VALUES_100KHZ;
396+
break;
397+
default:
398+
dev_warn(i2c->adap.dev.parent, "Unsupported scl frequency\n");
399+
return -EINVAL;
400+
}
401+
402+
/*
403+
* Value to be stored in a register is the number of clock cycles required
404+
* for the time duration. So the time is divided by the input clock time
405+
* period to get the number of clock cycles required. Refer Xilinx AXI I2C
406+
* PG document and I2C specification for further details.
407+
*/
408+
409+
/* THIGH - Depends on SCL clock frequency(i2c_clk) as below */
410+
reg_val = (DIV_ROUND_UP(i2c->input_clk, 2 * i2c->i2c_clk)) - 7;
411+
if (reg_val == 0)
412+
return -EINVAL;
413+
414+
xiic_setreg32(i2c, XIIC_THIGH_REG_OFFSET, reg_val - 1);
415+
416+
/* TLOW - Value same as THIGH */
417+
xiic_setreg32(i2c, XIIC_TLOW_REG_OFFSET, reg_val - 1);
418+
419+
/* TSUSTA */
420+
reg_val = (timing_reg_values[index].tsusta * clk_in_mhz) / 1000;
421+
xiic_setreg32(i2c, XIIC_TSUSTA_REG_OFFSET, reg_val - 1);
422+
423+
/* TSUSTO */
424+
reg_val = (timing_reg_values[index].tsusto * clk_in_mhz) / 1000;
425+
xiic_setreg32(i2c, XIIC_TSUSTO_REG_OFFSET, reg_val - 1);
426+
427+
/* THDSTA */
428+
reg_val = (timing_reg_values[index].thdsta * clk_in_mhz) / 1000;
429+
xiic_setreg32(i2c, XIIC_THDSTA_REG_OFFSET, reg_val - 1);
430+
431+
/* TSUDAT */
432+
reg_val = (timing_reg_values[index].tsudat * clk_in_mhz) / 1000;
433+
xiic_setreg32(i2c, XIIC_TSUDAT_REG_OFFSET, reg_val - 1);
434+
435+
/* TBUF */
436+
reg_val = (timing_reg_values[index].tbuf * clk_in_mhz) / 1000;
437+
xiic_setreg32(i2c, XIIC_TBUF_REG_OFFSET, reg_val - 1);
438+
439+
/* THDDAT */
440+
xiic_setreg32(i2c, XIIC_THDDAT_REG_OFFSET, 1);
441+
442+
return 0;
443+
}
444+
313445
static int xiic_reinit(struct xiic_i2c *i2c)
314446
{
315447
int ret;
316448

317449
xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK);
318450

451+
ret = xiic_setclk(i2c);
452+
if (ret)
453+
return ret;
454+
319455
/* Set receive Fifo depth to maximum (zero based). */
320456
xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1);
321457

@@ -1138,6 +1274,15 @@ static int xiic_i2c_probe(struct platform_device *pdev)
11381274
pm_runtime_use_autosuspend(i2c->dev);
11391275
pm_runtime_set_active(i2c->dev);
11401276
pm_runtime_enable(i2c->dev);
1277+
1278+
/* SCL frequency configuration */
1279+
i2c->input_clk = clk_get_rate(i2c->clk);
1280+
ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
1281+
&i2c->i2c_clk);
1282+
/* If clock-frequency not specified in DT, do not configure in SW */
1283+
if (ret || i2c->i2c_clk > I2C_MAX_FAST_MODE_PLUS_FREQ)
1284+
i2c->i2c_clk = 0;
1285+
11411286
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
11421287
xiic_process, IRQF_ONESHOT,
11431288
pdev->name, i2c);
@@ -1181,6 +1326,9 @@ static int xiic_i2c_probe(struct platform_device *pdev)
11811326
i2c_new_client_device(&i2c->adap, pdata->devices + i);
11821327
}
11831328

1329+
dev_dbg(&pdev->dev, "mmio %08lx irq %d scl clock frequency %d\n",
1330+
(unsigned long)res->start, irq, i2c->i2c_clk);
1331+
11841332
return 0;
11851333

11861334
err_clk_dis:

0 commit comments

Comments
 (0)