
Existing felix DSA drivers (vsc9959, vsc9953) are all switches that were integrated in NXP SoCs, which makes them a bit unusual compared to the usual Microchip branded Ocelot switches. To be precise, looking at Documentation/devicetree/bindings/net/mscc,vsc7514-switch.yaml, one can see 21 memory regions for the "switch" node, and these correspond to the "targets" of the switch IP, which are spread throughout the guts of that SoC's memory space. In NXP integrations, those targets still exist, but they were condensed within a single memory region, with no other peripheral in between them, so it made more sense for the driver to ioremap the entire memory space of the switch, and then find the targets within that memory space via some offsets hardcoded in the driver. The effect of this design decision is that now, the felix driver expects hardware instantiations to provide their own resource definitions, which is kind of odd when considering a typical device (those are retrieved from 'reg' properties in the device tree, using platform_get_resource() or similar). Allow other hardware instantiations that share the felix driver to not provide a hardcoded array of resources in the future. Instead, make the common denominator based on which regmaps are created be just the resource "names". Each instantiation comes with its own array of names that are mandatory for it, and with an optional array of resources. So we split the resources in 2 arrays, one is what's requested and the other is what's provided. There is one pool of provided resources, in felix->info->resources (of length felix->info->num_resources). There are 2 different ways of requesting a resource. One is by enum ocelot_target (this handles the global regmaps), and one is by int port (this handles the per-port ones). For the existing vsc9959 and vsc9953, it would be a bit stupid to request something that's not provided, given that the 2 arrays are both defined in the same place. The advantage is that we can now modify felix_request_regmap_by_name() to make felix->info->resources[] optional, and if absent, the implementation can call dev_get_regmap() and this is something that is compatible with MFD. Co-developed-by: Colin Foster <colin.foster@in-advantage.com> Signed-off-by: Colin Foster <colin.foster@in-advantage.com> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
102 lines
3.6 KiB
C
102 lines
3.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/* Copyright 2019 NXP
|
|
*/
|
|
#ifndef _MSCC_FELIX_H
|
|
#define _MSCC_FELIX_H
|
|
|
|
#define ocelot_to_felix(o) container_of((o), struct felix, ocelot)
|
|
#define FELIX_MAC_QUIRKS OCELOT_QUIRK_PCS_PERFORMS_RATE_ADAPTATION
|
|
|
|
#define OCELOT_PORT_MODE_INTERNAL BIT(0)
|
|
#define OCELOT_PORT_MODE_SGMII BIT(1)
|
|
#define OCELOT_PORT_MODE_QSGMII BIT(2)
|
|
#define OCELOT_PORT_MODE_2500BASEX BIT(3)
|
|
#define OCELOT_PORT_MODE_USXGMII BIT(4)
|
|
#define OCELOT_PORT_MODE_1000BASEX BIT(5)
|
|
|
|
/* Platform-specific information */
|
|
struct felix_info {
|
|
/* Hardcoded resources provided by the hardware instantiation. */
|
|
const struct resource *resources;
|
|
size_t num_resources;
|
|
/* Names of the mandatory resources that will be requested during
|
|
* probe. Must have TARGET_MAX elements, since it is indexed by target.
|
|
*/
|
|
const char *const *resource_names;
|
|
const struct reg_field *regfields;
|
|
const u32 *const *map;
|
|
const struct ocelot_ops *ops;
|
|
const u32 *port_modes;
|
|
int num_mact_rows;
|
|
const struct ocelot_stat_layout *stats_layout;
|
|
int num_ports;
|
|
int num_tx_queues;
|
|
struct vcap_props *vcap;
|
|
u16 vcap_pol_base;
|
|
u16 vcap_pol_max;
|
|
u16 vcap_pol_base2;
|
|
u16 vcap_pol_max2;
|
|
const struct ptp_clock_info *ptp_caps;
|
|
|
|
/* Some Ocelot switches are integrated into the SoC without the
|
|
* extraction IRQ line connected to the ARM GIC. By enabling this
|
|
* workaround, the few packets that are delivered to the CPU port
|
|
* module (currently only PTP) are copied not only to the hardware CPU
|
|
* port module, but also to the 802.1Q Ethernet CPU port, and polling
|
|
* the extraction registers is triggered once the DSA tagger sees a PTP
|
|
* frame. The Ethernet frame is only used as a notification: it is
|
|
* dropped, and the original frame is extracted over MMIO and annotated
|
|
* with the RX timestamp.
|
|
*/
|
|
bool quirk_no_xtr_irq;
|
|
|
|
int (*mdio_bus_alloc)(struct ocelot *ocelot);
|
|
void (*mdio_bus_free)(struct ocelot *ocelot);
|
|
void (*phylink_validate)(struct ocelot *ocelot, int port,
|
|
unsigned long *supported,
|
|
struct phylink_link_state *state);
|
|
int (*port_setup_tc)(struct dsa_switch *ds, int port,
|
|
enum tc_setup_type type, void *type_data);
|
|
void (*tas_guard_bands_update)(struct ocelot *ocelot, int port);
|
|
void (*port_sched_speed_set)(struct ocelot *ocelot, int port,
|
|
u32 speed);
|
|
};
|
|
|
|
/* Methods for initializing the hardware resources specific to a tagging
|
|
* protocol (like the NPI port, for "ocelot" or "seville", or the VCAP TCAMs,
|
|
* for "ocelot-8021q").
|
|
* It is important that the resources configured here do not have side effects
|
|
* for the other tagging protocols. If that is the case, their configuration
|
|
* needs to go to felix_tag_proto_setup_shared().
|
|
*/
|
|
struct felix_tag_proto_ops {
|
|
int (*setup)(struct dsa_switch *ds);
|
|
void (*teardown)(struct dsa_switch *ds);
|
|
unsigned long (*get_host_fwd_mask)(struct dsa_switch *ds);
|
|
int (*change_master)(struct dsa_switch *ds, int port,
|
|
struct net_device *master,
|
|
struct netlink_ext_ack *extack);
|
|
};
|
|
|
|
extern const struct dsa_switch_ops felix_switch_ops;
|
|
|
|
/* DSA glue / front-end for struct ocelot */
|
|
struct felix {
|
|
struct dsa_switch *ds;
|
|
const struct felix_info *info;
|
|
struct ocelot ocelot;
|
|
struct mii_bus *imdio;
|
|
struct phylink_pcs **pcs;
|
|
resource_size_t switch_base;
|
|
enum dsa_tag_protocol tag_proto;
|
|
const struct felix_tag_proto_ops *tag_proto_ops;
|
|
struct kthread_worker *xmit_worker;
|
|
unsigned long host_flood_uc_mask;
|
|
unsigned long host_flood_mc_mask;
|
|
};
|
|
|
|
struct net_device *felix_port_to_netdev(struct ocelot *ocelot, int port);
|
|
int felix_netdev_to_port(struct net_device *dev);
|
|
|
|
#endif
|