1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2022 StarFive Technology Co., Ltd. 4 * Author: Yanhong Wang<yanhong.wang@starfivetech.com> 5 */ 6 7#include <common.h> 8#include <asm/arch/regs.h> 9#include <asm/io.h> 10#include <clk.h> 11#include <dm.h> 12#include <fdtdec.h> 13#include <init.h> 14#include <linux/bitops.h> 15#include <linux/sizes.h> 16#include <linux/delay.h> 17#include <ram.h> 18#include <reset.h> 19 20#include "starfive_ddr.h" 21 22DECLARE_GLOBAL_DATA_PTR; 23 24struct starfive_ddr_priv { 25 struct udevice *dev; 26 struct ram_info info; 27 void __iomem *ctrlreg; 28 void __iomem *phyreg; 29 struct reset_ctl_bulk rst; 30 struct clk clk; 31 u32 fre; 32}; 33 34static int starfive_ddr_setup(struct udevice *dev, struct starfive_ddr_priv *priv) 35{ 36 enum ddr_size_t size; 37 38 switch (priv->info.size) { 39 case SZ_2G: 40 size = DDR_SIZE_2G; 41 break; 42 43 case SZ_4G: 44 size = DDR_SIZE_4G; 45 break; 46 47 case 0x200000000: 48 size = DDR_SIZE_8G; 49 break; 50 51 case 0x400000000: 52 default: 53 pr_err("unsupport size %lx\n", priv->info.size); 54 return -EINVAL; 55 } 56 57 ddr_phy_train(priv->phyreg + (PHY_BASE_ADDR << 2)); 58 ddr_phy_util(priv->phyreg + (PHY_AC_BASE_ADDR << 2)); 59 ddr_phy_start(priv->phyreg, size); 60 61 DDR_REG_SET(BUS, DDR_BUS_OSC_DIV2); 62 ddrcsr_boot(priv->ctrlreg, priv->ctrlreg + SEC_CTRL_ADDR, 63 priv->phyreg, size); 64 65 return 0; 66} 67 68static int starfive_ddr_probe(struct udevice *dev) 69{ 70 struct starfive_ddr_priv *priv = dev_get_priv(dev); 71 fdt_addr_t addr; 72 u64 rate; 73 int ret; 74 75 priv->info.base = gd->ram_base; 76 priv->info.size = gd->ram_size; 77 78 priv->dev = dev; 79 addr = dev_read_addr_index(dev, 0); 80 if (addr == FDT_ADDR_T_NONE) 81 return -EINVAL; 82 83 priv->ctrlreg = (void __iomem *)addr; 84 addr = dev_read_addr_index(dev, 1); 85 if (addr == FDT_ADDR_T_NONE) 86 return -EINVAL; 87 88 priv->phyreg = (void __iomem *)addr; 89 ret = dev_read_u32(dev, "clock-frequency", &priv->fre); 90 if (ret) 91 return ret; 92 93 switch (priv->fre) { 94 case 2133: 95 rate = 1066000000; 96 break; 97 98 case 2800: 99 rate = 1400000000; 100 break; 101 102 default: 103 pr_err("Unknown DDR frequency %d\n", priv->fre); 104 return -EINVAL; 105 }; 106 107 ret = reset_get_bulk(dev, &priv->rst); 108 if (ret) 109 return ret; 110 111 ret = reset_deassert_bulk(&priv->rst); 112 if (ret < 0) 113 return ret; 114 115 ret = clk_get_by_index(dev, 0, &priv->clk); 116 if (ret) 117 goto err_free_reset; 118 119 ret = clk_set_rate(&priv->clk, rate); 120 if (ret < 0) 121 goto err_free_reset; 122 123 ret = starfive_ddr_setup(dev, priv); 124 printf("DDR version: dc2e84f0.\n"); 125 126 return ret; 127 128err_free_reset: 129 reset_release_bulk(&priv->rst); 130 131 return ret; 132} 133 134static int starfive_ddr_get_info(struct udevice *dev, struct ram_info *info) 135{ 136 struct starfive_ddr_priv *priv = dev_get_priv(dev); 137 138 *info = priv->info; 139 140 return 0; 141} 142 143static struct ram_ops starfive_ddr_ops = { 144 .get_info = starfive_ddr_get_info, 145}; 146 147static const struct udevice_id starfive_ddr_ids[] = { 148 { .compatible = "starfive,jh7110-dmc" }, 149 { } 150}; 151 152U_BOOT_DRIVER(starfive_ddr) = { 153 .name = "starfive_ddr", 154 .id = UCLASS_RAM, 155 .of_match = starfive_ddr_ids, 156 .ops = &starfive_ddr_ops, 157 .probe = starfive_ddr_probe, 158 .priv_auto = sizeof(struct starfive_ddr_priv), 159}; 160