Skip to content

Commit f3cad26

Browse files
steen-hegelund-mchpdavem330
authored andcommitted
net: sparx5: add hostmode with phylink support
This patch adds netdevs and phylink support for the ports in the switch. It also adds register based injection and extraction for these ports. Frame DMA support for injection and extraction will be added in a later series. Signed-off-by: Steen Hegelund <[email protected]> Signed-off-by: Bjarni Jonasson <[email protected]> Signed-off-by: Lars Povlsen <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3cfa11b commit f3cad26

File tree

6 files changed

+841
-10
lines changed

6 files changed

+841
-10
lines changed

drivers/net/ethernet/microchip/sparx5/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55

66
obj-$(CONFIG_SPARX5_SWITCH) += sparx5-switch.o
77

8-
sparx5-switch-objs := sparx5_main.o
8+
sparx5-switch-objs := sparx5_main.o sparx5_packet.o \
9+
sparx5_netdev.o sparx5_phylink.o

drivers/net/ethernet/microchip/sparx5/sparx5_main.c

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,16 @@ static int sparx5_create_port(struct sparx5 *sparx5,
250250
struct initial_port_config *config)
251251
{
252252
struct sparx5_port *spx5_port;
253-
254-
/* netdev creation to be added in later patches */
255-
spx5_port = devm_kzalloc(sparx5->dev, sizeof(*spx5_port), GFP_KERNEL);
253+
struct net_device *ndev;
254+
struct phylink *phylink;
255+
256+
ndev = sparx5_create_netdev(sparx5, config->portno);
257+
if (IS_ERR(ndev)) {
258+
dev_err(sparx5->dev, "Could not create net device: %02u\n",
259+
config->portno);
260+
return PTR_ERR(ndev);
261+
}
262+
spx5_port = netdev_priv(ndev);
256263
spx5_port->of_node = config->node;
257264
spx5_port->serdes = config->serdes;
258265
spx5_port->pvid = NULL_VID;
@@ -262,8 +269,28 @@ static int sparx5_create_port(struct sparx5 *sparx5,
262269
spx5_port->max_vlan_tags = SPX5_PORT_MAX_TAGS_NONE;
263270
spx5_port->vlan_type = SPX5_VLAN_PORT_TYPE_UNAWARE;
264271
spx5_port->custom_etype = 0x8880; /* Vitesse */
272+
spx5_port->phylink_pcs.poll = true;
273+
spx5_port->phylink_pcs.ops = &sparx5_phylink_pcs_ops;
274+
sparx5->ports[config->portno] = spx5_port;
275+
276+
spx5_port->conf = config->conf;
277+
278+
/* VLAN setup to be added in later patches */
279+
280+
/* Create a phylink for PHY management. Also handles SFPs */
281+
spx5_port->phylink_config.dev = &spx5_port->ndev->dev;
282+
spx5_port->phylink_config.type = PHYLINK_NETDEV;
283+
spx5_port->phylink_config.pcs_poll = true;
284+
285+
phylink = phylink_create(&spx5_port->phylink_config,
286+
of_fwnode_handle(config->node),
287+
config->conf.phy_mode,
288+
&sparx5_phylink_mac_ops);
289+
if (IS_ERR(phylink))
290+
return PTR_ERR(phylink);
265291

266-
/* PHYLINK support to be added in later patches */
292+
spx5_port->phylink = phylink;
293+
phylink_set_pcs(phylink, &spx5_port->phylink_pcs);
267294

268295
return 0;
269296
}
@@ -525,6 +552,7 @@ static void sparx5_board_init(struct sparx5 *sparx5)
525552
static int sparx5_start(struct sparx5 *sparx5)
526553
{
527554
u32 idx;
555+
int err;
528556

529557
/* Setup own UPSIDs */
530558
for (idx = 0; idx < 3; idx++) {
@@ -558,13 +586,34 @@ static int sparx5_start(struct sparx5 *sparx5)
558586
/* Enable queue limitation watermarks */
559587
sparx5_qlim_set(sparx5);
560588

561-
/* netdev and resource calendar support to be added in later patches */
589+
/* Resource calendar support to be added in later patches */
590+
591+
err = sparx5_register_netdevs(sparx5);
592+
if (err)
593+
return err;
562594

563595
sparx5_board_init(sparx5);
564596

565-
/* Injection/Extraction config to be added in later patches */
597+
/* Start register based INJ/XTR */
598+
err = -ENXIO;
599+
if (err && sparx5->xtr_irq >= 0) {
600+
err = devm_request_irq(sparx5->dev, sparx5->xtr_irq,
601+
sparx5_xtr_handler, IRQF_SHARED,
602+
"sparx5-xtr", sparx5);
603+
if (!err)
604+
err = sparx5_manual_injection_mode(sparx5);
605+
if (err)
606+
sparx5->xtr_irq = -ENXIO;
607+
} else {
608+
sparx5->xtr_irq = -ENXIO;
609+
}
610+
return err;
611+
}
566612

567-
return 0;
613+
static void sparx5_cleanup_ports(struct sparx5 *sparx5)
614+
{
615+
sparx5_unregister_netdevs(sparx5);
616+
sparx5_destroy_netdevs(sparx5);
568617
}
569618

570619
static int mchp_sparx5_probe(struct platform_device *pdev)
@@ -674,7 +723,8 @@ static int mchp_sparx5_probe(struct platform_device *pdev)
674723
ether_addr_copy(sparx5->base_mac, mac_addr);
675724
}
676725

677-
/* Inj/Xtr IRQ support to be added in later patches */
726+
sparx5->xtr_irq = platform_get_irq_byname(sparx5->pdev, "xtr");
727+
678728
/* Read chip ID to check CPU interface */
679729
sparx5->chip_id = spx5_rd(sparx5, GCB_CHIP_ID);
680730

@@ -715,14 +765,26 @@ static int mchp_sparx5_probe(struct platform_device *pdev)
715765
goto cleanup_config;
716766

717767
cleanup_ports:
718-
/* Port cleanup to be added in later patches */
768+
sparx5_cleanup_ports(sparx5);
719769
cleanup_config:
720770
kfree(configs);
721771
cleanup_pnode:
722772
of_node_put(ports);
723773
return err;
724774
}
725775

