Commit 02be9746 authored by Olof Johansson's avatar Olof Johansson

Merge tag 'mvebu-drivers-3.16' of git://git.infradead.org/linux-mvebu into next/drivers

Merge "ARM: mvebu: driver changes for v3.16" from Jason Cooper:

mvebu driver changes for v3.16

 - mvebu-devbus
    - changes need to add support for the orion5x platform

* tag 'mvebu-drivers-3.16' of git://git.infradead.org/linux-mvebu:
  memory: mvebu-devbus: add a devbus, keep-config property
  memory: mvebu-devbus: add Orion5x support
  memory: mvebu-devbus: split functions
  memory: mvebu-devbus: use _SHIFT suffixes instead of _BIT
  memory: mvebu-devbus: use ARMADA_ prefix in defines
  ARM: orion5x: fix target ID for crypto SRAM window
  memory: mvebu-devbus: fix the conversion of the bus width
Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents eb7e855b 0456d330
......@@ -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,14 @@ Required properties:
integer values for each chip-select line in use:
0 <physical address of mapping> <size>
Mandatory timing properties for child nodes:
Optional properties:
- devbus,keep-config This property can optionally be used to keep
using the timing parameters set by the
bootloader. It makes all the timing properties
described below unused.
Timing properties for child nodes:
Read parameters:
......@@ -30,21 +38,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, except if devbus,keep-config is used.
- devbus,bus-width: Defines the bus width (e.g. <16>)
- devbus,bus-width: Defines the bus width, in bits (e.g. <16>).
Mandatory, except if devbus,keep-config is used.
- 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, except if devbus,keep-config is used.
- 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, except if devbus,keep-config is used.
- 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, except if devbus,keep-config is used.
- devbus,rd-setup-ps: Defines the time delay between DEV_CSn assertion to
DEV_OEn assertion. If set to 0 (default),
......@@ -52,6 +65,8 @@ Read parameters:
This parameter has no affect on <acc-first-ps> parameter
(no affect on first data sample). Set <rd-setup-ps>
to a value smaller than <acc-first-ps>.
Mandatory for "marvell,mvebu-devbus" compatible string,
except if devbus,keep-config is used.
- 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 +77,20 @@ Read parameters:
last data sampled. Also this parameter has no
affect on <turn-off-ps> parameter.
Set <rd-hold-ps> to a value smaller than <turn-off-ps>.
Mandatory for "marvell,mvebu-devbus" compatible string,
except if devbus,keep-config is used.
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 +98,13 @@ Write parameters:
<wr-high-ps> - <tick> 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,
except if devbus,keep-config is used.
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
......
......@@ -21,7 +21,7 @@ struct mv_sata_platform_data;
#define ORION_MBUS_DEVBUS_BOOT_ATTR 0x0f
#define ORION_MBUS_DEVBUS_TARGET(cs) 0x01
#define ORION_MBUS_DEVBUS_ATTR(cs) (~(1 << cs))
#define ORION_MBUS_SRAM_TARGET 0x00
#define ORION_MBUS_SRAM_TARGET 0x09
#define ORION_MBUS_SRAM_ATTR 0x00
/*
......
......@@ -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
......@@ -30,19 +30,47 @@
#include <linux/platform_device.h>
/* Register definitions */
#define DEV_WIDTH_BIT 30
#define BADR_SKEW_BIT 28
#define RD_HOLD_BIT 23
#define ACC_NEXT_BIT 17
#define RD_SETUP_BIT 12
#define ACC_FIRST_BIT 6
#define SYNC_ENABLE_BIT 24
#define WR_HIGH_BIT 16
#define WR_LOW_BIT 8
#define READ_PARAM_OFFSET 0x0
#define WRITE_PARAM_OFFSET 0x4
#define ARMADA_DEV_WIDTH_SHIFT 30
#define ARMADA_BADR_SKEW_SHIFT 28
#define ARMADA_RD_HOLD_SHIFT 23
#define ARMADA_ACC_NEXT_SHIFT 17
#define ARMADA_RD_SETUP_SHIFT 12
#define ARMADA_ACC_FIRST_SHIFT 6
#define ARMADA_SYNC_ENABLE_SHIFT 24
#define ARMADA_WR_HIGH_SHIFT 16
#define ARMADA_WR_LOW_SHIFT 8
#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;
......@@ -89,117 +117,167 @@ static int get_timing_param_ps(struct devbus *devbus,
return 0;
}
static int devbus_set_timing_params(struct devbus *devbus,
struct device_node *node)
static int devbus_get_timing_params(struct devbus *devbus,
struct device_node *node,
struct devbus_read_params *r,
struct devbus_write_params *w)
{
struct devbus_read_params r;
struct devbus_write_params w;
u32 value;
int err;
dev_dbg(devbus->dev, "Setting timing parameter, tick is %lu ps\n",
devbus->tick_ps);
/* 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) {
dev_err(devbus->dev,
"%s has no 'devbus,bus-width' property\n",
node->full_name);
return err;
}
/* Convert bit width to byte width */
r.bus_width /= 8;
/*
* The bus width is encoded into the register as 0 for 8 bits,
* and 1 for 16 bits, so we do the necessary conversion here.
*/
if (r->bus_width == 8)
r->bus_width = 0;
else if (r->bus_width == 16)
r->bus_width = 1;
else {
dev_err(devbus->dev, "invalid bus width %d\n", r->bus_width);
return -EINVAL;
}
err = get_timing_param_ps(devbus, node, "devbus,badr-skew-ps",
&r.badr_skew);
&r->badr_skew);
if (err < 0)
return err;
err = get_timing_param_ps(devbus, node, "devbus,turn-off-ps",
&r.turn_off);
&r->turn_off);
if (err < 0)
return err;
err = get_timing_param_ps(devbus, node, "devbus,acc-first-ps",
&r.acc_first);
&r->acc_first);
if (err < 0)
return err;
err = get_timing_param_ps(devbus, node, "devbus,acc-next-ps",
&r.acc_next);
&r->acc_next);
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",
&w.ale_wr);
&w->ale_wr);
if (err < 0)
return err;
err = get_timing_param_ps(devbus, node, "devbus,wr-low-ps",
&w.wr_low);
&w->wr_low);
if (err < 0)
return err;
err = get_timing_param_ps(devbus, node, "devbus,wr-high-ps",
&w.wr_high);
&w->wr_high);
if (err < 0)
return err;
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,
struct devbus_write_params *w)
{
u32 value;
/* Set read timings */
value = r.bus_width << DEV_WIDTH_BIT |
r.badr_skew << BADR_SKEW_BIT |
r.rd_hold << RD_HOLD_BIT |
r.acc_next << ACC_NEXT_BIT |
r.rd_setup << RD_SETUP_BIT |
r.acc_first << ACC_FIRST_BIT |
r.turn_off;
value = r->bus_width << ARMADA_DEV_WIDTH_SHIFT |
r->badr_skew << ARMADA_BADR_SKEW_SHIFT |
r->rd_hold << ARMADA_RD_HOLD_SHIFT |
r->acc_next << ARMADA_ACC_NEXT_SHIFT |
r->rd_setup << ARMADA_RD_SETUP_SHIFT |
r->acc_first << ARMADA_ACC_FIRST_SHIFT |
r->turn_off;
dev_dbg(devbus->dev, "read parameters register 0x%p = 0x%x\n",
devbus->base + READ_PARAM_OFFSET,
devbus->base + ARMADA_READ_PARAM_OFFSET,
value);
writel(value, devbus->base + READ_PARAM_OFFSET);
writel(value, devbus->base + ARMADA_READ_PARAM_OFFSET);
/* Set write timings */
value = w.sync_enable << SYNC_ENABLE_BIT |
w.wr_low << WR_LOW_BIT |
w.wr_high << WR_HIGH_BIT |
w.ale_wr;
value = w->sync_enable << ARMADA_SYNC_ENABLE_SHIFT |
w->wr_low << ARMADA_WR_LOW_SHIFT |
w->wr_high << ARMADA_WR_HIGH_SHIFT |
w->ale_wr;
dev_dbg(devbus->dev, "write parameters register: 0x%p = 0x%x\n",
devbus->base + WRITE_PARAM_OFFSET,
devbus->base + ARMADA_WRITE_PARAM_OFFSET,
value);
writel(value, devbus->base + WRITE_PARAM_OFFSET);
return 0;
writel(value, devbus->base + ARMADA_WRITE_PARAM_OFFSET);
}
static int mvebu_devbus_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = pdev->dev.of_node;
struct devbus_read_params r;
struct devbus_write_params w;
struct devbus *devbus;
struct resource *res;
struct clk *clk;
......@@ -229,10 +307,21 @@ static int mvebu_devbus_probe(struct platform_device *pdev)
rate = clk_get_rate(clk) / 1000;
devbus->tick_ps = 1000000000 / rate;
/* Read the device tree node and set the new timing parameters */
err = devbus_set_timing_params(devbus, node);
if (err < 0)
return err;
dev_dbg(devbus->dev, "Setting timing parameter, tick is %lu ps\n",
devbus->tick_ps);
if (!of_property_read_bool(node, "devbus,keep-config")) {
/* Read the Device Tree node */
err = devbus_get_timing_params(devbus, node, &r, &w);
if (err < 0)
return err;
/* 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);
}
/*
* We need to create a child device explicitly from here to
......@@ -248,6 +337,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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment