Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drivers: memory: Introduce Marvell EBU Device Bus driver

Marvell EBU SoCs such as Armada 370/XP, Orion5x (88f5xxx) and
Discovery (mv78xx0) supports a Device Bus controller to access several
kinds of memories and I/O devices (NOR, NAND, SRAM, FPGA).

This commit adds a driver to handle this controller. So far only
Armada 370, Armada XP and Discovery SoCs are supported.

The driver must be registered through a device tree node;
as explained in the binding document.

For each child node in the device tree, this driver will:
* set timing parameters
* register a child device
* setup an address decoding window, using the mbus driver

Keep in mind the address decoding window setup is only a temporary hack.
This code will be removed from this devbus driver as soon as a proper device
tree binding for the mbus driver is added.

Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Ezequiel Garcia and committed by
Greg Kroah-Hartman
3edad321 ced9017a

+507
+156
Documentation/devicetree/bindings/memory-controllers/mvebu-devbus.txt
··· 1 + Device tree bindings for MVEBU Device Bus controllers 2 + 3 + The Device Bus controller available in some Marvell's SoC allows to control 4 + different types of standard memory and I/O devices such as NOR, NAND, and FPGA. 5 + The actual devices are instantiated from the child nodes of a Device Bus node. 6 + 7 + Required properties: 8 + 9 + - compatible: Currently only Armada 370/XP SoC are supported, 10 + with this compatible string: 11 + 12 + marvell,mvebu-devbus 13 + 14 + - reg: A resource specifier for the register space. 15 + This is the base address of a chip select within 16 + the controller's register space. 17 + (see the example below) 18 + 19 + - #address-cells: Must be set to 1 20 + - #size-cells: Must be set to 1 21 + - ranges: Must be set up to reflect the memory layout with four 22 + integer values for each chip-select line in use: 23 + 0 <physical address of mapping> <size> 24 + 25 + Mandatory timing properties for child nodes: 26 + 27 + Read parameters: 28 + 29 + - devbus,turn-off-ps: Defines the time during which the controller does not 30 + drive the AD bus after the completion of a device read. 31 + This prevents contentions on the Device Bus after a read 32 + cycle from a slow device. 33 + 34 + - devbus,bus-width: Defines the bus width (e.g. <16>) 35 + 36 + - devbus,badr-skew-ps: Defines the time delay from from A[2:0] toggle, 37 + to read data sample. This parameter is useful for 38 + synchronous pipelined devices, where the address 39 + precedes the read data by one or two cycles. 40 + 41 + - devbus,acc-first-ps: Defines the time delay from the negation of 42 + ALE[0] to the cycle that the first read data is sampled 43 + by the controller. 44 + 45 + - devbus,acc-next-ps: Defines the time delay between the cycle that 46 + samples data N and the cycle that samples data N+1 47 + (in burst accesses). 48 + 49 + - devbus,rd-setup-ps: Defines the time delay between DEV_CSn assertion to 50 + DEV_OEn assertion. If set to 0 (default), 51 + DEV_OEn and DEV_CSn are asserted at the same cycle. 52 + This parameter has no affect on <acc-first-ps> parameter 53 + (no affect on first data sample). Set <rd-setup-ps> 54 + to a value smaller than <acc-first-ps>. 55 + 56 + - devbus,rd-hold-ps: Defines the time between the last data sample to the 57 + de-assertion of DEV_CSn. If set to 0 (default), 58 + DEV_OEn and DEV_CSn are de-asserted at the same cycle 59 + (the cycle of the last data sample). 60 + This parameter has no affect on DEV_OEn de-assertion. 61 + DEV_OEn is always de-asserted the next cycle after 62 + last data sampled. Also this parameter has no 63 + affect on <turn-off-ps> parameter. 64 + Set <rd-hold-ps> to a value smaller than <turn-off-ps>. 65 + 66 + Write parameters: 67 + 68 + - devbus,ale-wr-ps: Defines the time delay from the ALE[0] negation cycle 69 + to the DEV_WEn assertion. 70 + 71 + - devbus,wr-low-ps: Defines the time during which DEV_WEn is active. 72 + A[2:0] and Data are kept valid as long as DEV_WEn 73 + is active. This parameter defines the setup time of 74 + address and data to DEV_WEn rise. 75 + 76 + - devbus,wr-high-ps: Defines the time during which DEV_WEn is kept 77 + inactive (high) between data beats of a burst write. 78 + DEV_A[2:0] and Data are kept valid (do not toggle) for 79 + <wr-high-ps> - <tick> ps. 80 + This parameter defines the hold time of address and 81 + data after DEV_WEn rise. 82 + 83 + - devbus,sync-enable: Synchronous device enable. 84 + 1: True 85 + 0: False 86 + 87 + An example for an Armada XP GP board, with a 16 MiB NOR device as child 88 + is showed below. Note that the Device Bus driver is in charge of allocating 89 + the mbus address decoding window for each of its child devices. 90 + The window is created using the chip select specified in the child 91 + device node together with the base address and size specified in the ranges 92 + property. For instance, in the example below the allocated decoding window 93 + will start at base address 0xf0000000, with a size 0x1000000 (16 MiB) 94 + for chip select 0 (a.k.a DEV_BOOTCS). 95 + 96 + This address window handling is done in this mvebu-devbus only as a temporary 97 + solution. It will be removed when the support for mbus device tree binding is 98 + added. 99 + 100 + The reg property implicitly specifies the chip select as this: 101 + 102 + 0x10400: DEV_BOOTCS 103 + 0x10408: DEV_CS0 104 + 0x10410: DEV_CS1 105 + 0x10418: DEV_CS2 106 + 0x10420: DEV_CS3 107 + 108 + Example: 109 + 110 + devbus-bootcs@d0010400 { 111 + status = "okay"; 112 + ranges = <0 0xf0000000 0x1000000>; /* @addr 0xf0000000, size 0x1000000 */ 113 + #address-cells = <1>; 114 + #size-cells = <1>; 115 + 116 + /* Device Bus parameters are required */ 117 + 118 + /* Read parameters */ 119 + devbus,bus-width = <8>; 120 + devbus,turn-off-ps = <60000>; 121 + devbus,badr-skew-ps = <0>; 122 + devbus,acc-first-ps = <124000>; 123 + devbus,acc-next-ps = <248000>; 124 + devbus,rd-setup-ps = <0>; 125 + devbus,rd-hold-ps = <0>; 126 + 127 + /* Write parameters */ 128 + devbus,sync-enable = <0>; 129 + devbus,wr-high-ps = <60000>; 130 + devbus,wr-low-ps = <60000>; 131 + devbus,ale-wr-ps = <60000>; 132 + 133 + flash@0 { 134 + compatible = "cfi-flash"; 135 + 136 + /* 16 MiB */ 137 + reg = <0 0x1000000>; 138 + bank-width = <2>; 139 + #address-cells = <1>; 140 + #size-cells = <1>; 141 + 142 + /* 143 + * We split the 16 MiB in two partitions, 144 + * just as an example. 145 + */ 146 + partition@0 { 147 + label = "First"; 148 + reg = <0 0x800000>; 149 + }; 150 + 151 + partition@800000 { 152 + label = "Second"; 153 + reg = <0x800000 0x800000>; 154 + }; 155 + }; 156 + };
+10
drivers/memory/Kconfig
··· 20 20 parameters and other settings during frequency, voltage and 21 21 temperature changes 22 22 23 + config MVEBU_DEVBUS 24 + bool "Marvell EBU Device Bus Controller" 25 + default y 26 + depends on PLAT_ORION && OF 27 + help 28 + This driver is for the Device Bus controller available in some 29 + Marvell EBU SoCs such as Discovery (mv78xx0), Orion (88f5xxx) and 30 + Armada 370 and Armada XP. This controller allows to handle flash 31 + devices such as NOR, NAND, SRAM, and FPGA. 32 + 23 33 config TEGRA20_MC 24 34 bool "Tegra20 Memory Controller(MC) driver" 25 35 default y
+1
drivers/memory/Makefile
··· 6 6 obj-$(CONFIG_OF) += of_memory.o 7 7 endif 8 8 obj-$(CONFIG_TI_EMIF) += emif.o 9 + obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o 9 10 obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o 10 11 obj-$(CONFIG_TEGRA30_MC) += tegra30-mc.o
+340
drivers/memory/mvebu-devbus.c
··· 1 + /* 2 + * Marvell EBU SoC Device Bus Controller 3 + * (memory controller for NOR/NAND/SRAM/FPGA devices) 4 + * 5 + * Copyright (C) 2013 Marvell 6 + * 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 9 + * the Free Software Foundation version 2 of the License. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 + * 19 + */ 20 + 21 + #include <linux/kernel.h> 22 + #include <linux/module.h> 23 + #include <linux/slab.h> 24 + #include <linux/err.h> 25 + #include <linux/io.h> 26 + #include <linux/clk.h> 27 + #include <linux/mbus.h> 28 + #include <linux/of_platform.h> 29 + #include <linux/of_address.h> 30 + #include <linux/platform_device.h> 31 + 32 + /* Register definitions */ 33 + #define DEV_WIDTH_BIT 30 34 + #define BADR_SKEW_BIT 28 35 + #define RD_HOLD_BIT 23 36 + #define ACC_NEXT_BIT 17 37 + #define RD_SETUP_BIT 12 38 + #define ACC_FIRST_BIT 6 39 + 40 + #define SYNC_ENABLE_BIT 24 41 + #define WR_HIGH_BIT 16 42 + #define WR_LOW_BIT 8 43 + 44 + #define READ_PARAM_OFFSET 0x0 45 + #define WRITE_PARAM_OFFSET 0x4 46 + 47 + static const char * const devbus_wins[] = { 48 + "devbus-boot", 49 + "devbus-cs0", 50 + "devbus-cs1", 51 + "devbus-cs2", 52 + "devbus-cs3", 53 + }; 54 + 55 + struct devbus_read_params { 56 + u32 bus_width; 57 + u32 badr_skew; 58 + u32 turn_off; 59 + u32 acc_first; 60 + u32 acc_next; 61 + u32 rd_setup; 62 + u32 rd_hold; 63 + }; 64 + 65 + struct devbus_write_params { 66 + u32 sync_enable; 67 + u32 wr_high; 68 + u32 wr_low; 69 + u32 ale_wr; 70 + }; 71 + 72 + struct devbus { 73 + struct device *dev; 74 + void __iomem *base; 75 + unsigned long tick_ps; 76 + }; 77 + 78 + static int get_timing_param_ps(struct devbus *devbus, 79 + struct device_node *node, 80 + const char *name, 81 + u32 *ticks) 82 + { 83 + u32 time_ps; 84 + int err; 85 + 86 + err = of_property_read_u32(node, name, &time_ps); 87 + if (err < 0) { 88 + dev_err(devbus->dev, "%s has no '%s' property\n", 89 + name, node->full_name); 90 + return err; 91 + } 92 + 93 + *ticks = (time_ps + devbus->tick_ps - 1) / devbus->tick_ps; 94 + 95 + dev_dbg(devbus->dev, "%s: %u ps -> 0x%x\n", 96 + name, time_ps, *ticks); 97 + return 0; 98 + } 99 + 100 + static int devbus_set_timing_params(struct devbus *devbus, 101 + struct device_node *node) 102 + { 103 + struct devbus_read_params r; 104 + struct devbus_write_params w; 105 + u32 value; 106 + int err; 107 + 108 + dev_dbg(devbus->dev, "Setting timing parameter, tick is %lu ps\n", 109 + devbus->tick_ps); 110 + 111 + /* Get read timings */ 112 + err = of_property_read_u32(node, "devbus,bus-width", &r.bus_width); 113 + if (err < 0) { 114 + dev_err(devbus->dev, 115 + "%s has no 'devbus,bus-width' property\n", 116 + node->full_name); 117 + return err; 118 + } 119 + /* Convert bit width to byte width */ 120 + r.bus_width /= 8; 121 + 122 + err = get_timing_param_ps(devbus, node, "devbus,badr-skew-ps", 123 + &r.badr_skew); 124 + if (err < 0) 125 + return err; 126 + 127 + err = get_timing_param_ps(devbus, node, "devbus,turn-off-ps", 128 + &r.turn_off); 129 + if (err < 0) 130 + return err; 131 + 132 + err = get_timing_param_ps(devbus, node, "devbus,acc-first-ps", 133 + &r.acc_first); 134 + if (err < 0) 135 + return err; 136 + 137 + err = get_timing_param_ps(devbus, node, "devbus,acc-next-ps", 138 + &r.acc_next); 139 + if (err < 0) 140 + return err; 141 + 142 + err = get_timing_param_ps(devbus, node, "devbus,rd-setup-ps", 143 + &r.rd_setup); 144 + if (err < 0) 145 + return err; 146 + 147 + err = get_timing_param_ps(devbus, node, "devbus,rd-hold-ps", 148 + &r.rd_hold); 149 + if (err < 0) 150 + return err; 151 + 152 + /* Get write timings */ 153 + err = of_property_read_u32(node, "devbus,sync-enable", 154 + &w.sync_enable); 155 + if (err < 0) { 156 + dev_err(devbus->dev, 157 + "%s has no 'devbus,sync-enable' property\n", 158 + node->full_name); 159 + return err; 160 + } 161 + 162 + err = get_timing_param_ps(devbus, node, "devbus,ale-wr-ps", 163 + &w.ale_wr); 164 + if (err < 0) 165 + return err; 166 + 167 + err = get_timing_param_ps(devbus, node, "devbus,wr-low-ps", 168 + &w.wr_low); 169 + if (err < 0) 170 + return err; 171 + 172 + err = get_timing_param_ps(devbus, node, "devbus,wr-high-ps", 173 + &w.wr_high); 174 + if (err < 0) 175 + return err; 176 + 177 + /* Set read timings */ 178 + value = r.bus_width << DEV_WIDTH_BIT | 179 + r.badr_skew << BADR_SKEW_BIT | 180 + r.rd_hold << RD_HOLD_BIT | 181 + r.acc_next << ACC_NEXT_BIT | 182 + r.rd_setup << RD_SETUP_BIT | 183 + r.acc_first << ACC_FIRST_BIT | 184 + r.turn_off; 185 + 186 + dev_dbg(devbus->dev, "read parameters register 0x%p = 0x%x\n", 187 + devbus->base + READ_PARAM_OFFSET, 188 + value); 189 + 190 + writel(value, devbus->base + READ_PARAM_OFFSET); 191 + 192 + /* Set write timings */ 193 + value = w.sync_enable << SYNC_ENABLE_BIT | 194 + w.wr_low << WR_LOW_BIT | 195 + w.wr_high << WR_HIGH_BIT | 196 + w.ale_wr; 197 + 198 + dev_dbg(devbus->dev, "write parameters register: 0x%p = 0x%x\n", 199 + devbus->base + WRITE_PARAM_OFFSET, 200 + value); 201 + 202 + writel(value, devbus->base + WRITE_PARAM_OFFSET); 203 + 204 + return 0; 205 + } 206 + 207 + static int mvebu_devbus_probe(struct platform_device *pdev) 208 + { 209 + struct device *dev = &pdev->dev; 210 + struct device_node *node = pdev->dev.of_node; 211 + struct device_node *parent; 212 + struct devbus *devbus; 213 + struct resource *res; 214 + struct clk *clk; 215 + unsigned long rate; 216 + const __be32 *ranges; 217 + int err, cs; 218 + int addr_cells, p_addr_cells, size_cells; 219 + int ranges_len, tuple_len; 220 + u32 base, size; 221 + 222 + devbus = devm_kzalloc(&pdev->dev, sizeof(struct devbus), GFP_KERNEL); 223 + if (!devbus) 224 + return -ENOMEM; 225 + 226 + devbus->dev = dev; 227 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 228 + devbus->base = devm_ioremap_resource(&pdev->dev, res); 229 + if (IS_ERR(devbus->base)) 230 + return PTR_ERR(devbus->base); 231 + 232 + clk = devm_clk_get(&pdev->dev, NULL); 233 + if (IS_ERR(clk)) 234 + return PTR_ERR(clk); 235 + clk_prepare_enable(clk); 236 + 237 + /* 238 + * Obtain clock period in picoseconds, 239 + * we need this in order to convert timing 240 + * parameters from cycles to picoseconds. 241 + */ 242 + rate = clk_get_rate(clk) / 1000; 243 + devbus->tick_ps = 1000000000 / rate; 244 + 245 + /* Read the device tree node and set the new timing parameters */ 246 + err = devbus_set_timing_params(devbus, node); 247 + if (err < 0) 248 + return err; 249 + 250 + /* 251 + * Allocate an address window for this device. 252 + * If the device probing fails, then we won't be able to 253 + * remove the allocated address decoding window. 254 + * 255 + * FIXME: This is only a temporary hack! We need to do this here 256 + * because we still don't have device tree bindings for mbus. 257 + * Once that support is added, we will declare these address windows 258 + * statically in the device tree, and remove the window configuration 259 + * from here. 260 + */ 261 + 262 + /* 263 + * Get the CS to choose the window string. 264 + * This is a bit hacky, but it will be removed once the 265 + * address windows are declared in the device tree. 266 + */ 267 + cs = (((unsigned long)devbus->base) % 0x400) / 8; 268 + 269 + /* 270 + * Parse 'ranges' property to obtain a (base,size) window tuple. 271 + * This will be removed once the address windows 272 + * are declared in the device tree. 273 + */ 274 + parent = of_get_parent(node); 275 + if (!parent) 276 + return -EINVAL; 277 + 278 + p_addr_cells = of_n_addr_cells(parent); 279 + of_node_put(parent); 280 + 281 + addr_cells = of_n_addr_cells(node); 282 + size_cells = of_n_size_cells(node); 283 + tuple_len = (p_addr_cells + addr_cells + size_cells) * sizeof(__be32); 284 + 285 + ranges = of_get_property(node, "ranges", &ranges_len); 286 + if (ranges == NULL || ranges_len != tuple_len) 287 + return -EINVAL; 288 + 289 + base = of_translate_address(node, ranges + addr_cells); 290 + if (base == OF_BAD_ADDR) 291 + return -EINVAL; 292 + size = of_read_number(ranges + addr_cells + p_addr_cells, size_cells); 293 + 294 + /* 295 + * Create an mbus address windows. 296 + * FIXME: Remove this, together with the above code, once the 297 + * address windows are declared in the device tree. 298 + */ 299 + err = mvebu_mbus_add_window(devbus_wins[cs], base, size); 300 + if (err < 0) 301 + return err; 302 + 303 + /* 304 + * We need to create a child device explicitly from here to 305 + * guarantee that the child will be probed after the timing 306 + * parameters for the bus are written. 307 + */ 308 + err = of_platform_populate(node, NULL, NULL, dev); 309 + if (err < 0) { 310 + mvebu_mbus_del_window(base, size); 311 + return err; 312 + } 313 + 314 + return 0; 315 + } 316 + 317 + static const struct of_device_id mvebu_devbus_of_match[] = { 318 + { .compatible = "marvell,mvebu-devbus" }, 319 + {}, 320 + }; 321 + MODULE_DEVICE_TABLE(of, mvebu_devbus_of_match); 322 + 323 + static struct platform_driver mvebu_devbus_driver = { 324 + .probe = mvebu_devbus_probe, 325 + .driver = { 326 + .name = "mvebu-devbus", 327 + .owner = THIS_MODULE, 328 + .of_match_table = mvebu_devbus_of_match, 329 + }, 330 + }; 331 + 332 + static int __init mvebu_devbus_init(void) 333 + { 334 + return platform_driver_register(&mvebu_devbus_driver); 335 + } 336 + module_init(mvebu_devbus_init); 337 + 338 + MODULE_LICENSE("GPL v2"); 339 + MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>"); 340 + MODULE_DESCRIPTION("Marvell EBU SoC Device Bus controller");