drivers/i2c/busses/i2c-bcm-kona.c

Source file repositories/reference/linux-study-clean/drivers/i2c/busses/i2c-bcm-kona.c

File Facts

System
Linux kernel
Corpus path
drivers/i2c/busses/i2c-bcm-kona.c
Extension
.c
Size
22964 bytes
Lines
887
Domain
Driver Families
Bucket
drivers/i2c
Inferred role
Driver Families: implementation source
Status
source 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

struct bus_speed_cfg {
	uint8_t time_m;		/* Number of cycles for setup time */
	uint8_t time_n;		/* Number of cycles for hold time */
	uint8_t prescale;	/* Prescale divider */
	uint8_t time_p;		/* Timing coefficient */
	uint8_t no_div;		/* Disable clock divider */
	uint8_t time_div;	/* Post-prescale divider */
};

/* Internal divider settings for high-speed mode */
struct hs_bus_speed_cfg {
	uint8_t hs_hold;	/* Number of clock cycles SCL stays low until
				   the end of bit period */
	uint8_t hs_high_phase;	/* Number of clock cycles SCL stays high
				   before it falls */
	uint8_t hs_setup;	/* Number of clock cycles SCL stays low
				   before it rises  */
	uint8_t prescale;	/* Prescale divider */
	uint8_t time_p;		/* Timing coefficient */
	uint8_t no_div;		/* Disable clock divider */
	uint8_t time_div;	/* Post-prescale divider */
};

static const struct bus_speed_cfg std_cfg_table[] = {
	[BCM_SPD_100K] = {0x01, 0x01, 0x03, 0x06, 0x00, 0x02},
	[BCM_SPD_400K] = {0x05, 0x01, 0x03, 0x05, 0x01, 0x02},
	[BCM_SPD_1MHZ] = {0x01, 0x01, 0x03, 0x01, 0x01, 0x03},
};

static const struct hs_bus_speed_cfg hs_cfg_table[] = {
	[BCM_SPD_3P4MHZ] = {0x01, 0x08, 0x14, 0x00, 0x06, 0x01, 0x00},
};

struct bcm_kona_i2c_dev {
	struct device *device;

	void __iomem *base;
	int irq;
	struct clk *external_clk;

	struct i2c_adapter adapter;

	struct completion done;

	const struct bus_speed_cfg *std_cfg;
	const struct hs_bus_speed_cfg *hs_cfg;
};

static void bcm_kona_i2c_send_cmd_to_ctrl(struct bcm_kona_i2c_dev *dev,
					  enum bcm_kona_cmd_t cmd)
{
	dev_dbg(dev->device, "%s, %d\n", __func__, cmd);

	switch (cmd) {
	case BCM_CMD_NOACTION:
		writel((CS_CMD_CMD_NO_ACTION << CS_CMD_SHIFT) |
		       (CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT),
		       dev->base + CS_OFFSET);
		break;

	case BCM_CMD_START:
		writel((CS_ACK_CMD_GEN_START << CS_ACK_SHIFT) |
		       (CS_CMD_CMD_START_RESTART << CS_CMD_SHIFT) |
		       (CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT),
		       dev->base + CS_OFFSET);
		break;

	case BCM_CMD_RESTART:
		writel((CS_ACK_CMD_GEN_RESTART << CS_ACK_SHIFT) |
		       (CS_CMD_CMD_START_RESTART << CS_CMD_SHIFT) |
		       (CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT),
		       dev->base + CS_OFFSET);
		break;

	case BCM_CMD_STOP:
		writel((CS_CMD_CMD_STOP << CS_CMD_SHIFT) |
		       (CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT),
		       dev->base + CS_OFFSET);
		break;

	default:
		dev_err(dev->device, "Unknown command %d\n", cmd);
	}
}

static void bcm_kona_i2c_enable_clock(struct bcm_kona_i2c_dev *dev)
{
	writel(readl(dev->base + CLKEN_OFFSET) | CLKEN_CLKEN_MASK,
	       dev->base + CLKEN_OFFSET);
}

Annotation

Implementation Notes