drivers/i2c/busses/i2c-designware-master.c

Source file repositories/reference/linux-study-clean/drivers/i2c/busses/i2c-designware-master.c

File Facts

System
Linux kernel
Corpus path
drivers/i2c/busses/i2c-designware-master.c
Extension
.c
Size
28478 bytes
Lines
1052
Domain
Driver Families
Bucket
drivers/i2c
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (dev->fp_hcnt && dev->fp_lcnt) {
			dev->fs_hcnt = dev->fp_hcnt;
			dev->fs_lcnt = dev->fp_lcnt;
		} else {
			ic_clk = i2c_dw_clk_rate(dev);
			dev->fs_hcnt =
				i2c_dw_scl_hcnt(dev,
						DW_IC_FS_SCL_HCNT,
						ic_clk,
						260,	/* tHIGH = 260 ns */
						sda_falling_time,
						0);	/* No offset */
			dev->fs_lcnt =
				i2c_dw_scl_lcnt(dev,
						DW_IC_FS_SCL_LCNT,
						ic_clk,
						500,	/* tLOW = 500 ns */
						scl_falling_time,
						0);	/* No offset */
		}
		fp_str = " Plus";
	}
	/*
	 * Calculate SCL timing parameters for fast mode if not set. They are
	 * needed also in high speed mode.
	 */
	if (!dev->fs_hcnt || !dev->fs_lcnt) {
		ic_clk = i2c_dw_clk_rate(dev);
		dev->fs_hcnt =
			i2c_dw_scl_hcnt(dev,
					DW_IC_FS_SCL_HCNT,
					ic_clk,
					600,	/* tHD;STA = tHIGH = 0.6 us */
					sda_falling_time,
					0);	/* No offset */
		dev->fs_lcnt =
			i2c_dw_scl_lcnt(dev,
					DW_IC_FS_SCL_LCNT,
					ic_clk,
					1300,	/* tLOW = 1.3 us */
					scl_falling_time,
					0);	/* No offset */
	}
	dev_dbg(dev->dev, "Fast Mode%s HCNT:LCNT = %d:%d\n",
		fp_str, dev->fs_hcnt, dev->fs_lcnt);

	/* Check is high speed possible and fall back to fast mode if not */
	if ((dev->master_cfg & DW_IC_CON_SPEED_MASK) ==
		DW_IC_CON_SPEED_HIGH) {
		if ((comp_param1 & DW_IC_COMP_PARAM_1_SPEED_MODE_MASK)
			!= DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH) {
			dev_err(dev->dev, "High Speed not supported!\n");
			t->bus_freq_hz = I2C_MAX_FAST_MODE_FREQ;
			dev->master_cfg &= ~DW_IC_CON_SPEED_MASK;
			dev->master_cfg |= DW_IC_CON_SPEED_FAST;
			dev->hs_hcnt = 0;
			dev->hs_lcnt = 0;
		} else if (!dev->hs_hcnt || !dev->hs_lcnt) {
			u32 t_high, t_low;

			/*
			 * The legal values stated in the databook for bus
			 * capacitance are only 100pF and 400pF.
			 * If dev->bus_capacitance_pF is greater than or equals
			 * to 400, t_high and t_low are assumed to be
			 * appropriate values for 400pF, otherwise 100pF.
			 */
			if (dev->bus_capacitance_pF >= 400) {
				/* assume bus capacitance is 400pF */
				t_high = dev->clk_freq_optimized ? 160 : 120;
				t_low = 320;
			} else {
				/* assume bus capacitance is 100pF */
				t_high = 60;
				t_low = dev->clk_freq_optimized ? 120 : 160;
			}

			ic_clk = i2c_dw_clk_rate(dev);
			dev->hs_hcnt =
				i2c_dw_scl_hcnt(dev,
						DW_IC_HS_SCL_HCNT,
						ic_clk,
						t_high,
						sda_falling_time,
						0);	/* No offset */
			dev->hs_lcnt =
				i2c_dw_scl_lcnt(dev,
						DW_IC_HS_SCL_LCNT,
						ic_clk,
						t_low,

Annotation

Implementation Notes