aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/memory
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/memory')
-rw-r--r--drivers/memory/Kconfig10
-rw-r--r--drivers/memory/Makefile1
-rw-r--r--drivers/memory/mvebu-devbus.c340
-rw-r--r--drivers/memory/tegra20-mc.c5
-rw-r--r--drivers/memory/tegra30-mc.c9
5 files changed, 361 insertions, 4 deletions
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 067f31174a0e..29a11db365bc 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -20,6 +20,16 @@ config TI_EMIF
20 parameters and other settings during frequency, voltage and 20 parameters and other settings during frequency, voltage and
21 temperature changes 21 temperature changes
22 22
23config MVEBU_DEVBUS
24 bool "Marvell EBU Device Bus Controller"
25 default y
26 depends on PLAT_ORION && OF
27 help
28 This driver is for the Device Bus controller available in some
29 Marvell EBU SoCs such as Discovery (mv78xx0), Orion (88f5xxx) and
30 Armada 370 and Armada XP. This controller allows to handle flash
31 devices such as NOR, NAND, SRAM, and FPGA.
32
23config TEGRA20_MC 33config TEGRA20_MC
24 bool "Tegra20 Memory Controller(MC) driver" 34 bool "Tegra20 Memory Controller(MC) driver"
25 default y 35 default y
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 9cce5d70ed52..969d923dad93 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -6,5 +6,6 @@ ifeq ($(CONFIG_DDR),y)
6obj-$(CONFIG_OF) += of_memory.o 6obj-$(CONFIG_OF) += of_memory.o
7endif 7endif
8obj-$(CONFIG_TI_EMIF) += emif.o 8obj-$(CONFIG_TI_EMIF) += emif.o
9obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o
9obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o 10obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o
10obj-$(CONFIG_TEGRA30_MC) += tegra30-mc.o 11obj-$(CONFIG_TEGRA30_MC) += tegra30-mc.o
diff --git a/drivers/memory/mvebu-devbus.c b/drivers/memory/mvebu-devbus.c
new file mode 100644
index 000000000000..978e8e3abc5c
--- /dev/null
+++ b/drivers/memory/mvebu-devbus.c
@@ -0,0 +1,340 @@
1/*
2 * Marvell EBU SoC Device Bus Controller
3 * (memory controller for NOR/NAND/SRAM/FPGA devices)
4 *
5 * Copyright (C) 2013 Marvell
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/slab.h>
24#include <linux/err.h>
25#include <linux/io.h>
26#include <linux/clk.h>
27#include <linux/mbus.h>
28#include <linux/of_platform.h>
29#include <linux/of_address.h>
30#include <linux/platform_device.h>
31
32/* Register definitions */
33#define DEV_WIDTH_BIT 30
34#define BADR_SKEW_BIT 28
35#define RD_HOLD_BIT 23
36#define ACC_NEXT_BIT 17
37#define RD_SETUP_BIT 12
38#define ACC_FIRST_BIT 6
39
40#define SYNC_ENABLE_BIT 24
41#define WR_HIGH_BIT 16
42#define WR_LOW_BIT 8
43
44#define READ_PARAM_OFFSET 0x0
45#define WRITE_PARAM_OFFSET 0x4
46
47static const char * const devbus_wins[] = {
48 "devbus-boot",
49 "devbus-cs0",
50 "devbus-cs1",
51 "devbus-cs2",
52 "devbus-cs3",
53};
54
55struct devbus_read_params {
56 u32 bus_width;
57 u32 badr_skew;
58 u32 turn_off;
59 u32 acc_first;
60 u32 acc_next;
61 u32 rd_setup;
62 u32 rd_hold;
63};
64
65struct devbus_write_params {
66 u32 sync_enable;
67 u32 wr_high;
68 u32 wr_low;
69 u32 ale_wr;
70};
71
72struct devbus {
73 struct device *dev;
74 void __iomem *base;
75 unsigned long tick_ps;
76};
77
78static int get_timing_param_ps(struct devbus *devbus,
79 struct device_node *node,
80 const char *name,
81 u32 *ticks)
82{
83 u32 time_ps;
84 int err;
85
86 err = of_property_read_u32(node, name, &time_ps);
87 if (err < 0) {
88 dev_err(devbus->dev, "%s has no '%s' property\n",
89 name, node->full_name);
90 return err;
91 }
92
93 *ticks = (time_ps + devbus->tick_ps - 1) / devbus->tick_ps;
94
95 dev_dbg(devbus->dev, "%s: %u ps -> 0x%x\n",
96 name, time_ps, *ticks);
97 return 0;
98}
99
100static int devbus_set_timing_params(struct devbus *devbus,
101 struct device_node *node)
102{
103 struct devbus_read_params r;
104 struct devbus_write_params w;
105 u32 value;
106 int err;
107
108 dev_dbg(devbus->dev, "Setting timing parameter, tick is %lu ps\n",
109 devbus->tick_ps);
110
111 /* Get read timings */
112 err = of_property_read_u32(node, "devbus,bus-width", &r.bus_width);
113 if (err < 0) {
114 dev_err(devbus->dev,
115 "%s has no 'devbus,bus-width' property\n",
116 node->full_name);
117 return err;
118 }
119 /* Convert bit width to byte width */
120 r.bus_width /= 8;
121
122 err = get_timing_param_ps(devbus, node, "devbus,badr-skew-ps",
123 &r.badr_skew);
124 if (err < 0)
125 return err;
126
127 err = get_timing_param_ps(devbus, node, "devbus,turn-off-ps",
128 &r.turn_off);
129 if (err < 0)
130 return err;
131
132 err = get_timing_param_ps(devbus, node, "devbus,acc-first-ps",
133 &r.acc_first);
134 if (err < 0)
135 return err;
136
137 err = get_timing_param_ps(devbus, node, "devbus,acc-next-ps",
138 &r.acc_next);
139 if (err < 0)
140 return err;
141
142 err = get_timing_param_ps(devbus, node, "devbus,rd-setup-ps",
143 &r.rd_setup);
144 if (err < 0)
145 return err;
146
147 err = get_timing_param_ps(devbus, node, "devbus,rd-hold-ps",
148 &r.rd_hold);
149 if (err < 0)
150 return err;
151
152 /* Get write timings */
153 err = of_property_read_u32(node, "devbus,sync-enable",
154 &w.sync_enable);
155 if (err < 0) {
156 dev_err(devbus->dev,
157 "%s has no 'devbus,sync-enable' property\n",
158 node->full_name);
159 return err;
160 }
161
162 err = get_timing_param_ps(devbus, node, "devbus,ale-wr-ps",
163 &w.ale_wr);
164 if (err < 0)
165 return err;
166
167 err = get_timing_param_ps(devbus, node, "devbus,wr-low-ps",
168 &w.wr_low);
169 if (err < 0)
170 return err;
171
172 err = get_timing_param_ps(devbus, node, "devbus,wr-high-ps",
173 &w.wr_high);
174 if (err < 0)
175 return err;
176
177 /* Set read timings */
178 value = r.bus_width << DEV_WIDTH_BIT |
179 r.badr_skew << BADR_SKEW_BIT |
180 r.rd_hold << RD_HOLD_BIT |
181 r.acc_next << ACC_NEXT_BIT |
182 r.rd_setup << RD_SETUP_BIT |
183 r.acc_first << ACC_FIRST_BIT |
184 r.turn_off;
185
186 dev_dbg(devbus->dev, "read parameters register 0x%p = 0x%x\n",
187 devbus->base + READ_PARAM_OFFSET,
188 value);
189
190 writel(value, devbus->base + READ_PARAM_OFFSET);
191
192 /* Set write timings */
193 value = w.sync_enable << SYNC_ENABLE_BIT |
194 w.wr_low << WR_LOW_BIT |
195 w.wr_high << WR_HIGH_BIT |
196 w.ale_wr;
197
198 dev_dbg(devbus->dev, "write parameters register: 0x%p = 0x%x\n",
199 devbus->base + WRITE_PARAM_OFFSET,
200 value);
201
202 writel(value, devbus->base + WRITE_PARAM_OFFSET);
203
204 return 0;
205}
206
207static int mvebu_devbus_probe(struct platform_device *pdev)
208{
209 struct device *dev = &pdev->dev;
210 struct device_node *node = pdev->dev.of_node;
211 struct device_node *parent;
212 struct devbus *devbus;
213 struct resource *res;
214 struct clk *clk;
215 unsigned long rate;
216 const __be32 *ranges;
217 int err, cs;
218 int addr_cells, p_addr_cells, size_cells;
219 int ranges_len, tuple_len;
220 u32 base, size;
221
222 devbus = devm_kzalloc(&pdev->dev, sizeof(struct devbus), GFP_KERNEL);
223 if (!devbus)
224 return -ENOMEM;
225
226 devbus->dev = dev;
227 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
228 devbus->base = devm_ioremap_resource(&pdev->dev, res);
229 if (IS_ERR(devbus->base))
230 return PTR_ERR(devbus->base);
231
232 clk = devm_clk_get(&pdev->dev, NULL);
233 if (IS_ERR(clk))
234 return PTR_ERR(clk);
235 clk_prepare_enable(clk);
236
237 /*
238 * Obtain clock period in picoseconds,
239 * we need this in order to convert timing
240 * parameters from cycles to picoseconds.
241 */
242 rate = clk_get_rate(clk) / 1000;
243 devbus->tick_ps = 1000000000 / rate;
244
245 /* Read the device tree node and set the new timing parameters */
246 err = devbus_set_timing_params(devbus, node);
247 if (err < 0)
248 return err;
249
250 /*
251 * Allocate an address window for this device.
252 * If the device probing fails, then we won't be able to
253 * remove the allocated address decoding window.
254 *
255 * FIXME: This is only a temporary hack! We need to do this here
256 * because we still don't have device tree bindings for mbus.
257 * Once that support is added, we will declare these address windows
258 * statically in the device tree, and remove the window configuration
259 * from here.
260 */
261
262 /*
263 * Get the CS to choose the window string.
264 * This is a bit hacky, but it will be removed once the
265 * address windows are declared in the device tree.
266 */
267 cs = (((unsigned long)devbus->base) % 0x400) / 8;
268
269 /*
270 * Parse 'ranges' property to obtain a (base,size) window tuple.
271 * This will be removed once the address windows
272 * are declared in the device tree.
273 */
274 parent = of_get_parent(node);
275 if (!parent)
276 return -EINVAL;
277
278 p_addr_cells = of_n_addr_cells(parent);
279 of_node_put(parent);
280
281 addr_cells = of_n_addr_cells(node);
282 size_cells = of_n_size_cells(node);
283 tuple_len = (p_addr_cells + addr_cells + size_cells) * sizeof(__be32);
284
285 ranges = of_get_property(node, "ranges", &ranges_len);
286 if (ranges == NULL || ranges_len != tuple_len)
287 return -EINVAL;
288
289 base = of_translate_address(node, ranges + addr_cells);
290 if (base == OF_BAD_ADDR)
291 return -EINVAL;
292 size = of_read_number(ranges + addr_cells + p_addr_cells, size_cells);
293
294 /*
295 * Create an mbus address windows.
296 * FIXME: Remove this, together with the above code, once the
297 * address windows are declared in the device tree.
298 */
299 err = mvebu_mbus_add_window(devbus_wins[cs], base, size);
300 if (err < 0)
301 return err;
302
303 /*
304 * We need to create a child device explicitly from here to
305 * guarantee that the child will be probed after the timing
306 * parameters for the bus are written.
307 */
308 err = of_platform_populate(node, NULL, NULL, dev);
309 if (err < 0) {
310 mvebu_mbus_del_window(base, size);
311 return err;
312 }
313
314 return 0;
315}
316
317static const struct of_device_id mvebu_devbus_of_match[] = {
318 { .compatible = "marvell,mvebu-devbus" },
319 {},
320};
321MODULE_DEVICE_TABLE(of, mvebu_devbus_of_match);
322
323static struct platform_driver mvebu_devbus_driver = {
324 .probe = mvebu_devbus_probe,
325 .driver = {
326 .name = "mvebu-devbus",
327 .owner = THIS_MODULE,
328 .of_match_table = mvebu_devbus_of_match,
329 },
330};
331
332static int __init mvebu_devbus_init(void)
333{
334 return platform_driver_register(&mvebu_devbus_driver);
335}
336module_init(mvebu_devbus_init);
337
338MODULE_LICENSE("GPL v2");
339MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
340MODULE_DESCRIPTION("Marvell EBU SoC Device Bus controller");
diff --git a/drivers/memory/tegra20-mc.c b/drivers/memory/tegra20-mc.c
index 2ca5f2814f4a..0548eeacd573 100644
--- a/drivers/memory/tegra20-mc.c
+++ b/drivers/memory/tegra20-mc.c
@@ -193,8 +193,11 @@ static irqreturn_t tegra20_mc_isr(int irq, void *data)
193 mask &= stat; 193 mask &= stat;
194 if (!mask) 194 if (!mask)
195 return IRQ_NONE; 195 return IRQ_NONE;
196 while ((bit = ffs(mask)) != 0) 196 while ((bit = ffs(mask)) != 0) {
197 tegra20_mc_decode(mc, bit - 1); 197 tegra20_mc_decode(mc, bit - 1);
198 mask &= ~BIT(bit - 1);
199 }
200
198 mc_writel(mc, stat, MC_INTSTATUS); 201 mc_writel(mc, stat, MC_INTSTATUS);
199 return IRQ_HANDLED; 202 return IRQ_HANDLED;
200} 203}
diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c
index f4ae074badc3..58d2979b4035 100644
--- a/drivers/memory/tegra30-mc.c
+++ b/drivers/memory/tegra30-mc.c
@@ -218,7 +218,7 @@ static void tegra30_mc_decode(struct tegra30_mc *mc, int n)
218 return; 218 return;
219 } 219 }
220 220
221 err = readl(mc + MC_ERR_STATUS); 221 err = mc_readl(mc, MC_ERR_STATUS);
222 222
223 type = (err & MC_ERR_TYPE_MASK) >> MC_ERR_TYPE_SHIFT; 223 type = (err & MC_ERR_TYPE_MASK) >> MC_ERR_TYPE_SHIFT;
224 perm = (err & MC_ERR_INVALID_SMMU_PAGE_MASK) >> 224 perm = (err & MC_ERR_INVALID_SMMU_PAGE_MASK) >>
@@ -235,7 +235,7 @@ static void tegra30_mc_decode(struct tegra30_mc *mc, int n)
235 if (cid < ARRAY_SIZE(tegra30_mc_client)) 235 if (cid < ARRAY_SIZE(tegra30_mc_client))
236 client = tegra30_mc_client[cid]; 236 client = tegra30_mc_client[cid];
237 237
238 addr = readl(mc + MC_ERR_ADR); 238 addr = mc_readl(mc, MC_ERR_ADR);
239 239
240 dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s %s %s)\n", 240 dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s %s %s)\n",
241 mc_int_err[idx], err, addr, client, 241 mc_int_err[idx], err, addr, client,
@@ -313,8 +313,11 @@ static irqreturn_t tegra30_mc_isr(int irq, void *data)
313 mask &= stat; 313 mask &= stat;
314 if (!mask) 314 if (!mask)
315 return IRQ_NONE; 315 return IRQ_NONE;
316 while ((bit = ffs(mask)) != 0) 316 while ((bit = ffs(mask)) != 0) {
317 tegra30_mc_decode(mc, bit - 1); 317 tegra30_mc_decode(mc, bit - 1);
318 mask &= ~BIT(bit - 1);
319 }
320
318 mc_writel(mc, stat, MC_INTSTATUS); 321 mc_writel(mc, stat, MC_INTSTATUS);
319 return IRQ_HANDLED; 322 return IRQ_HANDLED;
320} 323}