generic: ar8216: add support for ar8229
ar8229 is the builtin switch in ar934x and later chips. There is also a standalone version available and their registers/functions are the same. This commit added support for the builtin ar8229. The only thing missing for standalone ar8229 should be phy modes. Since I don't have a router using that, this commit doesn't add support for other phy modes. Only add its support for mdio-device probing method because the current PHY probing can't return 1G speed when it's a FE switch. Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
This commit is contained in:
		 Chuanhong Guo
					Chuanhong Guo
				
			
				
					committed by
					
						 Petr Štetiar
						Petr Štetiar
					
				
			
			
				
	
			
			
			 Petr Štetiar
						Petr Štetiar
					
				
			
						parent
						
							7d504f68a6
						
					
				
				
					commit
					cb7d96499c
				
			| @@ -25,6 +25,7 @@ | |||||||
| #include <linux/netlink.h> | #include <linux/netlink.h> | ||||||
| #include <linux/of_device.h> | #include <linux/of_device.h> | ||||||
| #include <linux/of_mdio.h> | #include <linux/of_mdio.h> | ||||||
|  | #include <linux/of_net.h> | ||||||
| #include <linux/bitops.h> | #include <linux/bitops.h> | ||||||
| #include <net/genetlink.h> | #include <net/genetlink.h> | ||||||
| #include <linux/switch.h> | #include <linux/switch.h> | ||||||
| @@ -715,7 +716,8 @@ ar8216_init_globals(struct ar8xxx_priv *priv) | |||||||
| } | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
| ar8216_init_port(struct ar8xxx_priv *priv, int port) | __ar8216_init_port(struct ar8xxx_priv *priv, int port, | ||||||
|  | 		   bool cpu_ge, bool flow_en) | ||||||
| { | { | ||||||
| 	/* Enable port learning and tx */ | 	/* Enable port learning and tx */ | ||||||
| 	ar8xxx_write(priv, AR8216_REG_PORT_CTRL(port), | 	ar8xxx_write(priv, AR8216_REG_PORT_CTRL(port), | ||||||
| @@ -727,12 +729,11 @@ ar8216_init_port(struct ar8xxx_priv *priv, int port) | |||||||
| 	if (port == AR8216_PORT_CPU) { | 	if (port == AR8216_PORT_CPU) { | ||||||
| 		ar8xxx_write(priv, AR8216_REG_PORT_STATUS(port), | 		ar8xxx_write(priv, AR8216_REG_PORT_STATUS(port), | ||||||
| 			AR8216_PORT_STATUS_LINK_UP | | 			AR8216_PORT_STATUS_LINK_UP | | ||||||
| 			(ar8xxx_has_gige(priv) ? | 			(cpu_ge ? AR8216_PORT_SPEED_1000M : AR8216_PORT_SPEED_100M) | | ||||||
|                                 AR8216_PORT_SPEED_1000M : AR8216_PORT_SPEED_100M) | |  | ||||||
| 			AR8216_PORT_STATUS_TXMAC | | 			AR8216_PORT_STATUS_TXMAC | | ||||||
| 			AR8216_PORT_STATUS_RXMAC | | 			AR8216_PORT_STATUS_RXMAC | | ||||||
| 			(chip_is_ar8316(priv) ? AR8216_PORT_STATUS_RXFLOW : 0) | | 			(flow_en ? AR8216_PORT_STATUS_RXFLOW : 0) | | ||||||
| 			(chip_is_ar8316(priv) ? AR8216_PORT_STATUS_TXFLOW : 0) | | 			(flow_en ? AR8216_PORT_STATUS_TXFLOW : 0) | | ||||||
| 			AR8216_PORT_STATUS_DUPLEX); | 			AR8216_PORT_STATUS_DUPLEX); | ||||||
| 	} else { | 	} else { | ||||||
| 		ar8xxx_write(priv, AR8216_REG_PORT_STATUS(port), | 		ar8xxx_write(priv, AR8216_REG_PORT_STATUS(port), | ||||||
| @@ -740,6 +741,13 @@ ar8216_init_port(struct ar8xxx_priv *priv, int port) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | ar8216_init_port(struct ar8xxx_priv *priv, int port) | ||||||
|  | { | ||||||
|  | 	__ar8216_init_port(priv, port, ar8xxx_has_gige(priv), | ||||||
|  | 			   chip_is_ar8316(priv)); | ||||||
|  | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
| ar8216_wait_atu_ready(struct ar8xxx_priv *priv, u16 r2, u16 r1) | ar8216_wait_atu_ready(struct ar8xxx_priv *priv, u16 r2, u16 r1) | ||||||
| { | { | ||||||
| @@ -807,6 +815,85 @@ static void ar8216_get_arl_entry(struct ar8xxx_priv *priv, | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int | ||||||
|  | ar8229_hw_init(struct ar8xxx_priv *priv) | ||||||
|  | { | ||||||
|  | 	int phy_if_mode; | ||||||
|  |  | ||||||
|  | 	if (priv->initialized) | ||||||
|  | 		return 0; | ||||||
|  |  | ||||||
|  | 	ar8xxx_write(priv, AR8216_REG_CTRL, AR8216_CTRL_RESET); | ||||||
|  | 	ar8xxx_reg_wait(priv, AR8216_REG_CTRL, AR8216_CTRL_RESET, 0, 1000); | ||||||
|  |  | ||||||
|  | 	phy_if_mode = of_get_phy_mode(priv->pdev->of_node); | ||||||
|  |  | ||||||
|  | 	if (phy_if_mode == PHY_INTERFACE_MODE_GMII) { | ||||||
|  | 		ar8xxx_write(priv, AR8229_REG_OPER_MODE0, | ||||||
|  | 				 AR8229_OPER_MODE0_MAC_GMII_EN); | ||||||
|  | 	} else if (phy_if_mode == PHY_INTERFACE_MODE_MII) { | ||||||
|  | 		ar8xxx_write(priv, AR8229_REG_OPER_MODE0, | ||||||
|  | 				 AR8229_OPER_MODE0_PHY_MII_EN); | ||||||
|  | 	} else { | ||||||
|  | 		pr_err("ar8229: unsupported mii mode\n"); | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (priv->port4_phy) | ||||||
|  | 		ar8xxx_write(priv, AR8229_REG_OPER_MODE1, | ||||||
|  | 			     AR8229_REG_OPER_MODE1_PHY4_MII_EN); | ||||||
|  |  | ||||||
|  | 	ar8xxx_phy_init(priv); | ||||||
|  |  | ||||||
|  | 	priv->initialized = true; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | ar8229_init_globals(struct ar8xxx_priv *priv) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | 	/* Enable CPU port, and disable mirror port */ | ||||||
|  | 	ar8xxx_write(priv, AR8216_REG_GLOBAL_CPUPORT, | ||||||
|  | 		     AR8216_GLOBAL_CPUPORT_EN | | ||||||
|  | 		     (15 << AR8216_GLOBAL_CPUPORT_MIRROR_PORT_S)); | ||||||
|  |  | ||||||
|  | 	/* Setup TAG priority mapping */ | ||||||
|  | 	ar8xxx_write(priv, AR8216_REG_TAG_PRIORITY, 0xfa50); | ||||||
|  |  | ||||||
|  | 	/* Enable aging, MAC replacing */ | ||||||
|  | 	ar8xxx_write(priv, AR8216_REG_ATU_CTRL, | ||||||
|  | 		     0x2b /* 5 min age time */ | | ||||||
|  | 		     AR8216_ATU_CTRL_AGE_EN | | ||||||
|  | 		     AR8216_ATU_CTRL_LEARN_CHANGE); | ||||||
|  |  | ||||||
|  | 	/* Enable ARP frame acknowledge */ | ||||||
|  | 	ar8xxx_reg_set(priv, AR8229_REG_QM_CTRL, | ||||||
|  | 		       AR8229_QM_CTRL_ARP_EN); | ||||||
|  |  | ||||||
|  | 	/* Enable Broadcast/Multicast frames transmitted to the CPU */ | ||||||
|  | 	ar8xxx_reg_set(priv, AR8216_REG_FLOOD_MASK, | ||||||
|  | 		       AR8229_FLOOD_MASK_BC_DP(0) | | ||||||
|  | 		       AR8229_FLOOD_MASK_MC_DP(0)); | ||||||
|  |  | ||||||
|  | 	/* setup MTU */ | ||||||
|  | 	ar8xxx_rmw(priv, AR8216_REG_GLOBAL_CTRL, | ||||||
|  | 		   AR8236_GCTRL_MTU, AR8236_GCTRL_MTU); | ||||||
|  |  | ||||||
|  | 	/* Enable MIB counters */ | ||||||
|  | 	ar8xxx_reg_set(priv, AR8216_REG_MIB_FUNC, | ||||||
|  | 		       AR8236_MIB_EN); | ||||||
|  |  | ||||||
|  | 	/* setup Service TAG */ | ||||||
|  | 	ar8xxx_rmw(priv, AR8216_REG_SERVICE_TAG, AR8216_SERVICE_TAG_M, 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | ar8229_init_port(struct ar8xxx_priv *priv, int port) | ||||||
|  | { | ||||||
|  | 	__ar8216_init_port(priv, port, true, true); | ||||||
|  | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
| ar8236_setup_port(struct ar8xxx_priv *priv, int port, u32 members) | ar8236_setup_port(struct ar8xxx_priv *priv, int port, u32 members) | ||||||
| { | { | ||||||
| @@ -1753,6 +1840,36 @@ static const struct ar8xxx_chip ar8216_chip = { | |||||||
| 	.mib_func = AR8216_REG_MIB_FUNC | 	.mib_func = AR8216_REG_MIB_FUNC | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | static const struct ar8xxx_chip ar8229_chip = { | ||||||
|  | 	.caps = AR8XXX_CAP_MIB_COUNTERS, | ||||||
|  |  | ||||||
|  | 	.reg_port_stats_start = 0x20000, | ||||||
|  | 	.reg_port_stats_length = 0x100, | ||||||
|  | 	.reg_arl_ctrl = AR8216_REG_ATU_CTRL, | ||||||
|  |  | ||||||
|  | 	.name = "Atheros AR8229", | ||||||
|  | 	.ports = AR8216_NUM_PORTS, | ||||||
|  | 	.vlans = AR8216_NUM_VLANS, | ||||||
|  | 	.swops = &ar8xxx_sw_ops, | ||||||
|  |  | ||||||
|  | 	.hw_init = ar8229_hw_init, | ||||||
|  | 	.init_globals = ar8229_init_globals, | ||||||
|  | 	.init_port = ar8229_init_port, | ||||||
|  | 	.setup_port = ar8236_setup_port, | ||||||
|  | 	.read_port_status = ar8216_read_port_status, | ||||||
|  | 	.atu_flush = ar8216_atu_flush, | ||||||
|  | 	.atu_flush_port = ar8216_atu_flush_port, | ||||||
|  | 	.vtu_flush = ar8216_vtu_flush, | ||||||
|  | 	.vtu_load_vlan = ar8216_vtu_load_vlan, | ||||||
|  | 	.set_mirror_regs = ar8216_set_mirror_regs, | ||||||
|  | 	.get_arl_entry = ar8216_get_arl_entry, | ||||||
|  | 	.sw_hw_apply = ar8xxx_sw_hw_apply, | ||||||
|  |  | ||||||
|  | 	.num_mibs = ARRAY_SIZE(ar8236_mibs), | ||||||
|  | 	.mib_decs = ar8236_mibs, | ||||||
|  | 	.mib_func = AR8216_REG_MIB_FUNC | ||||||
|  | }; | ||||||
|  |  | ||||||
| static const struct ar8xxx_chip ar8236_chip = { | static const struct ar8xxx_chip ar8236_chip = { | ||||||
| 	.caps = AR8XXX_CAP_MIB_COUNTERS, | 	.caps = AR8XXX_CAP_MIB_COUNTERS, | ||||||
|  |  | ||||||
| @@ -2336,6 +2453,9 @@ static struct phy_driver ar8xxx_phy_driver[] = { | |||||||
|  |  | ||||||
| static const struct of_device_id ar8xxx_mdiodev_of_match[] = { | static const struct of_device_id ar8xxx_mdiodev_of_match[] = { | ||||||
| 	{ | 	{ | ||||||
|  | 		.compatible = "qca,ar8229", | ||||||
|  | 		.data = &ar8229_chip, | ||||||
|  | 	}, { | ||||||
| 		.compatible = "qca,ar8236", | 		.compatible = "qca,ar8236", | ||||||
| 		.data = &ar8236_chip, | 		.data = &ar8236_chip, | ||||||
| 	}, { | 	}, { | ||||||
|   | |||||||
| @@ -52,6 +52,8 @@ | |||||||
| #define AR8216_REG_FLOOD_MASK		0x002C | #define AR8216_REG_FLOOD_MASK		0x002C | ||||||
| #define   AR8216_FM_UNI_DEST_PORTS	BITS(0, 6) | #define   AR8216_FM_UNI_DEST_PORTS	BITS(0, 6) | ||||||
| #define   AR8216_FM_MULTI_DEST_PORTS	BITS(16, 6) | #define   AR8216_FM_MULTI_DEST_PORTS	BITS(16, 6) | ||||||
|  | #define   AR8229_FLOOD_MASK_MC_DP(_p)	BIT(16 + (_p)) | ||||||
|  | #define   AR8229_FLOOD_MASK_BC_DP(_p)	BIT(25 + (_p)) | ||||||
| #define   AR8236_FM_CPU_BROADCAST_EN	BIT(26) | #define   AR8236_FM_CPU_BROADCAST_EN	BIT(26) | ||||||
| #define   AR8236_FM_CPU_BCAST_FWD_EN	BIT(25) | #define   AR8236_FM_CPU_BCAST_FWD_EN	BIT(25) | ||||||
|  |  | ||||||
| @@ -127,6 +129,12 @@ | |||||||
| #define   AR8216_ATU_CTRL_AGE_TIME	BITS(0, 16) | #define   AR8216_ATU_CTRL_AGE_TIME	BITS(0, 16) | ||||||
| #define   AR8216_ATU_CTRL_AGE_TIME_S	0 | #define   AR8216_ATU_CTRL_AGE_TIME_S	0 | ||||||
| #define   AR8236_ATU_CTRL_RES		BIT(20) | #define   AR8236_ATU_CTRL_RES		BIT(20) | ||||||
|  | #define   AR8216_ATU_CTRL_LEARN_CHANGE	BIT(18) | ||||||
|  |  | ||||||
|  | #define AR8216_REG_TAG_PRIORITY	0x0070 | ||||||
|  |  | ||||||
|  | #define AR8216_REG_SERVICE_TAG		0x0074 | ||||||
|  | #define  AR8216_SERVICE_TAG_M		BITS(0, 16) | ||||||
|  |  | ||||||
| #define AR8216_REG_MIB_FUNC		0x0080 | #define AR8216_REG_MIB_FUNC		0x0080 | ||||||
| #define   AR8216_MIB_TIMER		BITS(0, 16) | #define   AR8216_MIB_TIMER		BITS(0, 16) | ||||||
| @@ -142,6 +150,7 @@ | |||||||
| #define AR8216_REG_GLOBAL_CPUPORT		0x0078 | #define AR8216_REG_GLOBAL_CPUPORT		0x0078 | ||||||
| #define   AR8216_GLOBAL_CPUPORT_MIRROR_PORT	BITS(4, 4) | #define   AR8216_GLOBAL_CPUPORT_MIRROR_PORT	BITS(4, 4) | ||||||
| #define   AR8216_GLOBAL_CPUPORT_MIRROR_PORT_S	4 | #define   AR8216_GLOBAL_CPUPORT_MIRROR_PORT_S	4 | ||||||
|  | #define   AR8216_GLOBAL_CPUPORT_EN		BIT(8) | ||||||
|  |  | ||||||
| #define AR8216_PORT_OFFSET(_i)		(0x0100 * (_i + 1)) | #define AR8216_PORT_OFFSET(_i)		(0x0100 * (_i + 1)) | ||||||
| #define AR8216_REG_PORT_STATUS(_i)	(AR8216_PORT_OFFSET(_i) + 0x0000) | #define AR8216_REG_PORT_STATUS(_i)	(AR8216_PORT_OFFSET(_i) + 0x0000) | ||||||
| @@ -237,6 +246,16 @@ | |||||||
| #define AR8216_STATS_TXDEFER		0x98 | #define AR8216_STATS_TXDEFER		0x98 | ||||||
| #define AR8216_STATS_TXLATECOL		0x9c | #define AR8216_STATS_TXLATECOL		0x9c | ||||||
|  |  | ||||||
|  | #define AR8229_REG_OPER_MODE0		0x04 | ||||||
|  | #define   AR8229_OPER_MODE0_MAC_GMII_EN	BIT(6) | ||||||
|  | #define   AR8229_OPER_MODE0_PHY_MII_EN	BIT(10) | ||||||
|  |  | ||||||
|  | #define AR8229_REG_OPER_MODE1		0x08 | ||||||
|  | #define   AR8229_REG_OPER_MODE1_PHY4_MII_EN	BIT(28) | ||||||
|  |  | ||||||
|  | #define AR8229_REG_QM_CTRL		0x3c | ||||||
|  | #define   AR8229_QM_CTRL_ARP_EN		BIT(15) | ||||||
|  |  | ||||||
| #define AR8236_REG_PORT_VLAN(_i)	(AR8216_PORT_OFFSET((_i)) + 0x0008) | #define AR8236_REG_PORT_VLAN(_i)	(AR8216_PORT_OFFSET((_i)) + 0x0008) | ||||||
| #define   AR8236_PORT_VLAN_DEFAULT_ID	BITS(16, 12) | #define   AR8236_PORT_VLAN_DEFAULT_ID	BITS(16, 12) | ||||||
| #define   AR8236_PORT_VLAN_DEFAULT_ID_S	16 | #define   AR8236_PORT_VLAN_DEFAULT_ID_S	16 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user