xref: /openbmc/u-boot/drivers/ram/bmips_ram.c (revision 1d6edcbf)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2193030e5SÁlvaro Fernández Rojas /*
3193030e5SÁlvaro Fernández Rojas  * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
4193030e5SÁlvaro Fernández Rojas  *
5193030e5SÁlvaro Fernández Rojas  * Derived from linux/arch/mips/bcm63xx/cpu.c:
6193030e5SÁlvaro Fernández Rojas  *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
7193030e5SÁlvaro Fernández Rojas  *	Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
8193030e5SÁlvaro Fernández Rojas  */
9193030e5SÁlvaro Fernández Rojas 
10193030e5SÁlvaro Fernández Rojas #include <common.h>
119d922450SSimon Glass #include <dm.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 
165a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_REG		0x0
175a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_COL_SHIFT	4
185a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_COL_MASK	(0x3 << SDRAM_CFG_COL_SHIFT)
195a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_ROW_SHIFT	6
205a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_ROW_MASK	(0x3 << SDRAM_CFG_ROW_SHIFT)
215a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_32B_SHIFT	10
225a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_32B_MASK	(1 << SDRAM_CFG_32B_SHIFT)
235a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_BANK_SHIFT	13
245a0efcf7SÁlvaro Fernández Rojas #define SDRAM_CFG_BANK_MASK	(1 << SDRAM_CFG_BANK_SHIFT)
25a80bf5e4SÁlvaro Fernández Rojas #define SDRAM_6318_SPACE_SHIFT	4
26a80bf5e4SÁlvaro Fernández Rojas #define SDRAM_6318_SPACE_MASK	(0xf << SDRAM_6318_SPACE_SHIFT)
275a0efcf7SÁlvaro Fernández Rojas 
28193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_REG		0x4
29193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_32B_SHIFT	1
30193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_32B_MASK	(1 << MEMC_CFG_32B_SHIFT)
31193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_COL_SHIFT	3
32193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_COL_MASK	(0x3 << MEMC_CFG_COL_SHIFT)
33193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_ROW_SHIFT	6
34193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_ROW_MASK	(0x3 << MEMC_CFG_ROW_SHIFT)
35193030e5SÁlvaro Fernández Rojas 
36193030e5SÁlvaro Fernández Rojas #define DDR_CSEND_REG		0x8
37193030e5SÁlvaro Fernández Rojas 
38193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv;
39193030e5SÁlvaro Fernández Rojas 
40193030e5SÁlvaro Fernández Rojas struct bmips_ram_hw {
41193030e5SÁlvaro Fernández Rojas 	ulong (*get_ram_size)(struct bmips_ram_priv *);
42193030e5SÁlvaro Fernández Rojas };
43193030e5SÁlvaro Fernández Rojas 
44193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv {
45193030e5SÁlvaro Fernández Rojas 	void __iomem *regs;
46*3e4a68d3SPhilippe Reynes 	u32 force_size;
47193030e5SÁlvaro Fernández Rojas 	const struct bmips_ram_hw *hw;
48193030e5SÁlvaro Fernández Rojas };
49193030e5SÁlvaro Fernández Rojas 
bcm6318_get_ram_size(struct bmips_ram_priv * priv)50a80bf5e4SÁlvaro Fernández Rojas static ulong bcm6318_get_ram_size(struct bmips_ram_priv *priv)
51a80bf5e4SÁlvaro Fernández Rojas {
52a80bf5e4SÁlvaro Fernández Rojas 	u32 val;
53a80bf5e4SÁlvaro Fernández Rojas 
54a80bf5e4SÁlvaro Fernández Rojas 	val = readl_be(priv->regs + SDRAM_CFG_REG);
55a80bf5e4SÁlvaro Fernández Rojas 	val = (val & SDRAM_6318_SPACE_MASK) >> SDRAM_6318_SPACE_SHIFT;
56a80bf5e4SÁlvaro Fernández Rojas 
57a80bf5e4SÁlvaro Fernández Rojas 	return (1 << (val + 20));
58a80bf5e4SÁlvaro Fernández Rojas }
59a80bf5e4SÁlvaro Fernández Rojas 
bcm6328_get_ram_size(struct bmips_ram_priv * priv)60193030e5SÁlvaro Fernández Rojas static ulong bcm6328_get_ram_size(struct bmips_ram_priv *priv)
61193030e5SÁlvaro Fernández Rojas {
62193030e5SÁlvaro Fernández Rojas 	return readl_be(priv->regs + DDR_CSEND_REG) << 24;
63193030e5SÁlvaro Fernández Rojas }
64193030e5SÁlvaro Fernández Rojas 
bmips_dram_size(unsigned int cols,unsigned int rows,unsigned int is_32b,unsigned int banks)652165961cSÁlvaro Fernández Rojas static ulong bmips_dram_size(unsigned int cols, unsigned int rows,
662165961cSÁlvaro Fernández Rojas 			     unsigned int is_32b, unsigned int banks)
672165961cSÁlvaro Fernández Rojas {
682165961cSÁlvaro Fernández Rojas 	rows += 11; /* 0 => 11 address bits ... 2 => 13 address bits */
692165961cSÁlvaro Fernández Rojas 	cols += 8; /* 0 => 8 address bits ... 2 => 10 address bits */
702165961cSÁlvaro Fernández Rojas 	is_32b += 1;
712165961cSÁlvaro Fernández Rojas 
722165961cSÁlvaro Fernández Rojas 	return 1 << (cols + rows + is_32b + banks);
732165961cSÁlvaro Fernández Rojas }
742165961cSÁlvaro Fernández Rojas 
bcm6338_get_ram_size(struct bmips_ram_priv * priv)755a0efcf7SÁlvaro Fernández Rojas static ulong bcm6338_get_ram_size(struct bmips_ram_priv *priv)
765a0efcf7SÁlvaro Fernández Rojas {
775a0efcf7SÁlvaro Fernández Rojas 	unsigned int cols = 0, rows = 0, is_32b = 0, banks = 0;
785a0efcf7SÁlvaro Fernández Rojas 	u32 val;
795a0efcf7SÁlvaro Fernández Rojas 
805a0efcf7SÁlvaro Fernández Rojas 	val = readl_be(priv->regs + SDRAM_CFG_REG);
815a0efcf7SÁlvaro Fernández Rojas 	rows = (val & SDRAM_CFG_ROW_MASK) >> SDRAM_CFG_ROW_SHIFT;
825a0efcf7SÁlvaro Fernández Rojas 	cols = (val & SDRAM_CFG_COL_MASK) >> SDRAM_CFG_COL_SHIFT;
835a0efcf7SÁlvaro Fernández Rojas 	is_32b = (val & SDRAM_CFG_32B_MASK) ? 1 : 0;
845a0efcf7SÁlvaro Fernández Rojas 	banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1;
855a0efcf7SÁlvaro Fernández Rojas 
865a0efcf7SÁlvaro Fernández Rojas 	return bmips_dram_size(cols, rows, is_32b, banks);
875a0efcf7SÁlvaro Fernández Rojas }
885a0efcf7SÁlvaro Fernández Rojas 
bcm6358_get_ram_size(struct bmips_ram_priv * priv)89193030e5SÁlvaro Fernández Rojas static ulong bcm6358_get_ram_size(struct bmips_ram_priv *priv)
90193030e5SÁlvaro Fernández Rojas {
912165961cSÁlvaro Fernández Rojas 	unsigned int cols = 0, rows = 0, is_32b = 0;
92193030e5SÁlvaro Fernández Rojas 	u32 val;
93193030e5SÁlvaro Fernández Rojas 
94193030e5SÁlvaro Fernández Rojas 	val = readl_be(priv->regs + MEMC_CFG_REG);
95193030e5SÁlvaro Fernández Rojas 	rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT;
96193030e5SÁlvaro Fernández Rojas 	cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT;
972165961cSÁlvaro Fernández Rojas 	is_32b = (val & MEMC_CFG_32B_MASK) ? 0 : 1;
98193030e5SÁlvaro Fernández Rojas 
992165961cSÁlvaro Fernández Rojas 	return bmips_dram_size(cols, rows, is_32b, 2);
100193030e5SÁlvaro Fernández Rojas }
101193030e5SÁlvaro Fernández Rojas 
bmips_ram_get_info(struct udevice * dev,struct ram_info * info)102193030e5SÁlvaro Fernández Rojas static int bmips_ram_get_info(struct udevice *dev, struct ram_info *info)
103193030e5SÁlvaro Fernández Rojas {
104193030e5SÁlvaro Fernández Rojas 	struct bmips_ram_priv *priv = dev_get_priv(dev);
105193030e5SÁlvaro Fernández Rojas 	const struct bmips_ram_hw *hw = priv->hw;
106193030e5SÁlvaro Fernández Rojas 
107193030e5SÁlvaro Fernández Rojas 	info->base = 0x80000000;
108*3e4a68d3SPhilippe Reynes 	if (priv->force_size)
109*3e4a68d3SPhilippe Reynes 		info->size = priv->force_size;
110*3e4a68d3SPhilippe Reynes 	else
111193030e5SÁlvaro Fernández Rojas 		info->size = hw->get_ram_size(priv);
112193030e5SÁlvaro Fernández Rojas 
113193030e5SÁlvaro Fernández Rojas 	return 0;
114193030e5SÁlvaro Fernández Rojas }
115193030e5SÁlvaro Fernández Rojas 
116193030e5SÁlvaro Fernández Rojas static const struct ram_ops bmips_ram_ops = {
117193030e5SÁlvaro Fernández Rojas 	.get_info = bmips_ram_get_info,
118193030e5SÁlvaro Fernández Rojas };
119193030e5SÁlvaro Fernández Rojas 
120a80bf5e4SÁlvaro Fernández Rojas static const struct bmips_ram_hw bmips_ram_bcm6318 = {
121a80bf5e4SÁlvaro Fernández Rojas 	.get_ram_size = bcm6318_get_ram_size,
122a80bf5e4SÁlvaro Fernández Rojas };
123a80bf5e4SÁlvaro Fernández Rojas 
124193030e5SÁlvaro Fernández Rojas static const struct bmips_ram_hw bmips_ram_bcm6328 = {
125193030e5SÁlvaro Fernández Rojas 	.get_ram_size = bcm6328_get_ram_size,
126193030e5SÁlvaro Fernández Rojas };
127193030e5SÁlvaro Fernández Rojas 
1285a0efcf7SÁlvaro Fernández Rojas static const struct bmips_ram_hw bmips_ram_bcm6338 = {
1295a0efcf7SÁlvaro Fernández Rojas 	.get_ram_size = bcm6338_get_ram_size,
1305a0efcf7SÁlvaro Fernández Rojas };
1315a0efcf7SÁlvaro Fernández Rojas 
132193030e5SÁlvaro Fernández Rojas static const struct bmips_ram_hw bmips_ram_bcm6358 = {
133193030e5SÁlvaro Fernández Rojas 	.get_ram_size = bcm6358_get_ram_size,
134193030e5SÁlvaro Fernández Rojas };
135193030e5SÁlvaro Fernández Rojas 
136193030e5SÁlvaro Fernández Rojas static const struct udevice_id bmips_ram_ids[] = {
137193030e5SÁlvaro Fernández Rojas 	{
138a80bf5e4SÁlvaro Fernández Rojas 		.compatible = "brcm,bcm6318-mc",
139a80bf5e4SÁlvaro Fernández Rojas 		.data = (ulong)&bmips_ram_bcm6318,
140a80bf5e4SÁlvaro Fernández Rojas 	}, {
141193030e5SÁlvaro Fernández Rojas 		.compatible = "brcm,bcm6328-mc",
142193030e5SÁlvaro Fernández Rojas 		.data = (ulong)&bmips_ram_bcm6328,
143193030e5SÁlvaro Fernández Rojas 	}, {
1445a0efcf7SÁlvaro Fernández Rojas 		.compatible = "brcm,bcm6338-mc",
1455a0efcf7SÁlvaro Fernández Rojas 		.data = (ulong)&bmips_ram_bcm6338,
1465a0efcf7SÁlvaro Fernández Rojas 	}, {
147193030e5SÁlvaro Fernández Rojas 		.compatible = "brcm,bcm6358-mc",
148193030e5SÁlvaro Fernández Rojas 		.data = (ulong)&bmips_ram_bcm6358,
149b493a356SÁlvaro Fernández Rojas 	}, { /* sentinel */ }
150193030e5SÁlvaro Fernández Rojas };
151193030e5SÁlvaro Fernández Rojas 
bmips_ram_probe(struct udevice * dev)152193030e5SÁlvaro Fernández Rojas static int bmips_ram_probe(struct udevice *dev)
153193030e5SÁlvaro Fernández Rojas {
154193030e5SÁlvaro Fernández Rojas 	struct bmips_ram_priv *priv = dev_get_priv(dev);
155193030e5SÁlvaro Fernández Rojas 	const struct bmips_ram_hw *hw =
156193030e5SÁlvaro Fernández Rojas 		(const struct bmips_ram_hw *)dev_get_driver_data(dev);
157193030e5SÁlvaro Fernández Rojas 
15813a7bfe4SÁlvaro Fernández Rojas 	priv->regs = dev_remap_addr(dev);
15913a7bfe4SÁlvaro Fernández Rojas 	if (!priv->regs)
160193030e5SÁlvaro Fernández Rojas 		return -EINVAL;
161193030e5SÁlvaro Fernández Rojas 
162*3e4a68d3SPhilippe Reynes 	dev_read_u32(dev, "force-size", &priv->force_size);
163*3e4a68d3SPhilippe Reynes 
164193030e5SÁlvaro Fernández Rojas 	priv->hw = hw;
165193030e5SÁlvaro Fernández Rojas 
166193030e5SÁlvaro Fernández Rojas 	return 0;
167193030e5SÁlvaro Fernández Rojas }
168193030e5SÁlvaro Fernández Rojas 
169193030e5SÁlvaro Fernández Rojas U_BOOT_DRIVER(bmips_ram) = {
170193030e5SÁlvaro Fernández Rojas 	.name = "bmips-mc",
171193030e5SÁlvaro Fernández Rojas 	.id = UCLASS_RAM,
172193030e5SÁlvaro Fernández Rojas 	.of_match = bmips_ram_ids,
173193030e5SÁlvaro Fernández Rojas 	.probe = bmips_ram_probe,
174193030e5SÁlvaro Fernández Rojas 	.priv_auto_alloc_size = sizeof(struct bmips_ram_priv),
175193030e5SÁlvaro Fernández Rojas 	.ops = &bmips_ram_ops,
176193030e5SÁlvaro Fernández Rojas };
177