summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h
blob: eba41c24b7a7edd7601fc6913300aec303cd9c16 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * stmmac_pcs.h: Physical Coding Sublayer Header File
 *
 * Copyright (C) 2016 STMicroelectronics (R&D) Limited
 * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#ifndef __STMMAC_PCS_H__
#define __STMMAC_PCS_H__

#include <linux/slab.h>
#include <linux/io.h>
#include "common.h"

/* PCS registers (AN/TBI/SGMII/RGMII) offsets */
#define GMAC_AN_CTRL(x)		(x)		/* AN control */
#define GMAC_AN_STATUS(x)	(x + 0x4)	/* AN status */
#define GMAC_ANE_ADV(x)		(x + 0x8)	/* ANE Advertisement */
#define GMAC_ANE_LPA(x)		(x + 0xc)	/* ANE link partener ability */
#define GMAC_ANE_EXP(x)		(x + 0x10)	/* ANE expansion */
#define GMAC_TBI(x)		(x + 0x14)	/* TBI extend status */

/* AN Configuration defines */
#define GMAC_AN_CTRL_RAN	BIT(9)	/* Restart Auto-Negotiation */
#define GMAC_AN_CTRL_ANE	BIT(12)	/* Auto-Negotiation Enable */
#define GMAC_AN_CTRL_ELE	BIT(14)	/* External Loopback Enable */
#define GMAC_AN_CTRL_ECD	BIT(16)	/* Enable Comma Detect */
#define GMAC_AN_CTRL_LR		BIT(17)	/* Lock to Reference */
#define GMAC_AN_CTRL_SGMRAL	BIT(18)	/* SGMII RAL Control */

/* AN Status defines */
#define GMAC_AN_STATUS_LS	BIT(2)	/* Link Status 0:down 1:up */
#define GMAC_AN_STATUS_ANA	BIT(3)	/* Auto-Negotiation Ability */
#define GMAC_AN_STATUS_ANC	BIT(5)	/* Auto-Negotiation Complete */
#define GMAC_AN_STATUS_ES	BIT(8)	/* Extended Status */

/* ADV and LPA defines */
#define GMAC_ANE_FD		BIT(5)
#define GMAC_ANE_HD		BIT(6)
#define GMAC_ANE_PSE		GENMASK(8, 7)
#define GMAC_ANE_PSE_SHIFT	7
#define GMAC_ANE_RFE		GENMASK(13, 12)
#define GMAC_ANE_RFE_SHIFT	12
#define GMAC_ANE_ACK		BIT(14)

/**
 * dwmac_pcs_isr - TBI, RTBI, or SGMII PHY ISR
 * @ioaddr: IO registers pointer
 * @reg: Base address of the AN Control Register.
 * @intr_status: GMAC core interrupt status
 * @x: pointer to log these events as stats
 * Description: it is the ISR for PCS events: Auto-Negotiation Completed and
 * Link status.
 */
static inline void dwmac_pcs_isr(void __iomem *ioaddr, u32 reg,
				 unsigned int intr_status,
				 struct stmmac_extra_stats *x)
{
	u32 val = readl(ioaddr + GMAC_AN_STATUS(reg));

	if (intr_status & PCS_ANE_IRQ) {
		x->irq_pcs_ane_n++;
		if (val & GMAC_AN_STATUS_ANC)
			pr_info("stmmac_pcs: ANE process completed\n");
	}

	if (intr_status & PCS_LINK_IRQ) {
		x->irq_pcs_link_n++;
		if (val & GMAC_AN_STATUS_LS)
			pr_info("stmmac_pcs: Link Up\n");
		else
			pr_info("stmmac_pcs: Link Down\n");
	}
}

/**
 * dwmac_rane - To restart ANE
 * @ioaddr: IO registers pointer
 * @reg: Base address of the AN Control Register.
 * @restart: to restart ANE
 * Description: this is to just restart the Auto-Negotiation.
 */
static inline void dwmac_rane(void __iomem *ioaddr, u32 reg, bool restart)
{
	u32 value = readl(ioaddr + GMAC_AN_CTRL(reg));

	if (restart)
		value |= GMAC_AN_CTRL_RAN;

	writel(value, ioaddr + GMAC_AN_CTRL(reg));
}

/**
 * dwmac_ctrl_ane - To program the AN Control Register.
 * @ioaddr: IO registers pointer
 * @reg: Base address of the AN Control Register.
 * @ane: to enable the auto-negotiation
 * @srgmi_ral: to manage MAC-2-MAC SGMII connections.
 * @loopback: to cause the PHY to loopback tx data into rx path.
 * Description: this is the main function to configure the AN control register
 * and init the ANE, select loopback (usually for debugging purpose) and
 * configure SGMII RAL.
 */
static inline void dwmac_ctrl_ane(void __iomem *ioaddr, u32 reg, bool ane,
				  bool srgmi_ral, bool loopback)
{
	u32 value = readl(ioaddr + GMAC_AN_CTRL(reg));

	/* Enable and restart the Auto-Negotiation */
	if (ane)
		value |= GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_RAN;

	/* In case of MAC-2-MAC connection, block is configured to operate
	 * according to MAC conf register.
	 */
	if (srgmi_ral)
		value |= GMAC_AN_CTRL_SGMRAL;

	if (loopback)
		value |= GMAC_AN_CTRL_ELE;

	writel(value, ioaddr + GMAC_AN_CTRL(reg));
}

/**
 * dwmac_get_adv_lp - Get ADV and LP cap
 * @ioaddr: IO registers pointer
 * @reg: Base address of the AN Control Register.
 * @adv_lp: structure to store the adv,lp status
 * Description: this is to expose the ANE advertisement and Link partner ability
 * status to ethtool support.
 */
static inline void dwmac_get_adv_lp(void __iomem *ioaddr, u32 reg,
				    struct rgmii_adv *adv_lp)
{
	u32 value = readl(ioaddr + GMAC_ANE_ADV(reg));

	if (value & GMAC_ANE_FD)
		adv_lp->duplex = DUPLEX_FULL;
	if (value & GMAC_ANE_HD)
		adv_lp->duplex |= DUPLEX_HALF;

	adv_lp->pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT;

	value = readl(ioaddr + GMAC_ANE_LPA(reg));

	if (value & GMAC_ANE_FD)
		adv_lp->lp_duplex = DUPLEX_FULL;
	if (value & GMAC_ANE_HD)
		adv_lp->lp_duplex = DUPLEX_HALF;

	adv_lp->lp_pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT;
}
#endif /* __STMMAC_PCS_H__ */