summaryrefslogtreecommitdiffstats
path: root/qemu/roms/u-boot/board/renesas/sh7785lcr/README.sh7785lcr
blob: 56455fc16257fdfb853ba0d01a1b40ebe6642d85 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
========================================
Renesas Technology R0P7785LC0011RL board
========================================

This board specification:
=========================

The R0P7785LC0011RL(board config name:sh7785lcr) has the following device:

 - SH7785 (SH-4A)
 - DDR2-SDRAM 512MB
 - NOR Flash 64MB
 - 2D Graphic controller
 - SATA controller
 - Ethernet controller
 - USB host/peripheral controller
 - SD controller
 - I2C controller
 - RTC

This board has 2 physical memory maps. It can be changed with DIP switch(S2-5).

 phys address			| S2-5 = OFF	| S2-5 = ON
 -------------------------------+---------------+---------------
 0x00000000 - 0x03ffffff(CS0)	| NOR Flash	| NOR Flash
 0x04000000 - 0x05ffffff(CS1)	| PLD		| PLD
 0x06000000 - 0x07ffffff(CS1)	| reserved	| I2C
 0x08000000 - 0x0bffffff(CS2)	| USB		| DDR SDRAM
 0x0c000000 - 0x0fffffff(CS3)	| SD		| DDR SDRAM
 0x10000000 - 0x13ffffff(CS4)	| SM107		| SM107
 0x14000000 - 0x17ffffff(CS5)	| I2C		| USB
 0x18000000 - 0x1bffffff(CS6)	| reserved	| SD
 0x40000000 - 0x5fffffff	| DDR SDRAM	| (cannot use)


configuration for This board:
=============================

You can choose configuration as follows:

 - make sh7785lcr_config
 - make sh7785lcr_32bit_config

When you use "make sh7785lcr_config", there is build U-Boot for 29-bit
address mode. This mode can use 128MB DDR-SDRAM.

When you use "make sh7785lcr_32bit_config", there is build U-Boot for 32-bit
extended address mode. This mode can use 384MB DDR-SDRAM. And if you run
"pmb" command, this mode can use 512MB DDR-SDRAM.

 * 32-bit extended address mode PMB mapping *
  a) on start-up
   virt		| phys		| size		| device
   -------------+---------------+---------------+---------------
   0x88000000	| 0x48000000	| 384MB		| DDR-SDRAM (Cacheable)
   0xa0000000	| 0x00000000	| 64MB		| NOR Flash
   0xa4000000	| 0x04000000	| 16MB		| PLD
   0xa6000000	| 0x08000000	| 16MB		| USB
   0xa8000000	| 0x48000000	| 384MB		| DDR-SDRAM (Non-cacheable)

  b) after "pmb" command
   virt		| phys		| size		| device
   -------------+---------------+---------------+---------------
   0x80000000	| 0x40000000	| 512MB		| DDR-SDRAM (Cacheable)
   0xa0000000	| 0x40000000	| 512MB		| DDR-SDRAM (Non-cacheable)


This board specific command:
============================

This board has the following its specific command:

 - hwtest
 - printmac
 - setmac
 - pmb (sh7785lcr_32bit_config only)


1. hwtest

This is self-check command. This command has the following options:

 - all		: test all hardware
 - pld		: output PLD version
 - led		: turn on LEDs
 - dipsw	: test DIP switch
 - sm107	: output SM107 version
 - net		: check RTL8110 ID
 - sata		: check SiI3512 ID
 - net		: output PCI slot device ID

i.e)
=> hwtest led
turn on LEDs 3, 5, 7, 9
turn on LEDs 4, 6, 8, 10

=> hwtest net
Ethernet OK


2. printmac

This command outputs MAC address of this board.

i.e)
=> printmac
MAC = 00:00:87:**:**:**


3. setmac

This command writes MAC address of this board.

i.e)
=> setmac 00:00:87:**:**:**


4. pmb

This command change PMB for DDR-SDRAM all mapping. However you cannot use
NOR Flash and USB Host on U-Boot when you run this command.
i.e)
=> pmb
id='n403' href='#n403'>403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001
/*
 * (C) Copyright 2001
 * John Clemens <clemens@mclx.com>, Mission Critical Linux, Inc.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

/*************************************************************************
 * changes for Marvell DB64460 eval board 2003 by Ingo Assmus <ingo.assmus@keymile.com>
 *
  ************************************************************************/

/*
 * mpsc.c - driver for console over the MPSC.
 */


#include <common.h>
#include <config.h>
#include <asm/cache.h>

#include <malloc.h>
#include "mpsc.h"

#include "mv_regs.h"

