From: Thomas Petazzoni Date: Tue, 22 Apr 2014 21:26:12 +0000 (+0200) Subject: memory: mvebu-devbus: add Orion5x support X-Git-Tag: v3.16-rc1~30^2~40^2~15^2~1 X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=commitdiff_plain;h=c4ec7430c30a4012a04aa5535919845f543f075d;p=linux.git 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 Acked-by: Sebastian Hesselbarth Tested-by: Ezequiel Garcia Link: https://lkml.kernel.org/r/1398202002-28530-9-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- diff --git a/Documentation/devicetree/bindings/memory-controllers/mvebu-devbus.txt b/Documentation/devicetree/bindings/memory-controllers/mvebu-devbus.txt index 653c90c34a71..55adde214627 100644 --- a/Documentation/devicetree/bindings/memory-controllers/mvebu-devbus.txt +++ b/Documentation/devicetree/bindings/memory-controllers/mvebu-devbus.txt @@ -6,10 +6,11 @@ The actual devices are instantiated from the child nodes of a Device Bus node. Required properties: - - compatible: Currently only Armada 370/XP SoC are supported, - with this compatible string: + - compatible: Armada 370/XP SoC are supported using the + "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. 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: 0 -Mandatory timing properties for child nodes: +Timing properties for child nodes: Read parameters: @@ -30,21 +31,26 @@ Read parameters: drive the AD bus after the completion of a device read. This prevents contentions on the Device Bus after a read 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, to read data sample. This parameter is useful for synchronous pipelined devices, where the address precedes the read data by one or two cycles. + Mandatory. - devbus,acc-first-ps: Defines the time delay from the negation of ALE[0] to the cycle that the first read data is sampled by the controller. + Mandatory. - devbus,acc-next-ps: Defines the time delay between the cycle that samples data N and the cycle that samples data N+1 (in burst accesses). + Mandatory. - devbus,rd-setup-ps: Defines the time delay between DEV_CSn assertion to DEV_OEn assertion. If set to 0 (default), @@ -52,6 +58,8 @@ Read parameters: This parameter has no affect on parameter (no affect on first data sample). Set to a value smaller than . + Mandatory for "marvell,mvebu-devbus" + compatible string, ignored otherwise. - devbus,rd-hold-ps: Defines the time between the last data sample to the de-assertion of DEV_CSn. If set to 0 (default), @@ -62,16 +70,20 @@ Read parameters: last data sampled. Also this parameter has no affect on parameter. Set to a value smaller than . + Mandatory for "marvell,mvebu-devbus" + compatible string, ignored otherwise. Write parameters: - devbus,ale-wr-ps: Defines the time delay from the ALE[0] negation cycle to the DEV_WEn assertion. + Mandatory. - 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 is active. This parameter defines the setup time of address and data to DEV_WEn rise. + Mandatory. - devbus,wr-high-ps: Defines the time during which DEV_WEn is kept inactive (high) between data beats of a burst write. @@ -79,10 +91,13 @@ Write parameters: - ps. This parameter defines the hold time of address and data after DEV_WEn rise. + Mandatory. - devbus,sync-enable: Synchronous device enable. 1: True 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 is showed below. Note that the Device Bus driver is in charge of allocating 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 @@ * Marvell EBU SoC Device Bus Controller * (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 * 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_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 { u32 bus_width; u32 badr_skew; @@ -96,7 +124,6 @@ static int devbus_get_timing_params(struct devbus *devbus, { int err; - /* Get read timings */ err = of_property_read_u32(node, "devbus,bus-width", &r->bus_width); if (err < 0) { dev_err(devbus->dev, @@ -138,24 +165,25 @@ static int devbus_get_timing_params(struct devbus *devbus, if (err < 0) return err; - err = get_timing_param_ps(devbus, node, "devbus,rd-setup-ps", - &r->rd_setup); - if (err < 0) - return err; - - err = get_timing_param_ps(devbus, node, "devbus,rd-hold-ps", - &r->rd_hold); - if (err < 0) - return err; - - /* Get write timings */ - err = of_property_read_u32(node, "devbus,sync-enable", - &w->sync_enable); - if (err < 0) { - dev_err(devbus->dev, - "%s has no 'devbus,sync-enable' property\n", - node->full_name); - 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", + &r->rd_setup); + if (err < 0) + return err; + + err = get_timing_param_ps(devbus, node, "devbus,rd-hold-ps", + &r->rd_hold); + if (err < 0) + return err; + + err = of_property_read_u32(node, "devbus,sync-enable", + &w->sync_enable); + if (err < 0) { + dev_err(devbus->dev, + "%s has no 'devbus,sync-enable' property\n", + node->full_name); + return err; + } } err = get_timing_param_ps(devbus, node, "devbus,ale-wr-ps", @@ -176,6 +204,39 @@ static int devbus_get_timing_params(struct devbus *devbus, 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, struct device_node *node, struct devbus_read_params *r, @@ -255,7 +316,10 @@ static int mvebu_devbus_probe(struct platform_device *pdev) return err; /* Set the new timing parameters */ - devbus_armada_set_timing_params(devbus, node, &r, &w); + 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); /* * We need to create a child device explicitly from here to @@ -271,6 +335,7 @@ static int mvebu_devbus_probe(struct platform_device *pdev) static const struct of_device_id mvebu_devbus_of_match[] = { { .compatible = "marvell,mvebu-devbus" }, + { .compatible = "marvell,orion-devbus" }, {}, }; MODULE_DEVICE_TABLE(of, mvebu_devbus_of_match);