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