Commit 2ff8a1ee authored by Steen Hegelund's avatar Steen Hegelund Committed by Vinod Koul

phy: Add Sparx5 ethernet serdes PHY driver

Add the Microchip Sparx5 ethernet serdes PHY driver for the 6G, 10G and 25G
interfaces available in the Sparx5 SoC.
Signed-off-by: default avatarBjarni Jonasson <bjarni.jonasson@microchip.com>
Signed-off-by: default avatarSteen Hegelund <steen.hegelund@microchip.com>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Reviewed-by: default avatarAlexandre Belloni <alexandre.belloni@bootlin.com>
Link: https://lore.kernel.org/r/20210218161451.3489955-4-steen.hegelund@microchip.comSigned-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 6c172e73
......@@ -71,6 +71,7 @@ source "drivers/phy/ingenic/Kconfig"
source "drivers/phy/lantiq/Kconfig"
source "drivers/phy/marvell/Kconfig"
source "drivers/phy/mediatek/Kconfig"
source "drivers/phy/microchip/Kconfig"
source "drivers/phy/motorola/Kconfig"
source "drivers/phy/mscc/Kconfig"
source "drivers/phy/qualcomm/Kconfig"
......
......@@ -20,6 +20,7 @@ obj-y += allwinner/ \
lantiq/ \
marvell/ \
mediatek/ \
microchip/ \
motorola/ \
mscc/ \
qualcomm/ \
......
# SPDX-License-Identifier: GPL-2.0-only
#
# Phy drivers for Microchip devices
#
config PHY_SPARX5_SERDES
tristate "Microchip Sparx5 SerDes PHY driver"
select GENERIC_PHY
depends on OF
depends on HAS_IOMEM
help
Enable this for support of the 10G/25G SerDes on Microchip Sparx5.
# SPDX-License-Identifier: GPL-2.0-only
#
# Makefile for the Microchip phy drivers.
#
obj-$(CONFIG_PHY_SPARX5_SERDES) := sparx5_serdes.o
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0+
* Microchip Sparx5 SerDes driver
*
* Copyright (c) 2020 Microchip Technology Inc.
*/
#ifndef _SPARX5_SERDES_H_
#define _SPARX5_SERDES_H_
#include "sparx5_serdes_regs.h"
#define SPX5_SERDES_MAX 33
enum sparx5_serdes_type {
SPX5_SDT_6G = 6,
SPX5_SDT_10G = 10,
SPX5_SDT_25G = 25,
};
enum sparx5_serdes_mode {
SPX5_SD_MODE_NONE,
SPX5_SD_MODE_2G5,
SPX5_SD_MODE_QSGMII,
SPX5_SD_MODE_100FX,
SPX5_SD_MODE_1000BASEX,
SPX5_SD_MODE_SFI,
};
struct sparx5_serdes_private {
struct device *dev;
void __iomem *regs[NUM_TARGETS];
struct phy *phys[SPX5_SERDES_MAX];
bool cmu_enabled;
unsigned long coreclock;
};
struct sparx5_serdes_macro {
struct sparx5_serdes_private *priv;
u32 sidx;
u32 stpidx;
enum sparx5_serdes_type serdestype;
enum sparx5_serdes_mode serdesmode;
phy_interface_t portmode;
int speed;
enum phy_media media;
};
/* Read, Write and modify registers content.
* The register definition macros start at the id
*/
static inline void __iomem *sdx5_addr(void __iomem *base[],
int id, int tinst, int tcnt,
int gbase, int ginst,
int gcnt, int gwidth,
int raddr, int rinst,
int rcnt, int rwidth)
{
WARN_ON((tinst) >= tcnt);
WARN_ON((ginst) >= gcnt);
WARN_ON((rinst) >= rcnt);
return base[id + (tinst)] +
gbase + ((ginst) * gwidth) +
raddr + ((rinst) * rwidth);
}
static inline void __iomem *sdx5_inst_baseaddr(void __iomem *base,
int gbase, int ginst,
int gcnt, int gwidth,
int raddr, int rinst,
int rcnt, int rwidth)
{
WARN_ON((ginst) >= gcnt);
WARN_ON((rinst) >= rcnt);
return base +
gbase + ((ginst) * gwidth) +
raddr + ((rinst) * rwidth);
}
static inline void sdx5_rmw(u32 val, u32 mask, struct sparx5_serdes_private *priv,
int id, int tinst, int tcnt,
int gbase, int ginst, int gcnt, int gwidth,
int raddr, int rinst, int rcnt, int rwidth)
{
u32 nval;
void __iomem *addr =
sdx5_addr(priv->regs, id, tinst, tcnt,
gbase, ginst, gcnt, gwidth,
raddr, rinst, rcnt, rwidth);
nval = readl(addr);
nval = (nval & ~mask) | (val & mask);
writel(nval, addr);
}
static inline void sdx5_inst_rmw(u32 val, u32 mask, void __iomem *iomem,
int id, int tinst, int tcnt,
int gbase, int ginst, int gcnt, int gwidth,
int raddr, int rinst, int rcnt, int rwidth)
{
u32 nval;
void __iomem *addr =
sdx5_inst_baseaddr(iomem,
gbase, ginst, gcnt, gwidth,
raddr, rinst, rcnt, rwidth);
nval = readl(addr);
nval = (nval & ~mask) | (val & mask);
writel(nval, addr);
}
static inline void sdx5_rmw_addr(u32 val, u32 mask, void __iomem *addr)
{
u32 nval;
nval = readl(addr);
nval = (nval & ~mask) | (val & mask);
writel(nval, addr);
}
static inline void __iomem *sdx5_inst_get(struct sparx5_serdes_private *priv,
int id, int tinst)
{
return priv->regs[id + tinst];
}
static inline void __iomem *sdx5_inst_addr(void __iomem *iomem,
int id, int tinst, int tcnt,
int gbase,
int ginst, int gcnt, int gwidth,
int raddr,
int rinst, int rcnt, int rwidth)
{
return sdx5_inst_baseaddr(iomem, gbase, ginst, gcnt, gwidth,
raddr, rinst, rcnt, rwidth);
}
#endif /* _SPARX5_SERDES_REGS_H_ */
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment