blob: 235f5f0c30ae36cc2fc6961889bdfae912779c2a [file] [log] [blame]
Andrew Lunn6d917822017-05-26 01:03:21 +02001/*
2 * Marvell 88E6xxx SERDES manipulation, via SMI bus
3 *
4 * Copyright (c) 2008 Marvell Semiconductor
5 *
6 * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#include <linux/mii.h>
15
16#include "mv88e6xxx.h"
17#include "phy.h"
18#include "port.h"
19#include "serdes.h"
20
21static int mv88e6352_serdes_read(struct mv88e6xxx_chip *chip, int reg,
22 u16 *val)
23{
24 return mv88e6xxx_phy_page_read(chip, MV88E6352_ADDR_SERDES,
25 MV88E6352_SERDES_PAGE_FIBER,
26 reg, val);
27}
28
29static int mv88e6352_serdes_write(struct mv88e6xxx_chip *chip, int reg,
30 u16 val)
31{
32 return mv88e6xxx_phy_page_write(chip, MV88E6352_ADDR_SERDES,
33 MV88E6352_SERDES_PAGE_FIBER,
34 reg, val);
35}
36
37static int mv88e6352_serdes_power_set(struct mv88e6xxx_chip *chip, bool on)
38{
39 u16 val, new_val;
40 int err;
41
42 err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
43 if (err)
44 return err;
45
46 if (on)
47 new_val = val & ~BMCR_PDOWN;
48 else
49 new_val = val | BMCR_PDOWN;
50
51 if (val != new_val)
52 err = mv88e6352_serdes_write(chip, MII_BMCR, new_val);
53
54 return err;
55}
56
57int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
58{
59 int err;
60 u8 cmode;
61
62 err = mv88e6xxx_port_get_cmode(chip, port, &cmode);
63 if (err)
64 return err;
65
66 if ((cmode == PORT_STATUS_CMODE_100BASE_X) ||
67 (cmode == PORT_STATUS_CMODE_1000BASE_X) ||
68 (cmode == PORT_STATUS_CMODE_SGMII)) {
69 err = mv88e6352_serdes_power_set(chip, on);
70 if (err < 0)
71 return err;
72 }
73
74 return 0;
75}