[U-Boot] [PATCH v3 1/4] arm: Tegra2: Add basic NVIDIA Tegra2 SoC support

Tom Warren twarren.nvidia at gmail.com
Mon Jan 24 18:26:32 CET 2011


Mike,

On Mon, Jan 24, 2011 at 4:55 AM, Mike Rapoport <mike at compulab.co.il> wrote:
> On 01/19/11 23:19, Tom Warren wrote:
>> Signed-off-by: Tom Warren <twarren at nvidia.com>
>> ---
>> Changes for V2:
>>         - Coding style cleanup
>>         - Move serial driver changes to separate patch
>>         - Use board/nvidia/ instead of /board/tegra
>>         - Remove TRUE/FALSE defines
>>         - Use standard NS16550 register/bit defines in UART init
>>
>> Changes for V3:
>>         - Use I/O accessors for Tegra2 HW MMIO register access
>>         - Allow conditional compile of UARTA/UARTD code to save space
>>
>>  arch/arm/cpu/armv7/tegra2/Makefile           |   48 +++++
>>  arch/arm/cpu/armv7/tegra2/board.c            |   91 ++++++++++
>>  arch/arm/cpu/armv7/tegra2/config.mk          |   28 +++
>>  arch/arm/cpu/armv7/tegra2/lowlevel_init.S    |   66 +++++++
>>  arch/arm/cpu/armv7/tegra2/sys_info.c         |   35 ++++
>>  arch/arm/cpu/armv7/tegra2/timer.c            |  122 +++++++++++++
>>  arch/arm/include/asm/arch-tegra2/clk_rst.h   |  155 ++++++++++++++++
>>  arch/arm/include/asm/arch-tegra2/pinmux.h    |   52 ++++++
>>  arch/arm/include/asm/arch-tegra2/pmc.h       |  125 +++++++++++++
>>  arch/arm/include/asm/arch-tegra2/sys_proto.h |   33 ++++
>>  arch/arm/include/asm/arch-tegra2/tegra2.h    |   49 +++++
>>  arch/arm/include/asm/arch-tegra2/uart.h      |   45 +++++
>>  board/nvidia/common/board.c                  |  249 ++++++++++++++++++++++++++
>>  board/nvidia/common/board.h                  |   57 ++++++
>>  14 files changed, 1155 insertions(+), 0 deletions(-)
>>  create mode 100644 arch/arm/cpu/armv7/tegra2/Makefile
>>  create mode 100644 arch/arm/cpu/armv7/tegra2/board.c
>>  create mode 100644 arch/arm/cpu/armv7/tegra2/config.mk
>>  create mode 100644 arch/arm/cpu/armv7/tegra2/lowlevel_init.S
>>  create mode 100644 arch/arm/cpu/armv7/tegra2/sys_info.c
>>  create mode 100644 arch/arm/cpu/armv7/tegra2/timer.c
>>  create mode 100644 arch/arm/include/asm/arch-tegra2/clk_rst.h
>>  create mode 100644 arch/arm/include/asm/arch-tegra2/pinmux.h
>>  create mode 100644 arch/arm/include/asm/arch-tegra2/pmc.h
>>  create mode 100644 arch/arm/include/asm/arch-tegra2/sys_proto.h
>>  create mode 100644 arch/arm/include/asm/arch-tegra2/tegra2.h
>>  create mode 100644 arch/arm/include/asm/arch-tegra2/uart.h
>>  create mode 100644 board/nvidia/common/board.c
>>  create mode 100644 board/nvidia/common/board.h
>
> [ snip ]
>
>> + */
>> +
>> +#ifndef _CLK_RST_H_
>> +#define _CLK_RST_H_
>> +
>> +/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
>> +
>> +typedef volatile struct clk_rst_ctlr {
>
> Is it necessary to use the structure to map the clocks and reset controller?
> Wouldn't be better to port Linux implementation of Tegra2 clocks to U-Boot as well?
> Besides, since you're using I/O accessors anyway, the struct can replaces with
> base address and offset definitions.
I asked Wolfgang to pre-review the original patch, and this is what he
said about original
base+offset register access code:
Wolfgang> We do not allow this in U-Boot.  Please turn all offset
tables into C structs, and
Wolfgang> create a set of I/O accessor functions (or macros) as needed
to provide the needed
Wolfgang> memory barriers on your architecture.

Using structs seems like a natural way to map HW MMIO regs, and is
done throughout U-Boot.
The structs are already written, contain just the members needed for
U-Boot (to a large degree),
and as Wolfgang has said in the past, U-Boot is not Linux, so I see no
reason to bring in the
Linux Tegra2 structs for any of these HW blocks. When I start posting
the drivers (SPI, USB,
etc.), then it might make sense to use (copy w/edits) the Linux data
structs, etc.

>
>> +     uint crc_rst_src;               /* _RST_SOURCE_0,       0x00*/
>> +     uint crc_rst_dev_l;             /* _RST_DEVICES_L_0,    0x04*/
>> +     uint crc_rst_dev_h;             /* _RST_DEVICES_H_0,    0x08*/
>> +     uint crc_rst_dev_u;             /* _RST_DEVICES_U_0,    0x0C*/
>> +     uint crc_clk_out_enb_l;         /* _CLK_OUT_ENB_L_0,    0x10*/
>> +     uint crc_clk_out_enb_h;         /* _CLK_OUT_ENB_H_0,    0x14*/
>
> [ snip ]
>
>> +
>> +#ifndef _PINMUX_H_
>> +#define _PINMUX_H_
>> +
>> +/* APB MISC Pin Mux and Tristate (APB_MISC_PP_) registers */
>> +
>> +typedef volatile struct pinmux_tri_ctlr {
>
> The same comment is valid also for the pin multiplexing registers...
>
>> +     uint pmt_reserved0;             /* ABP_MISC_PP_ reserved offset 00 */
>> +     uint pmt_reserved1;             /* ABP_MISC_PP_ reserved offset 04 */
>> +     uint pmt_strap_opt_a;           /* _STRAPPING_OPT_A_0, offset 08 */
>> +
>> +#ifndef _PMC_H_
>> +#define _PMC_H_
>> +
>> +/* Power Management Controller (APBDEV_PMC_) registers */
>> +
>> +typedef volatile struct pmc_ctlr {
>
> And for the PMC registers as well.
>
>> +     uint pmc_cntrl;                 /* _CNTRL_0, offset 00 */
>> +     uint pmc_sec_disable;           /* _SEC_DISABLE_0, offset 04 */
>> +     uint pmc_pmc_swrst;             /* _PMC_SWRST_0, offset 08 */
>> +     uint pmc_wake_mask;             /* _WAKE_MASK_0, offset 0C */
>> +     uint pmc_wake_lvl;              /* _WAKE_LVL_0, offset 10 */
>
> [ snip ]
>
>> +#ifndef _TEGRA2_H_
>> +#define _TEGRA2_H_
>> +
>> +#define NV_PA_SDRAM_BASE     0x00000000
>> +#define NV_PA_TMRUS_BASE     0x60005010
>> +#define NV_PA_CLK_RST_BASE   0x60006000
>> +#define NV_PA_APB_MISC_BASE  0x70000000
>> +#define NV_PA_APB_UARTA_BASE (NV_PA_APB_MISC_BASE + 0x6000)
>> +#define NV_PA_APB_UARTB_BASE (NV_PA_APB_MISC_BASE + 0x6040)
>> +#define NV_PA_APB_UARTC_BASE (NV_PA_APB_MISC_BASE + 0x6200)
>> +#define NV_PA_APB_UARTD_BASE (NV_PA_APB_MISC_BASE + 0x6300)
>> +#define NV_PA_APB_UARTE_BASE (NV_PA_APB_MISC_BASE + 0x6400)
>> +#define NV_PA_PMC_BASE               0x7000E400
>
> what is the purpose of NV_PA prefix here?
NV_Physical_Address - a base address of a HW block (Power Management
Cntrlr, etc.)

>> +#define TEGRA2_SDRC_CS0              NV_PA_SDRAM_BASE
>> +#define LOW_LEVEL_SRAM_STACK 0x4000FFFC
>> +
>> +#ifndef __ASSEMBLY__
>> +typedef volatile struct timerus {
>> +     unsigned int cntr_1us;
>
> [ snip ]
>
>> +#ifndef _UART_H_
>> +#define _UART_H_
>> +
>> +/* UART registers */
>> +
>> +typedef volatile struct uart_ctlr {
>
> The same comment as for the other struct *_ctrl...
>
>> +     uint uart_thr_dlab_0;           /* UART_THR_DLAB_0_0, offset 00 */
>> +     uint uart_ier_dlab_0;           /* UART_IER_DLAB_0_0, offset 04 */
>> +     uint uart_iir_fcr;              /* UART_IIR_FCR_0, offset 08 */
>> +     uint uart_lcr;                  /* UART_LCR_0, offset 0C */
>> +     uint uart_mcr;                  /* UART_MCR_0, offset 10 */
>> +     uint uart_lsr;                  /* UART_LSR_0, offset 14 */
>> +     uint uart_msr;                  /* UART_MSR_0, offset 18 */
>> +     uint uart_spr;                  /* UART_SPR_0, offset 1C */
>> +     uint uart_irda_csr;             /* UART_IRDA_CSR_0, offset 20 */
>> +     uint uart_reserved[6];          /* Reserved, unused */
>> +     uint uart_asr;                  /* UART_ASR_0, offset 3C */
>> +} uart_ctlr;
>> +
>> +#define UART_FCR_TRIGGER_3   0x30    /* Mask for trigger set at 3 */
>> +
>> +#endif       /* UART_H */
>> diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
>> new file mode 100644
>> index 0000000..876facb
>> --- /dev/null
>> +++ b/board/nvidia/common/board.c
>
> It seems that this file is supposed to include code common to all Tegra2 based
> boards and not only NVidia boards. I'd suggest moving its contents to the
> arch/arm/cpu/armv7/tegra2/board.c
board_init and timer_init funcs are found mostly in board/xxxx files
in U-Boot, with
a few instances (mostly timer_init) in arch/arm/cpu/xxx files.  I'd
prefe to leave this file
where it is.

>
>> @@ -0,0 +1,249 @@
>> +/*
>> + *  (C) Copyright 2010,2011
>> + *  NVIDIA Corporation <www.nvidia.com>
>> + *
>
> [ snip ]
>
>> +/*
>> + * Routine: pin_mux_uart
>> + * Description: setup the pin muxes/tristate values for UART based on uart_num
>> + */
>> +void pin_mux_uart(int uart_num)
>> +{
>> +     pinmux_tri_ctlr *const pmt = (pinmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
>> +     u32 reg;
>> +
>> +#if CONFIG_TEGRA2_ENABLE_UARTA
>> +     if (uart_num  == UART_A) {
>> +             reg = readl(pmt->pmt_ctl_c);
>> +             reg &= 0xFFF0FFFF;      /* IRRX_/IRTX_SEL [19:16] = 00 UARTA */
>> +             writel(reg, pmt->pmt_ctl_c);
>> +
>> +             reg = readl(pmt->pmt_tri_a);
>> +             reg &= ~Z_IRRX;         /* Z_IRRX = normal (0) */
>> +             reg &= ~Z_IRTX;         /* Z_IRTX = normal (0) */
>> +             writel(reg, pmt->pmt_tri_a);
>
> This covers only one possiblity of UART-A pin muxing options
True, and when this code was in the board/nvidia/xxx area it made sense.
To date, all of our Tegra boards use these pinmux options for both UARTs.
If a board vendor chooses to use different pinmuxes, then they can override
these funcs in their board files, or use their own code triggered by their own
defines. But according to our HW guys, the vast majority will use these pins.

>
>> +     }
>> +#endif       /* CONFIG_TEGRA2_ENABLE_UARTA */
>> +#if CONFIG_TEGRA2_ENABLE_UARTD
>> +     if (uart_num == UART_D) {
>> +             reg = readl(pmt->pmt_ctl_b);
>> +             reg &= 0xFFFFFFF3;      /* GMC_SEL [3:2] = 00, UARTD */
>> +             writel(reg, pmt->pmt_ctl_b);
>> +
>> +             reg = readl(pmt->pmt_tri_a);
>> +             reg &= ~Z_GMC;          /* Z_GMC = normal (0) */
>> +             writel(reg, pmt->pmt_tri_a);
>> +     }
>
> ditto for UART-D
See my comment above.
>
>> +#endif       /* CONFIG_TEGRA2_ENABLE_UARTD */
>> +}
>> +
>> +void setup_uart(uart_ctlr *u)
>> +{
>> +     u32 reg;
>> +
>> +     /* Prepare the divisor value */
>> +     reg = NVRM_PLLP_FIXED_FREQ_KHZ * 1000 / NV_DEFAULT_DEBUG_BAUD / 16;
>> +
>> +     /* Set up UART parameters */
>> +     writel(UART_LCR_DLAB, u->uart_lcr);
>> +     writel(reg, u->uart_thr_dlab_0);
>> +     writel(0, u->uart_ier_dlab_0);
>> +     writel(0, u->uart_lcr);                 /* clear DLAB */
>> +     writel((UART_FCR_TRIGGER_3 | UART_FCR_FIFO_EN | \
>> +             UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR), u->uart_iir_fcr);
>> +     writel(0, u->uart_ier_dlab_0);
>> +     writel(UART_LCR_WLS_8, u->uart_lcr);    /* 8N1 */
>> +     writel(UART_MCR_RTS, u->uart_mcr);
>> +     writel(0, u->uart_msr);
>> +     writel(0, u->uart_spr);
>> +     writel(0, u->uart_irda_csr);
>> +     writel(0, u->uart_asr);
>> +     writel((UART_FCR_TRIGGER_3 | UART_FCR_FIFO_EN), u->uart_iir_fcr);
>> +
>> +     /* Flush any old characters out of the RX FIFO */
>> +     reg = readl(u->uart_lsr);
>> +
>> +     while (reg & UART_LSR_DR) {
>> +             reg = readl(u->uart_thr_dlab_0);
>> +             reg = readl(u->uart_lsr);
>> +     }
>> +}
>> +
>> +/*
>> + * Routine: init_uart
>> + * Description: init the UART clocks, muxes, and baudrate/parity/etc.
>> + */
>> +void init_uart(int uart_num)
>> +{
>> +#if CONFIG_TEGRA2_ENABLE_UARTA
>> +     if (uart_num == UART_A) {
>> +             uart_ctlr *const uart = (uart_ctlr *)NV_PA_APB_UARTA_BASE;
>> +
>> +             uart_clock_init(UART_A);
>> +
>> +             /* Enable UARTA - uses config 0 */
>> +             pin_mux_uart(UART_A);
>> +
>> +             setup_uart(uart);
>> +     }
>> +#endif       /* CONFIG_TEGRA2_ENABLE_UARTD */
>> +#if CONFIG_TEGRA2_ENABLE_UARTD
>> +     if (uart_num == UART_D) {
>> +             uart_ctlr *const uart = (uart_ctlr *)NV_PA_APB_UARTD_BASE;
>> +
>> +             uart_clock_init(UART_D);
>> +
>> +             /* Enable UARTD - uses config 0 */
>> +             pin_mux_uart(UART_D);
>> +
>> +             setup_uart(uart);
>> +     }
>> +#endif       /* CONFIG_TEGRA2_ENABLE_UARTD */
>> +}
>> +
>> +void uart_init(void)
>> +{
>> +#if (CONFIG_TEGRA2_ENABLE_UARTA)
>> +     init_uart(UART_A);
>> +#endif
>> +#if (CONFIG_TEGRA2_ENABLE_UARTD)
>> +     init_uart(UART_D);
>> +#endif
>> +}
>> diff --git a/board/nvidia/common/board.h b/board/nvidia/common/board.h
>> new file mode 100644
>> index 0000000..d49e978
>> --- /dev/null
>> +++ b/board/nvidia/common/board.h
>> @@ -0,0 +1,57 @@
>> +/*
>> + *  (C) Copyright 2010,2011
>> + *  NVIDIA Corporation <www.nvidia.com>
>> + *
>> + * See file CREDITS for list of people who contributed to this
>> + * project.
>> + *
>> + * 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
>> + */
>> +
>> +#ifndef _COMMON_BOARD_H_
>> +#define _COMMON_BOARD_H_
>> +
>> +#include <asm/arch/clk_rst.h>
>> +#include <asm/arch/pinmux.h>
>> +#include <asm/arch/uart.h>
>> +
>> +#define NVRM_PLLP_FIXED_FREQ_KHZ     216000
>> +#define NV_DEFAULT_DEBUG_BAUD                115200
>> +
>> +#define PLL_BYPASS           (1 << 31)
>> +#define PLL_ENABLE           (1 << 30)
>> +#define PLL_BASE_OVRRIDE     (1 << 28)
>> +#define PLL_DIVP             (1 << 20)       /* post divider, b22:20 */
>> +#define PLL_DIVM             0x0C            /* input divider, b4:0 */
>> +
>> +#define SWR_UARTD_RST                (1 << 2)
>> +#define CLK_ENB_UARTD                (1 << 2)
>> +#define SWR_UARTA_RST                (1 << 6)
>> +#define CLK_ENB_UARTA                (1 << 6)
>> +
>> +#define Z_GMC                        (1 << 29)
>> +#define Z_IRRX                       (1 << 20)
>> +#define Z_IRTX                       (1 << 19)
>> +
>> +enum {
>> +     UART_A = 1,
>> +     UART_B,
>> +     UART_C,
>> +     UART_D,
>> +     UART_E
>> +};
>> +
>> +#endif /* _COMMON_BOARD_H_ */
>
>
> --
> Sincerely yours,
> Mike.
Thanks,
Tom
>


More information about the U-Boot mailing list