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>
This commit is contained in:
Thomas Petazzoni
2014-04-22 23:26:12 +02:00
committed by Jason Cooper
parent 30bd30b603
commit c4ec7430c3
2 changed files with 104 additions and 24 deletions

View File

@@ -6,10 +6,11 @@ The actual devices are instantiated from the child nodes of a Device Bus node.
Required properties: Required properties:
- compatible: Currently only Armada 370/XP SoC are supported, - compatible: Armada 370/XP SoC are supported using the
with this compatible string: "marvell,mvebu-devbus" compatible string.
marvell,mvebu-devbus Orion5x SoC are supported using the
"marvell,orion-devbus" compatible string.
- reg: A resource specifier for the register space. - reg: A resource specifier for the register space.
This is the base address of a chip select within This is the base address of a chip select within
@@ -22,7 +23,7 @@ Required properties:
integer values for each chip-select line in use: integer values for each chip-select line in use:
0 <physical address of mapping> <size> 0 <physical address of mapping> <size>
Mandatory timing properties for child nodes: Timing properties for child nodes:
Read parameters: Read parameters:
@@ -30,21 +31,26 @@ Read parameters:
drive the AD bus after the completion of a device read. drive the AD bus after the completion of a device read.
This prevents contentions on the Device Bus after a read This prevents contentions on the Device Bus after a read
cycle from a slow device. cycle from a slow device.
Mandatory.
- devbus,bus-width: Defines the bus width (e.g. <16>) - devbus,bus-width: Defines the bus width, in bits (e.g. <16>).
Mandatory.
- devbus,badr-skew-ps: Defines the time delay from from A[2:0] toggle, - devbus,badr-skew-ps: Defines the time delay from from A[2:0] toggle,
to read data sample. This parameter is useful for to read data sample. This parameter is useful for
synchronous pipelined devices, where the address synchronous pipelined devices, where the address
precedes the read data by one or two cycles. precedes the read data by one or two cycles.
Mandatory.
- devbus,acc-first-ps: Defines the time delay from the negation of - devbus,acc-first-ps: Defines the time delay from the negation of
ALE[0] to the cycle that the first read data is sampled ALE[0] to the cycle that the first read data is sampled
by the controller. by the controller.
Mandatory.
- devbus,acc-next-ps: Defines the time delay between the cycle that - devbus,acc-next-ps: Defines the time delay between the cycle that
samples data N and the cycle that samples data N+1 samples data N and the cycle that samples data N+1
(in burst accesses). (in burst accesses).
Mandatory.
- devbus,rd-setup-ps: Defines the time delay between DEV_CSn assertion to - devbus,rd-setup-ps: Defines the time delay between DEV_CSn assertion to
DEV_OEn assertion. If set to 0 (default), DEV_OEn assertion. If set to 0 (default),
@@ -52,6 +58,8 @@ Read parameters:
This parameter has no affect on <acc-first-ps> parameter This parameter has no affect on <acc-first-ps> parameter
(no affect on first data sample). Set <rd-setup-ps> (no affect on first data sample). Set <rd-setup-ps>
to a value smaller than <acc-first-ps>. to a value smaller than <acc-first-ps>.
Mandatory for "marvell,mvebu-devbus"
compatible string, ignored otherwise.
- devbus,rd-hold-ps: Defines the time between the last data sample to the - devbus,rd-hold-ps: Defines the time between the last data sample to the
de-assertion of DEV_CSn. If set to 0 (default), de-assertion of DEV_CSn. If set to 0 (default),
@@ -62,16 +70,20 @@ Read parameters:
last data sampled. Also this parameter has no last data sampled. Also this parameter has no
affect on <turn-off-ps> parameter. affect on <turn-off-ps> parameter.
Set <rd-hold-ps> to a value smaller than <turn-off-ps>. Set <rd-hold-ps> to a value smaller than <turn-off-ps>.
Mandatory for "marvell,mvebu-devbus"
compatible string, ignored otherwise.
Write parameters: Write parameters:
- devbus,ale-wr-ps: Defines the time delay from the ALE[0] negation cycle - devbus,ale-wr-ps: Defines the time delay from the ALE[0] negation cycle
to the DEV_WEn assertion. to the DEV_WEn assertion.
Mandatory.
- devbus,wr-low-ps: Defines the time during which DEV_WEn is active. - devbus,wr-low-ps: Defines the time during which DEV_WEn is active.
A[2:0] and Data are kept valid as long as DEV_WEn A[2:0] and Data are kept valid as long as DEV_WEn
is active. This parameter defines the setup time of is active. This parameter defines the setup time of
address and data to DEV_WEn rise. address and data to DEV_WEn rise.
Mandatory.
- devbus,wr-high-ps: Defines the time during which DEV_WEn is kept - devbus,wr-high-ps: Defines the time during which DEV_WEn is kept
inactive (high) between data beats of a burst write. inactive (high) between data beats of a burst write.
@@ -79,10 +91,13 @@ Write parameters:
<wr-high-ps> - <tick> ps. <wr-high-ps> - <tick> ps.
This parameter defines the hold time of address and This parameter defines the hold time of address and
data after DEV_WEn rise. data after DEV_WEn rise.
Mandatory.
- devbus,sync-enable: Synchronous device enable. - devbus,sync-enable: Synchronous device enable.
1: True 1: True
0: False 0: False
Mandatory for "marvell,mvebu-devbus" compatible
string, ignored otherwise.
An example for an Armada XP GP board, with a 16 MiB NOR device as child An example for an Armada XP GP board, with a 16 MiB NOR device as child
is showed below. Note that the Device Bus driver is in charge of allocating is showed below. Note that the Device Bus driver is in charge of allocating