776+
static int mchp_sparx5_remove(struct platform_device *pdev)
777+
{
778+
struct sparx5 *sparx5 = platform_get_drvdata(pdev);
779+
780+
if (sparx5->xtr_irq) {
781+
disable_irq(sparx5->xtr_irq);
782+
sparx5->xtr_irq = -ENXIO;
783+
}
784+
sparx5_cleanup_ports(sparx5);
785+
return 0;
786+
}
787+
726788
static const struct of_device_id mchp_sparx5_match[] = {
727789
{ .compatible = "microchip,sparx5-switch" },
728790
{ }
@@ -731,6 +793,7 @@ MODULE_DEVICE_TABLE(of, mchp_sparx5_match);
731793

732794
static struct platform_driver mchp_sparx5_driver = {
733795
.probe = mchp_sparx5_probe,
796+
.remove = mchp_sparx5_remove,
734797
.driver = {
735798
.name = "sparx5-switch",
736799
.of_match_table = mchp_sparx5_match,

drivers/net/ethernet/microchip/sparx5/sparx5_main.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/if_vlan.h>
1515
#include <linux/bitmap.h>
1616
#include <linux/phylink.h>
17+
#include <linux/hrtimer.h>
1718

1819
/* Target chip type */
1920
enum spx5_target_chiptype {
@@ -69,6 +70,9 @@ enum sparx5_vlan_port_type {
6970
#define SPX5_BUFFER_CELL_SZ 184 /* Cell size */
7071
#define SPX5_BUFFER_MEMORY 4194280 /* 22795 words * 184 bytes */
7172

73+
#define XTR_QUEUE 0
74+
#define INJ_QUEUE 0
75+
7276
struct sparx5;
7377

7478
struct sparx5_port_config {
@@ -93,6 +97,9 @@ struct sparx5_port {
9397
struct device_node *of_node;
9498
struct phy *serdes;
9599
struct sparx5_port_config conf;
100+
struct phylink_config phylink_config;
101+
struct phylink *phylink;
102+
struct phylink_pcs phylink_pcs;
96103
u16 portno;
97104
/* Ingress default VLAN (pvid) */
98105
u16 pvid;
@@ -107,6 +114,7 @@ struct sparx5_port {
107114
u32 custom_etype;
108115
u32 ifh[IFH_LEN];
109116
bool vlan_aware;
117+
struct hrtimer inj_timer;
110118
};
111119

112120
enum sparx5_core_clockfreq {
@@ -130,8 +138,23 @@ struct sparx5 {
130138
u8 base_mac[ETH_ALEN];
131139
/* Board specifics */
132140
bool sd_sgpio_remapping;
141+
/* Register based inj/xtr */
142+
int xtr_irq;
133143
};
134144

145+
/* sparx5_packet.c */
146+
irqreturn_t sparx5_xtr_handler(int irq, void *_priv);
147+
int sparx5_port_xmit_impl(struct sk_buff *skb, struct net_device *dev);
148+
int sparx5_manual_injection_mode(struct sparx5 *sparx5);
149+
void sparx5_port_inj_timer_setup(struct sparx5_port *port);
150+
151+
/* sparx5_netdev.c */
152+
bool sparx5_netdevice_check(const struct net_device *dev);
153+
struct net_device *sparx5_create_netdev(struct sparx5 *sparx5, u32 portno);
154+
int sparx5_register_netdevs(struct sparx5 *sparx5);
155+
void sparx5_destroy_netdevs(struct sparx5 *sparx5);
156+
void sparx5_unregister_netdevs(struct sparx5 *sparx5);
157+
135158
/* Clock period in picoseconds */
136159
static inline u32 sparx5_clk_period(enum sparx5_core_clockfreq cclock)
137160
{
@@ -146,6 +169,16 @@ static inline u32 sparx5_clk_period(enum sparx5_core_clockfreq cclock)
146169
}
147170
}
148171

172+
static inline bool sparx5_is_baser(phy_interface_t interface)
173+
{
174+
return interface == PHY_INTERFACE_MODE_5GBASER ||
175+
interface == PHY_INTERFACE_MODE_10GBASER ||
176+
interface == PHY_INTERFACE_MODE_25GBASER;
177+
}
178+
179+
extern const struct phylink_mac_ops sparx5_phylink_mac_ops;
180+
extern const struct phylink_pcs_ops sparx5_phylink_pcs_ops;
181+
149182
/* Calculate raw offset */
150183
static inline __pure int spx5_offset(int id, int tinst, int tcnt,
151184
int gbase, int ginst,

0 commit comments

Comments
 (0)