ar71xx: fix MDIO access on ar7242 (based on a patch by Jess Zhu)
[openwrt/staging/yousong.git] / target / linux / ar71xx / files / arch / mips / ar71xx / devices.c
1 /*
2 * Atheros AR71xx SoC platform devices
3 *
4 * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
5 * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
6 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
7 *
8 * Parts of this file are based on Atheros 2.6.15 BSP
9 * Parts of this file are based on Atheros 2.6.31 BSP
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 as published
13 * by the Free Software Foundation.
14 */
15
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/delay.h>
19 #include <linux/etherdevice.h>
20 #include <linux/platform_device.h>
21 #include <linux/serial_8250.h>
22
23 #include <asm/mach-ar71xx/ar71xx.h>
24
25 #include "devices.h"
26
27 unsigned char ar71xx_mac_base[ETH_ALEN] __initdata;
28
29 static struct resource ar71xx_uart_resources[] = {
30 {
31 .start = AR71XX_UART_BASE,
32 .end = AR71XX_UART_BASE + AR71XX_UART_SIZE - 1,
33 .flags = IORESOURCE_MEM,
34 },
35 };
36
37 #define AR71XX_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
38 static struct plat_serial8250_port ar71xx_uart_data[] = {
39 {
40 .mapbase = AR71XX_UART_BASE,
41 .irq = AR71XX_MISC_IRQ_UART,
42 .flags = AR71XX_UART_FLAGS,
43 .iotype = UPIO_MEM32,
44 .regshift = 2,
45 }, {
46 /* terminating entry */
47 }
48 };
49
50 static struct platform_device ar71xx_uart_device = {
51 .name = "serial8250",
52 .id = PLAT8250_DEV_PLATFORM,
53 .resource = ar71xx_uart_resources,
54 .num_resources = ARRAY_SIZE(ar71xx_uart_resources),
55 .dev = {
56 .platform_data = ar71xx_uart_data
57 },
58 };
59
60 void __init ar71xx_add_device_uart(void)
61 {
62 switch (ar71xx_soc) {
63 case AR71XX_SOC_AR7130:
64 case AR71XX_SOC_AR7141:
65 case AR71XX_SOC_AR7161:
66 case AR71XX_SOC_AR7240:
67 case AR71XX_SOC_AR7241:
68 case AR71XX_SOC_AR7242:
69 case AR71XX_SOC_AR9130:
70 case AR71XX_SOC_AR9132:
71 ar71xx_uart_data[0].uartclk = ar71xx_ahb_freq;
72 break;
73
74 case AR71XX_SOC_AR9341:
75 case AR71XX_SOC_AR9342:
76 case AR71XX_SOC_AR9344:
77 ar71xx_uart_data[0].uartclk = ar71xx_ref_freq;
78 break;
79
80 default:
81 BUG();
82
83 }
84 platform_device_register(&ar71xx_uart_device);
85 }
86
87 static struct resource ar71xx_mdio_resources[] = {
88 {
89 .name = "mdio_base",
90 .flags = IORESOURCE_MEM,
91 .start = AR71XX_GE0_BASE,
92 .end = AR71XX_GE0_BASE + 0x200 - 1,
93 }
94 };
95
96 static struct ag71xx_mdio_platform_data ar71xx_mdio_data;
97
98 struct platform_device ar71xx_mdio_device = {
99 .name = "ag71xx-mdio",
100 .id = -1,
101 .resource = ar71xx_mdio_resources,
102 .num_resources = ARRAY_SIZE(ar71xx_mdio_resources),
103 .dev = {
104 .platform_data = &ar71xx_mdio_data,
105 },
106 };
107
108 static void ar71xx_set_pll(u32 cfg_reg, u32 pll_reg, u32 pll_val, u32 shift)
109 {
110 void __iomem *base;
111 u32 t;
112
113 base = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE);
114
115 t = __raw_readl(base + cfg_reg);
116 t &= ~(3 << shift);
117 t |= (2 << shift);
118 __raw_writel(t, base + cfg_reg);
119 udelay(100);
120
121 __raw_writel(pll_val, base + pll_reg);
122
123 t |= (3 << shift);
124 __raw_writel(t, base + cfg_reg);
125 udelay(100);
126
127 t &= ~(3 << shift);
128 __raw_writel(t, base + cfg_reg);
129 udelay(100);
130
131 printk(KERN_DEBUG "ar71xx: pll_reg %#x: %#x\n",
132 (unsigned int)(base + pll_reg), __raw_readl(base + pll_reg));
133
134 iounmap(base);
135 }
136
137 void __init ar71xx_add_device_mdio(u32 phy_mask)
138 {
139 switch (ar71xx_soc) {
140 case AR71XX_SOC_AR7240:
141 ar71xx_mdio_data.is_ar7240 = 1;
142 break;
143 case AR71XX_SOC_AR7241:
144 ar71xx_mdio_data.is_ar7240 = 1;
145 ar71xx_mdio_resources[0].start = AR71XX_GE1_BASE;
146 ar71xx_mdio_resources[0].end = AR71XX_GE1_BASE + 0x200 - 1;
147 break;
148 case AR71XX_SOC_AR7242:
149 ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG,
150 AR7242_PLL_REG_ETH0_INT_CLOCK, 0x62000000,
151 AR71XX_ETH0_PLL_SHIFT);
152 break;
153 default:
154 break;
155 }
156
157 ar71xx_mdio_data.phy_mask = phy_mask;
158
159 platform_device_register(&ar71xx_mdio_device);
160 }
161
162 struct ar71xx_eth_pll_data ar71xx_eth0_pll_data;
163 struct ar71xx_eth_pll_data ar71xx_eth1_pll_data;
164
165 static u32 ar71xx_get_eth_pll(unsigned int mac, int speed)
166 {
167 struct ar71xx_eth_pll_data *pll_data;
168 u32 pll_val;
169
170 switch (mac) {
171 case 0:
172 pll_data = &ar71xx_eth0_pll_data;
173 break;
174 case 1:
175 pll_data = &ar71xx_eth1_pll_data;
176 break;
177 default:
178 BUG();
179 }
180
181 switch (speed) {
182 case SPEED_10:
183 pll_val = pll_data->pll_10;
184 break;
185 case SPEED_100:
186 pll_val = pll_data->pll_100;
187 break;
188 case SPEED_1000:
189 pll_val = pll_data->pll_1000;
190 break;
191 default:
192 BUG();
193 }
194
195 return pll_val;
196 }
197
198 static void ar71xx_set_pll_ge0(int speed)
199 {
200 u32 val = ar71xx_get_eth_pll(0, speed);
201
202 ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG, AR71XX_PLL_REG_ETH0_INT_CLOCK,
203 val, AR71XX_ETH0_PLL_SHIFT);
204 }
205
206 static void ar71xx_set_pll_ge1(int speed)
207 {
208 u32 val = ar71xx_get_eth_pll(1, speed);
209
210 ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG, AR71XX_PLL_REG_ETH1_INT_CLOCK,
211 val, AR71XX_ETH1_PLL_SHIFT);
212 }
213
214 static void ar724x_set_pll_ge0(int speed)
215 {
216 /* TODO */
217 }
218
219 static void ar724x_set_pll_ge1(int speed)
220 {
221 /* TODO */
222 }
223
224 static void ar7242_set_pll_ge0(int speed)
225 {
226 u32 val = ar71xx_get_eth_pll(0, speed);
227
228 ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG, AR7242_PLL_REG_ETH0_INT_CLOCK,
229 val, AR71XX_ETH0_PLL_SHIFT);
230 }
231
232 static void ar91xx_set_pll_ge0(int speed)
233 {
234 u32 val = ar71xx_get_eth_pll(0, speed);
235
236 ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG, AR91XX_PLL_REG_ETH0_INT_CLOCK,
237 val, AR91XX_ETH0_PLL_SHIFT);
238 }
239
240 static void ar91xx_set_pll_ge1(int speed)
241 {
242 u32 val = ar71xx_get_eth_pll(1, speed);
243
244 ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG, AR91XX_PLL_REG_ETH1_INT_CLOCK,
245 val, AR91XX_ETH1_PLL_SHIFT);
246 }
247
248 static void ar71xx_ddr_flush_ge0(void)
249 {
250 ar71xx_ddr_flush(AR71XX_DDR_REG_FLUSH_GE0);
251 }
252
253 static void ar71xx_ddr_flush_ge1(void)
254 {
255 ar71xx_ddr_flush(AR71XX_DDR_REG_FLUSH_GE1);
256 }
257
258 static void ar724x_ddr_flush_ge0(void)
259 {
260 ar71xx_ddr_flush(AR724X_DDR_REG_FLUSH_GE0);
261 }
262
263 static void ar724x_ddr_flush_ge1(void)
264 {
265 ar71xx_ddr_flush(AR724X_DDR_REG_FLUSH_GE1);
266 }
267
268 static void ar91xx_ddr_flush_ge0(void)
269 {
270 ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_GE0);
271 }
272
273 static void ar91xx_ddr_flush_ge1(void)
274 {
275 ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_GE1);
276 }
277
278 static struct resource ar71xx_eth0_resources[] = {
279 {
280 .name = "mac_base",
281 .flags = IORESOURCE_MEM,
282 .start = AR71XX_GE0_BASE,
283 .end = AR71XX_GE0_BASE + 0x200 - 1,
284 }, {
285 .name = "mii_ctrl",
286 .flags = IORESOURCE_MEM,
287 .start = AR71XX_MII_BASE + MII_REG_MII0_CTRL,
288 .end = AR71XX_MII_BASE + MII_REG_MII0_CTRL + 3,
289 }, {
290 .name = "mac_irq",
291 .flags = IORESOURCE_IRQ,
292 .start = AR71XX_CPU_IRQ_GE0,
293 .end = AR71XX_CPU_IRQ_GE0,
294 },
295 };
296
297 struct ag71xx_platform_data ar71xx_eth0_data = {
298 .reset_bit = RESET_MODULE_GE0_MAC,
299 };
300
301 struct platform_device ar71xx_eth0_device = {
302 .name = "ag71xx",
303 .id = 0,
304 .resource = ar71xx_eth0_resources,
305 .num_resources = ARRAY_SIZE(ar71xx_eth0_resources),
306 .dev = {
307 .platform_data = &ar71xx_eth0_data,
308 },
309 };
310
311 static struct resource ar71xx_eth1_resources[] = {
312 {
313 .name = "mac_base",
314 .flags = IORESOURCE_MEM,
315 .start = AR71XX_GE1_BASE,
316 .end = AR71XX_GE1_BASE + 0x200 - 1,
317 }, {
318 .name = "mii_ctrl",
319 .flags = IORESOURCE_MEM,
320 .start = AR71XX_MII_BASE + MII_REG_MII1_CTRL,
321 .end = AR71XX_MII_BASE + MII_REG_MII1_CTRL + 3,
322 }, {
323 .name = "mac_irq",
324 .flags = IORESOURCE_IRQ,
325 .start = AR71XX_CPU_IRQ_GE1,
326 .end = AR71XX_CPU_IRQ_GE1,
327 },
328 };
329
330 struct ag71xx_platform_data ar71xx_eth1_data = {
331 .reset_bit = RESET_MODULE_GE1_MAC,
332 };
333
334 struct platform_device ar71xx_eth1_device = {
335 .name = "ag71xx",
336 .id = 1,
337 .resource = ar71xx_eth1_resources,
338 .num_resources = ARRAY_SIZE(ar71xx_eth1_resources),
339 .dev = {
340 .platform_data = &ar71xx_eth1_data,
341 },
342 };
343
344 #define AR71XX_PLL_VAL_1000 0x00110000
345 #define AR71XX_PLL_VAL_100 0x00001099
346 #define AR71XX_PLL_VAL_10 0x00991099
347
348 #define AR724X_PLL_VAL_1000 0x00110000
349 #define AR724X_PLL_VAL_100 0x00001099
350 #define AR724X_PLL_VAL_10 0x00991099
351
352 #define AR7242_PLL_VAL_1000 0x1c000000
353 #define AR7242_PLL_VAL_100 0x00000101
354 #define AR7242_PLL_VAL_10 0x00001616
355
356 #define AR91XX_PLL_VAL_1000 0x1a000000
357 #define AR91XX_PLL_VAL_100 0x13000a44
358 #define AR91XX_PLL_VAL_10 0x00441099
359
360 static void __init ar71xx_init_eth_pll_data(unsigned int id)
361 {
362 struct ar71xx_eth_pll_data *pll_data;
363 u32 pll_10, pll_100, pll_1000;
364
365 switch (id) {
366 case 0:
367 pll_data = &ar71xx_eth0_pll_data;
368 break;
369 case 1:
370 pll_data = &ar71xx_eth1_pll_data;
371 break;
372 default:
373 BUG();
374 }
375
376 switch (ar71xx_soc) {
377 case AR71XX_SOC_AR7130:
378 case AR71XX_SOC_AR7141:
379 case AR71XX_SOC_AR7161:
380 pll_10 = AR71XX_PLL_VAL_10;
381 pll_100 = AR71XX_PLL_VAL_100;
382 pll_1000 = AR71XX_PLL_VAL_1000;
383 break;
384
385 case AR71XX_SOC_AR7240:
386 case AR71XX_SOC_AR7241:
387 pll_10 = AR724X_PLL_VAL_10;
388 pll_100 = AR724X_PLL_VAL_100;
389 pll_1000 = AR724X_PLL_VAL_1000;
390 break;
391
392 case AR71XX_SOC_AR7242:
393 pll_10 = AR7242_PLL_VAL_10;
394 pll_100 = AR7242_PLL_VAL_100;
395 pll_1000 = AR7242_PLL_VAL_1000;
396 break;
397
398 case AR71XX_SOC_AR9130:
399 case AR71XX_SOC_AR9132:
400 pll_10 = AR91XX_PLL_VAL_10;
401 pll_100 = AR91XX_PLL_VAL_100;
402 pll_1000 = AR91XX_PLL_VAL_1000;
403 break;
404 default:
405 BUG();
406 }
407
408 if (!pll_data->pll_10)
409 pll_data->pll_10 = pll_10;
410
411 if (!pll_data->pll_100)
412 pll_data->pll_100 = pll_100;
413
414 if (!pll_data->pll_1000)
415 pll_data->pll_1000 = pll_1000;
416 }
417
418 static int ar71xx_eth_instance __initdata;
419 void __init ar71xx_add_device_eth(unsigned int id)
420 {
421 struct platform_device *pdev;
422 struct ag71xx_platform_data *pdata;
423
424 ar71xx_init_eth_pll_data(id);
425
426 switch (id) {
427 case 0:
428 switch (ar71xx_eth0_data.phy_if_mode) {
429 case PHY_INTERFACE_MODE_MII:
430 ar71xx_eth0_data.mii_if = MII0_CTRL_IF_MII;
431 break;
432 case PHY_INTERFACE_MODE_GMII:
433 ar71xx_eth0_data.mii_if = MII0_CTRL_IF_GMII;
434 break;
435 case PHY_INTERFACE_MODE_RGMII:
436 ar71xx_eth0_data.mii_if = MII0_CTRL_IF_RGMII;
437 break;
438 case PHY_INTERFACE_MODE_RMII:
439 ar71xx_eth0_data.mii_if = MII0_CTRL_IF_RMII;
440 break;
441 default:
442 printk(KERN_ERR "ar71xx: invalid PHY interface mode "
443 "for eth0\n");
444 return;
445 }
446 pdev = &ar71xx_eth0_device;
447 break;
448 case 1:
449 switch (ar71xx_eth1_data.phy_if_mode) {
450 case PHY_INTERFACE_MODE_RMII:
451 ar71xx_eth1_data.mii_if = MII1_CTRL_IF_RMII;
452 break;
453 case PHY_INTERFACE_MODE_RGMII:
454 ar71xx_eth1_data.mii_if = MII1_CTRL_IF_RGMII;
455 break;
456 default:
457 printk(KERN_ERR "ar71xx: invalid PHY interface mode "
458 "for eth1\n");
459 return;
460 }
461 pdev = &ar71xx_eth1_device;
462 break;
463 default:
464 printk(KERN_ERR "ar71xx: invalid ethernet id %d\n", id);
465 return;
466 }
467
468 pdata = pdev->dev.platform_data;
469
470 switch (ar71xx_soc) {
471 case AR71XX_SOC_AR7130:
472 pdata->ddr_flush = id ? ar71xx_ddr_flush_ge1
473 : ar71xx_ddr_flush_ge0;
474 pdata->set_pll = id ? ar71xx_set_pll_ge1
475 : ar71xx_set_pll_ge0;
476 break;
477
478 case AR71XX_SOC_AR7141:
479 case AR71XX_SOC_AR7161:
480 pdata->ddr_flush = id ? ar71xx_ddr_flush_ge1
481 : ar71xx_ddr_flush_ge0;
482 pdata->set_pll = id ? ar71xx_set_pll_ge1
483 : ar71xx_set_pll_ge0;
484 pdata->has_gbit = 1;
485 break;
486
487 case AR71XX_SOC_AR7242:
488 ar71xx_eth0_data.reset_bit |= AR724X_RESET_GE0_MDIO;
489 ar71xx_eth1_data.reset_bit |= AR724X_RESET_GE1_MDIO;
490 pdata->ddr_flush = id ? ar724x_ddr_flush_ge1
491 : ar724x_ddr_flush_ge0;
492 pdata->set_pll = id ? ar724x_set_pll_ge1
493 : ar7242_set_pll_ge0;
494 pdata->has_gbit = 1;
495 pdata->is_ar724x = 1;
496
497 if (!pdata->fifo_cfg1)
498 pdata->fifo_cfg1 = 0x0010ffff;
499 if (!pdata->fifo_cfg2)
500 pdata->fifo_cfg2 = 0x015500aa;
501 if (!pdata->fifo_cfg3)
502 pdata->fifo_cfg3 = 0x01f00140;
503 break;
504
505 case AR71XX_SOC_AR7241:
506 ar71xx_eth0_data.reset_bit |= AR724X_RESET_GE0_MDIO;
507 ar71xx_eth1_data.reset_bit |= AR724X_RESET_GE1_MDIO;
508 /* fall through */
509 case AR71XX_SOC_AR7240:
510 pdata->ddr_flush = id ? ar724x_ddr_flush_ge1
511 : ar724x_ddr_flush_ge0;
512 pdata->set_pll = id ? ar724x_set_pll_ge1
513 : ar724x_set_pll_ge0;
514 pdata->is_ar724x = 1;
515
516 if (!pdata->fifo_cfg1)
517 pdata->fifo_cfg1 = 0x0010ffff;
518 if (!pdata->fifo_cfg2)
519 pdata->fifo_cfg2 = 0x015500aa;
520 if (!pdata->fifo_cfg3)
521 pdata->fifo_cfg3 = 0x01f00140;
522 break;
523
524 case AR71XX_SOC_AR9130:
525 pdata->ddr_flush = id ? ar91xx_ddr_flush_ge1
526 : ar91xx_ddr_flush_ge0;
527 pdata->set_pll = id ? ar91xx_set_pll_ge1
528 : ar91xx_set_pll_ge0;
529 pdata->is_ar91xx = 1;
530 break;
531
532 case AR71XX_SOC_AR9132:
533 pdata->ddr_flush = id ? ar91xx_ddr_flush_ge1
534 : ar91xx_ddr_flush_ge0;
535 pdata->set_pll = id ? ar91xx_set_pll_ge1
536 : ar91xx_set_pll_ge0;
537 pdata->is_ar91xx = 1;
538 pdata->has_gbit = 1;
539 break;
540
541 default:
542 BUG();
543 }
544
545 switch (pdata->phy_if_mode) {
546 case PHY_INTERFACE_MODE_GMII:
547 case PHY_INTERFACE_MODE_RGMII:
548 if (!pdata->has_gbit) {
549 printk(KERN_ERR "ar71xx: no gbit available on eth%d\n",
550 id);
551 return;
552 }
553 /* fallthrough */
554 default:
555 break;
556 }
557
558 if (!is_valid_ether_addr(pdata->mac_addr)) {
559 random_ether_addr(pdata->mac_addr);
560 printk(KERN_DEBUG
561 "ar71xx: using random MAC address for eth%d\n",
562 ar71xx_eth_instance);
563 }
564
565 if (pdata->mii_bus_dev == NULL)
566 pdata->mii_bus_dev = &ar71xx_mdio_device.dev;
567
568 /* Reset the device */
569 ar71xx_device_stop(pdata->reset_bit);
570 mdelay(100);
571
572 ar71xx_device_start(pdata->reset_bit);
573 mdelay(100);
574
575 platform_device_register(pdev);
576 ar71xx_eth_instance++;
577 }
578
579 static struct resource ar71xx_spi_resources[] = {
580 [0] = {
581 .start = AR71XX_SPI_BASE,
582 .end = AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1,
583 .flags = IORESOURCE_MEM,
584 },
585 };
586
587 static struct platform_device ar71xx_spi_device = {
588 .name = "ar71xx-spi",
589 .id = -1,
590 .resource = ar71xx_spi_resources,
591 .num_resources = ARRAY_SIZE(ar71xx_spi_resources),
592 };
593
594 void __init ar71xx_add_device_spi(struct ar71xx_spi_platform_data *pdata,
595 struct spi_board_info const *info,
596 unsigned n)
597 {
598 spi_register_board_info(info, n);
599 ar71xx_spi_device.dev.platform_data = pdata;
600 platform_device_register(&ar71xx_spi_device);
601 }
602
603 void __init ar71xx_add_device_wdt(void)
604 {
605 platform_device_register_simple("ar71xx-wdt", -1, NULL, 0);
606 }
607
608 void __init ar71xx_set_mac_base(unsigned char *mac)
609 {
610 memcpy(ar71xx_mac_base, mac, ETH_ALEN);
611 }
612
613 void __init ar71xx_parse_mac_addr(char *mac_str)
614 {
615 u8 tmp[ETH_ALEN];
616 int t;
617
618 t = sscanf(mac_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
619 &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
620
621 if (t != ETH_ALEN)
622 t = sscanf(mac_str, "%02hhx.%02hhx.%02hhx.%02hhx.%02hhx.%02hhx",
623 &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
624
625 if (t == ETH_ALEN)
626 ar71xx_set_mac_base(tmp);
627 else
628 printk(KERN_DEBUG "ar71xx: failed to parse mac address "
629 "\"%s\"\n", mac_str);
630 }
631
632 static int __init ar71xx_ethaddr_setup(char *str)
633 {
634 ar71xx_parse_mac_addr(str);
635 return 1;
636 }
637 __setup("ethaddr=", ar71xx_ethaddr_setup);
638
639 static int __init ar71xx_kmac_setup(char *str)
640 {
641 ar71xx_parse_mac_addr(str);
642 return 1;
643 }
644 __setup("kmac=", ar71xx_kmac_setup);
645
646 void __init ar71xx_init_mac(unsigned char *dst, const unsigned char *src,
647 unsigned offset)
648 {
649 u32 t;
650
651 if (!is_valid_ether_addr(src)) {
652 memset(dst, '\0', ETH_ALEN);
653 return;
654 }
655
656 t = (((u32) src[3]) << 16) + (((u32) src[4]) << 8) + ((u32) src[5]);
657 t += offset;
658
659 dst[0] = src[0];
660 dst[1] = src[1];
661 dst[2] = src[2];
662 dst[3] = (t >> 16) & 0xff;
663 dst[4] = (t >> 8) & 0xff;
664 dst[5] = t & 0xff;
665 }