1 /* 2 * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <linux/ctype.h> 9 #include <linux/io.h> 10 11 #include "micro-support-card.h" 12 13 #define MICRO_SUPPORT_CARD_BASE 0x43f00000 14 #define SMC911X_BASE ((MICRO_SUPPORT_CARD_BASE) + 0x00000) 15 #define LED_BASE ((MICRO_SUPPORT_CARD_BASE) + 0x90000) 16 #define NS16550A_BASE ((MICRO_SUPPORT_CARD_BASE) + 0xb0000) 17 #define MICRO_SUPPORT_CARD_RESET ((MICRO_SUPPORT_CARD_BASE) + 0xd0034) 18 #define MICRO_SUPPORT_CARD_REVISION ((MICRO_SUPPORT_CARD_BASE) + 0xd00E0) 19 20 /* 21 * 0: reset deassert, 1: reset 22 * 23 * bit[0]: LAN, I2C, LED 24 * bit[1]: UART 25 */ 26 void support_card_reset_deassert(void) 27 { 28 writel(0x00010000, MICRO_SUPPORT_CARD_RESET); 29 } 30 31 void support_card_reset(void) 32 { 33 writel(0x00020003, MICRO_SUPPORT_CARD_RESET); 34 } 35 36 static int support_card_show_revision(void) 37 { 38 u32 revision; 39 40 revision = readl(MICRO_SUPPORT_CARD_REVISION); 41 printf("(CPLD version %d.%d)\n", revision >> 4, revision & 0xf); 42 return 0; 43 } 44 45 int check_support_card(void) 46 { 47 printf("SC: Micro Support Card "); 48 return support_card_show_revision(); 49 } 50 51 void support_card_init(void) 52 { 53 /* 54 * After power on, we need to keep the LAN controller in reset state 55 * for a while. (200 usec) 56 * Fortunately, enough wait time is already inserted in pll_init() 57 * function. So we do not have to wait here. 58 */ 59 support_card_reset_deassert(); 60 } 61 62 #if defined(CONFIG_SMC911X) 63 #include <netdev.h> 64 65 int board_eth_init(bd_t *bis) 66 { 67 return smc911x_initialize(0, SMC911X_BASE); 68 } 69 #endif 70 71 #if !defined(CONFIG_SYS_NO_FLASH) 72 73 #include <mtd/cfi_flash.h> 74 75 struct memory_bank { 76 phys_addr_t base; 77 unsigned long size; 78 }; 79 80 static int mem_is_flash(const struct memory_bank *mem) 81 { 82 const int loop = 128; 83 u32 *scratch_addr; 84 u32 saved_value; 85 int ret = 1; 86 int i; 87 88 /* just in case, use the tail of the memory bank */ 89 scratch_addr = map_physmem(mem->base + mem->size - sizeof(u32) * loop, 90 sizeof(u32) * loop, MAP_NOCACHE); 91 92 for (i = 0; i < loop; i++, scratch_addr++) { 93 saved_value = readl(scratch_addr); 94 writel(~saved_value, scratch_addr); 95 if (readl(scratch_addr) != saved_value) { 96 /* We assume no memory or SRAM here. */ 97 writel(saved_value, scratch_addr); 98 ret = 0; 99 break; 100 } 101 } 102 103 unmap_physmem(scratch_addr, MAP_NOCACHE); 104 105 return ret; 106 } 107 108 /* {address, size} */ 109 static const struct memory_bank memory_banks[] = { 110 {0x42000000, 0x01f00000}, 111 }; 112 113 static const struct memory_bank 114 *flash_banks_list[CONFIG_SYS_MAX_FLASH_BANKS_DETECT]; 115 116 phys_addr_t cfi_flash_bank_addr(int i) 117 { 118 return flash_banks_list[i]->base; 119 } 120 121 unsigned long cfi_flash_bank_size(int i) 122 { 123 return flash_banks_list[i]->size; 124 } 125 126 static void detect_num_flash_banks(void) 127 { 128 const struct memory_bank *memory_bank, *end; 129 130 cfi_flash_num_flash_banks = 0; 131 132 memory_bank = memory_banks; 133 end = memory_bank + ARRAY_SIZE(memory_banks); 134 135 for (; memory_bank < end; memory_bank++) { 136 if (cfi_flash_num_flash_banks >= 137 CONFIG_SYS_MAX_FLASH_BANKS_DETECT) 138 break; 139 140 if (mem_is_flash(memory_bank)) { 141 flash_banks_list[cfi_flash_num_flash_banks] = 142 memory_bank; 143 144 debug("flash bank found: base = 0x%lx, size = 0x%lx\n", 145 (unsigned long)memory_bank->base, 146 (unsigned long)memory_bank->size); 147 cfi_flash_num_flash_banks++; 148 } 149 } 150 151 debug("number of flash banks: %d\n", cfi_flash_num_flash_banks); 152 } 153 #else /* CONFIG_SYS_NO_FLASH */ 154 void detect_num_flash_banks(void) 155 { 156 }; 157 #endif /* CONFIG_SYS_NO_FLASH */ 158 159 void support_card_late_init(void) 160 { 161 detect_num_flash_banks(); 162 } 163 164 static const u8 ledval_num[] = { 165 0x7e, /* 0 */ 166 0x0c, /* 1 */ 167 0xb6, /* 2 */ 168 0x9e, /* 3 */ 169 0xcc, /* 4 */ 170 0xda, /* 5 */ 171 0xfa, /* 6 */ 172 0x4e, /* 7 */ 173 0xfe, /* 8 */ 174 0xde, /* 9 */ 175 }; 176 177 static const u8 ledval_alpha[] = { 178 0xee, /* A */ 179 0xf8, /* B */ 180 0x72, /* C */ 181 0xbc, /* D */ 182 0xf2, /* E */ 183 0xe2, /* F */ 184 0x7a, /* G */ 185 0xe8, /* H */ 186 0x08, /* I */ 187 0x3c, /* J */ 188 0xea, /* K */ 189 0x70, /* L */ 190 0x6e, /* M */ 191 0xa8, /* N */ 192 0xb8, /* O */ 193 0xe6, /* P */ 194 0xce, /* Q */ 195 0xa0, /* R */ 196 0xc8, /* S */ 197 0x8c, /* T */ 198 0x7c, /* U */ 199 0x54, /* V */ 200 0xfc, /* W */ 201 0xec, /* X */ 202 0xdc, /* Y */ 203 0xa4, /* Z */ 204 }; 205 206 static u8 char2ledval(char c) 207 { 208 if (isdigit(c)) 209 return ledval_num[c - '0']; 210 else if (isalpha(c)) 211 return ledval_alpha[toupper(c) - 'A']; 212 213 return 0; 214 } 215 216 void led_puts(const char *s) 217 { 218 int i; 219 u32 val = 0; 220 221 if (!s) 222 return; 223 224 for (i = 0; i < 4; i++) { 225 val <<= 8; 226 val |= char2ledval(*s); 227 if (*s != '\0') 228 s++; 229 } 230 231 writel(~val, LED_BASE); 232 } 233