blob: 9f230c9a973fa2836fa6e6c0027adafa9f81ff63 [file] [log] [blame]
Dirk Eibach049de792013-06-26 16:04:27 +02001/*
2 * (C) Copyright 2012
3 * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
4 *
Tom Rini9fab4bf2013-07-26 15:32:59 -04005 * SPDX-License-Identifier: GPL-2.0+
Dirk Eibach049de792013-06-26 16:04:27 +02006 */
7
8#include <common.h>
9#include <asm/io.h>
10#include <errno.h>
11
12#include <gdsys_fpga.h>
13
14enum {
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
24int 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
61int 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
96int 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}