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