1193030e5SÁlvaro Fernández Rojas /* 2193030e5SÁlvaro Fernández Rojas * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com> 3193030e5SÁlvaro Fernández Rojas * 4193030e5SÁlvaro Fernández Rojas * Derived from linux/arch/mips/bcm63xx/cpu.c: 5193030e5SÁlvaro Fernández Rojas * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> 6193030e5SÁlvaro Fernández Rojas * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org> 7193030e5SÁlvaro Fernández Rojas * 8193030e5SÁlvaro Fernández Rojas * SPDX-License-Identifier: GPL-2.0+ 9193030e5SÁlvaro Fernández Rojas */ 10193030e5SÁlvaro Fernández Rojas 11193030e5SÁlvaro Fernández Rojas #include <common.h> 129d922450SSimon Glass #include <dm.h> 13193030e5SÁlvaro Fernández Rojas #include <errno.h> 14193030e5SÁlvaro Fernández Rojas #include <ram.h> 15193030e5SÁlvaro Fernández Rojas #include <asm/io.h> 16193030e5SÁlvaro Fernández Rojas 175a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_REG 0x0 185a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_COL_SHIFT 4 195a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_COL_MASK (0x3 << SDRAM_CFG_COL_SHIFT) 205a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_ROW_SHIFT 6 215a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_ROW_MASK (0x3 << SDRAM_CFG_ROW_SHIFT) 225a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_32B_SHIFT 10 235a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_32B_MASK (1 << SDRAM_CFG_32B_SHIFT) 245a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_BANK_SHIFT 13 255a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_BANK_MASK (1 << SDRAM_CFG_BANK_SHIFT) 265a0efcf7SÁlvaro Fernández Rojas 27193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_REG 0x4 28193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_32B_SHIFT 1 29193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_32B_MASK (1 << MEMC_CFG_32B_SHIFT) 30193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_COL_SHIFT 3 31193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_COL_MASK (0x3 << MEMC_CFG_COL_SHIFT) 32193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_ROW_SHIFT 6 33193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_ROW_MASK (0x3 << MEMC_CFG_ROW_SHIFT) 34193030e5SÁlvaro Fernández Rojas 35193030e5SÁlvaro Fernández Rojas #define DDR_CSEND_REG 0x8 36193030e5SÁlvaro Fernández Rojas 37193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv; 38193030e5SÁlvaro Fernández Rojas 39193030e5SÁlvaro Fernández Rojas struct bmips_ram_hw { 40193030e5SÁlvaro Fernández Rojas ulong (*get_ram_size)(struct bmips_ram_priv *); 41193030e5SÁlvaro Fernández Rojas }; 42193030e5SÁlvaro Fernández Rojas 43193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv { 44193030e5SÁlvaro Fernández Rojas void __iomem *regs; 45193030e5SÁlvaro Fernández Rojas const struct bmips_ram_hw *hw; 46193030e5SÁlvaro Fernández Rojas }; 47193030e5SÁlvaro Fernández Rojas 48193030e5SÁlvaro Fernández Rojas static ulong bcm6328_get_ram_size(struct bmips_ram_priv *priv) 49193030e5SÁlvaro Fernández Rojas { 50193030e5SÁlvaro Fernández Rojas return readl_be(priv->regs + DDR_CSEND_REG) << 24; 51193030e5SÁlvaro Fernández Rojas } 52193030e5SÁlvaro Fernández Rojas 532165961cSÁlvaro Fernández Rojas static ulong bmips_dram_size(unsigned int cols, unsigned int rows, 542165961cSÁlvaro Fernández Rojas unsigned int is_32b, unsigned int banks) 552165961cSÁlvaro Fernández Rojas { 562165961cSÁlvaro Fernández Rojas rows += 11; /* 0 => 11 address bits ... 2 => 13 address bits */ 572165961cSÁlvaro Fernández Rojas cols += 8; /* 0 => 8 address bits ... 2 => 10 address bits */ 582165961cSÁlvaro Fernández Rojas is_32b += 1; 592165961cSÁlvaro Fernández Rojas 602165961cSÁlvaro Fernández Rojas return 1 << (cols + rows + is_32b + banks); 612165961cSÁlvaro Fernández Rojas } 622165961cSÁlvaro Fernández Rojas 635a0efcf7SÁlvaro Fernández Rojas static ulong bcm6338_get_ram_size(struct bmips_ram_priv *priv) 645a0efcf7SÁlvaro Fernández Rojas { 655a0efcf7SÁlvaro Fernández Rojas unsigned int cols = 0, rows = 0, is_32b = 0, banks = 0; 665a0efcf7SÁlvaro Fernández Rojas u32 val; 675a0efcf7SÁlvaro Fernández Rojas 685a0efcf7SÁlvaro Fernández Rojas val = readl_be(priv->regs + SDRAM_CFG_REG); 695a0efcf7SÁlvaro Fernández Rojas rows = (val & SDRAM_CFG_ROW_MASK) >> SDRAM_CFG_ROW_SHIFT; 705a0efcf7SÁlvaro Fernández Rojas cols = (val & SDRAM_CFG_COL_MASK) >> SDRAM_CFG_COL_SHIFT; 715a0efcf7SÁlvaro Fernández Rojas is_32b = (val & SDRAM_CFG_32B_MASK) ? 1 : 0; 725a0efcf7SÁlvaro Fernández Rojas banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1; 735a0efcf7SÁlvaro Fernández Rojas 745a0efcf7SÁlvaro Fernández Rojas return bmips_dram_size(cols, rows, is_32b, banks); 755a0efcf7SÁlvaro Fernández Rojas } 765a0efcf7SÁlvaro Fernández Rojas 77193030e5SÁlvaro Fernández Rojas static ulong bcm6358_get_ram_size(struct bmips_ram_priv *priv) 78193030e5SÁlvaro Fernández Rojas { 792165961cSÁlvaro Fernández Rojas unsigned int cols = 0, rows = 0, is_32b = 0; 80193030e5SÁlvaro Fernández Rojas u32 val; 81193030e5SÁlvaro Fernández Rojas 82193030e5SÁlvaro Fernández Rojas val = readl_be(priv->regs + MEMC_CFG_REG); 83193030e5SÁlvaro Fernández Rojas rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT; 84193030e5SÁlvaro Fernández Rojas cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT; 852165961cSÁlvaro Fernández Rojas is_32b = (val & MEMC_CFG_32B_MASK) ? 0 : 1; 86193030e5SÁlvaro Fernández Rojas 872165961cSÁlvaro Fernández Rojas return bmips_dram_size(cols, rows, is_32b, 2); 88193030e5SÁlvaro Fernández Rojas } 89193030e5SÁlvaro Fernández Rojas 90193030e5SÁlvaro Fernández Rojas static int bmips_ram_get_info(struct udevice *dev, struct ram_info *info) 91193030e5SÁlvaro Fernández Rojas { 92193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv *priv = dev_get_priv(dev); 93193030e5SÁlvaro Fernández Rojas const struct bmips_ram_hw *hw = priv->hw; 94193030e5SÁlvaro Fernández Rojas 95193030e5SÁlvaro Fernández Rojas info->base = 0x80000000; 96193030e5SÁlvaro Fernández Rojas info->size = hw->get_ram_size(priv); 97193030e5SÁlvaro Fernández Rojas 98193030e5SÁlvaro Fernández Rojas return 0; 99193030e5SÁlvaro Fernández Rojas } 100193030e5SÁlvaro Fernández Rojas 101193030e5SÁlvaro Fernández Rojas static const struct ram_ops bmips_ram_ops = { 102193030e5SÁlvaro Fernández Rojas .get_info = bmips_ram_get_info, 103193030e5SÁlvaro Fernández Rojas }; 104193030e5SÁlvaro Fernández Rojas 105193030e5SÁlvaro Fernández Rojas static const struct bmips_ram_hw bmips_ram_bcm6328 = { 106193030e5SÁlvaro Fernández Rojas .get_ram_size = bcm6328_get_ram_size, 107193030e5SÁlvaro Fernández Rojas }; 108193030e5SÁlvaro Fernández Rojas 1095a0efcf7SÁlvaro Fernández Rojas static const struct bmips_ram_hw bmips_ram_bcm6338 = { 1105a0efcf7SÁlvaro Fernández Rojas .get_ram_size = bcm6338_get_ram_size, 1115a0efcf7SÁlvaro Fernández Rojas }; 1125a0efcf7SÁlvaro Fernández Rojas 113193030e5SÁlvaro Fernández Rojas static const struct bmips_ram_hw bmips_ram_bcm6358 = { 114193030e5SÁlvaro Fernández Rojas .get_ram_size = bcm6358_get_ram_size, 115193030e5SÁlvaro Fernández Rojas }; 116193030e5SÁlvaro Fernández Rojas 117193030e5SÁlvaro Fernández Rojas static const struct udevice_id bmips_ram_ids[] = { 118193030e5SÁlvaro Fernández Rojas { 119193030e5SÁlvaro Fernández Rojas .compatible = "brcm,bcm6328-mc", 120193030e5SÁlvaro Fernández Rojas .data = (ulong)&bmips_ram_bcm6328, 121193030e5SÁlvaro Fernández Rojas }, { 1225a0efcf7SÁlvaro Fernández Rojas .compatible = "brcm,bcm6338-mc", 1235a0efcf7SÁlvaro Fernández Rojas .data = (ulong)&bmips_ram_bcm6338, 1245a0efcf7SÁlvaro Fernández Rojas }, { 125193030e5SÁlvaro Fernández Rojas .compatible = "brcm,bcm6358-mc", 126193030e5SÁlvaro Fernández Rojas .data = (ulong)&bmips_ram_bcm6358, 127b493a356SÁlvaro Fernández Rojas }, { /* sentinel */ } 128193030e5SÁlvaro Fernández Rojas }; 129193030e5SÁlvaro Fernández Rojas 130193030e5SÁlvaro Fernández Rojas static int bmips_ram_probe(struct udevice *dev) 131193030e5SÁlvaro Fernández Rojas { 132193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv *priv = dev_get_priv(dev); 133193030e5SÁlvaro Fernández Rojas const struct bmips_ram_hw *hw = 134193030e5SÁlvaro Fernández Rojas (const struct bmips_ram_hw *)dev_get_driver_data(dev); 135193030e5SÁlvaro Fernández Rojas fdt_addr_t addr; 136193030e5SÁlvaro Fernández Rojas fdt_size_t size; 137193030e5SÁlvaro Fernández Rojas 138*a821c4afSSimon Glass addr = devfdt_get_addr_size_index(dev, 0, &size); 139193030e5SÁlvaro Fernández Rojas if (addr == FDT_ADDR_T_NONE) 140193030e5SÁlvaro Fernández Rojas return -EINVAL; 141193030e5SÁlvaro Fernández Rojas 142193030e5SÁlvaro Fernández Rojas priv->regs = ioremap(addr, size); 143193030e5SÁlvaro Fernández Rojas priv->hw = hw; 144193030e5SÁlvaro Fernández Rojas 145193030e5SÁlvaro Fernández Rojas return 0; 146193030e5SÁlvaro Fernández Rojas } 147193030e5SÁlvaro Fernández Rojas 148193030e5SÁlvaro Fernández Rojas U_BOOT_DRIVER(bmips_ram) = { 149193030e5SÁlvaro Fernández Rojas .name = "bmips-mc", 150193030e5SÁlvaro Fernández Rojas .id = UCLASS_RAM, 151193030e5SÁlvaro Fernández Rojas .of_match = bmips_ram_ids, 152193030e5SÁlvaro Fernández Rojas .probe = bmips_ram_probe, 153193030e5SÁlvaro Fernández Rojas .priv_auto_alloc_size = sizeof(struct bmips_ram_priv), 154193030e5SÁlvaro Fernández Rojas .ops = &bmips_ram_ops, 155193030e5SÁlvaro Fernández Rojas .flags = DM_FLAG_PRE_RELOC, 156193030e5SÁlvaro Fernández Rojas }; 157