From patchwork Tue May 4 05:11:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Colin Foster X-Patchwork-Id: 12237375 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,MSGID_FROM_MTA_HEADER,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2E8BBC433ED for ; Tue, 4 May 2021 05:11:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1173D6139A for ; Tue, 4 May 2021 05:11:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229897AbhEDFMo (ORCPT ); Tue, 4 May 2021 01:12:44 -0400 Received: from mail-bn7nam10on2138.outbound.protection.outlook.com ([40.107.92.138]:55168 "EHLO NAM10-BN7-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S229738AbhEDFMn (ORCPT ); Tue, 4 May 2021 01:12:43 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ZdwpCZcwwDzv4gf1JJ50oWDT4VA4iEDD1WmOQM7UeUfdnEUusmmH1zUbif82E4Px1+0EohuC/MF8CVcdqhq2bpwkufcVmkpoYZonjs6SoAPcaJDcqdZIY1BMH1n1RPiTkZrL/s2YIN2tBPVJkRpVokxCsbkLtR5Cjy5QC+hXioWpxCxMdDomQM4ANC/c0dqCHf2/BdrkSIH7UIJhYJWrsgkXSfdEPkpJcJsSJLunnIYplTSDiDP6CYDTIXe1CLK7uJh9y5s5kuGqdCEekMlxbWI4g5keh9HSYLPhcbpgHcSdBgLgfKXgmZOtexJzhYwTm84CN+HjNAL3C5r3ol1kIg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=kSwj4DZ09k6Gghy5y+t0p/F8049PF7ZT1lucpZFidD0=; b=EYPCW0A0C8MpFUsylrzE8MtSY8IecnqMFbimsIQU2aho1XLvKz9ImtkJYiIOXZqUiJQGYdfNgHufZlorzO3p5HygGr1vQPQkij2mCYMIjvsAXRetbenEiSr16ZkxXoaYxKsHzR/k7KdjY7WYVzDUhcWKrKMBArpiw0WnSq7Hx9cbeKryhNF4JVU2eUkOln9IjXYBdefpuY68HuFdhmohjjI89obdosDmTud0uhsN7VurD2VcH40pYLY21E+Q/INqZuEJzZOgpg9AQufJiuWJGDj9MCpe2a+jDM7ONZ1gVCl/5NqCweA8mTgaoqjxULSWdtlGJ/B6cZ4bbCRsJXZUaw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=in-advantage.com; dmarc=pass action=none header.from=in-advantage.com; dkim=pass header.d=in-advantage.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=inadvantage.onmicrosoft.com; s=selector2-inadvantage-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=kSwj4DZ09k6Gghy5y+t0p/F8049PF7ZT1lucpZFidD0=; b=mz3DOSk78yIe9deKaBofv65ABdGWlHPCNxYRM76wohzC+wJaq1ZbqzDowp5QmWuLC6BNIh4llLG8eectAjKZQRn9wu9wHbQrM6R2fu/cKUeXAS9LjbLqZtGvZwu+MrXGOdXpP4spA7UDX5fIJNUaLspFByeMQaKRwb5yZd2fVNI= Authentication-Results: in-advantage.com; dkim=none (message not signed) header.d=none;in-advantage.com; dmarc=none action=none header.from=in-advantage.com; Received: from MWHSPR01MB355.namprd10.prod.outlook.com (2603:10b6:301:6c::37) by MWHPR1001MB2399.namprd10.prod.outlook.com (2603:10b6:301:30::31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4065.25; Tue, 4 May 2021 05:11:45 +0000 Received: from MWHSPR01MB355.namprd10.prod.outlook.com ([fe80::c559:f270:c9b5:a928]) by MWHSPR01MB355.namprd10.prod.outlook.com ([fe80::c559:f270:c9b5:a928%6]) with mapi id 15.20.4065.039; Tue, 4 May 2021 05:11:45 +0000 From: Colin Foster To: colin.foster@in-advantage.com Cc: Rob Herring , Vladimir Oltean , Claudiu Manoil , Alexandre Belloni , UNGLinuxDriver@microchip.com (supporter:OCELOT ETHERNET SWITCH DRIVER), Andrew Lunn , Vivien Didelot , Florian Fainelli , "David S. Miller" , Jakub Kicinski , Russell King , devicetree@vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS), linux-kernel@vger.kernel.org (open list), netdev@vger.kernel.org (open list:OCELOT ETHERNET SWITCH DRIVER) Subject: [RFC PATCH vN net-next 1/2] net: mscc: ocelot: add support for non-mmio regmaps Date: Mon, 3 May 2021 22:11:26 -0700 Message-Id: <20210504051130.1207550-1-colin.foster@in-advantage.com> X-Mailer: git-send-email 2.25.1 X-Originating-IP: [67.185.175.147] X-ClientProxiedBy: CO2PR04CA0133.namprd04.prod.outlook.com (2603:10b6:104::11) To MWHSPR01MB355.namprd10.prod.outlook.com (2603:10b6:301:6c::37) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from localhost.localdomain (67.185.175.147) by CO2PR04CA0133.namprd04.prod.outlook.com (2603:10b6:104::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4087.39 via Frontend Transport; Tue, 4 May 2021 05:11:44 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 68f34629-a1ef-46f9-65dd-08d90ebb1c36 X-MS-TrafficTypeDiagnostic: MWHPR1001MB2399: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:6108; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: azLePOdDgLYya8iHenq6ndyb+sqnzSFHSVL/pbCkZJYBChYdVCWYHxyUiFa/EpY4shQasrmhlWbkWCmYnJnxSVjCTqjHFMAaEUhR6o3IrmHlHhwXva/ROF6w18LreQmnUr52pugD8e0VZ/vcwHIgNvSuph1N0LQiVUqLoMHCWLjsnwYRfSoJBhgemwuAHafXNKQQ+l3cDpWSrwv4cgqZxzRTLr09QOtgDcBvUBFgpsorK67cNQ+PDO9htP7DWJMavdHJ3ZQqxLF6FJBSfQctdxmnj/TsYXkUPmwKZbOQgtBRpDc3C6civMZH/EvKIwfi0e0PKb5ZdgRGUDCQ4PJtFJkrtqm2OoMdyjvIcwGDsCQw9qGIQVAsnvR3VUVc0+ljfKsmH7yDh+FmWPFEskVSOb+RZSlPZJtWgeGWZfz+DzlBF8C9SI2eIWDSxy13K1DIG9bpjtIyivpX3ySFKoGe8hgfBXQ6jTZ04RErz0/1TZSh1cM4y00ECC7cTad9qqmhOxYON8Gu531V3GSr623K/QmNq0n8V6tMs1P4DY0N5v4ddyVqKmy2pVEQx9G6iDZWKCnUG+M8nL7MqU+K4HpE1xk5x3qvWBFvzGeQ6OImUpnJjMRbwqFsUk37mA1LA2we5NA6amzpVDh7TjPi5dV3NpgeNN6HVxDiXMI8qpbEX6b5NGE1Sz6azWlDc+OuAWvr X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:MWHSPR01MB355.namprd10.prod.outlook.com;PTR:;CAT:NONE;SFS:(366004)(136003)(396003)(376002)(39830400003)(346002)(66946007)(86362001)(5660300002)(44832011)(36756003)(66476007)(956004)(52116002)(66556008)(6666004)(4326008)(478600001)(2616005)(6506007)(2906002)(34206002)(54906003)(6512007)(1076003)(316002)(6486002)(7416002)(16526019)(26005)(37006003)(38350700002)(8676002)(38100700002)(186003)(8936002)(83380400001)(69590400013);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData: JA6TMxaw9fcYVDaZpKQsh3k222uRLPmBFp/5TfRCCZFtYNakzbYveBM4ZBY9K8XqiiVJIpgFI/3l1RzwG8ZCojuRTFd7UVjEElECfKm8DHj//STCh9xH3r4NQ2G9cki4nOJqf3j5knrxmRlb2lCkcEletd5OOWWy1jM9hakZ5gvOGi0peOek0y3jTVPDULGDGwY+BPVwtB2OSVIT/GvN6PbLZacx7DH8m/K/qG01eb6H5pDaiQvu4ShLnRpTCbkzSmRNE1I7Qg8SwI97E+TsxYCKBtDs5zeKGkM2SqXy6ozOMuguXdvFihEVyVDTTU4Dgzh/2HqgBoL4bZuCDRDBAYVCX85EB8vLPQtXGnF0VXY5sEBtC+bc2H74SvxoT94UF/zQI8fYFSpkSQEGQRIJ5SsgneMX0msHra0XrFRVd1ekvWmCtpGP5t0xRGfHa8EnKRTAPNQvUSqaPrP8nzDXueykphdOj7On5ZPF6ZkerJPfTivCvYugU4lG3vMmP47HpemvHwBcxHkz4C6l15M8lB9x+17xiB2YBGktYYsUHADFgwWidngMM6xylxJCUcHAoIKa+0LH1ql8q9R5Dao4528z1efJ8OfxH/7Z0ulMKuKvQUm1v4VO71QVjqOhDPWsRg66D2vk5rz07uTBYqwAN/B0KrOkhh5OWwIWAp0cIYtcdgR2gFvoNybq9et1iyy0MOHt8Ly1eCtcXfXDgdX4b7IFVJAilzej5gbwiNXYfOaEcgjYp2BK1Bw976yz3UlzT/cW0EdSUxYxp+HXOZEgP0dJRLiNj0S1KqCZI6sGTrTEZ7x8vHTjG6BlJNR0oTQZ48ID0eLIcYEj4HPDjfjow0/uteYjHObJ0qvIo6X9LcojP5hfBID4st41B1Wbaja2Qqpf7/7qlPzJNjK1h4Kh3V9Q5jlmBxoPr8YSUJoY6hXRciBY2obJioHmBpmiazxp/KhtZWDpgc44/z1P2X1GWtGA9DotLES9t3lo1hyCO1wUZKbrxMX5UQrmNq2XXFia9jLvNtJOXYcS5BGpSWrJXCYWgIfPS6w7eC0I+qANLnaFnv3MVHrlFhMZkYFG7jaxMkNuXx21nlWjXL1dGRbs3GKxISrUQ2zqTQdB/Bn9uhscBXyUbwTtqenBl9La6Aux0/2kkfu+v9bIBT59HCNyKZ9vaS3CWqJWFZwqu+cP3UiTMHGDETT+Ox3OU2DIRew3JXBJqCxBB7NFftP3OOHok2g3iTkQbu/gURy6N+fucuyewgRDnCsqfEy1LLQ6vEqSd9dRxAvGRwamtboLrgl4d4rbajo0XBJUkSz4fVA7rdfX2TJk5J+T+SI0G4C53ZRO X-OriginatorOrg: in-advantage.com X-MS-Exchange-CrossTenant-Network-Message-Id: 68f34629-a1ef-46f9-65dd-08d90ebb1c36 X-MS-Exchange-CrossTenant-AuthSource: MWHSPR01MB355.namprd10.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 04 May 2021 05:11:44.9243 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 48e842ca-fbd8-4633-a79d-0c955a7d3aae X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 0kE/vW1TXDOIBMRXYItRPKhNlziE8GFin/QG8r8yJRKSEBUCf7jmxKtKdqEYRnIkkrbnXXjUl37zi7iXUawAkxTGQRerEhfiBvlyeQPE+UI= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR1001MB2399 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Control for external VSC75XX chips can be performed via non-mmio interfaces, e.g. SPI. Adding the offets array (one per target) and the offset element per port allows the ability to track this location that would otherwise be found in the MMIO regmap resource. Tracking this offset in the ocelot driver and allowing the ocelot_regmap_init function to be overloaded with a device-specific initializer. This driver could update the *offset element to handle the value that would otherwise be mapped via resource *res->start. Signed-off-by: Colin Foster --- drivers/net/dsa/ocelot/felix.c | 6 ++++-- drivers/net/dsa/ocelot/felix.h | 2 ++ drivers/net/dsa/ocelot/felix_vsc9959.c | 1 + drivers/net/dsa/ocelot/seville_vsc9953.c | 1 + drivers/net/ethernet/mscc/ocelot_io.c | 27 +++++++++++++++++------- include/soc/mscc/ocelot.h | 5 ++++- 6 files changed, 31 insertions(+), 11 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 628afb47b579..71aa11b209e8 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -1122,7 +1122,8 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) res.start += felix->switch_base; res.end += felix->switch_base; - target = ocelot_regmap_init(ocelot, &res); + target = felix->info->init_regmap(ocelot, &res, + &ocelot->offsets[i]); if (IS_ERR(target)) { dev_err(ocelot->dev, "Failed to map device memory space\n"); @@ -1159,7 +1160,8 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) res.start += felix->switch_base; res.end += felix->switch_base; - target = ocelot_regmap_init(ocelot, &res); + target = felix->info->init_regmap(ocelot, &res, + &ocelot_port->offset); if (IS_ERR(target)) { dev_err(ocelot->dev, "Failed to map memory space for port %d\n", diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index 4d96cad815d5..03ae576e018a 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -47,6 +47,8 @@ struct felix_info { enum tc_setup_type type, void *type_data); void (*port_sched_speed_set)(struct ocelot *ocelot, int port, u32 speed); + struct regmap *(*init_regmap)(struct ocelot *ocelot, + struct resource *res, u32 *offset); }; extern const struct dsa_switch_ops felix_switch_ops; diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index 5ff623ee76a6..87178345116b 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -1362,6 +1362,7 @@ static const struct felix_info felix_info_vsc9959 = { .prevalidate_phy_mode = vsc9959_prevalidate_phy_mode, .port_setup_tc = vsc9959_port_setup_tc, .port_sched_speed_set = vsc9959_sched_speed_set, + .init_regmap = ocelot_regmap_init, }; static irqreturn_t felix_irq_handler(int irq, void *data) diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index 84f93a874d50..d88a9729222c 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -1181,6 +1181,7 @@ static const struct felix_info seville_info_vsc9953 = { .mdio_bus_free = vsc9953_mdio_bus_free, .phylink_validate = vsc9953_phylink_validate, .prevalidate_phy_mode = vsc9953_prevalidate_phy_mode, + .init_regmap = ocelot_regmap_init, }; static int seville_probe(struct platform_device *pdev) diff --git a/drivers/net/ethernet/mscc/ocelot_io.c b/drivers/net/ethernet/mscc/ocelot_io.c index ea4e83410fe4..8f314639faff 100644 --- a/drivers/net/ethernet/mscc/ocelot_io.c +++ b/drivers/net/ethernet/mscc/ocelot_io.c @@ -18,7 +18,8 @@ u32 __ocelot_read_ix(struct ocelot *ocelot, u32 reg, u32 offset) WARN_ON(!target); regmap_read(ocelot->targets[target], - ocelot->map[target][reg & REG_MASK] + offset, &val); + ocelot->offsets[target] + + ocelot->map[target][reg & REG_MASK] + offset, &val); return val; } EXPORT_SYMBOL(__ocelot_read_ix); @@ -30,7 +31,8 @@ void __ocelot_write_ix(struct ocelot *ocelot, u32 val, u32 reg, u32 offset) WARN_ON(!target); regmap_write(ocelot->targets[target], - ocelot->map[target][reg & REG_MASK] + offset, val); + ocelot->offsets[target] + + ocelot->map[target][reg & REG_MASK] + offset, val); } EXPORT_SYMBOL(__ocelot_write_ix); @@ -42,7 +44,8 @@ void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask, u32 reg, WARN_ON(!target); regmap_update_bits(ocelot->targets[target], - ocelot->map[target][reg & REG_MASK] + offset, + ocelot->offsets[target] + + ocelot->map[target][reg & REG_MASK] + offset, mask, val); } EXPORT_SYMBOL(__ocelot_rmw_ix); @@ -55,7 +58,8 @@ u32 ocelot_port_readl(struct ocelot_port *port, u32 reg) WARN_ON(!target); - regmap_read(port->target, ocelot->map[target][reg & REG_MASK], &val); + regmap_read(port->target, + port->offset + ocelot->map[target][reg & REG_MASK], &val); return val; } EXPORT_SYMBOL(ocelot_port_readl); @@ -67,7 +71,8 @@ void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg) WARN_ON(!target); - regmap_write(port->target, ocelot->map[target][reg & REG_MASK], val); + regmap_write(port->target, + port->offset + ocelot->map[target][reg & REG_MASK], val); } EXPORT_SYMBOL(ocelot_port_writel); @@ -85,7 +90,8 @@ u32 __ocelot_target_read_ix(struct ocelot *ocelot, enum ocelot_target target, u32 val; regmap_read(ocelot->targets[target], - ocelot->map[target][reg] + offset, &val); + ocelot->offsets[target] + ocelot->map[target][reg] + offset, + &val); return val; } @@ -93,7 +99,9 @@ void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target, u32 val, u32 reg, u32 offset) { regmap_write(ocelot->targets[target], - ocelot->map[target][reg] + offset, val); + ocelot->offsets[target] + ocelot->map[target][reg] + + offset, + val); } int ocelot_regfields_init(struct ocelot *ocelot, @@ -136,10 +144,13 @@ static struct regmap_config ocelot_regmap_config = { .reg_stride = 4, }; -struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res) +struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res, + u32 *offset) { void __iomem *regs; + *offset = 0; + regs = devm_ioremap_resource(ocelot->dev, res); if (IS_ERR(regs)) return ERR_CAST(regs); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 425ff29d9389..ad45c1af4be9 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -591,6 +591,7 @@ struct ocelot_port { struct ocelot *ocelot; struct regmap *target; + u32 offset; bool vlan_aware; /* VLAN that untagged frames are classified to, on ingress */ @@ -621,6 +622,7 @@ struct ocelot { const struct ocelot_ops *ops; struct regmap *targets[TARGET_MAX]; struct regmap_field *regfields[REGFIELD_MAX]; + u32 offsets[TARGET_MAX]; const u32 *const *map; const struct ocelot_stat_layout *stats_layout; unsigned int num_stats; @@ -780,7 +782,8 @@ static inline void ocelot_drain_cpu_queue(struct ocelot *ocelot, int grp) /* Hardware initialization */ int ocelot_regfields_init(struct ocelot *ocelot, const struct reg_field *const regfields); -struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res); +struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res, + u32 *offset); int ocelot_init(struct ocelot *ocelot); void ocelot_deinit(struct ocelot *ocelot); void ocelot_init_port(struct ocelot *ocelot, int port); From patchwork Tue May 4 05:11:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Colin Foster X-Patchwork-Id: 12237377 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,MSGID_FROM_MTA_HEADER,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CAF20C43460 for ; Tue, 4 May 2021 05:11:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A99646103E for ; Tue, 4 May 2021 05:11:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229947AbhEDFMu (ORCPT ); Tue, 4 May 2021 01:12:50 -0400 Received: from mail-bn7nam10on2118.outbound.protection.outlook.com ([40.107.92.118]:40026 "EHLO NAM10-BN7-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S229738AbhEDFMq (ORCPT ); Tue, 4 May 2021 01:12:46 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=QBqvFtTcqhn7taFAANGHtsqWpX7BFDV/EK6uKz5YtWWyrFkcOTUkHt28Wi7AN+WhnkxPfaQ/XLkvOyZdGtGomUxbBl3/9GbFHHTFWajLGrsmTNfgoVEnroZuNo0aUn74+RYl9nI+wWx3ANgQReywqJcark2aoGS3hz80Ex7+s6Su7RVcipd87jwAfcpfSO9e5/n/cBVYFg7fwcOrQiOq+3517b06uSVqv+gsh4J641QESMf5e2yb5tqDicV4kIOwLsiydUGvwXhNUKBs1apoxZcvBltWTNIpOEJGdK1lpimHUsYKOdX8AIgqK8xa/gnCz5wIM67f90JmuP/mqy7kYQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=4McXCcpTuZaSp0dAYGLBA/oHIDqaY4Wv+zNqLP/V0oY=; b=Nuwc33O5fMdqJj19G3wtlNfXoJKWHOm3+aItz21u+BqzCQUuzg7uJsIhOgTzNQ/BeZP97KAc4p2tgrgBmEHEkQ8bXc0h5kYqfqJy8FSEqJbhl+573pLcMFcGltxPCMlnpkxOuKph69vkC4T8qOe4tT5Y2drnviepTVXFWLc0VluFstLUS5bSWOfg0K5JXn0p5WGGNSU+iGBZlNN6NJFH/1hvYEp9AeG1uf9v2ZugGACYPHysPbOcX+rURznRq6SrfWo1CSLa6H4uOj/tFzj6krkBljQLNqbLUgKJ9BUwEuPCH2HLeQuBjmvME0bbLNXi0X6Hw7HEnSeJyhRyL+5wfw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=in-advantage.com; dmarc=pass action=none header.from=in-advantage.com; dkim=pass header.d=in-advantage.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=inadvantage.onmicrosoft.com; s=selector2-inadvantage-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=4McXCcpTuZaSp0dAYGLBA/oHIDqaY4Wv+zNqLP/V0oY=; b=z1FtQO3sK4lkSZQ445j5RWxI86gPRTi6M22IOWEjnIUDn07W8MUb+Kws0n4DX2IRkfhKJrde8MRAdD0Gg/m3KTPnzGLQZnr0Ef7JnnWj4IWX1CKxlof02FD9XNe4GQ6UhGalOHFe/f8cSBmdRkp9OJTshQqugkLB3oCarU7ZTe0= Authentication-Results: in-advantage.com; dkim=none (message not signed) header.d=none;in-advantage.com; dmarc=none action=none header.from=in-advantage.com; Received: from MWHSPR01MB355.namprd10.prod.outlook.com (2603:10b6:301:6c::37) by MWHPR1001MB2399.namprd10.prod.outlook.com (2603:10b6:301:30::31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4065.25; Tue, 4 May 2021 05:11:49 +0000 Received: from MWHSPR01MB355.namprd10.prod.outlook.com ([fe80::c559:f270:c9b5:a928]) by MWHSPR01MB355.namprd10.prod.outlook.com ([fe80::c559:f270:c9b5:a928%6]) with mapi id 15.20.4065.039; Tue, 4 May 2021 05:11:48 +0000 From: Colin Foster To: colin.foster@in-advantage.com Cc: Rob Herring , Vladimir Oltean , Claudiu Manoil , Alexandre Belloni , UNGLinuxDriver@microchip.com (supporter:OCELOT ETHERNET SWITCH DRIVER), Andrew Lunn , Vivien Didelot , Florian Fainelli , "David S. Miller" , Jakub Kicinski , Russell King , devicetree@vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS), linux-kernel@vger.kernel.org (open list), netdev@vger.kernel.org (open list:OCELOT ETHERNET SWITCH DRIVER) Subject: [RFC PATCH vN net-next 2/2] net: mscc: ocelot: add support for VSC75XX SPI control Date: Mon, 3 May 2021 22:11:27 -0700 Message-Id: <20210504051130.1207550-2-colin.foster@in-advantage.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210504051130.1207550-1-colin.foster@in-advantage.com> References: <20210504051130.1207550-1-colin.foster@in-advantage.com> X-Originating-IP: [67.185.175.147] X-ClientProxiedBy: CO2PR04CA0133.namprd04.prod.outlook.com (2603:10b6:104::11) To MWHSPR01MB355.namprd10.prod.outlook.com (2603:10b6:301:6c::37) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from localhost.localdomain (67.185.175.147) by CO2PR04CA0133.namprd04.prod.outlook.com (2603:10b6:104::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4087.39 via Frontend Transport; Tue, 4 May 2021 05:11:48 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: a3c36c50-e184-4158-e235-08d90ebb1eaf X-MS-TrafficTypeDiagnostic: MWHPR1001MB2399: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:4125; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: cWDvCTUETNZOH+tutA7LpOEa1136XkHC4/LzQRsPIr0XXnLZjJoa31I1E2lji1KYs0koTSp3nlniWLoImcAfh3eGeqm2T57GXAfbXLEdEd8IAHJaYZcNQdEEOdTw9khxKwniq1NrXurljPqpiRpYk8wem23TDYLe4076UsmHHWNbTx6+8cBqE98Eo0e0E6MaEviG1AhDnW2jelAQTutKhc/LMbDoaXo6ehgq26rIi90xPQDGc1+VucldVnMFQ0hmOj8OCV3Xw9NV94VE19BU35mvc0vYYZ786mtjHkBStUOm+2GkoIlgy4nDm05qnwkRjY7y4Ye4BOpDZABaEpabzoBWAcvhFqq19YE1jxPCmL451evmE0NRFhF3UOXWk7nuzryV3UfGXUMd61KlLHQzQTChnpSQI5OmbmZb/7LF/rBM7V+42gUrA8GazKm59bGqS6j3ytSzueUon/pCHPhxbNHXAiopsNc4bmW8RVf6GisexBJWxFRwLAmszQAZc354azFLhcZZC659MUDE9C6c//y7jWu56Z4zDvoP9vKBHFaiCvPK6qQlgkf827ozgatb5SCFGEsGKZRC9W95RMrEevVsKVFz0jsN9OeaBu9W4fUc2ZDsbb7xK3v2NVq4Q/+syeSffD0reGm5kYFxMmQhUSL01gz1avFpT0pfgOHUQrEvXu2N40eNUSnDhsj/ogEc6mknOxA/gy9tDmeTAgBJ4bQicS3nMdktfuEq9I9EOgt7a5wAXWUhqdkaZ475O4VTRLxfiDGlbpdR5kldMMn7YA== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:MWHSPR01MB355.namprd10.prod.outlook.com;PTR:;CAT:NONE;SFS:(366004)(136003)(396003)(376002)(39830400003)(346002)(66946007)(86362001)(5660300002)(44832011)(36756003)(66476007)(956004)(52116002)(66556008)(966005)(6666004)(4326008)(478600001)(2616005)(6506007)(2906002)(34206002)(54906003)(6512007)(1076003)(316002)(30864003)(6486002)(7416002)(16526019)(26005)(37006003)(38350700002)(8676002)(38100700002)(186003)(8936002)(83380400001)(69590400013)(579004);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData: qRHmE4EFW5JkPp/V0ElQ4DAJBxC+Hzu2YKYAAaBiG/gsqYjJbipZi3/Vv2VB3TPA4enLfuxgUNbDyzoFO2PlF5FeQvygWyaWs/iitQVo3pzfahDptVvWWXCRlu+Q1sQ+CgDUWOKuOHA2OI/hlTWHiJQGk+GgjoBINYz9pvZ5PAZEZTrPjDxOQ+g0wcYZJS+yYWPNI4HMcE1PXwxCk737q6729qT5dQEjTA7lIdvj749wJ0Cq8XGpgTBpQs8BcMISf5LOJLGrvYkVgVs7Mciq4VvQZusNL8adwo3FCjpY7FzL6dw/Xexmr1slI9JJbHjFOtA84Y8d44I6Bbg2QSsfpsUzBtmH70QHLUQ/c7F0Z5QG+CUKSF1WGJ9Z5dxMIu+tNE3YElwEks2cxqOlF+1YUFCK5OplU7Zm7PBo3YX4DpKX9DIGnVH6E7FmtRrzxTOiuCo7WQEO6ugrOXPDSuoMy+CevjlU5eM4r8CurGiH8WGcl7GEnH9Q3VqgLgheDODTraAYX5lozspsOK4Ilhe0QivuKbt8mDy4kOZ1SXJOoc6lYfjyqUC19TuphOhwiFBeUAsC/gt+ai/ndDDg5e4jqopYqzW9BD8Ixzkuz8T+8ciEfwqrsqOd/yAAGzDaCSKht/gesDOOuwLgJd2BCjTk+d0FRaAG4WVazHc71iQnbV9u9WKTmTjG3JMHyMTPT0LqSMeVrQwDWt+7JeoVBXW9VtIPisU/u+97adpW9zebtKdTjFkc1vgCTPSQo1LLJR1e82jqLSyVzBi8ExVu66URNY+dzZP3P3kCExqv5l83L7hMsDqBx2+JKML4zFynlkauYqgGbp56j5SCiCusYqMWqk3IQZAAVjDJ57POwpi3L5LRSOt86U0bmZZnjmacYDKzKAQLWagmxt5s+ZtIoDpgk+QNhURIesfBCCbPq6io0roURfFfLhoLBAR4vRGUUhoxv0R6ejTY14aK31bDD06evqDhqbmxS7mnRXak5RqmIG7R7pM+ku4wIwsldLuGC0JjfFEwEmqiS+iFNeL/cl9nhbXu4S8M0PCaVV83/Ka0JprQMBDEXF7sMwSP3UECRqXOdTxCLmgAh7lKv1R61MNufi5fWtWz6kulUhL+K1UHlFoWJ5BBUIQ0SKDri/tpe3719uSaHYp9ak18uXhaEthq1iAD3gut7Q5C2nOR2AmXtDZDTPNy2kU4q+SohxYIW4f5tLd9ysdDOj7s6jVXQa8aYQXAuQJxUIDxubMIR17HlAmu41E2Vu2e3lg8zr93Zc/YTopcvfA7ABc83pNl2kjnywVHMV5GD9s4yBEoaTuQWVfd3e+gUg8E15KI+soswbgC X-OriginatorOrg: in-advantage.com X-MS-Exchange-CrossTenant-Network-Message-Id: a3c36c50-e184-4158-e235-08d90ebb1eaf X-MS-Exchange-CrossTenant-AuthSource: MWHSPR01MB355.namprd10.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 04 May 2021 05:11:48.9020 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 48e842ca-fbd8-4633-a79d-0c955a7d3aae X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 75oyOS5Z3ptshFc1EZX3wAMHYsSZ/FuNBiAF00jjfCNp2oHjXJfIRwACBEX0XlPo0Gsc+nPWqJbQ2Q0smAdwu6qz5aoyzRIZwh+Ia7J/oOU= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR1001MB2399 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Add support for control for VSC75XX chips over SPI control. Starting with the VSC9959 code, this will utilize a spi bus instead of PCIe or memory-mapped IO to control the chip. Signed-off-by: Colin Foster --- arch/arm/boot/dts/rpi-vsc7512-spi-overlay.dts | 124 ++ drivers/net/dsa/ocelot/Kconfig | 11 + drivers/net/dsa/ocelot/Makefile | 5 + drivers/net/dsa/ocelot/felix_vsc7512_spi.c | 1214 +++++++++++++++++ include/soc/mscc/ocelot.h | 15 + 5 files changed, 1369 insertions(+) create mode 100644 arch/arm/boot/dts/rpi-vsc7512-spi-overlay.dts create mode 100644 drivers/net/dsa/ocelot/felix_vsc7512_spi.c diff --git a/arch/arm/boot/dts/rpi-vsc7512-spi-overlay.dts b/arch/arm/boot/dts/rpi-vsc7512-spi-overlay.dts new file mode 100644 index 000000000000..f2dd8a7edc56 --- /dev/null +++ b/arch/arm/boot/dts/rpi-vsc7512-spi-overlay.dts @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2021 Innovative Advantage Inc - https://www.in-advantage.com/ + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835"; + + fragment@0 { + target = <&spi0_cs_pins>; + frag0: __overlay__ { + brcm,pins = <8>; + }; + }; + + fragment@1 { + target = <&spidev0>; + __overlay__ { + status = "disabled"; + }; + }; + + fragment@2 { + target = <&spidev1>; + __overlay__ { + status = "disabled"; + }; + }; + + fragment@3 { + target = <&spi0>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + cs-gpios = <&gpio 8 1>; + status = "okay"; + + vsc7512: vsc7512@0{ + compatible = "mscc,vsc7512"; + spi-max-frequency = <250000>; + reg = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + ethernet = <ðernet>; + phy-mode = "internal"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + port@1 { + reg = <1>; + label = "swp1"; + status = "disabled"; + }; + + port@2 { + reg = <2>; + label = "swp2"; + status = "disabled"; + }; + + port@3 { + reg = <3>; + label = "swp3"; + status = "disabled"; + }; + + port@4 { + reg = <4>; + label = "swp4"; + status = "disabled"; + }; + + port@5 { + reg = <5>; + label = "swp5"; + status = "disabled"; + }; + + port@6 { + reg = <6>; + label = "swp6"; + status = "disabled"; + }; + + port@7 { + reg = <7>; + label = "swp7"; + status = "disabled"; + }; + + port@8 { + reg = <8>; + label = "swp8"; + status = "disabled"; + }; + + port@9 { + reg = <9>; + label = "swp9"; + status = "disabled"; + }; + + port@10 { + reg = <10>; + label = "swp10"; + status = "disabled"; + }; + }; + }; + }; + }; +}; diff --git a/drivers/net/dsa/ocelot/Kconfig b/drivers/net/dsa/ocelot/Kconfig index 932b6b6fe817..2db147ce9fe7 100644 --- a/drivers/net/dsa/ocelot/Kconfig +++ b/drivers/net/dsa/ocelot/Kconfig @@ -14,6 +14,17 @@ config NET_DSA_MSCC_FELIX This driver supports the VSC9959 (Felix) switch, which is embedded as a PCIe function of the NXP LS1028A ENETC RCiEP. +config NET_DSA_MSCC_FELIX_SPI + tristate "Ocelot / Felix Ethernet SPI switch support" + depends on NET_DSA && SPI + depends on NET_VENDOR_MICROSEMI + select MSCC_OCELOT_SWITCH_LIB + select NET_DSA_TAG_OCELOT_8021Q + select NET_DSA_TAG_OCELOT + select PCS_LYNX + help + This driver supports the VSC75XX chips when controlled through SPI. + config NET_DSA_MSCC_SEVILLE tristate "Ocelot / Seville Ethernet switch support" depends on NET_DSA diff --git a/drivers/net/dsa/ocelot/Makefile b/drivers/net/dsa/ocelot/Makefile index f6dd131e7491..f2c9c52ba76c 100644 --- a/drivers/net/dsa/ocelot/Makefile +++ b/drivers/net/dsa/ocelot/Makefile @@ -1,11 +1,16 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_NET_DSA_MSCC_FELIX) += mscc_felix.o +obj-$(CONFIG_NET_DSA_MSCC_FELIX_SPI) += mscc_felix_spi.o obj-$(CONFIG_NET_DSA_MSCC_SEVILLE) += mscc_seville.o mscc_felix-objs := \ felix.o \ felix_vsc9959.o +mscc_felix_spi-objs := \ + felix.o \ + felix_vsc7512_spi.o + mscc_seville-objs := \ felix.o \ seville_vsc9953.o diff --git a/drivers/net/dsa/ocelot/felix_vsc7512_spi.c b/drivers/net/dsa/ocelot/felix_vsc7512_spi.c new file mode 100644 index 000000000000..1cb5758b752c --- /dev/null +++ b/drivers/net/dsa/ocelot/felix_vsc7512_spi.c @@ -0,0 +1,1214 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* Copyright 2017 Microsemi Corporation + * Copyright 2018-2019 NXP Semiconductors + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "felix.h" + +#define VSC7512_TAS_GCL_ENTRY_MAX 63 + +// Note: These addresses and offsets are all shifted down +// by two. This is because the SPI protocol needs them to +// be before they get sent out. +// +// An alternative is to keep them standardized, but then +// a separate spi_bus regmap would need to be defined. +// +// That might be optimal though. The 'Read' protocol of +// the VSC driver might be much quicker if we add padding +// bytes, which I don't think regmap supports. +static const u32 vsc7512_ana_regmap[] = { + REG(ANA_ADVLEARN, 0x2400), + REG(ANA_VLANMASK, 0x2401), + REG_RESERVED(ANA_PORT_B_DOMAIN), + REG(ANA_ANAGEFIL, 0x2403), + REG(ANA_ANEVENTS, 0x2404), + REG(ANA_STORMLIMIT_BURST, 0x2405), + REG(ANA_STORMLIMIT_CFG, 0x2406), + REG(ANA_ISOLATED_PORTS, 0x240a), + REG(ANA_COMMUNITY_PORTS, 0x240b), + REG(ANA_AUTOAGE, 0x240c), + REG(ANA_MACTOPTIONS, 0x240d), + REG(ANA_LEARNDISC, 0x240e), + REG(ANA_AGENCTRL, 0x240f), + REG(ANA_MIRRORPORTS, 0x2410), + REG(ANA_EMIRRORPORTS, 0x2411), + REG(ANA_FLOODING, 0x2412), + REG(ANA_FLOODING_IPMC, 0x2413), + REG(ANA_SFLOW_CFG, 0x2414), + REG(ANA_PORT_MODE, 0x2420), + REG(ANA_PGID_PGID, 0x2300), + REG(ANA_TABLES_ANMOVED, 0x22cc), + REG(ANA_TABLES_MACHDATA, 0x22cd), + REG(ANA_TABLES_MACLDATA, 0x22ce), + REG(ANA_TABLES_MACACCESS, 0x22cf), + REG(ANA_TABLES_MACTINDX, 0x22d0), + REG(ANA_TABLES_VLANACCESS, 0x22d1), + REG(ANA_TABLES_VLANTIDX, 0x22d2), + REG(ANA_TABLES_ENTRYLIM, 0x22c0), + REG(ANA_TABLES_PTP_ID_HIGH, 0x22d5), + REG(ANA_TABLES_PTP_ID_LOW, 0x22d6), + REG(ANA_PORT_VLAN_CFG, 0x1c00), + REG(ANA_PORT_DROP_CFG, 0x1c01), + REG(ANA_PORT_QOS_CFG, 0x1c02), + REG(ANA_PORT_VCAP_CFG, 0x1c03), + REG(ANA_PORT_VCAP_S1_KEY_CFG, 0x1c04), + REG(ANA_PORT_VCAP_S2_CFG, 0x1c07), + REG(ANA_PORT_PCP_DEI_MAP, 0x1c08), + REG(ANA_PORT_CPU_FWD_CFG, 0x1c18), + REG(ANA_PORT_CPU_FWD_BPDU_CFG, 0x1c19), + REG(ANA_PORT_CPU_FWD_GARP_CFG, 0x1c1a), + REG(ANA_PORT_CPU_FWD_CCM_CFG, 0x1c1b), + REG(ANA_PORT_PORT_CFG, 0x1c1c), + REG(ANA_PORT_POL_CFG, 0x1c1d), + REG(ANA_PORT_PTP_CFG, 0x1c1e), + REG(ANA_PORT_PTP_DLY1_CFG, 0x1c1f), + REG(ANA_PORT_PTP_DLY2_CFG, 0x1c20), + REG(ANA_PFC_PFC_CFG, 0x2200), + REG_RESERVED(ANA_PFC_PFC_TIMER), + REG_RESERVED(ANA_IPT_OAM_MEP_CFG), + REG_RESERVED(ANA_IPT_IPT), + REG_RESERVED(ANA_PPT_PPT), + REG_RESERVED(ANA_FID_MAP_FID_MAP), + REG(ANA_AGGR_CFG, 0x242d), + REG(ANA_CPUQ_CFG, 0x242e), + REG_RESERVED(ANA_CPUQ_CFG2), + REG(ANA_CPUQ_8021_CFG, 0x242f), + REG(ANA_DSCP_CFG, 0x2440), + REG(ANA_DSCP_REWR_CFG, 0x2480), + REG(ANA_VCAP_RNG_TYPE_CFG, 0x2490), + REG(ANA_VCAP_RNG_VAL_CFG, 0x2498), + REG_RESERVED(ANA_VRAP_CFG), + REG_RESERVED(ANA_VRAP_HDR_DATA), + REG_RESERVED(ANA_VRAP_HDR_MASK), + REG(ANA_DISCARD_CFG, 0x24a3), + REG(ANA_FID_CFG, 0x24a4), + REG(ANA_POL_PIR_CFG, 0x1000), + REG(ANA_POL_CIR_CFG, 0x1001), + REG(ANA_POL_MODE_CFG, 0x1002), + REG(ANA_POL_PIR_STATE, 0x1003), + REG(ANA_POL_CIR_STATE, 0x1004), + REG_RESERVED(ANA_POL_STATE), + REG(ANA_POL_FLOWC, 0x22e0), + REG(ANA_POL_HYST, 0x22fb), + REG_RESERVED(ANA_POL_MISC_CFG), +}; + +static const u32 vsc7512_qs_regmap[] = { + REG(QS_XTR_GRP_CFG, 0x0000), + REG(QS_XTR_RD, 0x0002), + REG(QS_XTR_FRM_PRUNING, 0x004), + REG(QS_XTR_FLUSH, 0x0006), + REG(QS_XTR_DATA_PRESENT, 0x0007), + + REG(QS_INJ_GRP_CFG, 0x0009), + REG(QS_INJ_WR, 0x000b), + REG(QS_INJ_CTRL, 0x000d), + REG(QS_INJ_STATUS, 0x000f), + REG(QS_INJ_ERR, 0x0010), + REG_RESERVED(QS_INH_DBG), +}; + +static const u32 vsc7512_vcap_regmap[] = { + REG(VCAP_CORE_UPDATE_CTRL, 0x000000), + REG(VCAP_CORE_MV_CFG, 0x000001), + REG(VCAP_CACHE_ENTRY_DAT, 0x000002), + REG(VCAP_CACHE_MASK_DAT, 0x000042), + REG(VCAP_CACHE_ACTION_DAT, 0x000082), + REG(VCAP_CACHE_CNT_DAT, 0x0000c2), + REG(VCAP_CACHE_TG_DAT, 0x0000e2), + REG(VCAP_CONST_VCAP_VER, 0x0000e6), + REG(VCAP_CONST_ENTRY_WIDTH, 0x0000e7), + REG(VCAP_CONST_ENTRY_CNT, 0x0000e8), + REG(VCAP_CONST_ENTRY_SWCNT, 0x0000e9), + REG(VCAP_CONST_ENTRY_TG_WIDTH, 0x0000ea), + REG(VCAP_CONST_ACTION_DEF_CNT, 0x0000eb), + REG(VCAP_CONST_ACTION_WIDTH, 0x0000ec), + REG(VCAP_CONST_CNT_WIDTH, 0x0000ed), + REG(VCAP_CONST_CORE_CNT, 0x0000ee), + REG(VCAP_CONST_IF_CNT, 0x0000ef), +}; + +static const u32 vsc7512_qsys_regmap[] = { + REG(QSYS_PORT_MODE, 0x4480), + REG(QSYS_SWITCH_PORT_MODE, 0x448d), + REG(QSYS_STAT_CNT_CFG, 0x4499), + REG(QSYS_EEE_CFG, 0x449a), + REG(QSYS_EEE_THRES, 0x44a5), + REG(QSYS_IGR_NO_SHARING, 0x44a6), + REG(QSYS_EGR_NO_SHARING, 0x44a7), + REG(QSYS_SW_STATUS, 0x44a8), + REG(QSYS_EXT_CPU_CFG, 0x44b4), + REG_RESERVED(QSYS_PAD_CFG), + REG(QSYS_CPU_GROUP_MAP, 0x44b6), + REG_RESERVED(QSYS_QMAP), + REG_RESERVED(QSYS_ISDX_SGRP), + REG_RESERVED(QSYS_TIMED_FRAME_ENTRY), + REG(QSYS_TFRM_MISC, 0x44c4), + REG(QSYS_TFRM_PORT_DLY, 0x44c5), + REG(QSYS_TFRM_TIMER_CFG_1, 0x44c6), + REG(QSYS_TFRM_TIMER_CFG_2, 0x44c7), + REG(QSYS_TFRM_TIMER_CFG_3, 0x44c8), + REG(QSYS_TFRM_TIMER_CFG_4, 0x44c9), + REG(QSYS_TFRM_TIMER_CFG_5, 0x44ca), + REG(QSYS_TFRM_TIMER_CFG_6, 0x44cb), + REG(QSYS_TFRM_TIMER_CFG_7, 0x44cc), + REG(QSYS_TFRM_TIMER_CFG_8, 0x44cd), + REG(QSYS_RED_PROFILE, 0x44ce), + REG(QSYS_RES_QOS_MODE, 0x44de), + REG(QSYS_RES_CFG, 0x4800), + REG(QSYS_RES_STAT, 0x4801), + REG(QSYS_EGR_DROP_MODE, 0x44df), + REG(QSYS_EQ_CTRL, 0x44e0), + REG_RESERVED(QSYS_EVENTS_CORE), + REG(QSYS_CIR_CFG, 0x0000), + REG(QSYS_EIR_CFG, 0x0001), + REG(QSYS_SE_CFG, 0x0002), + REG(QSYS_SE_DWRR_CFG, 0x0003), + REG_RESERVED(QSYS_SE_CONNECT), + REG(QSYS_SE_DLB_SENSE, 0x0010), + REG(QSYS_CIR_STATE, 0x0011), + REG(QSYS_EIR_STATE, 0x0012), + REG_RESERVED(QSYS_SE_STATE), + REG(QSYS_HSCH_MISC_CFG, 0x44e2), +}; + +static const u32 vsc7512_rew_regmap[] = { + REG(REW_PORT_VLAN_CFG, 0x000), + REG(REW_TAG_CFG, 0x001), + REG(REW_PORT_CFG, 0x002), + REG(REW_DSCP_CFG, 0x003), + REG(REW_PCP_DEI_QOS_MAP_CFG, 0x004), + REG(REW_PTP_CFG, 0x014), + REG(REW_PTP_DLY1_CFG, 0x015), + REG(REW_RED_TAG_CFG, 0x016), + REG(REW_DSCP_REMAP_DP1_CFG, 0x104), + REG(REW_DSCP_REMAP_CFG, 0x144), + REG_RESERVED(REW_STAT_CFG), + REG_RESERVED(REW_REW_STICKY), + REG_RESERVED(REW_PPT), +}; + +static const u32 vsc7512_sys_regmap[] = { + REG(SYS_COUNT_RX_OCTETS, 0x000), + REG(SYS_COUNT_RX_MULTICAST, 0x002), + REG(SYS_COUNT_RX_SHORTS, 0x004), + REG(SYS_COUNT_RX_FRAGMENTS, 0x005), + REG(SYS_COUNT_RX_JABBERS, 0x006), + REG(SYS_COUNT_RX_64, 0x009), + REG(SYS_COUNT_RX_65_127, 0x00a), + REG(SYS_COUNT_RX_128_255, 0x00b), + REG(SYS_COUNT_RX_256_1023, 0x00c), + REG(SYS_COUNT_RX_1024_1526, 0x00d), + REG(SYS_COUNT_RX_1527_MAX, 0x00e), + REG(SYS_COUNT_RX_LONGS, 0x011), + REG(SYS_COUNT_TX_OCTETS, 0x080), + REG(SYS_COUNT_TX_COLLISION, 0x084), + REG(SYS_COUNT_TX_DROPS, 0x085), + REG(SYS_COUNT_TX_64, 0x087), + REG(SYS_COUNT_TX_65_127, 0x088), + REG(SYS_COUNT_TX_128_511, 0x089), + REG(SYS_COUNT_TX_512_1023, 0x08a), + REG(SYS_COUNT_TX_1024_1526, 0x08b), + REG(SYS_COUNT_TX_1527_MAX, 0x08c), + REG(SYS_COUNT_TX_AGING, 0x09e), + REG(SYS_RESET_CFG, 0x142), + REG(SYS_VLAN_ETYPE_CFG, 0x144), + REG(SYS_PORT_MODE, 0x145), + REG(SYS_FRONT_PORT_MODE, 0x152), + REG(SYS_FRM_AGING, 0x15d), + REG(SYS_STAT_CFG, 0x15e), + REG_RESERVED(SYS_MISC_CFG), + REG(SYS_REW_MAC_HIGH_CFG, 0x16c), + REG(SYS_REW_MAC_LOW_CFG, 0x177), + REG(SYS_PAUSE_CFG, 0x182), + REG(SYS_PAUSE_TOT_CFG, 0x18e), + REG(SYS_ATOP, 0x18f), + REG(SYS_ATOP_TOT_CFG, 0x19b), + REG(SYS_MAC_FC_CFG, 0x19c), + REG(SYS_MMGT, 0x1a7), + REG_RESERVED(SYS_MMGT_FAST), + REG_RESERVED(SYS_EVENTS_DIF), + REG_RESERVED(SYS_EVENTS_CORE), + REG_RESERVED(SYS_CNT), + REG(SYS_PTP_STATUS, 0x1ae), + REG(SYS_PTP_TXSTAMP, 0x1af), + REG(SYS_PTP_NXT, 0x1b0), + REG(SYS_PTP_CFG, 0x1b1), + REG_RESERVED(SYS_CM_ADDR), + REG_RESERVED(SYS_CM_DATA_WR), + REG_RESERVED(SYS_CM_DATA_RD), + REG_RESERVED(SYS_CM_OP), + REG_RESERVED(SYS_CM_DATA), +}; + +static const u32 vsc7512_ptp_regmap[] = { + REG(PTP_PIN_CFG, 0x000000), + REG(PTP_PIN_TOD_SEC_MSB, 0x000001), + REG(PTP_PIN_TOD_SEC_LSB, 0x000002), + REG(PTP_PIN_TOD_NSEC, 0x000003), + REG(PTP_PIN_WF_HIGH_PERIOD, 0x000005), + REG(PTP_PIN_WF_LOW_PERIOD, 0x000006), + REG(PTP_CFG_MISC, 0x000028), + REG(PTP_CLK_CFG_ADJ_CFG, 0x000029), + REG(PTP_CLK_CFG_ADJ_FREQ, 0x00002a), +}; + +static const u32 vsc7512_gcb_regmap[] = { + REG(GCB_SOFT_RST, 0xc002), +}; + +static const u32 vsc7512_dev_gmii_regmap[] = { + REG(DEV_CLOCK_CFG, 0x0), + REG(DEV_PORT_MISC, 0x1), + REG(DEV_EEE_CFG, 0x3), + REG(DEV_RX_PATH_DELAY, 0x4), + REG(DEV_TX_PATH_DELAY, 0x5), + REG(DEV_PTP_PREDICT_CFG, 0x6), + REG(DEV_MAC_ENA_CFG, 0x7), + REG(DEV_MAC_MODE_CFG, 0x8), + REG(DEV_MAC_MAXLEN_CFG, 0x9), + REG(DEV_MAC_TAGS_CFG, 0xa), + REG(DEV_MAC_ADV_CHK_CFG, 0xb), + REG(DEV_MAC_IFG_CFG, 0xc), + REG(DEV_MAC_HDX_CFG, 0xd), + REG(DEV_MAC_DBG_CFG, 0xe), + REG(DEV_MAC_FC_MAC_LOW_CFG, 0xf), + REG(DEV_MAC_FC_MAC_HIGH_CFG, 0x10), + REG(DEV_MAC_STICKY, 0x11), + REG_RESERVED(PCS1G_CFG), + REG_RESERVED(PCS1G_MODE_CFG), + REG_RESERVED(PCS1G_SD_CFG), + REG_RESERVED(PCS1G_ANEG_CFG), + REG_RESERVED(PCS1G_ANEG_NP_CFG), + REG_RESERVED(PCS1G_LB_CFG), + REG_RESERVED(PCS1G_DBG_CFG), + REG_RESERVED(PCS1G_CDET_CFG), + REG_RESERVED(PCS1G_ANEG_STATUS), + REG_RESERVED(PCS1G_ANEG_NP_STATUS), + REG_RESERVED(PCS1G_LINK_STATUS), + REG_RESERVED(PCS1G_LINK_DOWN_CNT), + REG_RESERVED(PCS1G_STICKY), + REG_RESERVED(PCS1G_DEBUG_STATUS), + REG_RESERVED(PCS1G_LPI_CFG), + REG_RESERVED(PCS1G_LPI_WAKE_ERROR_CNT), + REG_RESERVED(PCS1G_LPI_STATUS), + REG_RESERVED(PCS1G_TSTPAT_MODE_CFG), + REG_RESERVED(PCS1G_TSTPAT_STATUS), + REG_RESERVED(DEV_PCS_FX100_CFG), + REG_RESERVED(DEV_PCS_FX100_STATUS), +}; + +static const u32 vsc7512_cpu_org_regmap[] = { + REG(DEV_CPUORG_IF_CTRL, 0x0000), + REG(DEV_CPUORG_IF_CFGSTAT, 0x0001), + REG(DEV_CPUORG_ORG_CFG, 0x0002), + REG(DEV_CPUORG_ERR_CNTS, 0x0003), + REG(DEV_CPUORG_TIMEOUT_CFG, 0x0004), + REG(DEV_CPUORG_GPR, 0x0005), + REG(DEV_CPUORG_MAILBOX_SET, 0x0006), + REG(DEV_CPUORG_MAILBOX_CLR, 0x0007), + REG(DEV_CPUORG_MAILBOX, 0x0008), + REG(DEV_CPUORG_SEMA_CFG, 0x0009), + REG(DEV_CPUORG_SEMA0, 0x000a), + REG(DEV_CPUORG_SEMA0_OWNER, 0x000b), + REG(DEV_CPUORG_SEMA1, 0x000c), + REG(DEV_CPUORG_SEMA1_OWNER, 0x000d), +}; + +static const u32 *vsc7512_regmap[TARGET_MAX] = { + [ANA] = vsc7512_ana_regmap, + [QS] = vsc7512_qs_regmap, + [QSYS] = vsc7512_qsys_regmap, + [REW] = vsc7512_rew_regmap, + [SYS] = vsc7512_sys_regmap, + [S0] = vsc7512_vcap_regmap, + [S1] = vsc7512_vcap_regmap, + [S2] = vsc7512_vcap_regmap, + [PTP] = vsc7512_ptp_regmap, + [GCB] = vsc7512_gcb_regmap, + [DEV_GMII] = vsc7512_dev_gmii_regmap, + [DEV_CPUORG] = vsc7512_cpu_org_regmap, +}; + +static int vsc7512_soft_rst_status(struct ocelot *ocelot) +{ + int val; + + ocelot_field_read(ocelot, GCB_SOFT_RST_SWC_RST, &val); + + return val; +} + +#define VSC7512_INIT_TIMEOUT 50000 +#define VSC7512_GCB_RST_SLEEP 100 + +static int vsc7512_reset(struct ocelot *ocelot) +{ + int val, err; + + ocelot_field_write(ocelot, GCB_SOFT_RST_SWC_RST, 1); + + err = readx_poll_timeout(vsc7512_soft_rst_status, ocelot, val, !val, + VSC7512_GCB_RST_SLEEP, VSC7512_INIT_TIMEOUT); + if (err) { + dev_err(ocelot->dev, "timeout: switch core reset\n"); + return err; + } + + return 0; +} + +static u16 vsc7512_wm_enc(u16 value) +{ + WARN_ON(value >= 16 * BIT(8)); + + if (value >= BIT(8)) + return BIT(8) | (value / 16); + + return value; +} + +static const struct ocelot_ops vsc7512_ops = { + .reset = vsc7512_reset, + .wm_enc = vsc7512_wm_enc, + .port_to_netdev = felix_port_to_netdev, + .netdev_to_port = felix_netdev_to_port, +}; + +/* Addresses are relative to the SPI device's base address, downshifted by 2*/ +static const struct resource vsc7512_target_io_res[TARGET_MAX] = { + [ANA] = { + .start = 0x1c620000, + .end = 0x1c623fff, + .name = "ana", + }, + [QS] = { + .start = 0x1c420000, + .end = 0x1c42003f, + .name = "qs", + }, + [QSYS] = { + .start = 0x1c600000, + .end = 0x1c607fff, + .name = "qsys", + }, + [REW] = { + .start = 0x1c40c000, + .end = 0x1c40ffff, + .name = "rew", + }, + [SYS] = { + .start = 0x1c404000, + .end = 0x1c407fff, + .name = "sys", + }, + [S0] = { + .start = 0x1c410000, + .end = 0x1c4100ff, + .name = "s0", + }, + [S1] = { + .start = 0x1c414000, + .end = 0x1c4140ff, + .name = "s1", + }, + [S2] = { + .start = 0x1c418000, + .end = 0x1c4180ff, + .name = "s2", + }, + [GCB] = { + .start = 0x1c41c000, + .end = 0x1c41c07f, + .name = "devcpu_gcb", + }, + [DEV_CPUORG] = { + .start = 0x1c400000, + .end = 0x1c4000ff, + .name = "devcpu_org", + }, +}; + +static const struct resource vsc7512_port_io_res[] = { + { + .start = 0x1c478000, + .end = 0x1c47bfff, + .name = "port0", + }, + { + .start = 0x1c47c000, + .end = 0x1c47ffff, + .name = "port1", + }, + { + .start = 0x1c480000, + .end = 0x1c483fff, + .name = "port2", + }, + { + .start = 0x1c484000, + .end = 0x1c487fff, + .name = "port3", + }, + { + .start = 0x1c488000, + .end = 0x1c48bfff, + .name = "port4", + }, + { + .start = 0x1c48c000, + .end = 0x1c48ffff, + .name = "port5", + }, +}; + +static const struct reg_field vsc7512_regfields[REGFIELD_MAX] = { + [ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 11, 11), + [ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 10), + [ANA_ANEVENTS_MSTI_DROP] = REG_FIELD(ANA_ANEVENTS, 27, 27), + [ANA_ANEVENTS_ACLKILL] = REG_FIELD(ANA_ANEVENTS, 26, 26), + [ANA_ANEVENTS_ACLUSED] = REG_FIELD(ANA_ANEVENTS, 25, 25), + [ANA_ANEVENTS_AUTOAGE] = REG_FIELD(ANA_ANEVENTS, 24, 24), + [ANA_ANEVENTS_VS2TTL1] = REG_FIELD(ANA_ANEVENTS, 23, 23), + [ANA_ANEVENTS_STORM_DROP] = REG_FIELD(ANA_ANEVENTS, 22, 22), + [ANA_ANEVENTS_LEARN_DROP] = REG_FIELD(ANA_ANEVENTS, 21, 21), + [ANA_ANEVENTS_AGED_ENTRY] = REG_FIELD(ANA_ANEVENTS, 20, 20), + [ANA_ANEVENTS_CPU_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 19, 19), + [ANA_ANEVENTS_AUTO_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 18, 18), + [ANA_ANEVENTS_LEARN_REMOVE] = REG_FIELD(ANA_ANEVENTS, 17, 17), + [ANA_ANEVENTS_AUTO_LEARNED] = REG_FIELD(ANA_ANEVENTS, 16, 16), + [ANA_ANEVENTS_AUTO_MOVED] = REG_FIELD(ANA_ANEVENTS, 15, 15), + [ANA_ANEVENTS_DROPPED] = REG_FIELD(ANA_ANEVENTS, 14, 14), + [ANA_ANEVENTS_CLASSIFIED_DROP] = REG_FIELD(ANA_ANEVENTS, 13, 13), + [ANA_ANEVENTS_CLASSIFIED_COPY] = REG_FIELD(ANA_ANEVENTS, 12, 12), + [ANA_ANEVENTS_VLAN_DISCARD] = REG_FIELD(ANA_ANEVENTS, 11, 11), + [ANA_ANEVENTS_FWD_DISCARD] = REG_FIELD(ANA_ANEVENTS, 10, 10), + [ANA_ANEVENTS_MULTICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 9, 9), + [ANA_ANEVENTS_UNICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 8, 8), + [ANA_ANEVENTS_DEST_KNOWN] = REG_FIELD(ANA_ANEVENTS, 7, 7), + [ANA_ANEVENTS_BUCKET3_MATCH] = REG_FIELD(ANA_ANEVENTS, 6, 6), + [ANA_ANEVENTS_BUCKET2_MATCH] = REG_FIELD(ANA_ANEVENTS, 5, 5), + [ANA_ANEVENTS_BUCKET1_MATCH] = REG_FIELD(ANA_ANEVENTS, 4, 4), + [ANA_ANEVENTS_BUCKET0_MATCH] = REG_FIELD(ANA_ANEVENTS, 3, 3), + [ANA_ANEVENTS_CPU_OPERATION] = REG_FIELD(ANA_ANEVENTS, 2, 2), + [ANA_ANEVENTS_DMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 1, 1), + [ANA_ANEVENTS_SMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 0, 0), + [ANA_TABLES_MACACCESS_B_DOM] = REG_FIELD(ANA_TABLES_MACACCESS, 18, 18), + [ANA_TABLES_MACTINDX_BUCKET] = REG_FIELD(ANA_TABLES_MACTINDX, 10, 11), + [ANA_TABLES_MACTINDX_M_INDEX] = REG_FIELD(ANA_TABLES_MACTINDX, 0, 9), + [GCB_SOFT_RST_SWC_RST] = REG_FIELD(GCB_SOFT_RST, 0, 0), + [QSYS_TIMED_FRAME_ENTRY_TFRM_VLD] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 20, 20), + [QSYS_TIMED_FRAME_ENTRY_TFRM_FP] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 8, 19), + [QSYS_TIMED_FRAME_ENTRY_TFRM_PORTNO] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 4, 7), + [QSYS_TIMED_FRAME_ENTRY_TFRM_TM_SEL] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 1, 3), + [QSYS_TIMED_FRAME_ENTRY_TFRM_TM_T] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 0, 0), + [SYS_RESET_CFG_CORE_ENA] = REG_FIELD(SYS_RESET_CFG, 2, 2), + [SYS_RESET_CFG_MEM_ENA] = REG_FIELD(SYS_RESET_CFG, 1, 1), + [SYS_RESET_CFG_MEM_INIT] = REG_FIELD(SYS_RESET_CFG, 0, 0), + /* Replicated per number of ports (12), register size 4 per port */ + [QSYS_SWITCH_PORT_MODE_PORT_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 14, 14, 12, 4), + [QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 11, 13, 12, 4), + [QSYS_SWITCH_PORT_MODE_YEL_RSRVD] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 10, 10, 12, 4), + [QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 9, 9, 12, 4), + [QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 12, 4), + [QSYS_SWITCH_PORT_MODE_TX_PFC_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 0, 0, 12, 4), + [SYS_PORT_MODE_DATA_WO_TS] = REG_FIELD_ID(SYS_PORT_MODE, 5, 6, 12, 4), + [SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 12, 4), + [SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 12, 4), + [SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 12, 4), + [SYS_PAUSE_CFG_PAUSE_START] = REG_FIELD_ID(SYS_PAUSE_CFG, 10, 18, 12, 4), + [SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 9, 12, 4), + [SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 12, 4), +}; + +static const struct ocelot_stat_layout vsc7512_stats_layout[] = { + { .offset = 0x00, .name = "rx_octets", }, + { .offset = 0x01, .name = "rx_unicast", }, + { .offset = 0x02, .name = "rx_multicast", }, + { .offset = 0x03, .name = "rx_broadcast", }, + { .offset = 0x04, .name = "rx_shorts", }, + { .offset = 0x05, .name = "rx_fragments", }, + { .offset = 0x06, .name = "rx_jabbers", }, + { .offset = 0x07, .name = "rx_crc_align_errs", }, + { .offset = 0x08, .name = "rx_sym_errs", }, + { .offset = 0x09, .name = "rx_frames_below_65_octets", }, + { .offset = 0x0A, .name = "rx_frames_65_to_127_octets", }, + { .offset = 0x0B, .name = "rx_frames_128_to_255_octets", }, + { .offset = 0x0C, .name = "rx_frames_256_to_511_octets", }, + { .offset = 0x0D, .name = "rx_frames_512_to_1023_octets", }, + { .offset = 0x0E, .name = "rx_frames_1024_to_1526_octets", }, + { .offset = 0x0F, .name = "rx_frames_over_1526_octets", }, + { .offset = 0x10, .name = "rx_pause", }, + { .offset = 0x11, .name = "rx_control", }, + { .offset = 0x12, .name = "rx_longs", }, + { .offset = 0x13, .name = "rx_classified_drops", }, + { .offset = 0x14, .name = "rx_red_prio_0", }, + { .offset = 0x15, .name = "rx_red_prio_1", }, + { .offset = 0x16, .name = "rx_red_prio_2", }, + { .offset = 0x17, .name = "rx_red_prio_3", }, + { .offset = 0x18, .name = "rx_red_prio_4", }, + { .offset = 0x19, .name = "rx_red_prio_5", }, + { .offset = 0x1A, .name = "rx_red_prio_6", }, + { .offset = 0x1B, .name = "rx_red_prio_7", }, + { .offset = 0x1C, .name = "rx_yellow_prio_0", }, + { .offset = 0x1D, .name = "rx_yellow_prio_1", }, + { .offset = 0x1E, .name = "rx_yellow_prio_2", }, + { .offset = 0x1F, .name = "rx_yellow_prio_3", }, + { .offset = 0x20, .name = "rx_yellow_prio_4", }, + { .offset = 0x21, .name = "rx_yellow_prio_5", }, + { .offset = 0x22, .name = "rx_yellow_prio_6", }, + { .offset = 0x23, .name = "rx_yellow_prio_7", }, + { .offset = 0x24, .name = "rx_green_prio_0", }, + { .offset = 0x25, .name = "rx_green_prio_1", }, + { .offset = 0x26, .name = "rx_green_prio_2", }, + { .offset = 0x27, .name = "rx_green_prio_3", }, + { .offset = 0x28, .name = "rx_green_prio_4", }, + { .offset = 0x29, .name = "rx_green_prio_5", }, + { .offset = 0x2A, .name = "rx_green_prio_6", }, + { .offset = 0x2B, .name = "rx_green_prio_7", }, + { .offset = 0x40, .name = "tx_octets", }, + { .offset = 0x41, .name = "tx_unicast", }, + { .offset = 0x42, .name = "tx_multicast", }, + { .offset = 0x43, .name = "tx_broadcast", }, + { .offset = 0x44, .name = "tx_collision", }, + { .offset = 0x45, .name = "tx_drops", }, + { .offset = 0x46, .name = "tx_pause", }, + { .offset = 0x47, .name = "tx_frames_below_65_octets", }, + { .offset = 0x48, .name = "tx_frames_65_to_127_octets", }, + { .offset = 0x49, .name = "tx_frames_128_255_octets", }, + { .offset = 0x4A, .name = "tx_frames_256_511_octets", }, + { .offset = 0x4B, .name = "tx_frames_512_1023_octets", }, + { .offset = 0x4C, .name = "tx_frames_1024_1526_octets", }, + { .offset = 0x4D, .name = "tx_frames_over_1526_octets", }, + { .offset = 0x4E, .name = "tx_yellow_prio_0", }, + { .offset = 0x4F, .name = "tx_yellow_prio_1", }, + { .offset = 0x50, .name = "tx_yellow_prio_2", }, + { .offset = 0x51, .name = "tx_yellow_prio_3", }, + { .offset = 0x52, .name = "tx_yellow_prio_4", }, + { .offset = 0x53, .name = "tx_yellow_prio_5", }, + { .offset = 0x54, .name = "tx_yellow_prio_6", }, + { .offset = 0x55, .name = "tx_yellow_prio_7", }, + { .offset = 0x56, .name = "tx_green_prio_0", }, + { .offset = 0x57, .name = "tx_green_prio_1", }, + { .offset = 0x58, .name = "tx_green_prio_2", }, + { .offset = 0x59, .name = "tx_green_prio_3", }, + { .offset = 0x5A, .name = "tx_green_prio_4", }, + { .offset = 0x5B, .name = "tx_green_prio_5", }, + { .offset = 0x5C, .name = "tx_green_prio_6", }, + { .offset = 0x5D, .name = "tx_green_prio_7", }, + { .offset = 0x5E, .name = "tx_aged", }, + { .offset = 0x80, .name = "drop_local", }, + { .offset = 0x81, .name = "drop_tail", }, + { .offset = 0x82, .name = "drop_yellow_prio_0", }, + { .offset = 0x83, .name = "drop_yellow_prio_1", }, + { .offset = 0x84, .name = "drop_yellow_prio_2", }, + { .offset = 0x85, .name = "drop_yellow_prio_3", }, + { .offset = 0x86, .name = "drop_yellow_prio_4", }, + { .offset = 0x87, .name = "drop_yellow_prio_5", }, + { .offset = 0x88, .name = "drop_yellow_prio_6", }, + { .offset = 0x89, .name = "drop_yellow_prio_7", }, + { .offset = 0x8A, .name = "drop_green_prio_0", }, + { .offset = 0x8B, .name = "drop_green_prio_1", }, + { .offset = 0x8C, .name = "drop_green_prio_2", }, + { .offset = 0x8D, .name = "drop_green_prio_3", }, + { .offset = 0x8E, .name = "drop_green_prio_4", }, + { .offset = 0x8F, .name = "drop_green_prio_5", }, + { .offset = 0x90, .name = "drop_green_prio_6", }, + { .offset = 0x91, .name = "drop_green_prio_7", }, +}; + +struct felix_spi_data { + struct regmap *map; + struct felix felix; +}; + +/* TODO: The regmap has overlaps for DEVCPU_ORG and other peripherals. I believe + * this is handled with a page register, and should hopefully be easy to use + * with the existing regmap_config with regmap_range_cfg + */ +static const struct regmap_config felix_spi_regmap_config = { + .reg_bits = 24, + .reg_stride = 1, + .val_bits = 32, + + .write_flag_mask = BIT(7), + .max_register = 0x3fffffff, + .use_single_write = true, + .use_single_read = true, + .can_multi_write = false, + + .reg_format_endian = REGMAP_ENDIAN_BIG, + .val_format_endian = REGMAP_ENDIAN_NATIVE, +}; + +#define VSC7512_BYTE_ORDER_LE 0x00000000 +#define VSC7512_BYTE_ORDER_BE 0x81818181 +#define VSC7512_BIT_ORDER_MSB 0x00000000 +#define VSC7512_BIT_ORDER_LSB 0x42424242 + +static int felix_spi_init_bus(struct spi_device *spi, + struct felix_spi_data *felix_spi) +{ + int err; + u32 val, check; + + val = 0; + +#ifdef __LITTLE_ENDIAN + val |= VSC7512_BYTE_ORDER_LE; +#else + val |= VSC7512_BYTE_ORDER_BE; +#endif + + // Hard code this write to set up the interface. After this is done, + // ocelot_read interface should be able to be used. + err = regmap_write(felix_spi->map, (0x71000000 >> 2) & 0x3fffff, val); + if (err < 0) { + dev_err(&spi->dev, "error %d configuring SPI interface\n", err); + return err; + } + + val = 0x00000000; + err = regmap_write(felix_spi->map, (0x71000004 >> 2) & 0x3fffff, val); + if (err < 0) { + dev_err(&spi->dev, "error %d writing padding bytes\n", err); + return err; + } + + check = val | 0x02000000; + + err = regmap_read(felix_spi->map, (0x71000004 >> 2) & 0x3fffff, &val); + if (err < 0) { + dev_err(&spi->dev, "Error %d writing padding bytes\n", err); + return err; + } else if (check != val) { + dev_err(&spi->dev, + "Error configuring SPI bus. V: 0x%08x != 0x%08x\n", val, + check); + return -ENODEV; + } + + return err; +} + +static void vsc7512_phylink_validate(struct ocelot *ocelot, int port, + unsigned long *supported, + struct phylink_link_state *state) +{ + struct ocelot_port *ocelot_port = ocelot->ports[port]; + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { + 0, + }; + + if (state->interface != PHY_INTERFACE_MODE_NA && + state->interface != ocelot_port->phy_mode) { + bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + return; + } + + phylink_set_port_modes(mask); + phylink_set(mask, Autoneg); + phylink_set(mask, Pause); + phylink_set(mask, Asym_Pause); + phylink_set(mask, 10baseT_Half); + phylink_set(mask, 10baseT_Full); + phylink_set(mask, 100baseT_Half); + phylink_set(mask, 100baseT_Full); + phylink_set(mask, 1000baseT_Half); + phylink_set(mask, 1000baseT_Full); + + if (state->interface == PHY_INTERFACE_MODE_INTERNAL || + state->interface == PHY_INTERFACE_MODE_INTERNAL || + state->interface == PHY_INTERFACE_MODE_INTERNAL) { + phylink_set(mask, 2500baseT_Full); + phylink_set(mask, 2500baseX_Full); + } + + bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); + bitmap_and(state->advertising, state->advertising, mask, + __ETHTOOL_LINK_MODE_MASK_NBITS); +} + +static int vsc7512_prevalidate_phy_mode(struct ocelot *ocelot, int port, + phy_interface_t phy_mode) +{ + switch (phy_mode) { + case PHY_INTERFACE_MODE_INTERNAL: + // TODO: I don't know what ports would not be supported + // internally. + return 0; + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_2500BASEX: + if (port == 4 || port == 5) + return -EOPNOTSUPP; + return 0; + default: + return -EOPNOTSUPP; + } +} + +static int vsc7512_port_setup_tc(struct dsa_switch *ds, int port, + enum tc_setup_type type, void *type_data) +{ + return -EOPNOTSUPP; +} + +static void vsc7512_sched_speed_set(struct ocelot *ocelot, int port, u32 speed) +{ + u8 tas_speed; + + switch (speed) { + case SPEED_10: + tas_speed = OCELOT_SPEED_10; + break; + + case SPEED_100: + tas_speed = OCELOT_SPEED_100; + break; + + case SPEED_1000: + tas_speed = OCELOT_SPEED_1000; + break; + + case SPEED_2500: + tas_speed = OCELOT_SPEED_2500; + break; + + default: + tas_speed = OCELOT_SPEED_1000; + break; + } + + ocelot_rmw_rix(ocelot, QSYS_TAG_CONFIG_LINK_SPEED(tas_speed), + QSYS_TAG_CONFIG_LINK_SPEED_M, QSYS_TAG_CONFIG, port); +} + +static const struct vcap_field vsc7512_vcap_es0_keys[] = { + [VCAP_ES0_EGR_PORT] = { 0, 4 }, + [VCAP_ES0_IGR_PORT] = { 4, 4 }, + [VCAP_ES0_RSV] = { 8, 2 }, + [VCAP_ES0_L2_MC] = { 10, 1 }, + [VCAP_ES0_L2_BC] = { 11, 1 }, + [VCAP_ES0_VID] = { 12, 12 }, + [VCAP_ES0_DP] = { 24, 1 }, + [VCAP_ES0_PCP] = { 25, 3 }, +}; + +static const struct vcap_field vsc7512_vcap_es0_actions[] = { + [VCAP_ES0_ACT_PUSH_OUTER_TAG] = { 0, 2 }, + [VCAP_ES0_ACT_PUSH_INNER_TAG] = { 2, 1 }, + [VCAP_ES0_ACT_TAG_A_TPID_SEL] = { 3, 2 }, + [VCAP_ES0_ACT_TAG_A_VID_SEL] = { 5, 1 }, + [VCAP_ES0_ACT_TAG_A_PCP_SEL] = { 6, 2 }, + [VCAP_ES0_ACT_TAG_A_DEI_SEL] = { 8, 2 }, + [VCAP_ES0_ACT_TAG_B_TPID_SEL] = { 10, 2 }, + [VCAP_ES0_ACT_TAG_B_VID_SEL] = { 12, 1 }, + [VCAP_ES0_ACT_TAG_B_PCP_SEL] = { 13, 2 }, + [VCAP_ES0_ACT_TAG_B_DEI_SEL] = { 15, 2 }, + [VCAP_ES0_ACT_VID_A_VAL] = { 17, 12 }, + [VCAP_ES0_ACT_PCP_A_VAL] = { 29, 3 }, + [VCAP_ES0_ACT_DEI_A_VAL] = { 32, 1 }, + [VCAP_ES0_ACT_VID_B_VAL] = { 33, 12 }, + [VCAP_ES0_ACT_PCP_B_VAL] = { 45, 3 }, + [VCAP_ES0_ACT_DEI_B_VAL] = { 48, 1 }, + [VCAP_ES0_ACT_RSV] = { 49, 24 }, + [VCAP_ES0_ACT_HIT_STICKY] = { 73, 1 }, +}; + +static const struct vcap_field vsc7512_vcap_is1_keys[] = { + [VCAP_IS1_HK_TYPE] = { 0, 1 }, + [VCAP_IS1_HK_LOOKUP] = { 1, 2 }, + [VCAP_IS1_HK_IGR_PORT_MASK] = { 3, 12 }, + [VCAP_IS1_HK_RSV] = { 15, 9 }, + [VCAP_IS1_HK_OAM_Y1731] = { 24, 1 }, + [VCAP_IS1_HK_L2_MC] = { 25, 1 }, + [VCAP_IS1_HK_L2_BC] = { 26, 1 }, + [VCAP_IS1_HK_IP_MC] = { 27, 1 }, + [VCAP_IS1_HK_VLAN_TAGGED] = { 28, 1 }, + [VCAP_IS1_HK_VLAN_DBL_TAGGED] = { 29, 1 }, + [VCAP_IS1_HK_TPID] = { 30, 1 }, + [VCAP_IS1_HK_VID] = { 31, 12 }, + [VCAP_IS1_HK_DEI] = { 43, 1 }, + [VCAP_IS1_HK_PCP] = { 44, 3 }, + /* Specific Fields for IS1 Half Key S1_NORMAL */ + [VCAP_IS1_HK_L2_SMAC] = { 47, 48 }, + [VCAP_IS1_HK_ETYPE_LEN] = { 95, 1 }, + [VCAP_IS1_HK_ETYPE] = { 96, 16 }, + [VCAP_IS1_HK_IP_SNAP] = { 112, 1 }, + [VCAP_IS1_HK_IP4] = { 113, 1 }, + /* Layer-3 Information */ + [VCAP_IS1_HK_L3_FRAGMENT] = { 114, 1 }, + [VCAP_IS1_HK_L3_FRAG_OFS_GT0] = { 115, 1 }, + [VCAP_IS1_HK_L3_OPTIONS] = { 116, 1 }, + [VCAP_IS1_HK_L3_DSCP] = { 117, 6 }, + [VCAP_IS1_HK_L3_IP4_SIP] = { 123, 32 }, + /* Layer-4 Information */ + [VCAP_IS1_HK_TCP_UDP] = { 155, 1 }, + [VCAP_IS1_HK_TCP] = { 156, 1 }, + [VCAP_IS1_HK_L4_SPORT] = { 157, 16 }, + [VCAP_IS1_HK_L4_RNG] = { 173, 8 }, + /* Specific Fields for IS1 Half Key S1_5TUPLE_IP4 */ + [VCAP_IS1_HK_IP4_INNER_TPID] = { 47, 1 }, + [VCAP_IS1_HK_IP4_INNER_VID] = { 48, 12 }, + [VCAP_IS1_HK_IP4_INNER_DEI] = { 60, 1 }, + [VCAP_IS1_HK_IP4_INNER_PCP] = { 61, 3 }, + [VCAP_IS1_HK_IP4_IP4] = { 64, 1 }, + [VCAP_IS1_HK_IP4_L3_FRAGMENT] = { 65, 1 }, + [VCAP_IS1_HK_IP4_L3_FRAG_OFS_GT0] = { 66, 1 }, + [VCAP_IS1_HK_IP4_L3_OPTIONS] = { 67, 1 }, + [VCAP_IS1_HK_IP4_L3_DSCP] = { 68, 6 }, + [VCAP_IS1_HK_IP4_L3_IP4_DIP] = { 74, 32 }, + [VCAP_IS1_HK_IP4_L3_IP4_SIP] = { 106, 32 }, + [VCAP_IS1_HK_IP4_L3_PROTO] = { 138, 8 }, + [VCAP_IS1_HK_IP4_TCP_UDP] = { 146, 1 }, + [VCAP_IS1_HK_IP4_TCP] = { 147, 1 }, + [VCAP_IS1_HK_IP4_L4_RNG] = { 148, 8 }, + [VCAP_IS1_HK_IP4_IP_PAYLOAD_S1_5TUPLE] = { 156, 32 }, +}; + +static const struct vcap_field vsc7512_vcap_is1_actions[] = { + [VCAP_IS1_ACT_DSCP_ENA] = { 0, 1 }, + [VCAP_IS1_ACT_DSCP_VAL] = { 1, 6 }, + [VCAP_IS1_ACT_QOS_ENA] = { 7, 1 }, + [VCAP_IS1_ACT_QOS_VAL] = { 8, 3 }, + [VCAP_IS1_ACT_DP_ENA] = { 11, 1 }, + [VCAP_IS1_ACT_DP_VAL] = { 12, 1 }, + [VCAP_IS1_ACT_PAG_OVERRIDE_MASK] = { 13, 8 }, + [VCAP_IS1_ACT_PAG_VAL] = { 21, 8 }, + [VCAP_IS1_ACT_RSV] = { 29, 9 }, + /* The fields below are incorrectly shifted by 2 in the manual */ + [VCAP_IS1_ACT_VID_REPLACE_ENA] = { 38, 1 }, + [VCAP_IS1_ACT_VID_ADD_VAL] = { 39, 12 }, + [VCAP_IS1_ACT_FID_SEL] = { 51, 2 }, + [VCAP_IS1_ACT_FID_VAL] = { 53, 13 }, + [VCAP_IS1_ACT_PCP_DEI_ENA] = { 66, 1 }, + [VCAP_IS1_ACT_PCP_VAL] = { 67, 3 }, + [VCAP_IS1_ACT_DEI_VAL] = { 70, 1 }, + [VCAP_IS1_ACT_VLAN_POP_CNT_ENA] = { 71, 1 }, + [VCAP_IS1_ACT_VLAN_POP_CNT] = { 72, 2 }, + [VCAP_IS1_ACT_CUSTOM_ACE_TYPE_ENA] = { 74, 4 }, + [VCAP_IS1_ACT_HIT_STICKY] = { 78, 1 }, +}; + +static const struct vcap_field vsc7512_vcap_is2_keys[] = { + /* Common: 46 bits */ + [VCAP_IS2_TYPE] = { 0, 4 }, + [VCAP_IS2_HK_FIRST] = { 4, 1 }, + [VCAP_IS2_HK_PAG] = { 5, 8 }, + [VCAP_IS2_HK_IGR_PORT_MASK] = { 13, 12 }, + [VCAP_IS2_HK_RSV2] = { 25, 1 }, + [VCAP_IS2_HK_HOST_MATCH] = { 26, 1 }, + [VCAP_IS2_HK_L2_MC] = { 27, 1 }, + [VCAP_IS2_HK_L2_BC] = { 28, 1 }, + [VCAP_IS2_HK_VLAN_TAGGED] = { 29, 1 }, + [VCAP_IS2_HK_VID] = { 30, 12 }, + [VCAP_IS2_HK_DEI] = { 42, 1 }, + [VCAP_IS2_HK_PCP] = { 43, 3 }, + /* MAC_ETYPE / MAC_LLC / MAC_SNAP / OAM common */ + [VCAP_IS2_HK_L2_DMAC] = { 46, 48 }, + [VCAP_IS2_HK_L2_SMAC] = { 94, 48 }, + /* MAC_ETYPE (TYPE=000) */ + [VCAP_IS2_HK_MAC_ETYPE_ETYPE] = { 142, 16 }, + [VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0] = { 158, 16 }, + [VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1] = { 174, 8 }, + [VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2] = { 182, 3 }, + /* MAC_LLC (TYPE=001) */ + [VCAP_IS2_HK_MAC_LLC_L2_LLC] = { 142, 40 }, + /* MAC_SNAP (TYPE=010) */ + [VCAP_IS2_HK_MAC_SNAP_L2_SNAP] = { 142, 40 }, + /* MAC_ARP (TYPE=011) */ + [VCAP_IS2_HK_MAC_ARP_SMAC] = { 46, 48 }, + [VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK] = { 94, 1 }, + [VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK] = { 95, 1 }, + [VCAP_IS2_HK_MAC_ARP_LEN_OK] = { 96, 1 }, + [VCAP_IS2_HK_MAC_ARP_TARGET_MATCH] = { 97, 1 }, + [VCAP_IS2_HK_MAC_ARP_SENDER_MATCH] = { 98, 1 }, + [VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN] = { 99, 1 }, + [VCAP_IS2_HK_MAC_ARP_OPCODE] = { 100, 2 }, + [VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP] = { 102, 32 }, + [VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP] = { 134, 32 }, + [VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP] = { 166, 1 }, + /* IP4_TCP_UDP / IP4_OTHER common */ + [VCAP_IS2_HK_IP4] = { 46, 1 }, + [VCAP_IS2_HK_L3_FRAGMENT] = { 47, 1 }, + [VCAP_IS2_HK_L3_FRAG_OFS_GT0] = { 48, 1 }, + [VCAP_IS2_HK_L3_OPTIONS] = { 49, 1 }, + [VCAP_IS2_HK_IP4_L3_TTL_GT0] = { 50, 1 }, + [VCAP_IS2_HK_L3_TOS] = { 51, 8 }, + [VCAP_IS2_HK_L3_IP4_DIP] = { 59, 32 }, + [VCAP_IS2_HK_L3_IP4_SIP] = { 91, 32 }, + [VCAP_IS2_HK_DIP_EQ_SIP] = { 123, 1 }, + /* IP4_TCP_UDP (TYPE=100) */ + [VCAP_IS2_HK_TCP] = { 124, 1 }, + [VCAP_IS2_HK_L4_DPORT] = { 125, 16 }, + [VCAP_IS2_HK_L4_SPORT] = { 141, 16 }, + [VCAP_IS2_HK_L4_RNG] = { 157, 8 }, + [VCAP_IS2_HK_L4_SPORT_EQ_DPORT] = { 165, 1 }, + [VCAP_IS2_HK_L4_SEQUENCE_EQ0] = { 166, 1 }, + [VCAP_IS2_HK_L4_FIN] = { 167, 1 }, + [VCAP_IS2_HK_L4_SYN] = { 168, 1 }, + [VCAP_IS2_HK_L4_RST] = { 169, 1 }, + [VCAP_IS2_HK_L4_PSH] = { 170, 1 }, + [VCAP_IS2_HK_L4_ACK] = { 171, 1 }, + [VCAP_IS2_HK_L4_URG] = { 172, 1 }, + [VCAP_IS2_HK_L4_1588_DOM] = { 173, 8 }, + [VCAP_IS2_HK_L4_1588_VER] = { 181, 4 }, + /* IP4_OTHER (TYPE=101) */ + [VCAP_IS2_HK_IP4_L3_PROTO] = { 124, 8 }, + [VCAP_IS2_HK_L3_PAYLOAD] = { 132, 56 }, + /* IP6_STD (TYPE=110) */ + [VCAP_IS2_HK_IP6_L3_TTL_GT0] = { 46, 1 }, + [VCAP_IS2_HK_L3_IP6_SIP] = { 47, 128 }, + [VCAP_IS2_HK_IP6_L3_PROTO] = { 175, 8 }, + /* OAM (TYPE=111) */ + [VCAP_IS2_HK_OAM_MEL_FLAGS] = { 142, 7 }, + [VCAP_IS2_HK_OAM_VER] = { 149, 5 }, + [VCAP_IS2_HK_OAM_OPCODE] = { 154, 8 }, + [VCAP_IS2_HK_OAM_FLAGS] = { 162, 8 }, + [VCAP_IS2_HK_OAM_MEPID] = { 170, 16 }, + [VCAP_IS2_HK_OAM_CCM_CNTS_EQ0] = { 186, 1 }, + [VCAP_IS2_HK_OAM_IS_Y1731] = { 187, 1 }, +}; + +static const struct vcap_field vsc7512_vcap_is2_actions[] = { + [VCAP_IS2_ACT_HIT_ME_ONCE] = { 0, 1 }, + [VCAP_IS2_ACT_CPU_COPY_ENA] = { 1, 1 }, + [VCAP_IS2_ACT_CPU_QU_NUM] = { 2, 3 }, + [VCAP_IS2_ACT_MASK_MODE] = { 5, 2 }, + [VCAP_IS2_ACT_MIRROR_ENA] = { 7, 1 }, + [VCAP_IS2_ACT_LRN_DIS] = { 8, 1 }, + [VCAP_IS2_ACT_POLICE_ENA] = { 9, 1 }, + [VCAP_IS2_ACT_POLICE_IDX] = { 10, 9 }, + [VCAP_IS2_ACT_POLICE_VCAP_ONLY] = { 19, 1 }, + [VCAP_IS2_ACT_PORT_MASK] = { 20, 11 }, + [VCAP_IS2_ACT_REW_OP] = { 31, 9 }, + [VCAP_IS2_ACT_SMAC_REPLACE_ENA] = { 40, 1 }, + [VCAP_IS2_ACT_RSV] = { 41, 2 }, + [VCAP_IS2_ACT_ACL_ID] = { 43, 6 }, + [VCAP_IS2_ACT_HIT_CNT] = { 49, 32 }, +}; + +static struct vcap_props vsc7512_vcap_props[] = { + [VCAP_ES0] = { + .action_type_width = 0, + .action_table = { + [ES0_ACTION_TYPE_NORMAL] = { + .width = 73, + .count = 1, + }, + }, + .target = S0, + .keys = vsc7512_vcap_es0_keys, + .actions = vsc7512_vcap_es0_actions, + }, + [VCAP_IS1] = { + .action_type_width = 0, + .action_table = { + [IS1_ACTION_TYPE_NORMAL] = { + .width = 78, + .count = 4, + }, + }, + .target = S1, + .keys = vsc7512_vcap_is1_keys, + .actions = vsc7512_vcap_is1_actions, + }, + [VCAP_IS2] = { + .action_type_width = 1, + .action_table = { + [IS2_ACTION_TYPE_NORMAL] = { + .width = 49, + .count = 2, + }, + [IS2_ACTION_TYPE_SMAC_SIP] = { + .width = 6, + .count = 4, + }, + }, + .target = S2, + .keys = vsc7512_vcap_is2_keys, + .actions = vsc7512_vcap_is2_actions, + }, +}; + +static struct regmap *vsc7512_regmap_init(struct ocelot *ocelot, + struct resource *res, u32 *offset) +{ + struct felix *felix = ocelot_to_felix(ocelot); + struct felix_spi_data *felix_spi = container_of(felix, struct + felix_spi_data, felix); + + // Use offset instead of res, since we don't have MMIO for SPI + *offset = res->start; + return felix_spi->map; +} + +static const struct felix_info felix_spi_info = { + .target_io_res = vsc7512_target_io_res, + .port_io_res = vsc7512_port_io_res, + .imdio_res = NULL, + .regfields = vsc7512_regfields, + .map = vsc7512_regmap, + .ops = &vsc7512_ops, + .stats_layout = vsc7512_stats_layout, + .num_stats = ARRAY_SIZE(vsc7512_stats_layout), + + .vcap = vsc7512_vcap_props, + + // Not sure about these + .num_mact_rows = 2048, + .num_ports = 6, + .num_tx_queues = OCELOT_NUM_TC, + .switch_pci_bar = 0, + .imdio_pci_bar = 0, + + // Force ocelot->ptp to 0 + .ptp_caps = NULL, + + // No need for this? + .mdio_bus_alloc = NULL, + .mdio_bus_free = NULL, + .phylink_validate = vsc7512_phylink_validate, + .prevalidate_phy_mode = vsc7512_prevalidate_phy_mode, + .port_setup_tc = vsc7512_port_setup_tc, + .port_sched_speed_set = vsc7512_sched_speed_set, + .init_regmap = vsc7512_regmap_init, +}; + +static int felix_spi_probe(struct spi_device *spi) +{ + struct dsa_switch *ds; + struct ocelot *ocelot; + struct felix *felix; + int err; + struct felix_spi_data *felix_spi; + + pr_info("felix_spi: CS: %d M: %d, BPW: %d, MaxSpeed: %d\n", + spi->chip_select, spi->mode, spi->bits_per_word, + spi->max_speed_hz); + + felix_spi = devm_kzalloc(&spi->dev, sizeof(struct felix_spi_data), + GFP_KERNEL); + + if (!felix_spi) + return -ENOMEM; + + dev_set_drvdata(&spi->dev, felix_spi); + + spi->bits_per_word = 8; + + /* TODO: There are a couple of goals to achieve. Step 1: Get the device + * working in slow SPI mode with a fixed bit and byte order. Fixing this + * should allow devm_regmap_init_spi to be used directly, though there + * are penalties incurred. Specifically the bus is running much slower + * than it could, hindering performance. + * + * Operating at a faster SPI rate could boost performance significantly + * with fixed delays or padding bytes. Especially on consecutive reads. + * + * Ideally the SPI bus would be configured to run at the configured + * speed / fastest speed possible with consecutive reads / writes + * enabled, if supported. For reads, we would have to reason about the + * speed vs the delay time or the number of padding bytes. + */ + + spi->max_speed_hz = 500000; + err = spi_setup(spi); + if (err < 0) { + dev_err(&spi->dev, "Error %d initializing SPI\n", err); + return err; + } + + felix_spi->map = devm_regmap_init_spi(spi, &felix_spi_regmap_config); + + if (IS_ERR(felix_spi->map)) { + dev_err(&spi->dev, "regmap init failed\n"); + return PTR_ERR(felix_spi->map); + } + + err = felix_spi_init_bus(spi, felix_spi); + if (err < 0) { + dev_err(&spi->dev, "device init failed: %d\n", err); + return err; + } + + felix = &felix_spi->felix; + + ocelot = &felix->ocelot; + ocelot->dev = &spi->dev; + + // Not sure about this + ocelot->num_flooding_pgids = OCELOT_NUM_TC; + + felix->info = &felix_spi_info; + + ocelot->ptp = 0; + + ds = kzalloc(sizeof(*ds), GFP_KERNEL); + if (!ds) { + err = -ENOMEM; + dev_err(&spi->dev, "Failed to allocate DSA switch\n"); + goto err_alloc_ds; + } + + ds->dev = &spi->dev; + ds->num_ports = felix->info->num_ports; + ds->num_tx_queues = felix->info->num_tx_queues; + ds->ops = &felix_switch_ops; + ds->priv = ocelot; + + err = dsa_register_switch(ds); + if (err) { + dev_err(&spi->dev, "Failed to register DSA switch: %d\n", err); + goto err_register_ds; + } + + return 0; + +err_register_ds: + kfree(ds); +err_alloc_ds: + kfree(felix); + return err; +} + +static int felix_spi_remove(struct spi_device *pdev) +{ + struct felix *felix; + + felix = spi_get_drvdata(pdev); + + return 0; +} + +const struct of_device_id vsc7512_of_match[] = { { .compatible = + "mscc,vsc7512" }, + {} }; +MODULE_DEVICE_TABLE(of, vsc7512_of_match); + +static struct spi_driver felix_vsc7512_spi_driver = { + .driver = { + .name = "vsc7512", + .of_match_table = of_match_ptr(vsc7512_of_match), + }, + .probe = felix_spi_probe, + .remove = felix_spi_remove, +}; +module_spi_driver(felix_vsc7512_spi_driver); + +MODULE_DESCRIPTION("Felix Switch SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index ad45c1af4be9..8b6e0574f294 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -127,6 +127,7 @@ enum ocelot_target { PTP, GCB, DEV_GMII, + DEV_CPUORG, TARGET_MAX, }; @@ -444,6 +445,20 @@ enum ocelot_reg { PCS1G_TSTPAT_STATUS, DEV_PCS_FX100_CFG, DEV_PCS_FX100_STATUS, + DEV_CPUORG_IF_CTRL = DEV_CPUORG << TARGET_OFFSET, + DEV_CPUORG_IF_CFGSTAT, + DEV_CPUORG_ORG_CFG, + DEV_CPUORG_ERR_CNTS, + DEV_CPUORG_TIMEOUT_CFG, + DEV_CPUORG_GPR, + DEV_CPUORG_MAILBOX_SET, + DEV_CPUORG_MAILBOX_CLR, + DEV_CPUORG_MAILBOX, + DEV_CPUORG_SEMA_CFG, + DEV_CPUORG_SEMA0, + DEV_CPUORG_SEMA0_OWNER, + DEV_CPUORG_SEMA1, + DEV_CPUORG_SEMA1_OWNER, }; enum ocelot_regfield {