#include "../include/memory.h"

DECLARE_GLOBAL_DATA_PTR;

/* Define this if you wish to use the MPSC as a register based UART.
 * This will force the serial port to not use the SDMA engine at all.
 */
#undef CONFIG_MPSC_DEBUG_PORT


int (*mpsc_putchar) (char ch) = mpsc_putchar_early;
char (*mpsc_getchar) (void) = mpsc_getchar_debug;
int (*mpsc_test_char) (void) = mpsc_test_char_debug;


static volatile unsigned int *rx_desc_base = NULL;
static unsigned int rx_desc_index = 0;
static volatile unsigned int *tx_desc_base = NULL;
static unsigned int tx_desc_index = 0;

/* local function declarations */
static int galmpsc_connect (int channel, int connect);
static int galmpsc_route_rx_clock (int channel, int brg);
static int galmpsc_route_tx_clock (int channel, int brg);
static int galmpsc_write_config_regs (int mpsc, int mode);
static int galmpsc_config_channel_regs (int mpsc);
static int galmpsc_set_char_length (int mpsc, int value);
static int galmpsc_set_stop_bit_length (int mpsc, int value);
static int galmpsc_set_parity (int mpsc, int value);
static int galmpsc_enter_hunt (int mpsc);
static int galmpsc_set_brkcnt (int mpsc, int value);
static int galmpsc_set_tcschar (int mpsc, int value);
static int galmpsc_set_snoop (int mpsc, int value);
static int galmpsc_shutdown (int mpsc);

static int galsdma_set_RFT (int channel);
static int galsdma_set_SFM (int channel);
static int galsdma_set_rxle (int channel);
static int galsdma_set_txle (int channel);
static int galsdma_set_burstsize (int channel, unsigned int value);
static int galsdma_set_RC (int channel, unsigned int value);

static int galbrg_set_CDV (int channel, int value);
static int galbrg_enable (int channel);
static int galbrg_disable (int channel);
static int galbrg_set_clksrc (int channel, int value);
static int galbrg_set_CUV (int channel, int value);

static void galsdma_enable_rx (void);
static int galsdma_set_mem_space (unsigned int memSpace,
				  unsigned int memSpaceTarget,
				  unsigned int memSpaceAttr,
				  unsigned int baseAddress,
				  unsigned int size);


#define SOFTWARE_CACHE_MANAGEMENT

#ifdef SOFTWARE_CACHE_MANAGEMENT
#define FLUSH_DCACHE(a,b)		 if(dcache_status()){clean_dcache_range((u32)(a),(u32)(b));}
#define FLUSH_AND_INVALIDATE_DCACHE(a,b) if(dcache_status()){flush_dcache_range((u32)(a),(u32)(b));}
#define INVALIDATE_DCACHE(a,b)		 if(dcache_status()){invalidate_dcache_range((u32)(a),(u32)(b));}
#else
#define FLUSH_DCACHE(a,b)
#define FLUSH_AND_INVALIDATE_DCACHE(a,b)
#define INVALIDATE_DCACHE(a,b)
#endif

#ifdef CONFIG_MPSC_DEBUG_PORT
static void mpsc_debug_init (void)
{

	volatile unsigned int temp;

	/* Clear the CFR  (CHR4) */
	/* Write random 'Z' bit (bit 29) of CHR4 to enable debug uart *UNDOCUMENTED FEATURE* */
	temp = GTREGREAD (GALMPSC_CHANNELREG_4 + (CHANNEL * GALMPSC_REG_GAP));
	temp &= 0xffffff00;
	temp |= BIT29;
	GT_REG_WRITE (GALMPSC_CHANNELREG_4 + (CHANNEL * GALMPSC_REG_GAP),
		      temp);

	/* Set the Valid bit 'V' (bit 12) and int generation bit 'INT' (bit 15) */
	temp = GTREGREAD (GALMPSC_CHANNELREG_5 + (CHANNEL * GALMPSC_REG_GAP));
	temp |= (BIT12 | BIT15);
	GT_REG_WRITE (GALMPSC_CHANNELREG_5 + (CHANNEL * GALMPSC_REG_GAP),
		      temp);

	/* Set int mask */
	temp = GTREGREAD (GALMPSC_0_INT_MASK);
	temp |= BIT6;
	GT_REG_WRITE (GALMPSC_0_INT_MASK, temp);
}
#endif

