GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,309 @@
if TI816X
config TARGET_TI816X_EVM
bool "Support ti816x_evm"
help
This option specifies support for the TI8168 EVM development platform
with PG2.0 silicon and DDR3 DRAM.
endif
if TI814X
config TARGET_TI814X_EVM
bool "Support ti814x_evm"
help
This option specifies support for the TI8148
EVM development platform.
endif
if AM33XX
config AM33XX_CHILISOM
bool
select SUPPORT_SPL
choice
prompt "AM33xx board select"
config TARGET_AM335X_EVM
bool "Support am335x_evm"
select BOARD_LATE_INIT
select DM
select DM_GPIO
select DM_SERIAL
select TI_I2C_BOARD_DETECT
imply CMD_DM
imply SPL_DM
imply SPL_DM_SEQ_ALIAS
imply SPL_ENV_SUPPORT
imply SPL_FS_EXT4
imply SPL_FS_FAT
imply SPL_GPIO_SUPPORT
imply SPL_I2C_SUPPORT
imply SPL_LIBCOMMON_SUPPORT
imply SPL_LIBDISK_SUPPORT
imply SPL_LIBGENERIC_SUPPORT
imply SPL_MMC_SUPPORT
imply SPL_NAND_SUPPORT
imply SPL_OF_LIBFDT
imply SPL_POWER_SUPPORT
imply SPL_SEPARATE_BSS
imply SPL_SERIAL_SUPPORT
imply SPL_SYS_MALLOC_SIMPLE
imply SPL_WATCHDOG_SUPPORT
imply SPL_YMODEM_SUPPORT
help
This option specifies support for the AM335x
GP and HS EVM development platforms. The AM335x
GP EVM is a standalone test, development, and
evaluation module system that enables developers
to write software and develop hardware around
an AM335x processor subsystem.
config TARGET_AM335X_BALTOS
bool "Support am335x_baltos"
select BOARD_LATE_INIT
select DM
select DM_GPIO
select DM_SERIAL
imply CMD_DM
config TARGET_AM335X_IGEP003X
bool "Support am335x_igep003x"
select BOARD_LATE_INIT
select DM
select DM_GPIO
select DM_SERIAL
imply CMD_DM
config TARGET_AM335X_SHC
bool "Support am335x based shc board from bosch"
select BOARD_LATE_INIT
select DM
select DM_GPIO
select DM_SERIAL
imply CMD_DM
imply CMD_SPL
config TARGET_AM335X_GUARDIAN
bool "Support am335x based guardian board from bosch"
select BOARD_LATE_INIT
select DM
select DM_SERIAL
select DM_GPIO
select DM_USB
config TARGET_AM335X_SL50
bool "Support am335x_sl50"
select BOARD_LATE_INIT
select DM
select DM_GPIO
select DM_SERIAL
imply CMD_DM
config TARGET_BAV335X
bool "Support bav335x"
select BOARD_LATE_INIT
select DM
select DM_SERIAL
imply CMD_DM
help
The BAV335x OEM Network Processor integrates all the functions of an
embedded network computer in a small, easy to use SODIMM module which
incorporates the popular Texas Instruments Sitara 32bit ARM Coretex-A8
processor, with fast DDR3 512MB SDRAM, 4GB of embedded MMC and a Gigabit
ethernet with simple connection to external connectors.
For more information, visit: http://birdland.com/oem
config TARGET_BRXRE1
bool "Support BRXRE1"
select BOARD_LATE_INIT
config TARGET_BRSMARC1
bool "Support BRSMARC1"
select BOARD_LATE_INIT
config TARGET_BRPPT1
bool "Support BRPPT1"
select BOARD_LATE_INIT
config TARGET_CHILIBOARD
bool "Grinn chiliBoard"
select AM33XX_CHILISOM
select BOARD_LATE_INIT
select DM
select DM_SERIAL
imply CMD_DM
config TARGET_CM_T335
bool "Support cm_t335"
select DM
select DM_GPIO
select DM_SERIAL
imply CMD_DM
config TARGET_DRACO
bool "Support draco"
select BOARD_LATE_INIT
select DM
select DM_GPIO
select DM_SERIAL
imply CMD_DM
config TARGET_ETAMIN
bool "Support etamin"
select BOARD_LATE_INIT
select DM
select DM_GPIO
select DM_SERIAL
imply CMD_DM
config TARGET_PCM051
bool "Support pcm051"
select DM
select DM_GPIO
select DM_SERIAL
imply CMD_DM
config TARGET_PENGWYN
bool "Support pengwyn"
select DM
select DM_GPIO
select DM_SERIAL
imply CMD_DM
config TARGET_PEPPER
bool "Support pepper"
select DM
select DM_GPIO
select DM_SERIAL
imply CMD_DM
config TARGET_PHYCORE_AM335X_R2
bool "Support phyCORE AM335X R2"
select DM
select DM_GPIO
select DM_SERIAL
imply CMD_DM
config TARGET_PXM2
bool "Support pxm2"
select BOARD_LATE_INIT
select DM
select DM_GPIO
select DM_SERIAL
imply CMD_DM
config TARGET_RASTABAN
bool "Support rastaban"
select BOARD_LATE_INIT
select DM
select DM_GPIO
select DM_SERIAL
imply CMD_DM
config TARGET_RUT
bool "Support rut"
select BOARD_LATE_INIT
select DM
select DM_GPIO
select DM_SERIAL
imply CMD_DM
config TARGET_THUBAN
bool "Support thuban"
select BOARD_LATE_INIT
select DM
select DM_GPIO
select DM_SERIAL
imply CMD_DM
config TARGET_PDU001
bool "Support PDU001"
select DM
select DM_SERIAL
imply SPL_SEPARATE_BSS
imply CMD_DM
help
Support for PDU001 platform developed by EETS GmbH.
The PDU001 is a processor and display unit developed around
the Computing-Module m2 from bytes at work AG.
endchoice
endif
if AM43XX
choice
prompt "AM43xx board select"
config TARGET_AM43XX_EVM
bool "Support am43xx_evm"
select BOARD_LATE_INIT
select TI_I2C_BOARD_DETECT
imply DM_ETH
imply DM_I2C
imply DM_SPI
imply DM_SPI_FLASH
imply SPL_ENV_SUPPORT
imply SPL_FS_EXT4
imply SPL_FS_FAT
imply SPL_GPIO_SUPPORT
imply SPL_I2C_SUPPORT
imply SPL_LIBCOMMON_SUPPORT
imply SPL_LIBDISK_SUPPORT
imply SPL_LIBGENERIC_SUPPORT
imply SPL_MMC_SUPPORT
imply SPL_NAND_SUPPORT
imply SPL_POWER_SUPPORT
imply SPL_SERIAL_SUPPORT
imply SPL_WATCHDOG_SUPPORT
imply SPL_YMODEM_SUPPORT
help
This option specifies support for the AM43xx
GP and HS EVM development platforms.The AM437x
GP EVM is a standalone test, development, and
evaluation module system that enables developers
to write software and develop hardware around
an AM43xx processor subsystem.
config TARGET_CM_T43
bool "Support cm_t43"
endchoice
config SPL_RTC_DDR_SUPPORT
bool
depends on SPL
prompt "Enable RTC-DDR ONLY Support"
help
If you want RTC-DDR ONLY Support, say Y. RTC Only with DDR in
self-refresh mode is a special power saving mode where in all
the other voltages are turned off apart from the RTC domain and DDR.
So only RTC is alive and ticking and one can program it to wake
up after a predetermined period. Once RTC alarm fires, the PMIC
powers up all the voltage domains. U-Boot takes a special path
as the DDR has contents is in self-refresh and restore path is
followed.
endif
if AM43XX || AM33XX
config PUB_ROM_DATA_SIZE
hex "Size in bytes of the L3 SRAM reserved by ROM to store data"
default 0x8400
help
During the device boot, the public ROM uses the top of
the public L3 OCMC RAM to store r/w data like stack,
heap, globals etc. When the ROM is copying the boot
image from the boot media into memory, the image must
not spill over into this area. This value can be used
during compile time to determine the maximum size of a
boot image. Once the ROM transfers control to the boot
image, this area is no longer used, and can be reclaimed
for run time use by the boot image.
endif
@@ -0,0 +1,28 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
obj-$(CONFIG_AM33XX) += clock_am33xx.o
obj-$(CONFIG_TI814X) += clock_ti814x.o
obj-$(CONFIG_AM43XX) += clock_am43xx.o
ifneq ($(CONFIG_AM43XX)$(CONFIG_AM33XX),)
obj-y += clock.o
endif
obj-$(CONFIG_TI816X) += clock_ti816x.o
obj-y += sys_info.o
obj-y += ddr.o
ifeq ($(CONFIG_TI816X)$(CONFIG_SKIP_LOWLEVEL_INIT),)
obj-y += emif4.o
endif
obj-$(CONFIG_TI816X) += ti816x_emif4.o
obj-y += board.o
obj-y += mux.o
obj-y += prcm-regs.o
obj-y += hw_data.o
obj-y += fdt.o
obj-$(CONFIG_CLOCK_SYNTHESIZER) += clk_synthesizer.o
obj-$(CONFIG_AM33XX_CHILISOM) += chilisom.o
@@ -0,0 +1,580 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* board.c
*
* Common board functions for AM33XX based boards
*
* Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
*/
#include <common.h>
#include <dm.h>
#include <debug_uart.h>
#include <errno.h>
#include <ns16550.h>
#include <spl.h>
#include <asm/arch/cpu.h>
#include <asm/arch/hardware.h>
#include <asm/arch/omap.h>
#include <asm/arch/ddr_defs.h>
#include <asm/arch/clock.h>
#include <asm/arch/gpio.h>
#include <asm/arch/i2c.h>
#include <asm/arch/mem.h>
#include <asm/arch/mmc_host_def.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
#include <asm/emif.h>
#include <asm/gpio.h>
#include <asm/omap_common.h>
#include <i2c.h>
#include <miiphy.h>
#include <cpsw.h>
#include <linux/errno.h>
#include <linux/compiler.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/musb.h>
#include <asm/omap_musb.h>
#include <asm/davinci_rtc.h>
#define AM43XX_EMIF_BASE 0x4C000000
#define AM43XX_SDRAM_CONFIG_OFFSET 0x8
#define AM43XX_SDRAM_TYPE_MASK 0xE0000000
#define AM43XX_SDRAM_TYPE_SHIFT 29
#define AM43XX_SDRAM_TYPE_DDR3 3
#define AM43XX_READ_WRITE_LEVELING_CTRL_OFFSET 0xDC
#define AM43XX_RDWRLVLFULL_START 0x80000000
DECLARE_GLOBAL_DATA_PTR;
int dram_init(void)
{
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
sdram_init();
#endif
/* dram_init must store complete ramsize in gd->ram_size */
gd->ram_size = get_ram_size(
(void *)CONFIG_SYS_SDRAM_BASE,
CONFIG_MAX_RAM_BANK_SIZE);
return 0;
}
int dram_init_banksize(void)
{
gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
gd->bd->bi_dram[0].size = gd->ram_size;
return 0;
}
#if !CONFIG_IS_ENABLED(OF_CONTROL)
static const struct ns16550_platdata am33xx_serial[] = {
{ .base = CONFIG_SYS_NS16550_COM1, .reg_shift = 2,
.clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, },
# ifdef CONFIG_SYS_NS16550_COM2
{ .base = CONFIG_SYS_NS16550_COM2, .reg_shift = 2,
.clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, },
# ifdef CONFIG_SYS_NS16550_COM3
{ .base = CONFIG_SYS_NS16550_COM3, .reg_shift = 2,
.clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, },
{ .base = CONFIG_SYS_NS16550_COM4, .reg_shift = 2,
.clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, },
{ .base = CONFIG_SYS_NS16550_COM5, .reg_shift = 2,
.clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, },
{ .base = CONFIG_SYS_NS16550_COM6, .reg_shift = 2,
.clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, },
# endif
# endif
};
U_BOOT_DEVICES(am33xx_uarts) = {
{ "ns16550_serial", &am33xx_serial[0] },
# ifdef CONFIG_SYS_NS16550_COM2
{ "ns16550_serial", &am33xx_serial[1] },
# ifdef CONFIG_SYS_NS16550_COM3
{ "ns16550_serial", &am33xx_serial[2] },
{ "ns16550_serial", &am33xx_serial[3] },
{ "ns16550_serial", &am33xx_serial[4] },
{ "ns16550_serial", &am33xx_serial[5] },
# endif
# endif
};
#ifdef CONFIG_DM_I2C
static const struct omap_i2c_platdata am33xx_i2c[] = {
{ I2C_BASE1, 100000, OMAP_I2C_REV_V2},
{ I2C_BASE2, 100000, OMAP_I2C_REV_V2},
{ I2C_BASE3, 100000, OMAP_I2C_REV_V2},
};
U_BOOT_DEVICES(am33xx_i2c) = {
{ "i2c_omap", &am33xx_i2c[0] },
{ "i2c_omap", &am33xx_i2c[1] },
{ "i2c_omap", &am33xx_i2c[2] },
};
#endif
#ifdef CONFIG_DM_GPIO
static const struct omap_gpio_platdata am33xx_gpio[] = {
{ 0, AM33XX_GPIO0_BASE },
{ 1, AM33XX_GPIO1_BASE },
{ 2, AM33XX_GPIO2_BASE },
{ 3, AM33XX_GPIO3_BASE },
#ifdef CONFIG_AM43XX
{ 4, AM33XX_GPIO4_BASE },
{ 5, AM33XX_GPIO5_BASE },
#endif
};
U_BOOT_DEVICES(am33xx_gpios) = {
{ "gpio_omap", &am33xx_gpio[0] },
{ "gpio_omap", &am33xx_gpio[1] },
{ "gpio_omap", &am33xx_gpio[2] },
{ "gpio_omap", &am33xx_gpio[3] },
#ifdef CONFIG_AM43XX
{ "gpio_omap", &am33xx_gpio[4] },
{ "gpio_omap", &am33xx_gpio[5] },
#endif
};
#endif
#endif
#ifndef CONFIG_DM_GPIO
static const struct gpio_bank gpio_bank_am33xx[] = {
{ (void *)AM33XX_GPIO0_BASE },
{ (void *)AM33XX_GPIO1_BASE },
{ (void *)AM33XX_GPIO2_BASE },
{ (void *)AM33XX_GPIO3_BASE },
#ifdef CONFIG_AM43XX
{ (void *)AM33XX_GPIO4_BASE },
{ (void *)AM33XX_GPIO5_BASE },
#endif
};
const struct gpio_bank *const omap_gpio_bank = gpio_bank_am33xx;
#endif
#if defined(CONFIG_MMC_OMAP_HS)
int cpu_mmc_init(bd_t *bis)
{
int ret;
ret = omap_mmc_init(0, 0, 0, -1, -1);
if (ret)
return ret;
return omap_mmc_init(1, 0, 0, -1, -1);
}
#endif
/*
* RTC only with DDR in self-refresh mode magic value, checked against during
* boot to see if we have a valid config. This should be in sync with the value
* that will be in drivers/soc/ti/pm33xx.c.
*/
#define RTC_MAGIC_VAL 0x8cd0
/* Board type field bit shift for RTC only with DDR in self-refresh mode */
#define RTC_BOARD_TYPE_SHIFT 16
/* AM33XX has two MUSB controllers which can be host or gadget */
#if (defined(CONFIG_USB_MUSB_GADGET) || defined(CONFIG_USB_MUSB_HOST)) && \
(defined(CONFIG_AM335X_USB0) || defined(CONFIG_AM335X_USB1)) && \
(!CONFIG_IS_ENABLED(DM_USB) || !CONFIG_IS_ENABLED(OF_CONTROL)) && \
(!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_MUSB_NEW_SUPPORT))
static struct musb_hdrc_config musb_config = {
.multipoint = 1,
.dyn_fifo = 1,
.num_eps = 16,
.ram_bits = 12,
};
#if CONFIG_IS_ENABLED(DM_USB) && !CONFIG_IS_ENABLED(OF_CONTROL)
static struct ti_musb_platdata usb0 = {
.base = (void *)USB0_OTG_BASE,
.ctrl_mod_base = &((struct ctrl_dev *)CTRL_DEVICE_BASE)->usb_ctrl0,
.plat = {
.config = &musb_config,
.power = 50,
.platform_ops = &musb_dsps_ops,
},
};
static struct ti_musb_platdata usb1 = {
.base = (void *)USB1_OTG_BASE,
.ctrl_mod_base = &((struct ctrl_dev *)CTRL_DEVICE_BASE)->usb_ctrl1,
.plat = {
.config = &musb_config,
.power = 50,
.platform_ops = &musb_dsps_ops,
},
};
U_BOOT_DEVICES(am33xx_usbs) = {
#if CONFIG_AM335X_USB0_MODE == MUSB_PERIPHERAL
{ "ti-musb-peripheral", &usb0 },
#elif CONFIG_AM335X_USB0_MODE == MUSB_HOST
{ "ti-musb-host", &usb0 },
#endif
#if CONFIG_AM335X_USB1_MODE == MUSB_PERIPHERAL
{ "ti-musb-peripheral", &usb1 },
#elif CONFIG_AM335X_USB1_MODE == MUSB_HOST
{ "ti-musb-host", &usb1 },
#endif
};
int arch_misc_init(void)
{
return 0;
}
#else
static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
/* USB 2.0 PHY Control */
#define CM_PHY_PWRDN (1 << 0)
#define CM_PHY_OTG_PWRDN (1 << 1)
#define OTGVDET_EN (1 << 19)
#define OTGSESSENDEN (1 << 20)
static void am33xx_usb_set_phy_power(u8 on, u32 *reg_addr)
{
if (on) {
clrsetbits_le32(reg_addr, CM_PHY_PWRDN | CM_PHY_OTG_PWRDN,
OTGVDET_EN | OTGSESSENDEN);
} else {
clrsetbits_le32(reg_addr, 0, CM_PHY_PWRDN | CM_PHY_OTG_PWRDN);
}
}
#ifdef CONFIG_AM335X_USB0
static void am33xx_otg0_set_phy_power(struct udevice *dev, u8 on)
{
am33xx_usb_set_phy_power(on, &cdev->usb_ctrl0);
}
struct omap_musb_board_data otg0_board_data = {
.set_phy_power = am33xx_otg0_set_phy_power,
};
static struct musb_hdrc_platform_data otg0_plat = {
.mode = CONFIG_AM335X_USB0_MODE,
.config = &musb_config,
.power = 50,
.platform_ops = &musb_dsps_ops,
.board_data = &otg0_board_data,
};
#endif
#ifdef CONFIG_AM335X_USB1
static void am33xx_otg1_set_phy_power(struct udevice *dev, u8 on)
{
am33xx_usb_set_phy_power(on, &cdev->usb_ctrl1);
}
struct omap_musb_board_data otg1_board_data = {
.set_phy_power = am33xx_otg1_set_phy_power,
};
static struct musb_hdrc_platform_data otg1_plat = {
.mode = CONFIG_AM335X_USB1_MODE,
.config = &musb_config,
.power = 50,
.platform_ops = &musb_dsps_ops,
.board_data = &otg1_board_data,
};
#endif
int arch_misc_init(void)
{
#ifdef CONFIG_AM335X_USB0
musb_register(&otg0_plat, &otg0_board_data,
(void *)USB0_OTG_BASE);
#endif
#ifdef CONFIG_AM335X_USB1
musb_register(&otg1_plat, &otg1_board_data,
(void *)USB1_OTG_BASE);
#endif
return 0;
}
#endif
#else /* CONFIG_USB_MUSB_* && CONFIG_AM335X_USB* && !CONFIG_DM_USB */
int arch_misc_init(void)
{
struct udevice *dev;
int ret;
ret = uclass_first_device(UCLASS_MISC, &dev);
if (ret || !dev)
return ret;
#if defined(CONFIG_DM_ETH) && defined(CONFIG_USB_ETHER)
ret = usb_ether_init();
if (ret) {
pr_err("USB ether init failed\n");
return ret;
}
#endif
return 0;
}
#endif /* CONFIG_USB_MUSB_* && CONFIG_AM335X_USB* && !CONFIG_DM_USB */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
#if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC) || \
(defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_RTC_DDR_SUPPORT))
static void rtc32k_unlock(struct davinci_rtc *rtc)
{
/*
* Unlock the RTC's registers. For more details please see the
* RTC_SS section of the TRM. In order to unlock we need to
* write these specific values (keys) in this order.
*/
writel(RTC_KICK0R_WE, &rtc->kick0r);
writel(RTC_KICK1R_WE, &rtc->kick1r);
}
#endif
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_RTC_DDR_SUPPORT)
/*
* Write contents of the RTC_SCRATCH1 register based on board type
* Two things are passed
* on. First 16 bits (0:15) are written with RTC_MAGIC value. Once the
* control gets to kernel, kernel reads the scratchpad register and gets to
* know that bootloader has rtc_only support.
*
* Second important thing is the board type (16:31). This is needed in the
* rtc_only boot where in we want to avoid costly i2c reads to eeprom to
* identify the board type and we go ahead and copy the board strings to
* am43xx_board_name.
*/
void update_rtc_magic(void)
{
struct davinci_rtc *rtc = (struct davinci_rtc *)RTC_BASE;
u32 magic = RTC_MAGIC_VAL;
magic |= (rtc_only_get_board_type() << RTC_BOARD_TYPE_SHIFT);
rtc32k_unlock(rtc);
/* write magic */
writel(magic, &rtc->scratch1);
}
#endif
/*
* In the case of non-SPL based booting we'll want to call these
* functions a tiny bit later as it will require gd to be set and cleared
* and that's not true in s_init in this case so we cannot do it there.
*/
int board_early_init_f(void)
{
set_mux_conf_regs();
prcm_init();
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_RTC_DDR_SUPPORT)
update_rtc_magic();
#endif
return 0;
}
/*
* This function is the place to do per-board things such as ramp up the
* MPU clock frequency.
*/
__weak void am33xx_spl_board_init(void)
{
}
#if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC)
static void rtc32k_enable(void)
{
struct davinci_rtc *rtc = (struct davinci_rtc *)RTC_BASE;
rtc32k_unlock(rtc);
/* Enable the RTC 32K OSC by setting bits 3 and 6. */
writel((1 << 3) | (1 << 6), &rtc->osc);
}
#endif
static void uart_soft_reset(void)
{
struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
u32 regval;
regval = readl(&uart_base->uartsyscfg);
regval |= UART_RESET;
writel(regval, &uart_base->uartsyscfg);
while ((readl(&uart_base->uartsyssts) &
UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK)
;
/* Disable smart idle */
regval = readl(&uart_base->uartsyscfg);
regval |= UART_SMART_IDLE_EN;
writel(regval, &uart_base->uartsyscfg);
}
static void watchdog_disable(void)
{
struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
writel(0xAAAA, &wdtimer->wdtwspr);
while (readl(&wdtimer->wdtwwps) != 0x0)
;
writel(0x5555, &wdtimer->wdtwspr);
while (readl(&wdtimer->wdtwwps) != 0x0)
;
}
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_RTC_DDR_SUPPORT)
/*
* Check if we are executing rtc-only + DDR mode, and resume from it if needed
*/
static void rtc_only(void)
{
struct davinci_rtc *rtc = (struct davinci_rtc *)RTC_BASE;
struct prm_device_inst *prm_device =
(struct prm_device_inst *)PRM_DEVICE_INST;
u32 scratch1, sdrc;
void (*resume_func)(void);
scratch1 = readl(&rtc->scratch1);
/*
* Check RTC scratch against RTC_MAGIC_VAL, RTC_MAGIC_VAL is only
* written to this register when we want to wake up from RTC only
* with DDR in self-refresh mode. Contents of the RTC_SCRATCH1:
* bits 0-15: RTC_MAGIC_VAL
* bits 16-31: board type (needed for sdram_init)
*/
if ((scratch1 & 0xffff) != RTC_MAGIC_VAL)
return;
rtc32k_unlock(rtc);
/* Clear RTC magic */
writel(0, &rtc->scratch1);
/*
* Update board type based on value stored on RTC_SCRATCH1, this
* is done so that we don't need to read the board type from eeprom
* over i2c bus which is expensive
*/
rtc_only_update_board_type(scratch1 >> RTC_BOARD_TYPE_SHIFT);
/*
* Enable EMIF_DEVOFF in PRCM_PRM_EMIF_CTRL to indicate to EMIF we
* are resuming from self-refresh. This avoids an unnecessary re-init
* of the DDR. The re-init takes time and we would need to wait for
* it to complete before accessing DDR to avoid L3 NOC errors.
*/
writel(EMIF_CTRL_DEVOFF, &prm_device->emif_ctrl);
rtc_only_prcm_init();
sdram_init();
/* Check EMIF4D_SDRAM_CONFIG[31:29] SDRAM_TYPE */
/* Only perform leveling if SDRAM_TYPE = 3 (DDR3) */
sdrc = readl(AM43XX_EMIF_BASE + AM43XX_SDRAM_CONFIG_OFFSET);
sdrc &= AM43XX_SDRAM_TYPE_MASK;
sdrc >>= AM43XX_SDRAM_TYPE_SHIFT;
if (sdrc == AM43XX_SDRAM_TYPE_DDR3) {
writel(AM43XX_RDWRLVLFULL_START,
AM43XX_EMIF_BASE +
AM43XX_READ_WRITE_LEVELING_CTRL_OFFSET);
mdelay(1);
am43xx_wait:
sdrc = readl(AM43XX_EMIF_BASE +
AM43XX_READ_WRITE_LEVELING_CTRL_OFFSET);
if (sdrc == AM43XX_RDWRLVLFULL_START)
goto am43xx_wait;
}
resume_func = (void *)readl(&rtc->scratch0);
if (resume_func)
resume_func();
}
#endif
void s_init(void)
{
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_RTC_DDR_SUPPORT)
rtc_only();
#endif
}
void early_system_init(void)
{
/*
* The ROM will only have set up sufficient pinmux to allow for the
* first 4KiB NOR to be read, we must finish doing what we know of
* the NOR mux in this space in order to continue.
*/
#ifdef CONFIG_NOR_BOOT
enable_norboot_pin_mux();
#endif
watchdog_disable();
set_uart_mux_conf();
setup_early_clocks();
uart_soft_reset();
#ifdef CONFIG_SPL_BUILD
/*
* Save the boot parameters passed from romcode.
* We cannot delay the saving further than this,
* to prevent overwrites.
*/
save_omap_boot_params();
#endif
#ifdef CONFIG_DEBUG_UART_OMAP
debug_uart_init();
#endif
#ifdef CONFIG_SPL_BUILD
spl_early_init();
#endif
#ifdef CONFIG_TI_I2C_BOARD_DETECT
do_board_detect();
#endif
#if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC)
/* Enable RTC32K clock */
rtc32k_enable();
#endif
}
#ifdef CONFIG_SPL_BUILD
void board_init_f(ulong dummy)
{
hw_data_init();
early_system_init();
board_early_init_f();
sdram_init();
/* dram_init must store complete ramsize in gd->ram_size */
gd->ram_size = get_ram_size(
(void *)CONFIG_SYS_SDRAM_BASE,
CONFIG_MAX_RAM_BANK_SIZE);
}
#endif
#endif
int arch_cpu_init_dm(void)
{
hw_data_init();
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
early_system_init();
#endif
return 0;
}
@@ -0,0 +1,184 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
* Copyright (C) 2017, Grinn - http://grinn-global.com/
*/
#include <common.h>
#include <asm/arch/clock.h>
#include <asm/arch/clk_synthesizer.h>
#include <asm/arch/cpu.h>
#include <asm/arch/ddr_defs.h>
#include <asm/arch/hardware.h>
#include <asm/arch/omap.h>
#include <asm/arch/mem.h>
#include <asm/arch/mux.h>
#include <asm/arch/sys_proto.h>
#include <asm/emif.h>
#include <asm/io.h>
#include <errno.h>
#include <i2c.h>
#include <power/tps65217.h>
#include <spl.h>
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
static struct module_pin_mux i2c0_pin_mux[] = {
{OFFSET(i2c0_sda), (MODE(0) | RXACTIVE |
PULLUDEN | SLEWCTRL)}, /* I2C_DATA */
{OFFSET(i2c0_scl), (MODE(0) | RXACTIVE |
PULLUDEN | SLEWCTRL)}, /* I2C_SCLK */
{-1},
};
static struct module_pin_mux nand_pin_mux[] = {
{OFFSET(gpmc_ad0), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD0 */
{OFFSET(gpmc_ad1), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD1 */
{OFFSET(gpmc_ad2), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD2 */
{OFFSET(gpmc_ad3), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD3 */
{OFFSET(gpmc_ad4), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD4 */
{OFFSET(gpmc_ad5), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD5 */
{OFFSET(gpmc_ad6), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD6 */
{OFFSET(gpmc_ad7), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* NAND AD7 */
{OFFSET(gpmc_wait0), (MODE(0) | RXACTIVE | PULLUP_EN)}, /* NAND WAIT */
{OFFSET(gpmc_wpn), (MODE(7) | PULLUP_EN | RXACTIVE)}, /* NAND_WPN */
{OFFSET(gpmc_csn0), (MODE(0) | PULLUDEN)}, /* NAND_CS0 */
{OFFSET(gpmc_advn_ale), (MODE(0) | PULLUDEN)}, /* NAND_ADV_ALE */
{OFFSET(gpmc_oen_ren), (MODE(0) | PULLUDEN)}, /* NAND_OE */
{OFFSET(gpmc_wen), (MODE(0) | PULLUDEN)}, /* NAND_WEN */
{OFFSET(gpmc_be0n_cle), (MODE(0) | PULLUDEN)}, /* NAND_BE_CLE */
{-1},
};
static void enable_i2c0_pin_mux(void)
{
configure_module_pin_mux(i2c0_pin_mux);
}
void chilisom_enable_pin_mux(void)
{
/* chilisom pin mux */
configure_module_pin_mux(nand_pin_mux);
}
static const struct ddr_data ddr3_chilisom_data = {
.datardsratio0 = MT41K256M16HA125E_RD_DQS,
.datawdsratio0 = MT41K256M16HA125E_WR_DQS,
.datafwsratio0 = MT41K256M16HA125E_PHY_FIFO_WE,
.datawrsratio0 = MT41K256M16HA125E_PHY_WR_DATA,
};
static const struct cmd_control ddr3_chilisom_cmd_ctrl_data = {
.cmd0csratio = MT41K256M16HA125E_RATIO,
.cmd0iclkout = MT41K256M16HA125E_INVERT_CLKOUT,
.cmd1csratio = MT41K256M16HA125E_RATIO,
.cmd1iclkout = MT41K256M16HA125E_INVERT_CLKOUT,
.cmd2csratio = MT41K256M16HA125E_RATIO,
.cmd2iclkout = MT41K256M16HA125E_INVERT_CLKOUT,
};
static struct emif_regs ddr3_chilisom_emif_reg_data = {
.sdram_config = MT41K256M16HA125E_EMIF_SDCFG,
.ref_ctrl = MT41K256M16HA125E_EMIF_SDREF,
.sdram_tim1 = MT41K256M16HA125E_EMIF_TIM1,
.sdram_tim2 = MT41K256M16HA125E_EMIF_TIM2,
.sdram_tim3 = MT41K256M16HA125E_EMIF_TIM3,
.ocp_config = 0x00141414,
.zq_config = MT41K256M16HA125E_ZQ_CFG,
.emif_ddr_phy_ctlr_1 = MT41K256M16HA125E_EMIF_READ_LATENCY,
};
void chilisom_spl_board_init(void)
{
int mpu_vdd;
int usb_cur_lim;
enable_i2c0_pin_mux();
/* Get the frequency */
dpll_mpu_opp100.m = am335x_get_efuse_mpu_max_freq(cdev);
if (i2c_probe(TPS65217_CHIP_PM))
return;
/*
* Increase USB current limit to 1300mA or 1800mA and set
* the MPU voltage controller as needed.
*/
if (dpll_mpu_opp100.m == MPUPLL_M_1000) {
usb_cur_lim = TPS65217_USB_INPUT_CUR_LIMIT_1800MA;
mpu_vdd = TPS65217_DCDC_VOLT_SEL_1325MV;
} else {
usb_cur_lim = TPS65217_USB_INPUT_CUR_LIMIT_1300MA;
mpu_vdd = TPS65217_DCDC_VOLT_SEL_1275MV;
}
if (tps65217_reg_write(TPS65217_PROT_LEVEL_NONE,
TPS65217_POWER_PATH,
usb_cur_lim,
TPS65217_USB_INPUT_CUR_LIMIT_MASK))
puts("tps65217_reg_write failure\n");
/* Set DCDC3 (CORE) voltage to 1.125V */
if (tps65217_voltage_update(TPS65217_DEFDCDC3,
TPS65217_DCDC_VOLT_SEL_1125MV)) {
puts("tps65217_voltage_update failure\n");
return;
}
/* Set CORE Frequencies to OPP100 */
do_setup_dpll(&dpll_core_regs, &dpll_core_opp100);
/* Set DCDC2 (MPU) voltage */
if (tps65217_voltage_update(TPS65217_DEFDCDC2, mpu_vdd)) {
puts("tps65217_voltage_update failure\n");
return;
}
/* Set LDO3 to 1.8V and LDO4 to 3.3V */
if (tps65217_reg_write(TPS65217_PROT_LEVEL_2,
TPS65217_DEFLS1,
TPS65217_LDO_VOLTAGE_OUT_1_8,
TPS65217_LDO_MASK))
puts("tps65217_reg_write failure\n");
if (tps65217_reg_write(TPS65217_PROT_LEVEL_2,
TPS65217_DEFLS2,
TPS65217_LDO_VOLTAGE_OUT_3_3,
TPS65217_LDO_MASK))
puts("tps65217_reg_write failure\n");
/* Set MPU Frequency to what we detected now that voltages are set */
do_setup_dpll(&dpll_mpu_regs, &dpll_mpu_opp100);
}
#define OSC (V_OSCK/1000000)
const struct dpll_params dpll_ddr_chilisom = {
400, OSC-1, 1, -1, -1, -1, -1};
const struct dpll_params *get_dpll_ddr_params(void)
{
return &dpll_ddr_chilisom;
}
const struct ctrl_ioregs ioregs_chilisom = {
.cm0ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
.cm1ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
.cm2ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
.dt0ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
.dt1ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
};
void sdram_init(void)
{
config_ddr(400, &ioregs_chilisom,
&ddr3_chilisom_data,
&ddr3_chilisom_cmd_ctrl_data,
&ddr3_chilisom_emif_reg_data, 0);
}
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
@@ -0,0 +1,137 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* clk-synthesizer.c
*
* Clock synthesizer apis
*
* Copyright (C) 2016, Texas Instruments, Incorporated - http://www.ti.com/
*/
#include <common.h>
#include <asm/arch/clk_synthesizer.h>
#include <i2c.h>
/**
* clk_synthesizer_reg_read - Read register from synthesizer.
* dev: i2c bus device (not used if CONFIG_DM_I2C is not set)
* @addr: addr within the i2c device
* buf: Buffer to which value is to be read.
*
* For reading the register from this clock synthesizer, a command needs to
* be send along with enabling byte read more, and then read can happen.
* Returns 0 on success
*/
static int clk_synthesizer_reg_read(struct udevice *dev, int addr, u8 *buf)
{
int rc;
/* Enable Bye read */
addr = addr | CLK_SYNTHESIZER_BYTE_MODE;
#ifndef CONFIG_DM_I2C
/* Send the command byte */
rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1);
if (rc)
printf("Failed to send command to clock synthesizer\n");
/* Read the Data */
return i2c_read(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1);
#else
/* Send the command byte */
rc = dm_i2c_reg_write(dev, addr, *buf);
if (rc)
printf("Failed to send command to clock synthesizer\n");
/* Read the Data */
rc = dm_i2c_reg_read(dev, addr);
if (rc < 0)
return rc;
*buf = (u8)rc;
return 0;
#endif
}
/**
* clk_synthesizer_reg_write - Write a value to register in synthesizer.
* dev: i2c bus device (not used if CONFIG_DM_I2C is not set)
* @addr: addr within the i2c device
* val: Value to be written in the addr.
*
* Enable the byte read mode in the address and start the i2c transfer.
* Returns 0 on success
*/
static int clk_synthesizer_reg_write(struct udevice *dev, int addr, u8 val)
{
u8 cmd[2];
int rc = 0;
/* Enable byte write */
cmd[0] = addr | CLK_SYNTHESIZER_BYTE_MODE;
cmd[1] = val;
#ifndef CONFIG_DM_I2C
rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, cmd, 2);
#else
rc = dm_i2c_write(dev, addr, cmd, 2);
#endif
if (rc)
printf("Clock synthesizer reg write failed at addr = 0x%x\n",
addr);
return rc;
}
/**
* setup_clock_syntherizer - Program the clock synthesizer to get the desired
* frequency.
* @data: Data containing the desired output
*
* This is a PLL-based high performance synthesizer which gives 3 outputs
* as per the PLL_DIV and load capacitor programmed.
*/
int setup_clock_synthesizer(struct clk_synth *data)
{
int rc;
u8 val = 0;
struct udevice *dev = NULL;
#ifndef CONFIG_DM_I2C
rc = i2c_probe(CLK_SYNTHESIZER_I2C_ADDR);
if (rc) {
printf("i2c probe failed at address 0x%x\n",
CLK_SYNTHESIZER_I2C_ADDR);
return rc;
}
#else
rc = i2c_get_chip_for_busnum(0, CLK_SYNTHESIZER_I2C_ADDR, 1, &dev);
if (rc) {
printf("failed to get device for synthesizer at address 0x%x\n",
CLK_SYNTHESIZER_I2C_ADDR);
return rc;
}
#endif
rc = clk_synthesizer_reg_read(dev, CLK_SYNTHESIZER_ID_REG, &val);
if (val != data->id)
return rc;
/* Crystal Load capacitor selection */
rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_XCSEL,
data->capacitor);
if (rc)
return rc;
rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_MUX_REG,
data->mux);
if (rc)
return rc;
rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_PDIV2_REG,
data->pdiv2);
if (rc)
return rc;
rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_PDIV3_REG,
data->pdiv3);
if (rc)
return rc;
return 0;
}
@@ -0,0 +1,255 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* clock.c
*
* Clock initialization for AM33XX boards.
* Derived from OMAP4 boards
*
* Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/
*/
#include <common.h>
#include <asm/arch/cpu.h>
#include <asm/arch/clock.h>
#include <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
static void setup_post_dividers(const struct dpll_regs *dpll_regs,
const struct dpll_params *params)
{
/* Setup post-dividers */
if (params->m2 >= 0)
writel(params->m2, dpll_regs->cm_div_m2_dpll);
if (params->m3 >= 0)
writel(params->m3, dpll_regs->cm_div_m3_dpll);
if (params->m4 >= 0)
writel(params->m4, dpll_regs->cm_div_m4_dpll);
if (params->m5 >= 0)
writel(params->m5, dpll_regs->cm_div_m5_dpll);
if (params->m6 >= 0)
writel(params->m6, dpll_regs->cm_div_m6_dpll);
}
static inline void do_lock_dpll(const struct dpll_regs *dpll_regs)
{
clrsetbits_le32(dpll_regs->cm_clkmode_dpll,
CM_CLKMODE_DPLL_DPLL_EN_MASK,
DPLL_EN_LOCK << CM_CLKMODE_DPLL_EN_SHIFT);
}
static inline void wait_for_lock(const struct dpll_regs *dpll_regs)
{
if (!wait_on_value(ST_DPLL_CLK_MASK, ST_DPLL_CLK_MASK,
(void *)dpll_regs->cm_idlest_dpll, LDELAY)) {
printf("DPLL locking failed for 0x%x\n",
dpll_regs->cm_clkmode_dpll);
hang();
}
}
static inline void do_bypass_dpll(const struct dpll_regs *dpll_regs)
{
clrsetbits_le32(dpll_regs->cm_clkmode_dpll,
CM_CLKMODE_DPLL_DPLL_EN_MASK,
DPLL_EN_MN_BYPASS << CM_CLKMODE_DPLL_EN_SHIFT);
}
static inline void wait_for_bypass(const struct dpll_regs *dpll_regs)
{
if (!wait_on_value(ST_DPLL_CLK_MASK, 0,
(void *)dpll_regs->cm_idlest_dpll, LDELAY)) {
printf("Bypassing DPLL failed 0x%x\n",
dpll_regs->cm_clkmode_dpll);
}
}
static void bypass_dpll(const struct dpll_regs *dpll_regs)
{
do_bypass_dpll(dpll_regs);
wait_for_bypass(dpll_regs);
}
void do_setup_dpll(const struct dpll_regs *dpll_regs,
const struct dpll_params *params)
{
u32 temp;
if (!params)
return;
temp = readl(dpll_regs->cm_clksel_dpll);
bypass_dpll(dpll_regs);
/* Set M & N */
temp &= ~CM_CLKSEL_DPLL_M_MASK;
temp |= (params->m << CM_CLKSEL_DPLL_M_SHIFT) & CM_CLKSEL_DPLL_M_MASK;
temp &= ~CM_CLKSEL_DPLL_N_MASK;
temp |= (params->n << CM_CLKSEL_DPLL_N_SHIFT) & CM_CLKSEL_DPLL_N_MASK;
writel(temp, dpll_regs->cm_clksel_dpll);
setup_post_dividers(dpll_regs, params);
/* Wait till the DPLL locks */
do_lock_dpll(dpll_regs);
wait_for_lock(dpll_regs);
}
static void setup_dplls(void)
{
const struct dpll_params *params;
params = get_dpll_core_params();
do_setup_dpll(&dpll_core_regs, params);
params = get_dpll_mpu_params();
do_setup_dpll(&dpll_mpu_regs, params);
params = get_dpll_per_params();
do_setup_dpll(&dpll_per_regs, params);
writel(0x300, &cmwkup->clkdcoldodpllper);
params = get_dpll_ddr_params();
do_setup_dpll(&dpll_ddr_regs, params);
}
static inline void wait_for_clk_enable(u32 *clkctrl_addr)
{
u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_DISABLED;
u32 bound = LDELAY;
while ((idlest == MODULE_CLKCTRL_IDLEST_DISABLED) ||
(idlest == MODULE_CLKCTRL_IDLEST_TRANSITIONING)) {
clkctrl = readl(clkctrl_addr);
idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >>
MODULE_CLKCTRL_IDLEST_SHIFT;
if (--bound == 0) {
printf("Clock enable failed for 0x%p idlest 0x%x\n",
clkctrl_addr, clkctrl);
return;
}
}
}
static inline void enable_clock_module(u32 *const clkctrl_addr, u32 enable_mode,
u32 wait_for_enable)
{
clrsetbits_le32(clkctrl_addr, MODULE_CLKCTRL_MODULEMODE_MASK,
enable_mode << MODULE_CLKCTRL_MODULEMODE_SHIFT);
debug("Enable clock module - %p\n", clkctrl_addr);
if (wait_for_enable)
wait_for_clk_enable(clkctrl_addr);
}
static inline void wait_for_clk_disable(u32 *clkctrl_addr)
{
u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_FULLY_FUNCTIONAL;
u32 bound = LDELAY;
while ((idlest != MODULE_CLKCTRL_IDLEST_DISABLED)) {
clkctrl = readl(clkctrl_addr);
idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >>
MODULE_CLKCTRL_IDLEST_SHIFT;
if (--bound == 0) {
printf("Clock disable failed for 0x%p idlest 0x%x\n",
clkctrl_addr, clkctrl);
return;
}
}
}
static inline void disable_clock_module(u32 *const clkctrl_addr,
u32 wait_for_disable)
{
clrsetbits_le32(clkctrl_addr, MODULE_CLKCTRL_MODULEMODE_MASK,
MODULE_CLKCTRL_MODULEMODE_SW_DISABLE <<
MODULE_CLKCTRL_MODULEMODE_SHIFT);
debug("Disable clock module - %p\n", clkctrl_addr);
if (wait_for_disable)
wait_for_clk_disable(clkctrl_addr);
}
static inline void enable_clock_domain(u32 *const clkctrl_reg, u32 enable_mode)
{
clrsetbits_le32(clkctrl_reg, CD_CLKCTRL_CLKTRCTRL_MASK,
enable_mode << CD_CLKCTRL_CLKTRCTRL_SHIFT);
debug("Enable clock domain - %p\n", clkctrl_reg);
}
static inline void disable_clock_domain(u32 *const clkctrl_reg)
{
clrsetbits_le32(clkctrl_reg, CD_CLKCTRL_CLKTRCTRL_MASK,
CD_CLKCTRL_CLKTRCTRL_SW_SLEEP <<
CD_CLKCTRL_CLKTRCTRL_SHIFT);
debug("Disable clock domain - %p\n", clkctrl_reg);
}
void do_enable_clocks(u32 *const *clk_domains,
u32 *const *clk_modules_explicit_en, u8 wait_for_enable)
{
u32 i, max = 100;
/* Put the clock domains in SW_WKUP mode */
for (i = 0; (i < max) && clk_domains[i]; i++) {
enable_clock_domain(clk_domains[i],
CD_CLKCTRL_CLKTRCTRL_SW_WKUP);
}
/* Clock modules that need to be put in SW_EXPLICIT_EN mode */
for (i = 0; (i < max) && clk_modules_explicit_en[i]; i++) {
enable_clock_module(clk_modules_explicit_en[i],
MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN,
wait_for_enable);
};
}
void do_disable_clocks(u32 *const *clk_domains,
u32 *const *clk_modules_disable,
u8 wait_for_disable)
{
u32 i, max = 100;
/* Clock modules that need to be put in SW_DISABLE */
for (i = 0; (i < max) && clk_modules_disable[i]; i++)
disable_clock_module(clk_modules_disable[i],
wait_for_disable);
/* Put the clock domains in SW_SLEEP mode */
for (i = 0; (i < max) && clk_domains[i]; i++)
disable_clock_domain(clk_domains[i]);
}
/*
* Before scaling up the clocks we need to have the PMIC scale up the
* voltages first. This will be dependent on which PMIC is in use
* and in some cases we may not be scaling things up at all and thus not
* need to do anything here.
*/
__weak void scale_vcores(void)
{
}
void setup_early_clocks(void)
{
setup_clocks_for_console();
enable_basic_clocks();
timer_init();
}
void prcm_init(void)
{
scale_vcores();
setup_dplls();
}
void rtc_only_prcm_init(void)
{
const struct dpll_params *params;
rtc_only_enable_basic_clocks();
params = get_dpll_ddr_params();
do_setup_dpll(&dpll_ddr_regs, params);
}
@@ -0,0 +1,309 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* clock_am33xx.c
*
* clocks for AM33XX based boards
*
* Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/
*/
#include <common.h>
#include <asm/arch/cpu.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/clock.h>
#include <asm/arch/hardware.h>
#include <asm/io.h>
#define OSC (V_OSCK/1000000)
struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER;
struct cm_wkuppll *const cmwkup = (struct cm_wkuppll *)CM_WKUP;
struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL;
struct cm_rtc *const cmrtc = (struct cm_rtc *)CM_RTC;
const struct dpll_regs dpll_mpu_regs = {
.cm_clkmode_dpll = CM_WKUP + 0x88,
.cm_idlest_dpll = CM_WKUP + 0x20,
.cm_clksel_dpll = CM_WKUP + 0x2C,
.cm_div_m2_dpll = CM_WKUP + 0xA8,
};
const struct dpll_regs dpll_core_regs = {
.cm_clkmode_dpll = CM_WKUP + 0x90,
.cm_idlest_dpll = CM_WKUP + 0x5C,
.cm_clksel_dpll = CM_WKUP + 0x68,
.cm_div_m4_dpll = CM_WKUP + 0x80,
.cm_div_m5_dpll = CM_WKUP + 0x84,
.cm_div_m6_dpll = CM_WKUP + 0xD8,
};
const struct dpll_regs dpll_per_regs = {
.cm_clkmode_dpll = CM_WKUP + 0x8C,
.cm_idlest_dpll = CM_WKUP + 0x70,
.cm_clksel_dpll = CM_WKUP + 0x9C,
.cm_div_m2_dpll = CM_WKUP + 0xAC,
};
const struct dpll_regs dpll_ddr_regs = {
.cm_clkmode_dpll = CM_WKUP + 0x94,
.cm_idlest_dpll = CM_WKUP + 0x34,
.cm_clksel_dpll = CM_WKUP + 0x40,
.cm_div_m2_dpll = CM_WKUP + 0xA0,
};
const struct dpll_regs dpll_disp_regs = {
.cm_clkmode_dpll = CM_WKUP + 0x98,
.cm_idlest_dpll = CM_WKUP + 0x48,
.cm_clksel_dpll = CM_WKUP + 0x54,
.cm_div_m2_dpll = CM_WKUP + 0xA4,
};
struct dpll_params dpll_mpu_opp100 = {
CONFIG_SYS_MPUCLK, OSC-1, 1, -1, -1, -1, -1};
const struct dpll_params dpll_core_opp100 = {
1000, OSC-1, -1, -1, 10, 8, 4};
const struct dpll_params dpll_mpu_opp[NUM_CRYSTAL_FREQ][NUM_OPPS] = {
{ /* 19.2 MHz */
{125, 3, 2, -1, -1, -1, -1}, /* OPP 50 */
{-1, -1, -1, -1, -1, -1, -1}, /* OPP RESERVED */
{125, 3, 1, -1, -1, -1, -1}, /* OPP 100 */
{150, 3, 1, -1, -1, -1, -1}, /* OPP 120 */
{125, 2, 1, -1, -1, -1, -1}, /* OPP TB */
{625, 11, 1, -1, -1, -1, -1} /* OPP NT */
},
{ /* 24 MHz */
{25, 0, 2, -1, -1, -1, -1}, /* OPP 50 */
{-1, -1, -1, -1, -1, -1, -1}, /* OPP RESERVED */
{25, 0, 1, -1, -1, -1, -1}, /* OPP 100 */
{30, 0, 1, -1, -1, -1, -1}, /* OPP 120 */
{100, 3, 1, -1, -1, -1, -1}, /* OPP TB */
{125, 2, 1, -1, -1, -1, -1} /* OPP NT */
},
{ /* 25 MHz */
{24, 0, 2, -1, -1, -1, -1}, /* OPP 50 */
{-1, -1, -1, -1, -1, -1, -1}, /* OPP RESERVED */
{24, 0, 1, -1, -1, -1, -1}, /* OPP 100 */
{144, 4, 1, -1, -1, -1, -1}, /* OPP 120 */
{32, 0, 1, -1, -1, -1, -1}, /* OPP TB */
{40, 0, 1, -1, -1, -1, -1} /* OPP NT */
},
{ /* 26 MHz */
{300, 12, 2, -1, -1, -1, -1}, /* OPP 50 */
{-1, -1, -1, -1, -1, -1, -1}, /* OPP RESERVED */
{300, 12, 1, -1, -1, -1, -1}, /* OPP 100 */
{360, 12, 1, -1, -1, -1, -1}, /* OPP 120 */
{400, 12, 1, -1, -1, -1, -1}, /* OPP TB */
{500, 12, 1, -1, -1, -1, -1} /* OPP NT */
},
};
const struct dpll_params dpll_core_1000MHz[NUM_CRYSTAL_FREQ] = {
{625, 11, -1, -1, 10, 8, 4}, /* 19.2 MHz */
{125, 2, -1, -1, 10, 8, 4}, /* 24 MHz */
{40, 0, -1, -1, 10, 8, 4}, /* 25 MHz */
{500, 12, -1, -1, 10, 8, 4} /* 26 MHz */
};
const struct dpll_params dpll_per_192MHz[NUM_CRYSTAL_FREQ] = {
{400, 7, 5, -1, -1, -1, -1}, /* 19.2 MHz */
{400, 9, 5, -1, -1, -1, -1}, /* 24 MHz */
{384, 9, 5, -1, -1, -1, -1}, /* 25 MHz */
{480, 12, 5, -1, -1, -1, -1} /* 26 MHz */
};
const struct dpll_params dpll_ddr3_303MHz[NUM_CRYSTAL_FREQ] = {
{505, 15, 2, -1, -1, -1, -1}, /*19.2*/
{101, 3, 2, -1, -1, -1, -1}, /* 24 MHz */
{303, 24, 1, -1, -1, -1, -1}, /* 25 MHz */
{303, 12, 2, -1, -1, -1, -1} /* 26 MHz */
};
const struct dpll_params dpll_ddr3_400MHz[NUM_CRYSTAL_FREQ] = {
{125, 5, 1, -1, -1, -1, -1}, /*19.2*/
{50, 2, 1, -1, -1, -1, -1}, /* 24 MHz */
{16, 0, 1, -1, -1, -1, -1}, /* 25 MHz */
{200, 12, 1, -1, -1, -1, -1} /* 26 MHz */
};
const struct dpll_params dpll_ddr2_266MHz[NUM_CRYSTAL_FREQ] = {
{665, 47, 1, -1, -1, -1, -1}, /*19.2*/
{133, 11, 1, -1, -1, -1, -1}, /* 24 MHz */
{266, 24, 1, -1, -1, -1, -1}, /* 25 MHz */
{133, 12, 1, -1, -1, -1, -1} /* 26 MHz */
};
__weak const struct dpll_params *get_dpll_mpu_params(void)
{
return &dpll_mpu_opp100;
}
const struct dpll_params *get_dpll_core_params(void)
{
int ind = get_sys_clk_index();
return &dpll_core_1000MHz[ind];
}
const struct dpll_params *get_dpll_per_params(void)
{
int ind = get_sys_clk_index();
return &dpll_per_192MHz[ind];
}
void setup_clocks_for_console(void)
{
clrsetbits_le32(&cmwkup->wkclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK,
CD_CLKCTRL_CLKTRCTRL_SW_WKUP <<
CD_CLKCTRL_CLKTRCTRL_SHIFT);
clrsetbits_le32(&cmper->l4hsclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK,
CD_CLKCTRL_CLKTRCTRL_SW_WKUP <<
CD_CLKCTRL_CLKTRCTRL_SHIFT);
clrsetbits_le32(&cmwkup->wkup_uart0ctrl,
MODULE_CLKCTRL_MODULEMODE_MASK,
MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
MODULE_CLKCTRL_MODULEMODE_SHIFT);
clrsetbits_le32(&cmper->uart1clkctrl,
MODULE_CLKCTRL_MODULEMODE_MASK,
MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
MODULE_CLKCTRL_MODULEMODE_SHIFT);
clrsetbits_le32(&cmper->uart2clkctrl,
MODULE_CLKCTRL_MODULEMODE_MASK,
MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
MODULE_CLKCTRL_MODULEMODE_SHIFT);
clrsetbits_le32(&cmper->uart3clkctrl,
MODULE_CLKCTRL_MODULEMODE_MASK,
MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
MODULE_CLKCTRL_MODULEMODE_SHIFT);
clrsetbits_le32(&cmper->uart4clkctrl,
MODULE_CLKCTRL_MODULEMODE_MASK,
MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
MODULE_CLKCTRL_MODULEMODE_SHIFT);
clrsetbits_le32(&cmper->uart5clkctrl,
MODULE_CLKCTRL_MODULEMODE_MASK,
MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
MODULE_CLKCTRL_MODULEMODE_SHIFT);
}
void enable_basic_clocks(void)
{
u32 *const clk_domains[] = {
&cmper->l3clkstctrl,
&cmper->l4fwclkstctrl,
&cmper->l3sclkstctrl,
&cmper->l4lsclkstctrl,
&cmwkup->wkclkstctrl,
&cmper->emiffwclkctrl,
&cmrtc->clkstctrl,
0
};
u32 *const clk_modules_explicit_en[] = {
&cmper->l3clkctrl,
&cmper->l4lsclkctrl,
&cmper->l4fwclkctrl,
&cmwkup->wkl4wkclkctrl,
&cmper->l3instrclkctrl,
&cmper->l4hsclkctrl,
&cmwkup->wkgpio0clkctrl,
&cmwkup->wkctrlclkctrl,
&cmper->timer2clkctrl,
&cmper->gpmcclkctrl,
&cmper->elmclkctrl,
&cmper->mmc0clkctrl,
&cmper->mmc1clkctrl,
&cmwkup->wkup_i2c0ctrl,
&cmper->gpio1clkctrl,
&cmper->gpio2clkctrl,
&cmper->gpio3clkctrl,
&cmper->i2c1clkctrl,
&cmper->cpgmac0clkctrl,
&cmper->spi0clkctrl,
&cmrtc->rtcclkctrl,
&cmper->usb0clkctrl,
&cmper->emiffwclkctrl,
&cmper->emifclkctrl,
0
};
do_enable_clocks(clk_domains, clk_modules_explicit_en, 1);
/* Select the Master osc 24 MHZ as Timer2 clock source */
writel(0x1, &cmdpll->clktimer2clk);
}
/*
* Enable Spread Spectrum for the MPU by calculating the required
* values and setting the registers accordingly.
* @param permille The spreading in permille (10th of a percent)
*/
void set_mpu_spreadspectrum(int permille)
{
u32 multiplier_m;
u32 predivider_n;
u32 cm_clksel_dpll_mpu;
u32 cm_clkmode_dpll_mpu;
u32 ref_clock;
u32 pll_bandwidth;
u32 mod_freq_divider;
u32 exponent;
u32 mantissa;
u32 delta_m_step;
printf("Enabling Spread Spectrum of %d permille for MPU\n",
permille);
/* Read PLL parameter m and n */
cm_clksel_dpll_mpu = readl(&cmwkup->clkseldpllmpu);
multiplier_m = (cm_clksel_dpll_mpu >> 8) & 0x3FF;
predivider_n = cm_clksel_dpll_mpu & 0x7F;
/*
* Calculate reference clock (clock after pre-divider),
* its max. PLL bandwidth,
* and resulting mod_freq_divider
*/
ref_clock = V_OSCK / (predivider_n + 1);
pll_bandwidth = ref_clock / 70;
mod_freq_divider = ref_clock / (4 * pll_bandwidth);
/* Calculate Mantissa/Exponent */
exponent = 0;
mantissa = mod_freq_divider;
while ((mantissa > 127) && (exponent < 7)) {
exponent++;
mantissa /= 2;
}
if (mantissa > 127)
mantissa = 127;
mod_freq_divider = mantissa << exponent;
/*
* Calculate Modulation steps
* As we use Downspread only, the spread is twice the value of
* permille, so Div2!
* As it takes the value in percent, divide by ten!
*/
delta_m_step = ((u32)((multiplier_m * permille) / 10 / 2)) << 18;
delta_m_step /= 100;
delta_m_step /= mod_freq_divider;
if (delta_m_step > 0xFFFFF)
delta_m_step = 0xFFFFF;
/* Setup Spread Spectrum */
writel(delta_m_step, &cmwkup->sscdeltamstepdllmpu);
writel((exponent << 8) | mantissa, &cmwkup->sscmodfreqdivdpllmpu);
cm_clkmode_dpll_mpu = readl(&cmwkup->clkmoddpllmpu);
/* clear all SSC flags */
cm_clkmode_dpll_mpu &= ~(0xF << CM_CLKMODE_DPLL_SSC_EN_SHIFT);
/* enable SSC with Downspread only */
cm_clkmode_dpll_mpu |= CM_CLKMODE_DPLL_SSC_EN_MASK |
CM_CLKMODE_DPLL_SSC_DOWNSPREAD_MASK;
writel(cm_clkmode_dpll_mpu, &cmwkup->clkmoddpllmpu);
while (!(readl(&cmwkup->clkmoddpllmpu) & 0x2000))
;
}
@@ -0,0 +1,251 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* clock_am43xx.c
*
* clocks for AM43XX based boards
* Derived from AM33XX based boards
*
* Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/
*/
#include <common.h>
#include <asm/arch/cpu.h>
#include <asm/arch/clock.h>
#include <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER;
struct cm_wkuppll *const cmwkup = (struct cm_wkuppll *)CM_WKUP;
struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL;
const struct dpll_regs dpll_mpu_regs = {
.cm_clkmode_dpll = CM_WKUP + 0x560,
.cm_idlest_dpll = CM_WKUP + 0x564,
.cm_clksel_dpll = CM_WKUP + 0x56c,
.cm_div_m2_dpll = CM_WKUP + 0x570,
};
const struct dpll_regs dpll_core_regs = {
.cm_clkmode_dpll = CM_WKUP + 0x520,
.cm_idlest_dpll = CM_WKUP + 0x524,
.cm_clksel_dpll = CM_WKUP + 0x52C,
.cm_div_m4_dpll = CM_WKUP + 0x538,
.cm_div_m5_dpll = CM_WKUP + 0x53C,
.cm_div_m6_dpll = CM_WKUP + 0x540,
};
const struct dpll_regs dpll_per_regs = {
.cm_clkmode_dpll = CM_WKUP + 0x5E0,
.cm_idlest_dpll = CM_WKUP + 0x5E4,
.cm_clksel_dpll = CM_WKUP + 0x5EC,
.cm_div_m2_dpll = CM_WKUP + 0x5F0,
};
const struct dpll_regs dpll_ddr_regs = {
.cm_clkmode_dpll = CM_WKUP + 0x5A0,
.cm_idlest_dpll = CM_WKUP + 0x5A4,
.cm_clksel_dpll = CM_WKUP + 0x5AC,
.cm_div_m2_dpll = CM_WKUP + 0x5B0,
.cm_div_m4_dpll = CM_WKUP + 0x5B8,
};
void setup_clocks_for_console(void)
{
u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_DISABLED;
/* Do not add any spl_debug prints in this function */
clrsetbits_le32(&cmwkup->wkclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK,
CD_CLKCTRL_CLKTRCTRL_SW_WKUP <<
CD_CLKCTRL_CLKTRCTRL_SHIFT);
/* Enable UART0 */
clrsetbits_le32(&cmwkup->wkup_uart0ctrl,
MODULE_CLKCTRL_MODULEMODE_MASK,
MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
MODULE_CLKCTRL_MODULEMODE_SHIFT);
while ((idlest == MODULE_CLKCTRL_IDLEST_DISABLED) ||
(idlest == MODULE_CLKCTRL_IDLEST_TRANSITIONING)) {
clkctrl = readl(&cmwkup->wkup_uart0ctrl);
idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >>
MODULE_CLKCTRL_IDLEST_SHIFT;
}
}
void enable_basic_clocks(void)
{
u32 *const clk_domains[] = {
&cmper->l3clkstctrl,
&cmper->l3sclkstctrl,
&cmper->l4lsclkstctrl,
&cmwkup->wkclkstctrl,
&cmper->emifclkstctrl,
0
};
u32 *const clk_modules_explicit_en[] = {
&cmper->l3clkctrl,
&cmper->l4lsclkctrl,
&cmper->l4fwclkctrl,
&cmwkup->wkl4wkclkctrl,
&cmper->l3instrclkctrl,
&cmper->l4hsclkctrl,
&cmwkup->wkgpio0clkctrl,
&cmwkup->wkctrlclkctrl,
&cmper->timer2clkctrl,
&cmper->gpmcclkctrl,
&cmper->elmclkctrl,
&cmper->mmc0clkctrl,
&cmper->mmc1clkctrl,
&cmwkup->wkup_i2c0ctrl,
&cmper->gpio1clkctrl,
&cmper->gpio2clkctrl,
&cmper->gpio3clkctrl,
&cmper->gpio4clkctrl,
&cmper->gpio5clkctrl,
&cmper->i2c1clkctrl,
&cmper->cpgmac0clkctrl,
&cmper->emiffwclkctrl,
&cmper->emifclkctrl,
&cmper->otfaemifclkctrl,
&cmper->qspiclkctrl,
&cmper->spi0clkctrl,
0
};
do_enable_clocks(clk_domains, clk_modules_explicit_en, 1);
/* Select the Master osc clk as Timer2 clock source */
writel(0x1, &cmdpll->clktimer2clk);
/* For OPP100 the mac clock should be /5. */
writel(0x4, &cmdpll->clkselmacclk);
}
void rtc_only_enable_basic_clocks(void)
{
u32 *const clk_domains[] = {
&cmper->emifclkstctrl,
0
};
u32 *const clk_modules_explicit_en[] = {
&cmper->gpio5clkctrl,
&cmper->emiffwclkctrl,
&cmper->emifclkctrl,
&cmper->otfaemifclkctrl,
0
};
do_enable_clocks(clk_domains, clk_modules_explicit_en, 1);
/* Select the Master osc clk as Timer2 clock source */
writel(0x1, &cmdpll->clktimer2clk);
}
#ifdef CONFIG_TI_EDMA3
void enable_edma3_clocks(void)
{
u32 *const clk_domains_edma3[] = {
0
};
u32 *const clk_modules_explicit_en_edma3[] = {
&cmper->tpccclkctrl,
&cmper->tptc0clkctrl,
0
};
do_enable_clocks(clk_domains_edma3,
clk_modules_explicit_en_edma3,
1);
}
void disable_edma3_clocks(void)
{
u32 *const clk_domains_edma3[] = {
0
};
u32 *const clk_modules_disable_edma3[] = {
&cmper->tpccclkctrl,
&cmper->tptc0clkctrl,
0
};
do_disable_clocks(clk_domains_edma3,
clk_modules_disable_edma3,
1);
}
#endif
#if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP)
void enable_usb_clocks(int index)
{
u32 *usbclkctrl = 0;
u32 *usbphyocp2scpclkctrl = 0;
if (index == 0) {
usbclkctrl = &cmper->usb0clkctrl;
usbphyocp2scpclkctrl = &cmper->usbphyocp2scp0clkctrl;
setbits_le32(&cmper->usb0clkctrl,
USBOTGSSX_CLKCTRL_OPTFCLKEN_REFCLK960);
setbits_le32(&cmwkup->usbphy0clkctrl,
USBPHY0_CLKCTRL_OPTFCLKEN_CLK32K);
} else if (index == 1) {
usbclkctrl = &cmper->usb1clkctrl;
usbphyocp2scpclkctrl = &cmper->usbphyocp2scp1clkctrl;
setbits_le32(&cmper->usb1clkctrl,
USBOTGSSX_CLKCTRL_OPTFCLKEN_REFCLK960);
setbits_le32(&cmwkup->usbphy1clkctrl,
USBPHY0_CLKCTRL_OPTFCLKEN_CLK32K);
}
u32 *const clk_domains_usb[] = {
0
};
u32 *const clk_modules_explicit_en_usb[] = {
usbclkctrl,
usbphyocp2scpclkctrl,
0
};
do_enable_clocks(clk_domains_usb, clk_modules_explicit_en_usb, 1);
}
void disable_usb_clocks(int index)
{
u32 *usbclkctrl = 0;
u32 *usbphyocp2scpclkctrl = 0;
if (index == 0) {
usbclkctrl = &cmper->usb0clkctrl;
usbphyocp2scpclkctrl = &cmper->usbphyocp2scp0clkctrl;
clrbits_le32(&cmper->usb0clkctrl,
USBOTGSSX_CLKCTRL_OPTFCLKEN_REFCLK960);
clrbits_le32(&cmwkup->usbphy0clkctrl,
USBPHY0_CLKCTRL_OPTFCLKEN_CLK32K);
} else if (index == 1) {
usbclkctrl = &cmper->usb1clkctrl;
usbphyocp2scpclkctrl = &cmper->usbphyocp2scp1clkctrl;
clrbits_le32(&cmper->usb1clkctrl,
USBOTGSSX_CLKCTRL_OPTFCLKEN_REFCLK960);
clrbits_le32(&cmwkup->usbphy1clkctrl,
USBPHY0_CLKCTRL_OPTFCLKEN_CLK32K);
}
u32 *const clk_domains_usb[] = {
0
};
u32 *const clk_modules_disable_usb[] = {
usbclkctrl,
usbphyocp2scpclkctrl,
0
};
do_disable_clocks(clk_domains_usb, clk_modules_disable_usb, 1);
}
#endif
@@ -0,0 +1,409 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* clock_ti814x.c
*
* Clocks for TI814X based boards
*
* Copyright (C) 2013, Texas Instruments, Incorporated
*/
#include <common.h>
#include <asm/arch/cpu.h>
#include <asm/arch/clock.h>
#include <asm/arch/hardware.h>
#include <asm/io.h>
/* PRCM */
#define PRCM_MOD_EN 0x2
/* CLK_SRC */
#define OSC_SRC0 0
#define OSC_SRC1 1
#define L3_OSC_SRC OSC_SRC0
#define OSC_0_FREQ 20
#define DCO_HS2_MIN 500
#define DCO_HS2_MAX 1000
#define DCO_HS1_MIN 1000
#define DCO_HS1_MAX 2000
#define SELFREQDCO_HS2 0x00000801
#define SELFREQDCO_HS1 0x00001001
#define MPU_N 0x1
#define MPU_M 0x3C
#define MPU_M2 1
#define MPU_CLKCTRL 0x1
#define L3_N 19
#define L3_M 880
#define L3_M2 4
#define L3_CLKCTRL 0x801
#define DDR_N 19
#define DDR_M 666
#define DDR_M2 2
#define DDR_CLKCTRL 0x801
/* ADPLLJ register values */
#define ADPLLJ_CLKCTRL_HS2 0x00000801 /* HS2 mode, TINT2 = 1 */
#define ADPLLJ_CLKCTRL_HS1 0x00001001 /* HS1 mode, TINT2 = 1 */
#define ADPLLJ_CLKCTRL_CLKDCOLDOEN (1 << 29)
#define ADPLLJ_CLKCTRL_IDLE (1 << 23)
#define ADPLLJ_CLKCTRL_CLKOUTEN (1 << 20)
#define ADPLLJ_CLKCTRL_CLKOUTLDOEN (1 << 19)
#define ADPLLJ_CLKCTRL_CLKDCOLDOPWDNZ (1 << 17)
#define ADPLLJ_CLKCTRL_LPMODE (1 << 12)
#define ADPLLJ_CLKCTRL_DRIFTGUARDIAN (1 << 11)
#define ADPLLJ_CLKCTRL_REGM4XEN (1 << 10)
#define ADPLLJ_CLKCTRL_TINITZ (1 << 0)
#define ADPLLJ_CLKCTRL_CLKDCO (ADPLLJ_CLKCTRL_CLKDCOLDOEN | \
ADPLLJ_CLKCTRL_CLKOUTEN | \
ADPLLJ_CLKCTRL_CLKOUTLDOEN | \
ADPLLJ_CLKCTRL_CLKDCOLDOPWDNZ)
#define ADPLLJ_STATUS_PHASELOCK (1 << 10)
#define ADPLLJ_STATUS_FREQLOCK (1 << 9)
#define ADPLLJ_STATUS_PHSFRQLOCK (ADPLLJ_STATUS_PHASELOCK | \
ADPLLJ_STATUS_FREQLOCK)
#define ADPLLJ_STATUS_BYPASSACK (1 << 8)
#define ADPLLJ_STATUS_BYPASS (1 << 0)
#define ADPLLJ_STATUS_BYPASSANDACK (ADPLLJ_STATUS_BYPASSACK | \
ADPLLJ_STATUS_BYPASS)
#define ADPLLJ_TENABLE_ENB (1 << 0)
#define ADPLLJ_TENABLEDIV_ENB (1 << 0)
#define ADPLLJ_M2NDIV_M2SHIFT 16
#define MPU_PLL_BASE (PLL_SUBSYS_BASE + 0x048)
#define L3_PLL_BASE (PLL_SUBSYS_BASE + 0x110)
#define DDR_PLL_BASE (PLL_SUBSYS_BASE + 0x290)
struct ad_pll {
unsigned int pwrctrl;
unsigned int clkctrl;
unsigned int tenable;
unsigned int tenablediv;
unsigned int m2ndiv;
unsigned int mn2div;
unsigned int fracdiv;
unsigned int bwctrl;
unsigned int fracctrl;
unsigned int status;
unsigned int m3div;
unsigned int rampctrl;
};
#define OSC_SRC_CTRL (PLL_SUBSYS_BASE + 0x2C0)
#define ENET_CLKCTRL_CMPL 0x30000
#define SATA_PLL_BASE (CTRL_BASE + 0x0720)
struct sata_pll {
unsigned int pllcfg0;
unsigned int pllcfg1;
unsigned int pllcfg2;
unsigned int pllcfg3;
unsigned int pllcfg4;
unsigned int pllstatus;
unsigned int rxstatus;
unsigned int txstatus;
unsigned int testcfg;
};
#define SEL_IN_FREQ (0x1 << 31)
#define DIGCLRZ (0x1 << 30)
#define ENDIGLDO (0x1 << 4)
#define APLL_CP_CURR (0x1 << 3)
#define ENBGSC_REF (0x1 << 2)
#define ENPLLLDO (0x1 << 1)
#define ENPLL (0x1 << 0)
#define SATA_PLLCFG0_1 (SEL_IN_FREQ | ENBGSC_REF)
#define SATA_PLLCFG0_2 (SEL_IN_FREQ | ENDIGLDO | ENBGSC_REF)
#define SATA_PLLCFG0_3 (SEL_IN_FREQ | ENDIGLDO | ENBGSC_REF | ENPLLLDO)
#define SATA_PLLCFG0_4 (SEL_IN_FREQ | DIGCLRZ | ENDIGLDO | ENBGSC_REF | \
ENPLLLDO | ENPLL)
#define PLL_LOCK (0x1 << 0)
#define ENSATAMODE (0x1 << 31)
#define PLLREFSEL (0x1 << 30)
#define MDIVINT (0x4b << 18)
#define EN_CLKAUX (0x1 << 5)
#define EN_CLK125M (0x1 << 4)
#define EN_CLK100M (0x1 << 3)
#define EN_CLK50M (0x1 << 2)
#define SATA_PLLCFG1 (ENSATAMODE | \
PLLREFSEL | \
MDIVINT | \
EN_CLKAUX | \
EN_CLK125M | \
EN_CLK100M | \
EN_CLK50M)
#define DIGLDO_EN_CAPLESSMODE (0x1 << 22)
#define PLLDO_EN_LDO_STABLE (0x1 << 11)
#define PLLDO_EN_BUF_CUR (0x1 << 7)
#define PLLDO_EN_LP (0x1 << 6)
#define PLLDO_CTRL_TRIM_1_4V (0x10 << 1)
#define SATA_PLLCFG3 (DIGLDO_EN_CAPLESSMODE | \
PLLDO_EN_LDO_STABLE | \
PLLDO_EN_BUF_CUR | \
PLLDO_EN_LP | \
PLLDO_CTRL_TRIM_1_4V)
const struct cm_alwon *cmalwon = (struct cm_alwon *)CM_ALWON_BASE;
const struct cm_def *cmdef = (struct cm_def *)CM_DEFAULT_BASE;
const struct sata_pll *spll = (struct sata_pll *)SATA_PLL_BASE;
/*
* Enable the peripheral clock for required peripherals
*/
static void enable_per_clocks(void)
{
/* HSMMC1 */
writel(PRCM_MOD_EN, &cmalwon->mmchs1clkctrl);
while (readl(&cmalwon->mmchs1clkctrl) != PRCM_MOD_EN)
;
/* Ethernet */
writel(PRCM_MOD_EN, &cmalwon->ethclkstctrl);
writel(PRCM_MOD_EN, &cmalwon->ethernet0clkctrl);
while ((readl(&cmalwon->ethernet0clkctrl) & ENET_CLKCTRL_CMPL) != 0)
;
writel(PRCM_MOD_EN, &cmalwon->ethernet1clkctrl);
while ((readl(&cmalwon->ethernet1clkctrl) & ENET_CLKCTRL_CMPL) != 0)
;
/* RTC clocks */
writel(PRCM_MOD_EN, &cmalwon->rtcclkstctrl);
writel(PRCM_MOD_EN, &cmalwon->rtcclkctrl);
while (readl(&cmalwon->rtcclkctrl) != PRCM_MOD_EN)
;
}
/*
* select the HS1 or HS2 for DCO Freq
* return : CLKCTRL
*/
static u32 pll_dco_freq_sel(u32 clkout_dco)
{
if (clkout_dco >= DCO_HS2_MIN && clkout_dco < DCO_HS2_MAX)
return SELFREQDCO_HS2;
else if (clkout_dco >= DCO_HS1_MIN && clkout_dco < DCO_HS1_MAX)
return SELFREQDCO_HS1;
else
return -1;
}
/*
* select the sigma delta config
* return: sigma delta val
*/
static u32 pll_sigma_delta_val(u32 clkout_dco)
{
u32 sig_val = 0;
sig_val = (clkout_dco + 225) / 250;
sig_val = sig_val << 24;
return sig_val;
}
/*
* configure individual ADPLLJ
*/
static void pll_config(u32 base, u32 n, u32 m, u32 m2,
u32 clkctrl_val, int adpllj)
{
const struct ad_pll *adpll = (struct ad_pll *)base;
u32 m2nval, mn2val, read_clkctrl = 0, clkout_dco = 0;
u32 sig_val = 0, hs_mod = 0;
m2nval = (m2 << ADPLLJ_M2NDIV_M2SHIFT) | n;
mn2val = m;
/* calculate clkout_dco */
clkout_dco = ((OSC_0_FREQ / (n+1)) * m);
/* sigma delta & Hs mode selection skip for ADPLLS*/
if (adpllj) {
sig_val = pll_sigma_delta_val(clkout_dco);
hs_mod = pll_dco_freq_sel(clkout_dco);
}
/* by-pass pll */
read_clkctrl = readl(&adpll->clkctrl);
writel((read_clkctrl | ADPLLJ_CLKCTRL_IDLE), &adpll->clkctrl);
while ((readl(&adpll->status) & ADPLLJ_STATUS_BYPASSANDACK)
!= ADPLLJ_STATUS_BYPASSANDACK)
;
/* clear TINITZ */
read_clkctrl = readl(&adpll->clkctrl);
writel((read_clkctrl & ~ADPLLJ_CLKCTRL_TINITZ), &adpll->clkctrl);
/*
* ref_clk = 20/(n + 1);
* clkout_dco = ref_clk * m;
* clk_out = clkout_dco/m2;
*/
read_clkctrl = readl(&adpll->clkctrl) &
~(ADPLLJ_CLKCTRL_LPMODE |
ADPLLJ_CLKCTRL_DRIFTGUARDIAN |
ADPLLJ_CLKCTRL_REGM4XEN);
writel(m2nval, &adpll->m2ndiv);
writel(mn2val, &adpll->mn2div);
/* Skip for modena(ADPLLS) */
if (adpllj) {
writel(sig_val, &adpll->fracdiv);
writel((read_clkctrl | hs_mod), &adpll->clkctrl);
}
/* Load M2, N2 dividers of ADPLL */
writel(ADPLLJ_TENABLEDIV_ENB, &adpll->tenablediv);
writel(~ADPLLJ_TENABLEDIV_ENB, &adpll->tenablediv);
/* Load M, N dividers of ADPLL */
writel(ADPLLJ_TENABLE_ENB, &adpll->tenable);
writel(~ADPLLJ_TENABLE_ENB, &adpll->tenable);
/* Configure CLKDCOLDOEN,CLKOUTLDOEN,CLKOUT Enable BITS */
read_clkctrl = readl(&adpll->clkctrl) & ~ADPLLJ_CLKCTRL_CLKDCO;
if (adpllj)
writel((read_clkctrl | ADPLLJ_CLKCTRL_CLKDCO),
&adpll->clkctrl);
/* Enable TINTZ and disable IDLE(PLL in Active & Locked Mode */
read_clkctrl = readl(&adpll->clkctrl) & ~ADPLLJ_CLKCTRL_IDLE;
writel((read_clkctrl | ADPLLJ_CLKCTRL_TINITZ), &adpll->clkctrl);
/* Wait for phase and freq lock */
while ((readl(&adpll->status) & ADPLLJ_STATUS_PHSFRQLOCK) !=
ADPLLJ_STATUS_PHSFRQLOCK)
;
}
static void unlock_pll_control_mmr(void)
{
/* TRM 2.10.1.4 and 3.2.7-3.2.11 */
writel(0x1EDA4C3D, 0x481C5040);
writel(0x2FF1AC2B, 0x48140060);
writel(0xF757FDC0, 0x48140064);
writel(0xE2BC3A6D, 0x48140068);
writel(0x1EBF131D, 0x4814006c);
writel(0x6F361E05, 0x48140070);
}
static void mpu_pll_config(void)
{
pll_config(MPU_PLL_BASE, MPU_N, MPU_M, MPU_M2, MPU_CLKCTRL, 0);
}
static void l3_pll_config(void)
{
u32 l3_osc_src, rd_osc_src = 0;
l3_osc_src = L3_OSC_SRC;
rd_osc_src = readl(OSC_SRC_CTRL);
if (OSC_SRC0 == l3_osc_src)
writel((rd_osc_src & 0xfffffffe)|0x0, OSC_SRC_CTRL);
else
writel((rd_osc_src & 0xfffffffe)|0x1, OSC_SRC_CTRL);
pll_config(L3_PLL_BASE, L3_N, L3_M, L3_M2, L3_CLKCTRL, 1);
}
void ddr_pll_config(unsigned int ddrpll_m)
{
pll_config(DDR_PLL_BASE, DDR_N, DDR_M, DDR_M2, DDR_CLKCTRL, 1);
}
void sata_pll_config(void)
{
/*
* This sequence for configuring the SATA PLL
* resident in the control module is documented
* in TI8148 TRM section 21.3.1
*/
writel(SATA_PLLCFG1, &spll->pllcfg1);
udelay(50);
writel(SATA_PLLCFG3, &spll->pllcfg3);
udelay(50);
writel(SATA_PLLCFG0_1, &spll->pllcfg0);
udelay(50);
writel(SATA_PLLCFG0_2, &spll->pllcfg0);
udelay(50);
writel(SATA_PLLCFG0_3, &spll->pllcfg0);
udelay(50);
writel(SATA_PLLCFG0_4, &spll->pllcfg0);
udelay(50);
while (((readl(&spll->pllstatus) & PLL_LOCK) == 0))
;
}
void enable_dmm_clocks(void)
{
writel(PRCM_MOD_EN, &cmdef->fwclkctrl);
writel(PRCM_MOD_EN, &cmdef->l3fastclkstctrl);
writel(PRCM_MOD_EN, &cmdef->emif0clkctrl);
while ((readl(&cmdef->emif0clkctrl)) != PRCM_MOD_EN)
;
writel(PRCM_MOD_EN, &cmdef->emif1clkctrl);
while ((readl(&cmdef->emif1clkctrl)) != PRCM_MOD_EN)
;
while ((readl(&cmdef->l3fastclkstctrl) & 0x300) != 0x300)
;
writel(PRCM_MOD_EN, &cmdef->dmmclkctrl);
while ((readl(&cmdef->dmmclkctrl)) != PRCM_MOD_EN)
;
writel(PRCM_MOD_EN, &cmalwon->l3slowclkstctrl);
while ((readl(&cmalwon->l3slowclkstctrl) & 0x2100) != 0x2100)
;
}
void setup_clocks_for_console(void)
{
unlock_pll_control_mmr();
/* UART0 */
writel(PRCM_MOD_EN, &cmalwon->uart0clkctrl);
while (readl(&cmalwon->uart0clkctrl) != PRCM_MOD_EN)
;
}
void setup_early_clocks(void)
{
setup_clocks_for_console();
}
/*
* Configure the PLL/PRCM for necessary peripherals
*/
void prcm_init(void)
{
/* Enable the control module */
writel(PRCM_MOD_EN, &cmalwon->controlclkctrl);
/* Configure PLLs */
mpu_pll_config();
l3_pll_config();
sata_pll_config();
/* Enable the required peripherals */
enable_per_clocks();
}
@@ -0,0 +1,406 @@
/*
* clock_ti816x.c
*
* Clocks for TI816X based boards
*
* Copyright (C) 2013, Adeneo Embedded <www.adeneo-embedded.com>
* Antoine Tenart, <atenart@adeneo-embedded.com>
*
* Based on TI-PSP-04.00.02.14 :
*
* Copyright (C) 2009, Texas Instruments, Incorporated
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the
* GNU General Public License for more details.
*/
#include <common.h>
#include <asm/arch/ddr_defs.h>
#include <asm/arch/cpu.h>
#include <asm/arch/clock.h>
#include <asm/arch/hardware.h>
#include <asm/io.h>
#include <asm/emif.h>
#define CM_PLL_BASE (CTRL_BASE + 0x0400)
/* Main PLL */
#define MAIN_N 64
#define MAIN_P 0x1
#define MAIN_INTFREQ1 0x8
#define MAIN_FRACFREQ1 0x800000
#define MAIN_MDIV1 0x2
#define MAIN_INTFREQ2 0xE
#define MAIN_FRACFREQ2 0x0
#define MAIN_MDIV2 0x1
#define MAIN_INTFREQ3 0x8
#define MAIN_FRACFREQ3 0xAAAAB0
#define MAIN_MDIV3 0x3
#define MAIN_INTFREQ4 0x9
#define MAIN_FRACFREQ4 0x55554F
#define MAIN_MDIV4 0x3
#define MAIN_INTFREQ5 0x9
#define MAIN_FRACFREQ5 0x374BC6
#define MAIN_MDIV5 0xC
#define MAIN_MDIV6 0x48
#define MAIN_MDIV7 0x4
/* DDR PLL */
#define DDR_N 59
#define DDR_P 0x1
#define DDR_MDIV1 0x2
#define DDR_INTFREQ2 0x8
#define DDR_FRACFREQ2 0xD99999
#define DDR_MDIV2 0x1E
#define DDR_INTFREQ3 0x8
#define DDR_FRACFREQ3 0x0
#define DDR_MDIV3 0x4
#define DDR_INTFREQ4 0xE /* Expansion DDR clk */
#define DDR_FRACFREQ4 0x0
#define DDR_MDIV4 0x4
#define DDR_INTFREQ5 0xE /* Expansion DDR clk */
#define DDR_FRACFREQ5 0x0
#define DDR_MDIV5 0x4
#define CONTROL_STATUS (CTRL_BASE + 0x40)
#define DDR_RCD (CTRL_BASE + 0x070C)
#define CM_TIMER1_CLKSEL (PRCM_BASE + 0x390)
#define CM_ALWON_CUST_EFUSE_CLKCTRL (PRCM_BASE + 0x1628)
#define INTCPS_SYSCONFIG 0x48200010
#define CM_SYSCLK10_CLKSEL 0x48180324
struct cm_pll {
unsigned int mainpll_ctrl; /* offset 0x400 */
unsigned int mainpll_pwd;
unsigned int mainpll_freq1;
unsigned int mainpll_div1;
unsigned int mainpll_freq2;
unsigned int mainpll_div2;
unsigned int mainpll_freq3;
unsigned int mainpll_div3;
unsigned int mainpll_freq4;
unsigned int mainpll_div4;
unsigned int mainpll_freq5;
unsigned int mainpll_div5;
unsigned int resv0[1];
unsigned int mainpll_div6;
unsigned int resv1[1];
unsigned int mainpll_div7;
unsigned int ddrpll_ctrl; /* offset 0x440 */
unsigned int ddrpll_pwd;
unsigned int resv2[1];
unsigned int ddrpll_div1;
unsigned int ddrpll_freq2;
unsigned int ddrpll_div2;
unsigned int ddrpll_freq3;
unsigned int ddrpll_div3;
unsigned int ddrpll_freq4;
unsigned int ddrpll_div4;
unsigned int ddrpll_freq5;
unsigned int ddrpll_div5;
unsigned int videopll_ctrl; /* offset 0x470 */
unsigned int videopll_pwd;
unsigned int videopll_freq1;
unsigned int videopll_div1;
unsigned int videopll_freq2;
unsigned int videopll_div2;
unsigned int videopll_freq3;
unsigned int videopll_div3;
unsigned int resv3[4];
unsigned int audiopll_ctrl; /* offset 0x4A0 */
unsigned int audiopll_pwd;
unsigned int resv4[2];
unsigned int audiopll_freq2;
unsigned int audiopll_div2;
unsigned int audiopll_freq3;
unsigned int audiopll_div3;
unsigned int audiopll_freq4;
unsigned int audiopll_div4;
unsigned int audiopll_freq5;
unsigned int audiopll_div5;
};
const struct cm_alwon *cmalwon = (struct cm_alwon *)CM_ALWON_BASE;
const struct cm_def *cmdef = (struct cm_def *)CM_DEFAULT_BASE;
const struct cm_pll *cmpll = (struct cm_pll *)CM_PLL_BASE;
const struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
void enable_dmm_clocks(void)
{
writel(PRCM_MOD_EN, &cmdef->dmmclkctrl);
/* Wait for dmm to be fully functional, including OCP */
while (((readl(&cmdef->dmmclkctrl) >> 17) & 0x3) != 0)
;
}
void enable_emif_clocks(void)
{
writel(PRCM_MOD_EN, &cmdef->fwclkctrl);
writel(PRCM_MOD_EN, &cmdef->l3fastclkstctrl);
writel(PRCM_MOD_EN, &cmdef->emif0clkctrl);
writel(PRCM_MOD_EN, &cmdef->emif1clkctrl);
/* Wait for clocks to be active */
while ((readl(&cmdef->l3fastclkstctrl) & 0x300) != 0x300)
;
/* Wait for emif0 to be fully functional, including OCP */
while (((readl(&cmdef->emif0clkctrl) >> 17) & 0x3) != 0)
;
/* Wait for emif1 to be fully functional, including OCP */
while (((readl(&cmdef->emif1clkctrl) >> 17) & 0x3) != 0)
;
}
/* assume delay is aprox at least 1us */
static void ddr_delay(int d)
{
int i;
/*
* read a control register.
* this is a bit more delay and cannot be optimized by the compiler
* assuming one read takes 200 cycles and A8 is runing 1 GHz
* somewhat conservative setting
*/
for (i = 0; i < 50*d; i++)
readl(CONTROL_STATUS);
}
static void main_pll_init_ti816x(void)
{
u32 main_pll_ctrl = 0;
/* Put the PLL in bypass mode by setting BIT2 in its ctrl reg */
main_pll_ctrl = readl(&cmpll->mainpll_ctrl);
main_pll_ctrl &= 0xFFFFFFFB;
main_pll_ctrl |= BIT(2);
writel(main_pll_ctrl, &cmpll->mainpll_ctrl);
/* Enable PLL by setting BIT3 in its ctrl reg */
main_pll_ctrl = readl(&cmpll->mainpll_ctrl);
main_pll_ctrl &= 0xFFFFFFF7;
main_pll_ctrl |= BIT(3);
writel(main_pll_ctrl, &cmpll->mainpll_ctrl);
/* Write the values of N,P in the CTRL reg */
main_pll_ctrl = readl(&cmpll->mainpll_ctrl);
main_pll_ctrl &= 0xFF;
main_pll_ctrl |= (MAIN_N<<16 | MAIN_P<<8);
writel(main_pll_ctrl, &cmpll->mainpll_ctrl);
/* Power up clock1-7 */
writel(0x0, &cmpll->mainpll_pwd);
/* Program the freq and divider values for clock1-7 */
writel((1<<31 | 1<<28 | (MAIN_INTFREQ1<<24) | MAIN_FRACFREQ1),
&cmpll->mainpll_freq1);
writel(((1<<8) | MAIN_MDIV1), &cmpll->mainpll_div1);
writel((1<<31 | 1<<28 | (MAIN_INTFREQ2<<24) | MAIN_FRACFREQ2),
&cmpll->mainpll_freq2);
writel(((1<<8) | MAIN_MDIV2), &cmpll->mainpll_div2);
writel((1<<31 | 1<<28 | (MAIN_INTFREQ3<<24) | MAIN_FRACFREQ3),
&cmpll->mainpll_freq3);
writel(((1<<8) | MAIN_MDIV3), &cmpll->mainpll_div3);
writel((1<<31 | 1<<28 | (MAIN_INTFREQ4<<24) | MAIN_FRACFREQ4),
&cmpll->mainpll_freq4);
writel(((1<<8) | MAIN_MDIV4), &cmpll->mainpll_div4);
writel((1<<31 | 1<<28 | (MAIN_INTFREQ5<<24) | MAIN_FRACFREQ5),
&cmpll->mainpll_freq5);
writel(((1<<8) | MAIN_MDIV5), &cmpll->mainpll_div5);
writel((1<<8 | MAIN_MDIV6), &cmpll->mainpll_div6);
writel((1<<8 | MAIN_MDIV7), &cmpll->mainpll_div7);
/* Wait for PLL to lock */
while ((readl(&cmpll->mainpll_ctrl) & BIT(7)) != BIT(7))
;
/* Put the PLL in normal mode, disable bypass */
main_pll_ctrl = readl(&cmpll->mainpll_ctrl);
main_pll_ctrl &= 0xFFFFFFFB;
writel(main_pll_ctrl, &cmpll->mainpll_ctrl);
}
static void ddr_pll_bypass_ti816x(void)
{
u32 ddr_pll_ctrl = 0;
/* Put the PLL in bypass mode by setting BIT2 in its ctrl reg */
ddr_pll_ctrl = readl(&cmpll->ddrpll_ctrl);
ddr_pll_ctrl &= 0xFFFFFFFB;
ddr_pll_ctrl |= BIT(2);
writel(ddr_pll_ctrl, &cmpll->ddrpll_ctrl);
}
static void ddr_pll_init_ti816x(void)
{
u32 ddr_pll_ctrl = 0;
/* Enable PLL by setting BIT3 in its ctrl reg */
ddr_pll_ctrl = readl(&cmpll->ddrpll_ctrl);
ddr_pll_ctrl &= 0xFFFFFFF7;
ddr_pll_ctrl |= BIT(3);
writel(ddr_pll_ctrl, &cmpll->ddrpll_ctrl);
/* Write the values of N,P in the CTRL reg */
ddr_pll_ctrl = readl(&cmpll->ddrpll_ctrl);
ddr_pll_ctrl &= 0xFF;
ddr_pll_ctrl |= (DDR_N<<16 | DDR_P<<8);
writel(ddr_pll_ctrl, &cmpll->ddrpll_ctrl);
ddr_delay(10);
/* Power up clock1-5 */
writel(0x0, &cmpll->ddrpll_pwd);
/* Program the freq and divider values for clock1-3 */
writel(((0<<8) | DDR_MDIV1), &cmpll->ddrpll_div1);
ddr_delay(1);
writel(((1<<8) | DDR_MDIV1), &cmpll->ddrpll_div1);
writel((1<<31 | 1<<28 | (DDR_INTFREQ2<<24) | DDR_FRACFREQ2),
&cmpll->ddrpll_freq2);
writel(((1<<8) | DDR_MDIV2), &cmpll->ddrpll_div2);
writel(((0<<8) | DDR_MDIV3), &cmpll->ddrpll_div3);
ddr_delay(1);
writel(((1<<8) | DDR_MDIV3), &cmpll->ddrpll_div3);
ddr_delay(1);
writel((0<<31 | 1<<28 | (DDR_INTFREQ3<<24) | DDR_FRACFREQ3),
&cmpll->ddrpll_freq3);
ddr_delay(1);
writel((1<<31 | 1<<28 | (DDR_INTFREQ3<<24) | DDR_FRACFREQ3),
&cmpll->ddrpll_freq3);
ddr_delay(5);
/* Wait for PLL to lock */
while ((readl(&cmpll->ddrpll_ctrl) & BIT(7)) != BIT(7))
;
/* Power up RCD */
writel(BIT(0), DDR_RCD);
}
static void peripheral_enable(void)
{
/* Wake-up the l3_slow clock */
writel(PRCM_MOD_EN, &cmalwon->l3slowclkstctrl);
/*
* Note on Timers:
* There are 8 timers(0-7) out of which timer 0 is a secure timer.
* Timer 0 mux should not be changed
*
* To access the timer registers we need the to be
* enabled which is what we do in the first step
*/
/* Enable timer1 */
writel(PRCM_MOD_EN, &cmalwon->timer1clkctrl);
/* Select timer1 clock to be CLKIN (27MHz) */
writel(BIT(1), CM_TIMER1_CLKSEL);
/* Wait for timer1 to be ON-ACTIVE */
while (((readl(&cmalwon->l3slowclkstctrl)
& (0x80000<<1))>>20) != 1)
;
/* Wait for timer1 to be enabled */
while (((readl(&cmalwon->timer1clkctrl) & 0x30000)>>16) != 0)
;
/* Active posted mode */
writel(PRCM_MOD_EN, (DM_TIMER1_BASE + 0x54));
while (readl(DM_TIMER1_BASE + 0x10) & BIT(0))
;
/* Start timer1 */
writel(BIT(0), (DM_TIMER1_BASE + 0x38));
/* eFuse */
writel(PRCM_MOD_EN, CM_ALWON_CUST_EFUSE_CLKCTRL);
while (readl(CM_ALWON_CUST_EFUSE_CLKCTRL) != PRCM_MOD_EN)
;
/* Enable gpio0 */
writel(PRCM_MOD_EN, &cmalwon->gpio0clkctrl);
while (readl(&cmalwon->gpio0clkctrl) != PRCM_MOD_EN)
;
writel((BIT(1) | BIT(8)), &cmalwon->gpio0clkctrl);
/* Enable gpio1 */
writel(PRCM_MOD_EN, &cmalwon->gpio1clkctrl);
while (readl(&cmalwon->gpio1clkctrl) != PRCM_MOD_EN)
;
writel((BIT(1) | BIT(8)), &cmalwon->gpio1clkctrl);
/* Enable spi */
writel(PRCM_MOD_EN, &cmalwon->spiclkctrl);
while (readl(&cmalwon->spiclkctrl) != PRCM_MOD_EN)
;
/* Enable i2c0 */
writel(PRCM_MOD_EN, &cmalwon->i2c0clkctrl);
while (readl(&cmalwon->i2c0clkctrl) != PRCM_MOD_EN)
;
/* Enable ethernet0 */
writel(PRCM_MOD_EN, &cmalwon->ethclkstctrl);
writel(PRCM_MOD_EN, &cmalwon->ethernet0clkctrl);
writel(PRCM_MOD_EN, &cmalwon->ethernet1clkctrl);
/* Enable hsmmc */
writel(PRCM_MOD_EN, &cmalwon->sdioclkctrl);
while (readl(&cmalwon->sdioclkctrl) != PRCM_MOD_EN)
;
}
void setup_clocks_for_console(void)
{
/* Fix ROM code bug - from TI-PSP-04.00.02.14 */
writel(0x0, CM_SYSCLK10_CLKSEL);
ddr_pll_bypass_ti816x();
/* Enable uart0-2 */
writel(PRCM_MOD_EN, &cmalwon->uart0clkctrl);
while (readl(&cmalwon->uart0clkctrl) != PRCM_MOD_EN)
;
writel(PRCM_MOD_EN, &cmalwon->uart1clkctrl);
while (readl(&cmalwon->uart1clkctrl) != PRCM_MOD_EN)
;
writel(PRCM_MOD_EN, &cmalwon->uart2clkctrl);
while (readl(&cmalwon->uart2clkctrl) != PRCM_MOD_EN)
;
while ((readl(&cmalwon->l3slowclkstctrl) & 0x2100) != 0x2100)
;
}
void setup_early_clocks(void)
{
setup_clocks_for_console();
}
void prcm_init(void)
{
/* Enable the control */
writel(PRCM_MOD_EN, &cmalwon->controlclkctrl);
main_pll_init_ti816x();
ddr_pll_init_ti816x();
/*
* With clk freqs setup to desired values,
* enable the required peripherals
*/
peripheral_enable();
}
@@ -0,0 +1,414 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* DDR Configuration for AM33xx devices.
*
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
*/
#include <asm/arch/cpu.h>
#include <asm/arch/ddr_defs.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
#include <asm/emif.h>
/**
* Base address for EMIF instances
*/
static struct emif_reg_struct *emif_reg[2] = {
(struct emif_reg_struct *)EMIF4_0_CFG_BASE,
(struct emif_reg_struct *)EMIF4_1_CFG_BASE};
/**
* Base addresses for DDR PHY cmd/data regs
*/
static struct ddr_cmd_regs *ddr_cmd_reg[2] = {
(struct ddr_cmd_regs *)DDR_PHY_CMD_ADDR,
(struct ddr_cmd_regs *)DDR_PHY_CMD_ADDR2};
static struct ddr_data_regs *ddr_data_reg[2] = {
(struct ddr_data_regs *)DDR_PHY_DATA_ADDR,
(struct ddr_data_regs *)DDR_PHY_DATA_ADDR2};
/**
* Base address for ddr io control instances
*/
static struct ddr_cmdtctrl *ioctrl_reg = {
(struct ddr_cmdtctrl *)DDR_CONTROL_BASE_ADDR};
static inline u32 get_mr(int nr, u32 cs, u32 mr_addr)
{
u32 mr;
mr_addr |= cs << EMIF_REG_CS_SHIFT;
writel(mr_addr, &emif_reg[nr]->emif_lpddr2_mode_reg_cfg);
mr = readl(&emif_reg[nr]->emif_lpddr2_mode_reg_data);
debug("get_mr: EMIF1 cs %d mr %08x val 0x%x\n", cs, mr_addr, mr);
if (((mr & 0x0000ff00) >> 8) == (mr & 0xff) &&
((mr & 0x00ff0000) >> 16) == (mr & 0xff) &&
((mr & 0xff000000) >> 24) == (mr & 0xff))
return mr & 0xff;
else
return mr;
}
static inline void set_mr(int nr, u32 cs, u32 mr_addr, u32 mr_val)
{
mr_addr |= cs << EMIF_REG_CS_SHIFT;
writel(mr_addr, &emif_reg[nr]->emif_lpddr2_mode_reg_cfg);
writel(mr_val, &emif_reg[nr]->emif_lpddr2_mode_reg_data);
}
static void configure_mr(int nr, u32 cs)
{
u32 mr_addr;
while (get_mr(nr, cs, LPDDR2_MR0) & LPDDR2_MR0_DAI_MASK)
;
set_mr(nr, cs, LPDDR2_MR10, 0x56);
set_mr(nr, cs, LPDDR2_MR1, 0x43);
set_mr(nr, cs, LPDDR2_MR2, 0x2);
mr_addr = LPDDR2_MR2 | EMIF_REG_REFRESH_EN_MASK;
set_mr(nr, cs, mr_addr, 0x2);
}
/*
* Configure EMIF4D5 registers and MR registers For details about these magic
* values please see the EMIF registers section of the TRM.
*/
void config_sdram_emif4d5(const struct emif_regs *regs, int nr)
{
#ifdef CONFIG_AM43XX
struct prm_device_inst *prm_device =
(struct prm_device_inst *)PRM_DEVICE_INST;
#endif
writel(0xA0, &emif_reg[nr]->emif_pwr_mgmt_ctrl);
writel(0xA0, &emif_reg[nr]->emif_pwr_mgmt_ctrl_shdw);
writel(regs->zq_config, &emif_reg[nr]->emif_zq_config);
writel(regs->temp_alert_config, &emif_reg[nr]->emif_temp_alert_config);
writel(regs->emif_rd_wr_lvl_rmp_win,
&emif_reg[nr]->emif_rd_wr_lvl_rmp_win);
writel(regs->emif_rd_wr_lvl_rmp_ctl,
&emif_reg[nr]->emif_rd_wr_lvl_rmp_ctl);
writel(regs->emif_rd_wr_lvl_ctl, &emif_reg[nr]->emif_rd_wr_lvl_ctl);
writel(regs->emif_rd_wr_exec_thresh,
&emif_reg[nr]->emif_rd_wr_exec_thresh);
/*
* for most SOCs these registers won't need to be changed so only
* write to these registers if someone explicitly has set the
* register's value.
*/
if(regs->emif_cos_config) {
writel(regs->emif_prio_class_serv_map, &emif_reg[nr]->emif_prio_class_serv_map);
writel(regs->emif_connect_id_serv_1_map, &emif_reg[nr]->emif_connect_id_serv_1_map);
writel(regs->emif_connect_id_serv_2_map, &emif_reg[nr]->emif_connect_id_serv_2_map);
writel(regs->emif_cos_config, &emif_reg[nr]->emif_cos_config);
}
/*
* Sequence to ensure that the PHY is in a known state prior to
* startting hardware leveling. Also acts as to latch some state from
* the EMIF into the PHY.
*/
writel(0x2011, &emif_reg[nr]->emif_iodft_tlgc);
writel(0x2411, &emif_reg[nr]->emif_iodft_tlgc);
writel(0x2011, &emif_reg[nr]->emif_iodft_tlgc);
clrbits_le32(&emif_reg[nr]->emif_sdram_ref_ctrl,
EMIF_REG_INITREF_DIS_MASK);
writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config);
writel(regs->sdram_config, &cstat->secure_emif_sdram_config);
/* Wait 1ms because of L3 timeout error */
udelay(1000);
writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl);
writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw);
#ifdef CONFIG_AM43XX
/*
* Disable EMIF_DEVOFF
* -> Cold Boot: This is just rewriting the default register value.
* -> RTC Resume: Must disable DEVOFF before leveling.
*/
writel(0, &prm_device->emif_ctrl);
#endif
/* Perform hardware leveling for DDR3 */
if (emif_sdram_type(regs->sdram_config) == EMIF_SDRAM_TYPE_DDR3) {
writel(readl(&emif_reg[nr]->emif_ddr_ext_phy_ctrl_36) |
0x100, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36);
writel(readl(&emif_reg[nr]->emif_ddr_ext_phy_ctrl_36_shdw) |
0x100, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36_shdw);
writel(0x80000000, &emif_reg[nr]->emif_rd_wr_lvl_rmp_ctl);
/* Enable read leveling */
writel(0x80000000, &emif_reg[nr]->emif_rd_wr_lvl_ctl);
/* Wait 1ms because of L3 timeout error */
udelay(1000);
/*
* Enable full read and write leveling. Wait for read and write
* leveling bit to clear RDWRLVLFULL_START bit 31
*/
while ((readl(&emif_reg[nr]->emif_rd_wr_lvl_ctl) & 0x80000000)
!= 0)
;
/* Check the timeout register to see if leveling is complete */
if ((readl(&emif_reg[nr]->emif_status) & 0x70) != 0)
puts("DDR3 H/W leveling incomplete with errors\n");
} else {
/* DDR2 */
configure_mr(nr, 0);
configure_mr(nr, 1);
}
}
/**
* Configure SDRAM
*/
void config_sdram(const struct emif_regs *regs, int nr)
{
#ifdef CONFIG_TI816X
writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config);
writel(regs->emif_ddr_phy_ctlr_1, &emif_reg[nr]->emif_ddr_phy_ctrl_1);
writel(regs->emif_ddr_phy_ctlr_1, &emif_reg[nr]->emif_ddr_phy_ctrl_1_shdw);
writel(0x0000613B, &emif_reg[nr]->emif_sdram_ref_ctrl); /* initially a large refresh period */
writel(0x1000613B, &emif_reg[nr]->emif_sdram_ref_ctrl); /* trigger initialization */
writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl);
#else
if (regs->zq_config) {
writel(regs->zq_config, &emif_reg[nr]->emif_zq_config);
writel(regs->sdram_config, &cstat->secure_emif_sdram_config);
writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config);
/* Trigger initialization */
writel(0x00003100, &emif_reg[nr]->emif_sdram_ref_ctrl);
/* Wait 1ms because of L3 timeout error */
udelay(1000);
/* Write proper sdram_ref_cref_ctrl value */
writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl);
writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw);
}
writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl);
writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw);
writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config);
/* Write REG_COS_COUNT_1, REG_COS_COUNT_2, and REG_PR_OLD_COUNT. */
if (regs->ocp_config)
writel(regs->ocp_config, &emif_reg[nr]->emif_l3_config);
#endif
}
/**
* Set SDRAM timings
*/
void set_sdram_timings(const struct emif_regs *regs, int nr)
{
writel(regs->sdram_tim1, &emif_reg[nr]->emif_sdram_tim_1);
writel(regs->sdram_tim1, &emif_reg[nr]->emif_sdram_tim_1_shdw);
writel(regs->sdram_tim2, &emif_reg[nr]->emif_sdram_tim_2);
writel(regs->sdram_tim2, &emif_reg[nr]->emif_sdram_tim_2_shdw);
writel(regs->sdram_tim3, &emif_reg[nr]->emif_sdram_tim_3);
writel(regs->sdram_tim3, &emif_reg[nr]->emif_sdram_tim_3_shdw);
}
/*
* Configure EXT PHY registers for software leveling
*/
static void ext_phy_settings_swlvl(const struct emif_regs *regs, int nr)
{
u32 *ext_phy_ctrl_base = 0;
u32 *emif_ext_phy_ctrl_base = 0;
__maybe_unused const u32 *ext_phy_ctrl_const_regs;
u32 i = 0;
__maybe_unused u32 size;
ext_phy_ctrl_base = (u32 *)&(regs->emif_ddr_ext_phy_ctrl_1);
emif_ext_phy_ctrl_base =
(u32 *)&(emif_reg[nr]->emif_ddr_ext_phy_ctrl_1);
/* Configure external phy control timing registers */
for (i = 0; i < EMIF_EXT_PHY_CTRL_TIMING_REG; i++) {
writel(*ext_phy_ctrl_base, emif_ext_phy_ctrl_base++);
/* Update shadow registers */
writel(*ext_phy_ctrl_base++, emif_ext_phy_ctrl_base++);
}
#ifdef CONFIG_AM43XX
/*
* External phy 6-24 registers do not change with ddr frequency.
* These only need to be set on DDR2 on AM43xx.
*/
emif_get_ext_phy_ctrl_const_regs(&ext_phy_ctrl_const_regs, &size);
if (!size)
return;
for (i = 0; i < size; i++) {
writel(ext_phy_ctrl_const_regs[i], emif_ext_phy_ctrl_base++);
/* Update shadow registers */
writel(ext_phy_ctrl_const_regs[i], emif_ext_phy_ctrl_base++);
}
#endif
}
/*
* Configure EXT PHY registers for hardware leveling
*/
static void ext_phy_settings_hwlvl(const struct emif_regs *regs, int nr)
{
/*
* Enable hardware leveling on the EMIF. For details about these
* magic values please see the EMIF registers section of the TRM.
*/
if (regs->emif_ddr_phy_ctlr_1 & 0x00040000) {
/* PHY_INVERT_CLKOUT = 1 */
writel(0x00040100, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_1);
writel(0x00040100, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_1_shdw);
} else {
/* PHY_INVERT_CLKOUT = 0 */
writel(0x08020080, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_1);
writel(0x08020080, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_1_shdw);
}
writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_22);
writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_22_shdw);
writel(0x00600020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_23);
writel(0x00600020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_23_shdw);
writel(0x40010080, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_24);
writel(0x40010080, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_24_shdw);
writel(0x08102040, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_25);
writel(0x08102040, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_25_shdw);
writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_26);
writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_26_shdw);
writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_27);
writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_27_shdw);
writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_28);
writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_28_shdw);
writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_29);
writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_29_shdw);
writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_30);
writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_30_shdw);
writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_31);
writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_31_shdw);
writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_32);
writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_32_shdw);
writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_33);
writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_33_shdw);
writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_34);
writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_34_shdw);
writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_35);
writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_35_shdw);
writel(0x00000077, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36);
writel(0x00000077, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36_shdw);
/*
* Sequence to ensure that the PHY is again in a known state after
* hardware leveling.
*/
writel(0x2011, &emif_reg[nr]->emif_iodft_tlgc);
writel(0x2411, &emif_reg[nr]->emif_iodft_tlgc);
writel(0x2011, &emif_reg[nr]->emif_iodft_tlgc);
}
/**
* Configure DDR PHY
*/
void config_ddr_phy(const struct emif_regs *regs, int nr)
{
/*
* Disable initialization and refreshes for now until we finish
* programming EMIF regs and set time between rising edge of
* DDR_RESET to rising edge of DDR_CKE to > 500us per memory spec.
* We currently hardcode a value based on a max expected frequency
* of 400MHz.
*/
writel(EMIF_REG_INITREF_DIS_MASK | 0x3100,
&emif_reg[nr]->emif_sdram_ref_ctrl);
writel(regs->emif_ddr_phy_ctlr_1,
&emif_reg[nr]->emif_ddr_phy_ctrl_1);
writel(regs->emif_ddr_phy_ctlr_1,
&emif_reg[nr]->emif_ddr_phy_ctrl_1_shdw);
if (get_emif_rev((u32)emif_reg[nr]) == EMIF_4D5) {
if (emif_sdram_type(regs->sdram_config) == EMIF_SDRAM_TYPE_DDR3)
ext_phy_settings_hwlvl(regs, nr);
else
ext_phy_settings_swlvl(regs, nr);
}
}
/**
* Configure DDR CMD control registers
*/
void config_cmd_ctrl(const struct cmd_control *cmd, int nr)
{
if (!cmd)
return;
writel(cmd->cmd0csratio, &ddr_cmd_reg[nr]->cm0csratio);
writel(cmd->cmd0iclkout, &ddr_cmd_reg[nr]->cm0iclkout);
writel(cmd->cmd1csratio, &ddr_cmd_reg[nr]->cm1csratio);
writel(cmd->cmd1iclkout, &ddr_cmd_reg[nr]->cm1iclkout);
writel(cmd->cmd2csratio, &ddr_cmd_reg[nr]->cm2csratio);
writel(cmd->cmd2iclkout, &ddr_cmd_reg[nr]->cm2iclkout);
}
/**
* Configure DDR DATA registers
*/
void config_ddr_data(const struct ddr_data *data, int nr)
{
int i;
if (!data)
return;
for (i = 0; i < DDR_DATA_REGS_NR; i++) {
writel(data->datardsratio0,
&(ddr_data_reg[nr]+i)->dt0rdsratio0);
writel(data->datawdsratio0,
&(ddr_data_reg[nr]+i)->dt0wdsratio0);
writel(data->datawiratio0,
&(ddr_data_reg[nr]+i)->dt0wiratio0);
writel(data->datagiratio0,
&(ddr_data_reg[nr]+i)->dt0giratio0);
writel(data->datafwsratio0,
&(ddr_data_reg[nr]+i)->dt0fwsratio0);
writel(data->datawrsratio0,
&(ddr_data_reg[nr]+i)->dt0wrsratio0);
}
}
void config_io_ctrl(const struct ctrl_ioregs *ioregs)
{
if (!ioregs)
return;
writel(ioregs->cm0ioctl, &ioctrl_reg->cm0ioctl);
writel(ioregs->cm1ioctl, &ioctrl_reg->cm1ioctl);
writel(ioregs->cm2ioctl, &ioctrl_reg->cm2ioctl);
writel(ioregs->dt0ioctl, &ioctrl_reg->dt0ioctl);
writel(ioregs->dt1ioctl, &ioctrl_reg->dt1ioctl);
#ifdef CONFIG_AM43XX
writel(ioregs->dt2ioctrl, &ioctrl_reg->dt2ioctrl);
writel(ioregs->dt3ioctrl, &ioctrl_reg->dt3ioctrl);
writel(ioregs->emif_sdram_config_ext,
&ioctrl_reg->emif_sdram_config_ext);
#endif
}
@@ -0,0 +1,113 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* emif4.c
*
* AM33XX emif4 configuration file
*
* Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
*/
#include <common.h>
#include <asm/arch/cpu.h>
#include <asm/arch/ddr_defs.h>
#include <asm/arch/hardware.h>
#include <asm/arch/clock.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
#include <asm/emif.h>
static struct vtp_reg *vtpreg[2] = {
(struct vtp_reg *)VTP0_CTRL_ADDR,
(struct vtp_reg *)VTP1_CTRL_ADDR};
#ifdef CONFIG_AM33XX
static struct ddr_ctrl *ddrctrl = (struct ddr_ctrl *)DDR_CTRL_ADDR;
#endif
#ifdef CONFIG_AM43XX
static struct ddr_ctrl *ddrctrl = (struct ddr_ctrl *)DDR_CTRL_ADDR;
static struct cm_device_inst *cm_device =
(struct cm_device_inst *)CM_DEVICE_INST;
#endif
#ifdef CONFIG_TI814X
void config_dmm(const struct dmm_lisa_map_regs *regs)
{
struct dmm_lisa_map_regs *hw_lisa_map_regs =
(struct dmm_lisa_map_regs *)DMM_BASE;
enable_dmm_clocks();
writel(0, &hw_lisa_map_regs->dmm_lisa_map_3);
writel(0, &hw_lisa_map_regs->dmm_lisa_map_2);
writel(0, &hw_lisa_map_regs->dmm_lisa_map_1);
writel(0, &hw_lisa_map_regs->dmm_lisa_map_0);
writel(regs->dmm_lisa_map_3, &hw_lisa_map_regs->dmm_lisa_map_3);
writel(regs->dmm_lisa_map_2, &hw_lisa_map_regs->dmm_lisa_map_2);
writel(regs->dmm_lisa_map_1, &hw_lisa_map_regs->dmm_lisa_map_1);
writel(regs->dmm_lisa_map_0, &hw_lisa_map_regs->dmm_lisa_map_0);
}
#endif
static void config_vtp(int nr)
{
writel(readl(&vtpreg[nr]->vtp0ctrlreg) | VTP_CTRL_ENABLE,
&vtpreg[nr]->vtp0ctrlreg);
writel(readl(&vtpreg[nr]->vtp0ctrlreg) & (~VTP_CTRL_START_EN),
&vtpreg[nr]->vtp0ctrlreg);
writel(readl(&vtpreg[nr]->vtp0ctrlreg) | VTP_CTRL_START_EN,
&vtpreg[nr]->vtp0ctrlreg);
/* Poll for READY */
while ((readl(&vtpreg[nr]->vtp0ctrlreg) & VTP_CTRL_READY) !=
VTP_CTRL_READY)
;
}
void __weak ddr_pll_config(unsigned int ddrpll_m)
{
}
void config_ddr(unsigned int pll, const struct ctrl_ioregs *ioregs,
const struct ddr_data *data, const struct cmd_control *ctrl,
const struct emif_regs *regs, int nr)
{
ddr_pll_config(pll);
config_vtp(nr);
config_cmd_ctrl(ctrl, nr);
config_ddr_data(data, nr);
#ifdef CONFIG_AM33XX
config_io_ctrl(ioregs);
/* Set CKE to be controlled by EMIF/DDR PHY */
writel(DDR_CKE_CTRL_NORMAL, &ddrctrl->ddrckectrl);
#endif
#ifdef CONFIG_AM43XX
writel(readl(&cm_device->cm_dll_ctrl) & ~0x1, &cm_device->cm_dll_ctrl);
while ((readl(&cm_device->cm_dll_ctrl) & CM_DLL_READYST) == 0)
;
config_io_ctrl(ioregs);
/* Set CKE to be controlled by EMIF/DDR PHY */
writel(DDR_CKE_CTRL_NORMAL, &ddrctrl->ddrckectrl);
if (emif_sdram_type(regs->sdram_config) == EMIF_SDRAM_TYPE_DDR3)
#ifndef CONFIG_SPL_RTC_DDR_SUPPORT
/* Allow EMIF to control DDR_RESET */
writel(0x00000000, &ddrctrl->ddrioctrl);
#else
/* Override EMIF DDR_RESET control */
writel(0x80000000, &ddrctrl->ddrioctrl);
#endif /* CONFIG_SPL_RTC_DDR_SUPPORT */
#endif
/* Program EMIF instance */
config_ddr_phy(regs, nr);
set_sdram_timings(regs, nr);
if (get_emif_rev(EMIF1_BASE) == EMIF_4D5)
config_sdram_emif4d5(regs, nr);
else
config_sdram(regs, nr);
}
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2017 Texas Instruments, Inc.
*/
#include <common.h>
#include <linux/libfdt.h>
#include <fdt_support.h>
#include <malloc.h>
#include <asm/omap_common.h>
#include <asm/arch-am33xx/sys_proto.h>
#ifdef CONFIG_TI_SECURE_DEVICE
static void ft_hs_fixups(void *fdt, bd_t *bd)
{
/* Check we are running on an HS/EMU device type */
if (GP_DEVICE != get_device_type()) {
if ((ft_hs_disable_rng(fdt, bd) == 0) &&
(ft_hs_fixup_dram(fdt, bd) == 0) &&
(ft_hs_add_tee(fdt, bd) == 0))
return;
} else {
printf("ERROR: Incorrect device type (GP) detected!");
}
/* Fixup failed or wrong device type */
hang();
}
#else
static void ft_hs_fixups(void *fdt, bd_t *bd) { }
#endif /* #ifdef CONFIG_TI_SECURE_DEVICE */
/*
* Place for general cpu/SoC FDT fixups. Board specific
* fixups should remain in the board files which is where
* this function should be called from.
*/
void ft_cpu_setup(void *fdt, bd_t *bd)
{
ft_hs_fixups(fdt, bd);
}
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* HW data initialization for AM33xx.
*
* (C) Copyright 2017 Linaro Ltd.
* Sam Protsenko <semen.protsenko@linaro.org>
*/
#include <asm/arch/omap.h>
#include <asm/omap_common.h>
struct omap_sys_ctrl_regs const **ctrl =
(struct omap_sys_ctrl_regs const **)OMAP_SRAM_SCRATCH_SYS_CTRL;
void hw_data_init(void)
{
*ctrl = &am33xx_ctrl;
}
@@ -0,0 +1,47 @@
/*
* mux.c
*
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <common.h>
#include <asm/arch/mux.h>
#include <asm/arch/hardware.h>
#include <asm/io.h>
/*
* Configure the pin mux for the module
*/
void configure_module_pin_mux(struct module_pin_mux *mod_pin_mux)
{
int i;
if (!mod_pin_mux)
return;
for (i = 0; mod_pin_mux[i].reg_offset != -1; i++)
MUX_CFG(mod_pin_mux[i].val, mod_pin_mux[i].reg_offset);
}
/*
* provide a default over-writable definition
*/
void __weak set_uart_mux_conf(void)
{
}
/*
* provide a default over-writable definition
*/
void __weak set_mux_conf_regs(void)
{
}
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* HW regs data for AM33xx.
*
* (C) Copyright 2017 Linaro Ltd.
* Sam Protsenko <semen.protsenko@linaro.org>
*/
#include <asm/arch/hardware.h>
#include <asm/omap_common.h>
struct omap_sys_ctrl_regs const am33xx_ctrl = {
.control_status = CTRL_BASE + 0x40,
};
@@ -0,0 +1,214 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* sys_info.c
*
* System information functions
*
* Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
*
* Derived from Beagle Board and 3430 SDP code by
* Richard Woodruff <r-woodruff2@ti.com>
* Syed Mohammed Khasim <khasim@ti.com>
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/cpu.h>
#include <asm/arch/clock.h>
#include <power/tps65910.h>
#include <linux/compiler.h>
struct ctrl_stat *cstat = (struct ctrl_stat *)CTRL_BASE;
/**
* get_cpu_rev(void) - extract rev info
*/
u32 get_cpu_rev(void)
{
u32 id;
u32 rev;
id = readl(DEVICE_ID);
rev = (id >> 28) & 0xff;
return rev;
}
/**
* get_cpu_type(void) - extract cpu info
*/
u32 get_cpu_type(void)
{
u32 id = 0;
u32 partnum;
id = readl(DEVICE_ID);
partnum = (id >> 12) & 0xffff;
return partnum;
}
/**
* get_sysboot_value(void) - return SYS_BOOT[4:0]
*/
u32 get_sysboot_value(void)
{
return readl(&cstat->statusreg) & SYSBOOT_MASK;
}
u32 get_sys_clk_index(void)
{
struct ctrl_stat *ctrl = (struct ctrl_stat *)CTRL_BASE;
u32 ind = readl(&ctrl->statusreg);
#ifdef CONFIG_AM43XX
u32 src;
src = (ind & CTRL_CRYSTAL_FREQ_SRC_MASK) >> CTRL_CRYSTAL_FREQ_SRC_SHIFT;
if (src == CTRL_CRYSTAL_FREQ_SRC_EFUSE) /* Value read from EFUSE */
return ((ind & CTRL_CRYSTAL_FREQ_SELECTION_MASK) >>
CTRL_CRYSTAL_FREQ_SELECTION_SHIFT);
else /* Value read from SYS BOOT pins */
#endif
return ((ind & CTRL_SYSBOOT_15_14_MASK) >>
CTRL_SYSBOOT_15_14_SHIFT);
}
#ifdef CONFIG_DISPLAY_CPUINFO
static char *cpu_revs[] = {
"1.0",
"2.0",
"2.1"};
static char *cpu_revs_am43xx[] = {
"1.0",
"1.1",
"1.2"};
static char *dev_types[] = {
"TST",
"EMU",
"HS",
"GP"};
/**
* Print CPU information
*/
int print_cpuinfo(void)
{
char *cpu_s, *sec_s, *rev_s;
char **cpu_rev_arr = cpu_revs;
switch (get_cpu_type()) {
case AM335X:
cpu_s = "AM335X";
break;
case TI81XX:
cpu_s = "TI81XX";
break;
case AM437X:
cpu_s = "AM437X";
cpu_rev_arr = cpu_revs_am43xx;
break;
default:
cpu_s = "Unknown CPU type";
break;
}
if (get_cpu_rev() < ARRAY_SIZE(cpu_revs))
rev_s = cpu_rev_arr[get_cpu_rev()];
else
rev_s = "?";
if (get_device_type() < ARRAY_SIZE(dev_types))
sec_s = dev_types[get_device_type()];
else
sec_s = "?";
printf("CPU : %s-%s rev %s\n", cpu_s, sec_s, rev_s);
return 0;
}
#endif /* CONFIG_DISPLAY_CPUINFO */
#ifdef CONFIG_AM33XX
int am335x_get_efuse_mpu_max_freq(struct ctrl_dev *cdev)
{
int sil_rev;
sil_rev = readl(&cdev->deviceid) >> 28;
if (sil_rev == 0) {
/* No efuse in PG 1.0. Use max speed */
return MPUPLL_M_720;
} else if (sil_rev >= 1) {
/* Check what the efuse says our max speed is. */
int efuse_arm_mpu_max_freq, package_type;
efuse_arm_mpu_max_freq = readl(&cdev->efuse_sma);
package_type = (efuse_arm_mpu_max_freq & PACKAGE_TYPE_MASK) >>
PACKAGE_TYPE_SHIFT;
/* PG 2.0, efuse may not be set. */
if (package_type == PACKAGE_TYPE_UNDEFINED || package_type ==
PACKAGE_TYPE_RESERVED)
return MPUPLL_M_800;
switch ((efuse_arm_mpu_max_freq & DEVICE_ID_MASK)) {
case AM335X_ZCZ_1000:
return MPUPLL_M_1000;
case AM335X_ZCZ_800:
return MPUPLL_M_800;
case AM335X_ZCZ_720:
return MPUPLL_M_720;
case AM335X_ZCZ_600:
case AM335X_ZCE_600:
return MPUPLL_M_600;
case AM335X_ZCZ_300:
case AM335X_ZCE_300:
return MPUPLL_M_300;
}
}
/* unknown, use the PG1.0 max */
return MPUPLL_M_720;
}
int am335x_get_mpu_vdd(int sil_rev, int frequency)
{
int sel_mask = am335x_get_tps65910_mpu_vdd(sil_rev, frequency);
switch (sel_mask) {
case TPS65910_OP_REG_SEL_1_3_2_5:
return 1325000;
case TPS65910_OP_REG_SEL_1_2_0:
return 1200000;
case TPS65910_OP_REG_SEL_1_1_0:
return 1100000;
default:
return 1262500;
}
}
int am335x_get_tps65910_mpu_vdd(int sil_rev, int frequency)
{
/* For PG2.0 and later, we have one set of values. */
if (sil_rev >= 1) {
switch (frequency) {
case MPUPLL_M_1000:
return TPS65910_OP_REG_SEL_1_3_2_5;
case MPUPLL_M_800:
return TPS65910_OP_REG_SEL_1_2_6;
case MPUPLL_M_720:
return TPS65910_OP_REG_SEL_1_2_0;
case MPUPLL_M_600:
case MPUPLL_M_500:
case MPUPLL_M_300:
return TPS65910_OP_REG_SEL_1_1_0;
}
}
/* Default to PG1.0 values. */
return TPS65910_OP_REG_SEL_1_2_6;
}
#endif
@@ -0,0 +1,164 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* ti816x_emif4.c
*
* TI816x emif4 configuration file
*
* Copyright (C) 2017, Konsulko Group
*/
#include <common.h>
#include <asm/arch/cpu.h>
#include <asm/arch/ddr_defs.h>
#include <asm/arch/hardware.h>
#include <asm/arch/clock.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
#include <asm/emif.h>
/*********************************************************************
* Init DDR3 on TI816X EVM
*********************************************************************/
static void ddr_init_settings(const struct cmd_control *ctrl, int emif)
{
/*
* setup use_rank_delays to 1. This is only necessary when
* multiple ranks are in use. Though the EVM does not have
* multiple ranks, this is a good value to set.
*/
writel(1, DDRPHY_CONFIG_BASE + 0x134); // DATA0_REG_PHY_USE_RANK0_DELAYS
writel(1, DDRPHY_CONFIG_BASE + 0x1d8); // DATA1_REG_PHY_USE_RANK0_DELAYS
writel(1, DDRPHY_CONFIG_BASE + 0x27c); // DATA2_REG_PHY_USE_RANK0_DELAYS
writel(1, DDRPHY_CONFIG_BASE + 0x320); // DATA3_REG_PHY_USE_RANK0_DELAYS
config_cmd_ctrl(ctrl, emif);
/* for ddr3 this needs to be set to 1 */
writel(0x1, DDRPHY_CONFIG_BASE + 0x0F8); /* init mode */
writel(0x1, DDRPHY_CONFIG_BASE + 0x104);
writel(0x1, DDRPHY_CONFIG_BASE + 0x19C);
writel(0x1, DDRPHY_CONFIG_BASE + 0x1A8);
writel(0x1, DDRPHY_CONFIG_BASE + 0x240);
writel(0x1, DDRPHY_CONFIG_BASE + 0x24C);
writel(0x1, DDRPHY_CONFIG_BASE + 0x2E4);
writel(0x1, DDRPHY_CONFIG_BASE + 0x2F0);
/*
* This represents the initial value for the leveling process. The
* value is a ratio - so 0x100 represents one cycle. The real delay
* is determined through the leveling process.
*
* During the leveling process, 0x20 is subtracted from the value, so
* we have added that to the value we want to set. We also set the
* values such that byte3 completes leveling after byte2 and byte1
* after byte0.
*/
writel((0x20 << 10) | 0x20, DDRPHY_CONFIG_BASE + 0x0F0); /* data0 writelvl init ratio */
writel(0x0, DDRPHY_CONFIG_BASE + 0x0F4); /* */
writel((0x20 << 10) | 0x20, DDRPHY_CONFIG_BASE + 0x194); /* data1 writelvl init ratio */
writel(0x0, DDRPHY_CONFIG_BASE + 0x198); /* */
writel((0x20 << 10) | 0x20, DDRPHY_CONFIG_BASE + 0x238); /* data2 writelvl init ratio */
writel(0x0, DDRPHY_CONFIG_BASE + 0x23c); /* */
writel((0x20 << 10) | 0x20, DDRPHY_CONFIG_BASE + 0x2dc); /* data3 writelvl init ratio */
writel(0x0, DDRPHY_CONFIG_BASE + 0x2e0); /* */
writel((0x20 << 10) | 0x20, DDRPHY_CONFIG_BASE + 0x0FC); /* data0 gatelvl init ratio */
writel(0x0, DDRPHY_CONFIG_BASE + 0x100);
writel((0x20 << 10) | 0x20, DDRPHY_CONFIG_BASE + 0x1A0); /* data1 gatelvl init ratio */
writel(0x0, DDRPHY_CONFIG_BASE + 0x1A4);
writel((0x20 << 10) | 0x20, DDRPHY_CONFIG_BASE + 0x244); /* data2 gatelvl init ratio */
writel(0x0, DDRPHY_CONFIG_BASE + 0x248);
writel((0x20 << 10) | 0x20, DDRPHY_CONFIG_BASE + 0x2E8); /* data3 gatelvl init ratio */
writel(0x0, DDRPHY_CONFIG_BASE + 0x2EC);
writel(0x5, DDRPHY_CONFIG_BASE + 0x00C); /* cmd0 io config - output impedance of pad */
writel(0x5, DDRPHY_CONFIG_BASE + 0x010); /* cmd0 io clk config - output impedance of pad */
writel(0x5, DDRPHY_CONFIG_BASE + 0x040); /* cmd1 io config - output impedance of pad */
writel(0x5, DDRPHY_CONFIG_BASE + 0x044); /* cmd1 io clk config - output impedance of pad */
writel(0x5, DDRPHY_CONFIG_BASE + 0x074); /* cmd2 io config - output impedance of pad */
writel(0x5, DDRPHY_CONFIG_BASE + 0x078); /* cmd2 io clk config - output impedance of pad */
writel(0x4, DDRPHY_CONFIG_BASE + 0x0A8); /* data0 io config - output impedance of pad */
writel(0x4, DDRPHY_CONFIG_BASE + 0x0AC); /* data0 io clk config - output impedance of pad */
writel(0x4, DDRPHY_CONFIG_BASE + 0x14C); /* data1 io config - output impedance of pa */
writel(0x4, DDRPHY_CONFIG_BASE + 0x150); /* data1 io clk config - output impedance of pad */
writel(0x4, DDRPHY_CONFIG_BASE + 0x1F0); /* data2 io config - output impedance of pa */
writel(0x4, DDRPHY_CONFIG_BASE + 0x1F4); /* data2 io clk config - output impedance of pad */
writel(0x4, DDRPHY_CONFIG_BASE + 0x294); /* data3 io config - output impedance of pa */
writel(0x4, DDRPHY_CONFIG_BASE + 0x298); /* data3 io clk config - output impedance of pad */
}
static void ddr3_sw_levelling(const struct ddr_data *data, int emif)
{
/* Set the correct value to DDR_VTP_CTRL_0 */
writel(0x6, (DDRPHY_CONFIG_BASE + 0x358));
writel(data->datafwsratio0, (DDRPHY_CONFIG_BASE + 0x108));
writel(data->datafwsratio0, (DDRPHY_CONFIG_BASE + 0x1AC));
writel(data->datafwsratio0, (DDRPHY_CONFIG_BASE + 0x250));
writel(data->datafwsratio0, (DDRPHY_CONFIG_BASE + 0x2F4));
writel(data->datawdsratio0, (DDRPHY_CONFIG_BASE + 0x0DC));
writel(data->datawdsratio0, (DDRPHY_CONFIG_BASE + 0x180));
writel(data->datawdsratio0, (DDRPHY_CONFIG_BASE + 0x224));
writel(data->datawdsratio0, (DDRPHY_CONFIG_BASE + 0x2C8));
writel(data->datawrsratio0, (DDRPHY_CONFIG_BASE + 0x120));
writel(data->datawrsratio0, (DDRPHY_CONFIG_BASE + 0x1C4));
writel(data->datawrsratio0, (DDRPHY_CONFIG_BASE + 0x268));
writel(data->datawrsratio0, (DDRPHY_CONFIG_BASE + 0x30C));
writel(data->datardsratio0, (DDRPHY_CONFIG_BASE + 0x0C8));
writel(data->datardsratio0, (DDRPHY_CONFIG_BASE + 0x16C));
writel(data->datardsratio0, (DDRPHY_CONFIG_BASE + 0x210));
writel(data->datardsratio0, (DDRPHY_CONFIG_BASE + 0x2B4));
}
static struct dmm_lisa_map_regs *hw_lisa_map_regs =
(struct dmm_lisa_map_regs *)DMM_BASE;
#define DMM_PAT_BASE_ADDR (DMM_BASE + 0x420)
void config_dmm(const struct dmm_lisa_map_regs *regs)
{
writel(0, &hw_lisa_map_regs->dmm_lisa_map_3);
writel(0, &hw_lisa_map_regs->dmm_lisa_map_2);
writel(0, &hw_lisa_map_regs->dmm_lisa_map_1);
writel(0, &hw_lisa_map_regs->dmm_lisa_map_0);
writel(regs->dmm_lisa_map_3, &hw_lisa_map_regs->dmm_lisa_map_3);
writel(regs->dmm_lisa_map_2, &hw_lisa_map_regs->dmm_lisa_map_2);
writel(regs->dmm_lisa_map_1, &hw_lisa_map_regs->dmm_lisa_map_1);
writel(regs->dmm_lisa_map_0, &hw_lisa_map_regs->dmm_lisa_map_0);
/* Enable Tiled Access */
writel(0x80000000, DMM_PAT_BASE_ADDR);
}
void config_ddr(const struct ddr_data *data, const struct cmd_control *ctrl,
const struct emif_regs *regs,
const struct dmm_lisa_map_regs *lisa_regs, int nrs)
{
int i;
enable_emif_clocks();
for (i = 0; i < nrs; i++)
ddr_init_settings(ctrl, i);
enable_dmm_clocks();
/* Program the DMM to for non-interleaved configuration */
config_dmm(lisa_regs);
/* Program EMIF CFG Registers */
for (i = 0; i < nrs; i++) {
set_sdram_timings(regs, i);
config_sdram(regs, i);
}
udelay(1000);
for (i = 0; i < nrs; i++)
ddr3_sw_levelling(data, i);
udelay(50000); /* Some delay needed */
}