drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
Extension
.c
Size
5023 bytes
Lines
222
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 bb_info {
	struct mdiobb_ctrl ctrl;
	u32 __iomem *dir;
	u32 __iomem *dat;
	u32 mdio_msk;
	u32 mdc_msk;
};

/* FIXME: If any other users of GPIO crop up, then these will have to
 * have some sort of global synchronization to avoid races with other
 * pins on the same port.  The ideal solution would probably be to
 * bind the ports to a GPIO driver, and have this be a client of it.
 */
static inline void bb_set(u32 __iomem *p, u32 m)
{
	out_be32(p, in_be32(p) | m);
}

static inline void bb_clr(u32 __iomem *p, u32 m)
{
	out_be32(p, in_be32(p) & ~m);
}

static inline int bb_read(u32 __iomem *p, u32 m)
{
	return (in_be32(p) & m) != 0;
}

static inline void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
{
	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);

	if (dir)
		bb_set(bitbang->dir, bitbang->mdio_msk);
	else
		bb_clr(bitbang->dir, bitbang->mdio_msk);

	/* Read back to flush the write. */
	in_be32(bitbang->dir);
}

static inline int mdio_read(struct mdiobb_ctrl *ctrl)
{
	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
	return bb_read(bitbang->dat, bitbang->mdio_msk);
}

static inline void mdio(struct mdiobb_ctrl *ctrl, int what)
{
	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);

	if (what)
		bb_set(bitbang->dat, bitbang->mdio_msk);
	else
		bb_clr(bitbang->dat, bitbang->mdio_msk);

	/* Read back to flush the write. */
	in_be32(bitbang->dat);
}

static inline void mdc(struct mdiobb_ctrl *ctrl, int what)
{
	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);

	if (what)
		bb_set(bitbang->dat, bitbang->mdc_msk);
	else
		bb_clr(bitbang->dat, bitbang->mdc_msk);

	/* Read back to flush the write. */
	in_be32(bitbang->dat);
}

static const struct mdiobb_ops bb_ops = {
	.owner = THIS_MODULE,
	.set_mdc = mdc,
	.set_mdio_dir = mdio_dir,
	.set_mdio_data = mdio,
	.get_mdio_data = mdio_read,
};

static int fs_mii_bitbang_init(struct mii_bus *bus, struct device_node *np)
{
	struct resource res;
	const u32 *data;
	int mdio_pin, mdc_pin, len;
	struct bb_info *bitbang = bus->priv;

	int ret = of_address_to_resource(np, 0, &res);
	if (ret)

Annotation

Implementation Notes