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