1 /* 2 * (C) Copyright 2012 3 * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <asm/io.h> 10 #include <errno.h> 11 12 #include <gdsys_fpga.h> 13 14 enum { 15 MCINT_SLAVE_LINK_CHANGED_EV = 1 << 7, 16 MCINT_TX_ERROR_EV = 1 << 9, 17 MCINT_TX_BUFFER_FREE = 1 << 10, 18 MCINT_TX_PACKET_TRANSMITTED_EV = 1 << 11, 19 MCINT_RX_ERROR_EV = 1 << 13, 20 MCINT_RX_CONTENT_AVAILABLE = 1 << 14, 21 MCINT_RX_PACKET_RECEIVED_EV = 1 << 15, 22 }; 23 24 int mclink_probe(void) 25 { 26 unsigned int k; 27 int slaves = 0; 28 29 for (k = 0; k < CONFIG_SYS_MCLINK_MAX; ++k) { 30 int timeout = 0; 31 unsigned int ctr = 0; 32 u16 mc_status; 33 34 FPGA_GET_REG(k, mc_status, &mc_status); 35 36 if (!(mc_status & (1 << 15))) 37 break; 38 39 FPGA_SET_REG(k, mc_control, 0x8000); 40 41 FPGA_GET_REG(k, mc_status, &mc_status); 42 while (!(mc_status & (1 << 14))) { 43 udelay(100); 44 if (ctr++ > 500) { 45 timeout = 1; 46 break; 47 } 48 FPGA_GET_REG(k, mc_status, &mc_status); 49 } 50 if (timeout) 51 break; 52 53 printf("waited %d us for mclink %d to come up\n", ctr * 100, k); 54 55 slaves++; 56 } 57 58 return slaves; 59 } 60 61 int mclink_send(u8 slave, u16 addr, u16 data) 62 { 63 unsigned int ctr = 0; 64 u16 int_status; 65 u16 rx_cmd_status; 66 u16 rx_cmd; 67 68 /* reset interrupt status */ 69 FPGA_GET_REG(0, mc_int, &int_status); 70 FPGA_SET_REG(0, mc_int, int_status); 71 72 /* send */ 73 FPGA_SET_REG(0, mc_tx_address, addr); 74 FPGA_SET_REG(0, mc_tx_data, data); 75 FPGA_SET_REG(0, mc_tx_cmd, (slave & 0x03) << 14); 76 FPGA_SET_REG(0, mc_control, 0x8001); 77 78 /* wait for reply */ 79 FPGA_GET_REG(0, mc_int, &int_status); 80 while (!(int_status & MCINT_RX_PACKET_RECEIVED_EV)) { 81 udelay(100); 82 if (ctr++ > 3) 83 return -ETIMEDOUT; 84 FPGA_GET_REG(0, mc_int, &int_status); 85 } 86 87 FPGA_GET_REG(0, mc_rx_cmd_status, &rx_cmd_status); 88 rx_cmd = (rx_cmd_status >> 12) & 0x03; 89 if (rx_cmd != 0) 90 printf("mclink_send: received cmd %d, expected %d\n", rx_cmd, 91 0); 92 93 return 0; 94 } 95 96 int mclink_receive(u8 slave, u16 addr, u16 *data) 97 { 98 u16 rx_cmd_status; 99 u16 rx_cmd; 100 u16 int_status; 101 unsigned int ctr = 0; 102 103 /* send read request */ 104 FPGA_SET_REG(0, mc_tx_address, addr); 105 FPGA_SET_REG(0, mc_tx_cmd, 106 ((slave & 0x03) << 14) | (1 << 12) | (1 << 0)); 107 FPGA_SET_REG(0, mc_control, 0x8001); 108 109 110 /* wait for reply */ 111 FPGA_GET_REG(0, mc_int, &int_status); 112 while (!(int_status & MCINT_RX_CONTENT_AVAILABLE)) { 113 udelay(100); 114 if (ctr++ > 3) 115 return -ETIMEDOUT; 116 FPGA_GET_REG(0, mc_int, &int_status); 117 } 118 119 /* check reply */ 120 FPGA_GET_REG(0, mc_rx_cmd_status, &rx_cmd_status); 121 if ((rx_cmd_status >> 14) != slave) { 122 printf("mclink_receive: reply from slave %d, expected %d\n", 123 rx_cmd_status >> 14, slave); 124 return -EINVAL; 125 } 126 127 rx_cmd = (rx_cmd_status >> 12) & 0x03; 128 if (rx_cmd != 1) { 129 printf("mclink_send: received cmd %d, expected %d\n", 130 rx_cmd, 1); 131 return -EIO; 132 } 133 134 FPGA_GET_REG(0, mc_rx_data, data); 135 136 return 0; 137 } 138