char mpsc_getchar_debug (void)
{
	volatile int temp;
	volatile unsigned int cause;

	cause = GTREGREAD (GALMPSC_0_INT_CAUSE);
	while ((cause & BIT6) == 0) {
		cause = GTREGREAD (GALMPSC_0_INT_CAUSE);
	}

	temp = GTREGREAD (GALMPSC_CHANNELREG_10 +
			  (CHANNEL * GALMPSC_REG_GAP));
	/* By writing 1's to the set bits, the register is cleared */
	GT_REG_WRITE (GALMPSC_CHANNELREG_10 + (CHANNEL * GALMPSC_REG_GAP),
		      temp);
	GT_REG_WRITE (GALMPSC_0_INT_CAUSE, cause & ~BIT6);
	return (temp >> 16) & 0xff;
}

/* special function for running out of flash.  doesn't modify any
 * global variables [josh] */
int mpsc_putchar_early (char ch)
{
	int mpsc = CHANNEL;
	int temp =
		GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP));
	galmpsc_set_tcschar (mpsc, ch);
	GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP),
		      temp | 0x200);

#define MAGIC_FACTOR	(10*1000000)

	udelay (MAGIC_FACTOR / gd->baudrate);
	return 0;
}

/* This is used after relocation, see serial.c and mpsc_init2 */
static int mpsc_putchar_sdma (char ch)
{
	volatile unsigned int *p;
	unsigned int temp;


	/* align the descriptor */
	p = tx_desc_base;
	memset ((void *) p, 0, 8 * sizeof (unsigned int));

	/* fill one 64 bit buffer */
	/* word swap, pad with 0 */
	p[4] = 0;		/* x */
	p[5] = (unsigned int) ch;	/* x */

	/* CHANGED completely according to GT64260A dox - NTL */
	p[0] = 0x00010001;	/* 0 */
	p[1] = DESC_OWNER_BIT | DESC_FIRST | DESC_LAST;	/* 4 */
	p[2] = 0;		/* 8 */
	p[3] = (unsigned int) &p[4];	/* c */

#if 0
	p[9] = DESC_FIRST | DESC_LAST;
	p[10] = (unsigned int) &p[0];
	p[11] = (unsigned int) &p[12];
#endif

	FLUSH_DCACHE (&p[0], &p[8]);

	GT_REG_WRITE (GALSDMA_0_CUR_TX_PTR + (CHANNEL * GALSDMA_REG_DIFF),
		      (unsigned int) &p[0]);
	GT_REG_WRITE (GALSDMA_0_FIR_TX_PTR + (CHANNEL * GALSDMA_REG_DIFF),
		      (unsigned int) &p[0]);

	temp = GTREGREAD (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF));
	temp |= (TX_DEMAND | TX_STOP);
	GT_REG_WRITE (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF), temp);

	INVALIDATE_DCACHE (&p[1], &p[2]);

	while (p[1] & DESC_OWNER_BIT) {
		udelay (100);
		INVALIDATE_DCACHE (&p[1], &p[2]);
	}
	return 0;
}

char mpsc_getchar_sdma (void)
{
	static unsigned int done = 0;
	volatile char ch;
	unsigned int len = 0, idx = 0, temp;

	volatile unsigned int *p;


	do {
		p = &rx_desc_base[rx_desc_index * 8];

		INVALIDATE_DCACHE (&p[0], &p[1]);
		/* Wait for character */
		while (p[1] & DESC_OWNER_BIT) {
			udelay (100);
			INVALIDATE_DCACHE (&p[0], &p[1]);
		}

		/* Handle error case */
		if (p[1] & (1 << 15)) {
			printf ("oops, error: %08x\n", p[1]);

			temp = GTREGREAD (GALMPSC_CHANNELREG_2 +
					  (CHANNEL * GALMPSC_REG_GAP));
			temp |= (1 << 23);
			GT_REG_WRITE (GALMPSC_CHANNELREG_2 +
				      (CHANNEL * GALMPSC_REG_GAP), temp);

			/* Can't poll on abort bit, so we just wait. */
			udelay (100);

			galsdma_enable_rx ();
		}

		/* Number of bytes left in this descriptor */
		len = p[0] & 0xffff;

		if (len) {
			/* Where to look */
			idx = 5;
			if (done > 3)
				idx = 4;
			if (done > 7)
				idx = 7;
			if (done > 11)
				idx = 6;

			INVALIDATE_DCACHE (&p[idx], &p[idx + 1]);
			ch = p[idx] & 0xff;
			done++;
		}

		if (done < len) {
			/* this descriptor has more bytes still
			 * shift down the char we just read, and leave the
			 * buffer in place for the next time around
			 */
			p[idx] = p[idx] >> 8;
			FLUSH_DCACHE (&p[idx], &p[idx + 1]);
		}

		if (done == len) {
			/* nothing left in this descriptor.
			 * go to next one
			 */
			p[1] = DESC_OWNER_BIT | DESC_FIRST | DESC_LAST;
			p[0] = 0x00100000;
			FLUSH_DCACHE (&p[0], &p[1]);
			/* Next descriptor */
			rx_desc_index = (rx_desc_index + 1) % RX_DESC;
			done = 0;
		}
	} while (len == 0);	/* galileo bug.. len might be zero */

	return ch;
}


