5f00e9f36e7a3161f90dc008a716e55801674e8b
[openwrt/staging/lynxis/omap.git] / target / linux / mvebu / patches-3.10 / 0013-drivers-memory-Introduce-Marvell-EBU-Device-Bus-driv.patch
1 From 8b417cc752ac4158dcfcf02beafce80b90fd827d Mon Sep 17 00:00:00 2001
2 From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
3 Date: Tue, 23 Apr 2013 16:21:26 -0300
4 Subject: [PATCH 013/203] drivers: memory: Introduce Marvell EBU Device Bus
5 driver
6
7 Marvell EBU SoCs such as Armada 370/XP, Orion5x (88f5xxx) and
8 Discovery (mv78xx0) supports a Device Bus controller to access several
9 kinds of memories and I/O devices (NOR, NAND, SRAM, FPGA).
10
11 This commit adds a driver to handle this controller. So far only
12 Armada 370, Armada XP and Discovery SoCs are supported.
13
14 The driver must be registered through a device tree node;
15 as explained in the binding document.
16
17 For each child node in the device tree, this driver will:
18 * set timing parameters
19 * register a child device
20 * setup an address decoding window, using the mbus driver
21
22 Keep in mind the address decoding window setup is only a temporary hack.
23 This code will be removed from this devbus driver as soon as a proper device
24 tree binding for the mbus driver is added.
25
26 Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
27 Acked-by: Arnd Bergmann <arnd@arndb.de>
28 Acked-by: Jason Cooper <jason@lakedaemon.net>
29 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
30 ---
31 .../bindings/memory-controllers/mvebu-devbus.txt | 156 ++++++++++
32 drivers/memory/Kconfig | 10 +
33 drivers/memory/Makefile | 1 +
34 drivers/memory/mvebu-devbus.c | 340 +++++++++++++++++++++
35 4 files changed, 507 insertions(+)
36 create mode 100644 Documentation/devicetree/bindings/memory-controllers/mvebu-devbus.txt
37 create mode 100644 drivers/memory/mvebu-devbus.c
38
39 --- /dev/null
40 +++ b/Documentation/devicetree/bindings/memory-controllers/mvebu-devbus.txt
41 @@ -0,0 +1,156 @@
42 +Device tree bindings for MVEBU Device Bus controllers
43 +
44 +The Device Bus controller available in some Marvell's SoC allows to control
45 +different types of standard memory and I/O devices such as NOR, NAND, and FPGA.
46 +The actual devices are instantiated from the child nodes of a Device Bus node.
47 +
48 +Required properties:
49 +
50 + - compatible: Currently only Armada 370/XP SoC are supported,
51 + with this compatible string:
52 +
53 + marvell,mvebu-devbus
54 +
55 + - reg: A resource specifier for the register space.
56 + This is the base address of a chip select within
57 + the controller's register space.
58 + (see the example below)
59 +
60 + - #address-cells: Must be set to 1
61 + - #size-cells: Must be set to 1
62 + - ranges: Must be set up to reflect the memory layout with four
63 + integer values for each chip-select line in use:
64 + 0 <physical address of mapping> <size>
65 +
66 +Mandatory timing properties for child nodes:
67 +
68 +Read parameters:
69 +
70 + - devbus,turn-off-ps: Defines the time during which the controller does not
71 + drive the AD bus after the completion of a device read.
72 + This prevents contentions on the Device Bus after a read
73 + cycle from a slow device.
74 +
75 + - devbus,bus-width: Defines the bus width (e.g. <16>)
76 +
77 + - devbus,badr-skew-ps: Defines the time delay from from A[2:0] toggle,
78 + to read data sample. This parameter is useful for
79 + synchronous pipelined devices, where the address
80 + precedes the read data by one or two cycles.
81 +
82 + - devbus,acc-first-ps: Defines the time delay from the negation of
83 + ALE[0] to the cycle that the first read data is sampled
84 + by the controller.
85 +
86 + - devbus,acc-next-ps: Defines the time delay between the cycle that
87 + samples data N and the cycle that samples data N+1
88 + (in burst accesses).
89 +
90 + - devbus,rd-setup-ps: Defines the time delay between DEV_CSn assertion to
91 + DEV_OEn assertion. If set to 0 (default),
92 + DEV_OEn and DEV_CSn are asserted at the same cycle.
93 + This parameter has no affect on <acc-first-ps> parameter
94 + (no affect on first data sample). Set <rd-setup-ps>
95 + to a value smaller than <acc-first-ps>.
96 +
97 + - devbus,rd-hold-ps: Defines the time between the last data sample to the
98 + de-assertion of DEV_CSn. If set to 0 (default),
99 + DEV_OEn and DEV_CSn are de-asserted at the same cycle
100 + (the cycle of the last data sample).
101 + This parameter has no affect on DEV_OEn de-assertion.
102 + DEV_OEn is always de-asserted the next cycle after
103 + last data sampled. Also this parameter has no
104 + affect on <turn-off-ps> parameter.
105 + Set <rd-hold-ps> to a value smaller than <turn-off-ps>.
106 +
107 +Write parameters:
108 +
109 + - devbus,ale-wr-ps: Defines the time delay from the ALE[0] negation cycle
110 + to the DEV_WEn assertion.
111 +
112 + - devbus,wr-low-ps: Defines the time during which DEV_WEn is active.
113 + A[2:0] and Data are kept valid as long as DEV_WEn
114 + is active. This parameter defines the setup time of
115 + address and data to DEV_WEn rise.
116 +
117 + - devbus,wr-high-ps: Defines the time during which DEV_WEn is kept
118 + inactive (high) between data beats of a burst write.
119 + DEV_A[2:0] and Data are kept valid (do not toggle) for
120 + <wr-high-ps> - <tick> ps.
121 + This parameter defines the hold time of address and
122 + data after DEV_WEn rise.
123 +
124 + - devbus,sync-enable: Synchronous device enable.
125 + 1: True
126 + 0: False
127 +
128 +An example for an Armada XP GP board, with a 16 MiB NOR device as child
129 +is showed below. Note that the Device Bus driver is in charge of allocating
130 +the mbus address decoding window for each of its child devices.
131 +The window is created using the chip select specified in the child
132 +device node together with the base address and size specified in the ranges
133 +property. For instance, in the example below the allocated decoding window
134 +will start at base address 0xf0000000, with a size 0x1000000 (16 MiB)
135 +for chip select 0 (a.k.a DEV_BOOTCS).
136 +
137 +This address window handling is done in this mvebu-devbus only as a temporary
138 +solution. It will be removed when the support for mbus device tree binding is
139 +added.
140 +
141 +The reg property implicitly specifies the chip select as this:
142 +
143 + 0x10400: DEV_BOOTCS
144 + 0x10408: DEV_CS0
145 + 0x10410: DEV_CS1
146 + 0x10418: DEV_CS2
147 + 0x10420: DEV_CS3
148 +
149 +Example:
150 +
151 + devbus-bootcs@d0010400 {
152 + status = "okay";
153 + ranges = <0 0xf0000000 0x1000000>; /* @addr 0xf0000000, size 0x1000000 */
154 + #address-cells = <1>;
155 + #size-cells = <1>;
156 +
157 + /* Device Bus parameters are required */
158 +
159 + /* Read parameters */
160 + devbus,bus-width = <8>;
161 + devbus,turn-off-ps = <60000>;
162 + devbus,badr-skew-ps = <0>;
163 + devbus,acc-first-ps = <124000>;
164 + devbus,acc-next-ps = <248000>;
165 + devbus,rd-setup-ps = <0>;
166 + devbus,rd-hold-ps = <0>;
167 +
168 + /* Write parameters */
169 + devbus,sync-enable = <0>;
170 + devbus,wr-high-ps = <60000>;
171 + devbus,wr-low-ps = <60000>;
172 + devbus,ale-wr-ps = <60000>;
173 +
174 + flash@0 {
175 + compatible = "cfi-flash";
176 +
177 + /* 16 MiB */
178 + reg = <0 0x1000000>;
179 + bank-width = <2>;
180 + #address-cells = <1>;
181 + #size-cells = <1>;
182 +
183 + /*
184 + * We split the 16 MiB in two partitions,
185 + * just as an example.
186 + */
187 + partition@0 {
188 + label = "First";
189 + reg = <0 0x800000>;
190 + };
191 +
192 + partition@800000 {
193 + label = "Second";
194 + reg = <0x800000 0x800000>;
195 + };
196 + };
197 + };
198 --- a/drivers/memory/Kconfig
199 +++ b/drivers/memory/Kconfig
200 @@ -20,6 +20,16 @@ config TI_EMIF
201 parameters and other settings during frequency, voltage and
202 temperature changes
203
204 +config MVEBU_DEVBUS
205 + bool "Marvell EBU Device Bus Controller"
206 + default y
207 + depends on PLAT_ORION && OF
208 + help
209 + This driver is for the Device Bus controller available in some
210 + Marvell EBU SoCs such as Discovery (mv78xx0), Orion (88f5xxx) and
211 + Armada 370 and Armada XP. This controller allows to handle flash
212 + devices such as NOR, NAND, SRAM, and FPGA.
213 +
214 config TEGRA20_MC
215 bool "Tegra20 Memory Controller(MC) driver"
216 default y
217 --- a/drivers/memory/Makefile
218 +++ b/drivers/memory/Makefile
219 @@ -6,5 +6,6 @@ ifeq ($(CONFIG_DDR),y)
220 obj-$(CONFIG_OF) += of_memory.o
221 endif
222 obj-$(CONFIG_TI_EMIF) += emif.o
223 +obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o
224 obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o
225 obj-$(CONFIG_TEGRA30_MC) += tegra30-mc.o
226 --- /dev/null
227 +++ b/drivers/memory/mvebu-devbus.c
228 @@ -0,0 +1,340 @@
229 +/*
230 + * Marvell EBU SoC Device Bus Controller
231 + * (memory controller for NOR/NAND/SRAM/FPGA devices)
232 + *
233 + * Copyright (C) 2013 Marvell
234 + *
235 + * This program is free software: you can redistribute it and/or modify
236 + * it under the terms of the GNU General Public License as published by
237 + * the Free Software Foundation version 2 of the License.
238 + *
239 + * This program is distributed in the hope that it will be useful,
240 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
241 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
242 + * GNU General Public License for more details.
243 + *
244 + * You should have received a copy of the GNU General Public License
245 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
246 + *
247 + */
248 +
249 +#include <linux/kernel.h>
250 +#include <linux/module.h>
251 +#include <linux/slab.h>
252 +#include <linux/err.h>
253 +#include <linux/io.h>
254 +#include <linux/clk.h>
255 +#include <linux/mbus.h>
256 +#include <linux/of_platform.h>
257 +#include <linux/of_address.h>
258 +#include <linux/platform_device.h>
259 +
260 +/* Register definitions */
261 +#define DEV_WIDTH_BIT 30
262 +#define BADR_SKEW_BIT 28
263 +#define RD_HOLD_BIT 23
264 +#define ACC_NEXT_BIT 17
265 +#define RD_SETUP_BIT 12
266 +#define ACC_FIRST_BIT 6
267 +
268 +#define SYNC_ENABLE_BIT 24
269 +#define WR_HIGH_BIT 16
270 +#define WR_LOW_BIT 8
271 +
272 +#define READ_PARAM_OFFSET 0x0
273 +#define WRITE_PARAM_OFFSET 0x4
274 +
275 +static const char * const devbus_wins[] = {
276 + "devbus-boot",
277 + "devbus-cs0",
278 + "devbus-cs1",
279 + "devbus-cs2",
280 + "devbus-cs3",
281 +};
282 +
283 +struct devbus_read_params {
284 + u32 bus_width;
285 + u32 badr_skew;
286 + u32 turn_off;
287 + u32 acc_first;
288 + u32 acc_next;
289 + u32 rd_setup;
290 + u32 rd_hold;
291 +};
292 +
293 +struct devbus_write_params {
294 + u32 sync_enable;
295 + u32 wr_high;
296 + u32 wr_low;
297 + u32 ale_wr;
298 +};
299 +
300 +struct devbus {
301 + struct device *dev;
302 + void __iomem *base;
303 + unsigned long tick_ps;
304 +};
305 +
306 +static int get_timing_param_ps(struct devbus *devbus,
307 + struct device_node *node,
308 + const char *name,
309 + u32 *ticks)
310 +{
311 + u32 time_ps;
312 + int err;
313 +
314 + err = of_property_read_u32(node, name, &time_ps);
315 + if (err < 0) {
316 + dev_err(devbus->dev, "%s has no '%s' property\n",
317 + name, node->full_name);
318 + return err;
319 + }
320 +
321 + *ticks = (time_ps + devbus->tick_ps - 1) / devbus->tick_ps;
322 +
323 + dev_dbg(devbus->dev, "%s: %u ps -> 0x%x\n",
324 + name, time_ps, *ticks);
325 + return 0;
326 +}
327 +
328 +static int devbus_set_timing_params(struct devbus *devbus,
329 + struct device_node *node)
330 +{
331 + struct devbus_read_params r;
332 + struct devbus_write_params w;
333 + u32 value;
334 + int err;
335 +
336 + dev_dbg(devbus->dev, "Setting timing parameter, tick is %lu ps\n",
337 + devbus->tick_ps);
338 +
339 + /* Get read timings */
340 + err = of_property_read_u32(node, "devbus,bus-width", &r.bus_width);
341 + if (err < 0) {
342 + dev_err(devbus->dev,
343 + "%s has no 'devbus,bus-width' property\n",
344 + node->full_name);
345 + return err;
346 + }
347 + /* Convert bit width to byte width */
348 + r.bus_width /= 8;
349 +
350 + err = get_timing_param_ps(devbus, node, "devbus,badr-skew-ps",
351 + &r.badr_skew);
352 + if (err < 0)
353 + return err;
354 +
355 + err = get_timing_param_ps(devbus, node, "devbus,turn-off-ps",
356 + &r.turn_off);
357 + if (err < 0)
358 + return err;
359 +
360 + err = get_timing_param_ps(devbus, node, "devbus,acc-first-ps",
361 + &r.acc_first);
362 + if (err < 0)
363 + return err;
364 +
365 + err = get_timing_param_ps(devbus, node, "devbus,acc-next-ps",
366 + &r.acc_next);
367 + if (err < 0)
368 + return err;
369 +
370 + err = get_timing_param_ps(devbus, node, "devbus,rd-setup-ps",
371 + &r.rd_setup);
372 + if (err < 0)
373 + return err;
374 +
375 + err = get_timing_param_ps(devbus, node, "devbus,rd-hold-ps",
376 + &r.rd_hold);
377 + if (err < 0)
378 + return err;
379 +
380 + /* Get write timings */
381 + err = of_property_read_u32(node, "devbus,sync-enable",
382 + &w.sync_enable);
383 + if (err < 0) {
384 + dev_err(devbus->dev,
385 + "%s has no 'devbus,sync-enable' property\n",
386 + node->full_name);
387 + return err;
388 + }
389 +
390 + err = get_timing_param_ps(devbus, node, "devbus,ale-wr-ps",
391 + &w.ale_wr);
392 + if (err < 0)
393 + return err;
394 +
395 + err = get_timing_param_ps(devbus, node, "devbus,wr-low-ps",
396 + &w.wr_low);
397 + if (err < 0)
398 + return err;
399 +
400 + err = get_timing_param_ps(devbus, node, "devbus,wr-high-ps",
401 + &w.wr_high);
402 + if (err < 0)
403 + return err;
404 +
405 + /* Set read timings */
406 + value = r.bus_width << DEV_WIDTH_BIT |
407 + r.badr_skew << BADR_SKEW_BIT |
408 + r.rd_hold << RD_HOLD_BIT |
409 + r.acc_next << ACC_NEXT_BIT |
410 + r.rd_setup << RD_SETUP_BIT |
411 + r.acc_first << ACC_FIRST_BIT |
412 + r.turn_off;
413 +
414 + dev_dbg(devbus->dev, "read parameters register 0x%p = 0x%x\n",
415 + devbus->base + READ_PARAM_OFFSET,
416 + value);
417 +
418 + writel(value, devbus->base + READ_PARAM_OFFSET);
419 +
420 + /* Set write timings */
421 + value = w.sync_enable << SYNC_ENABLE_BIT |
422 + w.wr_low << WR_LOW_BIT |
423 + w.wr_high << WR_HIGH_BIT |
424 + w.ale_wr;
425 +
426 + dev_dbg(devbus->dev, "write parameters register: 0x%p = 0x%x\n",
427 + devbus->base + WRITE_PARAM_OFFSET,
428 + value);
429 +
430 + writel(value, devbus->base + WRITE_PARAM_OFFSET);
431 +
432 + return 0;
433 +}
434 +
435 +static int mvebu_devbus_probe(struct platform_device *pdev)
436 +{
437 + struct device *dev = &pdev->dev;
438 + struct device_node *node = pdev->dev.of_node;
439 + struct device_node *parent;
440 + struct devbus *devbus;
441 + struct resource *res;
442 + struct clk *clk;
443 + unsigned long rate;
444 + const __be32 *ranges;
445 + int err, cs;
446 + int addr_cells, p_addr_cells, size_cells;
447 + int ranges_len, tuple_len;
448 + u32 base, size;
449 +
450 + devbus = devm_kzalloc(&pdev->dev, sizeof(struct devbus), GFP_KERNEL);
451 + if (!devbus)
452 + return -ENOMEM;
453 +
454 + devbus->dev = dev;
455 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
456 + devbus->base = devm_ioremap_resource(&pdev->dev, res);
457 + if (IS_ERR(devbus->base))
458 + return PTR_ERR(devbus->base);
459 +
460 + clk = devm_clk_get(&pdev->dev, NULL);
461 + if (IS_ERR(clk))
462 + return PTR_ERR(clk);
463 + clk_prepare_enable(clk);
464 +
465 + /*
466 + * Obtain clock period in picoseconds,
467 + * we need this in order to convert timing
468 + * parameters from cycles to picoseconds.
469 + */
470 + rate = clk_get_rate(clk) / 1000;
471 + devbus->tick_ps = 1000000000 / rate;
472 +
473 + /* Read the device tree node and set the new timing parameters */
474 + err = devbus_set_timing_params(devbus, node);
475 + if (err < 0)
476 + return err;
477 +
478 + /*
479 + * Allocate an address window for this device.
480 + * If the device probing fails, then we won't be able to
481 + * remove the allocated address decoding window.
482 + *
483 + * FIXME: This is only a temporary hack! We need to do this here
484 + * because we still don't have device tree bindings for mbus.
485 + * Once that support is added, we will declare these address windows
486 + * statically in the device tree, and remove the window configuration
487 + * from here.
488 + */
489 +
490 + /*
491 + * Get the CS to choose the window string.
492 + * This is a bit hacky, but it will be removed once the
493 + * address windows are declared in the device tree.
494 + */
495 + cs = (((unsigned long)devbus->base) % 0x400) / 8;
496 +
497 + /*
498 + * Parse 'ranges' property to obtain a (base,size) window tuple.
499 + * This will be removed once the address windows
500 + * are declared in the device tree.
501 + */
502 + parent = of_get_parent(node);
503 + if (!parent)
504 + return -EINVAL;
505 +
506 + p_addr_cells = of_n_addr_cells(parent);
507 + of_node_put(parent);
508 +
509 + addr_cells = of_n_addr_cells(node);
510 + size_cells = of_n_size_cells(node);
511 + tuple_len = (p_addr_cells + addr_cells + size_cells) * sizeof(__be32);
512 +
513 + ranges = of_get_property(node, "ranges", &ranges_len);
514 + if (ranges == NULL || ranges_len != tuple_len)
515 + return -EINVAL;
516 +
517 + base = of_translate_address(node, ranges + addr_cells);
518 + if (base == OF_BAD_ADDR)
519 + return -EINVAL;
520 + size = of_read_number(ranges + addr_cells + p_addr_cells, size_cells);
521 +
522 + /*
523 + * Create an mbus address windows.
524 + * FIXME: Remove this, together with the above code, once the
525 + * address windows are declared in the device tree.
526 + */
527 + err = mvebu_mbus_add_window(devbus_wins[cs], base, size);
528 + if (err < 0)
529 + return err;
530 +
531 + /*
532 + * We need to create a child device explicitly from here to
533 + * guarantee that the child will be probed after the timing
534 + * parameters for the bus are written.
535 + */
536 + err = of_platform_populate(node, NULL, NULL, dev);
537 + if (err < 0) {
538 + mvebu_mbus_del_window(base, size);
539 + return err;
540 + }
541 +
542 + return 0;
543 +}
544 +
545 +static const struct of_device_id mvebu_devbus_of_match[] = {
546 + { .compatible = "marvell,mvebu-devbus" },
547 + {},
548 +};
549 +MODULE_DEVICE_TABLE(of, mvebu_devbus_of_match);
550 +
551 +static struct platform_driver mvebu_devbus_driver = {
552 + .probe = mvebu_devbus_probe,
553 + .driver = {
554 + .name = "mvebu-devbus",
555 + .owner = THIS_MODULE,
556 + .of_match_table = mvebu_devbus_of_match,
557 + },
558 +};
559 +
560 +static int __init mvebu_devbus_init(void)
561 +{
562 + return platform_driver_register(&mvebu_devbus_driver);
563 +}
564 +module_init(mvebu_devbus_init);
565 +
566 +MODULE_LICENSE("GPL v2");
567 +MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
568 +MODULE_DESCRIPTION("Marvell EBU SoC Device Bus controller");