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(0, MICRO_SUPPORT_CARD_RESET); 29 } 30 31 void support_card_reset(void) 32 { 33 writel(3, 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 memory_bank->base, memory_bank->size); 146 cfi_flash_num_flash_banks++; 147 } 148 } 149 150 debug("number of flash banks: %d\n", cfi_flash_num_flash_banks); 151 } 152 #else /* CONFIG_SYS_NO_FLASH */ 153 void detect_num_flash_banks(void) 154 { 155 }; 156 #endif /* CONFIG_SYS_NO_FLASH */ 157 158 void support_card_late_init(void) 159 { 160 detect_num_flash_banks(); 161 } 162 163 static const u8 ledval_num[] = { 164 0x7e, /* 0 */ 165 0x0c, /* 1 */ 166 0xb6, /* 2 */ 167 0x9e, /* 3 */ 168 0xcc, /* 4 */ 169 0xda, /* 5 */ 170 0xfa, /* 6 */ 171 0x4e, /* 7 */ 172 0xfe, /* 8 */ 173 0xde, /* 9 */ 174 }; 175 176 static const u8 ledval_alpha[] = { 177 0xee, /* A */ 178 0xf8, /* B */ 179 0x72, /* C */ 180 0xbc, /* D */ 181 0xf2, /* E */ 182 0xe2, /* F */ 183 0x7a, /* G */ 184 0xe8, /* H */ 185 0x08, /* I */ 186 0x3c, /* J */ 187 0xea, /* K */ 188 0x70, /* L */ 189 0x6e, /* M */ 190 0xa8, /* N */ 191 0xb8, /* O */ 192 0xe6, /* P */ 193 0xce, /* Q */ 194 0xa0, /* R */ 195 0xc8, /* S */ 196 0x8c, /* T */ 197 0x7c, /* U */ 198 0x54, /* V */ 199 0xfc, /* W */ 200 0xec, /* X */ 201 0xdc, /* Y */ 202 0xa4, /* Z */ 203 }; 204 205 static u8 char2ledval(char c) 206 { 207 if (isdigit(c)) 208 return ledval_num[c - '0']; 209 else if (isalpha(c)) 210 return ledval_alpha[toupper(c) - 'A']; 211 212 return 0; 213 } 214 215 void led_puts(const char *s) 216 { 217 int i; 218 u32 val = 0; 219 220 if (!s) 221 return; 222 223 for (i = 0; i < 4; i++) { 224 val <<= 8; 225 val |= char2ledval(*s); 226 if (*s != '\0') 227 s++; 228 } 229 230 writel(~val, LED_BASE); 231 } 232