int mpsc_test_char_debug (void)
{
	if ((GTREGREAD (GALMPSC_0_INT_CAUSE) & BIT6) == 0)
		return 0;
	else {
		return 1;
	}
}


int mpsc_test_char_sdma (void)
{
	volatile unsigned int *p = &rx_desc_base[rx_desc_index * 8];

	INVALIDATE_DCACHE (&p[1], &p[2]);

	if (p[1] & DESC_OWNER_BIT)
		return 0;
	else
		return 1;
}

int mpsc_init (int baud)
{
	/* BRG CONFIG */
	galbrg_set_baudrate (CHANNEL, baud);
	galbrg_set_clksrc (CHANNEL, 8);	/* set source=Tclk */
	galbrg_set_CUV (CHANNEL, 0);	/* set up CountUpValue */
	galbrg_enable (CHANNEL);	/* Enable BRG */

	/* Set up clock routing */
	galmpsc_connect (CHANNEL, GALMPSC_CONNECT);	/* connect it */

	galmpsc_route_rx_clock (CHANNEL, CHANNEL);	/* chosse BRG0 for Rx */
	galmpsc_route_tx_clock (CHANNEL, CHANNEL);	/* chose BRG0 for Tx */

	/* reset MPSC state */
	galmpsc_shutdown (CHANNEL);

	/* SDMA CONFIG */
	galsdma_set_burstsize (CHANNEL, L1_CACHE_BYTES / 8);	/* in 64 bit words (8 bytes) */
	galsdma_set_txle (CHANNEL);
	galsdma_set_rxle (CHANNEL);
	galsdma_set_RC (CHANNEL, 0xf);
	galsdma_set_SFM (CHANNEL);
	galsdma_set_RFT (CHANNEL);

	/* MPSC CONFIG */
	galmpsc_write_config_regs (CHANNEL, GALMPSC_UART);
	galmpsc_config_channel_regs (CHANNEL);
	galmpsc_set_char_length (CHANNEL, GALMPSC_CHAR_LENGTH_8);	/* 8 */
	galmpsc_set_parity (CHANNEL, GALMPSC_PARITY_NONE);	/* N */
	galmpsc_set_stop_bit_length (CHANNEL, GALMPSC_STOP_BITS_1);	/* 1 */

#ifdef CONFIG_MPSC_DEBUG_PORT
	mpsc_debug_init ();
#endif

	/* COMM_MPSC CONFIG */
#ifdef SOFTWARE_CACHE_MANAGEMENT
	galmpsc_set_snoop (CHANNEL, 0);	/* disable snoop */
#else
	galmpsc_set_snoop (CHANNEL, 1);	/* enable snoop */
#endif

	return 0;
}


void mpsc_sdma_init (void)
{
/* Setup SDMA channel0 SDMA_CONFIG_REG*/
	GT_REG_WRITE (SDMA_CONFIG_REG (0), 0x000020ff);

/*  Enable MPSC-Window0 for DRAM Bank0   */
	if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_0_BIT,
				   MV64460_SDMA_DRAM_CS_0_TARGET,
				   0,
				   memoryGetBankBaseAddress
				   (CS_0_LOW_DECODE_ADDRESS),
				   memoryGetBankSize (BANK0)) != true)
		printf ("%s: SDMA_Window0 memory setup failed !!! \n",
			__FUNCTION__);


/*  Disable MPSC-Window1    */
	if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_1_BIT,
				   MV64460_SDMA_DRAM_CS_0_TARGET,
				   0,
				   memoryGetBankBaseAddress
				   (CS_1_LOW_DECODE_ADDRESS),
				   memoryGetBankSize (BANK3)) != true)
		printf ("%s: SDMA_Window1 memory setup failed !!! \n",
			__FUNCTION__);


/*  Disable MPSC-Window2 */
	if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_2_BIT,
				   MV64460_SDMA_DRAM_CS_0_TARGET,
				   0,
				   memoryGetBankBaseAddress
				   (CS_2_LOW_DECODE_ADDRESS),
				   memoryGetBankSize (BANK3)) != true)
		printf ("%s: SDMA_Window2 memory setup failed !!! \n",
			__FUNCTION__);


