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
ocelot_ext_probe(struct platform_device * pdev)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
ocelot_ext_remove(struct platform_device * pdev)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
ocelot_ext_shutdown(struct platform_device * pdev)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