uboot/drivers/ddr/imx/imx8m/ddrphy_utils.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3* Copyright 2018 NXP
   4*/
   5
   6#include <common.h>
   7#include <errno.h>
   8#include <log.h>
   9#include <asm/io.h>
  10#include <asm/arch/ddr.h>
  11#include <asm/arch/clock.h>
  12#include <asm/arch/ddr.h>
  13#include <asm/arch/lpddr4_define.h>
  14
  15static inline void poll_pmu_message_ready(void)
  16{
  17        unsigned int reg;
  18
  19        do {
  20                reg = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0004);
  21        } while (reg & 0x1);
  22}
  23
  24static inline void ack_pmu_message_receive(void)
  25{
  26        unsigned int reg;
  27
  28        reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0031, 0x0);
  29
  30        do {
  31                reg = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0004);
  32        } while (!(reg & 0x1));
  33
  34        reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0031, 0x1);
  35}
  36
  37static inline unsigned int get_mail(void)
  38{
  39        unsigned int reg;
  40
  41        poll_pmu_message_ready();
  42
  43        reg = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0032);
  44
  45        ack_pmu_message_receive();
  46
  47        return reg;
  48}
  49
  50static inline unsigned int get_stream_message(void)
  51{
  52        unsigned int reg, reg2;
  53
  54        poll_pmu_message_ready();
  55
  56        reg = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0032);
  57
  58        reg2 = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0034);
  59
  60        reg2 = (reg2 << 16) | reg;
  61
  62        ack_pmu_message_receive();
  63
  64        return reg2;
  65}
  66
  67static inline void decode_major_message(unsigned int mail)
  68{
  69        debug("[PMU Major message = 0x%08x]\n", mail);
  70}
  71
  72static inline void decode_streaming_message(void)
  73{
  74        unsigned int string_index, arg __maybe_unused;
  75        int i = 0;
  76
  77        string_index = get_stream_message();
  78        debug("PMU String index = 0x%08x\n", string_index);
  79        while (i < (string_index & 0xffff)) {
  80                arg = get_stream_message();
  81                debug("arg[%d] = 0x%08x\n", i, arg);
  82                i++;
  83        }
  84
  85        debug("\n");
  86}
  87
  88int wait_ddrphy_training_complete(void)
  89{
  90        unsigned int mail;
  91
  92        while (1) {
  93                mail = get_mail();
  94                decode_major_message(mail);
  95                if (mail == 0x08) {
  96                        decode_streaming_message();
  97                } else if (mail == 0x07) {
  98                        debug("Training PASS\n");
  99                        return 0;
 100                } else if (mail == 0xff) {
 101                        debug("Training FAILED\n");
 102                        return -1;
 103                }
 104        }
 105}
 106
 107void ddrphy_init_set_dfi_clk(unsigned int drate)
 108{
 109        switch (drate) {
 110        case 4000:
 111                dram_pll_init(MHZ(1000));
 112                dram_disable_bypass();
 113                break;
 114        case 3200:
 115                dram_pll_init(MHZ(800));
 116                dram_disable_bypass();
 117                break;
 118        case 3000:
 119                dram_pll_init(MHZ(750));
 120                dram_disable_bypass();
 121                break;
 122        case 2400:
 123                dram_pll_init(MHZ(600));
 124                dram_disable_bypass();
 125                break;
 126        case 1600:
 127                dram_pll_init(MHZ(400));
 128                dram_disable_bypass();
 129                break;
 130        case 1066:
 131                dram_pll_init(MHZ(266));
 132                dram_disable_bypass();
 133                break;
 134        case 667:
 135                dram_pll_init(MHZ(167));
 136                dram_disable_bypass();
 137                break;
 138        case 400:
 139                dram_enable_bypass(MHZ(400));
 140                break;
 141        case 100:
 142                dram_enable_bypass(MHZ(100));
 143                break;
 144        default:
 145                return;
 146        }
 147}
 148
 149void ddrphy_init_read_msg_block(enum fw_type type)
 150{
 151}
 152
 153void lpddr4_mr_write(unsigned int mr_rank, unsigned int mr_addr,
 154                     unsigned int mr_data)
 155{
 156        unsigned int tmp;
 157        /*
 158         * 1. Poll MRSTAT.mr_wr_busy until it is 0.
 159         * This checks that there is no outstanding MR transaction.
 160         * No writes should be performed to MRCTRL0 and MRCTRL1 if
 161         * MRSTAT.mr_wr_busy = 1.
 162         */
 163        do {
 164                tmp = reg32_read(DDRC_MRSTAT(0));
 165        } while (tmp & 0x1);
 166        /*
 167         * 2. Write the MRCTRL0.mr_type, MRCTRL0.mr_addr, MRCTRL0.mr_rank and
 168         * (for MRWs) MRCTRL1.mr_data to define the MR transaction.
 169         */
 170        reg32_write(DDRC_MRCTRL0(0), (mr_rank << 4));
 171        reg32_write(DDRC_MRCTRL1(0), (mr_addr << 8) | mr_data);
 172        reg32setbit(DDRC_MRCTRL0(0), 31);
 173}
 174
 175unsigned int lpddr4_mr_read(unsigned int mr_rank, unsigned int mr_addr)
 176{
 177        unsigned int tmp;
 178
 179        reg32_write(DRC_PERF_MON_MRR0_DAT(0), 0x1);
 180        do {
 181                tmp = reg32_read(DDRC_MRSTAT(0));
 182        } while (tmp & 0x1);
 183
 184        reg32_write(DDRC_MRCTRL0(0), (mr_rank << 4) | 0x1);
 185        reg32_write(DDRC_MRCTRL1(0), (mr_addr << 8));
 186        reg32setbit(DDRC_MRCTRL0(0), 31);
 187        do {
 188                tmp = reg32_read(DRC_PERF_MON_MRR0_DAT(0));
 189        } while ((tmp & 0x8) == 0);
 190        tmp = reg32_read(DRC_PERF_MON_MRR1_DAT(0));
 191        tmp = tmp & 0xff;
 192        reg32_write(DRC_PERF_MON_MRR0_DAT(0), 0x4);
 193
 194        return tmp;
 195}
 196