/*  Disable MPSC-Window3 */
	if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_3_BIT,
				   MV64460_SDMA_DRAM_CS_0_TARGET,
				   0,
				   memoryGetBankBaseAddress
				   (CS_3_LOW_DECODE_ADDRESS),
				   memoryGetBankSize (BANK3)) != true)
		printf ("%s: SDMA_Window3 memory setup failed !!! \n",
			__FUNCTION__);

/*  Setup MPSC0 access mode Window0 full access */
	GT_SET_REG_BITS (MPSC0_ACCESS_PROTECTION_REG,
			 (MV64460_SDMA_WIN_ACCESS_FULL <<
			  (MV64460_CUNIT_BASE_ADDR_WIN_0_BIT * 2)));

/*  Setup MPSC1 access mode Window1 full access */
	GT_SET_REG_BITS (MPSC1_ACCESS_PROTECTION_REG,
			 (MV64460_SDMA_WIN_ACCESS_FULL <<
			  (MV64460_CUNIT_BASE_ADDR_WIN_0_BIT * 2)));

/* Setup MPSC internal address space base address	*/
	GT_REG_WRITE (CUNIT_INTERNAL_SPACE_BASE_ADDR_REG, CONFIG_SYS_GT_REGS);

/* no high address remap*/
	GT_REG_WRITE (CUNIT_HIGH_ADDR_REMAP_REG0, 0x00);
	GT_REG_WRITE (CUNIT_HIGH_ADDR_REMAP_REG1, 0x00);

/* clear interrupt cause register for MPSC (fault register)*/
	GT_REG_WRITE (CUNIT_INTERRUPT_CAUSE_REG, 0x00);
}


void mpsc_init2 (void)
{
	int i;

#ifndef CONFIG_MPSC_DEBUG_PORT
	mpsc_putchar = mpsc_putchar_sdma;
	mpsc_getchar = mpsc_getchar_sdma;
	mpsc_test_char = mpsc_test_char_sdma;
#endif
	/* RX descriptors */
	rx_desc_base = (unsigned int *) malloc (((RX_DESC + 1) * 8) *
						sizeof (unsigned int));

	/* align descriptors */
	rx_desc_base = (unsigned int *)
		(((unsigned int) rx_desc_base + 32) & 0xFFFFFFF0);

	rx_desc_index = 0;

	memset ((void *) rx_desc_base, 0,
		(RX_DESC * 8) * sizeof (unsigned int));

	for (i = 0; i < RX_DESC; i++) {
		rx_desc_base[i * 8 + 3] = (unsigned int) &rx_desc_base[i * 8 + 4];	/* Buffer */
		rx_desc_base[i * 8 + 2] = (unsigned int) &rx_desc_base[(i + 1) * 8];	/* Next descriptor */
		rx_desc_base[i * 8 + 1] = DESC_OWNER_BIT | DESC_FIRST | DESC_LAST;	/* Command & control */
		rx_desc_base[i * 8] = 0x00100000;
	}
	rx_desc_base[(i - 1) * 8 + 2] = (unsigned int) &rx_desc_base[0];

	FLUSH_DCACHE (&rx_desc_base[0], &rx_desc_base[RX_DESC * 8]);
	GT_REG_WRITE (GALSDMA_0_CUR_RX_PTR + (CHANNEL * GALSDMA_REG_DIFF),
		      (unsigned int) &rx_desc_base[0]);

	/* TX descriptors */
	tx_desc_base = (unsigned int *) malloc (((TX_DESC + 1) * 8) *
						sizeof (unsigned int));

	/* align descriptors */
	tx_desc_base = (unsigned int *)
		(((unsigned int) tx_desc_base + 32) & 0xFFFFFFF0);

	tx_desc_index = -1;

	memset ((void *) tx_desc_base, 0,
		(TX_DESC * 8) * sizeof (unsigned int));

	for (i = 0; i < TX_DESC; i++) {
		tx_desc_base[i * 8 + 5] = (unsigned int) 0x23232323;
		tx_desc_base[i * 8 + 4] = (unsigned int) 0x23232323;
		tx_desc_base[i * 8 + 3] =
			(unsigned int) &tx_desc_base[i * 8 + 4];
		tx_desc_base[i * 8 + 2] =
			(unsigned int) &tx_desc_base[(i + 1) * 8];
		tx_desc_base[i * 8 + 1] =
			DESC_OWNER_BIT | DESC_FIRST | DESC_LAST;

		/* set sbytecnt and shadow byte cnt to 1 */
		tx_desc_base[i * 8] = 0x00010001;
	}
	tx_desc_base[(i - 1) * 8 + 2] = (unsigned int) &tx_desc_base[0];

	FLUSH_DCACHE (&tx_desc_base[0], &tx_desc_base[TX_DESC * 8]);

	udelay (100);

	galsdma_enable_rx ();

	return;
}

