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