uboot/drivers/ram/bmips_ram.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
   3 *
   4 * Derived from linux/arch/mips/bcm63xx/cpu.c:
   5 *      Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
   6 *      Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11#include <common.h>
  12#include <dm.h>
  13#include <errno.h>
  14#include <ram.h>
  15#include <asm/io.h>
  16
  17#define SDRAM_CFG_REG           0x0
  18#define SDRAM_CFG_COL_SHIFT     4
  19#define SDRAM_CFG_COL_MASK      (0x3 << SDRAM_CFG_COL_SHIFT)
  20#define SDRAM_CFG_ROW_SHIFT     6
  21#define SDRAM_CFG_ROW_MASK      (0x3 << SDRAM_CFG_ROW_SHIFT)
  22#define SDRAM_CFG_32B_SHIFT     10
  23#define SDRAM_CFG_32B_MASK      (1 << SDRAM_CFG_32B_SHIFT)
  24#define SDRAM_CFG_BANK_SHIFT    13
  25#define SDRAM_CFG_BANK_MASK     (1 << SDRAM_CFG_BANK_SHIFT)
  26
  27#define MEMC_CFG_REG            0x4
  28#define MEMC_CFG_32B_SHIFT      1
  29#define MEMC_CFG_32B_MASK       (1 << MEMC_CFG_32B_SHIFT)
  30#define MEMC_CFG_COL_SHIFT      3
  31#define MEMC_CFG_COL_MASK       (0x3 << MEMC_CFG_COL_SHIFT)
  32#define MEMC_CFG_ROW_SHIFT      6
  33#define MEMC_CFG_ROW_MASK       (0x3 << MEMC_CFG_ROW_SHIFT)
  34
  35#define DDR_CSEND_REG           0x8
  36
  37struct bmips_ram_priv;
  38
  39struct bmips_ram_hw {
  40        ulong (*get_ram_size)(struct bmips_ram_priv *);
  41};
  42
  43struct bmips_ram_priv {
  44        void __iomem *regs;
  45        const struct bmips_ram_hw *hw;
  46};
  47
  48static ulong bcm6328_get_ram_size(struct bmips_ram_priv *priv)
  49{
  50        return readl_be(priv->regs + DDR_CSEND_REG) << 24;
  51}
  52
  53static ulong bmips_dram_size(unsigned int cols, unsigned int rows,
  54                             unsigned int is_32b, unsigned int banks)
  55{
  56        rows += 11; /* 0 => 11 address bits ... 2 => 13 address bits */
  57        cols += 8; /* 0 => 8 address bits ... 2 => 10 address bits */
  58        is_32b += 1;
  59
  60        return 1 << (cols + rows + is_32b + banks);
  61}
  62
  63static ulong bcm6338_get_ram_size(struct bmips_ram_priv *priv)
  64{
  65        unsigned int cols = 0, rows = 0, is_32b = 0, banks = 0;
  66        u32 val;
  67
  68        val = readl_be(priv->regs + SDRAM_CFG_REG);
  69        rows = (val & SDRAM_CFG_ROW_MASK) >> SDRAM_CFG_ROW_SHIFT;
  70        cols = (val & SDRAM_CFG_COL_MASK) >> SDRAM_CFG_COL_SHIFT;
  71        is_32b = (val & SDRAM_CFG_32B_MASK) ? 1 : 0;
  72        banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1;
  73
  74        return bmips_dram_size(cols, rows, is_32b, banks);
  75}
  76
  77static ulong bcm6358_get_ram_size(struct bmips_ram_priv *priv)
  78{
  79        unsigned int cols = 0, rows = 0, is_32b = 0;
  80        u32 val;
  81
  82        val = readl_be(priv->regs + MEMC_CFG_REG);
  83        rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT;
  84        cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT;
  85        is_32b = (val & MEMC_CFG_32B_MASK) ? 0 : 1;
  86
  87        return bmips_dram_size(cols, rows, is_32b, 2);
  88}
  89
  90static int bmips_ram_get_info(struct udevice *dev, struct ram_info *info)
  91{
  92        struct bmips_ram_priv *priv = dev_get_priv(dev);
  93        const struct bmips_ram_hw *hw = priv->hw;
  94
  95        info->base = 0x80000000;
  96        info->size = hw->get_ram_size(priv);
  97
  98        return 0;
  99}
 100
 101static const struct ram_ops bmips_ram_ops = {
 102        .get_info = bmips_ram_get_info,
 103};
 104
 105static const struct bmips_ram_hw bmips_ram_bcm6328 = {
 106        .get_ram_size = bcm6328_get_ram_size,
 107};
 108
 109static const struct bmips_ram_hw bmips_ram_bcm6338 = {
 110        .get_ram_size = bcm6338_get_ram_size,
 111};
 112
 113static const struct bmips_ram_hw bmips_ram_bcm6358 = {
 114        .get_ram_size = bcm6358_get_ram_size,
 115};
 116
 117static const struct udevice_id bmips_ram_ids[] = {
 118        {
 119                .compatible = "brcm,bcm6328-mc",
 120                .data = (ulong)&bmips_ram_bcm6328,
 121        }, {
 122                .compatible = "brcm,bcm6338-mc",
 123                .data = (ulong)&bmips_ram_bcm6338,
 124        }, {
 125                .compatible = "brcm,bcm6358-mc",
 126                .data = (ulong)&bmips_ram_bcm6358,
 127        }, { /* sentinel */ }
 128};
 129
 130static int bmips_ram_probe(struct udevice *dev)
 131{
 132        struct bmips_ram_priv *priv = dev_get_priv(dev);
 133        const struct bmips_ram_hw *hw =
 134                (const struct bmips_ram_hw *)dev_get_driver_data(dev);
 135        fdt_addr_t addr;
 136        fdt_size_t size;
 137
 138        addr = devfdt_get_addr_size_index(dev, 0, &size);
 139        if (addr == FDT_ADDR_T_NONE)
 140                return -EINVAL;
 141
 142        priv->regs = ioremap(addr, size);
 143        priv->hw = hw;
 144
 145        return 0;
 146}
 147
 148U_BOOT_DRIVER(bmips_ram) = {
 149        .name = "bmips-mc",
 150        .id = UCLASS_RAM,
 151        .of_match = bmips_ram_ids,
 152        .probe = bmips_ram_probe,
 153        .priv_auto_alloc_size = sizeof(struct bmips_ram_priv),
 154        .ops = &bmips_ram_ops,
 155        .flags = DM_FLAG_PRE_RELOC,
 156};
 157