diff options
Diffstat (limited to 'arch/arm/mach-aspeed/ast-scu.c')
-rw-r--r-- | arch/arm/mach-aspeed/ast-scu.c | 498 |
1 files changed, 498 insertions, 0 deletions
diff --git a/arch/arm/mach-aspeed/ast-scu.c b/arch/arm/mach-aspeed/ast-scu.c new file mode 100644 index 0000000000..0cc0d67b5d --- /dev/null +++ b/arch/arm/mach-aspeed/ast-scu.c @@ -0,0 +1,498 @@ +/******************************************************************************* + * File Name : arch/arm/cpu/ast-common/ast-scu.c + * Author : Ryan Chen + * Description : AST SCU + * + * Copyright (C) 2012-2020 ASPEED Technology Inc. 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * CLK24M + * | + * |--> H-PLL -->HCLK + * | + * |--> M-PLL -xx->MCLK + * | + * |--> V-PLL1 -xx->DCLK + * | + * |--> V-PLL2 -xx->D2CLK + * | + * |--> USB2PHY -->UTMICLK + * + * History : + * 1. 2012/08/15 Ryan Chen Create + * + ******************************************************************************/ +#include <common.h> +#include <asm/processor.h> +#include <asm/io.h> +#include <asm/arch/regs-scu.h> +#include <asm/arch/ast_scu.h> +#include <asm/arch/platform.h> +#include <asm/arch/aspeed.h> + +/* #define ASPEED_SCU_LOCK */ + +static inline u32 ast_scu_read(u32 reg) +{ + u32 val = readl(AST_SCU_BASE + reg); + + debug("ast_scu_read : reg = 0x%08x, val = 0x%08x\n", reg, val); + return val; +} + +static inline void ast_scu_write(u32 val, u32 reg) +{ + debug("ast_scu_write : reg = 0x%08x, val = 0x%08x\n", reg, val); + + writel(SCU_PROTECT_UNLOCK, AST_SCU_BASE); + writel(val, AST_SCU_BASE + reg); +#ifdef CONFIG_AST_SCU_LOCK + writel(0xaa, AST_SCU_BASE); +#endif +} + +/* SoC mapping Table */ +struct soc_id { + const char *name; + u32 rev_id; +}; + +#define SOC_ID(str, rev) { .name = str, .rev_id = rev, } + +static struct soc_id soc_map_table[] = { + SOC_ID("AST1100/AST2050-A0", 0x00000200), + SOC_ID("AST1100/AST2050-A1", 0x00000201), + SOC_ID("AST1100/AST2050-A2,3/AST2150-A0,1", 0x00000202), + SOC_ID("AST1510/AST2100-A0", 0x00000300), + SOC_ID("AST1510/AST2100-A1", 0x00000301), + SOC_ID("AST1510/AST2100-A2,3", 0x00000302), + SOC_ID("AST2200-A0,1", 0x00000102), + SOC_ID("AST2300-A0", 0x01000003), + SOC_ID("AST2300-A1", 0x01010303), + SOC_ID("AST1300-A1", 0x01010003), + SOC_ID("AST1050-A1", 0x01010203), + SOC_ID("AST2400-A0", 0x02000303), + SOC_ID("AST2400-A1", 0x02010303), + SOC_ID("AST1010-A0", 0x03000003), + SOC_ID("AST1010-A1", 0x03010003), + SOC_ID("AST1520-A0", 0x03000203), + SOC_ID("AST3200-A0", 0x03000303), + SOC_ID("AST2500-A0", 0x04000303), + SOC_ID("AST2510-A0", 0x04000103), + SOC_ID("AST2520-A0", 0x04000203), + SOC_ID("AST2530-A0", 0x04000403), + SOC_ID("AST1520-A1", 0x03010203), + SOC_ID("AST3200-A1", 0x03010303), + SOC_ID("AST2500-A1", 0x04010303), + SOC_ID("AST2510-A1", 0x04010103), + SOC_ID("AST2520-A1", 0x04010203), + SOC_ID("AST2530-A1", 0x04010403), +}; + +void ast_scu_init_eth(u8 num) +{ +/* Set MAC delay Timing */ +#ifndef AST_SOC_G5 + /* AST2300 max clk to 125Mhz, AST2400 max clk to 198Mhz */ + + /* RGMII --> H-PLL/6 */ + if (ast_scu_read(AST_SCU_HW_STRAP1) & + (SCU_HW_STRAP_MAC1_RGMII | SCU_HW_STRAP_MAC0_RGMII)) + ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & + ~SCU_CLK_MAC_MASK) | SCU_CLK_MAC_DIV(2), + AST_SCU_CLK_SEL); + else /* RMII --> H-PLL/10 */ + ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & + ~SCU_CLK_MAC_MASK) | SCU_CLK_MAC_DIV(4), + AST_SCU_CLK_SEL); + + ast_scu_write(0x2255, AST_SCU_MAC_CLK); +#endif + + switch (num) { + case 0: + ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_MAC0, + AST_SCU_RESET); + udelay(100); + ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & + ~SCU_MAC0CLK_STOP_EN, AST_SCU_CLK_STOP); + udelay(1000); + ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_MAC0, + AST_SCU_RESET); + + break; +#if defined(AST_MAC1_BASE) + case 1: + ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_MAC1, + AST_SCU_RESET); + udelay(100); + ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & + ~SCU_MAC1CLK_STOP_EN, AST_SCU_CLK_STOP); + udelay(1000); + ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_MAC1, + AST_SCU_RESET); + break; +#endif + } +} + +/* 0: disable spi + * 1: enable spi master + * 2: enable spi master and spi slave to ahb + * 3: enable spi pass-through + */ +void ast_scu_spi_master(u8 mode) +{ +#ifdef AST_SOC_G5 + switch (mode) { + case 0: + ast_scu_write(SCU_HW_STRAP_SPI_MODE_MASK, AST_SCU_REVISION_ID); + break; + case 1: + ast_scu_write(SCU_HW_STRAP_SPI_MODE_MASK, AST_SCU_REVISION_ID); + ast_scu_write(SCU_HW_STRAP_SPI_MASTER, AST_SCU_HW_STRAP1); + break; + case 2: + ast_scu_write(SCU_HW_STRAP_SPI_MODE_MASK, AST_SCU_REVISION_ID); + ast_scu_write(SCU_HW_STRAP_SPI_M_S_EN, AST_SCU_HW_STRAP1); + break; + case 3: + ast_scu_write(SCU_HW_STRAP_SPI_MODE_MASK, AST_SCU_REVISION_ID); + ast_scu_write(SCU_HW_STRAP_SPI_PASS_THROUGH, AST_SCU_HW_STRAP1); + break; + } +#else + switch (mode) { + case 0: + ast_scu_write(ast_scu_read(AST_SCU_HW_STRAP1) & + ~SCU_HW_STRAP_SPI_MODE_MASK, AST_SCU_HW_STRAP1); + break; + case 1: + ast_scu_write((ast_scu_read(AST_SCU_HW_STRAP1) & + ~SCU_HW_STRAP_SPI_MODE_MASK) | + SCU_HW_STRAP_SPI_MASTER, AST_SCU_HW_STRAP1); + break; + case 2: + ast_scu_write((ast_scu_read(AST_SCU_HW_STRAP1) & + ~SCU_HW_STRAP_SPI_MODE_MASK) | + SCU_HW_STRAP_SPI_MASTER, AST_SCU_HW_STRAP1); + break; + case 3: + ast_scu_write((ast_scu_read(AST_SCU_HW_STRAP1) & + ~SCU_HW_STRAP_SPI_MODE_MASK) | + SCU_HW_STRAP_SPI_PASS_THROUGH, AST_SCU_HW_STRAP1); + break; + } +#endif +} + +u32 ast_get_clk_source(void) +{ + if (ast_scu_read(AST_SCU_HW_STRAP1) & CLK_25M_IN) + return AST_PLL_25MHZ; + else + return AST_PLL_24MHZ; +} + +#if defined(AST_SOC_G5) + +u32 ast_get_h_pll_clk(void) +{ + u32 clk = 0; + u32 h_pll_set = ast_scu_read(AST_SCU_H_PLL); + + if (h_pll_set & SCU_H_PLL_OFF) + return 0; + + /* Programming */ + clk = ast_get_clk_source(); + if (h_pll_set & SCU_H_PLL_BYPASS_EN) { + return clk; + } else { + /* P = SCU24[18:13] + * M = SCU24[12:5] + * N = SCU24[4:0] + * hpll = 24MHz * [(M+1) /(N+1)] / (P+1) + */ + clk = ((clk * (SCU_H_PLL_GET_MNUM(h_pll_set) + 1)) / + (SCU_H_PLL_GET_NNUM(h_pll_set) + 1)) / + (SCU_H_PLL_GET_PNUM(h_pll_set) + 1); + } + debug("h_pll = %d\n", clk); + return clk; +} + +u32 ast_get_ahbclk(void) +{ + unsigned int axi_div, ahb_div, hpll; + + hpll = ast_get_h_pll_clk(); + /* AST2500 A1 fix */ + axi_div = 2; + ahb_div = (SCU_HW_STRAP_GET_AXI_AHB_RATIO( + ast_scu_read(AST_SCU_HW_STRAP1)) + 1); + + debug("HPLL=%d, AXI_Div=%d, AHB_DIV = %d, AHB CLK=%d\n", hpll, axi_div, + ahb_div, (hpll / axi_div) / ahb_div); + return ((hpll / axi_div) / ahb_div); +} + +#else /* ! AST_SOC_G5 */ + +u32 ast_get_h_pll_clk(void) +{ + u32 speed, clk = 0; + u32 h_pll_set = ast_scu_read(AST_SCU_H_PLL); + + if (h_pll_set & SCU_H_PLL_OFF) + return 0; + + if (h_pll_set & SCU_H_PLL_PARAMETER) { + /* Programming */ + clk = ast_get_clk_source(); + if (h_pll_set & SCU_H_PLL_BYPASS_EN) { + return clk; + } else { + /* OD == SCU24[4] + * OD = SCU_H_PLL_GET_DIV(h_pll_set); + * Numerator == SCU24[10:5] + * num = SCU_H_PLL_GET_NUM(h_pll_set); + * Denumerator == SCU24[3:0] + * denum = SCU_H_PLL_GET_DENUM(h_pll_set); + * hpll = 24MHz * (2-OD) * ((Numerator+2)/(Denumerator+1)) + */ + clk = ((clk * (2 - SCU_H_PLL_GET_DIV(h_pll_set)) * + (SCU_H_PLL_GET_NUM(h_pll_set) + 2)) / + (SCU_H_PLL_GET_DENUM(h_pll_set) + 1)); + } + } else { + /* HW Trap */ + speed = SCU_HW_STRAP_GET_H_PLL_CLK( + ast_scu_read(AST_SCU_HW_STRAP1)); + switch (speed) { + case 0: + clk = 384000000; + break; + case 1: + clk = 360000000; + break; + case 2: + clk = 336000000; + break; + case 3: + clk = 408000000; + break; + default: + BUG(); + break; + } + } + debug("h_pll = %d\n", clk); + return clk; +} + +u32 ast_get_ahbclk(void) +{ + unsigned int div, hpll; + + hpll = ast_get_h_pll_clk(); + div = SCU_HW_STRAP_GET_CPU_AHB_RATIO(ast_scu_read(AST_SCU_HW_STRAP1)); + div += 1; + + debug("HPLL=%d, Div=%d, AHB CLK=%d\n", hpll, div, hpll / div); + return (hpll / div); +} + +#endif /* AST_SOC_G5 */ + +void ast_scu_show_system_info(void) +{ + +#ifdef AST_SOC_G5 + unsigned int axi_div, ahb_div, h_pll; + + h_pll = ast_get_h_pll_clk(); + + /* AST2500 A1 fix */ + axi_div = 2; + ahb_div = (SCU_HW_STRAP_GET_AXI_AHB_RATIO( + ast_scu_read(AST_SCU_HW_STRAP1)) + 1); + + printf("CPU = %d MHz , AXI = %d MHz, AHB = %d MHz (%d:%d:1)\n", + h_pll / 1000000, + h_pll / axi_div / 1000000, + h_pll / axi_div / ahb_div / 1000000, axi_div, ahb_div); + +#else + u32 h_pll, div; + + h_pll = ast_get_h_pll_clk(); + + div = SCU_HW_STRAP_GET_CPU_AHB_RATIO(ast_scu_read(AST_SCU_HW_STRAP1)); + div += 1; + + printf("CPU = %d MHz ,AHB = %d MHz (%d:1)\n", h_pll / 1000000, + h_pll / div / 1000000, div); +#endif + return; +} + +void ast_scu_multi_func_eth(u8 num) +{ + switch (num) { + case 0: + if (ast_scu_read(AST_SCU_HW_STRAP1) & SCU_HW_STRAP_MAC0_RGMII) { + printf("MAC0 : RGMII\n"); + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | + SCU_FUN_PIN_MAC0_PHY_LINK, + AST_SCU_FUN_PIN_CTRL1); + } else { + printf("MAC0 : RMII/NCSI\n"); + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) & + ~SCU_FUN_PIN_MAC0_PHY_LINK, + AST_SCU_FUN_PIN_CTRL1); + } + +#ifdef AST_SOC_G5 + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | + SCU_FUN_PIN_MAC0_PHY_LINK, AST_SCU_FUN_PIN_CTRL1); + +#endif + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | + SCU_FUN_PIN_MAC0_MDIO | SCU_FUN_PIN_MAC0_MDC, + AST_SCU_FUN_PIN_CTRL3); + + break; + case 1: + if (ast_scu_read(AST_SCU_HW_STRAP1) & SCU_HW_STRAP_MAC1_RGMII) { + printf("MAC1 : RGMII\n"); + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | + SCU_FUN_PIN_MAC1_PHY_LINK, + AST_SCU_FUN_PIN_CTRL1); + } else { + printf("MAC1 : RMII/NCSI\n"); + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) & + ~SCU_FUN_PIN_MAC1_PHY_LINK, + AST_SCU_FUN_PIN_CTRL1); + } + + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | + SCU_FUN_PIN_MAC1_PHY_LINK, + AST_SCU_FUN_PIN_CTRL1); + + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | + SCU_FUC_PIN_MAC1_MDIO, + AST_SCU_FUN_PIN_CTRL5); + + break; + } +} + +void ast_scu_multi_func_romcs(u8 num) +{ + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | + SCU_FUN_PIN_ROMCS(num), AST_SCU_FUN_PIN_CTRL3); +} + +u32 ast_scu_revision_id(void) +{ + int i; + u32 rev_id = ast_scu_read(AST_SCU_REVISION_ID); + + for (i = 0; i < ARRAY_SIZE(soc_map_table); i++) { + if (rev_id == soc_map_table[i].rev_id) + break; + } + + if (i == ARRAY_SIZE(soc_map_table)) + printf("UnKnown SOC : %x\n", rev_id); + else + printf("SOC : %4s\n", soc_map_table[i].name); + + return rev_id; +} + +void ast_scu_security_info(void) +{ + switch ((ast_scu_read(AST_SCU_HW_STRAP2) >> 18) & 0x3) { + case 1: + printf("SEC : DSS Mode\n"); + break; + case 2: + printf("SEC : UnKnown\n"); + break; + case 3: + printf("SEC : SPI2 Mode\n"); + break; + } +} + +void ast_scu_sys_rest_info(void) +{ + u32 rest = ast_scu_read(AST_SCU_SYS_CTRL); + + if (rest & SCU_SYS_EXT_RESET_FLAG) { + printf("RST : External\n"); + ast_scu_write(SCU_SYS_EXT_RESET_FLAG, AST_SCU_SYS_CTRL); + } else if (rest & SCU_SYS_WDT_RESET_FLAG) { + printf("RST : Watchdog\n"); + ast_scu_write(SCU_SYS_WDT_RESET_FLAG, AST_SCU_SYS_CTRL); + } else if (rest & SCU_SYS_PWR_RESET_FLAG) { + printf("RST : Power On\n"); + ast_scu_write(SCU_SYS_PWR_RESET_FLAG, AST_SCU_SYS_CTRL); + } else { + printf("RST : CLK en\n"); + } +} + +u32 ast_scu_get_vga_memsize(void) +{ + u32 size = 0; + + switch (SCU_HW_STRAP_VGA_SIZE_GET(ast_scu_read(AST_SCU_HW_STRAP1))) { + case VGA_8M_DRAM: + size = 8 * 1024 * 1024; + break; + case VGA_16M_DRAM: + size = 16 * 1024 * 1024; + break; + case VGA_32M_DRAM: + size = 32 * 1024 * 1024; + break; + case VGA_64M_DRAM: + size = 64 * 1024 * 1024; + break; + default: + printf("error vga size\n"); + break; + } + return size; +} + +void ast_scu_get_who_init_dram(void) +{ + switch (SCU_VGA_DRAM_INIT_MASK(ast_scu_read(AST_SCU_VGA0))) { + case 0: + printf("DRAM : init by VBIOS\n"); + break; + case 1: + printf("DRAM : init by SOC\n"); + break; + default: + printf("error vga size\n"); + break; + } +} |