int galbrg_set_baudrate (int channel, int rate)
{
	int clock;

	galbrg_disable (channel);	/*ok */

#ifdef ZUMA_NTL
	/* from tclk */
	clock = (CONFIG_SYS_TCLK / (16 * rate)) - 1;
#else
	clock = (CONFIG_SYS_TCLK / (16 * rate)) - 1;
#endif

	galbrg_set_CDV (channel, clock);	/* set timer Reg. for BRG */

	galbrg_enable (channel);

	gd->baudrate = rate;

	return 0;
}

/* ------------------------------------------------------------------ */

/* Below are all the private functions that no one else needs */

static int galbrg_set_CDV (int channel, int value)
{
	unsigned int temp;

	temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP));
	temp &= 0xFFFF0000;
	temp |= (value & 0x0000FFFF);
	GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp);

	return 0;
}

static int galbrg_enable (int channel)
{
	unsigned int temp;

	temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP));
	temp |= 0x00010000;
	GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp);

	return 0;
}

static int galbrg_disable (int channel)
{
	unsigned int temp;

	temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP));
	temp &= 0xFFFEFFFF;
	GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp);

	return 0;
}

static int galbrg_set_clksrc (int channel, int value)
{
	unsigned int temp;

	temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP));
	temp &= 0xFFC3FFFF;	/* Bit 18 - 21 (MV 64260 18-22) */
	temp |= (value << 18);
	GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp);
	return 0;
}

static int galbrg_set_CUV (int channel, int value)
{
	/* set CountUpValue */
	GT_REG_WRITE (GALBRG_0_BTREG + (channel * GALBRG_REG_GAP), value);

	return 0;
}

#if 0
static int galbrg_reset (int channel)
{
	unsigned int temp;

	temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP));
	temp |= 0x20000;
	GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp);

	return 0;
}
#endif

static int galsdma_set_RFT (int channel)
{
	unsigned int temp;

	temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF));
	temp |= 0x00000001;
	GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF),
		      temp);

	return 0;
}

static int galsdma_set_SFM (int channel)
{
	unsigned int temp;

	temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF));
	temp |= 0x00000002;
	GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF),
		      temp);

	return 0;
}

static int galsdma_set_rxle (int channel)
{
	unsigned int temp;

	temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF));
	temp |= 0x00000040;
	GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF),
		      temp);

	return 0;
}

static int galsdma_set_txle (int channel)
{
	unsigned int temp;

	temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF));
	temp |= 0x00000080;
	GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF),
		      temp);

	return 0;
}

static int galsdma_set_RC (int channel, unsigned int value)
{
	unsigned int temp;

	temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF));
	temp &= ~0x0000003c;
	temp |= (value << 2);
	GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF),
		      temp);

	return 0;
}

static int galsdma_set_burstsize (int channel, unsigned int value)
{
	unsigned int temp;

	temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF));
	temp &= 0xFFFFCFFF;
	switch (value) {
	case 8:
		GT_REG_WRITE (GALSDMA_0_CONF_REG +
			      (channel * GALSDMA_REG_DIFF),
			      (temp | (0x3 << 12)));
		break;

	case 4:
		GT_REG_WRITE (GALSDMA_0_CONF_REG +
			      (channel * GALSDMA_REG_DIFF),
			      (temp | (0x2 << 12)));
		break;

	case 2:
		GT_REG_WRITE (GALSDMA_0_CONF_REG +
			      (channel * GALSDMA_REG_DIFF),
			      (temp | (0x1 << 12)));
		break;

	case 1:
		GT_REG_WRITE (GALSDMA_0_CONF_REG +
			      (channel * GALSDMA_REG_DIFF),
			      (temp | (0x0 << 12)));
		break;

	default:
		return -1;
		break;
	}

	return 0;
}

static int galmpsc_connect (int channel, int connect)
{
	unsigned int temp;

	temp = GTREGREAD (GALMPSC_ROUTING_REGISTER);

	if ((channel == 0) && connect)
		temp &= ~0x00000007;
	else if ((channel == 1) && connect)
		temp &= ~(0x00000007 << 6);
	else if ((channel == 0) && !connect)
		temp |= 0x00000007;
	else
		temp |= (0x00000007 << 6);

	/* Just in case... */
	temp &= 0x3fffffff;

	GT_REG_WRITE (GALMPSC_ROUTING_REGISTER, temp);

	return 0;
}