View File

@@ -2,7 +2,7 @@
* Marvell EBU SoC Device Bus Controller * Marvell EBU SoC Device Bus Controller
* (memory controller for NOR/NAND/SRAM/FPGA devices) * (memory controller for NOR/NAND/SRAM/FPGA devices)
* *
* Copyright (C) 2013 Marvell * Copyright (C) 2013-2014 Marvell
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -44,6 +44,34 @@
#define ARMADA_READ_PARAM_OFFSET 0x0 #define ARMADA_READ_PARAM_OFFSET 0x0
#define ARMADA_WRITE_PARAM_OFFSET 0x4 #define ARMADA_WRITE_PARAM_OFFSET 0x4
#define ORION_RESERVED (0x2 << 30)
#define ORION_BADR_SKEW_SHIFT 28
#define ORION_WR_HIGH_EXT_BIT BIT(27)
#define ORION_WR_HIGH_EXT_MASK 0x8
#define ORION_WR_LOW_EXT_BIT BIT(26)
#define ORION_WR_LOW_EXT_MASK 0x8
#define ORION_ALE_WR_EXT_BIT BIT(25)
#define ORION_ALE_WR_EXT_MASK 0x8
#define ORION_ACC_NEXT_EXT_BIT BIT(24)
#define ORION_ACC_NEXT_EXT_MASK 0x10
#define ORION_ACC_FIRST_EXT_BIT BIT(23)
#define ORION_ACC_FIRST_EXT_MASK 0x10
#define ORION_TURN_OFF_EXT_BIT BIT(22)
#define ORION_TURN_OFF_EXT_MASK 0x8
#define ORION_DEV_WIDTH_SHIFT 20
#define ORION_WR_HIGH_SHIFT 17
#define ORION_WR_HIGH_MASK 0x7
#define ORION_WR_LOW_SHIFT 14
#define ORION_WR_LOW_MASK 0x7
#define ORION_ALE_WR_SHIFT 11
#define ORION_ALE_WR_MASK 0x7
#define ORION_ACC_NEXT_SHIFT 7
#define ORION_ACC_NEXT_MASK 0xF
#define ORION_ACC_FIRST_SHIFT 3
#define ORION_ACC_FIRST_MASK 0xF
#define ORION_TURN_OFF_SHIFT 0
#define ORION_TURN_OFF_MASK 0x7
struct devbus_read_params { struct devbus_read_params {
u32 bus_width; u32 bus_width;
u32 badr_skew; u32 badr_skew;
@@ -96,7 +124,6 @@ static int devbus_get_timing_params(struct devbus *devbus,
{ {
int err; int err;
/* Get read timings */
err = of_property_read_u32(node, "devbus,bus-width", &r->bus_width); err = of_property_read_u32(node, "devbus,bus-width", &r->bus_width);
if (err < 0) { if (err < 0) {
dev_err(devbus->dev, dev_err(devbus->dev,
@@ -138,6 +165,7 @@ static int devbus_get_timing_params(struct devbus *devbus,
if (err < 0) if (err < 0)
return err; return err;
if (of_device_is_compatible(devbus->dev->of_node, "marvell,mvebu-devbus")) {
err = get_timing_param_ps(devbus, node, "devbus,rd-setup-ps", err = get_timing_param_ps(devbus, node, "devbus,rd-setup-ps",
&r->rd_setup); &r->rd_setup);
if (err < 0) if (err < 0)
@@ -148,7 +176,6 @@ static int devbus_get_timing_params(struct devbus *devbus,
if (err < 0) if (err < 0)
return err; return err;
/* Get write timings */
err = of_property_read_u32(node, "devbus,sync-enable", err = of_property_read_u32(node, "devbus,sync-enable",
&w->sync_enable); &w->sync_enable);
if (err < 0) { if (err < 0) {
@@ -157,6 +184,7 @@ static int devbus_get_timing_params(struct devbus *devbus,
node->full_name); node->full_name);
return err; return err;
} }
}
err = get_timing_param_ps(devbus, node, "devbus,ale-wr-ps", err = get_timing_param_ps(devbus, node, "devbus,ale-wr-ps",
&w->ale_wr); &w->ale_wr);
@@ -176,6 +204,39 @@ static int devbus_get_timing_params(struct devbus *devbus,
return 0; return 0;
} }
static void devbus_orion_set_timing_params(struct devbus *devbus,
struct device_node *node,
struct devbus_read_params *r,
struct devbus_write_params *w)
{
u32 value;
/*
* The hardware designers found it would be a good idea to
* split most of the values in the register into two fields:
* one containing all the low-order bits, and another one
* containing just the high-order bit. For all of those
* fields, we have to split the value into these two parts.
*/
value = (r->turn_off & ORION_TURN_OFF_MASK) << ORION_TURN_OFF_SHIFT |
(r->acc_first & ORION_ACC_FIRST_MASK) << ORION_ACC_FIRST_SHIFT |
(r->acc_next & ORION_ACC_NEXT_MASK) << ORION_ACC_NEXT_SHIFT |
(w->ale_wr & ORION_ALE_WR_MASK) << ORION_ALE_WR_SHIFT |
(w->wr_low & ORION_WR_LOW_MASK) << ORION_WR_LOW_SHIFT |
(w->wr_high & ORION_WR_HIGH_MASK) << ORION_WR_HIGH_SHIFT |
r->bus_width << ORION_DEV_WIDTH_SHIFT |
((r->turn_off & ORION_TURN_OFF_EXT_MASK) ? ORION_TURN_OFF_EXT_BIT : 0) |
((r->acc_first & ORION_ACC_FIRST_EXT_MASK) ? ORION_ACC_FIRST_EXT_BIT : 0) |
((r->acc_next & ORION_ACC_NEXT_EXT_MASK) ? ORION_ACC_NEXT_EXT_BIT : 0) |
((w->ale_wr & ORION_ALE_WR_EXT_MASK) ? ORION_ALE_WR_EXT_BIT : 0) |
((w->wr_low & ORION_WR_LOW_EXT_MASK) ? ORION_WR_LOW_EXT_BIT : 0) |
((w->wr_high & ORION_WR_HIGH_EXT_MASK) ? ORION_WR_HIGH_EXT_BIT : 0) |
(r->badr_skew << ORION_BADR_SKEW_SHIFT) |
ORION_RESERVED;
writel(value, devbus->base);
}
static void devbus_armada_set_timing_params(struct devbus *devbus, static void devbus_armada_set_timing_params(struct devbus *devbus,
struct device_node *node, struct device_node *node,
struct devbus_read_params *r, struct devbus_read_params *r,
@@ -255,6 +316,9 @@ static int mvebu_devbus_probe(struct platform_device *pdev)
return err; return err;
/* Set the new timing parameters */ /* Set the new timing parameters */
if (of_device_is_compatible(node, "marvell,orion-devbus"))
devbus_orion_set_timing_params(devbus, node, &r, &w);
else
devbus_armada_set_timing_params(devbus, node, &r, &w); devbus_armada_set_timing_params(devbus, node, &r, &w);
/* /*
@@ -271,6 +335,7 @@ static int mvebu_devbus_probe(struct platform_device *pdev)
static const struct of_device_id mvebu_devbus_of_match[] = { static const struct of_device_id mvebu_devbus_of_match[] = {
{ .compatible = "marvell,mvebu-devbus" }, { .compatible = "marvell,mvebu-devbus" },
{ .compatible = "marvell,orion-devbus" },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, mvebu_devbus_of_match); MODULE_DEVICE_TABLE(of, mvebu_devbus_of_match);