root/drivers/memory/mvebu-devbus.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_timing_param_ps
  2. devbus_get_timing_params
  3. devbus_orion_set_timing_params
  4. devbus_armada_set_timing_params
  5. mvebu_devbus_probe
  6. mvebu_devbus_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Marvell EBU SoC Device Bus Controller
   4  * (memory controller for NOR/NAND/SRAM/FPGA devices)
   5  *
   6  * Copyright (C) 2013-2014 Marvell
   7  */
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/module.h>
  11 #include <linux/slab.h>
  12 #include <linux/err.h>
  13 #include <linux/io.h>
  14 #include <linux/clk.h>
  15 #include <linux/mbus.h>
  16 #include <linux/of_platform.h>
  17 #include <linux/of_address.h>
  18 #include <linux/platform_device.h>
  19 
  20 /* Register definitions */
  21 #define ARMADA_DEV_WIDTH_SHIFT          30
  22 #define ARMADA_BADR_SKEW_SHIFT          28
  23 #define ARMADA_RD_HOLD_SHIFT            23
  24 #define ARMADA_ACC_NEXT_SHIFT           17
  25 #define ARMADA_RD_SETUP_SHIFT           12
  26 #define ARMADA_ACC_FIRST_SHIFT          6
  27 
  28 #define ARMADA_SYNC_ENABLE_SHIFT        24
  29 #define ARMADA_WR_HIGH_SHIFT            16
  30 #define ARMADA_WR_LOW_SHIFT             8
  31 
  32 #define ARMADA_READ_PARAM_OFFSET        0x0
  33 #define ARMADA_WRITE_PARAM_OFFSET       0x4
  34 
  35 #define ORION_RESERVED                  (0x2 << 30)
  36 #define ORION_BADR_SKEW_SHIFT           28
  37 #define ORION_WR_HIGH_EXT_BIT           BIT(27)
  38 #define ORION_WR_HIGH_EXT_MASK          0x8
  39 #define ORION_WR_LOW_EXT_BIT            BIT(26)
  40 #define ORION_WR_LOW_EXT_MASK           0x8
  41 #define ORION_ALE_WR_EXT_BIT            BIT(25)
  42 #define ORION_ALE_WR_EXT_MASK           0x8
  43 #define ORION_ACC_NEXT_EXT_BIT          BIT(24)
  44 #define ORION_ACC_NEXT_EXT_MASK         0x10
  45 #define ORION_ACC_FIRST_EXT_BIT         BIT(23)
  46 #define ORION_ACC_FIRST_EXT_MASK        0x10
  47 #define ORION_TURN_OFF_EXT_BIT          BIT(22)
  48 #define ORION_TURN_OFF_EXT_MASK         0x8
  49 #define ORION_DEV_WIDTH_SHIFT           20
  50 #define ORION_WR_HIGH_SHIFT             17
  51 #define ORION_WR_HIGH_MASK              0x7
  52 #define ORION_WR_LOW_SHIFT              14
  53 #define ORION_WR_LOW_MASK               0x7
  54 #define ORION_ALE_WR_SHIFT              11
  55 #define ORION_ALE_WR_MASK               0x7
  56 #define ORION_ACC_NEXT_SHIFT            7
  57 #define ORION_ACC_NEXT_MASK             0xF
  58 #define ORION_ACC_FIRST_SHIFT           3
  59 #define ORION_ACC_FIRST_MASK            0xF
  60 #define ORION_TURN_OFF_SHIFT            0
  61 #define ORION_TURN_OFF_MASK             0x7
  62 
  63 struct devbus_read_params {
  64         u32 bus_width;
  65         u32 badr_skew;
  66         u32 turn_off;
  67         u32 acc_first;
  68         u32 acc_next;
  69         u32 rd_setup;
  70         u32 rd_hold;
  71 };
  72 
  73 struct devbus_write_params {
  74         u32 sync_enable;
  75         u32 wr_high;
  76         u32 wr_low;
  77         u32 ale_wr;
  78 };
  79 
  80 struct devbus {
  81         struct device *dev;
  82         void __iomem *base;
  83         unsigned long tick_ps;
  84 };
  85 
  86 static int get_timing_param_ps(struct devbus *devbus,
  87                                struct device_node *node,
  88                                const char *name,
  89                                u32 *ticks)
  90 {
  91         u32 time_ps;
  92         int err;
  93 
  94         err = of_property_read_u32(node, name, &time_ps);
  95         if (err < 0) {
  96                 dev_err(devbus->dev, "%pOF has no '%s' property\n",
  97                         node, name);
  98                 return err;
  99         }
 100 
 101         *ticks = (time_ps + devbus->tick_ps - 1) / devbus->tick_ps;
 102 
 103         dev_dbg(devbus->dev, "%s: %u ps -> 0x%x\n",
 104                 name, time_ps, *ticks);
 105         return 0;
 106 }
 107 
 108 static int devbus_get_timing_params(struct devbus *devbus,
 109                                     struct device_node *node,
 110                                     struct devbus_read_params *r,
 111                                     struct devbus_write_params *w)
 112 {
 113         int err;
 114 
 115         err = of_property_read_u32(node, "devbus,bus-width", &r->bus_width);
 116         if (err < 0) {
 117                 dev_err(devbus->dev,
 118                         "%pOF has no 'devbus,bus-width' property\n",
 119                         node);
 120                 return err;
 121         }
 122 
 123         /*
 124          * The bus width is encoded into the register as 0 for 8 bits,
 125          * and 1 for 16 bits, so we do the necessary conversion here.
 126          */
 127         if (r->bus_width == 8)
 128                 r->bus_width = 0;
 129         else if (r->bus_width == 16)
 130                 r->bus_width = 1;
 131         else {
 132                 dev_err(devbus->dev, "invalid bus width %d\n", r->bus_width);
 133                 return -EINVAL;
 134         }
 135 
 136         err = get_timing_param_ps(devbus, node, "devbus,badr-skew-ps",
 137                                  &r->badr_skew);
 138         if (err < 0)
 139                 return err;
 140 
 141         err = get_timing_param_ps(devbus, node, "devbus,turn-off-ps",
 142                                  &r->turn_off);
 143         if (err < 0)
 144                 return err;
 145 
 146         err = get_timing_param_ps(devbus, node, "devbus,acc-first-ps",
 147                                  &r->acc_first);
 148         if (err < 0)
 149                 return err;
 150 
 151         err = get_timing_param_ps(devbus, node, "devbus,acc-next-ps",
 152                                  &r->acc_next);
 153         if (err < 0)
 154                 return err;
 155 
 156         if (of_device_is_compatible(devbus->dev->of_node, "marvell,mvebu-devbus")) {
 157                 err = get_timing_param_ps(devbus, node, "devbus,rd-setup-ps",
 158                                           &r->rd_setup);
 159                 if (err < 0)
 160                         return err;
 161 
 162                 err = get_timing_param_ps(devbus, node, "devbus,rd-hold-ps",
 163                                           &r->rd_hold);
 164                 if (err < 0)
 165                         return err;
 166 
 167                 err = of_property_read_u32(node, "devbus,sync-enable",
 168                                            &w->sync_enable);
 169                 if (err < 0) {
 170                         dev_err(devbus->dev,
 171                                 "%pOF has no 'devbus,sync-enable' property\n",
 172                                 node);
 173                         return err;
 174                 }
 175         }
 176 
 177         err = get_timing_param_ps(devbus, node, "devbus,ale-wr-ps",
 178                                  &w->ale_wr);
 179         if (err < 0)
 180                 return err;
 181 
 182         err = get_timing_param_ps(devbus, node, "devbus,wr-low-ps",
 183                                  &w->wr_low);
 184         if (err < 0)
 185                 return err;
 186 
 187         err = get_timing_param_ps(devbus, node, "devbus,wr-high-ps",
 188                                  &w->wr_high);
 189         if (err < 0)
 190                 return err;
 191 
 192         return 0;
 193 }
 194 
 195 static void devbus_orion_set_timing_params(struct devbus *devbus,
 196                                           struct device_node *node,
 197                                           struct devbus_read_params *r,
 198                                           struct devbus_write_params *w)
 199 {
 200         u32 value;
 201 
 202         /*
 203          * The hardware designers found it would be a good idea to
 204          * split most of the values in the register into two fields:
 205          * one containing all the low-order bits, and another one
 206          * containing just the high-order bit. For all of those
 207          * fields, we have to split the value into these two parts.
 208          */
 209         value = (r->turn_off   & ORION_TURN_OFF_MASK)  << ORION_TURN_OFF_SHIFT  |
 210                 (r->acc_first  & ORION_ACC_FIRST_MASK) << ORION_ACC_FIRST_SHIFT |
 211                 (r->acc_next   & ORION_ACC_NEXT_MASK)  << ORION_ACC_NEXT_SHIFT  |
 212                 (w->ale_wr     & ORION_ALE_WR_MASK)    << ORION_ALE_WR_SHIFT    |
 213                 (w->wr_low     & ORION_WR_LOW_MASK)    << ORION_WR_LOW_SHIFT    |
 214                 (w->wr_high    & ORION_WR_HIGH_MASK)   << ORION_WR_HIGH_SHIFT   |
 215                 r->bus_width                           << ORION_DEV_WIDTH_SHIFT |
 216                 ((r->turn_off  & ORION_TURN_OFF_EXT_MASK)  ? ORION_TURN_OFF_EXT_BIT  : 0) |
 217                 ((r->acc_first & ORION_ACC_FIRST_EXT_MASK) ? ORION_ACC_FIRST_EXT_BIT : 0) |
 218                 ((r->acc_next  & ORION_ACC_NEXT_EXT_MASK)  ? ORION_ACC_NEXT_EXT_BIT  : 0) |
 219                 ((w->ale_wr    & ORION_ALE_WR_EXT_MASK)    ? ORION_ALE_WR_EXT_BIT    : 0) |
 220                 ((w->wr_low    & ORION_WR_LOW_EXT_MASK)    ? ORION_WR_LOW_EXT_BIT    : 0) |
 221                 ((w->wr_high   & ORION_WR_HIGH_EXT_MASK)   ? ORION_WR_HIGH_EXT_BIT   : 0) |
 222                 (r->badr_skew << ORION_BADR_SKEW_SHIFT) |
 223                 ORION_RESERVED;
 224 
 225         writel(value, devbus->base);
 226 }
 227 
 228 static void devbus_armada_set_timing_params(struct devbus *devbus,
 229                                            struct device_node *node,
 230                                            struct devbus_read_params *r,
 231                                            struct devbus_write_params *w)
 232 {
 233         u32 value;
 234 
 235         /* Set read timings */
 236         value = r->bus_width << ARMADA_DEV_WIDTH_SHIFT |
 237                 r->badr_skew << ARMADA_BADR_SKEW_SHIFT |
 238                 r->rd_hold   << ARMADA_RD_HOLD_SHIFT   |
 239                 r->acc_next  << ARMADA_ACC_NEXT_SHIFT  |
 240                 r->rd_setup  << ARMADA_RD_SETUP_SHIFT  |
 241                 r->acc_first << ARMADA_ACC_FIRST_SHIFT |
 242                 r->turn_off;
 243 
 244         dev_dbg(devbus->dev, "read parameters register 0x%p = 0x%x\n",
 245                 devbus->base + ARMADA_READ_PARAM_OFFSET,
 246                 value);
 247 
 248         writel(value, devbus->base + ARMADA_READ_PARAM_OFFSET);
 249 
 250         /* Set write timings */
 251         value = w->sync_enable  << ARMADA_SYNC_ENABLE_SHIFT |
 252                 w->wr_low       << ARMADA_WR_LOW_SHIFT      |
 253                 w->wr_high      << ARMADA_WR_HIGH_SHIFT     |
 254                 w->ale_wr;
 255 
 256         dev_dbg(devbus->dev, "write parameters register: 0x%p = 0x%x\n",
 257                 devbus->base + ARMADA_WRITE_PARAM_OFFSET,
 258                 value);
 259 
 260         writel(value, devbus->base + ARMADA_WRITE_PARAM_OFFSET);
 261 }
 262 
 263 static int mvebu_devbus_probe(struct platform_device *pdev)
 264 {
 265         struct device *dev = &pdev->dev;
 266         struct device_node *node = pdev->dev.of_node;
 267         struct devbus_read_params r;
 268         struct devbus_write_params w;
 269         struct devbus *devbus;
 270         struct resource *res;
 271         struct clk *clk;
 272         unsigned long rate;
 273         int err;
 274 
 275         devbus = devm_kzalloc(&pdev->dev, sizeof(struct devbus), GFP_KERNEL);
 276         if (!devbus)
 277                 return -ENOMEM;
 278 
 279         devbus->dev = dev;
 280         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 281         devbus->base = devm_ioremap_resource(&pdev->dev, res);
 282         if (IS_ERR(devbus->base))
 283                 return PTR_ERR(devbus->base);
 284 
 285         clk = devm_clk_get(&pdev->dev, NULL);
 286         if (IS_ERR(clk))
 287                 return PTR_ERR(clk);
 288         clk_prepare_enable(clk);
 289 
 290         /*
 291          * Obtain clock period in picoseconds,
 292          * we need this in order to convert timing
 293          * parameters from cycles to picoseconds.
 294          */
 295         rate = clk_get_rate(clk) / 1000;
 296         devbus->tick_ps = 1000000000 / rate;
 297 
 298         dev_dbg(devbus->dev, "Setting timing parameter, tick is %lu ps\n",
 299                 devbus->tick_ps);
 300 
 301         if (!of_property_read_bool(node, "devbus,keep-config")) {
 302                 /* Read the Device Tree node */
 303                 err = devbus_get_timing_params(devbus, node, &r, &w);
 304                 if (err < 0)
 305                         return err;
 306 
 307                 /* Set the new timing parameters */
 308                 if (of_device_is_compatible(node, "marvell,orion-devbus"))
 309                         devbus_orion_set_timing_params(devbus, node, &r, &w);
 310                 else
 311                         devbus_armada_set_timing_params(devbus, node, &r, &w);
 312         }
 313 
 314         /*
 315          * We need to create a child device explicitly from here to
 316          * guarantee that the child will be probed after the timing
 317          * parameters for the bus are written.
 318          */
 319         err = of_platform_populate(node, NULL, NULL, dev);
 320         if (err < 0)
 321                 return err;
 322 
 323         return 0;
 324 }
 325 
 326 static const struct of_device_id mvebu_devbus_of_match[] = {
 327         { .compatible = "marvell,mvebu-devbus" },
 328         { .compatible = "marvell,orion-devbus" },
 329         {},
 330 };
 331 MODULE_DEVICE_TABLE(of, mvebu_devbus_of_match);
 332 
 333 static struct platform_driver mvebu_devbus_driver = {
 334         .probe          = mvebu_devbus_probe,
 335         .driver         = {
 336                 .name   = "mvebu-devbus",
 337                 .of_match_table = mvebu_devbus_of_match,
 338         },
 339 };
 340 
 341 static int __init mvebu_devbus_init(void)
 342 {
 343         return platform_driver_register(&mvebu_devbus_driver);
 344 }
 345 module_init(mvebu_devbus_init);
 346 
 347 MODULE_LICENSE("GPL v2");
 348 MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
 349 MODULE_DESCRIPTION("Marvell EBU SoC Device Bus controller");

/* [<][>][^][v][top][bottom][index][help] */