drivers/phy/phy-can-transceiver.c

Source file repositories/reference/linux-study-clean/drivers/phy/phy-can-transceiver.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/phy-can-transceiver.c
Extension
.c
Size
6804 bytes
Lines
248
Domain
Driver Families
Bucket
drivers/phy
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 can_transceiver_data {
	u32 flags;
#define CAN_TRANSCEIVER_STB_PRESENT	BIT(0)
#define CAN_TRANSCEIVER_EN_PRESENT	BIT(1)
#define CAN_TRANSCEIVER_DUAL_CH		BIT(2)
#define CAN_TRANSCEIVER_SILENT_PRESENT	BIT(3)
};

struct can_transceiver_phy {
	struct phy *generic_phy;
	struct gpio_desc *silent_gpio;
	struct gpio_desc *standby_gpio;
	struct gpio_desc *enable_gpio;
	struct can_transceiver_priv *priv;
};

struct can_transceiver_priv {
	struct mux_state *mux_state;
	int num_ch;
	struct can_transceiver_phy can_transceiver_phy[] __counted_by(num_ch);
};

/* Power on function */
static int can_transceiver_phy_power_on(struct phy *phy)
{
	struct can_transceiver_phy *can_transceiver_phy = phy_get_drvdata(phy);
	struct can_transceiver_priv *priv = can_transceiver_phy->priv;
	int ret;

	if (priv->mux_state) {
		ret = mux_state_select(priv->mux_state);
		if (ret) {
			dev_err(&phy->dev, "Failed to select CAN mux: %d\n", ret);
			return ret;
		}
	}
	gpiod_set_value_cansleep(can_transceiver_phy->silent_gpio, 0);
	gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 0);
	gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 1);

	return 0;
}

/* Power off function */
static int can_transceiver_phy_power_off(struct phy *phy)
{
	struct can_transceiver_phy *can_transceiver_phy = phy_get_drvdata(phy);
	struct can_transceiver_priv *priv = can_transceiver_phy->priv;

	gpiod_set_value_cansleep(can_transceiver_phy->silent_gpio, 1);
	gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 1);
	gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 0);
	if (priv->mux_state)
		mux_state_deselect(priv->mux_state);

	return 0;
}

static const struct phy_ops can_transceiver_phy_ops = {
	.power_on	= can_transceiver_phy_power_on,
	.power_off	= can_transceiver_phy_power_off,
	.owner		= THIS_MODULE,
};

static const struct can_transceiver_data tcan1042_drvdata = {
	.flags = CAN_TRANSCEIVER_STB_PRESENT,
};

static const struct can_transceiver_data tcan1043_drvdata = {
	.flags = CAN_TRANSCEIVER_STB_PRESENT | CAN_TRANSCEIVER_EN_PRESENT,
};

static const struct can_transceiver_data tja1048_drvdata = {
	.flags = CAN_TRANSCEIVER_STB_PRESENT | CAN_TRANSCEIVER_DUAL_CH,
};

static const struct can_transceiver_data tja1051_drvdata = {
	.flags = CAN_TRANSCEIVER_SILENT_PRESENT | CAN_TRANSCEIVER_EN_PRESENT,
};

static const struct can_transceiver_data tja1057_drvdata = {
	.flags = CAN_TRANSCEIVER_SILENT_PRESENT,
};

static const struct of_device_id can_transceiver_phy_ids[] = {
	{
		.compatible = "ti,tcan1042",
		.data = &tcan1042_drvdata
	},
	{

Annotation

Implementation Notes