goto restore_link;
}
+ if (chip->info->ops->port_set_cmode) {
+ err = chip->info->ops->port_set_cmode(chip, port, mode);
+ if (err && err != -EOPNOTSUPP)
+ goto restore_link;
+ }
+
err = 0;
restore_link:
if (chip->info->ops->port_set_link(chip, port, link))
.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
.port_set_ether_type = mv88e6351_port_set_ether_type,
.port_pause_config = mv88e6390_port_pause_config,
+ .port_set_cmode = mv88e6390x_port_set_cmode,
.stats_snapshot = mv88e6390_g1_stats_snapshot,
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
.port_jumbo_config = mv88e6165_port_jumbo_config,
.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
.port_pause_config = mv88e6390_port_pause_config,
+ .port_set_cmode = mv88e6390x_port_set_cmode,
.stats_snapshot = mv88e6390_g1_stats_snapshot,
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
#define PORT_STATUS_CMODE_100BASE_X 0x8
#define PORT_STATUS_CMODE_1000BASE_X 0x9
#define PORT_STATUS_CMODE_SGMII 0xa
+#define PORT_STATUS_CMODE_2500BASEX 0xb
+#define PORT_STATUS_CMODE_XAUI 0xc
+#define PORT_STATUS_CMODE_RXAUI 0xd
#define PORT_PCS_CTRL 0x01
#define PORT_PCS_CTRL_RGMII_DELAY_RXCLK BIT(15)
#define PORT_PCS_CTRL_RGMII_DELAY_TXCLK BIT(14)
int (*port_egress_rate_limiting)(struct mv88e6xxx_chip *chip, int port);
int (*port_pause_config)(struct mv88e6xxx_chip *chip, int port);
+ /* CMODE control what PHY mode the MAC will use, eg. SGMII, RGMII, etc.
+ * Some chips allow this to be configured on specific ports.
+ */
+ int (*port_set_cmode)(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode);
+
/* Snapshot the statistics for a port. The statistics can then
* be read back a leisure but still with a consistent view.
*/
* (at your option) any later version.
*/
+#include <linux/phy.h>
#include "mv88e6xxx.h"
#include "port.h"
return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
}
+int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode)
+{
+ u16 reg;
+ u16 cmode;
+ int err;
+
+ if (mode == PHY_INTERFACE_MODE_NA)
+ return 0;
+
+ if (port != 9 && port != 10)
+ return -EOPNOTSUPP;
+
+ switch (mode) {
+ case PHY_INTERFACE_MODE_1000BASEX:
+ cmode = PORT_STATUS_CMODE_1000BASE_X;
+ break;
+ case PHY_INTERFACE_MODE_SGMII:
+ cmode = PORT_STATUS_CMODE_SGMII;
+ break;
+ case PHY_INTERFACE_MODE_2500BASEX:
+ cmode = PORT_STATUS_CMODE_2500BASEX;
+ break;
+ case PHY_INTERFACE_MODE_XGMII:
+ cmode = PORT_STATUS_CMODE_XAUI;
+ break;
+ case PHY_INTERFACE_MODE_RXAUI:
+ cmode = PORT_STATUS_CMODE_RXAUI;
+ break;
+ default:
+ cmode = 0;
+ }
+
+ if (cmode) {
+ err = mv88e6xxx_port_read(chip, port, PORT_STATUS, ®);
+ if (err)
+ return err;
+
+ reg &= ~PORT_STATUS_CMODE_MASK;
+ reg |= cmode;
+
+ err = mv88e6xxx_port_write(chip, port, PORT_STATUS, reg);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
+{
+ int err;
+ u16 reg;
+
+ err = mv88e6xxx_port_read(chip, port, PORT_STATUS, ®);
+ if (err)
+ return err;
+
+ *cmode = reg & PORT_STATUS_CMODE_MASK;
+
+ return 0;
+}
+
/* Offset 0x02: Pause Control
*
* Do not limit the period of time that this port can be paused for by
int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
int mv88e6097_port_pause_config(struct mv88e6xxx_chip *chip, int port);
int mv88e6390_port_pause_config(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode);
+int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
#endif /* _MV88E6XXX_PORT_H */