1
2/*-
3 * Copyright (c) 2009-2010 Alexander Egorenkov <egorenar@gmail.com>
4 * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <dev/rt2860/rt2860_io.h>
20#include <dev/rt2860/rt2860_reg.h>
21
22/*
23 * Defines and macros
24 */
25
26/*
27 * RT2860_IO_EEPROM_RAISE_CLK
28 */
29#define RT2860_IO_EEPROM_RAISE_CLK(sc, val)							\
30do																	\
31{																	\
32	(val) |= RT2860_REG_EESK;										\
33																	\
34	rt2860_io_mac_write((sc), RT2860_REG_EEPROM_CSR, (val));		\
35																	\
36	DELAY(1);														\
37} while (0)
38
39/*
40 * RT2860_IO_EEPROM_LOWER_CLK
41 */
42#define RT2860_IO_EEPROM_LOWER_CLK(sc, val)							\
43do																	\
44{																	\
45	(val) &= ~RT2860_REG_EESK;										\
46																	\
47	rt2860_io_mac_write((sc), RT2860_REG_EEPROM_CSR, (val));		\
48																	\
49	DELAY(1);														\
50} while (0)
51
52#define RT2860_IO_BYTE_CRC16(byte, crc)								\
53	((uint16_t) (((crc) << 8) ^ rt2860_io_ccitt16[(((crc) >> 8) ^ (byte)) & 255]))
54
55/*
56 * Static function prototypes
57 */
58
59static void rt2860_io_eeprom_shiftout_bits(struct rt2860_softc *sc,
60	uint16_t val, uint16_t count);
61
62static uint16_t rt2860_io_eeprom_shiftin_bits(struct rt2860_softc *sc);
63
64static uint8_t rt2860_io_byte_rev(uint8_t byte);
65
66/* #ifdef RT305X_SOC */
67static const uint16_t rt3052_eeprom[] =
68{
69	0x3052, 0x0101, 0x0c00, 0x3043, 0x8852, 0xffff, 0xffff, 0xffff,
70	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
71	0xffff, 0xffff, 0xffff, 0xffff, 0x0c00, 0x3043, 0x7752, 0x0c00,
72	0x3043, 0x6652, 0x0822, 0x0024, 0xffff, 0x012f, 0x7755, 0xaaa8,
73	0x888c, 0xffff, 0x000c, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff,
74	0xffff, 0x0d0d, 0x0d0d, 0x0c0c, 0x0c0c, 0x0c0c, 0x0c0c, 0x0c0c,
75	0x1010, 0x1111, 0x1211, 0x1212, 0x1313, 0x1413, 0x1414, 0xffff,
76	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
77	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
78	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
79	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
80	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
81	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
82	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6666,
83	0xaacc, 0x6688, 0xaacc, 0x6688, 0xaacc, 0x6688, 0xaacc, 0x6688,
84	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
85	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
86	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
87	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
88	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
89	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
90	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
91	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
92	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
93	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
94	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
95	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
96	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
97	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
98	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
99	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
100	0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
101};
102
103uint8_t rt3052_rf_default[] = {
104	0x50,
105	0x01,
106	0xF7,
107	0x75,
108	0x40,
109	0x03,
110	0x42,
111	0x50,
112	0x39,
113	0x0F,
114	0x60,
115	0x21,
116	0x75,
117	0x75,
118	0x90,
119	0x58,
120	0xB3,
121	0x92,
122	0x2C,
123	0x02,
124	0xBA,
125	0xDB,
126	0x00,
127	0x31,
128	0x08,
129	0x01,
130	0x25, /* Core Power: 0x25=1.25V */
131	0x23, /* RF: 1.35V */
132      	0x13, /* ADC: must consist with R27 */
133	0x83,
134	0x00,
135	0x00,
136};
137/* #endif */
138
139
140/*
141 * Static variables
142 */
143
144static const uint16_t rt2860_io_ccitt16[] =
145{
146	0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
147	0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
148	0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
149	0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
150	0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
151	0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
152	0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
153	0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
154	0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
155	0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
156	0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
157	0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
158	0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
159	0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
160	0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
161	0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
162	0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
163	0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
164	0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
165	0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
166	0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
167	0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
168	0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
169	0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
170	0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
171	0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
172	0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
173	0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
174	0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
175	0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
176	0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
177	0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
178};
179
180/*
181 * rt2860_io_mac_read
182 */
183uint32_t rt2860_io_mac_read(struct rt2860_softc *sc, uint16_t reg)
184{
185	bus_space_read_4(sc->bst, sc->bsh, RT2860_REG_MAC_CSR0);
186	return bus_space_read_4(sc->bst, sc->bsh, reg);
187}
188
189/*
190 * rt2860_io_mac_read_multi
191 */
192void rt2860_io_mac_read_multi(struct rt2860_softc *sc,
193	uint16_t reg, void *buf, size_t len)
194{
195	bus_space_read_4(sc->bst, sc->bsh, RT2860_REG_MAC_CSR0);
196	bus_space_read_region_1(sc->bst, sc->bsh, reg, buf, len);
197}
198
199/*
200 * rt2860_io_mac_write
201 */
202void rt2860_io_mac_write(struct rt2860_softc *sc,
203	uint16_t reg, uint32_t val)
204{
205	bus_space_read_4(sc->bst, sc->bsh, RT2860_REG_MAC_CSR0);
206	bus_space_write_4(sc->bst, sc->bsh, reg, val);
207}
208
209/*
210 * rt2860_io_mac_write_multi
211 */
212void rt2860_io_mac_write_multi(struct rt2860_softc *sc,
213	uint16_t reg, const void *buf, size_t len)
214{
215	int i;
216	const uint8_t *p;
217
218	bus_space_read_4(sc->bst, sc->bsh, RT2860_REG_MAC_CSR0);
219
220	p = buf;
221	for (i = 0; i < len; i ++)
222		bus_space_write_1(sc->bst, sc->bsh, reg + i, *(p+i));
223//	bus_space_write_region_1(sc->bst, sc->bsh, reg, buf, len);
224}
225
226/*
227 * rt2860_io_mac_set_region_4
228 */
229void rt2860_io_mac_set_region_4(struct rt2860_softc *sc,
230	uint16_t reg, uint32_t val, size_t len)
231{
232	int i;
233
234	for (i = 0; i < len; i += sizeof(uint32_t))
235		rt2860_io_mac_write(sc, reg + i, val);
236}
237
238/* Read 16-bit from eFUSE ROM (>=RT3071 only.) */
239static uint16_t
240rt3090_efuse_read_2(struct rt2860_softc *sc, uint16_t addr)
241{
242	uint32_t tmp;
243	uint16_t reg;
244	int ntries;
245
246	addr *= 2;
247	/*-
248	 * Read one 16-byte block into registers EFUSE_DATA[0-3]:
249	 * DATA0: F E D C
250	 * DATA1: B A 9 8
251	 * DATA2: 7 6 5 4
252	 * DATA3: 3 2 1 0
253	 */
254	tmp = rt2860_io_mac_read(sc, RT3070_EFUSE_CTRL);
255	tmp &= ~(RT3070_EFSROM_MODE_MASK | RT3070_EFSROM_AIN_MASK);
256	tmp |= (addr & ~0xf) << RT3070_EFSROM_AIN_SHIFT | RT3070_EFSROM_KICK;
257	rt2860_io_mac_write(sc, RT3070_EFUSE_CTRL, tmp);
258	for (ntries = 0; ntries < 500; ntries++) {
259		tmp = rt2860_io_mac_read(sc, RT3070_EFUSE_CTRL);
260		if (!(tmp & RT3070_EFSROM_KICK))
261			break;
262		DELAY(2);
263	}
264	if (ntries == 500)
265		return 0xffff;
266
267	if ((tmp & RT3070_EFUSE_AOUT_MASK) == RT3070_EFUSE_AOUT_MASK)
268		return 0xffff;	/* address not found */
269
270	/* determine to which 32-bit register our 16-bit word belongs */
271	reg = RT3070_EFUSE_DATA3 - (addr & 0xc);
272	tmp = rt2860_io_mac_read(sc, reg);
273
274	return (addr & 2) ? tmp >> 16 : tmp & 0xffff;
275}
276
277
278/*
279 * rt2860_io_eeprom_read
280 */
281uint16_t rt2860_io_eeprom_read(struct rt2860_softc *sc, uint16_t addr)
282{
283	uint32_t tmp;
284	uint16_t val;
285
286	addr = (addr >> 1);
287
288	if (sc->mac_rev == 0x28720200) {
289		return (rt3052_eeprom[addr]);
290	} else if ((sc->mac_rev & 0xffff0000) >= 0x30710000) {
291		tmp = rt2860_io_mac_read(sc, RT3070_EFUSE_CTRL);
292		if (tmp & RT3070_SEL_EFUSE)
293			return (rt3090_efuse_read_2(sc, addr));
294	}
295
296	tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR);
297
298	tmp &= ~(RT2860_REG_EEDI | RT2860_REG_EEDO | RT2860_REG_EESK);
299	tmp |= RT2860_REG_EECS;
300
301	rt2860_io_mac_write(sc, RT2860_REG_EEPROM_CSR, tmp);
302
303	if (((sc->mac_rev & 0xffff0000) != 0x30710000) &&
304		((sc->mac_rev & 0xffff0000) != 0x30900000) &&
305		((sc->mac_rev & 0xffff0000) != 0x35720000) &&
306		((sc->mac_rev & 0xffff0000) != 0x33900000))
307	{
308		RT2860_IO_EEPROM_RAISE_CLK(sc, tmp);
309		RT2860_IO_EEPROM_LOWER_CLK(sc, tmp);
310	}
311
312	rt2860_io_eeprom_shiftout_bits(sc, RT2860_REG_EEOP_READ, 3);
313	rt2860_io_eeprom_shiftout_bits(sc, addr, sc->eeprom_addr_num);
314
315	val = rt2860_io_eeprom_shiftin_bits(sc);
316
317	tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR);
318
319	tmp &= ~(RT2860_REG_EECS | RT2860_REG_EEDI);
320
321	rt2860_io_mac_write(sc, RT2860_REG_EEPROM_CSR, tmp);
322
323	RT2860_IO_EEPROM_RAISE_CLK(sc, tmp);
324	RT2860_IO_EEPROM_LOWER_CLK(sc, tmp);
325
326	return val;
327}
328
329/*
330 * rt2860_io_eeprom_read_multi
331 */
332void rt2860_io_eeprom_read_multi(struct rt2860_softc *sc,
333	uint16_t addr, void *buf, size_t len)
334{
335	uint16_t *ptr;
336	int i;
337
338	len += len % sizeof(uint16_t);
339	ptr = buf;
340
341	i = 0;
342
343	do
344	{
345		*ptr++ = rt2860_io_eeprom_read(sc, addr + i);
346
347		i += sizeof(uint16_t);
348		len -= sizeof(uint16_t);
349	} while (len > 0);
350}
351
352/*
353 * rt2860_io_bbp_read
354 */
355uint8_t rt2860_io_bbp_read(struct rt2860_softc *sc, uint8_t reg)
356{
357	int ntries;
358	uint32_t tmp;
359
360	if (sc->mac_rev == 0x28720200)
361	{
362		for (ntries = 0; ntries < 100; ntries ++) {
363			if ( !(rt2860_io_mac_read(sc, RT2860_REG_BBP_CSR_CFG) &
364			    RT2860_REG_BBP_CSR_BUSY) )
365				break;
366			DELAY(1);
367		}
368		if (ntries == 100) {
369			printf("%s:%s: BBP busy after 100 probes\n",
370				device_get_nameunit(sc->dev), __func__);
371			return (0);
372		}
373		rt2860_io_mac_write(sc, RT2860_REG_BBP_CSR_CFG,
374		    RT2860_REG_BBP_CSR_READ |
375		    RT2860_REG_BBP_CSR_KICK | RT2860_REG_BBP_RW_MODE_PARALLEL |
376		    (reg & RT2860_REG_BBP_REG_MASK) << RT2860_REG_BBP_REG_SHIFT);
377		for (ntries = 0; ntries < 100; ntries ++) {
378			if ( !(rt2860_io_mac_read(sc, RT2860_REG_BBP_CSR_CFG) &
379			    RT2860_REG_BBP_CSR_BUSY) )
380				break;
381			DELAY(1);
382		}
383		if (ntries == 100) {
384			printf("%s:%s: BBP busy after 100 probes\n",
385				device_get_nameunit(sc->dev), __func__);
386			return (0);
387		}
388		else {
389			return
390			    ((rt2860_io_mac_read(sc, RT2860_REG_BBP_CSR_CFG) >>
391			    RT2860_REG_BBP_VAL_SHIFT) &
392			    RT2860_REG_BBP_VAL_MASK);
393		}
394		return (0);
395	}
396
397	for (ntries = 0; ntries < 100; ntries++)
398	{
399		if (!(rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT) &
400			RT2860_REG_BBP_CSR_BUSY))
401			break;
402
403		DELAY(1);
404	}
405
406	if (ntries == 100)
407	{
408		printf("%s: could not read from BBP through MCU: reg=0x%02x\n",
409			device_get_nameunit(sc->dev), reg);
410		return 0;
411	}
412
413	tmp = RT2860_REG_BBP_RW_MODE_PARALLEL |
414		RT2860_REG_BBP_CSR_BUSY |
415		RT2860_REG_BBP_CSR_READ |
416		((reg & RT2860_REG_BBP_REG_MASK) << RT2860_REG_BBP_REG_SHIFT);
417
418	rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT, tmp);
419
420	rt2860_io_mcu_cmd(sc, RT2860_IO_MCU_CMD_BBP,
421		RT2860_REG_H2M_TOKEN_NO_INTR, 0);
422
423	DELAY(1000);
424
425	for (ntries = 0; ntries < 100; ntries++)
426	{
427		tmp = rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT);
428		if (!(tmp & RT2860_REG_BBP_CSR_BUSY))
429			return ((tmp >> RT2860_REG_BBP_VAL_SHIFT) &
430				RT2860_REG_BBP_VAL_MASK);
431
432		DELAY(1);
433	}
434
435	printf("%s: could not read from BBP through MCU: reg=0x%02x\n",
436		device_get_nameunit(sc->dev), reg);
437
438	return 0;
439}
440
441/*
442 * rt2860_io_bbp_write
443 */
444void rt2860_io_bbp_write(struct rt2860_softc *sc, uint8_t reg, uint8_t val)
445{
446	int ntries;
447	uint32_t tmp;
448
449	if (sc->mac_rev == 0x28720200)
450	{
451		for (ntries = 0; ntries < 100; ntries ++) {
452			if ( !(rt2860_io_mac_read(sc, RT2860_REG_BBP_CSR_CFG) &
453			    RT2860_REG_BBP_CSR_BUSY) )
454				break;
455			DELAY(1);
456		}
457		if (ntries == 100) {
458			printf("%s:%s: BBP busy after 100 probes\n",
459				device_get_nameunit(sc->dev), __func__);
460			return;
461		}
462		rt2860_io_mac_write(sc, RT2860_REG_BBP_CSR_CFG,
463		    RT2860_REG_BBP_CSR_KICK | RT2860_REG_BBP_RW_MODE_PARALLEL |
464		    (reg & RT2860_REG_BBP_REG_MASK) << RT2860_REG_BBP_REG_SHIFT |
465		    (val & RT2860_REG_BBP_VAL_MASK) << RT2860_REG_BBP_VAL_SHIFT );
466		rt2860_io_bbp_read(sc, reg);
467		return;
468	}
469
470	for (ntries = 0; ntries < 100; ntries++)
471	{
472		if (!(rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT) &
473			RT2860_REG_BBP_CSR_BUSY))
474			break;
475
476		DELAY(1);
477	}
478
479	if (ntries == 100)
480	{
481		printf("%s: could not write to BBP through MCU: reg=0x%02x\n",
482			device_get_nameunit(sc->dev), reg);
483		return;
484	}
485
486	tmp = RT2860_REG_BBP_RW_MODE_PARALLEL |
487		RT2860_REG_BBP_CSR_BUSY |
488		((reg & RT2860_REG_BBP_REG_MASK) << RT2860_REG_BBP_REG_SHIFT) |
489		((val & RT2860_REG_BBP_VAL_MASK) << RT2860_REG_BBP_VAL_SHIFT);
490
491	rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT, tmp);
492
493	rt2860_io_mcu_cmd(sc, RT2860_IO_MCU_CMD_BBP,
494		RT2860_REG_H2M_TOKEN_NO_INTR, 0);
495
496	DELAY(1000);
497}
498
499/*
500 * rt2860_io_rf_write
501 */
502void rt2860_io_rf_write(struct rt2860_softc *sc, uint8_t reg, uint32_t val)
503{
504	int ntries;
505	if (sc->mac_rev == 0x28720200)
506	{
507		for (ntries = 0; ntries < 100; ntries ++) {
508			if ( !(rt2860_io_mac_read(sc, RT2872_REG_RF_CSR_CFG) &
509			    RT2872_REG_RF_CSR_BUSY) )
510				break;
511			DELAY(1);
512		}
513		if (ntries == 100) {
514			printf("%s:%s: RF busy after 100 probes\n",
515				device_get_nameunit(sc->dev), __func__);
516			return;
517		}
518		rt2860_io_mac_write(sc, RT2872_REG_RF_CSR_CFG,
519		    RT2872_REG_RF_CSR_KICK | RT2872_REG_RF_CSR_WRITE |
520		    (reg & RT2872_REG_RF_ID_MASK) << RT2872_REG_RF_ID_SHIFT |
521		    (val & RT2872_REG_RF_VAL_MASK) << RT2872_REG_RF_VAL_SHIFT );
522		rt2860_io_rf_read(sc, reg);
523		return;
524	}
525
526
527	for (ntries = 0; ntries < 100; ntries++)
528		if (!(rt2860_io_mac_read(sc, RT2860_REG_RF_CSR_CFG0) &
529			RT2860_REG_RF_BUSY))
530			break;
531
532	if (ntries == 100)
533	{
534		printf("%s: could not write to RF: reg=0x%02x\n",
535			device_get_nameunit(sc->dev), reg);
536		return;
537	}
538
539	rt2860_io_mac_write(sc, RT2860_REG_RF_CSR_CFG0, val);
540}
541
542/*
543 * rt2860_io_rf_read
544 */
545int32_t rt2860_io_rf_read(struct rt2860_softc *sc, uint8_t reg)
546{
547	int ntries;
548	if (sc->mac_rev == 0x28720200)
549	{
550		for (ntries = 0; ntries < 100; ntries ++) {
551			if ( !(rt2860_io_mac_read(sc, RT2872_REG_RF_CSR_CFG) &
552			    RT2872_REG_RF_CSR_BUSY) )
553				break;
554			DELAY(1);
555		}
556		if (ntries == 100) {
557			printf("%s:%s: RF busy after 100 probes\n",
558				device_get_nameunit(sc->dev), __func__);
559			return (-1);
560		}
561		rt2860_io_mac_write(sc, RT2872_REG_RF_CSR_CFG,
562		    RT2872_REG_RF_CSR_KICK |
563		    (reg & RT2872_REG_RF_ID_MASK) << RT2872_REG_RF_ID_SHIFT );
564
565		for (ntries = 0; ntries < 100; ntries ++) {
566			if ( !(rt2860_io_mac_read(sc, RT2872_REG_RF_CSR_CFG) &
567			    RT2872_REG_RF_CSR_BUSY) )
568				break;
569			DELAY(1);
570		}
571		if (ntries == 100) {
572			printf("%s:%s: RF busy after 100 probes\n",
573				device_get_nameunit(sc->dev), __func__);
574		}
575
576		return (rt2860_io_mac_read(sc, RT2872_REG_RF_CSR_CFG) & RT2872_REG_RF_VAL_MASK);
577	}
578	return (-1);
579}
580
581/*
582 * rt2860_io_rf_load_defaults
583 */
584void rt2860_io_rf_load_defaults(struct rt2860_softc *sc)
585{
586	int i;
587
588	if (sc->mac_rev == 0x28720200) {
589		for (i = 0; i < 32; i ++)
590			rt2860_io_rf_write(sc, i, rt3052_rf_default[i]);
591	}
592}
593
594/*
595 * rt2860_io_mcu_cmd
596 */
597void rt2860_io_mcu_cmd(struct rt2860_softc *sc, uint8_t cmd,
598	uint8_t token, uint16_t arg)
599{
600	uint32_t tmp;
601	int ntries;
602
603	if (sc->mac_rev == 0x28720200)
604		return;
605
606	for (ntries = 0; ntries < 100; ntries++)
607	{
608		if (!(rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX) &
609			RT2860_REG_H2M_BUSY))
610			break;
611
612		DELAY(2);
613	}
614
615	if (ntries == 100)
616	{
617		printf("%s: could not read H2M: cmd=0x%02x\n",
618			device_get_nameunit(sc->dev), cmd);
619		return;
620	}
621
622	tmp = RT2860_REG_H2M_BUSY | (token << 16) | arg;
623
624	rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX, tmp);
625	rt2860_io_mac_write(sc, RT2860_REG_H2M_HOST_CMD, cmd);
626}
627
628/*
629 * rt2860_io_mcu_cmd_check
630 */
631int rt2860_io_mcu_cmd_check(struct rt2860_softc *sc, uint8_t cid)
632{
633	uint32_t tmp, mask, status;
634	int result, ntries;
635
636	result = -1;
637
638	for (ntries = 0; ntries < 200; ntries++)
639	{
640		tmp = rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX_CID);
641
642		if (((cid >> RT2860_REG_H2M_CID0_SHIFT) & RT2860_REG_H2M_CID_MASK) == cid)
643		{
644			mask = (RT2860_REG_H2M_CID_MASK << RT2860_REG_H2M_CID0_SHIFT);
645			break;
646		}
647		else if (((tmp >> RT2860_REG_H2M_CID1_SHIFT) & RT2860_REG_H2M_CID_MASK) == cid)
648		{
649			mask = (RT2860_REG_H2M_CID_MASK << RT2860_REG_H2M_CID1_SHIFT);
650			break;
651		}
652		else if (((tmp >> RT2860_REG_H2M_CID2_SHIFT) & RT2860_REG_H2M_CID_MASK) == cid)
653		{
654			mask = (RT2860_REG_H2M_CID_MASK << RT2860_REG_H2M_CID2_SHIFT);
655			break;
656		}
657		else if (((tmp >> RT2860_REG_H2M_CID3_SHIFT) & RT2860_REG_H2M_CID_MASK) == cid)
658		{
659			mask = (RT2860_REG_H2M_CID_MASK << RT2860_REG_H2M_CID3_SHIFT);
660			break;
661		}
662
663		DELAY(100);
664	}
665
666	status = rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX_STATUS);
667
668	if (ntries < 200)
669	{
670		status &= mask;
671
672		if ((status == 0x1) ||
673			(status == 0x100) ||
674			(status == 0x10000) ||
675			(status == 0x1000000))
676			result = 0;
677	}
678
679	rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX_STATUS, 0xffffffff);
680	rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX_CID, 0xffffffff);
681
682	return result;
683}
684
685/*
686 * rt2860_io_mcu_load_ucode
687 */
688int rt2860_io_mcu_load_ucode(struct rt2860_softc *sc,
689	const uint8_t *ucode, size_t len)
690{
691	int i, ntries;
692	uint16_t crc;
693
694	for (i = 0, crc = 0xffff; i < len - 2; i++)
695		crc = RT2860_IO_BYTE_CRC16(rt2860_io_byte_rev(ucode[i]), crc);
696
697	if (ucode[len - 2] != rt2860_io_byte_rev(crc >> 8) ||
698		ucode[len - 1] != rt2860_io_byte_rev(crc))
699	{
700		printf("%s: wrong microcode crc\n",
701			device_get_nameunit(sc->dev));
702		return EINVAL;
703	}
704
705	rt2860_io_mac_write(sc, RT2860_REG_PBF_SYS_CTRL, RT2860_REG_HST_PM_SEL);
706
707	for(i = 0; i < len; i += 4)
708	{
709		rt2860_io_mac_write(sc, RT2860_REG_MCU_UCODE_BASE + i,
710		    (ucode[i+3] << 24) | (ucode[i+2] << 16) |
711		    (ucode[i+1] << 8) | ucode[i]);
712	}
713
714	if (sc->mac_rev != 0x28720200)
715		rt2860_io_mac_write_multi(sc, RT2860_REG_MCU_UCODE_BASE,
716		    ucode, len);
717
718	rt2860_io_mac_write(sc, RT2860_REG_PBF_SYS_CTRL, 0);
719
720	if (sc->mac_rev != 0x28720200)
721		rt2860_io_mac_write(sc, RT2860_REG_PBF_SYS_CTRL,
722		    RT2860_REG_MCU_RESET);
723
724	DELAY(10000);
725
726	/* initialize BBP R/W access agent */
727
728	rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT, 0);
729	rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX, 0);
730
731	if (sc->mac_rev != 0x28720200) {
732
733		for (ntries = 0; ntries < 1000; ntries++)
734		{
735			if (rt2860_io_mac_read(sc, RT2860_REG_PBF_SYS_CTRL) &
736				RT2860_REG_MCU_READY)
737				break;
738
739			DELAY(1000);
740		}
741
742		if (ntries == 1000)
743		{
744			printf("%s: timeout waiting for MCU to initialize\n",
745				device_get_nameunit(sc->dev));
746			return ETIMEDOUT;
747		}
748	}
749
750	return 0;
751}
752
753/*
754 * rt2860_io_eeprom_shiftout_bits
755 */
756static void rt2860_io_eeprom_shiftout_bits(struct rt2860_softc *sc,
757	uint16_t val, uint16_t count)
758{
759	uint32_t mask, tmp;
760
761	mask = (1 << (count - 1));
762
763	tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR);
764
765	tmp &= ~(RT2860_REG_EEDO | RT2860_REG_EEDI);
766
767	do
768	{
769	    tmp &= ~RT2860_REG_EEDI;
770
771	    if(val & mask)
772			tmp |= RT2860_REG_EEDI;
773
774		rt2860_io_mac_write(sc, RT2860_REG_EEPROM_CSR, tmp);
775
776		RT2860_IO_EEPROM_RAISE_CLK(sc, tmp);
777		RT2860_IO_EEPROM_LOWER_CLK(sc, tmp);
778
779	    mask = (mask >> 1);
780	} while (mask);
781
782	tmp &= ~RT2860_REG_EEDI;
783
784	rt2860_io_mac_write(sc, RT2860_REG_EEPROM_CSR, tmp);
785}
786
787/*
788 * rt2860_io_eeprom_shiftin_bits
789 */
790static uint16_t rt2860_io_eeprom_shiftin_bits(struct rt2860_softc *sc)
791{
792	uint32_t tmp;
793	uint16_t val;
794	int i;
795
796	val = 0;
797
798	tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR);
799
800	tmp &= ~(RT2860_REG_EEDO | RT2860_REG_EEDI);
801
802	for(i = 0; i < 16; i++)
803	{
804		val = (val << 1);
805
806		RT2860_IO_EEPROM_RAISE_CLK(sc, tmp);
807
808		tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR);
809
810		RT2860_IO_EEPROM_LOWER_CLK(sc, tmp);
811
812		tmp &= ~RT2860_REG_EEDI;
813		if(tmp & RT2860_REG_EEDO)
814		    val |= 1;
815	}
816
817	return val;
818}
819
820/*
821 * rt2860_io_byte_rev
822 */
823static uint8_t rt2860_io_byte_rev(uint8_t byte)
824{
825	int i;
826	uint8_t tmp;
827
828	for(i = 0, tmp = 0; ; i++)
829	{
830		if(byte & 0x80)
831			tmp |= 0x80;
832
833		if(i == 7)
834			break;
835
836		byte <<= 1;
837		tmp >>= 1;
838	}
839
840	return tmp;
841}
842