1 /* 2 * (C) Copyright 2012 3 * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24 #include <common.h> 25 #include <asm/io.h> 26 #include <errno.h> 27 28 #include <gdsys_fpga.h> 29 30 enum { 31 MCINT_SLAVE_LINK_CHANGED_EV = 1 << 7, 32 MCINT_TX_ERROR_EV = 1 << 9, 33 MCINT_TX_BUFFER_FREE = 1 << 10, 34 MCINT_TX_PACKET_TRANSMITTED_EV = 1 << 11, 35 MCINT_RX_ERROR_EV = 1 << 13, 36 MCINT_RX_CONTENT_AVAILABLE = 1 << 14, 37 MCINT_RX_PACKET_RECEIVED_EV = 1 << 15, 38 }; 39 40 int mclink_probe(void) 41 { 42 unsigned int k; 43 int slaves = 0; 44 45 for (k = 0; k < CONFIG_SYS_MCLINK_MAX; ++k) { 46 int timeout = 0; 47 unsigned int ctr = 0; 48 u16 mc_status; 49 50 FPGA_GET_REG(k, mc_status, &mc_status); 51 52 if (!(mc_status & (1 << 15))) 53 break; 54 55 FPGA_SET_REG(k, mc_control, 0x8000); 56 57 FPGA_GET_REG(k, mc_status, &mc_status); 58 while (!(mc_status & (1 << 14))) { 59 udelay(100); 60 if (ctr++ > 500) { 61 timeout = 1; 62 break; 63 } 64 FPGA_GET_REG(k, mc_status, &mc_status); 65 } 66 if (timeout) 67 break; 68 69 printf("waited %d us for mclink %d to come up\n", ctr * 100, k); 70 71 slaves++; 72 } 73 74 return slaves; 75 } 76 77 int mclink_send(u8 slave, u16 addr, u16 data) 78 { 79 unsigned int ctr = 0; 80 u16 int_status; 81 u16 rx_cmd_status; 82 u16 rx_cmd; 83 84 /* reset interrupt status */ 85 FPGA_GET_REG(0, mc_int, &int_status); 86 FPGA_SET_REG(0, mc_int, int_status); 87 88 /* send */ 89 FPGA_SET_REG(0, mc_tx_address, addr); 90 FPGA_SET_REG(0, mc_tx_data, data); 91 FPGA_SET_REG(0, mc_tx_cmd, (slave & 0x03) << 14); 92 FPGA_SET_REG(0, mc_control, 0x8001); 93 94 /* wait for reply */ 95 FPGA_GET_REG(0, mc_int, &int_status); 96 while (!(int_status & MCINT_RX_PACKET_RECEIVED_EV)) { 97 udelay(100); 98 if (ctr++ > 3) 99 return -ETIMEDOUT; 100 FPGA_GET_REG(0, mc_int, &int_status); 101 } 102 103 FPGA_GET_REG(0, mc_rx_cmd_status, &rx_cmd_status); 104 rx_cmd = (rx_cmd_status >> 12) & 0x03; 105 if (rx_cmd != 0) 106 printf("mclink_send: received cmd %d, expected %d\n", rx_cmd, 107 0); 108 109 return 0; 110 } 111 112 int mclink_receive(u8 slave, u16 addr, u16 *data) 113 { 114 u16 rx_cmd_status; 115 u16 rx_cmd; 116 u16 int_status; 117 unsigned int ctr = 0; 118 119 /* send read request */ 120 FPGA_SET_REG(0, mc_tx_address, addr); 121 FPGA_SET_REG(0, mc_tx_cmd, 122 ((slave & 0x03) << 14) | (1 << 12) | (1 << 0)); 123 FPGA_SET_REG(0, mc_control, 0x8001); 124 125 126 /* wait for reply */ 127 FPGA_GET_REG(0, mc_int, &int_status); 128 while (!(int_status & MCINT_RX_CONTENT_AVAILABLE)) { 129 udelay(100); 130 if (ctr++ > 3) 131 return -ETIMEDOUT; 132 FPGA_GET_REG(0, mc_int, &int_status); 133 } 134 135 /* check reply */ 136 FPGA_GET_REG(0, mc_rx_cmd_status, &rx_cmd_status); 137 if ((rx_cmd_status >> 14) != slave) { 138 printf("mclink_receive: reply from slave %d, expected %d\n", 139 rx_cmd_status >> 14, slave); 140 return -EINVAL; 141 } 142 143 rx_cmd = (rx_cmd_status >> 12) & 0x03; 144 if (rx_cmd != 1) { 145 printf("mclink_send: received cmd %d, expected %d\n", 146 rx_cmd, 1); 147 return -EIO; 148 } 149 150 FPGA_GET_REG(0, mc_rx_data, data); 151 152 return 0; 153 } 154