From: Trevor Woerner Date: Wed, 6 May 2020 12:02:36 +0000 (-0400) Subject: arm: lpc32xx: move SoC to mach-lpc32xx X-Git-Tag: v2020.07-rc3~16^2~17 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=b3d9a8b1857878fd72bf5385d91585fbafe516d6;p=oweals%2Fu-boot.git arm: lpc32xx: move SoC to mach-lpc32xx Following the example of most other SoCs in arch/$(ARCH)/cpu/$(CPU)/$(SOC) move the lpc32xx code from arch/arm/cpu/arm926ejs/lpc32xx to arch/arm/mach-lpc32xx. Following the checklist from commit 01f14456306c ("ARM: prepare for moving SoC sources into mach-*"): [1] move files from arch/arm/cpu/arm926ejs/lpc32xx to arch/arm/mach-lpx32xx [2] add machine entry to arch/arm/Makefile [3] remove "obj-y += ..." from arch/arm/cpu/arm926ejs/Makefile [4] fix the Kconfig file path in arch/arm/Kconfig [5] (no MAINTAINERS update) Reviewed-by: Simon Glass Signed-off-by: Trevor Woerner --- diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0d463088a2..bd802b3be9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1777,7 +1777,7 @@ source "arch/arm/mach-keystone/Kconfig" source "arch/arm/mach-kirkwood/Kconfig" -source "arch/arm/cpu/arm926ejs/lpc32xx/Kconfig" +source "arch/arm/mach-lpc32xx/Kconfig" source "arch/arm/mach-mvebu/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index e25bb0e594..33bb8923bf 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -62,6 +62,7 @@ machine-$(CONFIG_ARCH_K3) += k3 machine-$(CONFIG_ARCH_KEYSTONE) += keystone # TODO: rename CONFIG_KIRKWOOD -> CONFIG_ARCH_KIRKWOOD machine-$(CONFIG_KIRKWOOD) += kirkwood +machine-$(CONFIG_ARCH_LPC32XX) += lpc32xx machine-$(CONFIG_ARCH_MEDIATEK) += mediatek machine-$(CONFIG_ARCH_MESON) += meson machine-$(CONFIG_ARCH_MVEBU) += mvebu diff --git a/arch/arm/cpu/arm926ejs/Makefile b/arch/arm/cpu/arm926ejs/Makefile index b051025bb0..af63d5cc5e 100644 --- a/arch/arm/cpu/arm926ejs/Makefile +++ b/arch/arm/cpu/arm926ejs/Makefile @@ -13,7 +13,6 @@ endif endif obj-$(CONFIG_ARMADA100) += armada100/ -obj-$(if $(filter lpc32xx,$(SOC)),y) += lpc32xx/ obj-$(CONFIG_MX25) += mx25/ obj-$(CONFIG_MX27) += mx27/ obj-$(if $(filter mxs,$(SOC)),y) += mxs/ diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/Kconfig b/arch/arm/cpu/arm926ejs/lpc32xx/Kconfig deleted file mode 100644 index 986ad738ac..0000000000 --- a/arch/arm/cpu/arm926ejs/lpc32xx/Kconfig +++ /dev/null @@ -1,20 +0,0 @@ -if ARCH_LPC32XX - -config SYS_SOC - default "lpc32xx" - -choice - prompt "NXP LPC32xx board select" - -config TARGET_DEVKIT3250 - bool "Timll DevKit3250" - -config TARGET_WORK_92105 - bool "Work Microwave Work_92105" - -endchoice - -source "board/timll/devkit3250/Kconfig" -source "board/work-microwave/work_92105/Kconfig" - -endif diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/Makefile b/arch/arm/cpu/arm926ejs/lpc32xx/Makefile deleted file mode 100644 index 6303570bee..0000000000 --- a/arch/arm/cpu/arm926ejs/lpc32xx/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0+ -# -# (C) Copyright 2000-2006 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. - -obj-y = cpu.o clk.o devices.o timer.o - -obj-$(CONFIG_SPL_BUILD) += dram.o lowlevel_init.o diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/clk.c b/arch/arm/cpu/arm926ejs/lpc32xx/clk.c deleted file mode 100644 index cb2344d79f..0000000000 --- a/arch/arm/cpu/arm926ejs/lpc32xx/clk.c +++ /dev/null @@ -1,138 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2011 by Vladimir Zapolskiy - */ - -#include -#include -#include -#include -#include -#include - -static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; - -unsigned int get_sys_clk_rate(void) -{ - if (readl(&clk->sysclk_ctrl) & CLK_SYSCLK_PLL397) - return RTC_CLK_FREQUENCY * 397; - else - return OSC_CLK_FREQUENCY; -} - -unsigned int get_hclk_pll_rate(void) -{ - unsigned long long fin, fref, fcco, fout; - u32 val, m_div, n_div, p_div; - - /* - * Valid frequency ranges: - * 1 * 10^6 <= Fin <= 20 * 10^6 - * 1 * 10^6 <= Fref <= 27 * 10^6 - * 156 * 10^6 <= Fcco <= 320 * 10^6 - */ - - fref = fin = get_sys_clk_rate(); - if (fin > 20000000ULL || fin < 1000000ULL) - return 0; - - val = readl(&clk->hclkpll_ctrl); - m_div = ((val & CLK_HCLK_PLL_FEEDBACK_DIV_MASK) >> 1) + 1; - n_div = ((val & CLK_HCLK_PLL_PREDIV_MASK) >> 9) + 1; - if (val & CLK_HCLK_PLL_DIRECT) - p_div = 0; - else - p_div = ((val & CLK_HCLK_PLL_POSTDIV_MASK) >> 11) + 1; - p_div = 1 << p_div; - - if (val & CLK_HCLK_PLL_BYPASS) { - do_div(fin, p_div); - return fin; - } - - do_div(fref, n_div); - if (fref > 27000000ULL || fref < 1000000ULL) - return 0; - - fcco = fref * m_div; - fout = fcco; - if (val & CLK_HCLK_PLL_FEEDBACK) - fcco *= p_div; - else - do_div(fout, p_div); - - if (fcco > 320000000ULL || fcco < 156000000ULL) - return 0; - - return fout; -} - -unsigned int get_hclk_clk_div(void) -{ - u32 val; - - val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK; - - return 1 << val; -} - -unsigned int get_hclk_clk_rate(void) -{ - return get_hclk_pll_rate() / get_hclk_clk_div(); -} - -unsigned int get_periph_clk_div(void) -{ - u32 val; - - val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_PERIPH_DIV_MASK; - - return (val >> 2) + 1; -} - -unsigned int get_periph_clk_rate(void) -{ - if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN)) - return get_sys_clk_rate(); - - return get_hclk_pll_rate() / get_periph_clk_div(); -} - -unsigned int get_sdram_clk_rate(void) -{ - unsigned int src_clk; - - if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN)) - return get_sys_clk_rate(); - - src_clk = get_hclk_pll_rate(); - - if (readl(&clk->sdramclk_ctrl) & CLK_SDRAM_DDR_SEL) { - /* using DDR */ - switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_DDRAM_MASK) { - case CLK_HCLK_DDRAM_HALF: - return src_clk/2; - case CLK_HCLK_DDRAM_NOMINAL: - return src_clk; - default: - return 0; - } - } else { - /* using SDR */ - switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK) { - case CLK_HCLK_ARM_PLL_DIV_4: - return src_clk/4; - case CLK_HCLK_ARM_PLL_DIV_2: - return src_clk/2; - case CLK_HCLK_ARM_PLL_DIV_1: - return src_clk; - default: - return 0; - } - } -} - -int get_serial_clock(void) -{ - return get_periph_clk_rate(); -} diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c b/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c deleted file mode 100644 index 4c59a44f7e..0000000000 --- a/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2011-2015 by Vladimir Zapolskiy - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; -static struct wdt_regs *wdt = (struct wdt_regs *)WDT_BASE; - -void reset_cpu(ulong addr) -{ - /* Enable watchdog clock */ - setbits_le32(&clk->timclk_ctrl, CLK_TIMCLK_WATCHDOG); - - /* To be compatible with the original U-Boot code: - * addr: - 0: perform hard reset. - * - !=0: perform a soft reset; i.e. "RESOUT_N" not asserted). */ - if (addr == 0) { - /* Reset pulse length is 13005 peripheral clock frames */ - writel(13000, &wdt->pulse); - - /* Force WDOG_RESET2 and RESOUT_N signal active */ - writel(WDTIM_MCTRL_RESFRC2 | WDTIM_MCTRL_RESFRC1 - | WDTIM_MCTRL_M_RES2, &wdt->mctrl); - } else { - /* Force match output active */ - writel(0x01, &wdt->emr); - - /* Internal reset on match output (no pulse on "RESOUT_N") */ - writel(WDTIM_MCTRL_M_RES1, &wdt->mctrl); - } - - while (1) - /* NOP */; -} - -#if defined(CONFIG_ARCH_CPU_INIT) -int arch_cpu_init(void) -{ - /* - * It might be necessary to flush data cache, if U-Boot is loaded - * from kickstart bootloader, e.g. from S1L loader - */ - flush_dcache_all(); - - return 0; -} -#else -#error "You have to select CONFIG_ARCH_CPU_INIT" -#endif - -#if defined(CONFIG_DISPLAY_CPUINFO) -int print_cpuinfo(void) -{ - printf("CPU: NXP LPC32XX\n"); - printf("CPU clock: %uMHz\n", get_hclk_pll_rate() / 1000000); - printf("AHB bus clock: %uMHz\n", get_hclk_clk_rate() / 1000000); - printf("Peripheral clock: %uMHz\n", get_periph_clk_rate() / 1000000); - - return 0; -} -#endif - -#ifdef CONFIG_LPC32XX_ETH -int cpu_eth_init(bd_t *bis) -{ - lpc32xx_eth_initialize(bis); - return 0; -} -#endif diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/devices.c b/arch/arm/cpu/arm926ejs/lpc32xx/devices.c deleted file mode 100644 index 7e7646a2e1..0000000000 --- a/arch/arm/cpu/arm926ejs/lpc32xx/devices.c +++ /dev/null @@ -1,141 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2011 by Vladimir Zapolskiy - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; -static struct uart_ctrl_regs *ctrl = (struct uart_ctrl_regs *)UART_CTRL_BASE; -static struct mux_regs *mux = (struct mux_regs *)MUX_BASE; - -void lpc32xx_uart_init(unsigned int uart_id) -{ - if (uart_id < 1 || uart_id > 7) - return; - - /* Disable loopback mode, if it is set by S1L bootloader */ - clrbits_le32(&ctrl->loop, - UART_LOOPBACK(CONFIG_SYS_LPC32XX_UART)); - - if (uart_id < 3 || uart_id > 6) - return; - - /* Enable UART system clock */ - setbits_le32(&clk->uartclk_ctrl, CLK_UART(uart_id)); - - /* Set UART into autoclock mode */ - clrsetbits_le32(&ctrl->clkmode, - UART_CLKMODE_MASK(uart_id), - UART_CLKMODE_AUTO(uart_id)); - - /* Bypass pre-divider of UART clock */ - writel(CLK_UART_X_DIV(1) | CLK_UART_Y_DIV(1), - &clk->u3clk + (uart_id - 3)); -} - -#if !CONFIG_IS_ENABLED(OF_CONTROL) -static const struct ns16550_platdata lpc32xx_uart[] = { - { .base = UART3_BASE, .reg_shift = 2, - .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, }, - { .base = UART4_BASE, .reg_shift = 2, - .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, }, - { .base = UART5_BASE, .reg_shift = 2, - .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, }, - { .base = UART6_BASE, .reg_shift = 2, - .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, }, -}; - -#if defined(CONFIG_LPC32XX_HSUART) -static const struct lpc32xx_hsuart_platdata lpc32xx_hsuart[] = { - { HS_UART1_BASE, }, - { HS_UART2_BASE, }, - { HS_UART7_BASE, }, -}; -#endif - -U_BOOT_DEVICES(lpc32xx_uarts) = { -#if defined(CONFIG_LPC32XX_HSUART) - { "lpc32xx_hsuart", &lpc32xx_hsuart[0], }, - { "lpc32xx_hsuart", &lpc32xx_hsuart[1], }, -#endif - { "ns16550_serial", &lpc32xx_uart[0], }, - { "ns16550_serial", &lpc32xx_uart[1], }, - { "ns16550_serial", &lpc32xx_uart[2], }, - { "ns16550_serial", &lpc32xx_uart[3], }, -#if defined(CONFIG_LPC32XX_HSUART) - { "lpc32xx_hsuart", &lpc32xx_hsuart[2], }, -#endif -}; -#endif - -void lpc32xx_dma_init(void) -{ - /* Enable DMA interface */ - writel(CLK_DMA_ENABLE, &clk->dmaclk_ctrl); -} - -void lpc32xx_mac_init(void) -{ - /* Enable MAC interface */ - writel(CLK_MAC_REG | CLK_MAC_SLAVE | CLK_MAC_MASTER -#if defined(CONFIG_RMII) - | CLK_MAC_RMII, -#else - | CLK_MAC_MII, -#endif - &clk->macclk_ctrl); -} - -void lpc32xx_mlc_nand_init(void) -{ - /* Enable NAND interface */ - writel(CLK_NAND_MLC | CLK_NAND_MLC_INT, &clk->flashclk_ctrl); -} - -void lpc32xx_slc_nand_init(void) -{ - /* Enable SLC NAND interface */ - writel(CLK_NAND_SLC | CLK_NAND_SLC_SELECT, &clk->flashclk_ctrl); -} - -void lpc32xx_usb_init(void) -{ - /* Do not route the UART 5 Tx/Rx pins to the USB D+ and USB D- pins. */ - clrbits_le32(&ctrl->ctrl, UART_CTRL_UART5_USB_MODE); -} - -void lpc32xx_i2c_init(unsigned int devnum) -{ - /* Enable I2C interface */ - uint32_t ctrl = readl(&clk->i2cclk_ctrl); - if (devnum == 1) - ctrl |= CLK_I2C1_ENABLE; - if (devnum == 2) - ctrl |= CLK_I2C2_ENABLE; - writel(ctrl, &clk->i2cclk_ctrl); -} - -U_BOOT_DEVICE(lpc32xx_gpios) = { - .name = "gpio_lpc32xx" -}; - -/* Mux for SCK0, MISO0, MOSI0. We do not use SSEL0. */ - -#define P_MUX_SET_SSP0 0x1600 - -void lpc32xx_ssp_init(void) -{ - /* Enable SSP0 interface */ - writel(CLK_SSP0_ENABLE_CLOCK, &clk->ssp_ctrl); - /* Mux SSP0 pins */ - writel(P_MUX_SET_SSP0, &mux->p_mux_set); -} diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/dram.c b/arch/arm/cpu/arm926ejs/lpc32xx/dram.c deleted file mode 100644 index 4f975694fd..0000000000 --- a/arch/arm/cpu/arm926ejs/lpc32xx/dram.c +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * LPC32xx dram init - * - * (C) Copyright 2014 DENX Software Engineering GmbH - * Written-by: Albert ARIBAUD - * - * This is called by SPL to gain access to the SDR DRAM. - * - * This code runs from SRAM. - */ - -#include -#include -#include -#include -#include -#include -#include - -static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; -static struct emc_regs *emc = (struct emc_regs *)EMC_BASE; - -void ddr_init(struct emc_dram_settings *dram) -{ - uint32_t ck; - - /* Enable EMC interface and choose little endian mode */ - writel(1, &emc->ctrl); - writel(0, &emc->config); - /* Select maximum EMC Dynamic Memory Refresh Time */ - writel(0x7FF, &emc->refresh); - /* Determine CLK */ - ck = get_sdram_clk_rate(); - /* Configure SDRAM */ - writel(dram->cmddelay, &clk->sdramclk_ctrl); - writel(dram->config0, &emc->config0); - writel(dram->rascas0, &emc->rascas0); - writel(dram->rdconfig, &emc->read_config); - /* Set timings */ - writel((ck / dram->trp) & 0x0000000F, &emc->t_rp); - writel((ck / dram->tras) & 0x0000000F, &emc->t_ras); - writel((ck / dram->tsrex) & 0x0000007F, &emc->t_srex); - writel((ck / dram->twr) & 0x0000000F, &emc->t_wr); - writel((ck / dram->trc) & 0x0000001F, &emc->t_rc); - writel((ck / dram->trfc) & 0x0000001F, &emc->t_rfc); - writel((ck / dram->txsr) & 0x000000FF, &emc->t_xsr); - writel(dram->trrd, &emc->t_rrd); - writel(dram->tmrd, &emc->t_mrd); - writel(dram->tcdlr, &emc->t_cdlr); - /* Dynamic refresh */ - writel((((ck / dram->refresh) >> 4) & 0x7FF), &emc->refresh); - udelay(10); - /* Force all clocks, enable inverted ck, issue NOP command */ - writel(0x00000193, &emc->control); - udelay(100); - /* Keep all clocks enabled, issue a PRECHARGE ALL command */ - writel(0x00000113, &emc->control); - /* Fast dynamic refresh for at least a few SDRAM ck cycles */ - writel((((128) >> 4) & 0x7FF), &emc->refresh); - udelay(10); - /* set correct dynamic refresh timing */ - writel((((ck / dram->refresh) >> 4) & 0x7FF), &emc->refresh); - udelay(10); - /* set normal mode to CAS=3 */ - writel(0x00000093, &emc->control); - readl(EMC_DYCS0_BASE | dram->mode); - /* set extended mode to all zeroes */ - writel(0x00000093, &emc->control); - readl(EMC_DYCS0_BASE | dram->emode); - /* stop forcing clocks, keep inverted clock, issue normal mode */ - writel(0x00000010, &emc->control); -} diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S b/arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S deleted file mode 100644 index d42da2bc56..0000000000 --- a/arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * WORK Microwave work_92105 board low level init - * - * (C) Copyright 2014 DENX Software Engineering GmbH - * Written-by: Albert ARIBAUD - * - * Low level init is called from SPL to set up the clocks. - * On entry, the LPC3250 is in Direct Run mode with all clocks - * running at 13 MHz; on exit, ARM clock is 208 MHz, HCLK is - * 104 MHz and PCLK is 13 MHz. - * - * This code must run from SRAM so that the clock changes do - * not prevent it from executing. - */ - -.globl lowlevel_init - -lowlevel_init: - - /* Set ARM, HCLK, PCLK dividers for normal mode */ - ldr r0, =0x0000003D - ldr r1, =0x40004040 - str r0, [r1] - - /* Start HCLK PLL for 208 MHz */ - ldr r0, =0x0001401E - ldr r1, =0x40004058 - str r0, [r1] - - /* wait for HCLK PLL to lock */ -1: - ldr r0, [r1] - ands r0, r0, #1 - beq 1b - - /* switch to normal mode */ - ldr r1, =0x40004044 - ldr r0, [r1] - orr r0, #0x00000004 - str r0, [r1] - - /* Return to U-Boot via saved link register */ - mov pc, lr diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/timer.c b/arch/arm/cpu/arm926ejs/lpc32xx/timer.c deleted file mode 100644 index 3a896d10ca..0000000000 --- a/arch/arm/cpu/arm926ejs/lpc32xx/timer.c +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2011 Vladimir Zapolskiy - */ - -#include -#include -#include -#include -#include -#include - -static struct timer_regs *timer0 = (struct timer_regs *)TIMER0_BASE; -static struct timer_regs *timer1 = (struct timer_regs *)TIMER1_BASE; -static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; - -static void lpc32xx_timer_clock(u32 bit, int enable) -{ - if (enable) - setbits_le32(&clk->timclk_ctrl1, bit); - else - clrbits_le32(&clk->timclk_ctrl1, bit); -} - -static void lpc32xx_timer_reset(struct timer_regs *timer, u32 freq) -{ - writel(TIMER_TCR_COUNTER_RESET, &timer->tcr); - writel(TIMER_TCR_COUNTER_DISABLE, &timer->tcr); - writel(0, &timer->tc); - writel(0, &timer->pr); - - /* Count mode is every rising PCLK edge */ - writel(TIMER_CTCR_MODE_TIMER, &timer->ctcr); - - /* Set prescale counter value */ - writel((get_periph_clk_rate() / freq) - 1, &timer->pr); - - /* Ensure that the counter is not reset when matching TC */ - writel(0, &timer->mcr); -} - -static void lpc32xx_timer_count(struct timer_regs *timer, int enable) -{ - if (enable) - writel(TIMER_TCR_COUNTER_ENABLE, &timer->tcr); - else - writel(TIMER_TCR_COUNTER_DISABLE, &timer->tcr); -} - -int timer_init(void) -{ - lpc32xx_timer_clock(CLK_TIMCLK_TIMER0, 1); - lpc32xx_timer_reset(timer0, CONFIG_SYS_HZ); - lpc32xx_timer_count(timer0, 1); - - return 0; -} - -ulong get_timer(ulong base) -{ - return readl(&timer0->tc) - base; -} - -void __udelay(unsigned long usec) -{ - lpc32xx_timer_clock(CLK_TIMCLK_TIMER1, 1); - lpc32xx_timer_reset(timer1, CONFIG_SYS_HZ * 1000); - lpc32xx_timer_count(timer1, 1); - - while (readl(&timer1->tc) < usec) - /* NOP */; - - lpc32xx_timer_count(timer1, 0); - lpc32xx_timer_clock(CLK_TIMCLK_TIMER1, 0); -} - -unsigned long long get_ticks(void) -{ - return get_timer(0); -} - -ulong get_tbclk(void) -{ - return CONFIG_SYS_HZ; -} diff --git a/arch/arm/mach-lpc32xx/Kconfig b/arch/arm/mach-lpc32xx/Kconfig new file mode 100644 index 0000000000..986ad738ac --- /dev/null +++ b/arch/arm/mach-lpc32xx/Kconfig @@ -0,0 +1,20 @@ +if ARCH_LPC32XX + +config SYS_SOC + default "lpc32xx" + +choice + prompt "NXP LPC32xx board select" + +config TARGET_DEVKIT3250 + bool "Timll DevKit3250" + +config TARGET_WORK_92105 + bool "Work Microwave Work_92105" + +endchoice + +source "board/timll/devkit3250/Kconfig" +source "board/work-microwave/work_92105/Kconfig" + +endif diff --git a/arch/arm/mach-lpc32xx/Makefile b/arch/arm/mach-lpc32xx/Makefile new file mode 100644 index 0000000000..6303570bee --- /dev/null +++ b/arch/arm/mach-lpc32xx/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +obj-y = cpu.o clk.o devices.o timer.o + +obj-$(CONFIG_SPL_BUILD) += dram.o lowlevel_init.o diff --git a/arch/arm/mach-lpc32xx/clk.c b/arch/arm/mach-lpc32xx/clk.c new file mode 100644 index 0000000000..cb2344d79f --- /dev/null +++ b/arch/arm/mach-lpc32xx/clk.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 by Vladimir Zapolskiy + */ + +#include +#include +#include +#include +#include +#include + +static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; + +unsigned int get_sys_clk_rate(void) +{ + if (readl(&clk->sysclk_ctrl) & CLK_SYSCLK_PLL397) + return RTC_CLK_FREQUENCY * 397; + else + return OSC_CLK_FREQUENCY; +} + +unsigned int get_hclk_pll_rate(void) +{ + unsigned long long fin, fref, fcco, fout; + u32 val, m_div, n_div, p_div; + + /* + * Valid frequency ranges: + * 1 * 10^6 <= Fin <= 20 * 10^6 + * 1 * 10^6 <= Fref <= 27 * 10^6 + * 156 * 10^6 <= Fcco <= 320 * 10^6 + */ + + fref = fin = get_sys_clk_rate(); + if (fin > 20000000ULL || fin < 1000000ULL) + return 0; + + val = readl(&clk->hclkpll_ctrl); + m_div = ((val & CLK_HCLK_PLL_FEEDBACK_DIV_MASK) >> 1) + 1; + n_div = ((val & CLK_HCLK_PLL_PREDIV_MASK) >> 9) + 1; + if (val & CLK_HCLK_PLL_DIRECT) + p_div = 0; + else + p_div = ((val & CLK_HCLK_PLL_POSTDIV_MASK) >> 11) + 1; + p_div = 1 << p_div; + + if (val & CLK_HCLK_PLL_BYPASS) { + do_div(fin, p_div); + return fin; + } + + do_div(fref, n_div); + if (fref > 27000000ULL || fref < 1000000ULL) + return 0; + + fcco = fref * m_div; + fout = fcco; + if (val & CLK_HCLK_PLL_FEEDBACK) + fcco *= p_div; + else + do_div(fout, p_div); + + if (fcco > 320000000ULL || fcco < 156000000ULL) + return 0; + + return fout; +} + +unsigned int get_hclk_clk_div(void) +{ + u32 val; + + val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK; + + return 1 << val; +} + +unsigned int get_hclk_clk_rate(void) +{ + return get_hclk_pll_rate() / get_hclk_clk_div(); +} + +unsigned int get_periph_clk_div(void) +{ + u32 val; + + val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_PERIPH_DIV_MASK; + + return (val >> 2) + 1; +} + +unsigned int get_periph_clk_rate(void) +{ + if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN)) + return get_sys_clk_rate(); + + return get_hclk_pll_rate() / get_periph_clk_div(); +} + +unsigned int get_sdram_clk_rate(void) +{ + unsigned int src_clk; + + if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN)) + return get_sys_clk_rate(); + + src_clk = get_hclk_pll_rate(); + + if (readl(&clk->sdramclk_ctrl) & CLK_SDRAM_DDR_SEL) { + /* using DDR */ + switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_DDRAM_MASK) { + case CLK_HCLK_DDRAM_HALF: + return src_clk/2; + case CLK_HCLK_DDRAM_NOMINAL: + return src_clk; + default: + return 0; + } + } else { + /* using SDR */ + switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK) { + case CLK_HCLK_ARM_PLL_DIV_4: + return src_clk/4; + case CLK_HCLK_ARM_PLL_DIV_2: + return src_clk/2; + case CLK_HCLK_ARM_PLL_DIV_1: + return src_clk; + default: + return 0; + } + } +} + +int get_serial_clock(void) +{ + return get_periph_clk_rate(); +} diff --git a/arch/arm/mach-lpc32xx/cpu.c b/arch/arm/mach-lpc32xx/cpu.c new file mode 100644 index 0000000000..4c59a44f7e --- /dev/null +++ b/arch/arm/mach-lpc32xx/cpu.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011-2015 by Vladimir Zapolskiy + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; +static struct wdt_regs *wdt = (struct wdt_regs *)WDT_BASE; + +void reset_cpu(ulong addr) +{ + /* Enable watchdog clock */ + setbits_le32(&clk->timclk_ctrl, CLK_TIMCLK_WATCHDOG); + + /* To be compatible with the original U-Boot code: + * addr: - 0: perform hard reset. + * - !=0: perform a soft reset; i.e. "RESOUT_N" not asserted). */ + if (addr == 0) { + /* Reset pulse length is 13005 peripheral clock frames */ + writel(13000, &wdt->pulse); + + /* Force WDOG_RESET2 and RESOUT_N signal active */ + writel(WDTIM_MCTRL_RESFRC2 | WDTIM_MCTRL_RESFRC1 + | WDTIM_MCTRL_M_RES2, &wdt->mctrl); + } else { + /* Force match output active */ + writel(0x01, &wdt->emr); + + /* Internal reset on match output (no pulse on "RESOUT_N") */ + writel(WDTIM_MCTRL_M_RES1, &wdt->mctrl); + } + + while (1) + /* NOP */; +} + +#if defined(CONFIG_ARCH_CPU_INIT) +int arch_cpu_init(void) +{ + /* + * It might be necessary to flush data cache, if U-Boot is loaded + * from kickstart bootloader, e.g. from S1L loader + */ + flush_dcache_all(); + + return 0; +} +#else +#error "You have to select CONFIG_ARCH_CPU_INIT" +#endif + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + printf("CPU: NXP LPC32XX\n"); + printf("CPU clock: %uMHz\n", get_hclk_pll_rate() / 1000000); + printf("AHB bus clock: %uMHz\n", get_hclk_clk_rate() / 1000000); + printf("Peripheral clock: %uMHz\n", get_periph_clk_rate() / 1000000); + + return 0; +} +#endif + +#ifdef CONFIG_LPC32XX_ETH +int cpu_eth_init(bd_t *bis) +{ + lpc32xx_eth_initialize(bis); + return 0; +} +#endif diff --git a/arch/arm/mach-lpc32xx/devices.c b/arch/arm/mach-lpc32xx/devices.c new file mode 100644 index 0000000000..7e7646a2e1 --- /dev/null +++ b/arch/arm/mach-lpc32xx/devices.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 by Vladimir Zapolskiy + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; +static struct uart_ctrl_regs *ctrl = (struct uart_ctrl_regs *)UART_CTRL_BASE; +static struct mux_regs *mux = (struct mux_regs *)MUX_BASE; + +void lpc32xx_uart_init(unsigned int uart_id) +{ + if (uart_id < 1 || uart_id > 7) + return; + + /* Disable loopback mode, if it is set by S1L bootloader */ + clrbits_le32(&ctrl->loop, + UART_LOOPBACK(CONFIG_SYS_LPC32XX_UART)); + + if (uart_id < 3 || uart_id > 6) + return; + + /* Enable UART system clock */ + setbits_le32(&clk->uartclk_ctrl, CLK_UART(uart_id)); + + /* Set UART into autoclock mode */ + clrsetbits_le32(&ctrl->clkmode, + UART_CLKMODE_MASK(uart_id), + UART_CLKMODE_AUTO(uart_id)); + + /* Bypass pre-divider of UART clock */ + writel(CLK_UART_X_DIV(1) | CLK_UART_Y_DIV(1), + &clk->u3clk + (uart_id - 3)); +} + +#if !CONFIG_IS_ENABLED(OF_CONTROL) +static const struct ns16550_platdata lpc32xx_uart[] = { + { .base = UART3_BASE, .reg_shift = 2, + .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, }, + { .base = UART4_BASE, .reg_shift = 2, + .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, }, + { .base = UART5_BASE, .reg_shift = 2, + .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, }, + { .base = UART6_BASE, .reg_shift = 2, + .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, }, +}; + +#if defined(CONFIG_LPC32XX_HSUART) +static const struct lpc32xx_hsuart_platdata lpc32xx_hsuart[] = { + { HS_UART1_BASE, }, + { HS_UART2_BASE, }, + { HS_UART7_BASE, }, +}; +#endif + +U_BOOT_DEVICES(lpc32xx_uarts) = { +#if defined(CONFIG_LPC32XX_HSUART) + { "lpc32xx_hsuart", &lpc32xx_hsuart[0], }, + { "lpc32xx_hsuart", &lpc32xx_hsuart[1], }, +#endif + { "ns16550_serial", &lpc32xx_uart[0], }, + { "ns16550_serial", &lpc32xx_uart[1], }, + { "ns16550_serial", &lpc32xx_uart[2], }, + { "ns16550_serial", &lpc32xx_uart[3], }, +#if defined(CONFIG_LPC32XX_HSUART) + { "lpc32xx_hsuart", &lpc32xx_hsuart[2], }, +#endif +}; +#endif + +void lpc32xx_dma_init(void) +{ + /* Enable DMA interface */ + writel(CLK_DMA_ENABLE, &clk->dmaclk_ctrl); +} + +void lpc32xx_mac_init(void) +{ + /* Enable MAC interface */ + writel(CLK_MAC_REG | CLK_MAC_SLAVE | CLK_MAC_MASTER +#if defined(CONFIG_RMII) + | CLK_MAC_RMII, +#else + | CLK_MAC_MII, +#endif + &clk->macclk_ctrl); +} + +void lpc32xx_mlc_nand_init(void) +{ + /* Enable NAND interface */ + writel(CLK_NAND_MLC | CLK_NAND_MLC_INT, &clk->flashclk_ctrl); +} + +void lpc32xx_slc_nand_init(void) +{ + /* Enable SLC NAND interface */ + writel(CLK_NAND_SLC | CLK_NAND_SLC_SELECT, &clk->flashclk_ctrl); +} + +void lpc32xx_usb_init(void) +{ + /* Do not route the UART 5 Tx/Rx pins to the USB D+ and USB D- pins. */ + clrbits_le32(&ctrl->ctrl, UART_CTRL_UART5_USB_MODE); +} + +void lpc32xx_i2c_init(unsigned int devnum) +{ + /* Enable I2C interface */ + uint32_t ctrl = readl(&clk->i2cclk_ctrl); + if (devnum == 1) + ctrl |= CLK_I2C1_ENABLE; + if (devnum == 2) + ctrl |= CLK_I2C2_ENABLE; + writel(ctrl, &clk->i2cclk_ctrl); +} + +U_BOOT_DEVICE(lpc32xx_gpios) = { + .name = "gpio_lpc32xx" +}; + +/* Mux for SCK0, MISO0, MOSI0. We do not use SSEL0. */ + +#define P_MUX_SET_SSP0 0x1600 + +void lpc32xx_ssp_init(void) +{ + /* Enable SSP0 interface */ + writel(CLK_SSP0_ENABLE_CLOCK, &clk->ssp_ctrl); + /* Mux SSP0 pins */ + writel(P_MUX_SET_SSP0, &mux->p_mux_set); +} diff --git a/arch/arm/mach-lpc32xx/dram.c b/arch/arm/mach-lpc32xx/dram.c new file mode 100644 index 0000000000..4f975694fd --- /dev/null +++ b/arch/arm/mach-lpc32xx/dram.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * LPC32xx dram init + * + * (C) Copyright 2014 DENX Software Engineering GmbH + * Written-by: Albert ARIBAUD + * + * This is called by SPL to gain access to the SDR DRAM. + * + * This code runs from SRAM. + */ + +#include +#include +#include +#include +#include +#include +#include + +static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; +static struct emc_regs *emc = (struct emc_regs *)EMC_BASE; + +void ddr_init(struct emc_dram_settings *dram) +{ + uint32_t ck; + + /* Enable EMC interface and choose little endian mode */ + writel(1, &emc->ctrl); + writel(0, &emc->config); + /* Select maximum EMC Dynamic Memory Refresh Time */ + writel(0x7FF, &emc->refresh); + /* Determine CLK */ + ck = get_sdram_clk_rate(); + /* Configure SDRAM */ + writel(dram->cmddelay, &clk->sdramclk_ctrl); + writel(dram->config0, &emc->config0); + writel(dram->rascas0, &emc->rascas0); + writel(dram->rdconfig, &emc->read_config); + /* Set timings */ + writel((ck / dram->trp) & 0x0000000F, &emc->t_rp); + writel((ck / dram->tras) & 0x0000000F, &emc->t_ras); + writel((ck / dram->tsrex) & 0x0000007F, &emc->t_srex); + writel((ck / dram->twr) & 0x0000000F, &emc->t_wr); + writel((ck / dram->trc) & 0x0000001F, &emc->t_rc); + writel((ck / dram->trfc) & 0x0000001F, &emc->t_rfc); + writel((ck / dram->txsr) & 0x000000FF, &emc->t_xsr); + writel(dram->trrd, &emc->t_rrd); + writel(dram->tmrd, &emc->t_mrd); + writel(dram->tcdlr, &emc->t_cdlr); + /* Dynamic refresh */ + writel((((ck / dram->refresh) >> 4) & 0x7FF), &emc->refresh); + udelay(10); + /* Force all clocks, enable inverted ck, issue NOP command */ + writel(0x00000193, &emc->control); + udelay(100); + /* Keep all clocks enabled, issue a PRECHARGE ALL command */ + writel(0x00000113, &emc->control); + /* Fast dynamic refresh for at least a few SDRAM ck cycles */ + writel((((128) >> 4) & 0x7FF), &emc->refresh); + udelay(10); + /* set correct dynamic refresh timing */ + writel((((ck / dram->refresh) >> 4) & 0x7FF), &emc->refresh); + udelay(10); + /* set normal mode to CAS=3 */ + writel(0x00000093, &emc->control); + readl(EMC_DYCS0_BASE | dram->mode); + /* set extended mode to all zeroes */ + writel(0x00000093, &emc->control); + readl(EMC_DYCS0_BASE | dram->emode); + /* stop forcing clocks, keep inverted clock, issue normal mode */ + writel(0x00000010, &emc->control); +} diff --git a/arch/arm/mach-lpc32xx/lowlevel_init.S b/arch/arm/mach-lpc32xx/lowlevel_init.S new file mode 100644 index 0000000000..d42da2bc56 --- /dev/null +++ b/arch/arm/mach-lpc32xx/lowlevel_init.S @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * WORK Microwave work_92105 board low level init + * + * (C) Copyright 2014 DENX Software Engineering GmbH + * Written-by: Albert ARIBAUD + * + * Low level init is called from SPL to set up the clocks. + * On entry, the LPC3250 is in Direct Run mode with all clocks + * running at 13 MHz; on exit, ARM clock is 208 MHz, HCLK is + * 104 MHz and PCLK is 13 MHz. + * + * This code must run from SRAM so that the clock changes do + * not prevent it from executing. + */ + +.globl lowlevel_init + +lowlevel_init: + + /* Set ARM, HCLK, PCLK dividers for normal mode */ + ldr r0, =0x0000003D + ldr r1, =0x40004040 + str r0, [r1] + + /* Start HCLK PLL for 208 MHz */ + ldr r0, =0x0001401E + ldr r1, =0x40004058 + str r0, [r1] + + /* wait for HCLK PLL to lock */ +1: + ldr r0, [r1] + ands r0, r0, #1 + beq 1b + + /* switch to normal mode */ + ldr r1, =0x40004044 + ldr r0, [r1] + orr r0, #0x00000004 + str r0, [r1] + + /* Return to U-Boot via saved link register */ + mov pc, lr diff --git a/arch/arm/mach-lpc32xx/timer.c b/arch/arm/mach-lpc32xx/timer.c new file mode 100644 index 0000000000..3a896d10ca --- /dev/null +++ b/arch/arm/mach-lpc32xx/timer.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 Vladimir Zapolskiy + */ + +#include +#include +#include +#include +#include +#include + +static struct timer_regs *timer0 = (struct timer_regs *)TIMER0_BASE; +static struct timer_regs *timer1 = (struct timer_regs *)TIMER1_BASE; +static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; + +static void lpc32xx_timer_clock(u32 bit, int enable) +{ + if (enable) + setbits_le32(&clk->timclk_ctrl1, bit); + else + clrbits_le32(&clk->timclk_ctrl1, bit); +} + +static void lpc32xx_timer_reset(struct timer_regs *timer, u32 freq) +{ + writel(TIMER_TCR_COUNTER_RESET, &timer->tcr); + writel(TIMER_TCR_COUNTER_DISABLE, &timer->tcr); + writel(0, &timer->tc); + writel(0, &timer->pr); + + /* Count mode is every rising PCLK edge */ + writel(TIMER_CTCR_MODE_TIMER, &timer->ctcr); + + /* Set prescale counter value */ + writel((get_periph_clk_rate() / freq) - 1, &timer->pr); + + /* Ensure that the counter is not reset when matching TC */ + writel(0, &timer->mcr); +} + +static void lpc32xx_timer_count(struct timer_regs *timer, int enable) +{ + if (enable) + writel(TIMER_TCR_COUNTER_ENABLE, &timer->tcr); + else + writel(TIMER_TCR_COUNTER_DISABLE, &timer->tcr); +} + +int timer_init(void) +{ + lpc32xx_timer_clock(CLK_TIMCLK_TIMER0, 1); + lpc32xx_timer_reset(timer0, CONFIG_SYS_HZ); + lpc32xx_timer_count(timer0, 1); + + return 0; +} + +ulong get_timer(ulong base) +{ + return readl(&timer0->tc) - base; +} + +void __udelay(unsigned long usec) +{ + lpc32xx_timer_clock(CLK_TIMCLK_TIMER1, 1); + lpc32xx_timer_reset(timer1, CONFIG_SYS_HZ * 1000); + lpc32xx_timer_count(timer1, 1); + + while (readl(&timer1->tc) < usec) + /* NOP */; + + lpc32xx_timer_count(timer1, 0); + lpc32xx_timer_clock(CLK_TIMCLK_TIMER1, 0); +} + +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +ulong get_tbclk(void) +{ + return CONFIG_SYS_HZ; +}