183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 2193030e5SÁlvaro Fernández Rojas /* 3193030e5SÁlvaro Fernández Rojas * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com> 4193030e5SÁlvaro Fernández Rojas * 5193030e5SÁlvaro Fernández Rojas * Derived from linux/arch/mips/bcm63xx/cpu.c: 6193030e5SÁlvaro Fernández Rojas * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> 7193030e5SÁlvaro Fernández Rojas * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org> 8193030e5SÁlvaro Fernández Rojas */ 9193030e5SÁlvaro Fernández Rojas 10193030e5SÁlvaro Fernández Rojas #include <common.h> 119d922450SSimon Glass #include <dm.h> 12193030e5SÁlvaro Fernández Rojas #include <errno.h> 13193030e5SÁlvaro Fernández Rojas #include <ram.h> 14193030e5SÁlvaro Fernández Rojas #include <asm/io.h> 15193030e5SÁlvaro Fernández Rojas 165a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_REG 0x0 175a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_COL_SHIFT 4 185a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_COL_MASK (0x3 << SDRAM_CFG_COL_SHIFT) 195a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_ROW_SHIFT 6 205a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_ROW_MASK (0x3 << SDRAM_CFG_ROW_SHIFT) 215a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_32B_SHIFT 10 225a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_32B_MASK (1 << SDRAM_CFG_32B_SHIFT) 235a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_BANK_SHIFT 13 245a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_BANK_MASK (1 << SDRAM_CFG_BANK_SHIFT) 25a80bf5e4SÁlvaro Fernández Rojas #define SDRAM_6318_SPACE_SHIFT 4 26a80bf5e4SÁlvaro Fernández Rojas #define SDRAM_6318_SPACE_MASK (0xf << SDRAM_6318_SPACE_SHIFT) 275a0efcf7SÁlvaro Fernández Rojas 28193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_REG 0x4 29193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_32B_SHIFT 1 30193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_32B_MASK (1 << MEMC_CFG_32B_SHIFT) 31193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_COL_SHIFT 3 32193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_COL_MASK (0x3 << MEMC_CFG_COL_SHIFT) 33193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_ROW_SHIFT 6 34193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_ROW_MASK (0x3 << MEMC_CFG_ROW_SHIFT) 35193030e5SÁlvaro Fernández Rojas 36193030e5SÁlvaro Fernández Rojas #define DDR_CSEND_REG 0x8 37193030e5SÁlvaro Fernández Rojas 38193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv; 39193030e5SÁlvaro Fernández Rojas 40193030e5SÁlvaro Fernández Rojas struct bmips_ram_hw { 41193030e5SÁlvaro Fernández Rojas ulong (*get_ram_size)(struct bmips_ram_priv *); 42193030e5SÁlvaro Fernández Rojas }; 43193030e5SÁlvaro Fernández Rojas 44193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv { 45193030e5SÁlvaro Fernández Rojas void __iomem *regs; 46*3e4a68d3SPhilippe Reynes u32 force_size; 47193030e5SÁlvaro Fernández Rojas const struct bmips_ram_hw *hw; 48193030e5SÁlvaro Fernández Rojas }; 49193030e5SÁlvaro Fernández Rojas 50a80bf5e4SÁlvaro Fernández Rojas static ulong bcm6318_get_ram_size(struct bmips_ram_priv *priv) 51a80bf5e4SÁlvaro Fernández Rojas { 52a80bf5e4SÁlvaro Fernández Rojas u32 val; 53a80bf5e4SÁlvaro Fernández Rojas 54a80bf5e4SÁlvaro Fernández Rojas val = readl_be(priv->regs + SDRAM_CFG_REG); 55a80bf5e4SÁlvaro Fernández Rojas val = (val & SDRAM_6318_SPACE_MASK) >> SDRAM_6318_SPACE_SHIFT; 56a80bf5e4SÁlvaro Fernández Rojas 57a80bf5e4SÁlvaro Fernández Rojas return (1 << (val + 20)); 58a80bf5e4SÁlvaro Fernández Rojas } 59a80bf5e4SÁlvaro Fernández Rojas 60193030e5SÁlvaro Fernández Rojas static ulong bcm6328_get_ram_size(struct bmips_ram_priv *priv) 61193030e5SÁlvaro Fernández Rojas { 62193030e5SÁlvaro Fernández Rojas return readl_be(priv->regs + DDR_CSEND_REG) << 24; 63193030e5SÁlvaro Fernández Rojas } 64193030e5SÁlvaro Fernández Rojas 652165961cSÁlvaro Fernández Rojas static ulong bmips_dram_size(unsigned int cols, unsigned int rows, 662165961cSÁlvaro Fernández Rojas unsigned int is_32b, unsigned int banks) 672165961cSÁlvaro Fernández Rojas { 682165961cSÁlvaro Fernández Rojas rows += 11; /* 0 => 11 address bits ... 2 => 13 address bits */ 692165961cSÁlvaro Fernández Rojas cols += 8; /* 0 => 8 address bits ... 2 => 10 address bits */ 702165961cSÁlvaro Fernández Rojas is_32b += 1; 712165961cSÁlvaro Fernández Rojas 722165961cSÁlvaro Fernández Rojas return 1 << (cols + rows + is_32b + banks); 732165961cSÁlvaro Fernández Rojas } 742165961cSÁlvaro Fernández Rojas 755a0efcf7SÁlvaro Fernández Rojas static ulong bcm6338_get_ram_size(struct bmips_ram_priv *priv) 765a0efcf7SÁlvaro Fernández Rojas { 775a0efcf7SÁlvaro Fernández Rojas unsigned int cols = 0, rows = 0, is_32b = 0, banks = 0; 785a0efcf7SÁlvaro Fernández Rojas u32 val; 795a0efcf7SÁlvaro Fernández Rojas 805a0efcf7SÁlvaro Fernández Rojas val = readl_be(priv->regs + SDRAM_CFG_REG); 815a0efcf7SÁlvaro Fernández Rojas rows = (val & SDRAM_CFG_ROW_MASK) >> SDRAM_CFG_ROW_SHIFT; 825a0efcf7SÁlvaro Fernández Rojas cols = (val & SDRAM_CFG_COL_MASK) >> SDRAM_CFG_COL_SHIFT; 835a0efcf7SÁlvaro Fernández Rojas is_32b = (val & SDRAM_CFG_32B_MASK) ? 1 : 0; 845a0efcf7SÁlvaro Fernández Rojas banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1; 855a0efcf7SÁlvaro Fernández Rojas 865a0efcf7SÁlvaro Fernández Rojas return bmips_dram_size(cols, rows, is_32b, banks); 875a0efcf7SÁlvaro Fernández Rojas } 885a0efcf7SÁlvaro Fernández Rojas 89193030e5SÁlvaro Fernández Rojas static ulong bcm6358_get_ram_size(struct bmips_ram_priv *priv) 90193030e5SÁlvaro Fernández Rojas { 912165961cSÁlvaro Fernández Rojas unsigned int cols = 0, rows = 0, is_32b = 0; 92193030e5SÁlvaro Fernández Rojas u32 val; 93193030e5SÁlvaro Fernández Rojas 94193030e5SÁlvaro Fernández Rojas val = readl_be(priv->regs + MEMC_CFG_REG); 95193030e5SÁlvaro Fernández Rojas rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT; 96193030e5SÁlvaro Fernández Rojas cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT; 972165961cSÁlvaro Fernández Rojas is_32b = (val & MEMC_CFG_32B_MASK) ? 0 : 1; 98193030e5SÁlvaro Fernández Rojas 992165961cSÁlvaro Fernández Rojas return bmips_dram_size(cols, rows, is_32b, 2); 100193030e5SÁlvaro Fernández Rojas } 101193030e5SÁlvaro Fernández Rojas 102193030e5SÁlvaro Fernández Rojas static int bmips_ram_get_info(struct udevice *dev, struct ram_info *info) 103193030e5SÁlvaro Fernández Rojas { 104193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv *priv = dev_get_priv(dev); 105193030e5SÁlvaro Fernández Rojas const struct bmips_ram_hw *hw = priv->hw; 106193030e5SÁlvaro Fernández Rojas 107193030e5SÁlvaro Fernández Rojas info->base = 0x80000000; 108*3e4a68d3SPhilippe Reynes if (priv->force_size) 109*3e4a68d3SPhilippe Reynes info->size = priv->force_size; 110*3e4a68d3SPhilippe Reynes else 111193030e5SÁlvaro Fernández Rojas info->size = hw->get_ram_size(priv); 112193030e5SÁlvaro Fernández Rojas 113193030e5SÁlvaro Fernández Rojas return 0; 114193030e5SÁlvaro Fernández Rojas } 115193030e5SÁlvaro Fernández Rojas 116193030e5SÁlvaro Fernández Rojas static const struct ram_ops bmips_ram_ops = { 117193030e5SÁlvaro Fernández Rojas .get_info = bmips_ram_get_info, 118193030e5SÁlvaro Fernández Rojas }; 119193030e5SÁlvaro Fernández Rojas 120a80bf5e4SÁlvaro Fernández Rojas static const struct bmips_ram_hw bmips_ram_bcm6318 = { 121a80bf5e4SÁlvaro Fernández Rojas .get_ram_size = bcm6318_get_ram_size, 122a80bf5e4SÁlvaro Fernández Rojas }; 123a80bf5e4SÁlvaro Fernández Rojas 124193030e5SÁlvaro Fernández Rojas static const struct bmips_ram_hw bmips_ram_bcm6328 = { 125193030e5SÁlvaro Fernández Rojas .get_ram_size = bcm6328_get_ram_size, 126193030e5SÁlvaro Fernández Rojas }; 127193030e5SÁlvaro Fernández Rojas 1285a0efcf7SÁlvaro Fernández Rojas static const struct bmips_ram_hw bmips_ram_bcm6338 = { 1295a0efcf7SÁlvaro Fernández Rojas .get_ram_size = bcm6338_get_ram_size, 1305a0efcf7SÁlvaro Fernández Rojas }; 1315a0efcf7SÁlvaro Fernández Rojas 132193030e5SÁlvaro Fernández Rojas static const struct bmips_ram_hw bmips_ram_bcm6358 = { 133193030e5SÁlvaro Fernández Rojas .get_ram_size = bcm6358_get_ram_size, 134193030e5SÁlvaro Fernández Rojas }; 135193030e5SÁlvaro Fernández Rojas 136193030e5SÁlvaro Fernández Rojas static const struct udevice_id bmips_ram_ids[] = { 137193030e5SÁlvaro Fernández Rojas { 138a80bf5e4SÁlvaro Fernández Rojas .compatible = "brcm,bcm6318-mc", 139a80bf5e4SÁlvaro Fernández Rojas .data = (ulong)&bmips_ram_bcm6318, 140a80bf5e4SÁlvaro Fernández Rojas }, { 141193030e5SÁlvaro Fernández Rojas .compatible = "brcm,bcm6328-mc", 142193030e5SÁlvaro Fernández Rojas .data = (ulong)&bmips_ram_bcm6328, 143193030e5SÁlvaro Fernández Rojas }, { 1445a0efcf7SÁlvaro Fernández Rojas .compatible = "brcm,bcm6338-mc", 1455a0efcf7SÁlvaro Fernández Rojas .data = (ulong)&bmips_ram_bcm6338, 1465a0efcf7SÁlvaro Fernández Rojas }, { 147193030e5SÁlvaro Fernández Rojas .compatible = "brcm,bcm6358-mc", 148193030e5SÁlvaro Fernández Rojas .data = (ulong)&bmips_ram_bcm6358, 149b493a356SÁlvaro Fernández Rojas }, { /* sentinel */ } 150193030e5SÁlvaro Fernández Rojas }; 151193030e5SÁlvaro Fernández Rojas 152193030e5SÁlvaro Fernández Rojas static int bmips_ram_probe(struct udevice *dev) 153193030e5SÁlvaro Fernández Rojas { 154193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv *priv = dev_get_priv(dev); 155193030e5SÁlvaro Fernández Rojas const struct bmips_ram_hw *hw = 156193030e5SÁlvaro Fernández Rojas (const struct bmips_ram_hw *)dev_get_driver_data(dev); 157193030e5SÁlvaro Fernández Rojas 15813a7bfe4SÁlvaro Fernández Rojas priv->regs = dev_remap_addr(dev); 15913a7bfe4SÁlvaro Fernández Rojas if (!priv->regs) 160193030e5SÁlvaro Fernández Rojas return -EINVAL; 161193030e5SÁlvaro Fernández Rojas 162*3e4a68d3SPhilippe Reynes dev_read_u32(dev, "force-size", &priv->force_size); 163*3e4a68d3SPhilippe Reynes 164193030e5SÁlvaro Fernández Rojas priv->hw = hw; 165193030e5SÁlvaro Fernández Rojas 166193030e5SÁlvaro Fernández Rojas return 0; 167193030e5SÁlvaro Fernández Rojas } 168193030e5SÁlvaro Fernández Rojas 169193030e5SÁlvaro Fernández Rojas U_BOOT_DRIVER(bmips_ram) = { 170193030e5SÁlvaro Fernández Rojas .name = "bmips-mc", 171193030e5SÁlvaro Fernández Rojas .id = UCLASS_RAM, 172193030e5SÁlvaro Fernández Rojas .of_match = bmips_ram_ids, 173193030e5SÁlvaro Fernández Rojas .probe = bmips_ram_probe, 174193030e5SÁlvaro Fernández Rojas .priv_auto_alloc_size = sizeof(struct bmips_ram_priv), 175193030e5SÁlvaro Fernández Rojas .ops = &bmips_ram_ops, 176193030e5SÁlvaro Fernández Rojas .flags = DM_FLAG_PRE_RELOC, 177193030e5SÁlvaro Fernández Rojas }; 178