uboot/drivers/ram/imxrt_sdram.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2019
   4 * Author(s): Giulio Benetti <giulio.benetti@benettiengineering.com>
   5 */
   6
   7#include <common.h>
   8#include <clk.h>
   9#include <dm.h>
  10#include <dm/device_compat.h>
  11#include <init.h>
  12#include <log.h>
  13#include <ram.h>
  14#include <asm/io.h>
  15#include <linux/bitops.h>
  16#include <linux/delay.h>
  17#include <linux/err.h>
  18
  19/* SDRAM Command Code */
  20#define SD_CC_ARD               0x0     /* Master Bus (AXI) command - Read */
  21#define SD_CC_AWR               0x1     /* Master Bus (AXI) command - Write */
  22#define SD_CC_IRD               0x8     /* IP command - Read */
  23#define SD_CC_IWR               0x9     /* IP command - Write */
  24#define SD_CC_IMS               0xA     /* IP command - Set Mode Register */
  25#define SD_CC_IACT              0xB     /* IP command - ACTIVE */
  26#define SD_CC_IAF               0xC     /* IP command - Auto Refresh */
  27#define SD_CC_ISF               0xD     /* IP Command - Self Refresh */
  28#define SD_CC_IPRE              0xE     /* IP command - Precharge */
  29#define SD_CC_IPREA             0xF     /* IP command - Precharge ALL */
  30
  31#define SEMC_MCR_MDIS           BIT(1)
  32#define SEMC_MCR_DQSMD          BIT(2)
  33
  34#define SEMC_INTR_IPCMDERR      BIT(1)
  35#define SEMC_INTR_IPCMDDONE     BIT(0)
  36
  37#define SEMC_IPCMD_KEY          0xA55A0000
  38
  39struct imxrt_semc_regs {
  40        /* 0x0 */
  41        u32 mcr;
  42        u32 iocr;
  43        u32 bmcr0;
  44        u32 bmcr1;
  45        u32 br[9];
  46
  47        /* 0x34 */
  48        u32 res1;
  49        u32 inten;
  50        u32 intr;
  51        /* 0x40 */
  52        u32 sdramcr0;
  53        u32 sdramcr1;
  54        u32 sdramcr2;
  55        u32 sdramcr3;
  56        /* 0x50 */
  57        u32 nandcr0;
  58        u32 nandcr1;
  59        u32 nandcr2;
  60        u32 nandcr3;
  61        /* 0x60 */
  62        u32 norcr0;
  63        u32 norcr1;
  64        u32 norcr2;
  65        u32 norcr3;
  66        /* 0x70 */
  67        u32 sramcr0;
  68        u32 sramcr1;
  69        u32 sramcr2;
  70        u32 sramcr3;
  71        /* 0x80 */
  72        u32 dbicr0;
  73        u32 dbicr1;
  74        u32 res2[2];
  75        /* 0x90 */
  76        u32 ipcr0;
  77        u32 ipcr1;
  78        u32 ipcr2;
  79        u32 ipcmd;
  80        /* 0xA0 */
  81        u32 iptxdat;
  82        u32 res3[3];
  83        /* 0xB0 */
  84        u32 iprxdat;
  85        u32 res4[3];
  86        /* 0xC0 */
  87        u32 sts[16];
  88};
  89
  90#if !defined(TARGET_IMXRT1170_EVK)
  91#define SEMC_IOCR_MUX_A8_SHIFT          0
  92#define SEMC_IOCR_MUX_CSX0_SHIFT        3
  93#define SEMC_IOCR_MUX_CSX1_SHIFT        6
  94#define SEMC_IOCR_MUX_CSX2_SHIFT        9
  95#define SEMC_IOCR_MUX_CSX3_SHIFT        12
  96#define SEMC_IOCR_MUX_RDY_SHIFT         15
  97#else
  98#define SEMC_IOCR_MUX_A8_SHIFT          0
  99#define SEMC_IOCR_MUX_CSX0_SHIFT        4
 100#define SEMC_IOCR_MUX_CSX1_SHIFT        8
 101#define SEMC_IOCR_MUX_CSX2_SHIFT        12
 102#define SEMC_IOCR_MUX_CSX3_SHIFT        16
 103#define SEMC_IOCR_MUX_RDY_SHIFT         20
 104#endif
 105
 106struct imxrt_sdram_mux {
 107        u8 a8;
 108        u8 csx0;
 109        u8 csx1;
 110        u8 csx2;
 111        u8 csx3;
 112        u8 rdy;
 113};
 114
 115#define SEMC_SDRAMCR0_PS_SHIFT          0
 116#define SEMC_SDRAMCR0_BL_SHIFT          4
 117#define SEMC_SDRAMCR0_COL_SHIFT         8
 118#define SEMC_SDRAMCR0_CL_SHIFT          10
 119
 120struct imxrt_sdram_control {
 121        u8 memory_width;
 122        u8 burst_len;
 123        u8 no_columns;
 124        u8 cas_latency;
 125};
 126
 127#define SEMC_SDRAMCR1_PRE2ACT_SHIFT     0
 128#define SEMC_SDRAMCR1_ACT2RW_SHIFT      4
 129#define SEMC_SDRAMCR1_RFRC_SHIFT        8
 130#define SEMC_SDRAMCR1_WRC_SHIFT         13
 131#define SEMC_SDRAMCR1_CKEOFF_SHIFT      16
 132#define SEMC_SDRAMCR1_ACT2PRE_SHIFT     20
 133
 134#define SEMC_SDRAMCR2_SRRC_SHIFT        0
 135#define SEMC_SDRAMCR2_REF2REF_SHIFT     8
 136#define SEMC_SDRAMCR2_ACT2ACT_SHIFT     16
 137#define SEMC_SDRAMCR2_ITO_SHIFT         24
 138
 139#define SEMC_SDRAMCR3_REN               BIT(0)
 140#define SEMC_SDRAMCR3_REBL_SHIFT        1
 141#define SEMC_SDRAMCR3_PRESCALE_SHIFT    8
 142#define SEMC_SDRAMCR3_RT_SHIFT          16
 143#define SEMC_SDRAMCR3_UT_SHIFT          24
 144
 145struct imxrt_sdram_timing {
 146        u8 pre2act;
 147        u8 act2rw;
 148        u8 rfrc;
 149        u8 wrc;
 150        u8 ckeoff;
 151        u8 act2pre;
 152
 153        u8 srrc;
 154        u8 ref2ref;
 155        u8 act2act;
 156        u8 ito;
 157
 158        u8 rebl;
 159        u8 prescale;
 160        u8 rt;
 161        u8 ut;
 162};
 163
 164enum imxrt_semc_bank {
 165        SDRAM_BANK1,
 166        SDRAM_BANK2,
 167        SDRAM_BANK3,
 168        SDRAM_BANK4,
 169        MAX_SDRAM_BANK,
 170};
 171
 172#define SEMC_BR_VLD_MASK                1
 173#define SEMC_BR_MS_SHIFT                1
 174
 175struct bank_params {
 176        enum imxrt_semc_bank target_bank;
 177        u32 base_address;
 178        u32 memory_size;
 179};
 180
 181struct imxrt_sdram_params {
 182        struct imxrt_semc_regs *base;
 183
 184        struct imxrt_sdram_mux *sdram_mux;
 185        struct imxrt_sdram_control *sdram_control;
 186        struct imxrt_sdram_timing *sdram_timing;
 187
 188        struct bank_params bank_params[MAX_SDRAM_BANK];
 189        u8 no_sdram_banks;
 190};
 191
 192static int imxrt_sdram_wait_ipcmd_done(struct imxrt_semc_regs *regs)
 193{
 194        do {
 195                readl(&regs->intr);
 196
 197                if (regs->intr & SEMC_INTR_IPCMDDONE)
 198                        return 0;
 199                if (regs->intr & SEMC_INTR_IPCMDERR)
 200                        return -EIO;
 201
 202                mdelay(50);
 203        } while (1);
 204}
 205
 206static int imxrt_sdram_ipcmd(struct imxrt_semc_regs *regs, u32 mem_addr,
 207                             u32 ipcmd, u32 wd, u32 *rd)
 208{
 209        int ret;
 210
 211        if (ipcmd == SD_CC_IWR || ipcmd == SD_CC_IMS)
 212                writel(wd, &regs->iptxdat);
 213
 214        /* set slave address for every command as specified on RM */
 215        writel(mem_addr, &regs->ipcr0);
 216
 217        /* execute command */
 218        writel(SEMC_IPCMD_KEY | ipcmd, &regs->ipcmd);
 219
 220        ret = imxrt_sdram_wait_ipcmd_done(regs);
 221        if (ret < 0)
 222                return ret;
 223
 224        if (ipcmd == SD_CC_IRD) {
 225                if (!rd)
 226                        return -EINVAL;
 227
 228                *rd = readl(&regs->iprxdat);
 229        }
 230
 231        return 0;
 232}
 233
 234int imxrt_sdram_init(struct udevice *dev)
 235{
 236        struct imxrt_sdram_params *params = dev_get_plat(dev);
 237        struct imxrt_sdram_mux *mux = params->sdram_mux;
 238        struct imxrt_sdram_control *ctrl = params->sdram_control;
 239        struct imxrt_sdram_timing *time = params->sdram_timing;
 240        struct imxrt_semc_regs *regs = params->base;
 241        struct bank_params *bank_params;
 242        u32 rd;
 243        int i;
 244
 245        /* enable the SEMC controller */
 246        clrbits_le32(&regs->mcr, SEMC_MCR_MDIS);
 247        /* set DQS mode from DQS pad */
 248        setbits_le32(&regs->mcr, SEMC_MCR_DQSMD);
 249
 250        for (i = 0, bank_params = params->bank_params;
 251                i < params->no_sdram_banks; bank_params++,
 252                i++)
 253                writel((bank_params->base_address & 0xfffff000)
 254                       | bank_params->memory_size << SEMC_BR_MS_SHIFT
 255                       | SEMC_BR_VLD_MASK,
 256                       &regs->br[bank_params->target_bank]);
 257
 258        writel(mux->a8 << SEMC_IOCR_MUX_A8_SHIFT
 259                | mux->csx0 << SEMC_IOCR_MUX_CSX0_SHIFT
 260                | mux->csx1 << SEMC_IOCR_MUX_CSX1_SHIFT
 261                | mux->csx2 << SEMC_IOCR_MUX_CSX2_SHIFT
 262                | mux->csx3 << SEMC_IOCR_MUX_CSX3_SHIFT
 263                | mux->rdy << SEMC_IOCR_MUX_RDY_SHIFT,
 264                &regs->iocr);
 265
 266        writel(ctrl->memory_width << SEMC_SDRAMCR0_PS_SHIFT
 267                | ctrl->burst_len << SEMC_SDRAMCR0_BL_SHIFT
 268                | ctrl->no_columns << SEMC_SDRAMCR0_COL_SHIFT
 269                | ctrl->cas_latency << SEMC_SDRAMCR0_CL_SHIFT,
 270                &regs->sdramcr0);
 271
 272        writel(time->pre2act << SEMC_SDRAMCR1_PRE2ACT_SHIFT
 273                | time->act2rw << SEMC_SDRAMCR1_ACT2RW_SHIFT
 274                | time->rfrc << SEMC_SDRAMCR1_RFRC_SHIFT
 275                | time->wrc << SEMC_SDRAMCR1_WRC_SHIFT
 276                | time->ckeoff << SEMC_SDRAMCR1_CKEOFF_SHIFT
 277                | time->act2pre << SEMC_SDRAMCR1_ACT2PRE_SHIFT,
 278                &regs->sdramcr1);
 279
 280        writel(time->srrc << SEMC_SDRAMCR2_SRRC_SHIFT
 281                | time->ref2ref << SEMC_SDRAMCR2_REF2REF_SHIFT
 282                | time->act2act << SEMC_SDRAMCR2_ACT2ACT_SHIFT
 283                | time->ito << SEMC_SDRAMCR2_ITO_SHIFT,
 284                &regs->sdramcr2);
 285
 286        writel(time->rebl << SEMC_SDRAMCR3_REBL_SHIFT
 287                | time->prescale << SEMC_SDRAMCR3_PRESCALE_SHIFT
 288                | time->rt << SEMC_SDRAMCR3_RT_SHIFT
 289                | time->ut << SEMC_SDRAMCR3_UT_SHIFT
 290                | SEMC_SDRAMCR3_REN,
 291                &regs->sdramcr3);
 292
 293        writel(2, &regs->ipcr1);
 294
 295        for (i = 0, bank_params = params->bank_params;
 296                i < params->no_sdram_banks; bank_params++,
 297                i++) {
 298                mdelay(250);
 299                imxrt_sdram_ipcmd(regs, bank_params->base_address, SD_CC_IPREA,
 300                                  0, &rd);
 301                imxrt_sdram_ipcmd(regs, bank_params->base_address, SD_CC_IAF,
 302                                  0, &rd);
 303                imxrt_sdram_ipcmd(regs, bank_params->base_address, SD_CC_IAF,
 304                                  0, &rd);
 305                imxrt_sdram_ipcmd(regs, bank_params->base_address, SD_CC_IMS,
 306                                  ctrl->burst_len | (ctrl->cas_latency << 4),
 307                                  &rd);
 308                mdelay(250);
 309        }
 310
 311        return 0;
 312}
 313
 314static int imxrt_semc_of_to_plat(struct udevice *dev)
 315{
 316        struct imxrt_sdram_params *params = dev_get_plat(dev);
 317        ofnode bank_node;
 318        u8 bank = 0;
 319
 320        params->sdram_mux =
 321                (struct imxrt_sdram_mux *)
 322                 dev_read_u8_array_ptr(dev,
 323                                       "fsl,sdram-mux",
 324                                       sizeof(struct imxrt_sdram_mux));
 325        if (!params->sdram_mux) {
 326                pr_err("fsl,sdram-mux not found");
 327                return -EINVAL;
 328        }
 329
 330        params->sdram_control =
 331                (struct imxrt_sdram_control *)
 332                 dev_read_u8_array_ptr(dev,
 333                                       "fsl,sdram-control",
 334                                       sizeof(struct imxrt_sdram_control));
 335        if (!params->sdram_control) {
 336                pr_err("fsl,sdram-control not found");
 337                return -EINVAL;
 338        }
 339
 340        params->sdram_timing =
 341                (struct imxrt_sdram_timing *)
 342                 dev_read_u8_array_ptr(dev,
 343                                       "fsl,sdram-timing",
 344                                       sizeof(struct imxrt_sdram_timing));
 345        if (!params->sdram_timing) {
 346                pr_err("fsl,sdram-timing not found");
 347                return -EINVAL;
 348        }
 349
 350        dev_for_each_subnode(bank_node, dev) {
 351                struct bank_params *bank_params;
 352                char *bank_name;
 353                int ret;
 354
 355                /* extract the bank index from DT */
 356                bank_name = (char *)ofnode_get_name(bank_node);
 357                strsep(&bank_name, "@");
 358                if (!bank_name) {
 359                        pr_err("missing sdram bank index");
 360                        return -EINVAL;
 361                }
 362
 363                bank_params = &params->bank_params[bank];
 364                strict_strtoul(bank_name, 10,
 365                               (unsigned long *)&bank_params->target_bank);
 366                if (bank_params->target_bank >= MAX_SDRAM_BANK) {
 367                        pr_err("Found bank %d , but only bank 0,1,2,3 are supported",
 368                               bank_params->target_bank);
 369                        return -EINVAL;
 370                }
 371
 372                ret = ofnode_read_u32(bank_node,
 373                                      "fsl,memory-size",
 374                                      &bank_params->memory_size);
 375                if (ret < 0) {
 376                        pr_err("fsl,memory-size not found");
 377                        return -EINVAL;
 378                }
 379
 380                ret = ofnode_read_u32(bank_node,
 381                                      "fsl,base-address",
 382                                      &bank_params->base_address);
 383                if (ret < 0) {
 384                        pr_err("fsl,base-address not found");
 385                        return -EINVAL;
 386                }
 387
 388                debug("Found bank %s %u\n", bank_name,
 389                      bank_params->target_bank);
 390                bank++;
 391        }
 392
 393        params->no_sdram_banks = bank;
 394        debug("%s, no of banks = %d\n", __func__, params->no_sdram_banks);
 395
 396        return 0;
 397}
 398
 399static int imxrt_semc_probe(struct udevice *dev)
 400{
 401        struct imxrt_sdram_params *params = dev_get_plat(dev);
 402        int ret;
 403        fdt_addr_t addr;
 404
 405        addr = dev_read_addr(dev);
 406        if (addr == FDT_ADDR_T_NONE)
 407                return -EINVAL;
 408
 409        params->base = (struct imxrt_semc_regs *)addr;
 410
 411#ifdef CONFIG_CLK
 412        struct clk clk;
 413
 414        ret = clk_get_by_index(dev, 0, &clk);
 415        if (ret < 0)
 416                return ret;
 417
 418        ret = clk_enable(&clk);
 419
 420        if (ret) {
 421                dev_err(dev, "failed to enable clock\n");
 422                return ret;
 423        }
 424#endif
 425        ret = imxrt_sdram_init(dev);
 426        if (ret)
 427                return ret;
 428
 429        return 0;
 430}
 431
 432static int imxrt_semc_get_info(struct udevice *dev, struct ram_info *info)
 433{
 434        return 0;
 435}
 436
 437static struct ram_ops imxrt_semc_ops = {
 438        .get_info = imxrt_semc_get_info,
 439};
 440
 441static const struct udevice_id imxrt_semc_ids[] = {
 442        { .compatible = "fsl,imxrt-semc", .data = 0 },
 443        { }
 444};
 445
 446U_BOOT_DRIVER(imxrt_semc) = {
 447        .name = "imxrt_semc",
 448        .id = UCLASS_RAM,
 449        .of_match = imxrt_semc_ids,
 450        .ops = &imxrt_semc_ops,
 451        .of_to_plat = imxrt_semc_of_to_plat,
 452        .probe = imxrt_semc_probe,
 453        .plat_auto      = sizeof(struct imxrt_sdram_params),
 454};
 455