
From: Dirk Eibach eibach@gdsys.de
mclink is a serial interface for communication between gdsys FPGA.
Signed-off-by: Dirk Eibach dirk.eibach@gdsys.cc
--- Changes in v2: - update email account
board/gdsys/common/Makefile | 2 +- board/gdsys/common/mclink.c | 140 +++++++++++++++++++++++++++++++++++++++++++ board/gdsys/common/mclink.h | 31 ++++++++++ 3 files changed, 172 insertions(+), 1 deletions(-) create mode 100644 board/gdsys/common/mclink.c create mode 100644 board/gdsys/common/mclink.h
diff --git a/board/gdsys/common/Makefile b/board/gdsys/common/Makefile index 05dd65d..6f09550 100644 --- a/board/gdsys/common/Makefile +++ b/board/gdsys/common/Makefile @@ -31,7 +31,7 @@ LIB = $(obj)lib$(VENDOR).o
COBJS-$(CONFIG_IO) += miiphybb.o COBJS-$(CONFIG_IO64) += miiphybb.o -COBJS-$(CONFIG_IOCON) += osd.o +COBJS-$(CONFIG_IOCON) += osd.o mclink.o COBJS-$(CONFIG_DLVISION_10G) += osd.o
COBJS := $(COBJS-y) diff --git a/board/gdsys/common/mclink.c b/board/gdsys/common/mclink.c new file mode 100644 index 0000000..9a4f3e9 --- /dev/null +++ b/board/gdsys/common/mclink.c @@ -0,0 +1,140 @@ +/* + * (C) Copyright 2012 + * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <errno.h> + +#include <gdsys_fpga.h> + +enum { + MCINT_SLAVE_LINK_CHANGED_EV = 1 << 7, + MCINT_TX_ERROR_EV = 1 << 9, + MCINT_TX_BUFFER_FREE = 1 << 10, + MCINT_TX_PACKET_TRANSMITTED_EV = 1 << 11, + MCINT_RX_ERROR_EV = 1 << 13, + MCINT_RX_CONTENT_AVAILABLE = 1 << 14, + MCINT_RX_PACKET_RECEIVED_EV = 1 << 15, +}; + +int mclink_probe(void) +{ + unsigned int k; + unsigned int ctr = 0; + int slaves = 0; + + for (k = 0; k < CONFIG_SYS_MCLINK_MAX; ++k) { + int timeout = 0; + + if (!(fpga_get_reg(k, REG(mc_status)) & (1 << 15))) + break; + + fpga_set_reg(k, REG(mc_control), 0x8000); + + while (!(fpga_get_reg(k, REG(mc_status)) & (1 << 14))) { + udelay(100); + if (ctr++ > 3) { + timeout = 1; + break; + } + } + if (timeout) + break; + + slaves++; + } + + return slaves; +} + +int mclink_send(u8 slave, u16 addr, u16 data) +{ + unsigned int ctr = 0; + u16 int_status; + u16 rx_cmd_status; + u16 rx_cmd; + + /* reset interrupt status */ + int_status = fpga_get_reg(0, REG(mc_int)); + fpga_set_reg(0, REG(mc_int), int_status); + + /* send */ + fpga_set_reg(0, REG(mc_tx_address), addr); + fpga_set_reg(0, REG(mc_tx_data), data); + fpga_set_reg(0, REG(mc_tx_cmd), (slave & 0x03) << 14); + fpga_set_reg(0, REG(mc_control), 0x8001); + + /* wait for reply */ + while (!(fpga_get_reg(0, REG(mc_int)) & MCINT_RX_PACKET_RECEIVED_EV)) { + udelay(100); + if (ctr++ > 3) + return -ETIMEDOUT; + } + + rx_cmd_status = fpga_get_reg(0, REG(mc_rx_cmd_status)); + rx_cmd = (rx_cmd_status >> 12) & 0x03; + if (rx_cmd != 0) + printf("mclink_send: received cmd %d, expected %d\n", rx_cmd, + 0); + + return 0; +} + +int mclink_receive(u8 slave, u16 addr, u16 *data) +{ + u16 rx_cmd_status; + u16 rx_cmd; + unsigned int ctr = 0; + + /* send read request */ + fpga_set_reg(0, REG(mc_tx_address), addr); + fpga_set_reg(0, REG(mc_tx_cmd), + ((slave & 0x03) << 14) | (1 << 12) | (1 << 0)); + fpga_set_reg(0, REG(mc_control), 0x8001); + + /* wait for reply */ + while (!(fpga_get_reg(0, REG(mc_int)) & MCINT_RX_CONTENT_AVAILABLE)) { + udelay(100); + if (ctr++ > 3) + return -ETIMEDOUT; + } + + /* check reply */ + rx_cmd_status = fpga_get_reg(0, REG(mc_rx_cmd_status)); + if ((rx_cmd_status >> 14) != slave) { + printf("mclink_receive: reply from slave %d, expected %d\n", + rx_cmd_status >> 14, slave); + return -EINVAL; + } + + rx_cmd = (rx_cmd_status >> 12) & 0x03; + if (rx_cmd != 1) { + printf("mclink_send: received cmd %d, expected %d\n", + rx_cmd, 1); + return -EIO; + } + + *data = fpga_get_reg(0, REG(mc_rx_data)); + + return 0; +} diff --git a/board/gdsys/common/mclink.h b/board/gdsys/common/mclink.h new file mode 100644 index 0000000..47a62b4 --- /dev/null +++ b/board/gdsys/common/mclink.h @@ -0,0 +1,31 @@ +/* + * (C) Copyright 2012 + * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _MCLINK_H_ +#define _MCLINK_H_ + +int mclink_probe(void); +int mclink_send(u8 slave, u16 addr, u16 data); +int mclink_receive(u8 slave, u16 addr, u16 *data); + +#endif