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> 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 #include <dm/device.h> 16193030e5SÁlvaro Fernández Rojas 17193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_REG 0x4 18193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_32B_SHIFT 1 19193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_32B_MASK (1 << MEMC_CFG_32B_SHIFT) 20193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_COL_SHIFT 3 21193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_COL_MASK (0x3 << MEMC_CFG_COL_SHIFT) 22193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_ROW_SHIFT 6 23193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_ROW_MASK (0x3 << MEMC_CFG_ROW_SHIFT) 24193030e5SÁlvaro Fernández Rojas 25193030e5SÁlvaro Fernández Rojas #define DDR_CSEND_REG 0x8 26193030e5SÁlvaro Fernández Rojas 27193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv; 28193030e5SÁlvaro Fernández Rojas 29193030e5SÁlvaro Fernández Rojas struct bmips_ram_hw { 30193030e5SÁlvaro Fernández Rojas ulong (*get_ram_size)(struct bmips_ram_priv *); 31193030e5SÁlvaro Fernández Rojas }; 32193030e5SÁlvaro Fernández Rojas 33193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv { 34193030e5SÁlvaro Fernández Rojas void __iomem *regs; 35193030e5SÁlvaro Fernández Rojas const struct bmips_ram_hw *hw; 36193030e5SÁlvaro Fernández Rojas }; 37193030e5SÁlvaro Fernández Rojas 38193030e5SÁlvaro Fernández Rojas static ulong bcm6328_get_ram_size(struct bmips_ram_priv *priv) 39193030e5SÁlvaro Fernández Rojas { 40193030e5SÁlvaro Fernández Rojas return readl_be(priv->regs + DDR_CSEND_REG) << 24; 41193030e5SÁlvaro Fernández Rojas } 42193030e5SÁlvaro Fernández Rojas 43*2165961cSÁlvaro Fernández Rojas static ulong bmips_dram_size(unsigned int cols, unsigned int rows, 44*2165961cSÁlvaro Fernández Rojas unsigned int is_32b, unsigned int banks) 45*2165961cSÁlvaro Fernández Rojas { 46*2165961cSÁlvaro Fernández Rojas rows += 11; /* 0 => 11 address bits ... 2 => 13 address bits */ 47*2165961cSÁlvaro Fernández Rojas cols += 8; /* 0 => 8 address bits ... 2 => 10 address bits */ 48*2165961cSÁlvaro Fernández Rojas is_32b += 1; 49*2165961cSÁlvaro Fernández Rojas 50*2165961cSÁlvaro Fernández Rojas return 1 << (cols + rows + is_32b + banks); 51*2165961cSÁlvaro Fernández Rojas } 52*2165961cSÁlvaro Fernández Rojas 53193030e5SÁlvaro Fernández Rojas static ulong bcm6358_get_ram_size(struct bmips_ram_priv *priv) 54193030e5SÁlvaro Fernández Rojas { 55*2165961cSÁlvaro Fernández Rojas unsigned int cols = 0, rows = 0, is_32b = 0; 56193030e5SÁlvaro Fernández Rojas u32 val; 57193030e5SÁlvaro Fernández Rojas 58193030e5SÁlvaro Fernández Rojas val = readl_be(priv->regs + MEMC_CFG_REG); 59193030e5SÁlvaro Fernández Rojas rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT; 60193030e5SÁlvaro Fernández Rojas cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT; 61*2165961cSÁlvaro Fernández Rojas is_32b = (val & MEMC_CFG_32B_MASK) ? 0 : 1; 62193030e5SÁlvaro Fernández Rojas 63*2165961cSÁlvaro Fernández Rojas return bmips_dram_size(cols, rows, is_32b, 2); 64193030e5SÁlvaro Fernández Rojas } 65193030e5SÁlvaro Fernández Rojas 66193030e5SÁlvaro Fernández Rojas static int bmips_ram_get_info(struct udevice *dev, struct ram_info *info) 67193030e5SÁlvaro Fernández Rojas { 68193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv *priv = dev_get_priv(dev); 69193030e5SÁlvaro Fernández Rojas const struct bmips_ram_hw *hw = priv->hw; 70193030e5SÁlvaro Fernández Rojas 71193030e5SÁlvaro Fernández Rojas info->base = 0x80000000; 72193030e5SÁlvaro Fernández Rojas info->size = hw->get_ram_size(priv); 73193030e5SÁlvaro Fernández Rojas 74193030e5SÁlvaro Fernández Rojas return 0; 75193030e5SÁlvaro Fernández Rojas } 76193030e5SÁlvaro Fernández Rojas 77193030e5SÁlvaro Fernández Rojas static const struct ram_ops bmips_ram_ops = { 78193030e5SÁlvaro Fernández Rojas .get_info = bmips_ram_get_info, 79193030e5SÁlvaro Fernández Rojas }; 80193030e5SÁlvaro Fernández Rojas 81193030e5SÁlvaro Fernández Rojas static const struct bmips_ram_hw bmips_ram_bcm6328 = { 82193030e5SÁlvaro Fernández Rojas .get_ram_size = bcm6328_get_ram_size, 83193030e5SÁlvaro Fernández Rojas }; 84193030e5SÁlvaro Fernández Rojas 85193030e5SÁlvaro Fernández Rojas static const struct bmips_ram_hw bmips_ram_bcm6358 = { 86193030e5SÁlvaro Fernández Rojas .get_ram_size = bcm6358_get_ram_size, 87193030e5SÁlvaro Fernández Rojas }; 88193030e5SÁlvaro Fernández Rojas 89193030e5SÁlvaro Fernández Rojas static const struct udevice_id bmips_ram_ids[] = { 90193030e5SÁlvaro Fernández Rojas { 91193030e5SÁlvaro Fernández Rojas .compatible = "brcm,bcm6328-mc", 92193030e5SÁlvaro Fernández Rojas .data = (ulong)&bmips_ram_bcm6328, 93193030e5SÁlvaro Fernández Rojas }, { 94193030e5SÁlvaro Fernández Rojas .compatible = "brcm,bcm6358-mc", 95193030e5SÁlvaro Fernández Rojas .data = (ulong)&bmips_ram_bcm6358, 96b493a356SÁlvaro Fernández Rojas }, { /* sentinel */ } 97193030e5SÁlvaro Fernández Rojas }; 98193030e5SÁlvaro Fernández Rojas 99193030e5SÁlvaro Fernández Rojas static int bmips_ram_probe(struct udevice *dev) 100193030e5SÁlvaro Fernández Rojas { 101193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv *priv = dev_get_priv(dev); 102193030e5SÁlvaro Fernández Rojas const struct bmips_ram_hw *hw = 103193030e5SÁlvaro Fernández Rojas (const struct bmips_ram_hw *)dev_get_driver_data(dev); 104193030e5SÁlvaro Fernández Rojas fdt_addr_t addr; 105193030e5SÁlvaro Fernández Rojas fdt_size_t size; 106193030e5SÁlvaro Fernández Rojas 107193030e5SÁlvaro Fernández Rojas addr = dev_get_addr_size_index(dev, 0, &size); 108193030e5SÁlvaro Fernández Rojas if (addr == FDT_ADDR_T_NONE) 109193030e5SÁlvaro Fernández Rojas return -EINVAL; 110193030e5SÁlvaro Fernández Rojas 111193030e5SÁlvaro Fernández Rojas priv->regs = ioremap(addr, size); 112193030e5SÁlvaro Fernández Rojas priv->hw = hw; 113193030e5SÁlvaro Fernández Rojas 114193030e5SÁlvaro Fernández Rojas return 0; 115193030e5SÁlvaro Fernández Rojas } 116193030e5SÁlvaro Fernández Rojas 117193030e5SÁlvaro Fernández Rojas U_BOOT_DRIVER(bmips_ram) = { 118193030e5SÁlvaro Fernández Rojas .name = "bmips-mc", 119193030e5SÁlvaro Fernández Rojas .id = UCLASS_RAM, 120193030e5SÁlvaro Fernández Rojas .of_match = bmips_ram_ids, 121193030e5SÁlvaro Fernández Rojas .probe = bmips_ram_probe, 122193030e5SÁlvaro Fernández Rojas .priv_auto_alloc_size = sizeof(struct bmips_ram_priv), 123193030e5SÁlvaro Fernández Rojas .ops = &bmips_ram_ops, 124193030e5SÁlvaro Fernández Rojas .flags = DM_FLAG_PRE_RELOC, 125193030e5SÁlvaro Fernández Rojas }; 126