drivers/net/can/m_can/tcan4x5x-core.c

Source file repositories/reference/linux-study-clean/drivers/net/can/m_can/tcan4x5x-core.c

File Facts

System
Linux kernel
Corpus path
drivers/net/can/m_can/tcan4x5x-core.c
Extension
.c
Size
15532 bytes
Lines
611
Domain
Driver Families
Bucket
drivers/net
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 tcan4x5x_version_info {
	const char *name;
	u32 id2_register;

	bool has_wake_pin;
	bool has_state_pin;
};

enum {
	TCAN4552 = 0,
	TCAN4553,
	TCAN4X5X,
};

static const struct tcan4x5x_version_info tcan4x5x_versions[] = {
	[TCAN4552] = {
		.name = "4552",
		.id2_register = 0x32353534,
	},
	[TCAN4553] = {
		.name = "4553",
		.id2_register = 0x33353534,
	},
	/* generic version with no id2_register at the end */
	[TCAN4X5X] = {
		.name = "generic",
		.has_wake_pin = true,
		.has_state_pin = true,
	},
};

static inline struct tcan4x5x_priv *cdev_to_priv(struct m_can_classdev *cdev)
{
	return container_of(cdev, struct tcan4x5x_priv, cdev);
}

static void tcan4x5x_check_wake(struct tcan4x5x_priv *priv)
{
	int wake_state = 0;

	if (priv->device_state_gpio)
		wake_state = gpiod_get_value(priv->device_state_gpio);

	if (priv->device_wake_gpio && wake_state) {
		gpiod_set_value(priv->device_wake_gpio, 0);
		usleep_range(5, 50);
		gpiod_set_value(priv->device_wake_gpio, 1);
	}
}

static int tcan4x5x_reset(struct tcan4x5x_priv *priv)
{
	int ret = 0;

	if (priv->reset_gpio) {
		gpiod_set_value(priv->reset_gpio, 1);

		/* tpulse_width minimum 30us */
		usleep_range(30, 100);
		gpiod_set_value(priv->reset_gpio, 0);
	} else {
		ret = regmap_write(priv->regmap, TCAN4X5X_CONFIG,
				   TCAN4X5X_SW_RESET);
		if (ret)
			return ret;
	}

	usleep_range(700, 1000);

	return ret;
}

static u32 tcan4x5x_read_reg(struct m_can_classdev *cdev, int reg)
{
	struct tcan4x5x_priv *priv = cdev_to_priv(cdev);
	u32 val;

	regmap_read(priv->regmap, TCAN4X5X_MCAN_OFFSET + reg, &val);

	return val;
}

static int tcan4x5x_read_fifo(struct m_can_classdev *cdev, int addr_offset,
			      void *val, size_t val_count)
{
	struct tcan4x5x_priv *priv = cdev_to_priv(cdev);

	return regmap_bulk_read(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, val, val_count);
}

Annotation

Implementation Notes