aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/memory
diff options
context:
space:
mode:
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>2014-04-22 17:26:12 -0400
committerJason Cooper <jason@lakedaemon.net>2014-04-29 09:17:02 -0400
commitc4ec7430c30a4012a04aa5535919845f543f075d (patch)
tree6e84aa45bea83eaaec67fc5a473355c266ca69b8 /drivers/memory
parent30bd30b603462ae64a0b261a704a8b2b070c6688 (diff)
memory: mvebu-devbus: add Orion5x support
This commit adds support for the Orion5x family of Marvell processors into the mvebu-devbus driver. It differs from the already supported Armada 370/XP by: * Having a single register (instead of two) for doing all the timing configuration. * Having a few less timing configuration parameters. For this reason, a separate compatible string "marvell,orion-devbus" is introduced. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Acked-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com> Link: https://lkml.kernel.org/r/1398202002-28530-9-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper <jason@lakedaemon.net>
Diffstat (limited to 'drivers/memory')
-rw-r--r--drivers/memory/mvebu-devbus.c107
1 files changed, 86 insertions, 21 deletions
diff --git a/drivers/memory/mvebu-devbus.c b/drivers/memory/mvebu-devbus.c
index 5dc9c6360943..c8f3dad8a825 100644
--- a/drivers/memory/mvebu-devbus.c
+++ b/drivers/memory/mvebu-devbus.c
@@ -2,7 +2,7 @@
2 * Marvell EBU SoC Device Bus Controller 2 * Marvell EBU SoC Device Bus Controller
3 * (memory controller for NOR/NAND/SRAM/FPGA devices) 3 * (memory controller for NOR/NAND/SRAM/FPGA devices)
4 * 4 *
5 * Copyright (C) 2013 Marvell 5 * Copyright (C) 2013-2014 Marvell
6 * 6 *
7 * This program is free software: you can redistribute it and/or modify 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 8 * it under the terms of the GNU General Public License as published by
@@ -44,6 +44,34 @@
44#define ARMADA_READ_PARAM_OFFSET 0x0 44#define ARMADA_READ_PARAM_OFFSET 0x0
45#define ARMADA_WRITE_PARAM_OFFSET 0x4 45#define ARMADA_WRITE_PARAM_OFFSET 0x4
46 46
47#define ORION_RESERVED (0x2 << 30)
48#define ORION_BADR_SKEW_SHIFT 28
49#define ORION_WR_HIGH_EXT_BIT BIT(27)
50#define ORION_WR_HIGH_EXT_MASK 0x8
51#define ORION_WR_LOW_EXT_BIT BIT(26)
52#define ORION_WR_LOW_EXT_MASK 0x8
53#define ORION_ALE_WR_EXT_BIT BIT(25)
54#define ORION_ALE_WR_EXT_MASK 0x8
55#define ORION_ACC_NEXT_EXT_BIT BIT(24)
56#define ORION_ACC_NEXT_EXT_MASK 0x10
57#define ORION_ACC_FIRST_EXT_BIT BIT(23)
58#define ORION_ACC_FIRST_EXT_MASK 0x10
59#define ORION_TURN_OFF_EXT_BIT BIT(22)
60#define ORION_TURN_OFF_EXT_MASK 0x8
61#define ORION_DEV_WIDTH_SHIFT 20
62#define ORION_WR_HIGH_SHIFT 17
63#define ORION_WR_HIGH_MASK 0x7
64#define ORION_WR_LOW_SHIFT 14
65#define ORION_WR_LOW_MASK 0x7
66#define ORION_ALE_WR_SHIFT 11
67#define ORION_ALE_WR_MASK 0x7
68#define ORION_ACC_NEXT_SHIFT 7
69#define ORION_ACC_NEXT_MASK 0xF
70#define ORION_ACC_FIRST_SHIFT 3
71#define ORION_ACC_FIRST_MASK 0xF
72#define ORION_TURN_OFF_SHIFT 0
73#define ORION_TURN_OFF_MASK 0x7
74
47struct devbus_read_params { 75struct devbus_read_params {
48 u32 bus_width; 76 u32 bus_width;
49 u32 badr_skew; 77 u32 badr_skew;
@@ -96,7 +124,6 @@ static int devbus_get_timing_params(struct devbus *devbus,
96{ 124{
97 int err; 125 int err;
98 126
99 /* Get read timings */
100 err = of_property_read_u32(node, "devbus,bus-width", &r->bus_width); 127 err = of_property_read_u32(node, "devbus,bus-width", &r->bus_width);
101 if (err < 0) { 128 if (err < 0) {
102 dev_err(devbus->dev, 129 dev_err(devbus->dev,
@@ -138,24 +165,25 @@ static int devbus_get_timing_params(struct devbus *devbus,
138 if (err < 0) 165 if (err < 0)
139 return err; 166 return err;
140 167
141 err = get_timing_param_ps(devbus, node, "devbus,rd-setup-ps", 168 if (of_device_is_compatible(devbus->dev->of_node, "marvell,mvebu-devbus")) {
142 &r->rd_setup); 169 err = get_timing_param_ps(devbus, node, "devbus,rd-setup-ps",
143 if (err < 0) 170 &r->rd_setup);
144 return err; 171 if (err < 0)
145 172 return err;
146 err = get_timing_param_ps(devbus, node, "devbus,rd-hold-ps", 173
147 &r->rd_hold); 174 err = get_timing_param_ps(devbus, node, "devbus,rd-hold-ps",
148 if (err < 0) 175 &r->rd_hold);
149 return err; 176 if (err < 0)
150 177 return err;
151 /* Get write timings */ 178
152 err = of_property_read_u32(node, "devbus,sync-enable", 179 err = of_property_read_u32(node, "devbus,sync-enable",
153 &w->sync_enable); 180 &w->sync_enable);
154 if (err < 0) { 181 if (err < 0) {
155 dev_err(devbus->dev, 182 dev_err(devbus->dev,
156 "%s has no 'devbus,sync-enable' property\n", 183 "%s has no 'devbus,sync-enable' property\n",
157 node->full_name); 184 node->full_name);
158 return err; 185 return err;
186 }
159 } 187 }
160 188
161 err = get_timing_param_ps(devbus, node, "devbus,ale-wr-ps", 189 err = get_timing_param_ps(devbus, node, "devbus,ale-wr-ps",
@@ -176,6 +204,39 @@ static int devbus_get_timing_params(struct devbus *devbus,
176 return 0; 204 return 0;
177} 205}
178 206
207static void devbus_orion_set_timing_params(struct devbus *devbus,
208 struct device_node *node,
209 struct devbus_read_params *r,
210 struct devbus_write_params *w)
211{
212 u32 value;
213
214 /*
215 * The hardware designers found it would be a good idea to
216 * split most of the values in the register into two fields:
217 * one containing all the low-order bits, and another one
218 * containing just the high-order bit. For all of those
219 * fields, we have to split the value into these two parts.
220 */
221 value = (r->turn_off & ORION_TURN_OFF_MASK) << ORION_TURN_OFF_SHIFT |
222 (r->acc_first & ORION_ACC_FIRST_MASK) << ORION_ACC_FIRST_SHIFT |
223 (r->acc_next & ORION_ACC_NEXT_MASK) << ORION_ACC_NEXT_SHIFT |
224 (w->ale_wr & ORION_ALE_WR_MASK) << ORION_ALE_WR_SHIFT |
225 (w->wr_low & ORION_WR_LOW_MASK) << ORION_WR_LOW_SHIFT |
226 (w->wr_high & ORION_WR_HIGH_MASK) << ORION_WR_HIGH_SHIFT |
227 r->bus_width << ORION_DEV_WIDTH_SHIFT |
228 ((r->turn_off & ORION_TURN_OFF_EXT_MASK) ? ORION_TURN_OFF_EXT_BIT : 0) |
229 ((r->acc_first & ORION_ACC_FIRST_EXT_MASK) ? ORION_ACC_FIRST_EXT_BIT : 0) |
230 ((r->acc_next & ORION_ACC_NEXT_EXT_MASK) ? ORION_ACC_NEXT_EXT_BIT : 0) |
231 ((w->ale_wr & ORION_ALE_WR_EXT_MASK) ? ORION_ALE_WR_EXT_BIT : 0) |
232 ((w->wr_low & ORION_WR_LOW_EXT_MASK) ? ORION_WR_LOW_EXT_BIT : 0) |
233 ((w->wr_high & ORION_WR_HIGH_EXT_MASK) ? ORION_WR_HIGH_EXT_BIT : 0) |
234 (r->badr_skew << ORION_BADR_SKEW_SHIFT) |
235 ORION_RESERVED;
236
237 writel(value, devbus->base);
238}
239
179static void devbus_armada_set_timing_params(struct devbus *devbus, 240static void devbus_armada_set_timing_params(struct devbus *devbus,
180 struct device_node *node, 241 struct device_node *node,
181 struct devbus_read_params *r, 242 struct devbus_read_params *r,
@@ -255,7 +316,10 @@ static int mvebu_devbus_probe(struct platform_device *pdev)
255 return err; 316 return err;
256 317
257 /* Set the new timing parameters */ 318 /* Set the new timing parameters */
258 devbus_armada_set_timing_params(devbus, node, &r, &w); 319 if (of_device_is_compatible(node, "marvell,orion-devbus"))
320 devbus_orion_set_timing_params(devbus, node, &r, &w);
321 else
322 devbus_armada_set_timing_params(devbus, node, &r, &w);
259 323
260 /* 324 /*
261 * We need to create a child device explicitly from here to 325 * We need to create a child device explicitly from here to
@@ -271,6 +335,7 @@ static int mvebu_devbus_probe(struct platform_device *pdev)
271 335
272static const struct of_device_id mvebu_devbus_of_match[] = { 336static const struct of_device_id mvebu_devbus_of_match[] = {
273 { .compatible = "marvell,mvebu-devbus" }, 337 { .compatible = "marvell,mvebu-devbus" },
338 { .compatible = "marvell,orion-devbus" },
274 {}, 339 {},
275}; 340};
276MODULE_DEVICE_TABLE(of, mvebu_devbus_of_match); 341MODULE_DEVICE_TABLE(of, mvebu_devbus_of_match);