Home | History | Annotate | Download | only in ram
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright (C) 2017 lvaro Fernndez Rojas <noltari (at) gmail.com>
      4  *
      5  * Derived from linux/arch/mips/bcm63xx/cpu.c:
      6  *	Copyright (C) 2008 Maxime Bizon <mbizon (at) freebox.fr>
      7  *	Copyright (C) 2009 Florian Fainelli <florian (at) openwrt.org>
      8  */
      9 
     10 #include <common.h>
     11 #include <dm.h>
     12 #include <errno.h>
     13 #include <ram.h>
     14 #include <asm/io.h>
     15 
     16 #define SDRAM_CFG_REG		0x0
     17 #define SDRAM_CFG_COL_SHIFT	4
     18 #define SDRAM_CFG_COL_MASK	(0x3 << SDRAM_CFG_COL_SHIFT)
     19 #define SDRAM_CFG_ROW_SHIFT	6
     20 #define SDRAM_CFG_ROW_MASK	(0x3 << SDRAM_CFG_ROW_SHIFT)
     21 #define SDRAM_CFG_32B_SHIFT	10
     22 #define SDRAM_CFG_32B_MASK	(1 << SDRAM_CFG_32B_SHIFT)
     23 #define SDRAM_CFG_BANK_SHIFT	13
     24 #define SDRAM_CFG_BANK_MASK	(1 << SDRAM_CFG_BANK_SHIFT)
     25 #define SDRAM_6318_SPACE_SHIFT	4
     26 #define SDRAM_6318_SPACE_MASK	(0xf << SDRAM_6318_SPACE_SHIFT)
     27 
     28 #define MEMC_CFG_REG		0x4
     29 #define MEMC_CFG_32B_SHIFT	1
     30 #define MEMC_CFG_32B_MASK	(1 << MEMC_CFG_32B_SHIFT)
     31 #define MEMC_CFG_COL_SHIFT	3
     32 #define MEMC_CFG_COL_MASK	(0x3 << MEMC_CFG_COL_SHIFT)
     33 #define MEMC_CFG_ROW_SHIFT	6
     34 #define MEMC_CFG_ROW_MASK	(0x3 << MEMC_CFG_ROW_SHIFT)
     35 
     36 #define DDR_CSEND_REG		0x8
     37 
     38 struct bmips_ram_priv;
     39 
     40 struct bmips_ram_hw {
     41 	ulong (*get_ram_size)(struct bmips_ram_priv *);
     42 };
     43 
     44 struct bmips_ram_priv {
     45 	void __iomem *regs;
     46 	const struct bmips_ram_hw *hw;
     47 };
     48 
     49 static ulong bcm6318_get_ram_size(struct bmips_ram_priv *priv)
     50 {
     51 	u32 val;
     52 
     53 	val = readl_be(priv->regs + SDRAM_CFG_REG);
     54 	val = (val & SDRAM_6318_SPACE_MASK) >> SDRAM_6318_SPACE_SHIFT;
     55 
     56 	return (1 << (val + 20));
     57 }
     58 
     59 static ulong bcm6328_get_ram_size(struct bmips_ram_priv *priv)
     60 {
     61 	return readl_be(priv->regs + DDR_CSEND_REG) << 24;
     62 }
     63 
     64 static ulong bmips_dram_size(unsigned int cols, unsigned int rows,
     65 			     unsigned int is_32b, unsigned int banks)
     66 {
     67 	rows += 11; /* 0 => 11 address bits ... 2 => 13 address bits */
     68 	cols += 8; /* 0 => 8 address bits ... 2 => 10 address bits */
     69 	is_32b += 1;
     70 
     71 	return 1 << (cols + rows + is_32b + banks);
     72 }
     73 
     74 static ulong bcm6338_get_ram_size(struct bmips_ram_priv *priv)
     75 {
     76 	unsigned int cols = 0, rows = 0, is_32b = 0, banks = 0;
     77 	u32 val;
     78 
     79 	val = readl_be(priv->regs + SDRAM_CFG_REG);
     80 	rows = (val & SDRAM_CFG_ROW_MASK) >> SDRAM_CFG_ROW_SHIFT;
     81 	cols = (val & SDRAM_CFG_COL_MASK) >> SDRAM_CFG_COL_SHIFT;
     82 	is_32b = (val & SDRAM_CFG_32B_MASK) ? 1 : 0;
     83 	banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1;
     84 
     85 	return bmips_dram_size(cols, rows, is_32b, banks);
     86 }
     87 
     88 static ulong bcm6358_get_ram_size(struct bmips_ram_priv *priv)
     89 {
     90 	unsigned int cols = 0, rows = 0, is_32b = 0;
     91 	u32 val;
     92 
     93 	val = readl_be(priv->regs + MEMC_CFG_REG);
     94 	rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT;
     95 	cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT;
     96 	is_32b = (val & MEMC_CFG_32B_MASK) ? 0 : 1;
     97 
     98 	return bmips_dram_size(cols, rows, is_32b, 2);
     99 }
    100 
    101 static int bmips_ram_get_info(struct udevice *dev, struct ram_info *info)
    102 {
    103 	struct bmips_ram_priv *priv = dev_get_priv(dev);
    104 	const struct bmips_ram_hw *hw = priv->hw;
    105 
    106 	info->base = 0x80000000;
    107 	info->size = hw->get_ram_size(priv);
    108 
    109 	return 0;
    110 }
    111 
    112 static const struct ram_ops bmips_ram_ops = {
    113 	.get_info = bmips_ram_get_info,
    114 };
    115 
    116 static const struct bmips_ram_hw bmips_ram_bcm6318 = {
    117 	.get_ram_size = bcm6318_get_ram_size,
    118 };
    119 
    120 static const struct bmips_ram_hw bmips_ram_bcm6328 = {
    121 	.get_ram_size = bcm6328_get_ram_size,
    122 };
    123 
    124 static const struct bmips_ram_hw bmips_ram_bcm6338 = {
    125 	.get_ram_size = bcm6338_get_ram_size,
    126 };
    127 
    128 static const struct bmips_ram_hw bmips_ram_bcm6358 = {
    129 	.get_ram_size = bcm6358_get_ram_size,
    130 };
    131 
    132 static const struct udevice_id bmips_ram_ids[] = {
    133 	{
    134 		.compatible = "brcm,bcm6318-mc",
    135 		.data = (ulong)&bmips_ram_bcm6318,
    136 	}, {
    137 		.compatible = "brcm,bcm6328-mc",
    138 		.data = (ulong)&bmips_ram_bcm6328,
    139 	}, {
    140 		.compatible = "brcm,bcm6338-mc",
    141 		.data = (ulong)&bmips_ram_bcm6338,
    142 	}, {
    143 		.compatible = "brcm,bcm6358-mc",
    144 		.data = (ulong)&bmips_ram_bcm6358,
    145 	}, { /* sentinel */ }
    146 };
    147 
    148 static int bmips_ram_probe(struct udevice *dev)
    149 {
    150 	struct bmips_ram_priv *priv = dev_get_priv(dev);
    151 	const struct bmips_ram_hw *hw =
    152 		(const struct bmips_ram_hw *)dev_get_driver_data(dev);
    153 
    154 	priv->regs = dev_remap_addr(dev);
    155 	if (!priv->regs)
    156 		return -EINVAL;
    157 
    158 	priv->hw = hw;
    159 
    160 	return 0;
    161 }
    162 
    163 U_BOOT_DRIVER(bmips_ram) = {
    164 	.name = "bmips-mc",
    165 	.id = UCLASS_RAM,
    166 	.of_match = bmips_ram_ids,
    167 	.probe = bmips_ram_probe,
    168 	.priv_auto_alloc_size = sizeof(struct bmips_ram_priv),
    169 	.ops = &bmips_ram_ops,
    170 	.flags = DM_FLAG_PRE_RELOC,
    171 };
    172