uboot/drivers/mtd/renesas_rpc_hf.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Renesas RCar Gen3 RPC HyperFlash driver
   4 *
   5 * Copyright (C) 2016 Renesas Electronics Corporation
   6 * Copyright (C) 2016 Cogent Embedded, Inc.
   7 * Copyright (C) 2017 Marek Vasut <marek.vasut@gmail.com>
   8 */
   9
  10#include <common.h>
  11#include <malloc.h>
  12#include <asm/io.h>
  13#include <clk.h>
  14#include <dm.h>
  15#include <dm/device_compat.h>
  16#include <dm/of_access.h>
  17#include <errno.h>
  18#include <fdt_support.h>
  19#include <flash.h>
  20#include <mtd.h>
  21#include <wait_bit.h>
  22#include <linux/bitops.h>
  23#include <mtd/cfi_flash.h>
  24#include <asm/global_data.h>
  25
  26#define RPC_CMNCR               0x0000  /* R/W */
  27#define RPC_CMNCR_MD            BIT(31)
  28#define RPC_CMNCR_MOIIO0(val)   (((val) & 0x3) << 16)
  29#define RPC_CMNCR_MOIIO1(val)   (((val) & 0x3) << 18)
  30#define RPC_CMNCR_MOIIO2(val)   (((val) & 0x3) << 20)
  31#define RPC_CMNCR_MOIIO3(val)   (((val) & 0x3) << 22)
  32#define RPC_CMNCR_MOIIO_HIZ     (RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
  33                                 RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
  34#define RPC_CMNCR_IO0FV(val)    (((val) & 0x3) << 8)
  35#define RPC_CMNCR_IO2FV(val)    (((val) & 0x3) << 12)
  36#define RPC_CMNCR_IO3FV(val)    (((val) & 0x3) << 14)
  37#define RPC_CMNCR_IOFV_HIZ      (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
  38                                 RPC_CMNCR_IO3FV(3))
  39#define RPC_CMNCR_BSZ(val)      (((val) & 0x3) << 0)
  40
  41#define RPC_SSLDR               0x0004  /* R/W */
  42#define RPC_SSLDR_SPNDL(d)      (((d) & 0x7) << 16)
  43#define RPC_SSLDR_SLNDL(d)      (((d) & 0x7) << 8)
  44#define RPC_SSLDR_SCKDL(d)      (((d) & 0x7) << 0)
  45
  46#define RPC_DRCR                0x000C  /* R/W */
  47#define RPC_DRCR_SSLN           BIT(24)
  48#define RPC_DRCR_RBURST(v)      (((v) & 0x1F) << 16)
  49#define RPC_DRCR_RCF            BIT(9)
  50#define RPC_DRCR_RBE            BIT(8)
  51#define RPC_DRCR_SSLE           BIT(0)
  52
  53#define RPC_DRCMR               0x0010  /* R/W */
  54#define RPC_DRCMR_CMD(c)        (((c) & 0xFF) << 16)
  55#define RPC_DRCMR_OCMD(c)       (((c) & 0xFF) << 0)
  56
  57#define RPC_DREAR               0x0014  /* R/W */
  58#define RPC_DREAR_EAV(v)        (((v) & 0xFF) << 16)
  59#define RPC_DREAR_EAC(v)        (((v) & 0x7) << 0)
  60
  61#define RPC_DROPR               0x0018  /* R/W */
  62#define RPC_DROPR_OPD3(o)       (((o) & 0xFF) << 24)
  63#define RPC_DROPR_OPD2(o)       (((o) & 0xFF) << 16)
  64#define RPC_DROPR_OPD1(o)       (((o) & 0xFF) << 8)
  65#define RPC_DROPR_OPD0(o)       (((o) & 0xFF) << 0)
  66
  67#define RPC_DRENR               0x001C  /* R/W */
  68#define RPC_DRENR_CDB(o)        (u32)((((o) & 0x3) << 30))
  69#define RPC_DRENR_OCDB(o)       (((o) & 0x3) << 28)
  70#define RPC_DRENR_ADB(o)        (((o) & 0x3) << 24)
  71#define RPC_DRENR_OPDB(o)       (((o) & 0x3) << 20)
  72#define RPC_DRENR_SPIDB(o)      (((o) & 0x3) << 16)
  73#define RPC_DRENR_DME           BIT(15)
  74#define RPC_DRENR_CDE           BIT(14)
  75#define RPC_DRENR_OCDE          BIT(12)
  76#define RPC_DRENR_ADE(v)        (((v) & 0xF) << 8)
  77#define RPC_DRENR_OPDE(v)       (((v) & 0xF) << 4)
  78
  79#define RPC_SMCR                0x0020  /* R/W */
  80#define RPC_SMCR_SSLKP          BIT(8)
  81#define RPC_SMCR_SPIRE          BIT(2)
  82#define RPC_SMCR_SPIWE          BIT(1)
  83#define RPC_SMCR_SPIE           BIT(0)
  84
  85#define RPC_SMCMR               0x0024  /* R/W */
  86#define RPC_SMCMR_CMD(c)        (((c) & 0xFF) << 16)
  87#define RPC_SMCMR_OCMD(c)       (((c) & 0xFF) << 0)
  88
  89#define RPC_SMADR               0x0028  /* R/W */
  90#define RPC_SMOPR               0x002C  /* R/W */
  91#define RPC_SMOPR_OPD0(o)       (((o) & 0xFF) << 0)
  92#define RPC_SMOPR_OPD1(o)       (((o) & 0xFF) << 8)
  93#define RPC_SMOPR_OPD2(o)       (((o) & 0xFF) << 16)
  94#define RPC_SMOPR_OPD3(o)       (((o) & 0xFF) << 24)
  95
  96#define RPC_SMENR               0x0030  /* R/W */
  97#define RPC_SMENR_CDB(o)        (((o) & 0x3) << 30)
  98#define RPC_SMENR_OCDB(o)       (((o) & 0x3) << 28)
  99#define RPC_SMENR_ADB(o)        (((o) & 0x3) << 24)
 100#define RPC_SMENR_OPDB(o)       (((o) & 0x3) << 20)
 101#define RPC_SMENR_SPIDB(o)      (((o) & 0x3) << 16)
 102#define RPC_SMENR_DME           BIT(15)
 103#define RPC_SMENR_CDE           BIT(14)
 104#define RPC_SMENR_OCDE          BIT(12)
 105#define RPC_SMENR_ADE(v)        (((v) & 0xF) << 8)
 106#define RPC_SMENR_OPDE(v)       (((v) & 0xF) << 4)
 107#define RPC_SMENR_SPIDE(v)      (((v) & 0xF) << 0)
 108
 109#define RPC_SMRDR0              0x0038  /* R */
 110#define RPC_SMRDR1              0x003C  /* R */
 111#define RPC_SMWDR0              0x0040  /* R/W */
 112#define RPC_SMWDR1              0x0044  /* R/W */
 113#define RPC_CMNSR               0x0048  /* R */
 114#define RPC_CMNSR_SSLF          BIT(1)
 115#define RPC_CMNSR_TEND          BIT(0)
 116
 117#define RPC_DRDMCR              0x0058  /* R/W */
 118#define RPC_DRDMCR_DMCYC(v)     (((v) & 0xF) << 0)
 119
 120#define RPC_DRDRENR             0x005C  /* R/W */
 121#define RPC_DRDRENR_HYPE        (0x5 << 12)
 122#define RPC_DRDRENR_ADDRE       BIT(8)
 123#define RPC_DRDRENR_OPDRE       BIT(4)
 124#define RPC_DRDRENR_DRDRE       BIT(0)
 125
 126#define RPC_SMDMCR              0x0060  /* R/W */
 127#define RPC_SMDMCR_DMCYC(v)     (((v) & 0xF) << 0)
 128
 129#define RPC_SMDRENR             0x0064  /* R/W */
 130#define RPC_SMDRENR_HYPE        (0x5 << 12)
 131#define RPC_SMDRENR_ADDRE       BIT(8)
 132#define RPC_SMDRENR_OPDRE       BIT(4)
 133#define RPC_SMDRENR_SPIDRE      BIT(0)
 134
 135#define RPC_PHYCNT              0x007C  /* R/W */
 136#define RPC_PHYCNT_CAL          BIT(31)
 137#define PRC_PHYCNT_OCTA_AA      BIT(22)
 138#define PRC_PHYCNT_OCTA_SA      BIT(23)
 139#define PRC_PHYCNT_EXDS         BIT(21)
 140#define RPC_PHYCNT_OCT          BIT(20)
 141#define RPC_PHYCNT_WBUF2        BIT(4)
 142#define RPC_PHYCNT_WBUF         BIT(2)
 143#define RPC_PHYCNT_MEM(v)       (((v) & 0x3) << 0)
 144
 145#define RPC_PHYINT              0x0088  /* R/W */
 146#define RPC_PHYINT_RSTEN        BIT(18)
 147#define RPC_PHYINT_WPEN         BIT(17)
 148#define RPC_PHYINT_INTEN        BIT(16)
 149#define RPC_PHYINT_RST          BIT(2)
 150#define RPC_PHYINT_WP           BIT(1)
 151#define RPC_PHYINT_INT          BIT(0)
 152
 153#define RPC_WBUF                0x8000  /* R/W size=4/8/16/32/64Bytes */
 154#define RPC_WBUF_SIZE           0x100
 155
 156static phys_addr_t rpc_base;
 157
 158enum rpc_hf_size {
 159        RPC_HF_SIZE_16BIT = RPC_SMENR_SPIDE(0x8),
 160        RPC_HF_SIZE_32BIT = RPC_SMENR_SPIDE(0xC),
 161        RPC_HF_SIZE_64BIT = RPC_SMENR_SPIDE(0xF),
 162};
 163
 164static int rpc_hf_wait_tend(void)
 165{
 166        void __iomem *reg = (void __iomem *)rpc_base + RPC_CMNSR;
 167        return wait_for_bit_le32(reg, RPC_CMNSR_TEND, true, 1000, 0);
 168}
 169
 170static int rpc_hf_mode(bool man)
 171{
 172        int ret;
 173
 174        ret = rpc_hf_wait_tend();
 175        if (ret)
 176                return ret;
 177
 178        clrsetbits_le32(rpc_base + RPC_PHYCNT,
 179                 RPC_PHYCNT_WBUF | RPC_PHYCNT_WBUF2 |
 180                 RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3),
 181                 RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3));
 182
 183        clrsetbits_le32(rpc_base + RPC_CMNCR,
 184                 RPC_CMNCR_MD | RPC_CMNCR_BSZ(3),
 185                 RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ |
 186                 (man ? RPC_CMNCR_MD : 0) | RPC_CMNCR_BSZ(1));
 187
 188        if (man)
 189                return 0;
 190
 191        writel(RPC_DRCR_RBURST(0x1F) | RPC_DRCR_RCF | RPC_DRCR_RBE,
 192               rpc_base + RPC_DRCR);
 193
 194        writel(RPC_DRCMR_CMD(0xA0), rpc_base + RPC_DRCMR);
 195        writel(RPC_DRENR_CDB(2) | RPC_DRENR_OCDB(2) | RPC_DRENR_ADB(2) |
 196               RPC_DRENR_SPIDB(2) | RPC_DRENR_CDE | RPC_DRENR_OCDE |
 197               RPC_DRENR_ADE(4), rpc_base + RPC_DRENR);
 198        writel(RPC_DRDMCR_DMCYC(0xE), rpc_base + RPC_DRDMCR);
 199        writel(RPC_DRDRENR_HYPE | RPC_DRDRENR_ADDRE | RPC_DRDRENR_DRDRE,
 200               rpc_base + RPC_DRDRENR);
 201
 202        /* Dummy read */
 203        readl(rpc_base + RPC_DRCR);
 204
 205        return 0;
 206}
 207
 208static int rpc_hf_xfer(void *addr, u64 wdata, u64 *rdata,
 209                       enum rpc_hf_size size, bool write)
 210{
 211        int ret;
 212        u32 val;
 213
 214        ret = rpc_hf_mode(1);
 215        if (ret)
 216                return ret;
 217
 218        /* Submit HF address, SMCMR CMD[7] ~= CA Bit# 47 (R/nW) */
 219        writel(write ? 0 : RPC_SMCMR_CMD(0x80), rpc_base + RPC_SMCMR);
 220        writel((uintptr_t)addr >> 1, rpc_base + RPC_SMADR);
 221        writel(0x0, rpc_base + RPC_SMOPR);
 222
 223        writel(RPC_SMDRENR_HYPE | RPC_SMDRENR_ADDRE | RPC_SMDRENR_SPIDRE,
 224               rpc_base + RPC_SMDRENR);
 225
 226        val = RPC_SMENR_CDB(2) | RPC_SMENR_OCDB(2) |
 227              RPC_SMENR_ADB(2) | RPC_SMENR_SPIDB(2) |
 228              RPC_SMENR_CDE | RPC_SMENR_OCDE | RPC_SMENR_ADE(4) | size;
 229
 230        if (write) {
 231                writel(val, rpc_base + RPC_SMENR);
 232
 233                if (size == RPC_HF_SIZE_64BIT)
 234                        writeq(cpu_to_be64(wdata), rpc_base + RPC_SMWDR0);
 235                else
 236                        writel(cpu_to_be32(wdata), rpc_base + RPC_SMWDR0);
 237
 238                writel(RPC_SMCR_SPIWE | RPC_SMCR_SPIE, rpc_base + RPC_SMCR);
 239        } else {
 240                val |= RPC_SMENR_DME;
 241
 242                writel(RPC_SMDMCR_DMCYC(0xE), rpc_base + RPC_SMDMCR);
 243
 244                writel(val, rpc_base + RPC_SMENR);
 245
 246                writel(RPC_SMCR_SPIRE | RPC_SMCR_SPIE, rpc_base + RPC_SMCR);
 247
 248                ret = rpc_hf_wait_tend();
 249                if (ret)
 250                        return ret;
 251
 252                if (size == RPC_HF_SIZE_64BIT)
 253                        *rdata = be64_to_cpu(readq(rpc_base + RPC_SMRDR0));
 254                else
 255                        *rdata = be32_to_cpu(readl(rpc_base + RPC_SMRDR0));
 256        }
 257
 258        return rpc_hf_mode(0);
 259}
 260
 261static void rpc_hf_write_cmd(void *addr, u64 wdata, enum rpc_hf_size size)
 262{
 263        int ret;
 264
 265        ret = rpc_hf_xfer(addr, wdata, NULL, size, 1);
 266        if (ret)
 267                printf("RPC: Write failed, ret=%i\n", ret);
 268}
 269
 270static u64 rpc_hf_read_reg(void *addr, enum rpc_hf_size size)
 271{
 272        u64 rdata = 0;
 273        int ret;
 274
 275        ret = rpc_hf_xfer(addr, 0, &rdata, size, 0);
 276        if (ret)
 277                printf("RPC: Read failed, ret=%i\n", ret);
 278
 279        return rdata;
 280}
 281
 282void flash_write8(u8 value, void *addr)
 283{
 284        rpc_hf_write_cmd(addr, value, RPC_HF_SIZE_16BIT);
 285}
 286
 287void flash_write16(u16 value, void *addr)
 288{
 289        rpc_hf_write_cmd(addr, value, RPC_HF_SIZE_16BIT);
 290}
 291
 292void flash_write32(u32 value, void *addr)
 293{
 294        rpc_hf_write_cmd(addr, value, RPC_HF_SIZE_32BIT);
 295}
 296
 297void flash_write64(u64 value, void *addr)
 298{
 299        rpc_hf_write_cmd(addr, value, RPC_HF_SIZE_64BIT);
 300}
 301
 302u8 flash_read8(void *addr)
 303{
 304        return rpc_hf_read_reg(addr, RPC_HF_SIZE_16BIT);
 305}
 306
 307u16 flash_read16(void *addr)
 308{
 309        return rpc_hf_read_reg(addr, RPC_HF_SIZE_16BIT);
 310}
 311
 312u32 flash_read32(void *addr)
 313{
 314        return rpc_hf_read_reg(addr, RPC_HF_SIZE_32BIT);
 315}
 316
 317u64 flash_read64(void *addr)
 318{
 319        return rpc_hf_read_reg(addr, RPC_HF_SIZE_64BIT);
 320}
 321
 322static int rpc_hf_bind(struct udevice *parent)
 323{
 324        const void *fdt = gd->fdt_blob;
 325        ofnode node;
 326        int ret, off;
 327
 328        /*
 329         * Check if there are any SPI NOR child nodes, if so, do NOT bind
 330         * as this controller will be operated by the QSPI driver instead.
 331         */
 332        dev_for_each_subnode(node, parent) {
 333                off = ofnode_to_offset(node);
 334
 335                ret = fdt_node_check_compatible(fdt, off, "spi-flash");
 336                if (!ret)
 337                        return -ENODEV;
 338
 339                ret = fdt_node_check_compatible(fdt, off, "jedec,spi-nor");
 340                if (!ret)
 341                        return -ENODEV;
 342        }
 343
 344        return 0;
 345}
 346
 347static int rpc_hf_probe(struct udevice *dev)
 348{
 349        void *blob = (void *)gd->fdt_blob;
 350        const fdt32_t *cell;
 351        int node = dev_of_offset(dev);
 352        int parent, addrc, sizec, len, ret;
 353        struct clk clk;
 354        phys_addr_t flash_base;
 355
 356        parent = fdt_parent_offset(blob, node);
 357        fdt_support_default_count_cells(blob, parent, &addrc, &sizec);
 358        cell = fdt_getprop(blob, node, "reg", &len);
 359        if (!cell)
 360                return -ENOENT;
 361
 362        if (addrc != 2 || sizec != 2)
 363                return -EINVAL;
 364
 365
 366        ret = clk_get_by_index(dev, 0, &clk);
 367        if (ret < 0) {
 368                dev_err(dev, "Failed to get RPC clock\n");
 369                return ret;
 370        }
 371
 372        ret = clk_enable(&clk);
 373        clk_free(&clk);
 374        if (ret) {
 375                dev_err(dev, "Failed to enable RPC clock\n");
 376                return ret;
 377        }
 378
 379        rpc_base = fdt_translate_address(blob, node, cell);
 380        flash_base = fdt_translate_address(blob, node, cell + addrc + sizec);
 381
 382        flash_info[0].dev = dev;
 383        flash_info[0].base = flash_base;
 384        cfi_flash_num_flash_banks = 1;
 385        gd->bd->bi_flashstart = flash_base;
 386
 387        return 0;
 388}
 389
 390static const struct udevice_id rpc_hf_ids[] = {
 391        { .compatible = "renesas,rpc" },
 392        {}
 393};
 394
 395U_BOOT_DRIVER(rpc_hf) = {
 396        .name           = "rpc_hf",
 397        .id             = UCLASS_MTD,
 398        .of_match       = rpc_hf_ids,
 399        .bind           = rpc_hf_bind,
 400        .probe          = rpc_hf_probe,
 401};
 402