drivers/net/ethernet/sunplus/spl2sw_mac.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/sunplus/spl2sw_mac.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/sunplus/spl2sw_mac.c
Extension
.c
Size
8954 bytes
Lines
275
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

// SPDX-License-Identifier: GPL-2.0
/* Copyright Sunplus Technology Co., Ltd.
 *       All rights reserved.
 */

#include <linux/platform_device.h>
#include <linux/netdevice.h>
#include <linux/bitfield.h>
#include <linux/of_mdio.h>

#include "spl2sw_register.h"
#include "spl2sw_define.h"
#include "spl2sw_desc.h"
#include "spl2sw_mac.h"

void spl2sw_mac_hw_stop(struct spl2sw_common *comm)
{
	u32 reg;

	if (comm->enable == 0) {
		/* Mask and clear all interrupts. */
		writel(0xffffffff, comm->l2sw_reg_base + L2SW_SW_INT_MASK_0);
		writel(0xffffffff, comm->l2sw_reg_base + L2SW_SW_INT_STATUS_0);

		/* Disable cpu 0 and cpu 1. */
		reg = readl(comm->l2sw_reg_base + L2SW_CPU_CNTL);
		reg |= MAC_DIS_SOC1_CPU | MAC_DIS_SOC0_CPU;
		writel(reg, comm->l2sw_reg_base + L2SW_CPU_CNTL);
	}

	/* Disable LAN ports. */
	reg = readl(comm->l2sw_reg_base + L2SW_PORT_CNTL0);
	reg |= FIELD_PREP(MAC_DIS_PORT, ~comm->enable);
	writel(reg, comm->l2sw_reg_base + L2SW_PORT_CNTL0);
}

void spl2sw_mac_hw_start(struct spl2sw_common *comm)
{
	u32 reg;

	/* Enable cpu port 0 (6) & CRC padding (8) */
	reg = readl(comm->l2sw_reg_base + L2SW_CPU_CNTL);
	reg &= ~MAC_DIS_SOC0_CPU;
	reg |= MAC_EN_CRC_SOC0;
	writel(reg, comm->l2sw_reg_base + L2SW_CPU_CNTL);

	/* Enable port 0 & port 1 */
	reg = readl(comm->l2sw_reg_base + L2SW_PORT_CNTL0);
	reg &= FIELD_PREP(MAC_DIS_PORT, ~comm->enable) | ~MAC_DIS_PORT;
	writel(reg, comm->l2sw_reg_base + L2SW_PORT_CNTL0);
}

int spl2sw_mac_addr_add(struct spl2sw_mac *mac)
{
	struct spl2sw_common *comm = mac->comm;
	u32 reg;
	int ret;

	/* Write 6-octet MAC address. */
	writel((mac->mac_addr[0] << 0) + (mac->mac_addr[1] << 8),
	       comm->l2sw_reg_base + L2SW_W_MAC_15_0);
	writel((mac->mac_addr[2] << 0) + (mac->mac_addr[3] << 8) +
	       (mac->mac_addr[4] << 16) + (mac->mac_addr[5] << 24),
	       comm->l2sw_reg_base + L2SW_W_MAC_47_16);

	/* Set learn port = cpu_port, aging = 1 */
	reg = MAC_W_CPU_PORT_0 | FIELD_PREP(MAC_W_VID, mac->vlan_id) |
	      FIELD_PREP(MAC_W_AGE, 1) | MAC_W_MAC_CMD;
	writel(reg, comm->l2sw_reg_base + L2SW_WT_MAC_AD0);

	/* Wait for completing. */
	ret = read_poll_timeout(readl, reg, reg & MAC_W_MAC_DONE, 1, 200, true,
				comm->l2sw_reg_base + L2SW_WT_MAC_AD0);
	if (ret) {
		netdev_err(mac->ndev, "Failed to add address to table!\n");
		return ret;
	}

	netdev_dbg(mac->ndev, "mac_ad0 = %08x, mac_ad = %08x%04x\n",
		   readl(comm->l2sw_reg_base + L2SW_WT_MAC_AD0),
		   (u32)FIELD_GET(MAC_W_MAC_47_16,
		   readl(comm->l2sw_reg_base + L2SW_W_MAC_47_16)),
		   (u32)FIELD_GET(MAC_W_MAC_15_0,
		   readl(comm->l2sw_reg_base + L2SW_W_MAC_15_0)));
	return 0;
}

int spl2sw_mac_addr_del(struct spl2sw_mac *mac)
{
	struct spl2sw_common *comm = mac->comm;

Annotation

Implementation Notes