uboot/drivers/ram/stm32mp1/stm32mp1_ram.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
   2/*
   3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
   4 */
   5
   6#include <common.h>
   7#include <clk.h>
   8#include <dm.h>
   9#include <ram.h>
  10#include <regmap.h>
  11#include <syscon.h>
  12#include <asm/io.h>
  13#include "stm32mp1_ddr.h"
  14
  15static const char *const clkname[] = {
  16        "ddrc1",
  17        "ddrc2",
  18        "ddrcapb",
  19        "ddrphycapb",
  20        "ddrphyc" /* LAST clock => used for get_rate() */
  21};
  22
  23int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed)
  24{
  25        unsigned long ddrphy_clk;
  26        unsigned long ddr_clk;
  27        struct clk clk;
  28        int ret;
  29        int idx;
  30
  31        for (idx = 0; idx < ARRAY_SIZE(clkname); idx++) {
  32                ret = clk_get_by_name(priv->dev, clkname[idx], &clk);
  33
  34                if (!ret)
  35                        ret = clk_enable(&clk);
  36
  37                if (ret) {
  38                        printf("error for %s : %d\n", clkname[idx], ret);
  39                        return ret;
  40                }
  41        }
  42
  43        priv->clk = clk;
  44        ddrphy_clk = clk_get_rate(&priv->clk);
  45
  46        debug("DDR: mem_speed (%d MHz), RCC %d MHz\n",
  47              mem_speed, (u32)(ddrphy_clk / 1000 / 1000));
  48        /* max 10% frequency delta */
  49        ddr_clk = abs(ddrphy_clk - mem_speed * 1000 * 1000);
  50        if (ddr_clk > (mem_speed * 1000 * 100)) {
  51                pr_err("DDR expected freq %d MHz, current is %d MHz\n",
  52                       mem_speed, (u32)(ddrphy_clk / 1000 / 1000));
  53                return -EINVAL;
  54        }
  55
  56        return 0;
  57}
  58
  59static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev)
  60{
  61        struct ddr_info *priv = dev_get_priv(dev);
  62        int ret, idx;
  63        struct clk axidcg;
  64        struct stm32mp1_ddr_config config;
  65
  66#define PARAM(x, y) \
  67        { x,\
  68          offsetof(struct stm32mp1_ddr_config, y),\
  69          sizeof(config.y) / sizeof(u32)}
  70
  71#define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x)
  72#define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x)
  73
  74        const struct {
  75                const char *name; /* name in DT */
  76                const u32 offset; /* offset in config struct */
  77                const u32 size;   /* size of parameters */
  78        } param[] = {
  79                CTL_PARAM(reg),
  80                CTL_PARAM(timing),
  81                CTL_PARAM(map),
  82                CTL_PARAM(perf),
  83                PHY_PARAM(reg),
  84                PHY_PARAM(timing),
  85                PHY_PARAM(cal)
  86        };
  87
  88        config.info.speed = dev_read_u32_default(dev, "st,mem-speed", 0);
  89        config.info.size = dev_read_u32_default(dev, "st,mem-size", 0);
  90        config.info.name = dev_read_string(dev, "st,mem-name");
  91        if (!config.info.name) {
  92                debug("%s: no st,mem-name\n", __func__);
  93                return -EINVAL;
  94        }
  95        printf("RAM: %s\n", config.info.name);
  96
  97        for (idx = 0; idx < ARRAY_SIZE(param); idx++) {
  98                ret = dev_read_u32_array(dev, param[idx].name,
  99                                         (void *)((u32)&config +
 100                                                  param[idx].offset),
 101                                         param[idx].size);
 102                debug("%s: %s[0x%x] = %d\n", __func__,
 103                      param[idx].name, param[idx].size, ret);
 104                if (ret) {
 105                        pr_err("%s: Cannot read %s\n",
 106                               __func__, param[idx].name);
 107                        return -EINVAL;
 108                }
 109        }
 110
 111        ret = clk_get_by_name(dev, "axidcg", &axidcg);
 112        if (ret) {
 113                debug("%s: Cannot found axidcg\n", __func__);
 114                return -EINVAL;
 115        }
 116        clk_disable(&axidcg); /* disable clock gating during init */
 117
 118        stm32mp1_ddr_init(priv, &config);
 119
 120        clk_enable(&axidcg); /* enable clock gating */
 121
 122        /* check size */
 123        debug("%s : get_ram_size(%x, %x)\n", __func__,
 124              (u32)priv->info.base, (u32)STM32_DDR_SIZE);
 125
 126        priv->info.size = get_ram_size((long *)priv->info.base,
 127                                       STM32_DDR_SIZE);
 128
 129        debug("%s : %x\n", __func__, (u32)priv->info.size);
 130
 131        /* check memory access for all memory */
 132        if (config.info.size != priv->info.size) {
 133                printf("DDR invalid size : 0x%x, expected 0x%x\n",
 134                       priv->info.size, config.info.size);
 135                return -EINVAL;
 136        }
 137        return 0;
 138}
 139
 140static int stm32mp1_ddr_probe(struct udevice *dev)
 141{
 142        struct ddr_info *priv = dev_get_priv(dev);
 143        struct regmap *map;
 144        int ret;
 145
 146        debug("STM32MP1 DDR probe\n");
 147        priv->dev = dev;
 148
 149        ret = regmap_init_mem(dev_ofnode(dev), &map);
 150        if (ret)
 151                return ret;
 152
 153        priv->ctl = regmap_get_range(map, 0);
 154        priv->phy = regmap_get_range(map, 1);
 155
 156        priv->rcc = STM32_RCC_BASE;
 157
 158        priv->info.base = STM32_DDR_BASE;
 159
 160#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
 161        priv->info.size = 0;
 162        return stm32mp1_ddr_setup(dev);
 163#else
 164        priv->info.size = dev_read_u32_default(dev, "st,mem-size", 0);
 165        return 0;
 166#endif
 167}
 168
 169static int stm32mp1_ddr_get_info(struct udevice *dev, struct ram_info *info)
 170{
 171        struct ddr_info *priv = dev_get_priv(dev);
 172
 173        *info = priv->info;
 174
 175        return 0;
 176}
 177
 178static struct ram_ops stm32mp1_ddr_ops = {
 179        .get_info = stm32mp1_ddr_get_info,
 180};
 181
 182static const struct udevice_id stm32mp1_ddr_ids[] = {
 183        { .compatible = "st,stm32mp1-ddr" },
 184        { }
 185};
 186
 187U_BOOT_DRIVER(ddr_stm32mp1) = {
 188        .name = "stm32mp1_ddr",
 189        .id = UCLASS_RAM,
 190        .of_match = stm32mp1_ddr_ids,
 191        .ops = &stm32mp1_ddr_ops,
 192        .probe = stm32mp1_ddr_probe,
 193        .priv_auto_alloc_size = sizeof(struct ddr_info),
 194};
 195