* [v5] dsa: mv88e6xxx: make serdes SGMII/Fiber tx amplitude configurable
@ 2022-02-09 9:54 Holger Brunck
2022-02-09 12:36 ` Marek Behún
2022-02-09 13:37 ` Andrew Lunn
0 siblings, 2 replies; 6+ messages in thread
From: Holger Brunck @ 2022-02-09 9:54 UTC (permalink / raw)
To: netdev; +Cc: Holger Brunck, Andrew Lunn, Jakub Kicinski, Marek Behún
The mv88e6352, mv88e6240 and mv88e6176 have a serdes interface. This patch
allows to configure the output swing to a desired value in the
phy-handle of the port. The value which is peak to peak has to be
specified in microvolts. As the chips only supports eight dedicated
values we return EINVAL if the value in the DTS does not match one of
these values.
CC: Andrew Lunn <andrew@lunn.ch>
CC: Jakub Kicinski <kuba@kernel.org>
CC: Marek Behún <kabel@kernel.org>
Signed-off-by: Holger Brunck <holger.brunck@hitachienergy.com>
---
changes for v5:
- rebase on netdev-next
- release phy_handle
- fix register and mask handling
- simpify mv88e6352_serdes_p2p_to_reg array
changes for v4:
- adapted for new dt-binding
https://www.spinics.net/lists/netdev/msg793918.html
drivers/net/dsa/mv88e6xxx/chip.c | 25 ++++++++++++++++++++
drivers/net/dsa/mv88e6xxx/chip.h | 4 ++++
drivers/net/dsa/mv88e6xxx/serdes.c | 38 ++++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx/serdes.h | 5 ++++
4 files changed, 72 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index c54649c4c3a0..92fe29e55f09 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2987,7 +2987,10 @@ static int mv88e6xxx_setup_upstream_port(struct mv88e6xxx_chip *chip, int port)
static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
{
+ struct device_node *phy_handle = NULL;
struct dsa_switch *ds = chip->ds;
+ struct dsa_port *dp;
+ int tx_amp;
int err;
u16 reg;
@@ -3178,6 +3181,25 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
return err;
}
+ if (chip->info->ops->serdes_set_tx_p2p_amplitude) {
+ dp = dsa_to_port(ds, port);
+ if (dp)
+ phy_handle = of_parse_phandle(dp->dn, "phy-handle", 0);
+
+ if (phy_handle && !of_property_read_u32(phy_handle,
+ "tx-p2p-microvolt",
+ &tx_amp)) {
+ err = mv88e6352_serdes_set_tx_p2p_amplitude(chip, port,
+ tx_amp);
+ if (err) {
+ of_node_put(phy_handle);
+ return err;
+ }
+ }
+ if (phy_handle)
+ of_node_put(phy_handle);
+ }
+
/* Port based VLAN map: give each port the same default address
* database, and allow bidirectional communication between the
* CPU and DSA port(s), and the other ports.
@@ -4241,6 +4263,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
.serdes_irq_status = mv88e6352_serdes_irq_status,
.serdes_get_regs_len = mv88e6352_serdes_get_regs_len,
.serdes_get_regs = mv88e6352_serdes_get_regs,
+ .serdes_set_tx_p2p_amplitude = mv88e6352_serdes_set_tx_p2p_amplitude,
.gpio_ops = &mv88e6352_gpio_ops,
.phylink_get_caps = mv88e6352_phylink_get_caps,
};
@@ -4521,6 +4544,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
.serdes_irq_status = mv88e6352_serdes_irq_status,
.serdes_get_regs_len = mv88e6352_serdes_get_regs_len,
.serdes_get_regs = mv88e6352_serdes_get_regs,
+ .serdes_set_tx_p2p_amplitude = mv88e6352_serdes_set_tx_p2p_amplitude,
.gpio_ops = &mv88e6352_gpio_ops,
.avb_ops = &mv88e6352_avb_ops,
.ptp_ops = &mv88e6352_ptp_ops,
@@ -4927,6 +4951,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
.serdes_get_stats = mv88e6352_serdes_get_stats,
.serdes_get_regs_len = mv88e6352_serdes_get_regs_len,
.serdes_get_regs = mv88e6352_serdes_get_regs,
+ .serdes_set_tx_p2p_amplitude = mv88e6352_serdes_set_tx_p2p_amplitude,
.phylink_get_caps = mv88e6352_phylink_get_caps,
};
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 12aa637779f5..620de163a680 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -588,6 +588,10 @@ struct mv88e6xxx_ops {
void (*serdes_get_regs)(struct mv88e6xxx_chip *chip, int port,
void *_p);
+ /* SERDES SGMII/Fiber Output Amplitude */
+ int (*serdes_set_tx_p2p_amplitude)(struct mv88e6xxx_chip *chip,
+ int port, int val);
+
/* Address Translation Unit operations */
int (*atu_get_hash)(struct mv88e6xxx_chip *chip, u8 *hash);
int (*atu_set_hash)(struct mv88e6xxx_chip *chip, u8 hash);
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 6a177bf654ee..d16816a267d3 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -1313,6 +1313,44 @@ void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
}
}
+static const int mv88e6352_serdes_p2p_to_reg[] = {
+ /* Index of value in microvolts corresponds to the register value */
+ 14000, 112000, 210000, 308000, 406000, 504000, 602000, 700000,
+};
+
+int mv88e6352_serdes_set_tx_p2p_amplitude(struct mv88e6xxx_chip *chip, int port,
+ int val)
+{
+ bool found = false;
+ u16 ctrl, reg;
+ int err;
+ int i;
+
+ err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
+ if (err <= 0)
+ return err;
+
+ for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_p2p_to_reg); ++i) {
+ if (mv88e6352_serdes_p2p_to_reg[i] == val) {
+ reg = i;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ return -EINVAL;
+
+ err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_SPEC_CTRL2, &ctrl);
+ if (err)
+ return err;
+
+ ctrl &= ~MV88E6352_SERDES_OUT_AMP_MASK;
+ ctrl |= reg;
+
+ return mv88e6352_serdes_write(chip, MV88E6352_SERDES_SPEC_CTRL2, ctrl);
+}
+
static int mv88e6393x_serdes_power_lane(struct mv88e6xxx_chip *chip, int lane,
bool on)
{
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index 8dd8ed225b45..e3a2e7a1232c 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -27,6 +27,8 @@
#define MV88E6352_SERDES_INT_FIBRE_ENERGY BIT(4)
#define MV88E6352_SERDES_INT_STATUS 0x13
+#define MV88E6352_SERDES_SPEC_CTRL2 0x1a
+#define MV88E6352_SERDES_OUT_AMP_MASK 0x0007
#define MV88E6341_PORT5_LANE 0x15
@@ -176,6 +178,9 @@ void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p);
int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port);
void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p);
+int mv88e6352_serdes_set_tx_p2p_amplitude(struct mv88e6xxx_chip *chip, int port,
+ int val);
+
/* Return the (first) SERDES lane address a port is using, -errno otherwise. */
static inline int mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,
int port)
--
2.34.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [v5] dsa: mv88e6xxx: make serdes SGMII/Fiber tx amplitude configurable
2022-02-09 9:54 [v5] dsa: mv88e6xxx: make serdes SGMII/Fiber tx amplitude configurable Holger Brunck
@ 2022-02-09 12:36 ` Marek Behún
2022-02-09 13:23 ` Holger Brunck
2022-02-09 13:37 ` Andrew Lunn
1 sibling, 1 reply; 6+ messages in thread
From: Marek Behún @ 2022-02-09 12:36 UTC (permalink / raw)
To: Holger Brunck; +Cc: netdev, Andrew Lunn, Jakub Kicinski
On Wed, 9 Feb 2022 10:54:27 +0100
Holger Brunck <holger.brunck@hitachienergy.com> wrote:
> @@ -3178,6 +3181,25 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
> return err;
> }
>
> + if (chip->info->ops->serdes_set_tx_p2p_amplitude) {
> + dp = dsa_to_port(ds, port);
> + if (dp)
> + phy_handle = of_parse_phandle(dp->dn, "phy-handle", 0);
> +
> + if (phy_handle && !of_property_read_u32(phy_handle,
> + "tx-p2p-microvolt",
> + &tx_amp)) {
> + err = mv88e6352_serdes_set_tx_p2p_amplitude(chip, port,
> + tx_amp);
You should use
err = chip->info->ops->serdes_set_tx_p2p_amplitude(...);
instead of
err = mv88e6352_serdes_set_tx_p2p_amplitude(...);
since you are adding this operation to the operations structure and
since mv88e6xxx_setup_port() is a generic method.
Sorry, I overlooked this in v4 :-(
Marek
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [v5] dsa: mv88e6xxx: make serdes SGMII/Fiber tx amplitude configurable
2022-02-09 12:36 ` Marek Behún
@ 2022-02-09 13:23 ` Holger Brunck
0 siblings, 0 replies; 6+ messages in thread
From: Holger Brunck @ 2022-02-09 13:23 UTC (permalink / raw)
To: Marek Behún; +Cc: netdev@vger.kernel.org, Andrew Lunn, Jakub Kicinski
> > @@ -3178,6 +3181,25 @@ static int mv88e6xxx_setup_port(struct
> mv88e6xxx_chip *chip, int port)
> > return err;
> > }
> >
> > + if (chip->info->ops->serdes_set_tx_p2p_amplitude) {
> > + dp = dsa_to_port(ds, port);
> > + if (dp)
> > + phy_handle = of_parse_phandle(dp->dn,
> > + "phy-handle", 0);
> > +
> > + if (phy_handle && !of_property_read_u32(phy_handle,
> > + "tx-p2p-microvolt",
> > + &tx_amp)) {
> > + err = mv88e6352_serdes_set_tx_p2p_amplitude(chip, port,
> > +
> > + tx_amp);
>
> You should use
> err = chip->info->ops->serdes_set_tx_p2p_amplitude(...);
> instead of
> err = mv88e6352_serdes_set_tx_p2p_amplitude(...);
> since you are adding this operation to the operations structure and since
> mv88e6xxx_setup_port() is a generic method.
>
ah sure that makes sense, so that others can add other implementations.
> Sorry, I overlooked this in v4 :-(
>
no problem. I wait another day for other inputs and then send an update.
Best regards
Holger
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [v5] dsa: mv88e6xxx: make serdes SGMII/Fiber tx amplitude configurable
2022-02-09 9:54 [v5] dsa: mv88e6xxx: make serdes SGMII/Fiber tx amplitude configurable Holger Brunck
2022-02-09 12:36 ` Marek Behún
@ 2022-02-09 13:37 ` Andrew Lunn
2022-02-09 15:04 ` Holger Brunck
1 sibling, 1 reply; 6+ messages in thread
From: Andrew Lunn @ 2022-02-09 13:37 UTC (permalink / raw)
To: Holger Brunck; +Cc: netdev, Jakub Kicinski, Marek Behún
> + if (chip->info->ops->serdes_set_tx_p2p_amplitude) {
> + dp = dsa_to_port(ds, port);
> + if (dp)
> + phy_handle = of_parse_phandle(dp->dn, "phy-handle", 0);
> +
> + if (phy_handle && !of_property_read_u32(phy_handle,
> + "tx-p2p-microvolt",
> + &tx_amp)) {
> + err = mv88e6352_serdes_set_tx_p2p_amplitude(chip, port,
> + tx_amp);
> + if (err) {
> + of_node_put(phy_handle);
> + return err;
> + }
You could move this test
> + }
> + if (phy_handle)
> + of_node_put(phy_handle);
to here, since you need to put the phy_handle anyway.
Andrew
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [v5] dsa: mv88e6xxx: make serdes SGMII/Fiber tx amplitude configurable
2022-02-09 13:37 ` Andrew Lunn
@ 2022-02-09 15:04 ` Holger Brunck
2022-02-09 16:08 ` Marek Behún
0 siblings, 1 reply; 6+ messages in thread
From: Holger Brunck @ 2022-02-09 15:04 UTC (permalink / raw)
To: Andrew Lunn; +Cc: netdev@vger.kernel.org, Jakub Kicinski, Marek Behún
> > + if (chip->info->ops->serdes_set_tx_p2p_amplitude) {
> > + dp = dsa_to_port(ds, port);
> > + if (dp)
> > + phy_handle = of_parse_phandle(dp->dn, "phy-handle", 0);
> > +
> > + if (phy_handle && !of_property_read_u32(phy_handle,
> > + "tx-p2p-microvolt",
> > + &tx_amp)) {
> > + err = mv88e6352_serdes_set_tx_p2p_amplitude(chip, port,
> > + tx_amp);
> > + if (err) {
> > + of_node_put(phy_handle);
> > + return err;
> > + }
>
> You could move this test
>
> > + }
> > + if (phy_handle)
> > + of_node_put(phy_handle);
>
> to here, since you need to put the phy_handle anyway.
>
ok. I think I will also rename the ...set_tx_p2p_amplitude to ...set_tx_p2p to
shorten the function names. Makes it easier to read.
Best regards
Holger
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [v5] dsa: mv88e6xxx: make serdes SGMII/Fiber tx amplitude configurable
2022-02-09 15:04 ` Holger Brunck
@ 2022-02-09 16:08 ` Marek Behún
0 siblings, 0 replies; 6+ messages in thread
From: Marek Behún @ 2022-02-09 16:08 UTC (permalink / raw)
To: Holger Brunck; +Cc: Andrew Lunn, netdev@vger.kernel.org, Jakub Kicinski
On Wed, 9 Feb 2022 15:04:56 +0000
Holger Brunck <holger.brunck@hitachienergy.com> wrote:
> > > + if (chip->info->ops->serdes_set_tx_p2p_amplitude) {
> > > + dp = dsa_to_port(ds, port);
> > > + if (dp)
> > > + phy_handle = of_parse_phandle(dp->dn, "phy-handle", 0);
> > > +
> > > + if (phy_handle && !of_property_read_u32(phy_handle,
> > > + "tx-p2p-microvolt",
> > > + &tx_amp)) {
> > > + err = mv88e6352_serdes_set_tx_p2p_amplitude(chip, port,
> > > + tx_amp);
> > > + if (err) {
> > > + of_node_put(phy_handle);
> > > + return err;
> > > + }
> >
> > You could move this test
> >
> > > + }
> > > + if (phy_handle)
> > > + of_node_put(phy_handle);
> >
> > to here, since you need to put the phy_handle anyway.
> >
>
> ok. I think I will also rename the ...set_tx_p2p_amplitude to ...set_tx_p2p to
> shorten the function names. Makes it easier to read.
Please don't drop "amplitude". If anything, drop the "p2p".
Marek
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2022-02-09 16:08 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-02-09 9:54 [v5] dsa: mv88e6xxx: make serdes SGMII/Fiber tx amplitude configurable Holger Brunck
2022-02-09 12:36 ` Marek Behún
2022-02-09 13:23 ` Holger Brunck
2022-02-09 13:37 ` Andrew Lunn
2022-02-09 15:04 ` Holger Brunck
2022-02-09 16:08 ` Marek Behún
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).