linux/drivers/memory/mvebu-devbus.c
<<
>>
Prefs
   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
  63struct 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
  73struct devbus_write_params {
  74        u32 sync_enable;
  75        u32 wr_high;
  76        u32 wr_low;
  77        u32 ale_wr;
  78};
  79
  80struct devbus {
  81        struct device *dev;
  82        void __iomem *base;
  83        unsigned long tick_ps;
  84};
  85
  86static 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
 108static 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
 195static 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
 228static 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
 263static 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
 326static const struct of_device_id mvebu_devbus_of_match[] = {
 327        { .compatible = "marvell,mvebu-devbus" },
 328        { .compatible = "marvell,orion-devbus" },
 329        {},
 330};
 331MODULE_DEVICE_TABLE(of, mvebu_devbus_of_match);
 332
 333static 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
 341static int __init mvebu_devbus_init(void)
 342{
 343        return platform_driver_register(&mvebu_devbus_driver);
 344}
 345module_init(mvebu_devbus_init);
 346
 347MODULE_LICENSE("GPL v2");
 348MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
 349MODULE_DESCRIPTION("Marvell EBU SoC Device Bus controller");
 350