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