drivers/net/can/c_can/c_can_platform.c

Source file repositories/reference/linux-study-clean/drivers/net/can/c_can/c_can_platform.c

File Facts

System
Linux kernel
Corpus path
drivers/net/can/c_can/c_can_platform.c
Extension
.c
Size
12280 bytes
Lines
470
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

if (timeout == 1000) {
			dev_err(&priv->dev->dev, "%s: time out\n", __func__);
			break;
		}
	} while ((ctrl & mask) != val);
}

static void c_can_hw_raminit_syscon(const struct c_can_priv *priv, bool enable)
{
	const struct c_can_raminit *raminit = &priv->raminit_sys;
	u32 ctrl = 0;
	u32 mask;

	spin_lock(&raminit_lock);

	mask = 1 << raminit->bits.start | 1 << raminit->bits.done;
	regmap_read(raminit->syscon, raminit->reg, &ctrl);

	/* We clear the start bit first. The start bit is
	 * looking at the 0 -> transition, but is not self clearing;
	 * NOTE: DONE must be written with 1 to clear it.
	 * We can't clear the DONE bit here using regmap_update_bits()
	 * as it will bypass the write if initial condition is START:0 DONE:1
	 * e.g. on DRA7 which needs START pulse.
	 */
	ctrl &= ~mask;	/* START = 0, DONE = 0 */
	regmap_update_bits(raminit->syscon, raminit->reg, mask, ctrl);

	/* check if START bit is 0. Ignore DONE bit for now
	 * as it can be either 0 or 1.
	 */
	c_can_hw_raminit_wait_syscon(priv, 1 << raminit->bits.start, ctrl);

	if (enable) {
		/* Clear DONE bit & set START bit. */
		ctrl |= 1 << raminit->bits.start;
		/* DONE must be written with 1 to clear it */
		ctrl |= 1 << raminit->bits.done;
		regmap_update_bits(raminit->syscon, raminit->reg, mask, ctrl);
		/* prevent further clearing of DONE bit */
		ctrl &= ~(1 << raminit->bits.done);
		/* clear START bit if start pulse is needed */
		if (raminit->needs_pulse) {
			ctrl &= ~(1 << raminit->bits.start);
			regmap_update_bits(raminit->syscon, raminit->reg,
					   mask, ctrl);
		}

		ctrl |= 1 << raminit->bits.done;
		c_can_hw_raminit_wait_syscon(priv, mask, ctrl);
	}
	spin_unlock(&raminit_lock);
}

static u32 c_can_plat_read_reg32(const struct c_can_priv *priv, enum reg index)
{
	u32 val;

	val = priv->read_reg(priv, index);
	val |= ((u32)priv->read_reg(priv, index + 1)) << 16;

	return val;
}

static void c_can_plat_write_reg32(const struct c_can_priv *priv,
				   enum reg index, u32 val)
{
	priv->write_reg(priv, index + 1, val >> 16);
	priv->write_reg(priv, index, val);
}

static u32 d_can_plat_read_reg32(const struct c_can_priv *priv, enum reg index)
{
	return readl(priv->base + priv->regs[index]);
}

static void d_can_plat_write_reg32(const struct c_can_priv *priv,
				   enum reg index, u32 val)
{
	writel(val, priv->base + priv->regs[index]);
}

static void c_can_hw_raminit_wait(const struct c_can_priv *priv, u32 mask)
{
	while (priv->read_reg32(priv, C_CAN_FUNCTION_REG) & mask)
		udelay(1);
}

static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable)
{

Annotation

Implementation Notes