xref: /rk3399_rockchip-uboot/board/gdsys/common/mclink.c (revision 56b50286d57d0a8769d28611a4e104fca972b3ff)
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