uboot/drivers/ddr/altera/sdram_soc64.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2016-2019 Intel Corporation <www.intel.com>
   4 *
   5 */
   6
   7#include <common.h>
   8#include <cpu_func.h>
   9#include <dm.h>
  10#include <errno.h>
  11#include <div64.h>
  12#include <fdtdec.h>
  13#include <hang.h>
  14#include <init.h>
  15#include <log.h>
  16#include <ram.h>
  17#include <reset.h>
  18#include "sdram_soc64.h"
  19#include <wait_bit.h>
  20#include <asm/arch/firewall.h>
  21#include <asm/arch/system_manager.h>
  22#include <asm/arch/reset_manager.h>
  23#include <asm/cache.h>
  24#include <asm/global_data.h>
  25#include <asm/io.h>
  26#include <dm/device_compat.h>
  27#include <linux/sizes.h>
  28
  29#define PGTABLE_OFF     0x4000
  30
  31u32 hmc_readl(struct altera_sdram_plat *plat, u32 reg)
  32{
  33        return readl(plat->iomhc + reg);
  34}
  35
  36u32 hmc_ecc_readl(struct altera_sdram_plat *plat, u32 reg)
  37{
  38        return readl(plat->hmc + reg);
  39}
  40
  41u32 hmc_ecc_writel(struct altera_sdram_plat *plat,
  42                   u32 data, u32 reg)
  43{
  44        return writel(data, plat->hmc + reg);
  45}
  46
  47u32 ddr_sch_writel(struct altera_sdram_plat *plat, u32 data,
  48                   u32 reg)
  49{
  50        return writel(data, plat->ddr_sch + reg);
  51}
  52
  53int emif_clear(struct altera_sdram_plat *plat)
  54{
  55        hmc_ecc_writel(plat, 0, RSTHANDSHAKECTRL);
  56
  57        return wait_for_bit_le32((const void *)(plat->hmc +
  58                                 RSTHANDSHAKESTAT),
  59                                 DDR_HMC_RSTHANDSHAKE_MASK,
  60                                 false, 1000, false);
  61}
  62
  63int emif_reset(struct altera_sdram_plat *plat)
  64{
  65        u32 c2s, s2c, ret;
  66
  67        c2s = hmc_ecc_readl(plat, RSTHANDSHAKECTRL) & DDR_HMC_RSTHANDSHAKE_MASK;
  68        s2c = hmc_ecc_readl(plat, RSTHANDSHAKESTAT) & DDR_HMC_RSTHANDSHAKE_MASK;
  69
  70        debug("DDR: c2s=%08x s2c=%08x nr0=%08x nr1=%08x nr2=%08x dst=%08x\n",
  71              c2s, s2c, hmc_readl(plat, NIOSRESERVED0),
  72              hmc_readl(plat, NIOSRESERVED1), hmc_readl(plat, NIOSRESERVED2),
  73              hmc_readl(plat, DRAMSTS));
  74
  75        if (s2c && emif_clear(plat)) {
  76                printf("DDR: emif_clear() failed\n");
  77                return -1;
  78        }
  79
  80        debug("DDR: Triggerring emif reset\n");
  81        hmc_ecc_writel(plat, DDR_HMC_CORE2SEQ_INT_REQ, RSTHANDSHAKECTRL);
  82
  83        /* if seq2core[3] = 0, we are good */
  84        ret = wait_for_bit_le32((const void *)(plat->hmc +
  85                                 RSTHANDSHAKESTAT),
  86                                 DDR_HMC_SEQ2CORE_INT_RESP_MASK,
  87                                 false, 1000, false);
  88        if (ret) {
  89                printf("DDR: failed to get ack from EMIF\n");
  90                return ret;
  91        }
  92
  93        ret = emif_clear(plat);
  94        if (ret) {
  95                printf("DDR: emif_clear() failed\n");
  96                return ret;
  97        }
  98
  99        debug("DDR: %s triggered successly\n", __func__);
 100        return 0;
 101}
 102
 103int poll_hmc_clock_status(void)
 104{
 105        return wait_for_bit_le32((const void *)(socfpga_get_sysmgr_addr() +
 106                                 SYSMGR_SOC64_HMC_CLK),
 107                                 SYSMGR_HMC_CLK_STATUS_MSK, true, 1000, false);
 108}
 109
 110void sdram_clear_mem(phys_addr_t addr, phys_size_t size)
 111{
 112        phys_size_t i;
 113
 114        if (addr % CONFIG_SYS_CACHELINE_SIZE) {
 115                printf("DDR: address 0x%llx is not cacheline size aligned.\n",
 116                       addr);
 117                hang();
 118        }
 119
 120        if (size % CONFIG_SYS_CACHELINE_SIZE) {
 121                printf("DDR: size 0x%llx is not multiple of cacheline size\n",
 122                       size);
 123                hang();
 124        }
 125
 126        /* Use DC ZVA instruction to clear memory to zeros by a cache line */
 127        for (i = 0; i < size; i = i + CONFIG_SYS_CACHELINE_SIZE) {
 128                asm volatile("dc zva, %0"
 129                     :
 130                     : "r"(addr)
 131                     : "memory");
 132                addr += CONFIG_SYS_CACHELINE_SIZE;
 133        }
 134}
 135
 136void sdram_init_ecc_bits(struct bd_info *bd)
 137{
 138        phys_size_t size, size_init;
 139        phys_addr_t start_addr;
 140        int bank = 0;
 141        unsigned int start = get_timer(0);
 142
 143        icache_enable();
 144
 145        start_addr = bd->bi_dram[0].start;
 146        size = bd->bi_dram[0].size;
 147
 148        /* Initialize small block for page table */
 149        memset((void *)start_addr, 0, PGTABLE_SIZE + PGTABLE_OFF);
 150        gd->arch.tlb_addr = start_addr + PGTABLE_OFF;
 151        gd->arch.tlb_size = PGTABLE_SIZE;
 152        start_addr += PGTABLE_SIZE + PGTABLE_OFF;
 153        size -= (PGTABLE_OFF + PGTABLE_SIZE);
 154        dcache_enable();
 155
 156        while (1) {
 157                while (size) {
 158                        size_init = min((phys_addr_t)SZ_1G, (phys_addr_t)size);
 159                        sdram_clear_mem(start_addr, size_init);
 160                        size -= size_init;
 161                        start_addr += size_init;
 162                        WATCHDOG_RESET();
 163                }
 164
 165                bank++;
 166                if (bank >= CONFIG_NR_DRAM_BANKS)
 167                        break;
 168
 169                start_addr = bd->bi_dram[bank].start;
 170                size = bd->bi_dram[bank].size;
 171        }
 172
 173        dcache_disable();
 174        icache_disable();
 175
 176        printf("SDRAM-ECC: Initialized success with %d ms\n",
 177               (unsigned int)get_timer(start));
 178}
 179
 180void sdram_size_check(struct bd_info *bd)
 181{
 182        phys_size_t total_ram_check = 0;
 183        phys_size_t ram_check = 0;
 184        phys_addr_t start = 0;
 185        int bank;
 186
 187        /* Sanity check ensure correct SDRAM size specified */
 188        debug("DDR: Running SDRAM size sanity check\n");
 189
 190        for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
 191                start = bd->bi_dram[bank].start;
 192                while (ram_check < bd->bi_dram[bank].size) {
 193                        ram_check += get_ram_size((void *)(start + ram_check),
 194                                                 (phys_size_t)SZ_1G);
 195                }
 196                total_ram_check += ram_check;
 197                ram_check = 0;
 198        }
 199
 200        /* If the ram_size is 2GB smaller, we can assume the IO space is
 201         * not mapped in.  gd->ram_size is the actual size of the dram
 202         * not the accessible size.
 203         */
 204        if (total_ram_check != gd->ram_size) {
 205                puts("DDR: SDRAM size check failed!\n");
 206                hang();
 207        }
 208
 209        debug("DDR: SDRAM size check passed!\n");
 210}
 211
 212/**
 213 * sdram_calculate_size() - Calculate SDRAM size
 214 *
 215 * Calculate SDRAM device size based on SDRAM controller parameters.
 216 * Size is specified in bytes.
 217 */
 218phys_size_t sdram_calculate_size(struct altera_sdram_plat *plat)
 219{
 220        u32 dramaddrw = hmc_readl(plat, DRAMADDRW);
 221
 222        phys_size_t size = 1 << (DRAMADDRW_CFG_CS_ADDR_WIDTH(dramaddrw) +
 223                         DRAMADDRW_CFG_BANK_GRP_ADDR_WIDTH(dramaddrw) +
 224                         DRAMADDRW_CFG_BANK_ADDR_WIDTH(dramaddrw) +
 225                         DRAMADDRW_CFG_ROW_ADDR_WIDTH(dramaddrw) +
 226                         DRAMADDRW_CFG_COL_ADDR_WIDTH(dramaddrw));
 227
 228        size *= (2 << (hmc_ecc_readl(plat, DDRIOCTRL) &
 229                        DDR_HMC_DDRIOCTRL_IOSIZE_MSK));
 230
 231        return size;
 232}
 233
 234static int altera_sdram_of_to_plat(struct udevice *dev)
 235{
 236        struct altera_sdram_plat *plat = dev_get_plat(dev);
 237        fdt_addr_t addr;
 238
 239        addr = dev_read_addr_index(dev, 0);
 240        if (addr == FDT_ADDR_T_NONE)
 241                return -EINVAL;
 242        plat->ddr_sch = (void __iomem *)addr;
 243
 244        addr = dev_read_addr_index(dev, 1);
 245        if (addr == FDT_ADDR_T_NONE)
 246                return -EINVAL;
 247        plat->iomhc = (void __iomem *)addr;
 248
 249        addr = dev_read_addr_index(dev, 2);
 250        if (addr == FDT_ADDR_T_NONE)
 251                return -EINVAL;
 252        plat->hmc = (void __iomem *)addr;
 253
 254        return 0;
 255}
 256
 257static int altera_sdram_probe(struct udevice *dev)
 258{
 259        int ret;
 260        struct altera_sdram_priv *priv = dev_get_priv(dev);
 261
 262        ret = reset_get_bulk(dev, &priv->resets);
 263        if (ret) {
 264                dev_err(dev, "Can't get reset: %d\n", ret);
 265                return -ENODEV;
 266        }
 267        reset_deassert_bulk(&priv->resets);
 268
 269        if (sdram_mmr_init_full(dev) != 0) {
 270                puts("SDRAM init failed.\n");
 271                goto failed;
 272        }
 273
 274        return 0;
 275
 276failed:
 277        reset_release_bulk(&priv->resets);
 278        return -ENODEV;
 279}
 280
 281static int altera_sdram_get_info(struct udevice *dev,
 282                                 struct ram_info *info)
 283{
 284        struct altera_sdram_priv *priv = dev_get_priv(dev);
 285
 286        info->base = priv->info.base;
 287        info->size = priv->info.size;
 288
 289        return 0;
 290}
 291
 292static struct ram_ops altera_sdram_ops = {
 293        .get_info = altera_sdram_get_info,
 294};
 295
 296static const struct udevice_id altera_sdram_ids[] = {
 297        { .compatible = "altr,sdr-ctl-s10" },
 298        { .compatible = "intel,sdr-ctl-agilex" },
 299        { /* sentinel */ }
 300};
 301
 302U_BOOT_DRIVER(altera_sdram) = {
 303        .name = "altr_sdr_ctl",
 304        .id = UCLASS_RAM,
 305        .of_match = altera_sdram_ids,
 306        .ops = &altera_sdram_ops,
 307        .of_to_plat = altera_sdram_of_to_plat,
 308        .plat_auto      = sizeof(struct altera_sdram_plat),
 309        .probe = altera_sdram_probe,
 310        .priv_auto      = sizeof(struct altera_sdram_priv),
 311};
 312