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