linux/drivers/bus/uniphier-system-bus.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License as published by
   6 * the Free Software Foundation; either version 2 of the License, or
   7 * (at your option) any later version.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 */
  14
  15#include <linux/io.h>
  16#include <linux/log2.h>
  17#include <linux/module.h>
  18#include <linux/of.h>
  19#include <linux/of_address.h>
  20#include <linux/of_platform.h>
  21#include <linux/platform_device.h>
  22
  23/* System Bus Controller registers */
  24#define UNIPHIER_SBC_BASE       0x100   /* base address of bank0 space */
  25#define    UNIPHIER_SBC_BASE_BE         BIT(0)  /* bank_enable */
  26#define UNIPHIER_SBC_CTRL0      0x200   /* timing parameter 0 of bank0 */
  27#define UNIPHIER_SBC_CTRL1      0x204   /* timing parameter 1 of bank0 */
  28#define UNIPHIER_SBC_CTRL2      0x208   /* timing parameter 2 of bank0 */
  29#define UNIPHIER_SBC_CTRL3      0x20c   /* timing parameter 3 of bank0 */
  30#define UNIPHIER_SBC_CTRL4      0x300   /* timing parameter 4 of bank0 */
  31
  32#define UNIPHIER_SBC_STRIDE     0x10    /* register stride to next bank */
  33#define UNIPHIER_SBC_NR_BANKS   8       /* number of banks (chip select) */
  34#define UNIPHIER_SBC_BASE_DUMMY 0xffffffff      /* data to squash bank 0, 1 */
  35
  36struct uniphier_system_bus_bank {
  37        u32 base;
  38        u32 end;
  39};
  40
  41struct uniphier_system_bus_priv {
  42        struct device *dev;
  43        void __iomem *membase;
  44        struct uniphier_system_bus_bank bank[UNIPHIER_SBC_NR_BANKS];
  45};
  46
  47static int uniphier_system_bus_add_bank(struct uniphier_system_bus_priv *priv,
  48                                        int bank, u32 addr, u64 paddr, u32 size)
  49{
  50        u64 end, mask;
  51
  52        dev_dbg(priv->dev,
  53                "range found: bank = %d, addr = %08x, paddr = %08llx, size = %08x\n",
  54                bank, addr, paddr, size);
  55
  56        if (bank >= ARRAY_SIZE(priv->bank)) {
  57                dev_err(priv->dev, "unsupported bank number %d\n", bank);
  58                return -EINVAL;
  59        }
  60
  61        if (priv->bank[bank].base || priv->bank[bank].end) {
  62                dev_err(priv->dev,
  63                        "range for bank %d has already been specified\n", bank);
  64                return -EINVAL;
  65        }
  66
  67        if (paddr > U32_MAX) {
  68                dev_err(priv->dev, "base address %llx is too high\n", paddr);
  69                return -EINVAL;
  70        }
  71
  72        end = paddr + size;
  73
  74        if (addr > paddr) {
  75                dev_err(priv->dev,
  76                        "base %08x cannot be mapped to %08llx of parent\n",
  77                        addr, paddr);
  78                return -EINVAL;
  79        }
  80        paddr -= addr;
  81
  82        paddr = round_down(paddr, 0x00020000);
  83        end = round_up(end, 0x00020000);
  84
  85        if (end > U32_MAX) {
  86                dev_err(priv->dev, "end address %08llx is too high\n", end);
  87                return -EINVAL;
  88        }
  89        mask = paddr ^ (end - 1);
  90        mask = roundup_pow_of_two(mask);
  91
  92        paddr = round_down(paddr, mask);
  93        end = round_up(end, mask);
  94
  95        priv->bank[bank].base = paddr;
  96        priv->bank[bank].end = end;
  97
  98        dev_dbg(priv->dev, "range added: bank = %d, addr = %08x, end = %08x\n",
  99                bank, priv->bank[bank].base, priv->bank[bank].end);
 100
 101        return 0;
 102}
 103
 104static int uniphier_system_bus_check_overlap(
 105                                const struct uniphier_system_bus_priv *priv)
 106{
 107        int i, j;
 108
 109        for (i = 0; i < ARRAY_SIZE(priv->bank); i++) {
 110                for (j = i + 1; j < ARRAY_SIZE(priv->bank); j++) {
 111                        if (priv->bank[i].end > priv->bank[j].base &&
 112                            priv->bank[i].base < priv->bank[j].end) {
 113                                dev_err(priv->dev,
 114                                        "region overlap between bank%d and bank%d\n",
 115                                        i, j);
 116                                return -EINVAL;
 117                        }
 118                }
 119        }
 120
 121        return 0;
 122}
 123
 124static void uniphier_system_bus_check_boot_swap(
 125                                        struct uniphier_system_bus_priv *priv)
 126{
 127        void __iomem *base_reg = priv->membase + UNIPHIER_SBC_BASE;
 128        int is_swapped;
 129
 130        is_swapped = !(readl(base_reg) & UNIPHIER_SBC_BASE_BE);
 131
 132        dev_dbg(priv->dev, "Boot Swap: %s\n", is_swapped ? "on" : "off");
 133
 134        /*
 135         * If BOOT_SWAP was asserted on power-on-reset, the CS0 and CS1 are
 136         * swapped.  In this case, bank0 and bank1 should be swapped as well.
 137         */
 138        if (is_swapped)
 139                swap(priv->bank[0], priv->bank[1]);
 140}
 141
 142static void uniphier_system_bus_set_reg(
 143                                const struct uniphier_system_bus_priv *priv)
 144{
 145        void __iomem *base_reg = priv->membase + UNIPHIER_SBC_BASE;
 146        u32 base, end, mask, val;
 147        int i;
 148
 149        for (i = 0; i < ARRAY_SIZE(priv->bank); i++) {
 150                base = priv->bank[i].base;
 151                end = priv->bank[i].end;
 152
 153                if (base == end) {
 154                        /*
 155                         * If SBC_BASE0 or SBC_BASE1 is set to zero, the access
 156                         * to anywhere in the system bus space is routed to
 157                         * bank 0 (if boot swap if off) or bank 1 (if boot swap
 158                         * if on).  It means that CPUs cannot get access to
 159                         * bank 2 or later.  In other words, bank 0/1 cannot
 160                         * be disabled even if its bank_enable bits is cleared.
 161                         * This seems odd, but it is how this hardware goes.
 162                         * As a workaround, dummy data (0xffffffff) should be
 163                         * set when the bank 0/1 is unused.  As for bank 2 and
 164                         * later, they can be simply disable by clearing the
 165                         * bank_enable bit.
 166                         */
 167                        if (i < 2)
 168                                val = UNIPHIER_SBC_BASE_DUMMY;
 169                        else
 170                                val = 0;
 171                } else {
 172                        mask = base ^ (end - 1);
 173
 174                        val = base & 0xfffe0000;
 175                        val |= (~mask >> 16) & 0xfffe;
 176                        val |= UNIPHIER_SBC_BASE_BE;
 177                }
 178                dev_dbg(priv->dev, "SBC_BASE[%d] = 0x%08x\n", i, val);
 179
 180                writel(val, base_reg + UNIPHIER_SBC_STRIDE * i);
 181        }
 182}
 183
 184static int uniphier_system_bus_probe(struct platform_device *pdev)
 185{
 186        struct device *dev = &pdev->dev;
 187        struct uniphier_system_bus_priv *priv;
 188        struct resource *regs;
 189        const __be32 *ranges;
 190        u32 cells, addr, size;
 191        u64 paddr;
 192        int pna, bank, rlen, rone, ret;
 193
 194        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 195        if (!priv)
 196                return -ENOMEM;
 197
 198        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 199        priv->membase = devm_ioremap_resource(dev, regs);
 200        if (IS_ERR(priv->membase))
 201                return PTR_ERR(priv->membase);
 202
 203        priv->dev = dev;
 204
 205        pna = of_n_addr_cells(dev->of_node);
 206
 207        ret = of_property_read_u32(dev->of_node, "#address-cells", &cells);
 208        if (ret) {
 209                dev_err(dev, "failed to get #address-cells\n");
 210                return ret;
 211        }
 212        if (cells != 2) {
 213                dev_err(dev, "#address-cells must be 2\n");
 214                return -EINVAL;
 215        }
 216
 217        ret = of_property_read_u32(dev->of_node, "#size-cells", &cells);
 218        if (ret) {
 219                dev_err(dev, "failed to get #size-cells\n");
 220                return ret;
 221        }
 222        if (cells != 1) {
 223                dev_err(dev, "#size-cells must be 1\n");
 224                return -EINVAL;
 225        }
 226
 227        ranges = of_get_property(dev->of_node, "ranges", &rlen);
 228        if (!ranges) {
 229                dev_err(dev, "failed to get ranges property\n");
 230                return -ENOENT;
 231        }
 232
 233        rlen /= sizeof(*ranges);
 234        rone = pna + 2;
 235
 236        for (; rlen >= rone; rlen -= rone) {
 237                bank = be32_to_cpup(ranges++);
 238                addr = be32_to_cpup(ranges++);
 239                paddr = of_translate_address(dev->of_node, ranges);
 240                if (paddr == OF_BAD_ADDR)
 241                        return -EINVAL;
 242                ranges += pna;
 243                size = be32_to_cpup(ranges++);
 244
 245                ret = uniphier_system_bus_add_bank(priv, bank, addr,
 246                                                   paddr, size);
 247                if (ret)
 248                        return ret;
 249        }
 250
 251        ret = uniphier_system_bus_check_overlap(priv);
 252        if (ret)
 253                return ret;
 254
 255        uniphier_system_bus_check_boot_swap(priv);
 256
 257        uniphier_system_bus_set_reg(priv);
 258
 259        platform_set_drvdata(pdev, priv);
 260
 261        /* Now, the bus is configured.  Populate platform_devices below it */
 262        return of_platform_default_populate(dev->of_node, NULL, dev);
 263}
 264
 265static int __maybe_unused uniphier_system_bus_resume(struct device *dev)
 266{
 267        uniphier_system_bus_set_reg(dev_get_drvdata(dev));
 268
 269        return 0;
 270}
 271
 272static const struct dev_pm_ops uniphier_system_bus_pm_ops = {
 273        SET_SYSTEM_SLEEP_PM_OPS(NULL, uniphier_system_bus_resume)
 274};
 275
 276static const struct of_device_id uniphier_system_bus_match[] = {
 277        { .compatible = "socionext,uniphier-system-bus" },
 278        { /* sentinel */ }
 279};
 280MODULE_DEVICE_TABLE(of, uniphier_system_bus_match);
 281
 282static struct platform_driver uniphier_system_bus_driver = {
 283        .probe          = uniphier_system_bus_probe,
 284        .driver = {
 285                .name   = "uniphier-system-bus",
 286                .of_match_table = uniphier_system_bus_match,
 287                .pm = &uniphier_system_bus_pm_ops,
 288        },
 289};
 290module_platform_driver(uniphier_system_bus_driver);
 291
 292MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
 293MODULE_DESCRIPTION("UniPhier System Bus driver");
 294MODULE_LICENSE("GPL");
 295