static int galmpsc_route_rx_clock (int channel, int brg)
{
	unsigned int temp;

	temp = GTREGREAD (GALMPSC_RxC_ROUTE);

	if (channel == 0) {
		temp &= ~0x0000000F;
		temp |= brg;
	} else {
		temp &= ~0x00000F00;
		temp |= (brg << 8);
	}

	GT_REG_WRITE (GALMPSC_RxC_ROUTE, temp);

	return 0;
}

static int galmpsc_route_tx_clock (int channel, int brg)
{
	unsigned int temp;

	temp = GTREGREAD (GALMPSC_TxC_ROUTE);

	if (channel == 0) {
		temp &= ~0x0000000F;
		temp |= brg;
	} else {
		temp &= ~0x00000F00;
		temp |= (brg << 8);
	}

	GT_REG_WRITE (GALMPSC_TxC_ROUTE, temp);

	return 0;
}

static int galmpsc_write_config_regs (int mpsc, int mode)
{
	if (mode == GALMPSC_UART) {
		/* Main config reg Low (Null modem, Enable Tx/Rx, UART mode) */
		GT_REG_WRITE (GALMPSC_MCONF_LOW + (mpsc * GALMPSC_REG_GAP),
			      0x000004c4);

		/* Main config reg High (32x Rx/Tx clock mode, width=8bits */
		GT_REG_WRITE (GALMPSC_MCONF_HIGH + (mpsc * GALMPSC_REG_GAP),
			      0x024003f8);
		/*        22 2222 1111 */
		/*        54 3210 9876 */
		/* 0000 0010 0000 0000 */
		/*       1 */
		/*       098 7654 3210 */
		/* 0000 0011 1111 1000 */
	} else
		return -1;

	return 0;
}

static int galmpsc_config_channel_regs (int mpsc)
{
	GT_REG_WRITE (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP), 0);
	GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), 0);
	GT_REG_WRITE (GALMPSC_CHANNELREG_3 + (mpsc * GALMPSC_REG_GAP), 1);
	GT_REG_WRITE (GALMPSC_CHANNELREG_4 + (mpsc * GALMPSC_REG_GAP), 0);
	GT_REG_WRITE (GALMPSC_CHANNELREG_5 + (mpsc * GALMPSC_REG_GAP), 0);
	GT_REG_WRITE (GALMPSC_CHANNELREG_6 + (mpsc * GALMPSC_REG_GAP), 0);
	GT_REG_WRITE (GALMPSC_CHANNELREG_7 + (mpsc * GALMPSC_REG_GAP), 0);
	GT_REG_WRITE (GALMPSC_CHANNELREG_8 + (mpsc * GALMPSC_REG_GAP), 0);
	GT_REG_WRITE (GALMPSC_CHANNELREG_9 + (mpsc * GALMPSC_REG_GAP), 0);
	GT_REG_WRITE (GALMPSC_CHANNELREG_10 + (mpsc * GALMPSC_REG_GAP), 0);

	galmpsc_set_brkcnt (mpsc, 0x3);
	galmpsc_set_tcschar (mpsc, 0xab);

	return 0;
}

static int galmpsc_set_brkcnt (int mpsc, int value)
{
	unsigned int temp;

	temp = GTREGREAD (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP));
	temp &= 0x0000FFFF;
	temp |= (value << 16);
	GT_REG_WRITE (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP), temp);

	return 0;
}

static int galmpsc_set_tcschar (int mpsc, int value)
{
	unsigned int temp;

	temp = GTREGREAD (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP));
	temp &= 0xFFFF0000;
	temp |= value;
	GT_REG_WRITE (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP), temp);

	return 0;
}

static int galmpsc_set_char_length (int mpsc, int value)
{
	unsigned int temp;

	temp = GTREGREAD (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP));
	temp &= 0xFFFFCFFF;
	temp |= (value << 12);
	GT_REG_WRITE (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP), temp);

	return 0;
}

static int galmpsc_set_stop_bit_length (int mpsc, int value)
{
	unsigned int temp;

	temp = GTREGREAD (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP));
	temp &= 0xFFFFBFFF;
	temp |= (value << 14);
	GT_REG_WRITE (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP), temp);

	return 0;
}

static int galmpsc_set_parity (int mpsc, int value)
{
	unsigned int temp;

	temp = GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP));
	if (value != -1) {
		temp &= 0xFFF3FFF3;
		temp |= ((value << 18) | (value << 2));
		temp |= ((value << 17) | (value << 1));
	} else {
		temp &= 0xFFF1FFF1;
	}

	GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), temp);

	return 0;
}

