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
bcm6328_get_ram_size(struct bmips_ram_priv * priv)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
bmips_dram_size(unsigned int cols,unsigned int rows,unsigned int is_32b,unsigned int banks)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
bcm6338_get_ram_size(struct bmips_ram_priv * priv)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
bcm6358_get_ram_size(struct bmips_ram_priv * priv)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
bmips_ram_get_info(struct udevice * dev,struct ram_info * info)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
bmips_ram_probe(struct udevice * dev)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