1/* $NetBSD: tx39xx.c,v 1.7 2009/03/14 14:45:59 dsl Exp $ */
2
3/*-
4 * Copyright (c) 1999 Shin Takemura, UCHIYAMA Yasushi
5 * All rights reserved.
6 *
7 * This software is part of the PocketBSD.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed by the PocketBSD project
20 *	and its contributors.
21 * 4. Neither the name of the project nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 */
38
39#include <pbsdboot.h>
40
41extern void tx39xx_asm_code();
42extern void tx39xx_asm_code_end();
43void tx39xx_asm_code_holder(void);
44
45#define TX39_SYSADDR_CONFIG_REG		0x10C00000
46#define TX39_SYSADDR_CONFIG_REG_LEN	0x00200000
47typedef int tx_chipset_tag_t;
48u_int32_t __tx39conf_addr;
49
50u_int32_t
51tx_conf_read(tx_chipset_tag_t t, int reg)
52{
53	return *((u_int32_t*)(__tx39conf_addr + reg));
54}
55
56void
57tx_conf_write(tx_chipset_tag_t t, int reg, u_int32_t val)
58{
59	u_int32_t addr = (u_int32_t)t;
60	*((u_int32_t*)(__tx39conf_addr +reg)) = val;
61}
62
63void
64tx39xx_init(SYSTEM_INFO *info)
65{
66	/* 4KByte page */
67	system_info.si_pagesize = info->dwPageSize;
68	/* DRAM Bank 0/1 physical addr range */
69	system_info.si_dramstart = 0x04000000;
70	system_info.si_drammaxsize = 0x04000000;
71	/* Pointer for bootstrap code */
72	system_info.si_asmcode = (unsigned char*)tx39xx_asm_code;
73	system_info.si_asmcodelen = (unsigned char*)tx39xx_asm_code_end
74		- system_info.si_asmcode;
75	system_info.si_boot = mips_boot;
76	system_info.si_intrvec = 0x80;
77
78	__tx39conf_addr = (int)VirtualAlloc(0, TX39_SYSADDR_CONFIG_REG_LEN, MEM_RESERVE,
79			    PAGE_NOACCESS);
80	if (!VirtualCopy((LPVOID)__tx39conf_addr,
81			 (LPVOID)(TX39_SYSADDR_CONFIG_REG >> 8),
82			 TX39_SYSADDR_CONFIG_REG_LEN,
83			 PAGE_READWRITE|PAGE_NOCACHE|PAGE_PHYSICAL)) {
84		msg_printf(MSG_ERROR, whoami,
85			   TEXT("Mapping TX39 configuration register failed.\n"));
86	}
87}
88
89void
90tx39xx_asm_code_holder()
91{
92	/*
93	 * void
94	 * startprog(register struct map_s *map)
95	 * {
96	 *   register unsigned char *addr;
97	 *   register unsigned char *p;
98	 *   register int i;
99	 *
100	 *   addr = map->base;
101	 *   i = 0;
102	 *   while (p = map->leaf[i / map->leafsize][i % map->leafsize]) {
103	 *     register unsigned char *pe = p + map->pagesize;
104	 *     while (p < pe) {
105	 *       *addr++ = *p++;
106	 *     }
107	 *     i++;
108	 *   }
109	 * }
110	 *
111	 *  register assignment:
112	 *    struct map_s *map		a0
113	 *    unsigned char *addr	a1
114	 *    unsigned char *p		a2
115	 *    unsigned char *pe		a3
116	 *    int i			t0
117	 *
118	 * struct map_s {
119	 *   void *entry;	+0
120	 *   void *base;	+4
121	 *   int pagesize;	+8
122	 *   int leafsize;	+12
123	 *   int nleaves;	+16
124	 *   void *arg0;	+20
125	 *   void *arg1;  +24
126	 *   void *arg2;	+28
127	 *   void *arg3;	+32
128	 *   void **leaf[32];	+36
129	 *
130	 */
131	__asm(
132		".set noreorder;"
133		".globl tx39xx_asm_code;"
134		"tx39xx_asm_code:"
135		"lui	a0, 0x0000;"
136		"ori	a0, 0x0000;"
137
138		/* Disable interrupt */
139		"nop;"
140		"mtc0	zero, $12;"
141		"nop;"
142
143		/*
144		 * Copy kernel to bootaddr
145		 */
146		/* addr = map->base;	*/
147		"lw	a1, 4(a0);"
148
149		/*   i = 0;		*/
150		"ori	t0, zero, 0;"
151
152	" loop_start:"
153
154		/*   while (p = map->leaf[i / map->leafsize][i % map->leafsize]) { */
155		/*   t1 = map->leafsize */
156		"lw	t1, 12(a0);"
157
158		/*   lo = i / map->leafsize, hi = i % map->leafsize */
159		"addu	t3, zero, t0;"
160		"div	t3, t1;"
161		/*   t2 = map->leaf */
162		"addiu	t2, a0, 36;"
163		/*   t3 = i / map->leafsize */
164		"nop;"
165		"mflo	t3;"
166		/*   t2 = map->leaf[i / map->leafsize] */
167		"sll	t3, t3, 2;"
168		"addu	t2, t2, t3;"
169		"lw	t2, 0(t2);"
170		/*   t3 = i % map->leafsize */
171		"mfhi	t3;"
172
173		/*   p = map->leaf[i / map->leafsize][i % map->leafsize] */
174		"sll	t3, t3, 2;"
175		"addu	t2, t2, t3;"
176		"lw	a2, 0(t2);"
177
178		/*		if (p == NULL) {	*/
179		/*			break;			*/
180		/*		}					*/
181		"beq	a2, zero, loop_end;"
182		"nop;"
183
184		/*     register unsigned char *pe = p + map->pagesize; */
185		"lw	t1, 8(a0);"
186		"add	a3, a2, t1;"
187
188		/*		while (p < pe) {		*/
189	"loop_start2:"
190		"sltu        t1, a2, a3;"
191		"beq         zero,t1,loop_end2;"
192		"nop;"
193
194		/*			*addr++ = *p++;	*/
195		"lw	t1, 0(a2);"
196		"sw	t1, 0(a1);"
197		"addi	a2, a2, 4;"
198		"addi	a1, a1, 4;"
199
200		/*		}	*/
201		"beq	zero, zero, loop_start2;"
202		"nop;"
203
204		/*     i++;	*/
205	"loop_end2:"
206		"addi	t0, t0, 1;"
207		"beq	zero, zero, loop_start;"
208		"nop;"
209
210	"loop_end:"
211		"move t3, a0;"
212	);
213
214	/*
215	 * Flush cache
216	 */
217	__asm(
218		"li	t1, 16384;"
219		"li	t2, 8192;"
220
221		/* Disable I-cache */
222		"li	t5, ~0x00000020;"
223		"mfc0	t6, $3;"
224		"and	t5, t5, t6;"
225		"nop;"
226		"mtc0	t5, $3;"
227		/* Stop streaming */
228		"beq	zero, zero, 1f;"
229		"nop;"
230	"1:"
231		/* Flush I-cache */
232		"li	t0, 0x80000000;"
233		"addu	t1, t0, t1;"
234		"subu	t1, t1, 128;"
235	"2:"
236		".word 0xbd000000;"
237		".word 0xbd000010;"
238		".word 0xbd000020;"
239		".word 0xbd000030;"
240		".word 0xbd000040;"
241		".word 0xbd000050;"
242		".word 0xbd000060;"
243		".word 0xbd000070;"
244		"bne	t0, t1, 2b;"
245		"addu	t0, t0, 128;"
246
247		/* Flush D-cache */
248		"li	t0, 0x80000000;"
249		"addu	t1, t0, t2;"
250
251	"3:"
252		"lw	t2, 0(t0);"
253		"bne	t1, t0, 3b;"
254		"addiu	t0, t0, 4;"
255
256		/* Enable I-cache */
257		"nop;"
258		"mtc0	t6, $3;"
259		"nop;"
260	);
261	/*
262	 *  Jump to kernel entry
263	 */
264	__asm(
265
266		"lw	t0, 0(t3);"	/* entry addr */
267		"lw	a1, 24(t3);"	/* arg1 */
268		"lw	a2, 28(t3);"	/* arg2 */
269		"lw	a3, 32(t3);"	/* arg3 */
270		"lw	a0, 20(t3);"	/* arg0 */
271		"jr	t0;"
272		"nop;"
273
274		".globl tx39xx_asm_code_end;"
275		"tx39xx_asm_code_end: nop;"
276		".set reorder;	"
277	);
278}
279