blob: bd8df36ab537c22cde46aa6d4557b6227e3da6ba [file] [log] [blame]
David Brazdil0f672f62019-12-10 10:32:29 +00001/* SPDX-License-Identifier: GPL-2.0-or-later */
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002/*
3 * Marvell 88E6xxx SERDES manipulation, via SMI bus
4 *
5 * Copyright (c) 2008 Marvell Semiconductor
6 *
7 * Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00008 */
9
10#ifndef _MV88E6XXX_SERDES_H
11#define _MV88E6XXX_SERDES_H
12
13#include "chip.h"
14
15#define MV88E6352_ADDR_SERDES 0x0f
16#define MV88E6352_SERDES_PAGE_FIBER 0x01
David Brazdil0f672f62019-12-10 10:32:29 +000017#define MV88E6352_SERDES_IRQ 0x0b
18#define MV88E6352_SERDES_INT_ENABLE 0x12
19#define MV88E6352_SERDES_INT_SPEED_CHANGE BIT(14)
20#define MV88E6352_SERDES_INT_DUPLEX_CHANGE BIT(13)
21#define MV88E6352_SERDES_INT_PAGE_RX BIT(12)
22#define MV88E6352_SERDES_INT_AN_COMPLETE BIT(11)
23#define MV88E6352_SERDES_INT_LINK_CHANGE BIT(10)
24#define MV88E6352_SERDES_INT_SYMBOL_ERROR BIT(9)
25#define MV88E6352_SERDES_INT_FALSE_CARRIER BIT(8)
26#define MV88E6352_SERDES_INT_FIFO_OVER_UNDER BIT(7)
27#define MV88E6352_SERDES_INT_FIBRE_ENERGY BIT(4)
28#define MV88E6352_SERDES_INT_STATUS 0x13
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000029
David Brazdil0f672f62019-12-10 10:32:29 +000030
31#define MV88E6341_PORT5_LANE 0x15
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000032
33#define MV88E6390_PORT9_LANE0 0x09
34#define MV88E6390_PORT9_LANE1 0x12
35#define MV88E6390_PORT9_LANE2 0x13
36#define MV88E6390_PORT9_LANE3 0x14
37#define MV88E6390_PORT10_LANE0 0x0a
38#define MV88E6390_PORT10_LANE1 0x15
39#define MV88E6390_PORT10_LANE2 0x16
40#define MV88E6390_PORT10_LANE3 0x17
41
42/* 10GBASE-R and 10GBASE-X4/X2 */
43#define MV88E6390_PCS_CONTROL_1 0x1000
44#define MV88E6390_PCS_CONTROL_1_RESET BIT(15)
45#define MV88E6390_PCS_CONTROL_1_LOOPBACK BIT(14)
46#define MV88E6390_PCS_CONTROL_1_SPEED BIT(13)
47#define MV88E6390_PCS_CONTROL_1_PDOWN BIT(11)
48
49/* 1000BASE-X and SGMII */
50#define MV88E6390_SGMII_CONTROL 0x2000
51#define MV88E6390_SGMII_CONTROL_RESET BIT(15)
52#define MV88E6390_SGMII_CONTROL_LOOPBACK BIT(14)
53#define MV88E6390_SGMII_CONTROL_PDOWN BIT(11)
54#define MV88E6390_SGMII_STATUS 0x2001
55#define MV88E6390_SGMII_STATUS_AN_DONE BIT(5)
56#define MV88E6390_SGMII_STATUS_REMOTE_FAULT BIT(4)
57#define MV88E6390_SGMII_STATUS_LINK BIT(2)
58#define MV88E6390_SGMII_INT_ENABLE 0xa001
59#define MV88E6390_SGMII_INT_SPEED_CHANGE BIT(14)
60#define MV88E6390_SGMII_INT_DUPLEX_CHANGE BIT(13)
61#define MV88E6390_SGMII_INT_PAGE_RX BIT(12)
62#define MV88E6390_SGMII_INT_AN_COMPLETE BIT(11)
63#define MV88E6390_SGMII_INT_LINK_DOWN BIT(10)
64#define MV88E6390_SGMII_INT_LINK_UP BIT(9)
65#define MV88E6390_SGMII_INT_SYMBOL_ERROR BIT(8)
66#define MV88E6390_SGMII_INT_FALSE_CARRIER BIT(7)
67#define MV88E6390_SGMII_INT_STATUS 0xa002
David Brazdil0f672f62019-12-10 10:32:29 +000068#define MV88E6390_SGMII_PHY_STATUS 0xa003
69#define MV88E6390_SGMII_PHY_STATUS_SPEED_MASK GENMASK(15, 14)
70#define MV88E6390_SGMII_PHY_STATUS_SPEED_1000 0x8000
71#define MV88E6390_SGMII_PHY_STATUS_SPEED_100 0x4000
72#define MV88E6390_SGMII_PHY_STATUS_SPEED_10 0x0000
73#define MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL BIT(13)
74#define MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID BIT(11)
75#define MV88E6390_SGMII_PHY_STATUS_LINK BIT(10)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000076
David Brazdil0f672f62019-12-10 10:32:29 +000077u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
78u8 mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
79u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
80u8 mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
81unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
82 int port);
83unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
84 int port);
85int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
86 bool on);
87int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
88 bool on);
89int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
90 bool enable);
91int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
92 bool enable);
93irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
94 u8 lane);
95irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
96 u8 lane);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000097int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
98int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
99 int port, uint8_t *data);
100int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
101 uint64_t *data);
David Brazdil0f672f62019-12-10 10:32:29 +0000102
103/* Return the (first) SERDES lane address a port is using, 0 otherwise. */
104static inline u8 mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,
105 int port)
106{
107 if (!chip->info->ops->serdes_get_lane)
108 return 0;
109
110 return chip->info->ops->serdes_get_lane(chip, port);
111}
112
113static inline int mv88e6xxx_serdes_power_up(struct mv88e6xxx_chip *chip,
114 int port, u8 lane)
115{
116 if (!chip->info->ops->serdes_power)
117 return -EOPNOTSUPP;
118
119 return chip->info->ops->serdes_power(chip, port, lane, true);
120}
121
122static inline int mv88e6xxx_serdes_power_down(struct mv88e6xxx_chip *chip,
123 int port, u8 lane)
124{
125 if (!chip->info->ops->serdes_power)
126 return -EOPNOTSUPP;
127
128 return chip->info->ops->serdes_power(chip, port, lane, false);
129}
130
131static inline unsigned int
132mv88e6xxx_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
133{
134 if (!chip->info->ops->serdes_irq_mapping)
135 return 0;
136
137 return chip->info->ops->serdes_irq_mapping(chip, port);
138}
139
140static inline int mv88e6xxx_serdes_irq_enable(struct mv88e6xxx_chip *chip,
141 int port, u8 lane)
142{
143 if (!chip->info->ops->serdes_irq_enable)
144 return -EOPNOTSUPP;
145
146 return chip->info->ops->serdes_irq_enable(chip, port, lane, true);
147}
148
149static inline int mv88e6xxx_serdes_irq_disable(struct mv88e6xxx_chip *chip,
150 int port, u8 lane)
151{
152 if (!chip->info->ops->serdes_irq_enable)
153 return -EOPNOTSUPP;
154
155 return chip->info->ops->serdes_irq_enable(chip, port, lane, false);
156}
157
158static inline irqreturn_t
159mv88e6xxx_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, u8 lane)
160{
161 if (!chip->info->ops->serdes_irq_status)
162 return IRQ_NONE;
163
164 return chip->info->ops->serdes_irq_status(chip, port, lane);
165}
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000166
167#endif