micro-support-card.c 4.4 KB
Newer Older
1
/*
2
 * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
3 4 5 6 7
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
8
#include <linux/ctype.h>
9
#include <linux/io.h>
10 11

#include "micro-support-card.h"
12

13 14 15 16 17 18 19
#define MICRO_SUPPORT_CARD_BASE		0x43f00000
#define SMC911X_BASE			((MICRO_SUPPORT_CARD_BASE) + 0x00000)
#define LED_BASE			((MICRO_SUPPORT_CARD_BASE) + 0x90000)
#define NS16550A_BASE			((MICRO_SUPPORT_CARD_BASE) + 0xb0000)
#define MICRO_SUPPORT_CARD_RESET	((MICRO_SUPPORT_CARD_BASE) + 0xd0034)
#define MICRO_SUPPORT_CARD_REVISION	((MICRO_SUPPORT_CARD_BASE) + 0xd00E0)

20 21 22 23 24 25 26 27
/*
 * 0: reset deassert, 1: reset
 *
 * bit[0]: LAN, I2C, LED
 * bit[1]: UART
 */
void support_card_reset_deassert(void)
{
28
	writel(0, MICRO_SUPPORT_CARD_RESET);
29 30 31 32
}

void support_card_reset(void)
{
33
	writel(3, MICRO_SUPPORT_CARD_RESET);
34 35 36 37 38 39
}

static int support_card_show_revision(void)
{
	u32 revision;

40 41
	revision = readl(MICRO_SUPPORT_CARD_REVISION);
	printf("(CPLD version %d.%d)\n", revision >> 4, revision & 0xf);
42 43 44
	return 0;
}

45 46 47 48 49 50
int check_support_card(void)
{
	printf("SC:    Micro Support Card ");
	return support_card_show_revision();
}

51 52 53 54 55
void support_card_init(void)
{
	/*
	 * After power on, we need to keep the LAN controller in reset state
	 * for a while. (200 usec)
56
	 * Fortunately, enough wait time is already inserted in pll_init()
57 58 59 60 61 62 63 64 65 66
	 * function. So we do not have to wait here.
	 */
	support_card_reset_deassert();
}

#if defined(CONFIG_SMC911X)
#include <netdev.h>

int board_eth_init(bd_t *bis)
{
67
	return smc911x_initialize(0, SMC911X_BASE);
68 69 70 71 72 73 74
}
#endif

#if !defined(CONFIG_SYS_NO_FLASH)

#include <mtd/cfi_flash.h>

75 76 77 78
struct memory_bank {
	phys_addr_t base;
	unsigned long size;
};
79

80
static int mem_is_flash(const struct memory_bank *mem)
81 82 83 84 85 86 87
{
	const int loop = 128;
	u32 *scratch_addr;
	u32 saved_value;
	int ret = 1;
	int i;

88 89 90
	/* just in case, use the tail of the memory bank */
	scratch_addr = map_physmem(mem->base + mem->size - sizeof(u32) * loop,
				   sizeof(u32) * loop, MAP_NOCACHE);
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107

	for (i = 0; i < loop; i++, scratch_addr++) {
		saved_value = readl(scratch_addr);
		writel(~saved_value, scratch_addr);
		if (readl(scratch_addr) != saved_value) {
			/* We assume no memory or SRAM here. */
			writel(saved_value, scratch_addr);
			ret = 0;
			break;
		}
	}

	unmap_physmem(scratch_addr, MAP_NOCACHE);

	return ret;
}

108 109
/* {address, size} */
static const struct memory_bank memory_banks[] = {
110
	{0x42000000, 0x01f00000},
111 112 113 114 115 116
};

static const struct memory_bank
*flash_banks_list[CONFIG_SYS_MAX_FLASH_BANKS_DETECT];

phys_addr_t cfi_flash_bank_addr(int i)
117
{
118 119
	return flash_banks_list[i]->base;
}
120

121 122 123 124 125 126 127 128 129 130 131
unsigned long cfi_flash_bank_size(int i)
{
	return flash_banks_list[i]->size;
}

static void detect_num_flash_banks(void)
{
	const struct memory_bank *memory_bank, *end;

	cfi_flash_num_flash_banks = 0;

132 133
	memory_bank = memory_banks;
	end = memory_bank + ARRAY_SIZE(memory_banks);
134 135 136 137 138 139 140 141 142 143 144

	for (; memory_bank < end; memory_bank++) {
		if (cfi_flash_num_flash_banks >=
		    CONFIG_SYS_MAX_FLASH_BANKS_DETECT)
			break;

		if (mem_is_flash(memory_bank)) {
			flash_banks_list[cfi_flash_num_flash_banks] =
								memory_bank;

			debug("flash bank found: base = 0x%lx, size = 0x%lx\n",
145 146
			      (unsigned long)memory_bank->base,
			      (unsigned long)memory_bank->size);
147
			cfi_flash_num_flash_banks++;
148 149 150
		}
	}

151 152
	debug("number of flash banks: %d\n", cfi_flash_num_flash_banks);
}
153
#else /* CONFIG_SYS_NO_FLASH */
154 155 156
void detect_num_flash_banks(void)
{
};
157
#endif /* CONFIG_SYS_NO_FLASH */
158 159 160 161

void support_card_late_init(void)
{
	detect_num_flash_banks();
162
}
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230

static const u8 ledval_num[] = {
	0x7e, /* 0 */
	0x0c, /* 1 */
	0xb6, /* 2 */
	0x9e, /* 3 */
	0xcc, /* 4 */
	0xda, /* 5 */
	0xfa, /* 6 */
	0x4e, /* 7 */
	0xfe, /* 8 */
	0xde, /* 9 */
};

static const u8 ledval_alpha[] = {
	0xee, /* A */
	0xf8, /* B */
	0x72, /* C */
	0xbc, /* D */
	0xf2, /* E */
	0xe2, /* F */
	0x7a, /* G */
	0xe8, /* H */
	0x08, /* I */
	0x3c, /* J */
	0xea, /* K */
	0x70, /* L */
	0x6e, /* M */
	0xa8, /* N */
	0xb8, /* O */
	0xe6, /* P */
	0xce, /* Q */
	0xa0, /* R */
	0xc8, /* S */
	0x8c, /* T */
	0x7c, /* U */
	0x54, /* V */
	0xfc, /* W */
	0xec, /* X */
	0xdc, /* Y */
	0xa4, /* Z */
};

static u8 char2ledval(char c)
{
	if (isdigit(c))
		return ledval_num[c - '0'];
	else if (isalpha(c))
		return ledval_alpha[toupper(c) - 'A'];

	return 0;
}

void led_puts(const char *s)
{
	int i;
	u32 val = 0;

	if (!s)
		return;

	for (i = 0; i < 4; i++) {
		val <<= 8;
		val |= char2ledval(*s);
		if (*s != '\0')
			s++;
	}

231
	writel(~val, LED_BASE);
232
}