drivers/net/ethernet/micrel/ks8851_par.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/micrel/ks8851_par.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/micrel/ks8851_par.c
Extension
.c
Size
9635 bytes
Lines
344
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 ks8851_net_par {
	struct ks8851_net	ks8851;
	spinlock_t		lock;
	void __iomem		*hw_addr;
	void __iomem		*hw_addr_cmd;
	u16			cmd_reg_cache;
};

#define to_ks8851_par(ks) container_of((ks), struct ks8851_net_par, ks8851)

/**
 * ks8851_lock_par - register access lock
 * @ks: The chip state
 *
 * Claim chip register access lock
 */
static void ks8851_lock_par(struct ks8851_net *ks)
{
	struct ks8851_net_par *ksp = to_ks8851_par(ks);

	spin_lock_bh(&ksp->lock);
}

/**
 * ks8851_unlock_par - register access unlock
 * @ks: The chip state
 *
 * Release chip register access lock
 */
static void ks8851_unlock_par(struct ks8851_net *ks)
{
	struct ks8851_net_par *ksp = to_ks8851_par(ks);

	spin_unlock_bh(&ksp->lock);
}

/**
 * ks_check_endian - Check whether endianness of the bus is correct
 * @ks	  : The chip information
 *
 * The KS8851-16MLL EESK pin allows selecting the endianness of the 16bit
 * bus. To maintain optimum performance, the bus endianness should be set
 * such that it matches the endianness of the CPU.
 */
static int ks_check_endian(struct ks8851_net *ks)
{
	struct ks8851_net_par *ksp = to_ks8851_par(ks);
	u16 cider;

	/*
	 * Read CIDER register first, however read it the "wrong" way around.
	 * If the endian strap on the KS8851-16MLL in incorrect and the chip
	 * is operating in different endianness than the CPU, then the meaning
	 * of BE[3:0] byte-enable bits is also swapped such that:
	 *    BE[3,2,1,0] becomes BE[1,0,3,2]
	 *
	 * Luckily for us, the byte-enable bits are the top four MSbits of
	 * the address register and the CIDER register is at offset 0xc0.
	 * Hence, by reading address 0xc0c0, which is not impacted by endian
	 * swapping, we assert either BE[3:2] or BE[1:0] while reading the
	 * CIDER register.
	 *
	 * If the bus configuration is correct, reading 0xc0c0 asserts
	 * BE[3:2] and this read returns 0x0000, because to read register
	 * with bottom two LSbits of address set to 0, BE[1:0] must be
	 * asserted.
	 *
	 * If the bus configuration is NOT correct, reading 0xc0c0 asserts
	 * BE[1:0] and this read returns non-zero 0x8872 value.
	 */
	iowrite16(BE3 | BE2 | KS_CIDER, ksp->hw_addr_cmd);
	cider = ioread16(ksp->hw_addr);
	if (!cider)
		return 0;

	netdev_err(ks->netdev, "incorrect EESK endian strap setting\n");

	return -EINVAL;
}

/**
 * ks8851_wrreg16_par - write 16bit register value to chip
 * @ks: The chip state
 * @reg: The register address
 * @val: The value to write
 *
 * Issue a write to put the value @val into the register specified in @reg.
 */
static void ks8851_wrreg16_par(struct ks8851_net *ks, unsigned int reg,
			       unsigned int val)

Annotation

Implementation Notes