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