Home | History | Annotate | Line # | Download | only in boot2440
main.c revision 1.2.2.2
      1  1.2.2.2  yamt /*-
      2  1.2.2.2  yamt  * Copyright (c) 2012 The NetBSD Foundation, Inc.
      3  1.2.2.2  yamt  * All rights reserved.
      4  1.2.2.2  yamt  *
      5  1.2.2.2  yamt  * This code is derived from software contributed to The NetBSD Foundation
      6  1.2.2.2  yamt  * by Paul Fleischer <paul (at) xpg.dk>
      7  1.2.2.2  yamt  *
      8  1.2.2.2  yamt  * Redistribution and use in source and binary forms, with or without
      9  1.2.2.2  yamt  * modification, are permitted provided that the following conditions
     10  1.2.2.2  yamt  * are met:
     11  1.2.2.2  yamt  * 1. Redistributions of source code must retain the above copyright
     12  1.2.2.2  yamt  *    notice, this list of conditions and the following disclaimer.
     13  1.2.2.2  yamt  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.2.2.2  yamt  *    notice, this list of conditions and the following disclaimer in the
     15  1.2.2.2  yamt  *    documentation and/or other materials provided with the distribution.
     16  1.2.2.2  yamt  *
     17  1.2.2.2  yamt  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     18  1.2.2.2  yamt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     19  1.2.2.2  yamt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     20  1.2.2.2  yamt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     21  1.2.2.2  yamt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22  1.2.2.2  yamt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23  1.2.2.2  yamt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24  1.2.2.2  yamt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     25  1.2.2.2  yamt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     26  1.2.2.2  yamt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27  1.2.2.2  yamt  * POSSIBILITY OF SUCH DAMAGE.
     28  1.2.2.2  yamt  */
     29  1.2.2.2  yamt #include <sys/types.h>
     30  1.2.2.2  yamt 
     31  1.2.2.2  yamt #include <arm/armreg.h>
     32  1.2.2.2  yamt #include <arm/s3c2xx0/s3c2440reg.h>
     33  1.2.2.2  yamt 
     34  1.2.2.2  yamt #include <netinet/in.h>
     35  1.2.2.2  yamt #include <netinet/in_systm.h>
     36  1.2.2.2  yamt 
     37  1.2.2.2  yamt #include <lib/libkern/libkern.h>
     38  1.2.2.2  yamt #include <lib/libsa/stand.h>
     39  1.2.2.2  yamt #include <lib/libsa/loadfile.h>
     40  1.2.2.2  yamt #include <lib/libsa/iodesc.h>
     41  1.2.2.2  yamt 
     42  1.2.2.2  yamt #include <arch/evbarm/mini2440/mini2440_bootinfo.h>
     43  1.2.2.2  yamt 
     44  1.2.2.2  yamt #define CSR_READ(reg) \
     45  1.2.2.2  yamt 	*(volatile uint32_t *)(reg)
     46  1.2.2.2  yamt #define CSR_WRITE(reg, val) do { \
     47  1.2.2.2  yamt 	    *(volatile uint32_t *)((reg)) = val; \
     48  1.2.2.2  yamt 	} while (0)
     49  1.2.2.2  yamt 
     50  1.2.2.2  yamt #define UART_BAUDRATE		115200
     51  1.2.2.2  yamt #define S3C2XX0_XTAL_CLK	12000000
     52  1.2.2.2  yamt #define BOOTINFO_ADDR		0x31500000
     53  1.2.2.2  yamt 
     54  1.2.2.2  yamt /* Macros to turn on/off LEDs. Numbering is 1-4. */
     55  1.2.2.2  yamt #define LED_REG (volatile uint16_t*)(S3C2440_GPIO_BASE+GPIO_PBDAT)
     56  1.2.2.2  yamt #define CLEAR_LEDS() *LED_REG = *LED_REG | 0x1e0
     57  1.2.2.2  yamt #define LED_ON(led) *LED_REG = *LED_REG & ( ~(1<<(led+4)) & 0x1E0 )
     58  1.2.2.2  yamt #define LED_OFF(led) *LED_REG = *LED_REG | ( ~(1<<(led+4)) & 0x1E0 )
     59  1.2.2.2  yamt 
     60  1.2.2.2  yamt /* Local variables */
     61  1.2.2.2  yamt static time_t	wallclock = 0;
     62  1.2.2.2  yamt static uint32_t timer_inc_rate;
     63  1.2.2.2  yamt void *bootinfo;
     64  1.2.2.2  yamt int bi_size;
     65  1.2.2.2  yamt char *bi_next;
     66  1.2.2.2  yamt 
     67  1.2.2.2  yamt #define STR_EXPAND(tok) #tok
     68  1.2.2.2  yamt #define STR(tok) STR_EXPAND(tok)
     69  1.2.2.2  yamt 
     70  1.2.2.2  yamt #if defined(DEFAULT_BOOTFILE)
     71  1.2.2.2  yamt static char *default_boot=STR(DEFAULT_BOOTFILE);
     72  1.2.2.2  yamt #else
     73  1.2.2.2  yamt static char *default_boot="net:";
     74  1.2.2.2  yamt #endif
     75  1.2.2.2  yamt 
     76  1.2.2.2  yamt time_t getsecs();
     77  1.2.2.2  yamt time_t getusecs();
     78  1.2.2.2  yamt 
     79  1.2.2.2  yamt /* Local functions */
     80  1.2.2.2  yamt static void s3c24x0_clock_freq2(vaddr_t clkman_base, int *fclk, int *hclk,
     81  1.2.2.2  yamt 				int *pclk);
     82  1.2.2.2  yamt static void uart_init(uint32_t pclk);
     83  1.2.2.2  yamt static void time_init(uint32_t pclk);
     84  1.2.2.2  yamt static void bi_init(void *addr);
     85  1.2.2.2  yamt static void bi_add(void *new, int type, int size);
     86  1.2.2.2  yamt static void parse_mac_address(const char *str, uint8_t *enaddr);
     87  1.2.2.2  yamt static void brdsetup(void);
     88  1.2.2.2  yamt static void iomux(int, const char *);
     89  1.2.2.2  yamt 
     90  1.2.2.2  yamt extern void* dm9k_init(unsigned int tag, void *macaddr);
     91  1.2.2.2  yamt 
     92  1.2.2.2  yamt /* External variables */
     93  1.2.2.2  yamt extern char bootprog_name[], bootprog_rev[];
     94  1.2.2.2  yamt 
     95  1.2.2.2  yamt /* External functions */
     96  1.2.2.2  yamt extern void netif_match(unsigned int tag, uint8_t *macaddr);
     97  1.2.2.2  yamt /*  extern int sdif_init(unsigned int tag);*/
     98  1.2.2.2  yamt 
     99  1.2.2.2  yamt /* Global variables */
    100  1.2.2.2  yamt uint32_t socmodel;
    101  1.2.2.2  yamt int pclk;
    102  1.2.2.2  yamt struct btinfo_rootdevice	bi_rdev;
    103  1.2.2.2  yamt 
    104  1.2.2.2  yamt /* This is not very flexible, as only one net device is allowed */
    105  1.2.2.2  yamt struct btinfo_net		bi_net;
    106  1.2.2.2  yamt 
    107  1.2.2.2  yamt struct btinfo_bootpath		bi_path;
    108  1.2.2.2  yamt 
    109  1.2.2.2  yamt void
    110  1.2.2.2  yamt main(int argc, char *argv[])
    111  1.2.2.2  yamt {
    112  1.2.2.2  yamt 	int fclk, hclk;
    113  1.2.2.2  yamt 	int fd;
    114  1.2.2.2  yamt 	unsigned long marks[MARK_MAX];
    115  1.2.2.2  yamt 	unsigned char hdr[0x26];
    116  1.2.2.2  yamt 	void (*entry)(void*);
    117  1.2.2.2  yamt 	unsigned elfpriv;
    118  1.2.2.2  yamt 	char *bootfile;
    119  1.2.2.2  yamt 	char *bf;
    120  1.2.2.2  yamt 	bool kernel_loaded;
    121  1.2.2.2  yamt 	uint8_t enaddr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    122  1.2.2.2  yamt 
    123  1.2.2.2  yamt 	socmodel = CSR_READ(S3C2440_GPIO_BASE + GPIO_GSTATUS1);
    124  1.2.2.2  yamt 
    125  1.2.2.2  yamt 	brdsetup();
    126  1.2.2.2  yamt 
    127  1.2.2.2  yamt 	/* Give some indication that main() has been reached */
    128  1.2.2.2  yamt 	CLEAR_LEDS();
    129  1.2.2.2  yamt 	LED_ON(4);
    130  1.2.2.2  yamt 
    131  1.2.2.2  yamt 	/* Next, we setup the clock of the S3C2440 such that we are not
    132  1.2.2.2  yamt 	   dependent on any other bootloader in this regard.
    133  1.2.2.2  yamt 	   Target FCLK is 405MHz, and we assume an input crystal of 12MHz
    134  1.2.2.2  yamt 	*/
    135  1.2.2.2  yamt 	*(volatile uint32_t*)(S3C2440_CLKMAN_BASE+CLKMAN_MPLLCON) =
    136  1.2.2.2  yamt 		((0x7F << PLLCON_MDIV_SHIFT) & PLLCON_MDIV_MASK) |
    137  1.2.2.2  yamt 		((2 << PLLCON_PDIV_SHIFT) & PLLCON_PDIV_MASK) |
    138  1.2.2.2  yamt 		((1 << PLLCON_SDIV_SHIFT) & PLLCON_SDIV_MASK);
    139  1.2.2.2  yamt 	*(volatile uint32_t*)(S3C2440_CLKMAN_BASE+CLKMAN_UPLLCON) =
    140  1.2.2.2  yamt 		((0x38 << PLLCON_MDIV_SHIFT) & PLLCON_MDIV_MASK) |
    141  1.2.2.2  yamt 		((2 << PLLCON_PDIV_SHIFT) & PLLCON_PDIV_MASK) |
    142  1.2.2.2  yamt 		((2 << PLLCON_SDIV_SHIFT) & PLLCON_SDIV_MASK);
    143  1.2.2.2  yamt 
    144  1.2.2.2  yamt 	LED_ON(1);
    145  1.2.2.2  yamt 
    146  1.2.2.2  yamt 	s3c24x0_clock_freq2(S3C2440_CLKMAN_BASE, &fclk, &hclk, &pclk);
    147  1.2.2.2  yamt 
    148  1.2.2.2  yamt 	uart_init(pclk);
    149  1.2.2.2  yamt 	time_init(pclk);
    150  1.2.2.2  yamt 
    151  1.2.2.2  yamt 	/* Let the user know we are alive */
    152  1.2.2.2  yamt 	printf("\n");
    153  1.2.2.2  yamt 	printf(">> %s boot2440, revision %s\n", bootprog_name, bootprog_rev);
    154  1.2.2.2  yamt 	printf("SoC model:");
    155  1.2.2.2  yamt 	switch (socmodel) {
    156  1.2.2.2  yamt 	case 0x32440000:
    157  1.2.2.2  yamt 		printf(" S3C2440"); break;
    158  1.2.2.2  yamt 	case 0x32440001:
    159  1.2.2.2  yamt 		printf(" S3C2440A"); break;
    160  1.2.2.2  yamt 	}
    161  1.2.2.2  yamt 	printf(" (chipid %08x)\n", socmodel);
    162  1.2.2.2  yamt 
    163  1.2.2.2  yamt 	bootinfo = (void*) BOOTINFO_ADDR;
    164  1.2.2.2  yamt 	bi_init(bootinfo);
    165  1.2.2.2  yamt 
    166  1.2.2.2  yamt 	bi_net.devname[0] = 0;
    167  1.2.2.2  yamt 	bi_path.bootpath[0] = 0;
    168  1.2.2.2  yamt 
    169  1.2.2.2  yamt 	/* Try to get boot arguments from any previous boot-loader */
    170  1.2.2.2  yamt 	{
    171  1.2.2.2  yamt 		struct btinfo_bootstring ba;
    172  1.2.2.2  yamt 		int j, i;
    173  1.2.2.2  yamt 
    174  1.2.2.2  yamt 		j = 0;
    175  1.2.2.2  yamt 		for (i = 0; i < argc; i++) {
    176  1.2.2.2  yamt 			if (j == MAX_BOOT_STRING-1) {
    177  1.2.2.2  yamt 				ba.bootstring[j] = '\0';
    178  1.2.2.2  yamt 				continue;
    179  1.2.2.2  yamt 			}
    180  1.2.2.2  yamt 			if (strncmp(argv[i], "mac=", 4) == 0) {
    181  1.2.2.2  yamt 				parse_mac_address(argv[i]+4, enaddr);
    182  1.2.2.2  yamt 			} else {
    183  1.2.2.2  yamt 				if (j != 0)
    184  1.2.2.2  yamt 					ba.bootstring[j++] = ' ';
    185  1.2.2.2  yamt 
    186  1.2.2.2  yamt 				strncpy(ba.bootstring+j, argv[i], MAX_BOOT_STRING-j);
    187  1.2.2.2  yamt 				j += strlen(argv[i]);
    188  1.2.2.2  yamt 			}
    189  1.2.2.2  yamt 		}
    190  1.2.2.2  yamt 		bi_add(&ba, BTINFO_BOOTSTRING, sizeof(ba));
    191  1.2.2.2  yamt 	}
    192  1.2.2.2  yamt 
    193  1.2.2.2  yamt 	LED_ON(3);
    194  1.2.2.2  yamt 
    195  1.2.2.2  yamt 	if (argc > 1) {
    196  1.2.2.2  yamt 		bf = argv[argc-1];
    197  1.2.2.2  yamt 	} else {
    198  1.2.2.2  yamt 		bf = default_boot;
    199  1.2.2.2  yamt 	}
    200  1.2.2.2  yamt 
    201  1.2.2.2  yamt 	/* Detect networking devices */
    202  1.2.2.2  yamt 	netif_match(0, enaddr);
    203  1.2.2.2  yamt 
    204  1.2.2.2  yamt 	kernel_loaded = FALSE;
    205  1.2.2.2  yamt 	do {
    206  1.2.2.2  yamt 		bootfile = strsep(&bf, ";");
    207  1.2.2.2  yamt 		printf("Trying \"%s\"...\n", bootfile);
    208  1.2.2.2  yamt 		fd = open(bootfile, 0);
    209  1.2.2.2  yamt 		if (fd < 0) {
    210  1.2.2.2  yamt 			printf("Failed: %d\n", errno);
    211  1.2.2.2  yamt 			close(fd);
    212  1.2.2.2  yamt 			continue;
    213  1.2.2.2  yamt 		}
    214  1.2.2.2  yamt 
    215  1.2.2.2  yamt 		if (fdloadfile(fd, marks, LOAD_ALL) == 0) {
    216  1.2.2.2  yamt 			kernel_loaded = TRUE;
    217  1.2.2.2  yamt 			break;
    218  1.2.2.2  yamt 		}
    219  1.2.2.2  yamt 	} while(bf != NULL);
    220  1.2.2.2  yamt 
    221  1.2.2.2  yamt 	if (!kernel_loaded) {
    222  1.2.2.2  yamt 		panic("Failed to load kernel\n");
    223  1.2.2.2  yamt 		_rtt();
    224  1.2.2.2  yamt 	}
    225  1.2.2.2  yamt 
    226  1.2.2.2  yamt #if 1
    227  1.2.2.2  yamt 	/* Set MAC address of the 'dme' net device, if
    228  1.2.2.2  yamt 	 * it isn't set already */
    229  1.2.2.2  yamt 	if (bi_net.devname[0] == 0) {
    230  1.2.2.2  yamt 		uint8_t en[6] = {DM9000MAC};
    231  1.2.2.2  yamt 		snprintf(bi_net.devname, sizeof(bi_net.devname), "dme");
    232  1.2.2.2  yamt 		bi_net.cookie = 0;
    233  1.2.2.2  yamt 
    234  1.2.2.2  yamt 		memcpy(bi_net.mac_address, en, sizeof(bi_net.mac_address));
    235  1.2.2.2  yamt 	}
    236  1.2.2.2  yamt #endif
    237  1.2.2.2  yamt 	/*
    238  1.2.2.2  yamt 	 * ARM ELF header has a distinctive value in "private flags"
    239  1.2.2.2  yamt 	 * field of offset [0x24:25];
    240  1.2.2.2  yamt 	 * - NetBSD 02 06
    241  1.2.2.2  yamt 	 * - Linux  02 00 (2.4) or 02 02 (2.6)
    242  1.2.2.2  yamt 	 */
    243  1.2.2.2  yamt 	lseek(fd, (off_t)0, SEEK_SET);
    244  1.2.2.2  yamt 	read(fd, &hdr, sizeof(hdr));
    245  1.2.2.2  yamt 	elfpriv = *(unsigned short *)&hdr[0x24];
    246  1.2.2.2  yamt 
    247  1.2.2.2  yamt 	entry = (void *)marks[MARK_ENTRY];
    248  1.2.2.2  yamt 	if (elfpriv == 0x0602) {
    249  1.2.2.2  yamt 		struct btinfo_symtab bi_syms;
    250  1.2.2.2  yamt 
    251  1.2.2.2  yamt 		bi_syms.nsym = marks[MARK_NSYM];
    252  1.2.2.2  yamt 		bi_syms.ssym = (void*)marks[MARK_SYM];
    253  1.2.2.2  yamt 		bi_syms.esym = (void*)marks[MARK_END];
    254  1.2.2.2  yamt 		bi_add(&bi_syms, BTINFO_SYMTAB, sizeof(bi_syms));
    255  1.2.2.2  yamt 		if (bi_path.bootpath[0] != 0)
    256  1.2.2.2  yamt 		  bi_add(&bi_path, BTINFO_BOOTPATH, sizeof(bi_path));
    257  1.2.2.2  yamt 		bi_add(&bi_rdev, BTINFO_ROOTDEVICE, sizeof(bi_rdev));
    258  1.2.2.2  yamt 		if (bi_net.devname[0] != 0 )
    259  1.2.2.2  yamt 			bi_add(&bi_net, BTINFO_NET, sizeof(bi_net));
    260  1.2.2.2  yamt 	} else {
    261  1.2.2.2  yamt 		printf("Loaded object is not NetBSD ARM ELF");
    262  1.2.2.2  yamt 		_rtt();
    263  1.2.2.2  yamt 	}
    264  1.2.2.2  yamt 
    265  1.2.2.2  yamt 	printf("entry=%p, nsym=%lu, ssym=%p, esym=%p\n",
    266  1.2.2.2  yamt 	       (void *)marks[MARK_ENTRY],
    267  1.2.2.2  yamt 	       marks[MARK_NSYM],
    268  1.2.2.2  yamt 	       (void *)marks[MARK_SYM],
    269  1.2.2.2  yamt 	       (void *)marks[MARK_END]);
    270  1.2.2.2  yamt 	(*entry)(bootinfo);
    271  1.2.2.2  yamt 
    272  1.2.2.2  yamt 	printf("exec returned, restarting...\n");
    273  1.2.2.2  yamt 	_rtt();
    274  1.2.2.2  yamt }
    275  1.2.2.2  yamt 
    276  1.2.2.2  yamt void
    277  1.2.2.2  yamt uart_init(uint32_t pclk)
    278  1.2.2.2  yamt {
    279  1.2.2.2  yamt 	/* Setup UART0 clocking: Use PCLK */
    280  1.2.2.2  yamt 	*(volatile uint32_t*)(S3C2440_UART_BASE(0)+SSCOM_UBRDIV) =
    281  1.2.2.2  yamt 		(pclk/(UART_BAUDRATE*16)) - 1;
    282  1.2.2.2  yamt 
    283  1.2.2.2  yamt 	*(volatile uint32_t*)(S3C2440_UART_BASE(0)+SSCOM_UCON) =
    284  1.2.2.2  yamt 		UCON_TXMODE_INT | UCON_RXMODE_INT;
    285  1.2.2.2  yamt 
    286  1.2.2.2  yamt 	*(volatile uint32_t*)(S3C2440_UART_BASE(0)+SSCOM_ULCON) =
    287  1.2.2.2  yamt 		ULCON_PARITY_NONE | ULCON_LENGTH_8;
    288  1.2.2.2  yamt 
    289  1.2.2.2  yamt 	*(volatile uint32_t*)(S3C2440_UART_BASE(0)+SSCOM_UFCON) =
    290  1.2.2.2  yamt 		UFCON_TXTRIGGER_0 | UFCON_TXFIFO_RESET | UFCON_FIFO_ENABLE;
    291  1.2.2.2  yamt }
    292  1.2.2.2  yamt 
    293  1.2.2.2  yamt static uint32_t countdown_duration;
    294  1.2.2.2  yamt 
    295  1.2.2.2  yamt static
    296  1.2.2.2  yamt void time_init(uint32_t pclk)
    297  1.2.2.2  yamt {
    298  1.2.2.2  yamt 	/* Configure timer0 to be as slow as possible:
    299  1.2.2.2  yamt 	   Prescaler = 255
    300  1.2.2.2  yamt 	   Divider = 16
    301  1.2.2.2  yamt 	 */
    302  1.2.2.2  yamt 
    303  1.2.2.2  yamt 	/* First, configure the prescaler */
    304  1.2.2.2  yamt 	*(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCFG0) = 0xff;
    305  1.2.2.2  yamt 
    306  1.2.2.2  yamt 	/* Next, the divider */
    307  1.2.2.2  yamt 	*(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCFG1) |=
    308  1.2.2.2  yamt 		(TCFG1_MUX_DIV16 <<TCFG1_MUX_SHIFT(0)) & TCFG1_MUX_MASK(0);
    309  1.2.2.2  yamt 
    310  1.2.2.2  yamt 		*(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) =
    311  1.2.2.2  yamt 			TCON_MANUALUPDATE(0);
    312  1.2.2.2  yamt 		*(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCNTB(0)) =
    313  1.2.2.2  yamt 			0xffff;
    314  1.2.2.2  yamt 		*(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) =
    315  1.2.2.2  yamt 			TCON_START(0);
    316  1.2.2.2  yamt 
    317  1.2.2.2  yamt 
    318  1.2.2.2  yamt 	/* Timer count down duration */
    319  1.2.2.2  yamt 	countdown_duration = 65535/(pclk/256/16);
    320  1.2.2.2  yamt 	timer_inc_rate = pclk/256/16;
    321  1.2.2.2  yamt 	//	printf("Countdown duration is: %ds\n", countdown_duration);
    322  1.2.2.2  yamt #if 0
    323  1.2.2.2  yamt 	{
    324  1.2.2.2  yamt 		/* Timer test */
    325  1.2.2.2  yamt 		time_t time, old_time;
    326  1.2.2.2  yamt 
    327  1.2.2.2  yamt 		while(1) {
    328  1.2.2.2  yamt 			time = old_time = getsecs();
    329  1.2.2.2  yamt 			do {
    330  1.2.2.2  yamt 				time = getsecs();
    331  1.2.2.2  yamt 			} while(time == old_time);
    332  1.2.2.2  yamt 			printf("Count %u\n", (int)time);
    333  1.2.2.2  yamt 		}
    334  1.2.2.2  yamt 	}
    335  1.2.2.2  yamt #endif
    336  1.2.2.2  yamt }
    337  1.2.2.2  yamt 
    338  1.2.2.2  yamt time_t
    339  1.2.2.2  yamt getsecs()
    340  1.2.2.2  yamt {
    341  1.2.2.2  yamt 	time_t secs = getusecs()/1000000;
    342  1.2.2.2  yamt 	return secs;
    343  1.2.2.2  yamt }
    344  1.2.2.2  yamt 
    345  1.2.2.2  yamt time_t
    346  1.2.2.2  yamt getusecs() {
    347  1.2.2.2  yamt 	uint32_t count;
    348  1.2.2.2  yamt 	//do {
    349  1.2.2.2  yamt 		count = *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCNTO(0));
    350  1.2.2.2  yamt //} while( count > 65500);
    351  1.2.2.2  yamt 
    352  1.2.2.2  yamt 	*(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) =
    353  1.2.2.2  yamt 		TCON_MANUALUPDATE(0);
    354  1.2.2.2  yamt 	*(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCNTB(0)) =
    355  1.2.2.2  yamt 		0xffff;
    356  1.2.2.2  yamt 	*(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) =
    357  1.2.2.2  yamt 		TCON_START(0);
    358  1.2.2.2  yamt 
    359  1.2.2.2  yamt 	wallclock += ((65535-count)*1000000) / timer_inc_rate;
    360  1.2.2.2  yamt 
    361  1.2.2.2  yamt 	return wallclock;
    362  1.2.2.2  yamt }
    363  1.2.2.2  yamt 
    364  1.2.2.2  yamt void
    365  1.2.2.2  yamt usleep(int us) {
    366  1.2.2.2  yamt 	uint32_t count;
    367  1.2.2.2  yamt 	uint32_t target_clock = wallclock+us;
    368  1.2.2.2  yamt 
    369  1.2.2.2  yamt 	while( wallclock < target_clock) {
    370  1.2.2.2  yamt 		do {
    371  1.2.2.2  yamt 			count = *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCNTO(0));
    372  1.2.2.2  yamt 		} while( count > 65500);
    373  1.2.2.2  yamt 
    374  1.2.2.2  yamt 		*(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) =
    375  1.2.2.2  yamt 			TCON_MANUALUPDATE(0);
    376  1.2.2.2  yamt 		*(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCNTB(0)) =
    377  1.2.2.2  yamt 			0xffff;
    378  1.2.2.2  yamt 		*(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) =
    379  1.2.2.2  yamt 			TCON_START(0);
    380  1.2.2.2  yamt 
    381  1.2.2.2  yamt 		wallclock += ((65535-count)*1000000) / timer_inc_rate;
    382  1.2.2.2  yamt 	}
    383  1.2.2.2  yamt }
    384  1.2.2.2  yamt 
    385  1.2.2.2  yamt 
    386  1.2.2.2  yamt void
    387  1.2.2.2  yamt mini2440_panic()
    388  1.2.2.2  yamt {
    389  1.2.2.2  yamt 	int i, l;
    390  1.2.2.2  yamt 	int v;
    391  1.2.2.2  yamt 	while(1) {
    392  1.2.2.2  yamt 		CLEAR_LEDS();
    393  1.2.2.2  yamt 		for(l=0; l<0xffffff; l++) {
    394  1.2.2.2  yamt 			v = *((int*)(S3C2440_TIMER_BASE+TIMER_TCNTO(0)));
    395  1.2.2.2  yamt 		}
    396  1.2.2.2  yamt 		for(i=1; i<=4; i++) {
    397  1.2.2.2  yamt 			LED_ON(i);
    398  1.2.2.2  yamt 		}
    399  1.2.2.2  yamt 		for(l=0; l<0xffffff; l++) {
    400  1.2.2.2  yamt 			v = *((int*)(S3C2440_TIMER_BASE+TIMER_TCNTO(0)));
    401  1.2.2.2  yamt 		}
    402  1.2.2.2  yamt 	}
    403  1.2.2.2  yamt }
    404  1.2.2.2  yamt 
    405  1.2.2.2  yamt void
    406  1.2.2.2  yamt s3c24x0_clock_freq2(vaddr_t clkman_base, int *fclk, int *hclk, int *pclk)
    407  1.2.2.2  yamt {
    408  1.2.2.2  yamt 	uint32_t pllcon, divn, camdivn;
    409  1.2.2.2  yamt 	int mdiv, pdiv, sdiv;
    410  1.2.2.2  yamt 	uint32_t f, h, p;
    411  1.2.2.2  yamt 
    412  1.2.2.2  yamt 	pllcon = *(volatile uint32_t *)(clkman_base + CLKMAN_MPLLCON);
    413  1.2.2.2  yamt 	divn = *(volatile uint32_t *)(clkman_base + CLKMAN_CLKDIVN);
    414  1.2.2.2  yamt 	camdivn = *(volatile uint32_t *)(clkman_base + CLKMAN_CAMDIVN);
    415  1.2.2.2  yamt 
    416  1.2.2.2  yamt 	mdiv = (pllcon & PLLCON_MDIV_MASK) >> PLLCON_MDIV_SHIFT;
    417  1.2.2.2  yamt 	pdiv = (pllcon & PLLCON_PDIV_MASK) >> PLLCON_PDIV_SHIFT;
    418  1.2.2.2  yamt 	sdiv = (pllcon & PLLCON_SDIV_MASK) >> PLLCON_SDIV_SHIFT;
    419  1.2.2.2  yamt 
    420  1.2.2.2  yamt 	f = ((mdiv + 8) * S3C2XX0_XTAL_CLK) / ((pdiv + 2) * (1 << sdiv)) * 2;
    421  1.2.2.2  yamt 	h = f;
    422  1.2.2.2  yamt 
    423  1.2.2.2  yamt 	/* HDIVN of CLKDIVN can have 4 distinct values */
    424  1.2.2.2  yamt 	switch( (divn & CLKDIVN_HDIVN_MASK) >> CLKDIVN_HDIVN_SHIFT )
    425  1.2.2.2  yamt 		{
    426  1.2.2.2  yamt 		case 0:
    427  1.2.2.2  yamt 			/* 00b: HCLK = FCLK/1*/
    428  1.2.2.2  yamt 			break;
    429  1.2.2.2  yamt 		case 1:
    430  1.2.2.2  yamt 			/* 01b: HCLK = FCLK/2*/
    431  1.2.2.2  yamt 			h /= 2;
    432  1.2.2.2  yamt 			break;
    433  1.2.2.2  yamt 		case 2:
    434  1.2.2.2  yamt 			/* 10b: HCLK = FCLK/4 when CAMDIVN[9] (HCLK4_HALF) = 0
    435  1.2.2.2  yamt 			 *      HCLK = FCLK/8 when CAMDIVN[9] (HCLK4_HALF) = 1 */
    436  1.2.2.2  yamt 			if( camdivn & CLKCAMDIVN_HCLK4_HALF )
    437  1.2.2.2  yamt 				h /= 8;
    438  1.2.2.2  yamt 			else
    439  1.2.2.2  yamt 				h /= 4;
    440  1.2.2.2  yamt 			break;
    441  1.2.2.2  yamt 		case 3:
    442  1.2.2.2  yamt 			/* 11b: HCLK = FCLK/3 when CAMDIVN[8] (HCLK3_HALF) = 0
    443  1.2.2.2  yamt 			 *      HCLK = FCLK/6 when CAMDIVN[8] (HCLK3_HALF) = 1 */
    444  1.2.2.2  yamt 			if( camdivn & CLKCAMDIVN_HCLK3_HALF )
    445  1.2.2.2  yamt 				h /= 6;
    446  1.2.2.2  yamt 			else
    447  1.2.2.2  yamt 				h /= 3;
    448  1.2.2.2  yamt 			break;
    449  1.2.2.2  yamt 		}
    450  1.2.2.2  yamt 
    451  1.2.2.2  yamt 	p = h;
    452  1.2.2.2  yamt 
    453  1.2.2.2  yamt 	if (divn & CLKDIVN_PDIVN)
    454  1.2.2.2  yamt 		p /= 2;
    455  1.2.2.2  yamt 
    456  1.2.2.2  yamt 	if (fclk) *fclk = f;
    457  1.2.2.2  yamt 	if (hclk) *hclk = h;
    458  1.2.2.2  yamt 	if (pclk) *pclk = p;
    459  1.2.2.2  yamt }
    460  1.2.2.2  yamt 
    461  1.2.2.2  yamt void
    462  1.2.2.2  yamt putchar(int c)
    463  1.2.2.2  yamt {
    464  1.2.2.2  yamt 	uint32_t stat;
    465  1.2.2.2  yamt 
    466  1.2.2.2  yamt 	if (c == '\n')
    467  1.2.2.2  yamt 		putchar('\r');
    468  1.2.2.2  yamt 
    469  1.2.2.2  yamt 	do {
    470  1.2.2.2  yamt 		stat = CSR_READ(S3C2440_UART_BASE(0) + SSCOM_UTRSTAT);
    471  1.2.2.2  yamt 	} while ((stat & UTRSTAT_TXEMPTY) == 0);
    472  1.2.2.2  yamt 
    473  1.2.2.2  yamt 	CSR_WRITE(S3C2440_UART_BASE(0) + SSCOM_UTXH, c);
    474  1.2.2.2  yamt }
    475  1.2.2.2  yamt 
    476  1.2.2.2  yamt void
    477  1.2.2.2  yamt _rtt()
    478  1.2.2.2  yamt {
    479  1.2.2.2  yamt 	int cpsr_save, tmp;
    480  1.2.2.2  yamt 	/* Disable interrupts */
    481  1.2.2.2  yamt 	__asm volatile("mrs %0, cpsr;"
    482  1.2.2.2  yamt 		       "orr %1, %0, %2;"
    483  1.2.2.2  yamt 		       "msr cpsr_c, %1;"
    484  1.2.2.2  yamt 		       : "=r" (cpsr_save), "=r" (tmp)
    485  1.2.2.2  yamt 		       : "I" (I32_bit)
    486  1.2.2.2  yamt 		       );
    487  1.2.2.2  yamt 
    488  1.2.2.2  yamt 	/* Disable MMU */
    489  1.2.2.2  yamt 	__asm volatile("mrc p15, 0, %0, c1, c0, 0;"
    490  1.2.2.2  yamt 		       "bic %0, %0, %1;"
    491  1.2.2.2  yamt 		       "mcr p15, 0, %0, c1, c0, 0;"
    492  1.2.2.2  yamt 		       : "=r" (tmp)
    493  1.2.2.2  yamt 		       : "I" (CPU_CONTROL_MMU_ENABLE)
    494  1.2.2.2  yamt 		       );
    495  1.2.2.2  yamt 
    496  1.2.2.2  yamt 	/* Configure watchdog to fire now */
    497  1.2.2.2  yamt 	*(volatile uint32_t *)(S3C2440_WDT_BASE + WDT_WTCON) =
    498  1.2.2.2  yamt 		(0 << WTCON_PRESCALE_SHIFT) | WTCON_ENABLE |
    499  1.2.2.2  yamt 		WTCON_CLKSEL_16 | WTCON_ENRST;
    500  1.2.2.2  yamt }
    501  1.2.2.2  yamt 
    502  1.2.2.2  yamt void
    503  1.2.2.2  yamt bi_init(void *addr)
    504  1.2.2.2  yamt {
    505  1.2.2.2  yamt 	struct btinfo_magic bi_magic;
    506  1.2.2.2  yamt 
    507  1.2.2.2  yamt 	memset(addr, 0, BOOTINFO_MAXSIZE);
    508  1.2.2.2  yamt 	bi_next = (char*) addr;
    509  1.2.2.2  yamt 	bi_size = 0;
    510  1.2.2.2  yamt 
    511  1.2.2.2  yamt 	bi_magic.magic = BOOTINFO_MAGIC;
    512  1.2.2.2  yamt 	bi_add(&bi_magic, BTINFO_MAGIC, sizeof(bi_magic));
    513  1.2.2.2  yamt }
    514  1.2.2.2  yamt 
    515  1.2.2.2  yamt 
    516  1.2.2.2  yamt void
    517  1.2.2.2  yamt bi_add(void *new, int type, int size)
    518  1.2.2.2  yamt {
    519  1.2.2.2  yamt 	struct btinfo_common *bi;
    520  1.2.2.2  yamt 
    521  1.2.2.2  yamt 	if (bi_size + size > BOOTINFO_MAXSIZE)
    522  1.2.2.2  yamt 		return;
    523  1.2.2.2  yamt 
    524  1.2.2.2  yamt 	bi = new;
    525  1.2.2.2  yamt 	bi->next = size;
    526  1.2.2.2  yamt 	bi->type = type;
    527  1.2.2.2  yamt 	memcpy(bi_next, new, size);
    528  1.2.2.2  yamt 	bi_next += size;
    529  1.2.2.2  yamt }
    530  1.2.2.2  yamt 
    531  1.2.2.2  yamt static void
    532  1.2.2.2  yamt parse_mac_address(const char *str, uint8_t *enaddr)
    533  1.2.2.2  yamt {
    534  1.2.2.2  yamt 	int i;
    535  1.2.2.2  yamt 	char *next = (char*)str;
    536  1.2.2.2  yamt 
    537  1.2.2.2  yamt 	for(i=0;i<6;i++) {
    538  1.2.2.2  yamt 		str = next;
    539  1.2.2.2  yamt 		enaddr[i] = (unsigned char)strtoll(str, &next, 16);
    540  1.2.2.2  yamt 		if( *next == ':' ) {
    541  1.2.2.2  yamt 			next++;
    542  1.2.2.2  yamt 		} else {
    543  1.2.2.2  yamt 			break;
    544  1.2.2.2  yamt 		}
    545  1.2.2.2  yamt 	}
    546  1.2.2.2  yamt }
    547  1.2.2.2  yamt 
    548  1.2.2.2  yamt static void
    549  1.2.2.2  yamt brdsetup(void)
    550  1.2.2.2  yamt {
    551  1.2.2.2  yamt /*
    552  1.2.2.2  yamt  * MINI2440 pin usage summary
    553  1.2.2.2  yamt  *
    554  1.2.2.2  yamt  *  B5	output	LED1 control
    555  1.2.2.2  yamt  *  B6	output	LED2 control
    556  1.2.2.2  yamt  *  B7	output	LED3 control
    557  1.2.2.2  yamt  *  B8	output	LED4 control
    558  1.2.2.2  yamt  *  G0	EINT8	K1 button
    559  1.2.2.2  yamt  *  G3	EINT11	K2 button
    560  1.2.2.2  yamt  *  G5	EINT13	K3 button
    561  1.2.2.2  yamt  *  G6	EINT14	K4 button
    562  1.2.2.2  yamt  *  G7	EINT15	K5 button
    563  1.2.2.2  yamt  *  G11	EINT19	K6 button
    564  1.2.2.2  yamt  *  F7	EINT7	DM9000 interrupt
    565  1.2.2.2  yamt  *  G12	EINT20	camera interrupt
    566  1.2.2.2  yamt  *  G8	input	SD card presense detect
    567  1.2.2.2  yamt  *  H8	input	SD write protect sense
    568  1.2.2.2  yamt  *  B0	TOUT0	buzzer PWM
    569  1.2.2.2  yamt  *  B1	TOUT1	LCD backlight PWM
    570  1.2.2.2  yamt  *  B2	output	UDA1341 audio L3MODE
    571  1.2.2.2  yamt  *  B3	output	UDA1341 audio L3DATA
    572  1.2.2.2  yamt  *  B4	output	UDA1341 audio L3LOCK
    573  1.2.2.2  yamt  *
    574  1.2.2.2  yamt  *  A21, A11, G15, G14, G13: not used.
    575  1.2.2.2  yamt  *
    576  1.2.2.2  yamt  *      i       input sense
    577  1.2.2.2  yamt  *      o       output control
    578  1.2.2.2  yamt  *      2       function 2
    579  1.2.2.2  yamt  *      3       function 3
    580  1.2.2.2  yamt  *      0       output control (A only)
    581  1.2.2.2  yamt  *      1       function 1 (A only)
    582  1.2.2.2  yamt  *      ./x     no function, not connected or don't-care
    583  1.2.2.2  yamt  *
    584  1.2.2.2  yamt  * A ........ .1x11111 1111x111 11111111
    585  1.2.2.2  yamt  * B                   .....22o ooooooo2
    586  1.2.2.2  yamt  * C                   22222222 22222222
    587  1.2.2.2  yamt  * D                   22222222 22222222
    588  1.2.2.2  yamt  * E                   22222222 22222222
    589  1.2.2.2  yamt  * F                   ........ 22222222
    590  1.2.2.2  yamt  * G                   xxx2222i 22232322
    591  1.2.2.2  yamt  * H                   .....22i 22222222
    592  1.2.2.2  yamt  * J                   ...22222 22222222
    593  1.2.2.2  yamt  */
    594  1.2.2.2  yamt 	iomux('A', "........ .1x11111 1111x111 11111111");
    595  1.2.2.2  yamt 	iomux('B', ".....22o ooooooo2");
    596  1.2.2.2  yamt 	iomux('C', "22222222 22222222");
    597  1.2.2.2  yamt 	iomux('D', "22222222 22222222");
    598  1.2.2.2  yamt 	iomux('E', "22222222 22222222");
    599  1.2.2.2  yamt 	iomux('F', "........ 22222222");
    600  1.2.2.2  yamt 	iomux('G', "xxx2222i 22232322");
    601  1.2.2.2  yamt 	iomux('H', ".....22i 22222222");
    602  1.2.2.2  yamt 	iomux('J', "...22222 22222222");
    603  1.2.2.2  yamt 
    604  1.2.2.2  yamt 	/* mask all possible external interrupt source [23:3] */
    605  1.2.2.2  yamt 	CSR_WRITE(S3C2440_GPIO_BASE + GPIO_EINTMASK, ~0);
    606  1.2.2.2  yamt }
    607  1.2.2.2  yamt 
    608  1.2.2.2  yamt static void
    609  1.2.2.2  yamt iomux(int grp, const char *cnf)
    610  1.2.2.2  yamt {
    611  1.2.2.2  yamt 	uint32_t con;
    612  1.2.2.2  yamt 	int sft, i, v;
    613  1.2.2.2  yamt 
    614  1.2.2.2  yamt 	con = v = 0;
    615  1.2.2.2  yamt 	sft = (grp != 'A') ? 2 : 1;
    616  1.2.2.2  yamt 	for (i = 0; cnf[i] != '\0'; i++) {
    617  1.2.2.2  yamt 		switch (cnf[i]) {
    618  1.2.2.2  yamt 		case 'i':
    619  1.2.2.2  yamt 		case '0':
    620  1.2.2.2  yamt 		case '.':
    621  1.2.2.2  yamt 		case 'x':
    622  1.2.2.2  yamt 			v = 0; break;
    623  1.2.2.2  yamt 		case 'o':
    624  1.2.2.2  yamt 		case '1':
    625  1.2.2.2  yamt 			v = 1; break;
    626  1.2.2.2  yamt 		case '2':
    627  1.2.2.2  yamt 			v = 2; break;
    628  1.2.2.2  yamt 		case '3':
    629  1.2.2.2  yamt 			v = 3; break;
    630  1.2.2.2  yamt 		default:
    631  1.2.2.2  yamt 			continue;
    632  1.2.2.2  yamt 		}
    633  1.2.2.2  yamt 		con = (con << sft) | v;
    634  1.2.2.2  yamt 	}
    635  1.2.2.2  yamt 	CSR_WRITE(S3C2440_GPIO_BASE + 0x10 * (grp - 'A'), con);
    636  1.2.2.2  yamt }
    637