0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <stddef.h>
0011 #include "stdio.h"
0012 #include "types.h"
0013 #include "io.h"
0014 #include "ops.h"
0015
0016 #include "ugecon.h"
0017
0018 BSS_STACK(8192);
0019
0020 #define HW_REG(x) ((void *)(x))
0021
0022 #define EXI_CTRL HW_REG(0x0d800070)
0023 #define EXI_CTRL_ENABLE (1<<0)
0024
0025 #define MEM2_TOP (0x10000000 + 64*1024*1024)
0026 #define FIRMWARE_DEFAULT_SIZE (12*1024*1024)
0027
0028
0029 struct mipc_infohdr {
0030 char magic[3];
0031 u8 version;
0032 u32 mem2_boundary;
0033 u32 ipc_in;
0034 size_t ipc_in_size;
0035 u32 ipc_out;
0036 size_t ipc_out_size;
0037 };
0038
0039 static int mipc_check_address(u32 pa)
0040 {
0041
0042 if (pa < 0x10000000 || pa > 0x14000000)
0043 return -EINVAL;
0044 return 0;
0045 }
0046
0047 static struct mipc_infohdr *mipc_get_infohdr(void)
0048 {
0049 struct mipc_infohdr **hdrp, *hdr;
0050
0051
0052 hdrp = (struct mipc_infohdr **)0x13fffffc;
0053 if (mipc_check_address((u32)hdrp)) {
0054 printf("mini: invalid hdrp %08X\n", (u32)hdrp);
0055 hdr = NULL;
0056 goto out;
0057 }
0058
0059 hdr = *hdrp;
0060 if (mipc_check_address((u32)hdr)) {
0061 printf("mini: invalid hdr %08X\n", (u32)hdr);
0062 hdr = NULL;
0063 goto out;
0064 }
0065 if (memcmp(hdr->magic, "IPC", 3)) {
0066 printf("mini: invalid magic\n");
0067 hdr = NULL;
0068 goto out;
0069 }
0070
0071 out:
0072 return hdr;
0073 }
0074
0075 static int mipc_get_mem2_boundary(u32 *mem2_boundary)
0076 {
0077 struct mipc_infohdr *hdr;
0078 int error;
0079
0080 hdr = mipc_get_infohdr();
0081 if (!hdr) {
0082 error = -1;
0083 goto out;
0084 }
0085
0086 if (mipc_check_address(hdr->mem2_boundary)) {
0087 printf("mini: invalid mem2_boundary %08X\n",
0088 hdr->mem2_boundary);
0089 error = -EINVAL;
0090 goto out;
0091 }
0092 *mem2_boundary = hdr->mem2_boundary;
0093 error = 0;
0094 out:
0095 return error;
0096
0097 }
0098
0099 static void platform_fixups(void)
0100 {
0101 void *mem;
0102 u32 reg[4];
0103 u32 mem2_boundary;
0104 int len;
0105 int error;
0106
0107 mem = finddevice("/memory");
0108 if (!mem)
0109 fatal("Can't find memory node\n");
0110
0111
0112 len = getprop(mem, "reg", reg, sizeof(reg));
0113 if (len != sizeof(reg)) {
0114
0115 goto out;
0116 }
0117
0118
0119 error = mipc_get_mem2_boundary(&mem2_boundary);
0120 if (error) {
0121
0122 mem2_boundary = MEM2_TOP - FIRMWARE_DEFAULT_SIZE;
0123 }
0124
0125 if (mem2_boundary > reg[2] && mem2_boundary < reg[2] + reg[3]) {
0126 reg[3] = mem2_boundary - reg[2];
0127 printf("top of MEM2 @ %08X\n", reg[2] + reg[3]);
0128 setprop(mem, "reg", reg, sizeof(reg));
0129 }
0130
0131 out:
0132 return;
0133 }
0134
0135 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5)
0136 {
0137 u32 heapsize = 24*1024*1024 - (u32)_end;
0138
0139 simple_alloc_init(_end, heapsize, 32, 64);
0140 fdt_init(_dtb_start);
0141
0142
0143
0144
0145
0146 out_be32(EXI_CTRL, in_be32(EXI_CTRL) | EXI_CTRL_ENABLE);
0147
0148 if (ug_probe())
0149 console_ops.write = ug_console_write;
0150
0151 platform_ops.fixups = platform_fixups;
0152 }
0153