xref: /openbmc/u-boot/drivers/ram/bmips_ram.c (revision 2165961c)
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>
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 #include <dm/device.h>
16193030e5SÁlvaro Fernández Rojas 
17193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_REG		0x4
18193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_32B_SHIFT	1
19193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_32B_MASK	(1 << MEMC_CFG_32B_SHIFT)
20193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_COL_SHIFT	3
21193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_COL_MASK	(0x3 << MEMC_CFG_COL_SHIFT)
22193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_ROW_SHIFT	6
23193030e5SÁlvaro Fernández Rojas #define MEMC_CFG_ROW_MASK	(0x3 << MEMC_CFG_ROW_SHIFT)
24193030e5SÁlvaro Fernández Rojas 
25193030e5SÁlvaro Fernández Rojas #define DDR_CSEND_REG		0x8
26193030e5SÁlvaro Fernández Rojas 
27193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv;
28193030e5SÁlvaro Fernández Rojas 
29193030e5SÁlvaro Fernández Rojas struct bmips_ram_hw {
30193030e5SÁlvaro Fernández Rojas 	ulong (*get_ram_size)(struct bmips_ram_priv *);
31193030e5SÁlvaro Fernández Rojas };
32193030e5SÁlvaro Fernández Rojas 
33193030e5SÁlvaro Fernández Rojas struct bmips_ram_priv {
34193030e5SÁlvaro Fernández Rojas 	void __iomem *regs;
35193030e5SÁlvaro Fernández Rojas 	const struct bmips_ram_hw *hw;
36193030e5SÁlvaro Fernández Rojas };
37193030e5SÁlvaro Fernández Rojas 
38193030e5SÁlvaro Fernández Rojas static ulong bcm6328_get_ram_size(struct bmips_ram_priv *priv)
39193030e5SÁlvaro Fernández Rojas {
40193030e5SÁlvaro Fernández Rojas 	return readl_be(priv->regs + DDR_CSEND_REG) << 24;
41193030e5SÁlvaro Fernández Rojas }
42193030e5SÁlvaro Fernández Rojas 
43*2165961cSÁlvaro Fernández Rojas static ulong bmips_dram_size(unsigned int cols, unsigned int rows,
44*2165961cSÁlvaro Fernández Rojas 			     unsigned int is_32b, unsigned int banks)
45*2165961cSÁlvaro Fernández Rojas {
46*2165961cSÁlvaro Fernández Rojas 	rows += 11; /* 0 => 11 address bits ... 2 => 13 address bits */
47*2165961cSÁlvaro Fernández Rojas 	cols += 8; /* 0 => 8 address bits ... 2 => 10 address bits */
48*2165961cSÁlvaro Fernández Rojas 	is_32b += 1;
49*2165961cSÁlvaro Fernández Rojas 
50*2165961cSÁlvaro Fernández Rojas 	return 1 << (cols + rows + is_32b + banks);
51*2165961cSÁlvaro Fernández Rojas }
52*2165961cSÁlvaro Fernández Rojas 
53193030e5SÁlvaro Fernández Rojas static ulong bcm6358_get_ram_size(struct bmips_ram_priv *priv)
54193030e5SÁlvaro Fernández Rojas {
55*2165961cSÁlvaro Fernández Rojas 	unsigned int cols = 0, rows = 0, is_32b = 0;
56193030e5SÁlvaro Fernández Rojas 	u32 val;
57193030e5SÁlvaro Fernández Rojas 
58193030e5SÁlvaro Fernández Rojas 	val = readl_be(priv->regs + MEMC_CFG_REG);
59193030e5SÁlvaro Fernández Rojas 	rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT;
60193030e5SÁlvaro Fernández Rojas 	cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT;
61*2165961cSÁlvaro Fernández Rojas 	is_32b = (val & MEMC_CFG_32B_MASK) ? 0 : 1;
62193030e5SÁlvaro Fernández Rojas 
63*2165961cSÁlvaro Fernández Rojas 	return bmips_dram_size(cols, rows, is_32b, 2);
64193030e5SÁlvaro Fernández Rojas }
65193030e5SÁlvaro Fernández Rojas 
66193030e5SÁlvaro Fernández Rojas static int bmips_ram_get_info(struct udevice *dev, struct ram_info *info)
67193030e5SÁlvaro Fernández Rojas {
68193030e5SÁlvaro Fernández Rojas 	struct bmips_ram_priv *priv = dev_get_priv(dev);
69193030e5SÁlvaro Fernández Rojas 	const struct bmips_ram_hw *hw = priv->hw;
70193030e5SÁlvaro Fernández Rojas 
71193030e5SÁlvaro Fernández Rojas 	info->base = 0x80000000;
72193030e5SÁlvaro Fernández Rojas 	info->size = hw->get_ram_size(priv);
73193030e5SÁlvaro Fernández Rojas 
74193030e5SÁlvaro Fernández Rojas 	return 0;
75193030e5SÁlvaro Fernández Rojas }
76193030e5SÁlvaro Fernández Rojas 
77193030e5SÁlvaro Fernández Rojas static const struct ram_ops bmips_ram_ops = {
78193030e5SÁlvaro Fernández Rojas 	.get_info = bmips_ram_get_info,
79193030e5SÁlvaro Fernández Rojas };
80193030e5SÁlvaro Fernández Rojas 
81193030e5SÁlvaro Fernández Rojas static const struct bmips_ram_hw bmips_ram_bcm6328 = {
82193030e5SÁlvaro Fernández Rojas 	.get_ram_size = bcm6328_get_ram_size,
83193030e5SÁlvaro Fernández Rojas };
84193030e5SÁlvaro Fernández Rojas 
85193030e5SÁlvaro Fernández Rojas static const struct bmips_ram_hw bmips_ram_bcm6358 = {
86193030e5SÁlvaro Fernández Rojas 	.get_ram_size = bcm6358_get_ram_size,
87193030e5SÁlvaro Fernández Rojas };
88193030e5SÁlvaro Fernández Rojas 
89193030e5SÁlvaro Fernández Rojas static const struct udevice_id bmips_ram_ids[] = {
90193030e5SÁlvaro Fernández Rojas 	{
91193030e5SÁlvaro Fernández Rojas 		.compatible = "brcm,bcm6328-mc",
92193030e5SÁlvaro Fernández Rojas 		.data = (ulong)&bmips_ram_bcm6328,
93193030e5SÁlvaro Fernández Rojas 	}, {
94193030e5SÁlvaro Fernández Rojas 		.compatible = "brcm,bcm6358-mc",
95193030e5SÁlvaro Fernández Rojas 		.data = (ulong)&bmips_ram_bcm6358,
96b493a356SÁlvaro Fernández Rojas 	}, { /* sentinel */ }
97193030e5SÁlvaro Fernández Rojas };
98193030e5SÁlvaro Fernández Rojas 
99193030e5SÁlvaro Fernández Rojas static int bmips_ram_probe(struct udevice *dev)
100193030e5SÁlvaro Fernández Rojas {
101193030e5SÁlvaro Fernández Rojas 	struct bmips_ram_priv *priv = dev_get_priv(dev);
102193030e5SÁlvaro Fernández Rojas 	const struct bmips_ram_hw *hw =
103193030e5SÁlvaro Fernández Rojas 		(const struct bmips_ram_hw *)dev_get_driver_data(dev);
104193030e5SÁlvaro Fernández Rojas 	fdt_addr_t addr;
105193030e5SÁlvaro Fernández Rojas 	fdt_size_t size;
106193030e5SÁlvaro Fernández Rojas 
107193030e5SÁlvaro Fernández Rojas 	addr = dev_get_addr_size_index(dev, 0, &size);
108193030e5SÁlvaro Fernández Rojas 	if (addr == FDT_ADDR_T_NONE)
109193030e5SÁlvaro Fernández Rojas 		return -EINVAL;
110193030e5SÁlvaro Fernández Rojas 
111193030e5SÁlvaro Fernández Rojas 	priv->regs = ioremap(addr, size);
112193030e5SÁlvaro Fernández Rojas 	priv->hw = hw;
113193030e5SÁlvaro Fernández Rojas 
114193030e5SÁlvaro Fernández Rojas 	return 0;
115193030e5SÁlvaro Fernández Rojas }
116193030e5SÁlvaro Fernández Rojas 
117193030e5SÁlvaro Fernández Rojas U_BOOT_DRIVER(bmips_ram) = {
118193030e5SÁlvaro Fernández Rojas 	.name = "bmips-mc",
119193030e5SÁlvaro Fernández Rojas 	.id = UCLASS_RAM,
120193030e5SÁlvaro Fernández Rojas 	.of_match = bmips_ram_ids,
121193030e5SÁlvaro Fernández Rojas 	.probe = bmips_ram_probe,
122193030e5SÁlvaro Fernández Rojas 	.priv_auto_alloc_size = sizeof(struct bmips_ram_priv),
123193030e5SÁlvaro Fernández Rojas 	.ops = &bmips_ram_ops,
124193030e5SÁlvaro Fernández Rojas 	.flags = DM_FLAG_PRE_RELOC,
125193030e5SÁlvaro Fernández Rojas };
126