From 0dff8c753c8929a478357abb38db0d1c1a60ec94 Mon Sep 17 00:00:00 2001 From: Daniel Schwierzeck Date: Wed, 29 Aug 2012 22:08:15 +0200 Subject: net: switchlib: add framework for ethernet switch drivers Add a generic framework similar to phylib for ethernet switch drivers and devices. This is useful to share the init and setup code for switch devices across different boards. Signed-off-by: Daniel Schwierzeck Cc: Joe Hershberger --- a/Makefile +++ b/Makefile @@ -280,6 +280,7 @@ LIBS-y += drivers/mtd/ubi/libubi.o LIBS-y += drivers/mtd/spi/libspi_flash.o LIBS-y += drivers/net/libnet.o LIBS-y += drivers/net/phy/libphy.o +LIBS-y += drivers/net/switch/libswitch.o LIBS-y += drivers/pci/libpci.o LIBS-y += drivers/pcmcia/libpcmcia.o LIBS-y += drivers/power/libpower.o \ --- /dev/null +++ b/drivers/net/switch/Makefile @@ -0,0 +1,30 @@ +# +# Copyright (C) 2000-2011 Wolfgang Denk, DENX Software Engineering, wd@denx.de +# Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com +# +# SPDX-License-Identifier: GPL-2.0+ +# + +include $(TOPDIR)/config.mk + +LIB := $(obj)libswitch.o + +COBJS-$(CONFIG_SWITCH_MULTI) += switch.o + +COBJS := $(COBJS-y) +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) + +all: $(LIB) + +$(LIB): $(obj).depend $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### --- /dev/null +++ b/drivers/net/switch/switch.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +static struct list_head switch_drivers; +static struct list_head switch_devices; + +void switch_init(void) +{ + INIT_LIST_HEAD(&switch_drivers); + INIT_LIST_HEAD(&switch_devices); + + board_switch_init(); +} + +void switch_driver_register(struct switch_driver *drv) +{ + INIT_LIST_HEAD(&drv->list); + list_add_tail(&drv->list, &switch_drivers); +} + +int switch_device_register(struct switch_device *dev) +{ + struct switch_driver *drv; + + /* Add switch device only, if an adequate driver is registered */ + list_for_each_entry(drv, &switch_drivers, list) { + if (!strcmp(drv->name, dev->name)) { + dev->drv = drv; + + INIT_LIST_HEAD(&dev->list); + list_add_tail(&dev->list, &switch_devices); + + return 0; + } + } + + return -1; +} + +struct switch_device *switch_connect(struct mii_dev *bus) +{ + struct switch_device *sw; + int err; + + list_for_each_entry(sw, &switch_devices, list) { + sw->bus = bus; + + err = sw->drv->probe(sw); + if (!err) + return sw; + } + + return NULL; +} --- /dev/null +++ b/include/switch.h @@ -0,0 +1,102 @@ +/* + * This file is released under the terms of GPL v2 and any later version. + * See the file COPYING in the root directory of the source tree for details. + * + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com + */ + +#ifndef __SWITCH_H +#define __SWITCH_H + +#include + +#define SWITCH_NAME_SIZE 32 + +struct switch_device; +struct mii_dev; + +struct switch_driver { + struct list_head list; + + /* Switch device name */ + const char name[SWITCH_NAME_SIZE]; + + /* + * Called to probe the switch chip. Must return 0 if the switch + * chip matches the given switch device/driver combination. Otherwise + * 1 must be returned. + */ + int (*probe) (struct switch_device *dev); + + /* + * Called to initialize the switch chip. + */ + void (*setup) (struct switch_device *dev); +}; + +struct switch_device { + struct list_head list; + struct switch_driver *drv; + + /* MII bus the switch chip is connected to */ + struct mii_dev *bus; + + /* Switch device name */ + const char name[SWITCH_NAME_SIZE]; + + /* Bitmask for board specific setup of used switch ports */ + u16 port_mask; + + /* Number of switch port that is connected to host CPU */ + u16 cpu_port; +}; + +/* + * Board specific switch initialization. + * + * Called from switch_init to register the board specific switch_device + * structure. + */ +extern int board_switch_init(void); + +/* Initialize switch subsystem */ +#ifdef CONFIG_SWITCH_MULTI +extern void switch_init(void); +#else +static inline void switch_init(void) +{ +} +#endif + +/* Register a switch driver */ +extern void switch_driver_register(struct switch_driver *drv); + +/* Register a switch device */ +extern int switch_device_register(struct switch_device *dev); + +/* + * Probe the available switch chips and connect the found one + * with the given MII bus + */ +#ifdef CONFIG_SWITCH_MULTI +extern struct switch_device *switch_connect(struct mii_dev *bus); +#else +static inline struct switch_device *switch_connect(struct mii_dev *bus) +{ + return NULL; +} +#endif + +/* + * Setup the given switch device + */ +static inline void switch_setup(struct switch_device *dev) +{ + if (dev->drv->setup) + dev->drv->setup(dev); +} + +/* Init functions for supported Switch drivers */ + +#endif /* __SWITCH_H */ + --- a/net/eth.c +++ b/net/eth.c @@ -10,6 +10,7 @@ #include #include #include +#include void eth_parse_enetaddr(const char *addr, uchar *enetaddr) { @@ -287,6 +288,8 @@ int eth_initialize(bd_t *bis) phy_init(); #endif + switch_init(); + eth_env_init(bis); /*