mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 14:00:19 +00:00 
			
		
		
		
	As part of bringing the master branch back in to next, we need to allow for all of these changes to exist here. Reported-by: Jonas Karlman <jonas@kwiboo.se> Signed-off-by: Tom Rini <trini@konsulko.com>
		
			
				
	
	
		
			159 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			159 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0+
 | 
						|
/*
 | 
						|
 * Copyright (C) 2022 StarFive Technology Co., Ltd.
 | 
						|
 * Author: Yanhong Wang<yanhong.wang@starfivetech.com>
 | 
						|
 */
 | 
						|
 | 
						|
#include <asm/arch/regs.h>
 | 
						|
#include <asm/io.h>
 | 
						|
#include <clk.h>
 | 
						|
#include <dm.h>
 | 
						|
#include <fdtdec.h>
 | 
						|
#include <init.h>
 | 
						|
#include <linux/bitops.h>
 | 
						|
#include <linux/sizes.h>
 | 
						|
#include <linux/delay.h>
 | 
						|
#include <ram.h>
 | 
						|
#include <reset.h>
 | 
						|
 | 
						|
#include "starfive_ddr.h"
 | 
						|
 | 
						|
DECLARE_GLOBAL_DATA_PTR;
 | 
						|
 | 
						|
struct starfive_ddr_priv {
 | 
						|
	struct udevice	*dev;
 | 
						|
	struct ram_info info;
 | 
						|
	void __iomem	*ctrlreg;
 | 
						|
	void __iomem	*phyreg;
 | 
						|
	struct reset_ctl_bulk rst;
 | 
						|
	struct clk	clk;
 | 
						|
	u32	fre;
 | 
						|
};
 | 
						|
 | 
						|
static int starfive_ddr_setup(struct udevice *dev, struct starfive_ddr_priv *priv)
 | 
						|
{
 | 
						|
	enum ddr_size_t size;
 | 
						|
 | 
						|
	switch (priv->info.size) {
 | 
						|
	case SZ_2G:
 | 
						|
		size = DDR_SIZE_2G;
 | 
						|
		break;
 | 
						|
 | 
						|
	case SZ_4G:
 | 
						|
		size = DDR_SIZE_4G;
 | 
						|
		break;
 | 
						|
 | 
						|
	case 0x200000000:
 | 
						|
		size = DDR_SIZE_8G;
 | 
						|
		break;
 | 
						|
 | 
						|
	case 0x400000000:
 | 
						|
	default:
 | 
						|
		pr_err("unsupport size %lx\n", priv->info.size);
 | 
						|
		return -EINVAL;
 | 
						|
	}
 | 
						|
 | 
						|
	ddr_phy_train(priv->phyreg + (PHY_BASE_ADDR << 2));
 | 
						|
	ddr_phy_util(priv->phyreg + (PHY_AC_BASE_ADDR << 2));
 | 
						|
	ddr_phy_start(priv->phyreg, size);
 | 
						|
 | 
						|
	DDR_REG_SET(BUS, DDR_BUS_OSC_DIV2);
 | 
						|
	ddrcsr_boot(priv->ctrlreg, priv->ctrlreg + SEC_CTRL_ADDR,
 | 
						|
		    priv->phyreg, size);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int starfive_ddr_probe(struct udevice *dev)
 | 
						|
{
 | 
						|
	struct starfive_ddr_priv *priv = dev_get_priv(dev);
 | 
						|
	fdt_addr_t addr;
 | 
						|
	u64 rate;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	priv->info.base = gd->ram_base;
 | 
						|
	priv->info.size = gd->ram_size;
 | 
						|
 | 
						|
	priv->dev = dev;
 | 
						|
	addr = dev_read_addr_index(dev, 0);
 | 
						|
	if (addr == FDT_ADDR_T_NONE)
 | 
						|
		return -EINVAL;
 | 
						|
 | 
						|
	priv->ctrlreg = (void __iomem *)addr;
 | 
						|
	addr = dev_read_addr_index(dev, 1);
 | 
						|
	if (addr == FDT_ADDR_T_NONE)
 | 
						|
		return -EINVAL;
 | 
						|
 | 
						|
	priv->phyreg = (void __iomem *)addr;
 | 
						|
	ret = dev_read_u32(dev, "clock-frequency", &priv->fre);
 | 
						|
	if (ret)
 | 
						|
		return ret;
 | 
						|
 | 
						|
	switch (priv->fre) {
 | 
						|
	case 2133:
 | 
						|
		rate = 1066000000;
 | 
						|
		break;
 | 
						|
 | 
						|
	case 2800:
 | 
						|
		rate = 1400000000;
 | 
						|
		break;
 | 
						|
 | 
						|
	default:
 | 
						|
		pr_err("Unknown DDR frequency %d\n", priv->fre);
 | 
						|
		return  -EINVAL;
 | 
						|
	};
 | 
						|
 | 
						|
	ret = reset_get_bulk(dev, &priv->rst);
 | 
						|
	if (ret)
 | 
						|
		return ret;
 | 
						|
 | 
						|
	ret = reset_deassert_bulk(&priv->rst);
 | 
						|
	if (ret < 0)
 | 
						|
		return ret;
 | 
						|
 | 
						|
	ret = clk_get_by_index(dev, 0, &priv->clk);
 | 
						|
	if (ret)
 | 
						|
		goto err_free_reset;
 | 
						|
 | 
						|
	ret = clk_set_rate(&priv->clk, rate);
 | 
						|
	if (ret < 0)
 | 
						|
		goto err_free_reset;
 | 
						|
 | 
						|
	ret = starfive_ddr_setup(dev, priv);
 | 
						|
	printf("DDR version: dc2e84f0.\n");
 | 
						|
 | 
						|
	return ret;
 | 
						|
 | 
						|
err_free_reset:
 | 
						|
	reset_release_bulk(&priv->rst);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
 | 
						|
static int starfive_ddr_get_info(struct udevice *dev, struct ram_info *info)
 | 
						|
{
 | 
						|
	struct starfive_ddr_priv *priv = dev_get_priv(dev);
 | 
						|
 | 
						|
	*info = priv->info;
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static struct ram_ops starfive_ddr_ops = {
 | 
						|
	.get_info = starfive_ddr_get_info,
 | 
						|
};
 | 
						|
 | 
						|
static const struct udevice_id starfive_ddr_ids[] = {
 | 
						|
	{ .compatible = "starfive,jh7110-dmc" },
 | 
						|
	{ }
 | 
						|
};
 | 
						|
 | 
						|
U_BOOT_DRIVER(starfive_ddr) = {
 | 
						|
	.name = "starfive_ddr",
 | 
						|
	.id = UCLASS_RAM,
 | 
						|
	.of_match = starfive_ddr_ids,
 | 
						|
	.ops = &starfive_ddr_ops,
 | 
						|
	.probe = starfive_ddr_probe,
 | 
						|
	.priv_auto = sizeof(struct starfive_ddr_priv),
 | 
						|
};
 |