static int galmpsc_enter_hunt (int mpsc)
{
	int temp;

	temp = GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP));
	temp |= 0x80000000;
	GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), temp);

	while (GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)) &
	       MPSC_ENTER_HUNT) {
		udelay (1);
	}
	return 0;
}


static int galmpsc_shutdown (int mpsc)
{
	unsigned int temp;

	/* cause RX abort (clears RX) */
	temp = GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP));
	temp |= MPSC_RX_ABORT | MPSC_TX_ABORT;
	temp &= ~MPSC_ENTER_HUNT;
	GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), temp);

	GT_REG_WRITE (GALSDMA_0_COM_REG, 0);
	GT_REG_WRITE (GALSDMA_0_COM_REG, SDMA_TX_ABORT | SDMA_RX_ABORT);

	/* shut down the MPSC */
	GT_REG_WRITE (GALMPSC_MCONF_LOW, 0);
	GT_REG_WRITE (GALMPSC_MCONF_HIGH, 0);
	GT_REG_WRITE (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP), 0);

	udelay (100);

	/* shut down the sdma engines. */
	/* reset config to default */
	GT_REG_WRITE (GALSDMA_0_CONF_REG, 0x000000fc);

	udelay (100);

	/* clear the SDMA current and first TX and RX pointers */
	GT_REG_WRITE (GALSDMA_0_CUR_RX_PTR, 0);
	GT_REG_WRITE (GALSDMA_0_CUR_TX_PTR, 0);
	GT_REG_WRITE (GALSDMA_0_FIR_TX_PTR, 0);

	udelay (100);

	return 0;
}

static void galsdma_enable_rx (void)
{
	int temp;

	/* Enable RX processing */
	temp = GTREGREAD (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF));
	temp |= RX_ENABLE;
	GT_REG_WRITE (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF), temp);

	galmpsc_enter_hunt (CHANNEL);
}

static int galmpsc_set_snoop (int mpsc, int value)
{
	int reg =
		mpsc ? MPSC_1_ADDRESS_CONTROL_LOW :
		MPSC_0_ADDRESS_CONTROL_LOW;
	int temp = GTREGREAD (reg);

	if (value)
		temp |= (1 << 6) | (1 << 14) | (1 << 22) | (1 << 30);
	else
		temp &= ~((1 << 6) | (1 << 14) | (1 << 22) | (1 << 30));
	GT_REG_WRITE (reg, temp);
	return 0;
}

/*******************************************************************************
* galsdma_set_mem_space - Set MV64460 IDMA memory decoding map.
*
* DESCRIPTION:
*       the MV64460 SDMA has its own address decoding map that is de-coupled
*       from the CPU interface address decoding windows. The SDMA channels
*       share four address windows. Each region can be individually configured
*       by this function by associating it to a target interface and setting
*       base and size values.
*
*      NOTE!!!
*       The size must be in 64Kbyte granularity.
*       The base address must be aligned to the size.
*       The size must be a series of 1s followed by a series of zeros
*
* OUTPUT:
*       None.
*
* RETURN:
*       true for success, false otherwise.
*
*******************************************************************************/

static int galsdma_set_mem_space (unsigned int memSpace,
				  unsigned int memSpaceTarget,
				  unsigned int memSpaceAttr,
				  unsigned int baseAddress, unsigned int size)
{
	unsigned int temp;

	if (size == 0) {
		GT_RESET_REG_BITS (MV64460_CUNIT_BASE_ADDR_ENABLE_REG,
				   1 << memSpace);
		return true;
	}

	/* The base address must be aligned to the size.  */
	if (baseAddress % size != 0) {
		return false;
	}
	if (size < 0x10000) {
		return false;
	}

	/* Align size and base to 64K */
	baseAddress &= 0xffff0000;
	size &= 0xffff0000;
	temp = size >> 16;

	/* Checking that the size is a sequence of '1' followed by a
	   sequence of '0' starting from LSB to MSB. */
	while ((temp > 0) && (temp & 0x1)) {
		temp = temp >> 1;
	}

	if (temp != 0) {
		GT_REG_WRITE (MV64460_CUNIT_BASE_ADDR_REG0 + memSpace * 8,
			      (baseAddress | memSpaceTarget | memSpaceAttr));
		GT_REG_WRITE ((MV64460_CUNIT_SIZE0 + memSpace * 8),
			      (size - 1) & 0xffff0000);
		GT_RESET_REG_BITS (MV64460_CUNIT_BASE_ADDR_ENABLE_REG,
				   1 << memSpace);
	} else {
		/* An invalid size was specified */
		return false;
	}
	return true;
}