xref: /linux/drivers/net/dsa/ocelot/ocelot_ext.c (revision efdbee7d07916d994bc0ff0235d00d46fa991b61)
13d7316acSColin Foster // SPDX-License-Identifier: (GPL-2.0 OR MIT)
23d7316acSColin Foster /*
33d7316acSColin Foster  * Copyright 2021-2022 Innovative Advantage Inc.
43d7316acSColin Foster  */
53d7316acSColin Foster 
63d7316acSColin Foster #include <linux/mfd/ocelot.h>
73d7316acSColin Foster #include <linux/platform_device.h>
83d7316acSColin Foster #include <linux/regmap.h>
93d7316acSColin Foster #include <soc/mscc/ocelot.h>
103d7316acSColin Foster #include <soc/mscc/vsc7514_regs.h>
113d7316acSColin Foster #include "felix.h"
123d7316acSColin Foster 
133d7316acSColin Foster #define VSC7514_NUM_PORTS		11
143d7316acSColin Foster 
153d7316acSColin Foster #define OCELOT_PORT_MODE_SERDES		(OCELOT_PORT_MODE_SGMII | \
163d7316acSColin Foster 					 OCELOT_PORT_MODE_QSGMII)
173d7316acSColin Foster 
183d7316acSColin Foster static const u32 vsc7512_port_modes[VSC7514_NUM_PORTS] = {
193d7316acSColin Foster 	OCELOT_PORT_MODE_INTERNAL,
203d7316acSColin Foster 	OCELOT_PORT_MODE_INTERNAL,
213d7316acSColin Foster 	OCELOT_PORT_MODE_INTERNAL,
223d7316acSColin Foster 	OCELOT_PORT_MODE_INTERNAL,
234c05e5ceSColin Foster 	OCELOT_PORT_MODE_SERDES,
244c05e5ceSColin Foster 	OCELOT_PORT_MODE_SERDES,
254c05e5ceSColin Foster 	OCELOT_PORT_MODE_SERDES,
264c05e5ceSColin Foster 	OCELOT_PORT_MODE_SERDES,
274c05e5ceSColin Foster 	OCELOT_PORT_MODE_SERDES,
284c05e5ceSColin Foster 	OCELOT_PORT_MODE_SGMII,
294c05e5ceSColin Foster 	OCELOT_PORT_MODE_SERDES,
303d7316acSColin Foster };
313d7316acSColin Foster 
323d7316acSColin Foster static const struct ocelot_ops ocelot_ext_ops = {
333d7316acSColin Foster 	.reset		= ocelot_reset,
343d7316acSColin Foster 	.wm_enc		= ocelot_wm_enc,
353d7316acSColin Foster 	.wm_dec		= ocelot_wm_dec,
363d7316acSColin Foster 	.wm_stat	= ocelot_wm_stat,
373d7316acSColin Foster 	.port_to_netdev	= felix_port_to_netdev,
383d7316acSColin Foster 	.netdev_to_port	= felix_netdev_to_port,
393d7316acSColin Foster };
403d7316acSColin Foster 
413d7316acSColin Foster static const char * const vsc7512_resource_names[TARGET_MAX] = {
423d7316acSColin Foster 	[SYS] = "sys",
433d7316acSColin Foster 	[REW] = "rew",
443d7316acSColin Foster 	[S0] = "s0",
453d7316acSColin Foster 	[S1] = "s1",
463d7316acSColin Foster 	[S2] = "s2",
473d7316acSColin Foster 	[QS] = "qs",
483d7316acSColin Foster 	[QSYS] = "qsys",
493d7316acSColin Foster 	[ANA] = "ana",
503d7316acSColin Foster };
513d7316acSColin Foster 
523d7316acSColin Foster static const struct felix_info vsc7512_info = {
533d7316acSColin Foster 	.resource_names			= vsc7512_resource_names,
543d7316acSColin Foster 	.regfields			= vsc7514_regfields,
553d7316acSColin Foster 	.map				= vsc7514_regmap,
563d7316acSColin Foster 	.ops				= &ocelot_ext_ops,
573d7316acSColin Foster 	.vcap				= vsc7514_vcap_props,
583d7316acSColin Foster 	.num_mact_rows			= 1024,
593d7316acSColin Foster 	.num_ports			= VSC7514_NUM_PORTS,
603d7316acSColin Foster 	.port_modes			= vsc7512_port_modes,
614c05e5ceSColin Foster 	.phylink_mac_config		= ocelot_phylink_mac_config,
624c05e5ceSColin Foster 	.configure_serdes		= ocelot_port_configure_serdes,
633d7316acSColin Foster };
643d7316acSColin Foster 
653d7316acSColin Foster static int ocelot_ext_probe(struct platform_device *pdev)
663d7316acSColin Foster {
67*efdbee7dSVladimir Oltean 	return felix_register_switch(&pdev->dev, 0, 1, false, false,
68*efdbee7dSVladimir Oltean 				     DSA_TAG_PROTO_OCELOT, &vsc7512_info);
693d7316acSColin Foster }
703d7316acSColin Foster 
7168ace16cSUwe Kleine-König static void ocelot_ext_remove(struct platform_device *pdev)
723d7316acSColin Foster {
733d7316acSColin Foster 	struct felix *felix = dev_get_drvdata(&pdev->dev);
743d7316acSColin Foster 
753d7316acSColin Foster 	if (!felix)
7668ace16cSUwe Kleine-König 		return;
773d7316acSColin Foster 
783d7316acSColin Foster 	dsa_unregister_switch(felix->ds);
793d7316acSColin Foster }
803d7316acSColin Foster 
813d7316acSColin Foster static void ocelot_ext_shutdown(struct platform_device *pdev)
823d7316acSColin Foster {
833d7316acSColin Foster 	struct felix *felix = dev_get_drvdata(&pdev->dev);
843d7316acSColin Foster 
853d7316acSColin Foster 	if (!felix)
863d7316acSColin Foster 		return;
873d7316acSColin Foster 
883d7316acSColin Foster 	dsa_switch_shutdown(felix->ds);
893d7316acSColin Foster 
903d7316acSColin Foster 	dev_set_drvdata(&pdev->dev, NULL);
913d7316acSColin Foster }
923d7316acSColin Foster 
933d7316acSColin Foster static const struct of_device_id ocelot_ext_switch_of_match[] = {
943d7316acSColin Foster 	{ .compatible = "mscc,vsc7512-switch" },
953d7316acSColin Foster 	{ },
963d7316acSColin Foster };
973d7316acSColin Foster MODULE_DEVICE_TABLE(of, ocelot_ext_switch_of_match);
983d7316acSColin Foster 
993d7316acSColin Foster static struct platform_driver ocelot_ext_switch_driver = {
1003d7316acSColin Foster 	.driver = {
101ef1a99c6SVladimir Oltean 		.name = "ocelot-ext-switch",
1020f17b428SKrzysztof Kozlowski 		.of_match_table = ocelot_ext_switch_of_match,
1033d7316acSColin Foster 	},
1043d7316acSColin Foster 	.probe = ocelot_ext_probe,
10568ace16cSUwe Kleine-König 	.remove_new = ocelot_ext_remove,
1063d7316acSColin Foster 	.shutdown = ocelot_ext_shutdown,
1073d7316acSColin Foster };
1083d7316acSColin Foster module_platform_driver(ocelot_ext_switch_driver);
1093d7316acSColin Foster 
1103d7316acSColin Foster MODULE_DESCRIPTION("External Ocelot Switch driver");
1113d7316acSColin Foster MODULE_LICENSE("GPL");
1123d7316acSColin Foster MODULE_IMPORT_NS(MFD_OCELOT);
113