Merge branch 'master' of git://git.denx.de/u-boot-arm

Conflicts:
	arch/arm/cpu/armv7/config.mk
	board/ti/am43xx/mux.c
	include/configs/am43xx_evm.h

Signed-off-by: Tom Rini <trini@ti.com>
This commit is contained in:
Tom Rini 2014-02-26 16:49:58 -05:00
commit eeb72e6761
121 changed files with 5959 additions and 607 deletions

8
README
View file

@ -1741,7 +1741,7 @@ CBFS (Coreboot Filesystem) support
If this option is set, then U-Boot will prevent the environment If this option is set, then U-Boot will prevent the environment
variable "splashimage" from being set to a problematic address variable "splashimage" from being set to a problematic address
(see README.displaying-bmps and README.arm-unaligned-accesses). (see README.displaying-bmps).
This option is useful for targets where, due to alignment This option is useful for targets where, due to alignment
restrictions, an improperly aligned BMP image will cause a data restrictions, an improperly aligned BMP image will cause a data
abort. If you think you will not have problems with unaligned abort. If you think you will not have problems with unaligned
@ -3742,12 +3742,6 @@ Configuration Settings:
its config.mk file). If you find problems enabling this option on its config.mk file). If you find problems enabling this option on
your board please report the problem and send patches! your board please report the problem and send patches!
- CONFIG_SYS_SYM_OFFSETS
This is set by architectures that use offsets for link symbols
instead of absolute values. So bss_start is obtained using an
offset _bss_start_ofs from CONFIG_SYS_TEXT_BASE, rather than
directly. You should not need to touch this setting.
- CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC (OMAP only) - CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC (OMAP only)
This is set by OMAP boards for the max time that reset should This is set by OMAP boards for the max time that reset should
be asserted. See doc/README.omap-reset-time for details on how be asserted. See doc/README.omap-reset-time for details on how

View file

@ -70,32 +70,6 @@ _end_vect:
************************************************************************* *************************************************************************
*/ */
.globl _TEXT_BASE
_TEXT_BASE:
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
.word CONFIG_SPL_TEXT_BASE
#else
.word CONFIG_SYS_TEXT_BASE
#endif
/*
* These are defined in the board-specific linker script.
* Subtracting _start from them lets the linker put their
* relative position in the executable instead of leaving
* them null.
*/
.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start
.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end - _start
.globl _end_ofs
_end_ofs:
.word _end - _start
#ifdef CONFIG_USE_IRQ #ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */ /* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START .globl IRQ_STACK_START
@ -295,7 +269,6 @@ cpu_init_crit:
#ifdef CONFIG_SPL_BUILD #ifdef CONFIG_SPL_BUILD
.align 5 .align 5
do_hang: do_hang:
ldr sp, _TEXT_BASE /* use 32 words about stack */
bl hang /* hang and never return */ bl hang /* hang and never return */
#else /* !CONFIG_SPL_BUILD */ #else /* !CONFIG_SPL_BUILD */
.align 5 .align 5

View file

@ -33,7 +33,11 @@ SECTIONS
.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
. = ALIGN(4); . = ALIGN(4);
__image_copy_end = .; __image_copy_end = .;
_end = .;
.end :
{
*(.__end)
}
.bss : .bss :
{ {

View file

@ -77,33 +77,6 @@ _end_vect:
************************************************************************* *************************************************************************
*/ */
.globl _TEXT_BASE
_TEXT_BASE:
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
.word CONFIG_SPL_TEXT_BASE
#else
.word CONFIG_SYS_TEXT_BASE
#endif
/*
* These are defined in the board-specific linker script.
* Subtracting _start from them lets the linker put their
* relative position in the executable instead of leaving
* them null.
*/
.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start
.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end - _start
.globl _end_ofs
_end_ofs:
.word _end - _start
/* IRQ stack memory (calculated at run-time) + 8 bytes */ /* IRQ stack memory (calculated at run-time) + 8 bytes */
.globl IRQ_STACK_START_IN .globl IRQ_STACK_START_IN
IRQ_STACK_START_IN: IRQ_STACK_START_IN:

View file

@ -67,32 +67,6 @@ _pad: .word 0x12345678 /* now 16*4=64 */
************************************************************************* *************************************************************************
*/ */
.globl _TEXT_BASE
_TEXT_BASE:
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
.word CONFIG_SPL_TEXT_BASE
#else
.word CONFIG_SYS_TEXT_BASE
#endif
/*
* These are defined in the board-specific linker script.
* Subtracting _start from them lets the linker put their
* relative position in the executable instead of leaving
* them null.
*/
.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start
.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end - _start
.globl _end_ofs
_end_ofs:
.word _end - _start
#ifdef CONFIG_USE_IRQ #ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */ /* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START .globl IRQ_STACK_START

View file

@ -50,5 +50,8 @@ SECTIONS
.bss : { *(.bss*) } .bss : { *(.bss*) }
__bss_end = .; __bss_end = .;
_end = .; .end :
{
*(.__end)
}
} }

View file

@ -55,32 +55,6 @@ _fiq: .word fiq
************************************************************************* *************************************************************************
*/ */
.globl _TEXT_BASE
_TEXT_BASE:
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
.word CONFIG_SPL_TEXT_BASE
#else
.word CONFIG_SYS_TEXT_BASE
#endif
/*
* These are defined in the board-specific linker script.
* Subtracting _start from them lets the linker put their
* relative position in the executable instead of leaving
* them null.
*/
.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start
.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end - _start
.globl _end_ofs
_end_ofs:
.word _end - _start
#ifdef CONFIG_USE_IRQ #ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */ /* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START .globl IRQ_STACK_START

View file

@ -26,27 +26,18 @@
#define CONFIG_SYS_MATRIX_EBICSA_VAL CONFIG_SYS_MATRIX_EBI0CSA_VAL #define CONFIG_SYS_MATRIX_EBICSA_VAL CONFIG_SYS_MATRIX_EBI0CSA_VAL
#endif #endif
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE
.globl lowlevel_init .globl lowlevel_init
.type lowlevel_init,function .type lowlevel_init,function
lowlevel_init: lowlevel_init:
mov r5, pc /* r5 = POS1 + 4 current */
POS1: POS1:
adr r5, POS1 /* r5 = POS1 run time */
ldr r0, =POS1 /* r0 = POS1 compile */ ldr r0, =POS1 /* r0 = POS1 compile */
ldr r2, _TEXT_BASE
sub r0, r0, r2 /* r0 = POS1-_TEXT_BASE (POS1 relative) */
sub r5, r5, r0 /* r0 = CONFIG_SYS_TEXT_BASE-1 */ sub r5, r5, r0 /* r0 = CONFIG_SYS_TEXT_BASE-1 */
sub r5, r5, #4 /* r1 = text base - current */
/* memory control configuration 1 */ /* memory control configuration 1 */
ldr r0, =SMRDATA ldr r0, =SMRDATA
ldr r2, =SMRDATA1 ldr r2, =SMRDATA1
ldr r1, _TEXT_BASE
sub r0, r0, r1
sub r2, r2, r1
add r0, r0, r5 add r0, r0, r5
add r2, r2, r5 add r2, r2, r5
0: 0:
@ -149,9 +140,6 @@ PLL_setup_end:
ldr r0, =SMRDATA1 ldr r0, =SMRDATA1
ldr r2, =SMRDATA2 ldr r2, =SMRDATA2
ldr r1, _TEXT_BASE
sub r0, r0, r1
sub r2, r2, r1
add r0, r0, r5 add r0, r0, r5
add r2, r2, r5 add r2, r2, r5
2: 2:

View file

@ -101,32 +101,6 @@ fiq:
************************************************************************* *************************************************************************
*/ */
.globl _TEXT_BASE
_TEXT_BASE:
#ifdef CONFIG_SPL_TEXT_BASE
.word CONFIG_SPL_TEXT_BASE
#else
.word CONFIG_SYS_TEXT_BASE
#endif
/*
* These are defined in the board-specific linker script.
* Subtracting _start from them lets the linker put their
* relative position in the executable instead of leaving
* them null.
*/
.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start
.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end - _start
.globl _end_ofs
_end_ofs:
.word _end - _start
#ifdef CONFIG_USE_IRQ #ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */ /* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START .globl IRQ_STACK_START
@ -207,6 +181,5 @@ _reset:
bx lr bx lr
_hang: _hang:
ldr sp, _TEXT_BASE /* switch to abort stack */
1: 1:
bl 1b /* hang and never return */ bl 1b /* hang and never return */

View file

@ -49,9 +49,14 @@ SECTIONS
__bss_end = .; __bss_end = .;
} }
_end = .; .end :
{
*(.__end)
}
.dynsym _end : { *(.dynsym) } _image_binary_end = .;
.dynsym _image_binary_end : { *(.dynsym) }
.dynbss : { *(.dynbss) } .dynbss : { *(.dynbss) }
.dynstr : { *(.dynstr*) } .dynstr : { *(.dynstr*) }
.dynamic : { *(.dynamic*) } .dynamic : { *(.dynamic*) }

View file

@ -49,9 +49,14 @@ SECTIONS
__bss_end = .; __bss_end = .;
} }
_end = .; .end :
{
*(.__end)
}
.dynsym _end : { *(.dynsym) } _image_binary_end = .;
.dynsym _image_binary_end : { *(.dynsym) }
.dynbss : { *(.dynbss) } .dynbss : { *(.dynbss) }
.dynstr : { *(.dynstr*) } .dynstr : { *(.dynstr*) }
.dynamic : { *(.dynamic*) } .dynamic : { *(.dynamic*) }

View file

@ -102,32 +102,6 @@ _fiq:
************************************************************************* *************************************************************************
*/ */
.globl _TEXT_BASE
_TEXT_BASE:
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
.word CONFIG_SPL_TEXT_BASE
#else
.word CONFIG_SYS_TEXT_BASE
#endif
/*
* These are defined in the board-specific linker script.
* Subtracting _start from them lets the linker put their
* relative position in the executable instead of leaving
* them null.
*/
.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start
.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end - _start
.globl _end_ofs
_end_ofs:
.word _end - _start
#ifdef CONFIG_USE_IRQ #ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */ /* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START .globl IRQ_STACK_START
@ -330,7 +304,6 @@ flush_dcache:
#ifdef CONFIG_SPL_BUILD #ifdef CONFIG_SPL_BUILD
.align 5 .align 5
do_hang: do_hang:
ldr sp, _TEXT_BASE /* switch to abort stack */
1: 1:
bl 1b /* hang and never return */ bl 1b /* hang and never return */
#else /* !CONFIG_SPL_BUILD */ #else /* !CONFIG_SPL_BUILD */

View file

@ -71,32 +71,6 @@ _vectors_end:
************************************************************************* *************************************************************************
*/ */
.globl _TEXT_BASE
_TEXT_BASE:
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
.word CONFIG_SPL_TEXT_BASE
#else
.word CONFIG_SYS_TEXT_BASE
#endif
/*
* These are defined in the board-specific linker script.
* Subtracting _start from them lets the linker put their
* relative position in the executable instead of leaving
* them null.
*/
.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start
.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end - _start
.globl _end_ofs
_end_ofs:
.word _end - _start
#ifdef CONFIG_USE_IRQ #ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */ /* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START .globl IRQ_STACK_START

View file

@ -67,32 +67,6 @@ _fiq:
************************************************************************* *************************************************************************
*/ */
.globl _TEXT_BASE
_TEXT_BASE:
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
.word CONFIG_SPL_TEXT_BASE
#else
.word CONFIG_SYS_TEXT_BASE
#endif
/*
* These are defined in the board-specific linker script.
* Subtracting _start from them lets the linker put their
* relative position in the executable instead of leaving
* them null.
*/
.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start
.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end - _start
.globl _end_ofs
_end_ofs:
.word _end - _start
#ifdef CONFIG_USE_IRQ #ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */ /* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START .globl IRQ_STACK_START

View file

@ -23,6 +23,7 @@ obj-y += nonsec_virt.o
obj-y += virt-v7.o obj-y += virt-v7.o
endif endif
obj-$(CONFIG_KONA) += kona-common/
obj-$(CONFIG_OMAP_COMMON) += omap-common/ obj-$(CONFIG_OMAP_COMMON) += omap-common/
obj-$(CONFIG_TEGRA) += tegra-common/ obj-$(CONFIG_TEGRA) += tegra-common/

View file

@ -36,11 +36,15 @@
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
static const struct gpio_bank gpio_bank_am33xx[4] = { static const struct gpio_bank gpio_bank_am33xx[] = {
{ (void *)AM33XX_GPIO0_BASE, METHOD_GPIO_24XX }, { (void *)AM33XX_GPIO0_BASE, METHOD_GPIO_24XX },
{ (void *)AM33XX_GPIO1_BASE, METHOD_GPIO_24XX }, { (void *)AM33XX_GPIO1_BASE, METHOD_GPIO_24XX },
{ (void *)AM33XX_GPIO2_BASE, METHOD_GPIO_24XX }, { (void *)AM33XX_GPIO2_BASE, METHOD_GPIO_24XX },
{ (void *)AM33XX_GPIO3_BASE, METHOD_GPIO_24XX }, { (void *)AM33XX_GPIO3_BASE, METHOD_GPIO_24XX },
#ifdef CONFIG_AM43XX
{ (void *)AM33XX_GPIO4_BASE, METHOD_GPIO_24XX },
{ (void *)AM33XX_GPIO5_BASE, METHOD_GPIO_24XX },
#endif
}; };
const struct gpio_bank *const omap_gpio_bank = gpio_bank_am33xx; const struct gpio_bank *const omap_gpio_bank = gpio_bank_am33xx;

View file

@ -94,6 +94,8 @@ void enable_basic_clocks(void)
&cmper->gpio1clkctrl, &cmper->gpio1clkctrl,
&cmper->gpio2clkctrl, &cmper->gpio2clkctrl,
&cmper->gpio3clkctrl, &cmper->gpio3clkctrl,
&cmper->gpio4clkctrl,
&cmper->gpio5clkctrl,
&cmper->i2c1clkctrl, &cmper->i2c1clkctrl,
&cmper->emiffwclkctrl, &cmper->emiffwclkctrl,
&cmper->emifclkctrl, &cmper->emifclkctrl,

View file

@ -211,11 +211,8 @@ static u32 pll_dco_freq_sel(u32 clkout_dco)
static u32 pll_sigma_delta_val(u32 clkout_dco) static u32 pll_sigma_delta_val(u32 clkout_dco)
{ {
u32 sig_val = 0; u32 sig_val = 0;
float frac_div;
frac_div = (float) clkout_dco / 250; sig_val = (clkout_dco + 225) / 250;
frac_div = frac_div + 0.90;
sig_val = (int)frac_div;
sig_val = sig_val << 24; sig_val = sig_val << 24;
return sig_val; return sig_val;

View file

@ -38,7 +38,11 @@ SECTIONS
. = ALIGN(4); . = ALIGN(4);
__image_copy_end = .; __image_copy_end = .;
_end = .;
.end :
{
*(.__end)
} >.sram
.bss : .bss :
{ {

View file

@ -0,0 +1,11 @@
#
# Copyright 2013 Broadcom Corporation.
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += reset.o
obj-y += clk-core.o
obj-y += clk-bcm281xx.o
obj-y += clk-sdio.o
obj-y += clk-bsc.o

View file

@ -0,0 +1,523 @@
/*
* Copyright 2013 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
/*
*
* bcm281xx-specific clock tables
*
*/
#include <common.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <asm/arch/sysmap.h>
#include <asm/kona-common/clk.h>
#include "clk-core.h"
#define CLOCK_1K 1000
#define CLOCK_1M (CLOCK_1K * 1000)
/* declare a reference clock */
#define DECLARE_REF_CLK(clk_name, clk_parent, clk_rate, clk_div) \
static struct refclk clk_name = { \
.clk = { \
.name = #clk_name, \
.parent = clk_parent, \
.rate = clk_rate, \
.div = clk_div, \
.ops = &ref_clk_ops, \
}, \
}
/*
* Reference clocks
*/
/* Declare a list of reference clocks */
DECLARE_REF_CLK(ref_crystal, 0, 26 * CLOCK_1M, 1);
DECLARE_REF_CLK(var_96m, 0, 96 * CLOCK_1M, 1);
DECLARE_REF_CLK(ref_96m, 0, 96 * CLOCK_1M, 1);
DECLARE_REF_CLK(ref_312m, 0, 312 * CLOCK_1M, 0);
DECLARE_REF_CLK(ref_104m, &ref_312m.clk, 104 * CLOCK_1M, 3);
DECLARE_REF_CLK(ref_52m, &ref_104m.clk, 52 * CLOCK_1M, 2);
DECLARE_REF_CLK(ref_13m, &ref_52m.clk, 13 * CLOCK_1M, 4);
DECLARE_REF_CLK(var_312m, 0, 312 * CLOCK_1M, 0);
DECLARE_REF_CLK(var_104m, &var_312m.clk, 104 * CLOCK_1M, 3);
DECLARE_REF_CLK(var_52m, &var_104m.clk, 52 * CLOCK_1M, 2);
DECLARE_REF_CLK(var_13m, &var_52m.clk, 13 * CLOCK_1M, 4);
struct refclk_lkup {
struct refclk *procclk;
const char *name;
};
/* Lookup table for string to clk tranlation */
#define MKSTR(x) {&x, #x}
static struct refclk_lkup refclk_str_tbl[] = {
MKSTR(ref_crystal), MKSTR(var_96m), MKSTR(ref_96m),
MKSTR(ref_312m), MKSTR(ref_104m), MKSTR(ref_52m),
MKSTR(ref_13m), MKSTR(var_312m), MKSTR(var_104m),
MKSTR(var_52m), MKSTR(var_13m),
};
int refclk_entries = sizeof(refclk_str_tbl)/sizeof(refclk_str_tbl[0]);
/* convert ref clock string to clock structure pointer */
struct refclk *refclk_str_to_clk(const char *name)
{
int i;
struct refclk_lkup *tblp = refclk_str_tbl;
for (i = 0; i < refclk_entries; i++, tblp++) {
if (!(strcmp(name, tblp->name)))
return tblp->procclk;
}
return NULL;
}
/* frequency tables indexed by freq_id */
unsigned long master_axi_freq_tbl[8] = {
26 * CLOCK_1M,
52 * CLOCK_1M,
104 * CLOCK_1M,
156 * CLOCK_1M,
156 * CLOCK_1M,
208 * CLOCK_1M,
312 * CLOCK_1M,
312 * CLOCK_1M
};
unsigned long master_ahb_freq_tbl[8] = {
26 * CLOCK_1M,
52 * CLOCK_1M,
52 * CLOCK_1M,
52 * CLOCK_1M,
78 * CLOCK_1M,
104 * CLOCK_1M,
104 * CLOCK_1M,
156 * CLOCK_1M
};
unsigned long slave_axi_freq_tbl[8] = {
26 * CLOCK_1M,
52 * CLOCK_1M,
78 * CLOCK_1M,
104 * CLOCK_1M,
156 * CLOCK_1M,
156 * CLOCK_1M
};
unsigned long slave_apb_freq_tbl[8] = {
26 * CLOCK_1M,
26 * CLOCK_1M,
39 * CLOCK_1M,
52 * CLOCK_1M,
52 * CLOCK_1M,
78 * CLOCK_1M
};
static struct bus_clk_data bsc1_apb_data = {
.gate = HW_SW_GATE_AUTO(0x0458, 16, 0, 1),
};
static struct bus_clk_data bsc2_apb_data = {
.gate = HW_SW_GATE_AUTO(0x045c, 16, 0, 1),
};
static struct bus_clk_data bsc3_apb_data = {
.gate = HW_SW_GATE_AUTO(0x0484, 16, 0, 1),
};
/* * Master CCU clocks */
static struct peri_clk_data sdio1_data = {
.gate = HW_SW_GATE(0x0358, 18, 2, 3),
.clocks = CLOCKS("ref_crystal",
"var_52m",
"ref_52m",
"var_96m",
"ref_96m"),
.sel = SELECTOR(0x0a28, 0, 3),
.div = DIVIDER(0x0a28, 4, 14),
.trig = TRIGGER(0x0afc, 9),
};
static struct peri_clk_data sdio2_data = {
.gate = HW_SW_GATE(0x035c, 18, 2, 3),
.clocks = CLOCKS("ref_crystal",
"var_52m",
"ref_52m",
"var_96m",
"ref_96m"),
.sel = SELECTOR(0x0a2c, 0, 3),
.div = DIVIDER(0x0a2c, 4, 14),
.trig = TRIGGER(0x0afc, 10),
};
static struct peri_clk_data sdio3_data = {
.gate = HW_SW_GATE(0x0364, 18, 2, 3),
.clocks = CLOCKS("ref_crystal",
"var_52m",
"ref_52m",
"var_96m",
"ref_96m"),
.sel = SELECTOR(0x0a34, 0, 3),
.div = DIVIDER(0x0a34, 4, 14),
.trig = TRIGGER(0x0afc, 12),
};
static struct peri_clk_data sdio4_data = {
.gate = HW_SW_GATE(0x0360, 18, 2, 3),
.clocks = CLOCKS("ref_crystal",
"var_52m",
"ref_52m",
"var_96m",
"ref_96m"),
.sel = SELECTOR(0x0a30, 0, 3),
.div = DIVIDER(0x0a30, 4, 14),
.trig = TRIGGER(0x0afc, 11),
};
static struct peri_clk_data sdio1_sleep_data = {
.clocks = CLOCKS("ref_32k"),
.gate = SW_ONLY_GATE(0x0358, 20, 4),
};
static struct peri_clk_data sdio2_sleep_data = {
.clocks = CLOCKS("ref_32k"),
.gate = SW_ONLY_GATE(0x035c, 20, 4),
};
static struct peri_clk_data sdio3_sleep_data = {
.clocks = CLOCKS("ref_32k"),
.gate = SW_ONLY_GATE(0x0364, 20, 4),
};
static struct peri_clk_data sdio4_sleep_data = {
.clocks = CLOCKS("ref_32k"),
.gate = SW_ONLY_GATE(0x0360, 20, 4),
};
static struct bus_clk_data sdio1_ahb_data = {
.gate = HW_SW_GATE_AUTO(0x0358, 16, 0, 1),
};
static struct bus_clk_data sdio2_ahb_data = {
.gate = HW_SW_GATE_AUTO(0x035c, 16, 0, 1),
};
static struct bus_clk_data sdio3_ahb_data = {
.gate = HW_SW_GATE_AUTO(0x0364, 16, 0, 1),
};
static struct bus_clk_data sdio4_ahb_data = {
.gate = HW_SW_GATE_AUTO(0x0360, 16, 0, 1),
};
/* * Slave CCU clocks */
static struct peri_clk_data bsc1_data = {
.gate = HW_SW_GATE(0x0458, 18, 2, 3),
.clocks = CLOCKS("ref_crystal",
"var_104m",
"ref_104m",
"var_13m",
"ref_13m"),
.sel = SELECTOR(0x0a64, 0, 3),
.trig = TRIGGER(0x0afc, 23),
};
static struct peri_clk_data bsc2_data = {
.gate = HW_SW_GATE(0x045c, 18, 2, 3),
.clocks = CLOCKS("ref_crystal",
"var_104m",
"ref_104m",
"var_13m",
"ref_13m"),
.sel = SELECTOR(0x0a68, 0, 3),
.trig = TRIGGER(0x0afc, 24),
};
static struct peri_clk_data bsc3_data = {
.gate = HW_SW_GATE(0x0484, 18, 2, 3),
.clocks = CLOCKS("ref_crystal",
"var_104m",
"ref_104m",
"var_13m",
"ref_13m"),
.sel = SELECTOR(0x0a84, 0, 3),
.trig = TRIGGER(0x0b00, 2),
};
/*
* CCU clocks
*/
static struct ccu_clock kpm_ccu_clk = {
.clk = {
.name = "kpm_ccu_clk",
.ops = &ccu_clk_ops,
.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
},
.num_policy_masks = 1,
.policy_freq_offset = 0x00000008,
.freq_bit_shift = 8,
.policy_ctl_offset = 0x0000000c,
.policy0_mask_offset = 0x00000010,
.policy1_mask_offset = 0x00000014,
.policy2_mask_offset = 0x00000018,
.policy3_mask_offset = 0x0000001c,
.lvm_en_offset = 0x00000034,
.freq_id = 2,
.freq_tbl = master_axi_freq_tbl,
};
static struct ccu_clock kps_ccu_clk = {
.clk = {
.name = "kps_ccu_clk",
.ops = &ccu_clk_ops,
.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
},
.num_policy_masks = 2,
.policy_freq_offset = 0x00000008,
.freq_bit_shift = 8,
.policy_ctl_offset = 0x0000000c,
.policy0_mask_offset = 0x00000010,
.policy1_mask_offset = 0x00000014,
.policy2_mask_offset = 0x00000018,
.policy3_mask_offset = 0x0000001c,
.policy0_mask2_offset = 0x00000048,
.policy1_mask2_offset = 0x0000004c,
.policy2_mask2_offset = 0x00000050,
.policy3_mask2_offset = 0x00000054,
.lvm_en_offset = 0x00000034,
.freq_id = 2,
.freq_tbl = slave_axi_freq_tbl,
};
/*
* Bus clocks
*/
/* KPM bus clocks */
static struct bus_clock sdio1_ahb_clk = {
.clk = {
.name = "sdio1_ahb_clk",
.parent = &kpm_ccu_clk.clk,
.ops = &bus_clk_ops,
.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
},
.freq_tbl = master_ahb_freq_tbl,
.data = &sdio1_ahb_data,
};
static struct bus_clock sdio2_ahb_clk = {
.clk = {
.name = "sdio2_ahb_clk",
.parent = &kpm_ccu_clk.clk,
.ops = &bus_clk_ops,
.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
},
.freq_tbl = master_ahb_freq_tbl,
.data = &sdio2_ahb_data,
};
static struct bus_clock sdio3_ahb_clk = {
.clk = {
.name = "sdio3_ahb_clk",
.parent = &kpm_ccu_clk.clk,
.ops = &bus_clk_ops,
.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
},
.freq_tbl = master_ahb_freq_tbl,
.data = &sdio3_ahb_data,
};
static struct bus_clock sdio4_ahb_clk = {
.clk = {
.name = "sdio4_ahb_clk",
.parent = &kpm_ccu_clk.clk,
.ops = &bus_clk_ops,
.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
},
.freq_tbl = master_ahb_freq_tbl,
.data = &sdio4_ahb_data,
};
static struct bus_clock bsc1_apb_clk = {
.clk = {
.name = "bsc1_apb_clk",
.parent = &kps_ccu_clk.clk,
.ops = &bus_clk_ops,
.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
},
.freq_tbl = slave_apb_freq_tbl,
.data = &bsc1_apb_data,
};
static struct bus_clock bsc2_apb_clk = {
.clk = {
.name = "bsc2_apb_clk",
.parent = &kps_ccu_clk.clk,
.ops = &bus_clk_ops,
.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
},
.freq_tbl = slave_apb_freq_tbl,
.data = &bsc2_apb_data,
};
static struct bus_clock bsc3_apb_clk = {
.clk = {
.name = "bsc3_apb_clk",
.parent = &kps_ccu_clk.clk,
.ops = &bus_clk_ops,
.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
},
.freq_tbl = slave_apb_freq_tbl,
.data = &bsc3_apb_data,
};
/* KPM peripheral */
static struct peri_clock sdio1_clk = {
.clk = {
.name = "sdio1_clk",
.parent = &ref_52m.clk,
.ops = &peri_clk_ops,
.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
},
.data = &sdio1_data,
};
static struct peri_clock sdio2_clk = {
.clk = {
.name = "sdio2_clk",
.parent = &ref_52m.clk,
.ops = &peri_clk_ops,
.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
},
.data = &sdio2_data,
};
static struct peri_clock sdio3_clk = {
.clk = {
.name = "sdio3_clk",
.parent = &ref_52m.clk,
.ops = &peri_clk_ops,
.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
},
.data = &sdio3_data,
};
static struct peri_clock sdio4_clk = {
.clk = {
.name = "sdio4_clk",
.parent = &ref_52m.clk,
.ops = &peri_clk_ops,
.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
},
.data = &sdio4_data,
};
static struct peri_clock sdio1_sleep_clk = {
.clk = {
.name = "sdio1_sleep_clk",
.parent = &kpm_ccu_clk.clk,
.ops = &bus_clk_ops,
.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
},
.data = &sdio1_sleep_data,
};
static struct peri_clock sdio2_sleep_clk = {
.clk = {
.name = "sdio2_sleep_clk",
.parent = &kpm_ccu_clk.clk,
.ops = &bus_clk_ops,
.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
},
.data = &sdio2_sleep_data,
};
static struct peri_clock sdio3_sleep_clk = {
.clk = {
.name = "sdio3_sleep_clk",
.parent = &kpm_ccu_clk.clk,
.ops = &bus_clk_ops,
.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
},
.data = &sdio3_sleep_data,
};
static struct peri_clock sdio4_sleep_clk = {
.clk = {
.name = "sdio4_sleep_clk",
.parent = &kpm_ccu_clk.clk,
.ops = &bus_clk_ops,
.ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
},
.data = &sdio4_sleep_data,
};
/* KPS peripheral clock */
static struct peri_clock bsc1_clk = {
.clk = {
.name = "bsc1_clk",
.parent = &ref_13m.clk,
.rate = 13 * CLOCK_1M,
.div = 1,
.ops = &peri_clk_ops,
.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
},
.data = &bsc1_data,
};
static struct peri_clock bsc2_clk = {
.clk = {
.name = "bsc2_clk",
.parent = &ref_13m.clk,
.rate = 13 * CLOCK_1M,
.div = 1,
.ops = &peri_clk_ops,
.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
},
.data = &bsc2_data,
};
static struct peri_clock bsc3_clk = {
.clk = {
.name = "bsc3_clk",
.parent = &ref_13m.clk,
.rate = 13 * CLOCK_1M,
.div = 1,
.ops = &peri_clk_ops,
.ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
},
.data = &bsc3_data,
};
/* public table for registering clocks */
struct clk_lookup arch_clk_tbl[] = {
/* Peripheral clocks */
CLK_LK(sdio1),
CLK_LK(sdio2),
CLK_LK(sdio3),
CLK_LK(sdio4),
CLK_LK(sdio1_sleep),
CLK_LK(sdio2_sleep),
CLK_LK(sdio3_sleep),
CLK_LK(sdio4_sleep),
CLK_LK(bsc1),
CLK_LK(bsc2),
CLK_LK(bsc3),
/* Bus clocks */
CLK_LK(sdio1_ahb),
CLK_LK(sdio2_ahb),
CLK_LK(sdio3_ahb),
CLK_LK(sdio4_ahb),
CLK_LK(bsc1_apb),
CLK_LK(bsc2_apb),
CLK_LK(bsc3_apb),
};
/* public array size */
unsigned int arch_clk_tbl_array_size = ARRAY_SIZE(arch_clk_tbl);

View file

@ -0,0 +1,52 @@
/*
* Copyright 2013 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <asm/arch/sysmap.h>
#include <asm/kona-common/clk.h>
#include "clk-core.h"
/* Enable appropriate clocks for a BSC/I2C port */
int clk_bsc_enable(void *base)
{
int ret;
char *bscstr, *apbstr;
switch ((u32) base) {
case PMU_BSC_BASE_ADDR:
/* PMU clock is always enabled */
return 0;
case BSC1_BASE_ADDR:
bscstr = "bsc1_clk";
apbstr = "bsc1_apb_clk";
break;
case BSC2_BASE_ADDR:
bscstr = "bsc2_clk";
apbstr = "bsc2_apb_clk";
break;
case BSC3_BASE_ADDR:
bscstr = "bsc3_clk";
apbstr = "bsc3_apb_clk";
break;
default:
printf("%s: base 0x%p not found\n", __func__, base);
return -EINVAL;
}
/* Note that the bus clock must be enabled first */
ret = clk_get_and_enable(apbstr);
if (ret)
return ret;
ret = clk_get_and_enable(bscstr);
if (ret)
return ret;
return 0;
}

View file

@ -0,0 +1,513 @@
/*
* Copyright 2013 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
/*
*
* bcm281xx architecture clock framework
*
*/
#include <common.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <bitfield.h>
#include <asm/arch/sysmap.h>
#include <asm/kona-common/clk.h>
#include "clk-core.h"
#define CLK_WR_ACCESS_PASSWORD 0x00a5a501
#define WR_ACCESS_OFFSET 0 /* common to all clock blocks */
#define POLICY_CTL_GO 1 /* Load and refresh policy masks */
#define POLICY_CTL_GO_ATL 4 /* Active Load */
/* Helper function */
int clk_get_and_enable(char *clkstr)
{
int ret = 0;
struct clk *c;
debug("%s: %s\n", __func__, clkstr);
c = clk_get(clkstr);
if (c) {
ret = clk_enable(c);
if (ret)
return ret;
} else {
printf("%s: Couldn't find %s\n", __func__, clkstr);
return -EINVAL;
}
return ret;
}
/*
* Poll a register in a CCU's address space, returning when the
* specified bit in that register's value is set (or clear). Delay
* a microsecond after each read of the register. Returns true if
* successful, or false if we gave up trying.
*
* Caller must ensure the CCU lock is held.
*/
#define CLK_GATE_DELAY_USEC 2000
static inline int wait_bit(void *base, u32 offset, u32 bit, bool want)
{
unsigned int tries;
u32 bit_mask = 1 << bit;
for (tries = 0; tries < CLK_GATE_DELAY_USEC; tries++) {
u32 val;
bool bit_val;
val = readl(base + offset);
bit_val = (val & bit_mask) ? 1 : 0;
if (bit_val == want)
return 0; /* success */
udelay(1);
}
debug("%s: timeout on addr 0x%p, waiting for bit %d to go to %d\n",
__func__, base + offset, bit, want);
return -ETIMEDOUT;
}
/* Enable a peripheral clock */
static int peri_clk_enable(struct clk *c, int enable)
{
int ret = 0;
u32 reg;
struct peri_clock *peri_clk = to_peri_clk(c);
struct peri_clk_data *cd = peri_clk->data;
struct bcm_clk_gate *gate = &cd->gate;
void *base = (void *)c->ccu_clk_mgr_base;
debug("%s: %s\n", __func__, c->name);
clk_get_rate(c); /* Make sure rate and sel are filled in */
/* enable access */
writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
if (enable) {
debug("%s %s set rate %lu div %lu sel %d parent %lu\n",
__func__, c->name, c->rate, c->div, c->sel,
c->parent->rate);
/*
* clkgate - only software controllable gates are
* supported by u-boot which includes all clocks
* that matter. This avoids bringing in a lot of extra
* complexity as done in the kernel framework.
*/
if (gate_exists(gate)) {
reg = readl(base + cd->gate.offset);
reg |= (1 << cd->gate.en_bit);
writel(reg, base + cd->gate.offset);
}
/* div and pll select */
if (divider_exists(&cd->div)) {
reg = readl(base + cd->div.offset);
bitfield_replace(reg, cd->div.shift, cd->div.width,
c->div - 1);
writel(reg, base + cd->div.offset);
}
/* frequency selector */
if (selector_exists(&cd->sel)) {
reg = readl(base + cd->sel.offset);
bitfield_replace(reg, cd->sel.shift, cd->sel.width,
c->sel);
writel(reg, base + cd->sel.offset);
}
/* trigger */
if (trigger_exists(&cd->trig)) {
writel((1 << cd->trig.bit), base + cd->trig.offset);
/* wait for trigger status bit to go to 0 */
ret = wait_bit(base, cd->trig.offset, cd->trig.bit, 0);
if (ret)
return ret;
}
/* wait for running (status_bit = 1) */
ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 1);
if (ret)
return ret;
} else {
debug("%s disable clock %s\n", __func__, c->name);
/* clkgate */
reg = readl(base + cd->gate.offset);
reg &= ~(1 << cd->gate.en_bit);
writel(reg, base + cd->gate.offset);
/* wait for stop (status_bit = 0) */
ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 0);
}
/* disable access */
writel(0, base + WR_ACCESS_OFFSET);
return ret;
}
/* Set the rate of a peripheral clock */
static int peri_clk_set_rate(struct clk *c, unsigned long rate)
{
int ret = 0;
int i;
unsigned long diff;
unsigned long new_rate = 0, div = 1;
struct peri_clock *peri_clk = to_peri_clk(c);
struct peri_clk_data *cd = peri_clk->data;
const char **clock;
debug("%s: %s\n", __func__, c->name);
diff = rate;
i = 0;
for (clock = cd->clocks; *clock; clock++, i++) {
struct refclk *ref = refclk_str_to_clk(*clock);
if (!ref) {
printf("%s: Lookup of %s failed\n", __func__, *clock);
return -EINVAL;
}
/* round to the new rate */
div = ref->clk.rate / rate;
if (div == 0)
div = 1;
new_rate = ref->clk.rate / div;
/* get the min diff */
if (abs(new_rate - rate) < diff) {
diff = abs(new_rate - rate);
c->sel = i;
c->parent = &ref->clk;
c->rate = new_rate;
c->div = div;
}
}
debug("%s %s set rate %lu div %lu sel %d parent %lu\n", __func__,
c->name, c->rate, c->div, c->sel, c->parent->rate);
return ret;
}
/* Get the rate of a peripheral clock */
static unsigned long peri_clk_get_rate(struct clk *c)
{
struct peri_clock *peri_clk = to_peri_clk(c);
struct peri_clk_data *cd = peri_clk->data;
void *base = (void *)c->ccu_clk_mgr_base;
int div = 1;
const char **clock;
struct refclk *ref;
u32 reg;
debug("%s: %s\n", __func__, c->name);
if (selector_exists(&cd->sel)) {
reg = readl(base + cd->sel.offset);
c->sel = bitfield_extract(reg, cd->sel.shift, cd->sel.width);
} else {
/*
* For peri clocks that don't have a selector, the single
* reference clock will always exist at index 0.
*/
c->sel = 0;
}
if (divider_exists(&cd->div)) {
reg = readl(base + cd->div.offset);
div = bitfield_extract(reg, cd->div.shift, cd->div.width);
div += 1;
}
clock = cd->clocks;
ref = refclk_str_to_clk(clock[c->sel]);
if (!ref) {
printf("%s: Can't lookup %s\n", __func__, clock[c->sel]);
return 0;
}
c->parent = &ref->clk;
c->div = div;
c->rate = c->parent->rate / c->div;
debug("%s parent rate %lu div %d sel %d rate %lu\n", __func__,
c->parent->rate, div, c->sel, c->rate);
return c->rate;
}
/* Peripheral clock operations */
struct clk_ops peri_clk_ops = {
.enable = peri_clk_enable,
.set_rate = peri_clk_set_rate,
.get_rate = peri_clk_get_rate,
};
/* Enable a CCU clock */
static int ccu_clk_enable(struct clk *c, int enable)
{
struct ccu_clock *ccu_clk = to_ccu_clk(c);
void *base = (void *)c->ccu_clk_mgr_base;
int ret = 0;
u32 reg;
debug("%s: %s\n", __func__, c->name);
if (!enable)
return -EINVAL; /* CCU clock cannot shutdown */
/* enable access */
writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
/* config enable for policy engine */
writel(1, base + ccu_clk->lvm_en_offset);
/* wait for bit to go to 0 */
ret = wait_bit(base, ccu_clk->lvm_en_offset, 0, 0);
if (ret)
return ret;
/* freq ID */
if (!ccu_clk->freq_bit_shift)
ccu_clk->freq_bit_shift = 8;
/* Set frequency id for each of the 4 policies */
reg = ccu_clk->freq_id |
(ccu_clk->freq_id << (ccu_clk->freq_bit_shift)) |
(ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 2)) |
(ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 3));
writel(reg, base + ccu_clk->policy_freq_offset);
/* enable all clock mask */
writel(0x7fffffff, base + ccu_clk->policy0_mask_offset);
writel(0x7fffffff, base + ccu_clk->policy1_mask_offset);
writel(0x7fffffff, base + ccu_clk->policy2_mask_offset);
writel(0x7fffffff, base + ccu_clk->policy3_mask_offset);
if (ccu_clk->num_policy_masks == 2) {
writel(0x7fffffff, base + ccu_clk->policy0_mask2_offset);
writel(0x7fffffff, base + ccu_clk->policy1_mask2_offset);
writel(0x7fffffff, base + ccu_clk->policy2_mask2_offset);
writel(0x7fffffff, base + ccu_clk->policy3_mask2_offset);
}
/* start policy engine */
reg = readl(base + ccu_clk->policy_ctl_offset);
reg |= (POLICY_CTL_GO + POLICY_CTL_GO_ATL);
writel(reg, base + ccu_clk->policy_ctl_offset);
/* wait till started */
ret = wait_bit(base, ccu_clk->policy_ctl_offset, 0, 0);
if (ret)
return ret;
/* disable access */
writel(0, base + WR_ACCESS_OFFSET);
return ret;
}
/* Get the CCU clock rate */
static unsigned long ccu_clk_get_rate(struct clk *c)
{
struct ccu_clock *ccu_clk = to_ccu_clk(c);
debug("%s: %s\n", __func__, c->name);
c->rate = ccu_clk->freq_tbl[ccu_clk->freq_id];
return c->rate;
}
/* CCU clock operations */
struct clk_ops ccu_clk_ops = {
.enable = ccu_clk_enable,
.get_rate = ccu_clk_get_rate,
};
/* Enable a bus clock */
static int bus_clk_enable(struct clk *c, int enable)
{
struct bus_clock *bus_clk = to_bus_clk(c);
struct bus_clk_data *cd = bus_clk->data;
void *base = (void *)c->ccu_clk_mgr_base;
int ret = 0;
u32 reg;
debug("%s: %s\n", __func__, c->name);
/* enable access */
writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
/* enable gating */
reg = readl(base + cd->gate.offset);
if (!!(reg & (1 << cd->gate.status_bit)) == !!enable)
debug("%s already %s\n", c->name,
enable ? "enabled" : "disabled");
else {
int want = (enable) ? 1 : 0;
reg |= (1 << cd->gate.hw_sw_sel_bit);
if (enable)
reg |= (1 << cd->gate.en_bit);
else
reg &= ~(1 << cd->gate.en_bit);
writel(reg, base + cd->gate.offset);
ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit,
want);
if (ret)
return ret;
}
/* disable access */
writel(0, base + WR_ACCESS_OFFSET);
return ret;
}
/* Get the rate of a bus clock */
static unsigned long bus_clk_get_rate(struct clk *c)
{
struct bus_clock *bus_clk = to_bus_clk(c);
struct ccu_clock *ccu_clk;
debug("%s: %s\n", __func__, c->name);
ccu_clk = to_ccu_clk(c->parent);
c->rate = bus_clk->freq_tbl[ccu_clk->freq_id];
c->div = ccu_clk->freq_tbl[ccu_clk->freq_id] / c->rate;
return c->rate;
}
/* Bus clock operations */
struct clk_ops bus_clk_ops = {
.enable = bus_clk_enable,
.get_rate = bus_clk_get_rate,
};
/* Enable a reference clock */
static int ref_clk_enable(struct clk *c, int enable)
{
debug("%s: %s\n", __func__, c->name);
return 0;
}
/* Reference clock operations */
struct clk_ops ref_clk_ops = {
.enable = ref_clk_enable,
};
/*
* clk.h implementation follows
*/
/* Initialize the clock framework */
int clk_init(void)
{
debug("%s:\n", __func__);
return 0;
}
/* Get a clock handle, give a name string */
struct clk *clk_get(const char *con_id)
{
int i;
struct clk_lookup *clk_tblp;
debug("%s: %s\n", __func__, con_id);
clk_tblp = arch_clk_tbl;
for (i = 0; i < arch_clk_tbl_array_size; i++, clk_tblp++) {
if (clk_tblp->con_id) {
if (!con_id || strcmp(clk_tblp->con_id, con_id))
continue;
return clk_tblp->clk;
}
}
return NULL;
}
/* Enable a clock */
int clk_enable(struct clk *c)
{
int ret = 0;
debug("%s: %s\n", __func__, c->name);
if (!c->ops || !c->ops->enable)
return -1;
/* enable parent clock first */
if (c->parent)
ret = clk_enable(c->parent);
if (ret)
return ret;
if (!c->use_cnt) {
c->use_cnt++;
ret = c->ops->enable(c, 1);
}
return ret;
}
/* Disable a clock */
void clk_disable(struct clk *c)
{
debug("%s: %s\n", __func__, c->name);
if (!c->ops || !c->ops->enable)
return;
if (c->use_cnt) {
c->use_cnt--;
c->ops->enable(c, 0);
}
/* disable parent */
if (c->parent)
clk_disable(c->parent);
}
/* Get the clock rate */
unsigned long clk_get_rate(struct clk *c)
{
unsigned long rate;
debug("%s: %s\n", __func__, c->name);
if (!c || !c->ops || !c->ops->get_rate)
return 0;
rate = c->ops->get_rate(c);
debug("%s: rate = %ld\n", __func__, rate);
return rate;
}
/* Set the clock rate */
int clk_set_rate(struct clk *c, unsigned long rate)
{
int ret;
debug("%s: %s rate=%ld\n", __func__, c->name, rate);
if (!c || !c->ops || !c->ops->set_rate)
return -EINVAL;
if (c->use_cnt)
return -EINVAL;
ret = c->ops->set_rate(c, rate);
return ret;
}
/* Not required for this arch */
/*
long clk_round_rate(struct clk *clk, unsigned long rate);
int clk_set_parent(struct clk *clk, struct clk *parent);
struct clk *clk_get_parent(struct clk *clk);
*/

View file

@ -0,0 +1,495 @@
/*
* Copyright 2013 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <linux/stddef.h>
#ifdef CONFIG_CLK_DEBUG
#undef writel
#undef readl
static inline void writel(u32 val, void *addr)
{
printf("Write [0x%p] = 0x%08x\n", addr, val);
*(u32 *)addr = val;
}
static inline u32 readl(void *addr)
{
u32 val = *(u32 *)addr;
printf("Read [0x%p] = 0x%08x\n", addr, val);
return val;
}
#endif
struct clk;
struct clk_lookup {
const char *dev_id;
const char *con_id;
struct clk *clk;
};
extern struct clk_lookup arch_clk_tbl[];
extern unsigned int arch_clk_tbl_array_size;
/**
* struct clk_ops - standard clock operations
* @enable: enable/disable clock, see clk_enable() and clk_disable()
* @set_rate: set the clock rate, see clk_set_rate().
* @get_rate: get the clock rate, see clk_get_rate().
* @round_rate: round a given clock rate, see clk_round_rate().
* @set_parent: set the clock's parent, see clk_set_parent().
*
* Group the common clock implementations together so that we
* don't have to keep setting the same fiels again. We leave
* enable in struct clk.
*
*/
struct clk_ops {
int (*enable) (struct clk *c, int enable);
int (*set_rate) (struct clk *c, unsigned long rate);
unsigned long (*get_rate) (struct clk *c);
unsigned long (*round_rate) (struct clk *c, unsigned long rate);
int (*set_parent) (struct clk *c, struct clk *parent);
};
struct clk {
struct clk *parent;
const char *name;
int use_cnt;
unsigned long rate; /* in HZ */
/* programmable divider. 0 means fixed ratio to parent clock */
unsigned long div;
struct clk_src *src;
struct clk_ops *ops;
unsigned long ccu_clk_mgr_base;
int sel;
};
struct refclk *refclk_str_to_clk(const char *name);
#define U8_MAX ((u8)~0U)
#define U32_MAX ((u32)~0U)
#define U64_MAX ((u64)~0U)
/* The common clock framework uses u8 to represent a parent index */
#define PARENT_COUNT_MAX ((u32)U8_MAX)
#define BAD_CLK_INDEX U8_MAX /* Can't ever be valid */
#define BAD_CLK_NAME ((const char *)-1)
#define BAD_SCALED_DIV_VALUE U64_MAX
/*
* Utility macros for object flag management. If possible, flags
* should be defined such that 0 is the desired default value.
*/
#define FLAG(type, flag) BCM_CLK_ ## type ## _FLAGS_ ## flag
#define FLAG_SET(obj, type, flag) ((obj)->flags |= FLAG(type, flag))
#define FLAG_CLEAR(obj, type, flag) ((obj)->flags &= ~(FLAG(type, flag)))
#define FLAG_FLIP(obj, type, flag) ((obj)->flags ^= FLAG(type, flag))
#define FLAG_TEST(obj, type, flag) (!!((obj)->flags & FLAG(type, flag)))
/* Clock field state tests */
#define gate_exists(gate) FLAG_TEST(gate, GATE, EXISTS)
#define gate_is_enabled(gate) FLAG_TEST(gate, GATE, ENABLED)
#define gate_is_hw_controllable(gate) FLAG_TEST(gate, GATE, HW)
#define gate_is_sw_controllable(gate) FLAG_TEST(gate, GATE, SW)
#define gate_is_sw_managed(gate) FLAG_TEST(gate, GATE, SW_MANAGED)
#define gate_is_no_disable(gate) FLAG_TEST(gate, GATE, NO_DISABLE)
#define gate_flip_enabled(gate) FLAG_FLIP(gate, GATE, ENABLED)
#define divider_exists(div) FLAG_TEST(div, DIV, EXISTS)
#define divider_is_fixed(div) FLAG_TEST(div, DIV, FIXED)
#define divider_has_fraction(div) (!divider_is_fixed(div) && \
(div)->frac_width > 0)
#define selector_exists(sel) ((sel)->width != 0)
#define trigger_exists(trig) FLAG_TEST(trig, TRIG, EXISTS)
/* Clock type, used to tell common block what it's part of */
enum bcm_clk_type {
bcm_clk_none, /* undefined clock type */
bcm_clk_bus,
bcm_clk_core,
bcm_clk_peri
};
/*
* Gating control and status is managed by a 32-bit gate register.
*
* There are several types of gating available:
* - (no gate)
* A clock with no gate is assumed to be always enabled.
* - hardware-only gating (auto-gating)
* Enabling or disabling clocks with this type of gate is
* managed automatically by the hardware. Such clocks can be
* considered by the software to be enabled. The current status
* of auto-gated clocks can be read from the gate status bit.
* - software-only gating
* Auto-gating is not available for this type of clock.
* Instead, software manages whether it's enabled by setting or
* clearing the enable bit. The current gate status of a gate
* under software control can be read from the gate status bit.
* To ensure a change to the gating status is complete, the
* status bit can be polled to verify that the gate has entered
* the desired state.
* - selectable hardware or software gating
* Gating for this type of clock can be configured to be either
* under software or hardware control. Which type is in use is
* determined by the hw_sw_sel bit of the gate register.
*/
struct bcm_clk_gate {
u32 offset; /* gate register offset */
u32 status_bit; /* 0: gate is disabled; 0: gatge is enabled */
u32 en_bit; /* 0: disable; 1: enable */
u32 hw_sw_sel_bit; /* 0: hardware gating; 1: software gating */
u32 flags; /* BCM_CLK_GATE_FLAGS_* below */
};
/*
* Gate flags:
* HW means this gate can be auto-gated
* SW means the state of this gate can be software controlled
* NO_DISABLE means this gate is (only) enabled if under software control
* SW_MANAGED means the status of this gate is under software control
* ENABLED means this software-managed gate is *supposed* to be enabled
*/
#define BCM_CLK_GATE_FLAGS_EXISTS ((u32)1 << 0) /* Gate is valid */
#define BCM_CLK_GATE_FLAGS_HW ((u32)1 << 1) /* Can auto-gate */
#define BCM_CLK_GATE_FLAGS_SW ((u32)1 << 2) /* Software control */
#define BCM_CLK_GATE_FLAGS_NO_DISABLE ((u32)1 << 3) /* HW or enabled */
#define BCM_CLK_GATE_FLAGS_SW_MANAGED ((u32)1 << 4) /* SW now in control */
#define BCM_CLK_GATE_FLAGS_ENABLED ((u32)1 << 5) /* If SW_MANAGED */
/*
* Gate initialization macros.
*
* Any gate initially under software control will be enabled.
*/
/* A hardware/software gate initially under software control */
#define HW_SW_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \
{ \
.offset = (_offset), \
.status_bit = (_status_bit), \
.en_bit = (_en_bit), \
.hw_sw_sel_bit = (_hw_sw_sel_bit), \
.flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \
FLAG(GATE, SW_MANAGED)|FLAG(GATE, ENABLED)| \
FLAG(GATE, EXISTS), \
}
/* A hardware/software gate initially under hardware control */
#define HW_SW_GATE_AUTO(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \
{ \
.offset = (_offset), \
.status_bit = (_status_bit), \
.en_bit = (_en_bit), \
.hw_sw_sel_bit = (_hw_sw_sel_bit), \
.flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \
FLAG(GATE, EXISTS), \
}
/* A hardware-or-enabled gate (enabled if not under hardware control) */
#define HW_ENABLE_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \
{ \
.offset = (_offset), \
.status_bit = (_status_bit), \
.en_bit = (_en_bit), \
.hw_sw_sel_bit = (_hw_sw_sel_bit), \
.flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \
FLAG(GATE, NO_DISABLE)|FLAG(GATE, EXISTS), \
}
/* A software-only gate */
#define SW_ONLY_GATE(_offset, _status_bit, _en_bit) \
{ \
.offset = (_offset), \
.status_bit = (_status_bit), \
.en_bit = (_en_bit), \
.flags = FLAG(GATE, SW)|FLAG(GATE, SW_MANAGED)| \
FLAG(GATE, ENABLED)|FLAG(GATE, EXISTS), \
}
/* A hardware-only gate */
#define HW_ONLY_GATE(_offset, _status_bit) \
{ \
.offset = (_offset), \
.status_bit = (_status_bit), \
.flags = FLAG(GATE, HW)|FLAG(GATE, EXISTS), \
}
/*
* Each clock can have zero, one, or two dividers which change the
* output rate of the clock. Each divider can be either fixed or
* variable. If there are two dividers, they are the "pre-divider"
* and the "regular" or "downstream" divider. If there is only one,
* there is no pre-divider.
*
* A fixed divider is any non-zero (positive) value, and it
* indicates how the input rate is affected by the divider.
*
* The value of a variable divider is maintained in a sub-field of a
* 32-bit divider register. The position of the field in the
* register is defined by its offset and width. The value recorded
* in this field is always 1 less than the value it represents.
*
* In addition, a variable divider can indicate that some subset
* of its bits represent a "fractional" part of the divider. Such
* bits comprise the low-order portion of the divider field, and can
* be viewed as representing the portion of the divider that lies to
* the right of the decimal point. Most variable dividers have zero
* fractional bits. Variable dividers with non-zero fraction width
* still record a value 1 less than the value they represent; the
* added 1 does *not* affect the low-order bit in this case, it
* affects the bits above the fractional part only. (Often in this
* code a divider field value is distinguished from the value it
* represents by referring to the latter as a "divisor".)
*
* In order to avoid dealing with fractions, divider arithmetic is
* performed using "scaled" values. A scaled value is one that's
* been left-shifted by the fractional width of a divider. Dividing
* a scaled value by a scaled divisor produces the desired quotient
* without loss of precision and without any other special handling
* for fractions.
*
* The recorded value of a variable divider can be modified. To
* modify either divider (or both), a clock must be enabled (i.e.,
* using its gate). In addition, a trigger register (described
* below) must be used to commit the change, and polled to verify
* the change is complete.
*/
struct bcm_clk_div {
union {
struct { /* variable divider */
u32 offset; /* divider register offset */
u32 shift; /* field shift */
u32 width; /* field width */
u32 frac_width; /* field fraction width */
u64 scaled_div; /* scaled divider value */
};
u32 fixed; /* non-zero fixed divider value */
};
u32 flags; /* BCM_CLK_DIV_FLAGS_* below */
};
/*
* Divider flags:
* EXISTS means this divider exists
* FIXED means it is a fixed-rate divider
*/
#define BCM_CLK_DIV_FLAGS_EXISTS ((u32)1 << 0) /* Divider is valid */
#define BCM_CLK_DIV_FLAGS_FIXED ((u32)1 << 1) /* Fixed-value */
/* Divider initialization macros */
/* A fixed (non-zero) divider */
#define FIXED_DIVIDER(_value) \
{ \
.fixed = (_value), \
.flags = FLAG(DIV, EXISTS)|FLAG(DIV, FIXED), \
}
/* A divider with an integral divisor */
#define DIVIDER(_offset, _shift, _width) \
{ \
.offset = (_offset), \
.shift = (_shift), \
.width = (_width), \
.scaled_div = BAD_SCALED_DIV_VALUE, \
.flags = FLAG(DIV, EXISTS), \
}
/* A divider whose divisor has an integer and fractional part */
#define FRAC_DIVIDER(_offset, _shift, _width, _frac_width) \
{ \
.offset = (_offset), \
.shift = (_shift), \
.width = (_width), \
.frac_width = (_frac_width), \
.scaled_div = BAD_SCALED_DIV_VALUE, \
.flags = FLAG(DIV, EXISTS), \
}
/*
* Clocks may have multiple "parent" clocks. If there is more than
* one, a selector must be specified to define which of the parent
* clocks is currently in use. The selected clock is indicated in a
* sub-field of a 32-bit selector register. The range of
* representable selector values typically exceeds the number of
* available parent clocks. Occasionally the reset value of a
* selector field is explicitly set to a (specific) value that does
* not correspond to a defined input clock.
*
* We register all known parent clocks with the common clock code
* using a packed array (i.e., no empty slots) of (parent) clock
* names, and refer to them later using indexes into that array.
* We maintain an array of selector values indexed by common clock
* index values in order to map between these common clock indexes
* and the selector values used by the hardware.
*
* Like dividers, a selector can be modified, but to do so a clock
* must be enabled, and a trigger must be used to commit the change.
*/
struct bcm_clk_sel {
u32 offset; /* selector register offset */
u32 shift; /* field shift */
u32 width; /* field width */
u32 parent_count; /* number of entries in parent_sel[] */
u32 *parent_sel; /* array of parent selector values */
u8 clk_index; /* current selected index in parent_sel[] */
};
/* Selector initialization macro */
#define SELECTOR(_offset, _shift, _width) \
{ \
.offset = (_offset), \
.shift = (_shift), \
.width = (_width), \
.clk_index = BAD_CLK_INDEX, \
}
/*
* Making changes to a variable divider or a selector for a clock
* requires the use of a trigger. A trigger is defined by a single
* bit within a register. To signal a change, a 1 is written into
* that bit. To determine when the change has been completed, that
* trigger bit is polled; the read value will be 1 while the change
* is in progress, and 0 when it is complete.
*
* Occasionally a clock will have more than one trigger. In this
* case, the "pre-trigger" will be used when changing a clock's
* selector and/or its pre-divider.
*/
struct bcm_clk_trig {
u32 offset; /* trigger register offset */
u32 bit; /* trigger bit */
u32 flags; /* BCM_CLK_TRIG_FLAGS_* below */
};
/*
* Trigger flags:
* EXISTS means this trigger exists
*/
#define BCM_CLK_TRIG_FLAGS_EXISTS ((u32)1 << 0) /* Trigger is valid */
/* Trigger initialization macro */
#define TRIGGER(_offset, _bit) \
{ \
.offset = (_offset), \
.bit = (_bit), \
.flags = FLAG(TRIG, EXISTS), \
}
struct bus_clk_data {
struct bcm_clk_gate gate;
};
struct core_clk_data {
struct bcm_clk_gate gate;
};
struct peri_clk_data {
struct bcm_clk_gate gate;
struct bcm_clk_trig pre_trig;
struct bcm_clk_div pre_div;
struct bcm_clk_trig trig;
struct bcm_clk_div div;
struct bcm_clk_sel sel;
const char *clocks[]; /* must be last; use CLOCKS() to declare */
};
#define CLOCKS(...) { __VA_ARGS__, NULL, }
#define NO_CLOCKS { NULL, } /* Must use of no parent clocks */
struct refclk {
struct clk clk;
};
struct peri_clock {
struct clk clk;
struct peri_clk_data *data;
};
struct ccu_clock {
struct clk clk;
int num_policy_masks;
unsigned long policy_freq_offset;
int freq_bit_shift; /* 8 for most CCUs */
unsigned long policy_ctl_offset;
unsigned long policy0_mask_offset;
unsigned long policy1_mask_offset;
unsigned long policy2_mask_offset;
unsigned long policy3_mask_offset;
unsigned long policy0_mask2_offset;
unsigned long policy1_mask2_offset;
unsigned long policy2_mask2_offset;
unsigned long policy3_mask2_offset;
unsigned long lvm_en_offset;
int freq_id;
unsigned long *freq_tbl;
};
struct bus_clock {
struct clk clk;
struct bus_clk_data *data;
unsigned long *freq_tbl;
};
struct ref_clock {
struct clk clk;
};
static inline int is_same_clock(struct clk *a, struct clk *b)
{
return (a == b);
}
#define to_clk(p) (&((p)->clk))
#define name_to_clk(name) (&((name##_clk).clk))
/* declare a struct clk_lookup */
#define CLK_LK(name) \
{.con_id = __stringify(name##_clk), .clk = name_to_clk(name),}
static inline struct refclk *to_refclk(struct clk *clock)
{
return container_of(clock, struct refclk, clk);
}
static inline struct peri_clock *to_peri_clk(struct clk *clock)
{
return container_of(clock, struct peri_clock, clk);
}
static inline struct ccu_clock *to_ccu_clk(struct clk *clock)
{
return container_of(clock, struct ccu_clock, clk);
}
static inline struct bus_clock *to_bus_clk(struct clk *clock)
{
return container_of(clock, struct bus_clock, clk);
}
static inline struct ref_clock *to_ref_clk(struct clk *clock)
{
return container_of(clock, struct ref_clock, clk);
}
extern struct clk_ops peri_clk_ops;
extern struct clk_ops ccu_clk_ops;
extern struct clk_ops bus_clk_ops;
extern struct clk_ops ref_clk_ops;
extern int clk_get_and_enable(char *clkstr);

View file

@ -0,0 +1,73 @@
/*
* Copyright 2013 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <asm/arch/sysmap.h>
#include <asm/kona-common/clk.h>
#include "clk-core.h"
/* Enable appropriate clocks for an SDIO port */
int clk_sdio_enable(void *base, u32 rate, u32 *actual_ratep)
{
int ret;
struct clk *c;
char *clkstr;
char *slpstr;
char *ahbstr;
switch ((u32) base) {
case CONFIG_SYS_SDIO_BASE0:
clkstr = CONFIG_SYS_SDIO0 "_clk";
ahbstr = CONFIG_SYS_SDIO0 "_ahb_clk";
slpstr = CONFIG_SYS_SDIO0 "_sleep_clk";
break;
case CONFIG_SYS_SDIO_BASE1:
clkstr = CONFIG_SYS_SDIO1 "_clk";
ahbstr = CONFIG_SYS_SDIO1 "_ahb_clk";
slpstr = CONFIG_SYS_SDIO1 "_sleep_clk";
break;
case CONFIG_SYS_SDIO_BASE2:
clkstr = CONFIG_SYS_SDIO2 "_clk";
ahbstr = CONFIG_SYS_SDIO2 "_ahb_clk";
slpstr = CONFIG_SYS_SDIO2 "_sleep_clk";
break;
case CONFIG_SYS_SDIO_BASE3:
clkstr = CONFIG_SYS_SDIO3 "_clk";
ahbstr = CONFIG_SYS_SDIO3 "_ahb_clk";
slpstr = CONFIG_SYS_SDIO3 "_sleep_clk";
break;
default:
printf("%s: base 0x%p not found\n", __func__, base);
return -EINVAL;
}
ret = clk_get_and_enable(ahbstr);
if (ret)
return ret;
ret = clk_get_and_enable(slpstr);
if (ret)
return ret;
c = clk_get(clkstr);
if (c) {
ret = clk_set_rate(c, rate);
if (ret)
return ret;
ret = clk_enable(c);
if (ret)
return ret;
} else {
printf("%s: Couldn't find %s\n", __func__, clkstr);
return -EINVAL;
}
*actual_ratep = rate;
return 0;
}

View file

@ -0,0 +1,27 @@
/*
* Copyright 2013 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/sysmap.h>
#define EN_MASK 0x08000000 /* Enable timer */
#define SRSTEN_MASK 0x04000000 /* Enable soft reset */
#define CLKS_SHIFT 20 /* Clock period shift */
#define LD_SHIFT 0 /* Reload value shift */
void reset_cpu(ulong ignored)
{
/*
* Set WD enable, RST enable,
* 3.9 msec clock period (8), reload value (8*3.9ms)
*/
u32 reg = EN_MASK + SRSTEN_MASK + (8 << CLKS_SHIFT) + (8 << LD_SHIFT);
writel(reg, SECWD2_BASE_ADDR);
while (1)
; /* loop forever till reset */
}

View file

@ -10,6 +10,9 @@
PF_CPPFLAGS_ARMV7 := $(call cc-option, -march=armv7-a, -march=armv5) PF_CPPFLAGS_ARMV7 := $(call cc-option, -march=armv7-a, -march=armv5)
PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_ARMV7) PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_ARMV7)
# SEE README.arm-unaligned-accesses # On supported platforms we set the bit which causes us to trap on unaligned
# memory access. This is the opposite of what the compiler expects to be
# the default so we must pass in -mno-unaligned-access so that it is aware
# of our decision.
PF_NO_UNALIGNED := $(call cc-option, -mno-unaligned-access,) PF_NO_UNALIGNED := $(call cc-option, -mno-unaligned-access,)
PLATFORM_NO_UNALIGNED := $(PF_NO_UNALIGNED) PLATFORM_CPPFLAGS += $(PF_NO_UNALIGNED)

View file

@ -0,0 +1,9 @@
#
# Copyright 2013 Broadcom Corporation.
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += s_init.o
obj-y += hwinit-common.o
obj-y += clk-stubs.o

View file

@ -0,0 +1,21 @@
/*
* Copyright 2013 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
/*
* These weak functions are available to kona architectures that don't
* require clock enables from the driver code.
*/
int __weak clk_sdio_enable(void *base, u32 rate, u32 *actual_ratep)
{
return 0;
}
int __weak clk_bsc_enable(void *base, u32 rate, u32 *actual_ratep)
{
return 0;
}

View file

@ -0,0 +1,16 @@
/*
* Copyright 2013 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/sizes.h>
#ifndef CONFIG_SYS_DCACHE_OFF
void enable_caches(void)
{
/* Enable D-cache. I-cache is already enabled in start.S */
dcache_enable();
}
#endif

View file

@ -0,0 +1,12 @@
/*
* Copyright 2014 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
/*
* Early system init. Currently empty.
*/
void s_init(void)
{
}

View file

@ -39,7 +39,11 @@ SECTIONS
. = ALIGN(4); . = ALIGN(4);
__image_copy_end = .; __image_copy_end = .;
_end = .;
.end :
{
*(.__end)
}
.bss : .bss :
{ {

View file

@ -17,9 +17,6 @@
#include <asm/arch/clocks_omap3.h> #include <asm/arch/clocks_omap3.h>
#include <linux/linkage.h> #include <linux/linkage.h>
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE /* sdram load addr from config.mk */
#ifdef CONFIG_SPL_BUILD #ifdef CONFIG_SPL_BUILD
ENTRY(save_boot_params) ENTRY(save_boot_params)
ldr r4, =omap3_boot_device ldr r4, =omap3_boot_device

View file

@ -172,6 +172,20 @@ struct dplls omap4430_dplls_es1 = {
.ddr = NULL .ddr = NULL
}; };
struct dplls omap4430_dplls_es20 = {
.mpu = mpu_dpll_params_1200mhz,
.core = core_dpll_params_es2_1600mhz_ddr200mhz,
.per = per_dpll_params_1536mhz,
.iva = iva_dpll_params_1862mhz,
#ifdef CONFIG_SYS_OMAP_ABE_SYSCK
.abe = abe_dpll_params_sysclk_196608khz,
#else
.abe = &abe_dpll_params_32k_196608khz,
#endif
.usb = usb_dpll_params_1920mhz,
.ddr = NULL
};
struct dplls omap4430_dplls = { struct dplls omap4430_dplls = {
.mpu = mpu_dpll_params_1200mhz, .mpu = mpu_dpll_params_1200mhz,
.core = core_dpll_params_1600mhz, .core = core_dpll_params_1600mhz,
@ -413,6 +427,10 @@ void hw_data_init(void)
break; break;
case OMAP4430_ES2_0: case OMAP4430_ES2_0:
*dplls_data = &omap4430_dplls_es20;
*omap_vcores = &omap4430_volts;
break;
case OMAP4430_ES2_1: case OMAP4430_ES2_1:
case OMAP4430_ES2_2: case OMAP4430_ES2_2:
case OMAP4430_ES2_3: case OMAP4430_ES2_3:

View file

@ -432,7 +432,7 @@ struct omap_sys_ctrl_regs const dra7xx_ctrl = {
.control_srcomp_code_latch = 0x4A002E84, .control_srcomp_code_latch = 0x4A002E84,
.control_ddr_control_ext_0 = 0x4A002E88, .control_ddr_control_ext_0 = 0x4A002E88,
.control_padconf_core_base = 0x4A003400, .control_padconf_core_base = 0x4A003400,
.control_std_fuse_opp_vdd_mpu_2 = 0x4A003B24, .control_std_fuse_opp_vdd_mpu_2 = 0x4A003B20,
.control_port_emif1_sdram_config = 0x4AE0C110, .control_port_emif1_sdram_config = 0x4AE0C110,
.control_port_emif1_lpddr2_nvm_config = 0x4AE0C114, .control_port_emif1_lpddr2_nvm_config = 0x4AE0C114,
.control_port_emif2_sdram_config = 0x4AE0C118, .control_port_emif2_sdram_config = 0x4AE0C118,

View file

@ -28,7 +28,11 @@ SECTIONS
. = ALIGN(4); . = ALIGN(4);
__image_copy_end = .; __image_copy_end = .;
_end = .;
.end :
{
*(.__end)
}
.bss : { .bss : {
. = ALIGN(4); . = ALIGN(4);

View file

@ -70,29 +70,6 @@ _end_vect:
* *
*************************************************************************/ *************************************************************************/
.globl _TEXT_BASE
_TEXT_BASE:
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
.word CONFIG_SPL_TEXT_BASE
#else
.word CONFIG_SYS_TEXT_BASE
#endif
/*
* These are defined in the board-specific linker script.
*/
.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start
.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end - _start
.globl _end_ofs
_end_ofs:
.word _end - _start
#ifdef CONFIG_USE_IRQ #ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */ /* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START .globl IRQ_STACK_START

View file

@ -60,7 +60,12 @@ SECTIONS
*(.__rel_dyn_end) *(.__rel_dyn_end)
} }
_end = .; .end :
{
*(.__end)
}
_image_binary_end = .;
/* /*
* Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c

View file

@ -6,10 +6,7 @@
# #
PLATFORM_RELFLAGS += -fno-common -ffixed-x18 PLATFORM_RELFLAGS += -fno-common -ffixed-x18
# SEE README.arm-unaligned-accesses
PF_NO_UNALIGNED := $(call cc-option, -mstrict-align)
PLATFORM_NO_UNALIGNED := $(PF_NO_UNALIGNED)
PF_CPPFLAGS_ARMV8 := $(call cc-option, -march=armv8-a) PF_CPPFLAGS_ARMV8 := $(call cc-option, -march=armv8-a)
PF_NO_UNALIGNED := $(call cc-option, -mstrict-align)
PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_ARMV8) PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_ARMV8)
PLATFORM_CPPFLAGS += $(PF_NO_UNALIGNED) PLATFORM_CPPFLAGS += $(PF_NO_UNALIGNED)

View file

@ -37,7 +37,11 @@ SECTIONS
. = ALIGN(4); . = ALIGN(4);
__image_copy_end = .; __image_copy_end = .;
_end = .;
.end :
{
*(.__end)
} >.sram
.bss : .bss :
{ {

View file

@ -84,32 +84,6 @@ _end_vect:
************************************************************************* *************************************************************************
*/ */
.globl _TEXT_BASE
_TEXT_BASE:
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
.word CONFIG_SPL_TEXT_BASE
#else
.word CONFIG_SYS_TEXT_BASE
#endif
/*
* These are defined in the board-specific linker script.
* Subtracting _start from them lets the linker put their
* relative position in the executable instead of leaving
* them null.
*/
.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start
.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end - _start
.globl _end_ofs
_end_ofs:
.word _end - _start
#ifdef CONFIG_USE_IRQ #ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */ /* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START .globl IRQ_STACK_START
@ -316,7 +290,6 @@ cpu_init_crit:
#ifdef CONFIG_SPL_BUILD #ifdef CONFIG_SPL_BUILD
.align 5 .align 5
do_hang: do_hang:
ldr sp, _TEXT_BASE /* use 32 words about stack */
bl hang /* hang and never return */ bl hang /* hang and never return */
#else /* !CONFIG_SPL_BUILD */ #else /* !CONFIG_SPL_BUILD */
.align 5 .align 5

View file

@ -56,32 +56,6 @@ _fiq: .word fiq
************************************************************************* *************************************************************************
*/ */
.globl _TEXT_BASE
_TEXT_BASE:
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
.word CONFIG_SPL_TEXT_BASE
#else
.word CONFIG_SYS_TEXT_BASE
#endif
/*
* These are defined in the board-specific linker script.
* Subtracting _start from them lets the linker put their
* relative position in the executable instead of leaving
* them null.
*/
.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start
.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end - _start
.globl _end_ofs
_end_ofs:
.word _end - _start
#ifdef CONFIG_USE_IRQ #ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */ /* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START .globl IRQ_STACK_START

View file

@ -42,7 +42,12 @@ SECTIONS
__rel_dyn_end = .; __rel_dyn_end = .;
} }
_end = .; .end :
{
*(.__end)
}
_image_binary_end = .;
.bss __rel_dyn_start (OVERLAY) : { .bss __rel_dyn_start (OVERLAY) : {
__bss_start = .; __bss_start = .;
@ -51,7 +56,7 @@ SECTIONS
__bss_end = .; __bss_end = .;
} }
.dynsym _end : { *(.dynsym) } .dynsym _image_binary_end : { *(.dynsym) }
.dynbss : { *(.dynbss) } .dynbss : { *(.dynbss) }
.dynstr : { *(.dynstr*) } .dynstr : { *(.dynstr*) }
.dynamic : { *(.dynamic*) } .dynamic : { *(.dynamic*) }

View file

@ -60,7 +60,12 @@ SECTIONS
*(.__rel_dyn_end) *(.__rel_dyn_end)
} }
_end = .; .end :
{
*(.__end)
}
_image_binary_end = .;
/* /*
* Deprecated: this MMU section is used by pxa at present but * Deprecated: this MMU section is used by pxa at present but
@ -91,7 +96,7 @@ SECTIONS
KEEP(*(.__bss_end)); KEEP(*(.__bss_end));
} }
.dynsym _end : { *(.dynsym) } .dynsym _image_binary_end : { *(.dynsym) }
.dynbss : { *(.dynbss) } .dynbss : { *(.dynbss) }
.dynstr : { *(.dynstr*) } .dynstr : { *(.dynstr*) }
.dynamic : { *(.dynamic*) } .dynamic : { *(.dynamic*) }

View file

@ -171,7 +171,8 @@ struct cm_wkuppll {
unsigned int resv11[1]; unsigned int resv11[1];
unsigned int wkup_uart0ctrl; /* offset 0xB4 */ unsigned int wkup_uart0ctrl; /* offset 0xB4 */
unsigned int wkup_i2c0ctrl; /* offset 0xB8 */ unsigned int wkup_i2c0ctrl; /* offset 0xB8 */
unsigned int resv12[7]; unsigned int wkup_adctscctrl; /* offset 0xBC */
unsigned int resv12[6];
unsigned int divm6dpllcore; /* offset 0xD8 */ unsigned int divm6dpllcore; /* offset 0xD8 */
}; };
@ -221,7 +222,8 @@ struct cm_perpll {
unsigned int tpccclkctrl; /* offset 0xBC */ unsigned int tpccclkctrl; /* offset 0xBC */
unsigned int dcan0clkctrl; /* offset 0xC0 */ unsigned int dcan0clkctrl; /* offset 0xC0 */
unsigned int dcan1clkctrl; /* offset 0xC4 */ unsigned int dcan1clkctrl; /* offset 0xC4 */
unsigned int resv6[2]; unsigned int resv6;
unsigned int epwmss1clkctrl; /* offset 0xCC */
unsigned int emiffwclkctrl; /* offset 0xD0 */ unsigned int emiffwclkctrl; /* offset 0xD0 */
unsigned int epwmss0clkctrl; /* offset 0xD4 */ unsigned int epwmss0clkctrl; /* offset 0xD4 */
unsigned int epwmss2clkctrl; /* offset 0xD8 */ unsigned int epwmss2clkctrl; /* offset 0xD8 */
@ -353,7 +355,11 @@ struct cm_perpll {
unsigned int gpio2clkctrl; /* offset 0x480 */ unsigned int gpio2clkctrl; /* offset 0x480 */
unsigned int resv20; unsigned int resv20;
unsigned int gpio3clkctrl; /* offset 0x488 */ unsigned int gpio3clkctrl; /* offset 0x488 */
unsigned int resv21[7]; unsigned int resv41;
unsigned int gpio4clkctrl; /* offset 0x490 */
unsigned int resv42;
unsigned int gpio5clkctrl; /* offset 0x498 */
unsigned int resv21[3];
unsigned int i2c1clkctrl; /* offset 0x4A8 */ unsigned int i2c1clkctrl; /* offset 0x4A8 */
unsigned int resv22; unsigned int resv22;

View file

@ -58,6 +58,22 @@
#define MT41J128MJT125_PHY_FIFO_WE 0x100 #define MT41J128MJT125_PHY_FIFO_WE 0x100
#define MT41J128MJT125_IOCTRL_VALUE 0x18B #define MT41J128MJT125_IOCTRL_VALUE 0x18B
/* Micron MT41K128M16JT-187E */
#define MT41K128MJT187E_EMIF_READ_LATENCY 0x06
#define MT41K128MJT187E_EMIF_TIM1 0x0888B3DB
#define MT41K128MJT187E_EMIF_TIM2 0x36337FDA
#define MT41K128MJT187E_EMIF_TIM3 0x501F830F
#define MT41K128MJT187E_EMIF_SDCFG 0x61C04AB2
#define MT41K128MJT187E_EMIF_SDREF 0x0000093B
#define MT41K128MJT187E_ZQ_CFG 0x50074BE4
#define MT41K128MJT187E_RATIO 0x40
#define MT41K128MJT187E_INVERT_CLKOUT 0x1
#define MT41K128MJT187E_RD_DQS 0x3B
#define MT41K128MJT187E_WR_DQS 0x85
#define MT41K128MJT187E_PHY_WR_DATA 0xC1
#define MT41K128MJT187E_PHY_FIFO_WE 0x100
#define MT41K128MJT187E_IOCTRL_VALUE 0x18B
/* Micron MT41J64M16JT-125 */ /* Micron MT41J64M16JT-125 */
#define MT41J64MJT125_EMIF_SDCFG 0x61C04A32 #define MT41J64MJT125_EMIF_SDCFG 0x61C04A32

View file

@ -12,8 +12,8 @@
#define AM33XX_GPIO1_BASE 0x4804C000 #define AM33XX_GPIO1_BASE 0x4804C000
#define AM33XX_GPIO2_BASE 0x481AC000 #define AM33XX_GPIO2_BASE 0x481AC000
#define AM33XX_GPIO3_BASE 0x481AE000 #define AM33XX_GPIO3_BASE 0x481AE000
#define AM33XX_GPIO4_BASE 0x48320000
#define GPIO_22 22 #define AM33XX_GPIO5_BASE 0x48322000
/* GPIO CTRL register */ /* GPIO CTRL register */
#define GPIO_CTRL_DISABLEMODULE_SHIFT 0 #define GPIO_CTRL_DISABLEMODULE_SHIFT 0

View file

@ -0,0 +1,15 @@
/*
* Copyright 2013 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __ARCH_BCM281XX_GPIO_H
#define __ARCH_BCM281XX_GPIO_H
/*
* Empty file - cmd_gpio.c requires this. The implementation
* is in drivers/gpio/kona_gpio.c instead of inlined here.
*/
#endif

View file

@ -0,0 +1,25 @@
/*
* Copyright 2013 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __ARCH_BCM281XX_SYSMAP_H
#define BSC1_BASE_ADDR 0x3e016000
#define BSC2_BASE_ADDR 0x3e017000
#define BSC3_BASE_ADDR 0x3e018000
#define GPIO2_BASE_ADDR 0x35003000
#define KONA_MST_CLK_BASE_ADDR 0x3f001000
#define KONA_SLV_CLK_BASE_ADDR 0x3e011000
#define PMU_BSC_BASE_ADDR 0x3500d000
#define PWRMGR_BASE_ADDR 0x35010000
#define SDIO1_BASE_ADDR 0x3f180000
#define SDIO2_BASE_ADDR 0x3f190000
#define SDIO3_BASE_ADDR 0x3f1a0000
#define SDIO4_BASE_ADDR 0x3f1b0000
#define SECWD_BASE_ADDR 0x3500c000
#define SECWD2_BASE_ADDR 0x35002f40
#define TIMER_BASE_ADDR 0x3e00d000
#endif

View file

@ -0,0 +1,29 @@
/*
* Copyright 2013 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
/* This API file is loosely based on u-boot/drivers/video/ipu.h and linux */
#ifndef __KONA_COMMON_CLK_H
#define __KONA_COMMON_CLK_H
#include <linux/types.h>
struct clk;
/* Only implement required functions for your specific architecture */
int clk_init(void);
struct clk *clk_get(const char *id);
int clk_enable(struct clk *clk);
void clk_disable(struct clk *clk);
unsigned long clk_get_rate(struct clk *clk);
long clk_round_rate(struct clk *clk, unsigned long rate);
int clk_set_rate(struct clk *clk, unsigned long rate);
int clk_set_parent(struct clk *clk, struct clk *parent);
struct clk *clk_get_parent(struct clk *clk);
int clk_sdio_enable(void *base, u32 rate, u32 *actual_ratep);
int clk_bsc_enable(void *base);
#endif

View file

@ -0,0 +1,12 @@
/*
* Copyright 2013 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __KONA_SDHCI_H
#define __KONA_SDHCI_H
int kona_sdhci_init(int dev_index, u32 min_clk, u32 quirks);
#endif

View file

@ -32,7 +32,6 @@ endif
ifndef CONFIG_SYS_GENERIC_BOARD ifndef CONFIG_SYS_GENERIC_BOARD
obj-y += board.o obj-y += board.o
endif endif
obj-y += sections.o
obj-$(CONFIG_OF_LIBFDT) += bootm-fdt.o obj-$(CONFIG_OF_LIBFDT) += bootm-fdt.o
obj-$(CONFIG_CMD_BOOTM) += bootm.o obj-$(CONFIG_CMD_BOOTM) += bootm.o
@ -43,6 +42,7 @@ else
obj-$(CONFIG_SPL_FRAMEWORK) += spl.o obj-$(CONFIG_SPL_FRAMEWORK) += spl.o
endif endif
obj-y += sections.o
ifdef CONFIG_ARM64 ifdef CONFIG_ARM64
obj-y += interrupts_64.o obj-y += interrupts_64.o
else else

View file

@ -105,8 +105,8 @@ static int display_banner(void)
{ {
printf("\n\n%s\n\n", version_string); printf("\n\n%s\n\n", version_string);
debug("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n", debug("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
_TEXT_BASE, (ulong)&_start,
_bss_start_ofs + _TEXT_BASE, _bss_end_ofs + _TEXT_BASE); (ulong)&__bss_start, (ulong)&__bss_end);
#ifdef CONFIG_MODEM_SUPPORT #ifdef CONFIG_MODEM_SUPPORT
debug("Modem Support enabled\n"); debug("Modem Support enabled\n");
#endif #endif
@ -273,13 +273,13 @@ void board_init_f(ulong bootflag)
memset((void *)gd, 0, sizeof(gd_t)); memset((void *)gd, 0, sizeof(gd_t));
gd->mon_len = _bss_end_ofs; gd->mon_len = (ulong)&__bss_end - (ulong)_start;
#ifdef CONFIG_OF_EMBED #ifdef CONFIG_OF_EMBED
/* Get a pointer to the FDT */ /* Get a pointer to the FDT */
gd->fdt_blob = __dtb_db_begin; gd->fdt_blob = __dtb_db_begin;
#elif defined CONFIG_OF_SEPARATE #elif defined CONFIG_OF_SEPARATE
/* FDT is at end of image */ /* FDT is at end of image */
gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE); gd->fdt_blob = &_end;
#endif #endif
/* Allow the early environment to override the fdt address */ /* Allow the early environment to override the fdt address */
gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
@ -451,7 +451,7 @@ void board_init_f(ulong bootflag)
gd->relocaddr = addr; gd->relocaddr = addr;
gd->start_addr_sp = addr_sp; gd->start_addr_sp = addr_sp;
gd->reloc_off = addr - _TEXT_BASE; gd->reloc_off = addr - (ulong)&_start;
debug("relocation Offset is: %08lx\n", gd->reloc_off); debug("relocation Offset is: %08lx\n", gd->reloc_off);
if (new_fdt) { if (new_fdt) {
memcpy(new_fdt, gd->fdt_blob, fdt_size); memcpy(new_fdt, gd->fdt_blob, fdt_size);
@ -516,7 +516,7 @@ void board_init_r(gd_t *id, ulong dest_addr)
gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r"); bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");
monitor_flash_len = _end_ofs; monitor_flash_len = (ulong)&__rel_dyn_end - (ulong)_start;
/* Enable caches */ /* Enable caches */
enable_caches(); enable_caches();

View file

@ -153,7 +153,7 @@ void do_prefetch_abort (struct pt_regs *pt_regs)
void do_data_abort (struct pt_regs *pt_regs) void do_data_abort (struct pt_regs *pt_regs)
{ {
printf ("data abort\n\n MAYBE you should read doc/README.arm-unaligned-accesses\n\n"); printf ("data abort\n");
show_regs (pt_regs); show_regs (pt_regs);
bad_mode (); bad_mode ();
} }

View file

@ -25,3 +25,4 @@ char __image_copy_start[0] __attribute__((section(".__image_copy_start")));
char __image_copy_end[0] __attribute__((section(".__image_copy_end"))); char __image_copy_end[0] __attribute__((section(".__image_copy_end")));
char __rel_dyn_start[0] __attribute__((section(".__rel_dyn_start"))); char __rel_dyn_start[0] __attribute__((section(".__rel_dyn_start")));
char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end"))); char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end")));
char _end[0] __attribute__((section(".__end")));

View file

@ -49,5 +49,9 @@ SECTIONS
} >.sram } >.sram
__image_copy_end = .; __image_copy_end = .;
_end = .;
.end :
{
*(.__end)
} >.sram
} }

View file

@ -0,0 +1,22 @@
/*
* bur_comon.h
*
* common board information header for B&R boards
*
* Copyright (C) 2013 Hannes Petermaier <oe5hpm@oevsv.at>
* Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _BUR_COMMON_H_
#define _BUR_COMMON_H_
void blink(u32 blinks, u32 intervall, u32 pin);
void pmicsetup(u32 mpupll);
void enable_uart0_pin_mux(void);
void enable_i2c0_pin_mux(void);
void enable_board_pin_mux(void);
int board_eth_init(bd_t *bis);
#endif

216
board/BuR/common/common.c Normal file
View file

@ -0,0 +1,216 @@
/*
* common.c
*
* common board functions for B&R boards
*
* Copyright (C) 2013 Hannes Petermaier <oe5hpm@oevsv.at>
* Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
*
* SPDX-License-Identifier: GPL-2.0+
*
*/
#include <common.h>
#include <errno.h>
#include <spl.h>
#include <asm/arch/cpu.h>
#include <asm/arch/hardware.h>
#include <asm/arch/omap.h>
#include <asm/arch/clock.h>
#include <asm/arch/gpio.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
#include <asm/gpio.h>
#include <i2c.h>
#include <miiphy.h>
#include <cpsw.h>
#include <power/tps65217.h>
#include "bur_common.h"
static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
/* --------------------------------------------------------------------------*/
void blink(u32 blinks, u32 intervall, u32 pin)
{
gpio_direction_output(pin, 0);
int val = 0;
do {
val ^= 0x01;
gpio_set_value(pin, val);
mdelay(intervall);
} while (blinks--);
gpio_set_value(pin, 0);
}
#ifdef CONFIG_SPL_BUILD
void pmicsetup(u32 mpupll)
{
int mpu_vdd;
int usb_cur_lim;
/* setup I2C */
enable_i2c0_pin_mux();
i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE);
if (i2c_probe(TPS65217_CHIP_PM)) {
puts("PMIC (0x24) not found! skip further initalization.\n");
return;
}
/* Get the frequency which is defined by device fuses */
dpll_mpu_opp100.m = am335x_get_efuse_mpu_max_freq(cdev);
printf("detected max. frequency: %d - ", dpll_mpu_opp100.m);
if (0 != mpupll) {
dpll_mpu_opp100.m = MPUPLL_M_1000;
printf("retuning MPU-PLL to: %d MHz.\n", dpll_mpu_opp100.m);
} else {
puts("ok.\n");
}
/*
* 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 */
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");
/* Set LDO4 to 3.3V */
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);
}
void set_uart_mux_conf(void)
{
enable_uart0_pin_mux();
}
void set_mux_conf_regs(void)
{
enable_board_pin_mux();
}
#endif /* CONFIG_SPL_BUILD */
#if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \
(defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD))
static void cpsw_control(int enabled)
{
/* VTP can be added here */
return;
}
/* describing port offsets of TI's CPSW block */
static struct cpsw_slave_data cpsw_slaves[] = {
{
.slave_reg_ofs = 0x208,
.sliver_reg_ofs = 0xd80,
.phy_id = 0,
},
{
.slave_reg_ofs = 0x308,
.sliver_reg_ofs = 0xdc0,
.phy_id = 1,
},
};
static struct cpsw_platform_data cpsw_data = {
.mdio_base = CPSW_MDIO_BASE,
.cpsw_base = CPSW_BASE,
.mdio_div = 0xff,
.channels = 8,
.cpdma_reg_ofs = 0x800,
.slaves = 1,
.slave_data = cpsw_slaves,
.ale_reg_ofs = 0xd00,
.ale_entries = 1024,
.host_port_reg_ofs = 0x108,
.hw_stats_reg_ofs = 0x900,
.bd_ram_ofs = 0x2000,
.mac_control = (1 << 5),
.control = cpsw_control,
.host_port_num = 0,
.version = CPSW_CTRL_VERSION_2,
};
#endif /* CONFIG_DRIVER_TI_CPSW, ... */
#if defined(CONFIG_DRIVER_TI_CPSW)
int board_eth_init(bd_t *bis)
{
int rv = 0;
uint8_t mac_addr[6];
uint32_t mac_hi, mac_lo;
/* try reading mac address from efuse */
mac_lo = readl(&cdev->macid0l);
mac_hi = readl(&cdev->macid0h);
mac_addr[0] = mac_hi & 0xFF;
mac_addr[1] = (mac_hi & 0xFF00) >> 8;
mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
mac_addr[4] = mac_lo & 0xFF;
mac_addr[5] = (mac_lo & 0xFF00) >> 8;
#if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \
(defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD))
if (!getenv("ethaddr")) {
printf("<ethaddr> not set. Validating first E-fuse MAC ... ");
if (is_valid_ether_addr(mac_addr)) {
printf("using: %02X:%02X:%02X:%02X:%02X:%02X.\n",
mac_addr[0], mac_addr[1], mac_addr[2],
mac_addr[3], mac_addr[4], mac_addr[5]
);
eth_setenv_enetaddr("ethaddr", mac_addr);
}
}
writel(MII_MODE_ENABLE, &cdev->miisel);
cpsw_slaves[0].phy_if = PHY_INTERFACE_MODE_MII;
cpsw_slaves[1].phy_if = PHY_INTERFACE_MODE_MII;
rv = cpsw_register(&cpsw_data);
if (rv < 0) {
printf("Error %d registering CPSW switch\n", rv);
return 0;
}
#endif /* CONFIG_DRIVER_TI_CPSW, ... */
return rv;
}
#endif /* CONFIG_DRIVER_TI_CPSW */

12
board/BuR/kwb/Makefile Normal file
View file

@ -0,0 +1,12 @@
#
# Makefile
#
# Copyright (C) 2014 Hannes Petermaier <oe5hpm@oevsv.at> -
# Bernecker & Rainer Industrielektronik GmbH - http://www.br-automation.com/
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-$(CONFIG_SPL_BUILD) += mux.o
obj-y += ../common/common.o
obj-y += board.o

240
board/BuR/kwb/board.c Normal file
View file

@ -0,0 +1,240 @@
/*
* board.c
*
* Board functions for B&R KWB Board
*
* Copyright (C) 2013 Hannes Petermaier <oe5hpm@oevsv.at>
* Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
*
* SPDX-License-Identifier: GPL-2.0+
*
*/
#include <common.h>
#include <errno.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/sys_proto.h>
#include <asm/arch/mem.h>
#include <asm/io.h>
#include <asm/emif.h>
#include <asm/gpio.h>
#include <i2c.h>
#include <power/tps65217.h>
#include "../common/bur_common.h"
/* -------------------------------------------------------------------------*/
/* -- defines for used GPIO Hardware -- */
#define KEY (0+4)
#define LCD_PWR (0+5)
#define PUSH_KEY (0+31)
#define USB2SD_NRST (32+29)
#define USB2SD_PWR (96+13)
/* -------------------------------------------------------------------------*/
/* -- PSOC Resetcontroller Register defines -- */
/* I2C Address of controller */
#define RSTCTRL_ADDR 0x75
/* Register for CTRL-word */
#define RSTCTRL_CTRLREG 0x01
/* Register for giving some information to VxWorks OS */
#define RSTCTRL_SCRATCHREG 0x04
/* -- defines for RSTCTRL_CTRLREG -- */
#define RSTCTRL_FORCE_PWR_NEN 0x0404
#if defined(CONFIG_SPL_BUILD)
/* TODO: check ram-timing ! */
static const struct ddr_data ddr3_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_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_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,
.zq_config = MT41K256M16HA125E_ZQ_CFG,
.emif_ddr_phy_ctlr_1 = MT41K256M16HA125E_EMIF_READ_LATENCY,
};
static const struct ctrl_ioregs ddr3_ioregs = {
.cm0ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
.cm1ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
.cm2ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
.dt0ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
.dt1ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
};
#define OSC (V_OSCK/1000000)
const struct dpll_params dpll_ddr3 = { 400, OSC-1, 1, -1, -1, -1, -1};
void am33xx_spl_board_init(void)
{
unsigned int oldspeed;
unsigned short buf;
struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER;
struct cm_wkuppll *const cmwkup = (struct cm_wkuppll *)CM_WKUP;
/*
* enable additional clocks of modules which are accessed later from
* VxWorks OS
*/
u32 *const clk_domains[] = { 0 };
u32 *const clk_modules_kwbspecific[] = {
&cmwkup->wkup_adctscctrl,
&cmper->spi1clkctrl,
&cmper->dcan0clkctrl,
&cmper->dcan1clkctrl,
&cmper->epwmss0clkctrl,
&cmper->epwmss1clkctrl,
&cmper->epwmss2clkctrl,
0
};
do_enable_clocks(clk_domains, clk_modules_kwbspecific, 1);
/* power-OFF LCD-Display */
gpio_direction_output(LCD_PWR, 0);
/* setup I2C */
enable_i2c0_pin_mux();
i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE);
/* power-ON 3V3 via Resetcontroller */
oldspeed = i2c_get_bus_speed();
if (0 != i2c_set_bus_speed(CONFIG_SYS_OMAP24_I2C_SPEED_PSOC)) {
buf = RSTCTRL_FORCE_PWR_NEN;
i2c_write(RSTCTRL_ADDR, RSTCTRL_CTRLREG, 1,
(uint8_t *)&buf, sizeof(buf));
i2c_set_bus_speed(oldspeed);
} else {
puts("ERROR: i2c_set_bus_speed failed! (turn on PWR_nEN)\n");
}
#if defined(CONFIG_AM335X_USB0)
/* power on USB2SD Controller */
gpio_direction_output(USB2SD_PWR, 1);
mdelay(1);
/* give a reset Pulse to USB2SD Controller */
gpio_direction_output(USB2SD_NRST, 0);
mdelay(1);
gpio_set_value(USB2SD_NRST, 1);
#endif
pmicsetup(0);
}
const struct dpll_params *get_dpll_ddr_params(void)
{
return &dpll_ddr3;
}
void sdram_init(void)
{
config_ddr(400, &ddr3_ioregs,
&ddr3_data,
&ddr3_cmd_ctrl_data,
&ddr3_emif_reg_data, 0);
}
#endif /* CONFIG_SPL_BUILD */
/*
* Basic board specific setup. Pinmux has been handled already.
*/
int board_init(void)
{
gpmc_init();
return 0;
}
#ifdef CONFIG_BOARD_LATE_INIT
int board_late_init(void)
{
const unsigned int ton = 250;
const unsigned int toff = 1000;
unsigned int cnt = 3;
unsigned short buf = 0xAAAA;
unsigned int oldspeed;
tps65217_reg_write(TPS65217_PROT_LEVEL_NONE,
TPS65217_WLEDCTRL2, 0x32, 0xFF); /* 50% dimlevel */
if (gpio_get_value(KEY)) {
do {
/* turn on light */
tps65217_reg_write(TPS65217_PROT_LEVEL_NONE,
TPS65217_WLEDCTRL1, 0x09, 0xFF);
mdelay(ton);
/* turn off light */
tps65217_reg_write(TPS65217_PROT_LEVEL_NONE,
TPS65217_WLEDCTRL1, 0x01, 0xFF);
mdelay(toff);
cnt--;
if (!gpio_get_value(KEY) &&
gpio_get_value(PUSH_KEY) && 1 == cnt) {
puts("updating from USB ...\n");
setenv("bootcmd", "run usbupdate");
break;
} else if (!gpio_get_value(KEY)) {
break;
}
} while (cnt);
}
switch (cnt) {
case 0:
puts("3 blinks ... entering BOOT mode.\n");
buf = 0x0000;
break;
case 1:
puts("2 blinks ... entering DIAGNOSE mode.\n");
buf = 0x0F0F;
break;
case 2:
puts("1 blinks ... entering SERVICE mode.\n");
buf = 0xB4B4;
break;
case 3:
puts("0 blinks ... entering RUN mode.\n");
buf = 0x0404;
break;
}
mdelay(ton);
/* turn on light */
tps65217_reg_write(TPS65217_PROT_LEVEL_NONE,
TPS65217_WLEDCTRL1, 0x09, 0xFF);
/* write bootinfo into scratchregister of resetcontroller */
oldspeed = i2c_get_bus_speed();
if (0 != i2c_set_bus_speed(CONFIG_SYS_OMAP24_I2C_SPEED_PSOC)) {
i2c_write(RSTCTRL_ADDR, RSTCTRL_SCRATCHREG, 1,
(uint8_t *)&buf, sizeof(buf));
i2c_set_bus_speed(oldspeed);
} else {
puts("ERROR: i2c_set_bus_speed failed! (scratchregister)\n");
}
/*
* reset VBAR registers to its reset location, VxWorks 6.9.3.2 does
* expect that vectors are there, original u-boot moves them to _start
*/
__asm__("ldr r0,=0x20000");
__asm__("mcr p15, 0, r0, c12, c0, 0"); /* Set VBAR */
return 0;
}
#endif /* CONFIG_BOARD_LATE_INIT */

195
board/BuR/kwb/mux.c Normal file
View file

@ -0,0 +1,195 @@
/*
* mux.c
*
* Pinmux Setting for B&R LEIT Board(s)
*
* Copyright (C) 2013 Hannes Petermaier <oe5hpm@oevsv.at>
* Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/hardware.h>
#include <asm/arch/mux.h>
#include <asm/io.h>
#include <i2c.h>
static struct module_pin_mux usb0_pin_mux[] = {
{OFFSET(usb0_id), (MODE(0) | RXACTIVE)},
/* USB0 DrvBus Receiver disable (from romcode 0x20) */
{OFFSET(usb0_drvvbus), (MODE(0))},
/* USB1 DrvBus as GPIO due to HW-Workaround */
{OFFSET(usb1_drvvbus), (MODE(7))},
{-1},
};
static struct module_pin_mux spi1_pin_mux[] = {
/* SPI1_SCLK */
{OFFSET(mcasp0_aclkx), MODE(3) | PULLUDEN | RXACTIVE},
/* SPI1_D0 */
{OFFSET(mcasp0_fsx), MODE(3) | PULLUDEN | RXACTIVE},
/* SPI1_D1 */
{OFFSET(mcasp0_axr0), MODE(3) | PULLUDEN | RXACTIVE},
/* SPI1_CS0 */
{OFFSET(mcasp0_ahclkr), MODE(3) | PULLUDEN | PULLUP_EN | RXACTIVE},
{-1},
};
static struct module_pin_mux dcan0_pin_mux[] = {
/* DCAN0 TX */
{OFFSET(uart1_ctsn), MODE(2) | PULLUDEN | PULLUP_EN},
/* DCAN0 RX */
{OFFSET(uart1_rtsn), MODE(2) | RXACTIVE},
{-1},
};
static struct module_pin_mux dcan1_pin_mux[] = {
/* DCAN1 TX */
{OFFSET(uart1_rxd), MODE(2) | PULLUDEN | PULLUP_EN},
/* DCAN1 RX */
{OFFSET(uart1_txd), MODE(2) | RXACTIVE},
{-1},
};
static struct module_pin_mux gpios[] = {
/* GPIO0_29 (RMII1_REFCLK) - eMMC nRST */
{OFFSET(rmii1_refclk), (MODE(7) | PULLUDDIS)},
/* GPIO0_4 (SPI D1) - TA602 */
{OFFSET(spi0_d1), (MODE(7) | PULLUDDIS | RXACTIVE)},
/* GPIO0_5 (SPI CS0) - DISPLAY_ON_OFF */
{OFFSET(spi0_cs0), (MODE(7) | PULLUDDIS)},
/* GPIO0_7 (PWW0 OUT) - CAN TERM */
{OFFSET(ecap0_in_pwm0_out), (MODE(7) | PULLUDDIS | RXACTIVE)},
/* GPIO0_19 (DMA_INTR0) - CLKOUT SYS */
{OFFSET(xdma_event_intr0), (MODE(7) | RXACTIVE)},
/* GPIO0_20 (DMA_INTR1) - SPI1 nCS1 */
{OFFSET(xdma_event_intr1), (MODE(7) | PULLUDEN | PULLUP_EN)},
/* GPIO0_30 (GPMC_WAIT0) - TA601 */
{OFFSET(gpmc_wait0), (MODE(7) | PULLUDDIS | RXACTIVE)},
/* GPIO0_31 (GPMC_nWP) - SW601 PushButton */
{OFFSET(gpmc_wpn), (MODE(7) | PULLUDDIS | RXACTIVE)},
/* GPIO1_28 (GPMC_nWE) - FRAM_nWP */
{OFFSET(gpmc_be1n), (MODE(7) | PULLUDDIS)},
/* GPIO2_0 (GPMC_nCS3) - VBAT_OK */
{OFFSET(gpmc_csn3), (MODE(7) | PULLUDDIS | RXACTIVE) },
/* GPIO2_2 (GPMC_nADV_ALE) - DCOK */
{OFFSET(gpmc_advn_ale), (MODE(7) | PULLUDDIS | RXACTIVE)},
/* GPIO2_4 (GPMC_nWE) - TST_BAST */
{OFFSET(gpmc_wen), (MODE(7) | PULLUDDIS)},
/* GPIO3_18 (MCASP0_ACLKR) - SW601 CNTup, mapped to Counter eQEB0A_in */
{OFFSET(mcasp0_aclkr), (MODE(1) | PULLUDDIS | RXACTIVE)},
/* GPIO3_19 (MCASP0_FSR) - SW601 CNTdown, mapped to Counter eQEB0B_in */
{OFFSET(mcasp0_fsr), (MODE(1) | PULLUDDIS | RXACTIVE)},
/* GPIO3_20 (MCASP0_AXR1) - SW601 CNTdown, map to Counter eQEB0_index */
{OFFSET(mcasp0_axr1), (MODE(1) | PULLUDDIS | RXACTIVE)},
{-1},
};
static struct module_pin_mux uart0_pin_mux[] = {
/* UART0_CTS */
{OFFSET(uart0_ctsn), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)},
/* UART0_RXD */
{OFFSET(uart0_rxd), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)},
/* UART0_TXD */
{OFFSET(uart0_txd), (MODE(0) | PULLUDEN)},
{-1},
};
static struct module_pin_mux i2c0_pin_mux[] = {
/* I2C_DATA */
{OFFSET(i2c0_sda), (MODE(0) | RXACTIVE | PULLUDEN | SLEWCTRL)},
/* I2C_SCLK */
{OFFSET(i2c0_scl), (MODE(0) | RXACTIVE | PULLUDEN | SLEWCTRL)},
{-1},
};
static struct module_pin_mux mii1_pin_mux[] = {
{OFFSET(mii1_rxerr), MODE(0) | RXACTIVE}, /* MII1_RXERR */
{OFFSET(mii1_txen), MODE(0)}, /* MII1_TXEN */
{OFFSET(mii1_rxdv), MODE(0) | RXACTIVE}, /* MII1_RXDV */
{OFFSET(mii1_txd3), MODE(0)}, /* MII1_TXD3 */
{OFFSET(mii1_txd2), MODE(0)}, /* MII1_TXD2 */
{OFFSET(mii1_txd1), MODE(0)}, /* MII1_TXD1 */
{OFFSET(mii1_txd0), MODE(0)}, /* MII1_TXD0 */
{OFFSET(mii1_txclk), MODE(0) | RXACTIVE}, /* MII1_TXCLK */
{OFFSET(mii1_rxclk), MODE(0) | RXACTIVE}, /* MII1_RXCLK */
{OFFSET(mii1_rxd3), MODE(0) | RXACTIVE}, /* MII1_RXD3 */
{OFFSET(mii1_rxd2), MODE(0) | RXACTIVE}, /* MII1_RXD2 */
{OFFSET(mii1_rxd1), MODE(0) | RXACTIVE}, /* MII1_RXD1 */
{OFFSET(mii1_rxd0), MODE(0) | RXACTIVE}, /* MII1_RXD0 */
{OFFSET(mdio_data), MODE(0) | RXACTIVE | PULLUP_EN}, /* MDIO_DATA */
{OFFSET(mdio_clk), MODE(0) | PULLUP_EN}, /* MDIO_CLK */
{-1},
};
static struct module_pin_mux mmc1_pin_mux[] = {
{OFFSET(gpmc_ad3), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT3 */
{OFFSET(gpmc_ad2), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT2 */
{OFFSET(gpmc_ad1), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT1 */
{OFFSET(gpmc_ad0), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT0 */
{OFFSET(gpmc_csn1), (MODE(2) | RXACTIVE | PULLUP_EN)}, /* MMC1_CLK */
{OFFSET(gpmc_csn2), (MODE(2) | RXACTIVE | PULLUP_EN)}, /* MMC1_CMD */
{OFFSET(gpmc_csn0), (MODE(7) | RXACTIVE | PULLUP_EN)}, /* MMC1_WP */
{OFFSET(gpmc_advn_ale), (MODE(7) | RXACTIVE | PULLUP_EN)},/* MMC1_CD */
{-1},
};
static struct module_pin_mux lcd_pin_mux[] = {
{OFFSET(lcd_data0), (MODE(0) | PULLUDDIS)}, /* LCD-Data(0) */
{OFFSET(lcd_data1), (MODE(0) | PULLUDDIS)}, /* LCD-Data(1) */
{OFFSET(lcd_data2), (MODE(0) | PULLUDDIS)}, /* LCD-Data(2) */
{OFFSET(lcd_data3), (MODE(0) | PULLUDDIS)}, /* LCD-Data(3) */
{OFFSET(lcd_data4), (MODE(0) | PULLUDDIS)}, /* LCD-Data(4) */
{OFFSET(lcd_data5), (MODE(0) | PULLUDDIS)}, /* LCD-Data(5) */
{OFFSET(lcd_data6), (MODE(0) | PULLUDDIS)}, /* LCD-Data(6) */
{OFFSET(lcd_data7), (MODE(0) | PULLUDDIS)}, /* LCD-Data(7) */
{OFFSET(lcd_data8), (MODE(0) | PULLUDDIS)}, /* LCD-Data(8) */
{OFFSET(lcd_data9), (MODE(0) | PULLUDDIS)}, /* LCD-Data(9) */
{OFFSET(lcd_data10), (MODE(0) | PULLUDDIS)}, /* LCD-Data(10) */
{OFFSET(lcd_data11), (MODE(0) | PULLUDDIS)}, /* LCD-Data(11) */
{OFFSET(lcd_data12), (MODE(0) | PULLUDDIS)}, /* LCD-Data(12) */
{OFFSET(lcd_data13), (MODE(0) | PULLUDDIS)}, /* LCD-Data(13) */
{OFFSET(lcd_data14), (MODE(0) | PULLUDDIS)}, /* LCD-Data(14) */
{OFFSET(lcd_data15), (MODE(0) | PULLUDDIS)}, /* LCD-Data(15) */
{OFFSET(gpmc_ad8), (MODE(1) | PULLUDDIS)}, /* LCD-Data(16) */
{OFFSET(gpmc_ad9), (MODE(1) | PULLUDDIS)}, /* LCD-Data(17) */
{OFFSET(gpmc_ad10), (MODE(1) | PULLUDDIS)}, /* LCD-Data(18) */
{OFFSET(gpmc_ad11), (MODE(1) | PULLUDDIS)}, /* LCD-Data(19) */
{OFFSET(gpmc_ad12), (MODE(1) | PULLUDDIS)}, /* LCD-Data(20) */
{OFFSET(gpmc_ad13), (MODE(1) | PULLUDDIS)}, /* LCD-Data(21) */
{OFFSET(gpmc_ad14), (MODE(1) | PULLUDDIS)}, /* LCD-Data(22) */
{OFFSET(gpmc_ad15), (MODE(1) | PULLUDDIS)}, /* LCD-Data(23) */
{OFFSET(lcd_vsync), (MODE(0) | PULLUDDIS)}, /* LCD-VSync */
{OFFSET(lcd_hsync), (MODE(0) | PULLUDDIS)}, /* LCD-HSync */
{OFFSET(lcd_ac_bias_en), (MODE(0) | PULLUDDIS)},/* LCD-DE */
{OFFSET(lcd_pclk), (MODE(0) | PULLUDDIS)}, /* LCD-CLK */
{-1},
};
void enable_uart0_pin_mux(void)
{
configure_module_pin_mux(uart0_pin_mux);
}
void enable_i2c0_pin_mux(void)
{
configure_module_pin_mux(i2c0_pin_mux);
}
void enable_board_pin_mux(void)
{
configure_module_pin_mux(i2c0_pin_mux);
configure_module_pin_mux(mii1_pin_mux);
configure_module_pin_mux(usb0_pin_mux);
configure_module_pin_mux(spi1_pin_mux);
configure_module_pin_mux(dcan0_pin_mux);
configure_module_pin_mux(dcan1_pin_mux);
configure_module_pin_mux(mmc1_pin_mux);
configure_module_pin_mux(lcd_pin_mux);
configure_module_pin_mux(gpios);
}

View file

@ -0,0 +1,14 @@
#
# Makefile
#
# Copyright (C) 2013 Hannes Petermaier <oe5hpm@oevsv.at>
# Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
#
# SPDX-License-Identifier: GPL-2.0+
#
ifeq ($(CONFIG_SPL_BUILD),y)
obj-y := mux.o
endif
obj-y += ../common/common.o
obj-y += board.o

147
board/BuR/tseries/board.c Normal file
View file

@ -0,0 +1,147 @@
/*
* board.c
*
* Board functions for B&R LEIT Board
*
* Copyright (C) 2013 Hannes Petermaier <oe5hpm@oevsv.at>
* Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
*
* SPDX-License-Identifier: GPL-2.0+
*
*/
#include <common.h>
#include <errno.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/sys_proto.h>
#include <asm/arch/mem.h>
#include <asm/io.h>
#include <asm/emif.h>
#include <asm/gpio.h>
#include <i2c.h>
#include <power/tps65217.h>
#include "../common/bur_common.h"
DECLARE_GLOBAL_DATA_PTR;
/* --------------------------------------------------------------------------*/
/* -- defines for GPIO -- */
#define ETHLED_ORANGE (96+16) /* GPIO3_16 */
#define REPSWITCH (0+20) /* GPIO0_20 */
#if defined(CONFIG_SPL_BUILD)
/* TODO: check ram-timing ! */
static const struct ddr_data ddr3_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_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_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,
.zq_config = MT41K256M16HA125E_ZQ_CFG,
.emif_ddr_phy_ctlr_1 = MT41K256M16HA125E_EMIF_READ_LATENCY,
};
static const struct ctrl_ioregs ddr3_ioregs = {
.cm0ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
.cm1ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
.cm2ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
.dt0ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
.dt1ioctl = MT41K256M16HA125E_IOCTRL_VALUE,
};
#ifdef CONFIG_SPL_OS_BOOT
/*
* called from spl_nand.c
* return 0 for loading linux, return 1 for loading u-boot
*/
int spl_start_uboot(void)
{
if (0 == gpio_get_value(REPSWITCH)) {
blink(5, 125, ETHLED_ORANGE);
mdelay(1000);
printf("SPL: entering u-boot instead kernel image.\n");
return 1;
}
return 0;
}
#endif /* CONFIG_SPL_OS_BOOT */
#define OSC (V_OSCK/1000000)
static const struct dpll_params dpll_ddr3 = { 400, OSC-1, 1, -1, -1, -1, -1};
void am33xx_spl_board_init(void)
{
pmicsetup(1000);
}
const struct dpll_params *get_dpll_ddr_params(void)
{
return &dpll_ddr3;
}
void sdram_init(void)
{
config_ddr(400, &ddr3_ioregs,
&ddr3_data,
&ddr3_cmd_ctrl_data,
&ddr3_emif_reg_data, 0);
}
#endif /* CONFIG_SPL_BUILD */
/* Basic board specific setup. Pinmux has been handled already. */
int board_init(void)
{
gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
gpmc_init();
return 0;
}
#ifdef CONFIG_BOARD_LATE_INIT
int board_late_init(void)
{
gpio_direction_output(ETHLED_ORANGE, 0);
if (0 == gpio_get_value(REPSWITCH)) {
printf("\n\n\n"
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
"!!!!!!! recovery switch activated !!!!!!!\n"
"!!!!!!! running usbupdate !!!!!!!\n"
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n\n");
setenv("bootcmd", "sleep 2; run netupdate;");
}
printf("turning on display power+backlight ... ");
tps65217_reg_write(TPS65217_PROT_LEVEL_NONE, TPS65217_WLEDCTRL1,
0x09, TPS65217_MASK_ALL_BITS); /* 200 Hz, ON */
tps65217_reg_write(TPS65217_PROT_LEVEL_NONE, TPS65217_WLEDCTRL2,
0x62, TPS65217_MASK_ALL_BITS); /* 100% */
printf("ok.\n");
return 0;
}
#endif /* CONFIG_BOARD_LATE_INIT */

225
board/BuR/tseries/mux.c Normal file
View file

@ -0,0 +1,225 @@
/*
* mux.c
*
* Pinmux Setting for B&R LEIT Board(s)
*
* Copyright (C) 2013 Hannes Petermaier <oe5hpm@oevsv.at>
* Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/hardware.h>
#include <asm/arch/mux.h>
#include <asm/io.h>
#include <i2c.h>
static struct module_pin_mux uart0_pin_mux[] = {
/* UART0_CTS */
{OFFSET(uart0_ctsn), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)},
/* UART0_RXD */
{OFFSET(uart0_rxd), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)},
/* UART0_TXD */
{OFFSET(uart0_txd), (MODE(0) | PULLUDEN)},
{-1},
};
#ifdef CONFIG_MMC
static struct module_pin_mux mmc1_pin_mux[] = {
{OFFSET(gpmc_ad3), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT3 */
{OFFSET(gpmc_ad2), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT2 */
{OFFSET(gpmc_ad1), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT1 */
{OFFSET(gpmc_ad0), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT0 */
{OFFSET(gpmc_csn1), (MODE(2) | RXACTIVE | PULLUP_EN)}, /* MMC1_CLK */
{OFFSET(gpmc_csn2), (MODE(2) | RXACTIVE | PULLUP_EN)}, /* MMC1_CMD */
{OFFSET(gpmc_csn0), (MODE(7) | RXACTIVE | PULLUP_EN)}, /* MMC1_WP */
{OFFSET(gpmc_advn_ale), (MODE(7) | RXACTIVE | PULLUP_EN)},/* MMC1_CD */
{-1},
};
#endif
static struct module_pin_mux i2c0_pin_mux[] = {
/* I2C_DATA */
{OFFSET(i2c0_sda), (MODE(0) | RXACTIVE | PULLUDEN | SLEWCTRL)},
/* I2C_SCLK */
{OFFSET(i2c0_scl), (MODE(0) | RXACTIVE | PULLUDEN | SLEWCTRL)},
{-1},
};
static struct module_pin_mux spi0_pin_mux[] = {
/* SPI0_SCLK */
{OFFSET(spi0_sclk), (MODE(0) | RXACTIVE | PULLUDEN | PULLUP_EN)},
/* SPI0_D0 */
{OFFSET(spi0_d0), (MODE(0) | RXACTIVE | PULLUDEN | PULLUP_EN)},
/* SPI0_D1 */
{OFFSET(spi0_d1), (MODE(0) | RXACTIVE | PULLUDEN | PULLUP_EN)},
/* SPI0_CS0 */
{OFFSET(spi0_cs0), (MODE(0) | RXACTIVE | PULLUDEN | PULLUP_EN)},
{-1},
};
static struct module_pin_mux mii1_pin_mux[] = {
{OFFSET(mii1_rxerr), MODE(0) | RXACTIVE}, /* MII1_RXERR */
{OFFSET(mii1_txen), MODE(0)}, /* MII1_TXEN */
{OFFSET(mii1_rxdv), MODE(0) | RXACTIVE}, /* MII1_RXDV */
{OFFSET(mii1_txd3), MODE(0)}, /* MII1_TXD3 */
{OFFSET(mii1_txd2), MODE(0)}, /* MII1_TXD2 */
{OFFSET(mii1_txd1), MODE(0)}, /* MII1_TXD1 */
{OFFSET(mii1_txd0), MODE(0)}, /* MII1_TXD0 */
{OFFSET(mii1_txclk), MODE(0) | RXACTIVE}, /* MII1_TXCLK */
{OFFSET(mii1_rxclk), MODE(0) | RXACTIVE}, /* MII1_RXCLK */
{OFFSET(mii1_rxd3), MODE(0) | RXACTIVE}, /* MII1_RXD3 */
{OFFSET(mii1_rxd2), MODE(0) | RXACTIVE}, /* MII1_RXD2 */
{OFFSET(mii1_rxd1), MODE(0) | RXACTIVE}, /* MII1_RXD1 */
{OFFSET(mii1_rxd0), MODE(0) | RXACTIVE}, /* MII1_RXD0 */
{OFFSET(mdio_data), MODE(0) | RXACTIVE | PULLUP_EN},/* MDIO_DATA */
{OFFSET(mdio_clk), MODE(0) | PULLUP_EN}, /* MDIO_CLK */
{-1},
};
static struct module_pin_mux mii2_pin_mux[] = {
{OFFSET(gpmc_a0), MODE(1)}, /* MII2_TXEN */
{OFFSET(gpmc_a1), MODE(1) | RXACTIVE}, /* MII2_RXDV */
{OFFSET(gpmc_a2), MODE(1)}, /* MII2_TXD3 */
{OFFSET(gpmc_a3), MODE(1)}, /* MII2_TXD2 */
{OFFSET(gpmc_a4), MODE(1)}, /* MII2_TXD1 */
{OFFSET(gpmc_a5), MODE(1)}, /* MII2_TXD0 */
{OFFSET(gpmc_a6), MODE(1) | RXACTIVE}, /* MII2_TXCLK */
{OFFSET(gpmc_a7), MODE(1) | RXACTIVE}, /* MII2_RXCLK */
{OFFSET(gpmc_a8), MODE(1) | RXACTIVE}, /* MII2_RXD3 */
{OFFSET(gpmc_a9), MODE(1) | RXACTIVE}, /* MII2_RXD2 */
{OFFSET(gpmc_a10), MODE(1) | RXACTIVE}, /* MII2_RXD1 */
{OFFSET(gpmc_a11), MODE(1) | RXACTIVE}, /* MII2_RXD0 */
{OFFSET(gpmc_wpn), (MODE(1) | RXACTIVE)},/* MII2_RXERR */
/*
* MII2_CRS is shared with
* NAND_WAIT0
*/
{OFFSET(gpmc_be1n), (MODE(1) | RXACTIVE)},/* MII1_COL */
{-1},
};
#ifdef CONFIG_NAND
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},
};
#endif
static struct module_pin_mux gpIOs[] = {
/* GPIO0_6 (SPI0_CS1) - 3v3_PWR_nEN (Display Power Supply) */
{OFFSET(spi0_cs1), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)},
/* TIMER5 (MMC0_DAT3) - TIMER5 (Buzzer) */
{OFFSET(mmc0_dat3), (MODE(3) | PULLUDEN | RXACTIVE)},
/* TIMER6 (MMC0_DAT2) - PWM_BACK_3V3, later used as MODE3 for PWM */
{OFFSET(mmc0_dat2), (MODE(7) | PULLUDEN | RXACTIVE)},
/* GPIO2_28 (MMC0_DAT1) - MII_nNAND */
{OFFSET(mmc0_dat1), (MODE(7) | PULLUDEN | RXACTIVE)},
/* GPIO2_29 (MMC0_DAT0) - NAND_1n0 */
{OFFSET(mmc0_dat0), (MODE(7) | PULLUDEN | RXACTIVE)},
/* GPIO2_30 (MMC0_CLK) - nRESET (PHY) */
{OFFSET(mmc0_clk), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)},
/* GPIO3_18 (MCASP0_ACLKR) - CPLD JTAG TDI */
{OFFSET(mcasp0_aclkr), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)},
/* GPIO3_19 (MCASP0_FSR) - CPLD JTAG TMS */
{OFFSET(mcasp0_fsr), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)},
/* GPIO3_20 (MCASP0_AXR1) - CPLD JTAG TCK */
{OFFSET(mcasp0_axr1), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)},
/* GPIO3_21 (MCASP0_AHCLKX) - CPLD JTAG TDO */
{OFFSET(mcasp0_ahclkx), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)},
/* GPIO2_0 (GPMC_nCS3) - DCOK */
{OFFSET(gpmc_csn3), (MODE(7) | PULLUDDIS | RXACTIVE) },
/* GPIO0_29 (RMII1_REFCLK) - eMMC nRST */
{OFFSET(rmii1_refclk), (MODE(7) | PULLUDDIS | RXACTIVE) },
/*
* GPIO0_7 (PWW0 OUT)
* DISPLAY_ONOFF (Backlight Enable at LVDS Versions)
*/
{OFFSET(ecap0_in_pwm0_out), (MODE(7) | PULLUDEN | RXACTIVE)},
/* GPIO0_19 (DMA_INTR0) - ISPLAY_MODE (CPLD) */
{OFFSET(xdma_event_intr0), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)},
/* GPIO0_20 (DMA_INTR1) - REP-Switch */
{OFFSET(xdma_event_intr1), (MODE(7) | PULLUP_EN | RXACTIVE)},
/* GPIO3_14 (MCASP0_ACLKX) - frei / PP709 */
{OFFSET(mcasp0_aclkx), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE) },
/* GPIO3_15 (MCASP0_FSX) - PMIC_nRESET */
{OFFSET(mcasp0_fsx), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE) },
/* GPIO3_16 (MCASP0_AXR0) - ETH1_LEDY */
{OFFSET(mcasp0_axr0), (MODE(7) | PULLUDDIS) },
/* GPIO3_17 (MCASP0_AHCLKR) - ETH2_LEDY */
{OFFSET(mcasp0_ahclkr), (MODE(7) | PULLUDDIS) },
{-1},
};
static struct module_pin_mux lcd_pin_mux[] = {
{OFFSET(lcd_data0), (MODE(0) | PULLUDDIS)}, /* LCD-Data(0) */
{OFFSET(lcd_data1), (MODE(0) | PULLUDDIS)}, /* LCD-Data(1) */
{OFFSET(lcd_data2), (MODE(0) | PULLUDDIS)}, /* LCD-Data(2) */
{OFFSET(lcd_data3), (MODE(0) | PULLUDDIS)}, /* LCD-Data(3) */
{OFFSET(lcd_data4), (MODE(0) | PULLUDDIS)}, /* LCD-Data(4) */
{OFFSET(lcd_data5), (MODE(0) | PULLUDDIS)}, /* LCD-Data(5) */
{OFFSET(lcd_data6), (MODE(0) | PULLUDDIS)}, /* LCD-Data(6) */
{OFFSET(lcd_data7), (MODE(0) | PULLUDDIS)}, /* LCD-Data(7) */
{OFFSET(lcd_data8), (MODE(0) | PULLUDDIS)}, /* LCD-Data(8) */
{OFFSET(lcd_data9), (MODE(0) | PULLUDDIS)}, /* LCD-Data(9) */
{OFFSET(lcd_data10), (MODE(0) | PULLUDDIS)}, /* LCD-Data(10) */
{OFFSET(lcd_data11), (MODE(0) | PULLUDDIS)}, /* LCD-Data(11) */
{OFFSET(lcd_data12), (MODE(0) | PULLUDDIS)}, /* LCD-Data(12) */
{OFFSET(lcd_data13), (MODE(0) | PULLUDDIS)}, /* LCD-Data(13) */
{OFFSET(lcd_data14), (MODE(0) | PULLUDDIS)}, /* LCD-Data(14) */
{OFFSET(lcd_data15), (MODE(0) | PULLUDDIS)}, /* LCD-Data(15) */
{OFFSET(gpmc_ad8), (MODE(1) | PULLUDDIS)}, /* LCD-Data(16) */
{OFFSET(gpmc_ad9), (MODE(1) | PULLUDDIS)}, /* LCD-Data(17) */
{OFFSET(gpmc_ad10), (MODE(1) | PULLUDDIS)}, /* LCD-Data(18) */
{OFFSET(gpmc_ad11), (MODE(1) | PULLUDDIS)}, /* LCD-Data(19) */
{OFFSET(gpmc_ad12), (MODE(1) | PULLUDDIS)}, /* LCD-Data(20) */
{OFFSET(gpmc_ad13), (MODE(1) | PULLUDDIS)}, /* LCD-Data(21) */
{OFFSET(gpmc_ad14), (MODE(1) | PULLUDDIS)}, /* LCD-Data(22) */
{OFFSET(gpmc_ad15), (MODE(1) | PULLUDDIS)}, /* LCD-Data(23) */
{OFFSET(lcd_vsync), (MODE(0) | PULLUDDIS)}, /* LCD-VSync */
{OFFSET(lcd_hsync), (MODE(0) | PULLUDDIS)}, /* LCD-HSync */
{OFFSET(lcd_ac_bias_en), (MODE(0) | PULLUDDIS)},/* LCD-DE */
{OFFSET(lcd_pclk), (MODE(0) | PULLUDDIS)}, /* LCD-CLK */
{-1},
};
void enable_uart0_pin_mux(void)
{
configure_module_pin_mux(uart0_pin_mux);
}
void enable_i2c0_pin_mux(void)
{
configure_module_pin_mux(i2c0_pin_mux);
}
void enable_board_pin_mux(void)
{
configure_module_pin_mux(i2c0_pin_mux);
configure_module_pin_mux(mii1_pin_mux);
configure_module_pin_mux(mii2_pin_mux);
#ifdef CONFIG_NAND
configure_module_pin_mux(nand_pin_mux);
#elif defined(CONFIG_MMC)
configure_module_pin_mux(mmc1_pin_mux);
#endif
configure_module_pin_mux(spi0_pin_mux);
configure_module_pin_mux(lcd_pin_mux);
configure_module_pin_mux(gpIOs);
}

View file

@ -48,5 +48,9 @@ SECTIONS
} >.sram } >.sram
__image_copy_end = .; __image_copy_end = .;
_end = .;
.end :
{
*(.__end)
}
} }

View file

@ -183,7 +183,7 @@ cm_remap:
/* Now 0x00000000 is writeable, replace the vectors */ /* Now 0x00000000 is writeable, replace the vectors */
ldr r0, =_start /* r0 <- start of vectors */ ldr r0, =_start /* r0 <- start of vectors */
ldr r2, =_TEXT_BASE /* r2 <- past vectors */ add r2, r0, #64 /* r2 <- past vectors */
sub r1,r1,r1 /* destination 0x00000000 */ sub r1,r1,r1 /* destination 0x00000000 */
copy_vec: copy_vec:

View file

@ -0,0 +1,7 @@
#
# Copyright 2013 Broadcom Corporation.
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += $(BOARD).o

View file

@ -0,0 +1,87 @@
/*
* Copyright 2013 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <mmc.h>
#include <asm/kona-common/kona_sdhci.h>
#include <asm/kona-common/clk.h>
#include <asm/arch/sysmap.h>
#define SECWATCHDOG_SDOGCR_OFFSET 0x00000000
#define SECWATCHDOG_SDOGCR_EN_SHIFT 27
#define SECWATCHDOG_SDOGCR_SRSTEN_SHIFT 26
#define SECWATCHDOG_SDOGCR_CLKS_SHIFT 20
#define SECWATCHDOG_SDOGCR_LD_SHIFT 0
DECLARE_GLOBAL_DATA_PTR;
/*
* board_init - early hardware init
*/
int board_init(void)
{
printf("Relocation Offset is: %08lx\n", gd->reloc_off);
/* adress of boot parameters */
gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
clk_init();
return 0;
}
/*
* misc_init_r - miscellaneous platform dependent initializations
*/
int misc_init_r(void)
{
/* Disable watchdog reset - watchdog unused */
writel((0 << SECWATCHDOG_SDOGCR_EN_SHIFT) |
(0 << SECWATCHDOG_SDOGCR_SRSTEN_SHIFT) |
(4 << SECWATCHDOG_SDOGCR_CLKS_SHIFT) |
(0x5a0 << SECWATCHDOG_SDOGCR_LD_SHIFT),
(SECWD_BASE_ADDR + SECWATCHDOG_SDOGCR_OFFSET));
return 0;
}
/*
* dram_init - sets uboots idea of sdram size
*/
int dram_init(void)
{
gd->ram_size = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE,
CONFIG_SYS_SDRAM_SIZE);
return 0;
}
/* This is called after dram_init() so use get_ram_size result */
void dram_init_banksize(void)
{
gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
gd->bd->bi_dram[0].size = gd->ram_size;
}
#ifdef CONFIG_KONA_SDHCI
/*
* mmc_init - Initializes mmc
*/
int board_mmc_init(bd_t *bis)
{
int ret = 0;
/* Register eMMC - SDIO2 */
ret = kona_sdhci_init(1, 400000, 0);
if (ret)
return ret;
/* Register SD Card - SDIO4 kona_mmc_init assumes 0 based index */
ret = kona_sdhci_init(3, 400000, 0);
return ret;
}
#endif

View file

@ -57,7 +57,7 @@ unsigned long flash_init (void)
*/ */
flash_protect (FLAG_PROTECT_SET, flash_protect (FLAG_PROTECT_SET,
CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE,
CONFIG_SYS_FLASH_BASE + _bss_start_ofs, CONFIG_SYS_FLASH_BASE + (__bss_end - __bss_start),
&flash_info[0]); &flash_info[0]);
return size; return size;

View file

@ -57,7 +57,7 @@ unsigned long flash_init (void)
*/ */
flash_protect (FLAG_PROTECT_SET, flash_protect (FLAG_PROTECT_SET,
CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE,
CONFIG_SYS_FLASH_BASE + _bss_start_ofs, CONFIG_SYS_FLASH_BASE + (__bss_end - __bss_start),
&flash_info[0]); &flash_info[0]);
return size; return size;

View file

@ -61,7 +61,12 @@ SECTIONS
*(.__rel_dyn_end) *(.__rel_dyn_end)
} }
_end = .; .end :
{
*(.__end)
}
_image_binary_end = .;
/* /*
* Deprecated: this MMU section is used by pxa at present but * Deprecated: this MMU section is used by pxa at present but
@ -92,10 +97,14 @@ SECTIONS
KEEP(*(.__bss_end)); KEEP(*(.__bss_end));
} }
/DISCARD/ : { *(.dynsym) } .dynsym _image_binary_end : { *(.dynsym) }
/DISCARD/ : { *(.dynstr*) } .hash : { *(.hash) }
/DISCARD/ : { *(.dynamic*) } .got.plt : { *(.got.plt) }
/DISCARD/ : { *(.plt*) } .dynbss : { *(.dynbss) }
/DISCARD/ : { *(.interp*) } .dynstr : { *(.dynstr*) }
/DISCARD/ : { *(.gnu*) } .dynamic : { *(.dynamic*) }
.plt : { *(.plt*) }
.interp : { *(.interp*) }
.gnu : { *(.gnu*) }
.ARM.exidx : { *(.ARM.exidx*) }
} }

View file

@ -49,5 +49,9 @@ SECTIONS
} >.sram } >.sram
__image_copy_end = .; __image_copy_end = .;
_end = .;
.end :
{
*(.__end)
}
} }

View file

@ -61,5 +61,8 @@ SECTIONS
__bss_end = .; __bss_end = .;
} }
_end = .; .end :
{
*(.__end)
}
} }

View file

@ -69,7 +69,12 @@ SECTIONS
*(.__rel_dyn_end) *(.__rel_dyn_end)
} }
_end = .; .end :
{
*(.__end)
}
_image_binary_end = .;
/* /*
* Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c
@ -90,7 +95,7 @@ SECTIONS
KEEP(*(.__bss_end)); KEEP(*(.__bss_end));
} }
.dynsym _end : { *(.dynsym) } .dynsym _image_binary_end : { *(.dynsym) }
.dynbss : { *(.dynbss) } .dynbss : { *(.dynbss) }
.dynstr : { *(.dynstr*) } .dynstr : { *(.dynstr*) }
.dynamic : { *(.dynamic*) } .dynamic : { *(.dynamic*) }

View file

@ -325,8 +325,6 @@ const omap3_sysinfo sysinfo = {
MUX_VAL(CP(SYS_32K), (IEN | PTD | EN | M4)) \ MUX_VAL(CP(SYS_32K), (IEN | PTD | EN | M4)) \
MUX_VAL(CP(SYS_CLKREQ), (IEN | PTD | DIS | M0)) \ MUX_VAL(CP(SYS_CLKREQ), (IEN | PTD | DIS | M0)) \
MUX_VAL(CP(SYS_NIRQ), (IEN | PTD | EN | M4)) \ MUX_VAL(CP(SYS_NIRQ), (IEN | PTD | EN | M4)) \
MUX_VAL(CP(SYS_NRESWARM), (IEN | PTU | DIS | M4)) \
/* SYS_nRESWARM */\
MUX_VAL(CP(SYS_BOOT0), (IEN | PTD | DIS | M4)) \ MUX_VAL(CP(SYS_BOOT0), (IEN | PTD | DIS | M4)) \
MUX_VAL(CP(SYS_BOOT1), (IEN | PTD | DIS | M4)) \ MUX_VAL(CP(SYS_BOOT1), (IEN | PTD | DIS | M4)) \
MUX_VAL(CP(SYS_BOOT2), (IEN | PTD | DIS | M4)) \ MUX_VAL(CP(SYS_BOOT2), (IEN | PTD | DIS | M4)) \

View file

@ -197,13 +197,10 @@
#define REFCNT_266 0 #define REFCNT_266 0
/**************************************/ /**************************************/
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE
.globl lowlevel_init .globl lowlevel_init
lowlevel_init: lowlevel_init:
/* use r0 to relocate DATA read/write to flash rather than memory ! */ /* use r0 to relocate DATA read/write to flash rather than memory ! */
ldr r0, _TEXT_BASE ldr r0, =CONFIG_SYS_TEXT_BASE
ldr r13, =BWSCON ldr r13, =BWSCON
/* enable minimal access to PLD */ /* enable minimal access to PLD */

View file

@ -42,7 +42,11 @@ SECTIONS
. = ALIGN(4); . = ALIGN(4);
__image_copy_end = .; __image_copy_end = .;
_end = .;
.end :
{
*(.__end)
} >.sram
.bss : .bss :
{ {

View file

@ -22,9 +22,6 @@
* r9 has Mobile DDR size, 1 means 1GiB, 2 means 2GiB and so on * r9 has Mobile DDR size, 1 means 1GiB, 2 means 2GiB and so on
*/ */
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE
.globl lowlevel_init .globl lowlevel_init
lowlevel_init: lowlevel_init:
mov r11, lr mov r11, lr

View file

@ -110,16 +110,13 @@
#define REFCNT 1113 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */ #define REFCNT 1113 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
/**************************************/ /**************************************/
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE
.globl lowlevel_init .globl lowlevel_init
lowlevel_init: lowlevel_init:
/* memory control configuration */ /* memory control configuration */
/* make r0 relative the current location so that it */ /* make r0 relative the current location so that it */
/* reads SMRDATA out of FLASH rather than memory ! */ /* reads SMRDATA out of FLASH rather than memory ! */
ldr r0, =SMRDATA ldr r0, =SMRDATA
ldr r1, _TEXT_BASE ldr r1, =CONFIG_SYS_TEXT_BASE
sub r0, r0, r1 sub r0, r0, r1
ldr r1, =BWSCON /* Bus Width Status Controller */ ldr r1, =BWSCON /* Bus Width Status Controller */
add r2, r0, #13*4 add r2, r0, #13*4

View file

@ -17,9 +17,6 @@
* r5 has zero always * r5 has zero always
*/ */
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE
.globl lowlevel_init .globl lowlevel_init
lowlevel_init: lowlevel_init:
mov r9, lr mov r9, lr

View file

@ -0,0 +1,13 @@
#
# Makefile
#
# Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
#
# SPDX-License-Identifier: GPL-2.0+
#
ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_NOR_BOOT),y)
obj-y := mux.o
endif
obj-y += board.o

View file

@ -0,0 +1,207 @@
/*
* board.c
*
* Copyright (C) 2013 Lothar Felten <lothar.felten@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/arch/cpu.h>
#include <asm/arch/hardware.h>
#include <asm/arch/ddr_defs.h>
#include <asm/arch/clock.h>
#include <asm/arch/sys_proto.h>
#include <i2c.h>
#include <phy.h>
#include <cpsw.h>
#include "board.h"
DECLARE_GLOBAL_DATA_PTR;
static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
#if defined(CONFIG_SPL_BUILD)
/* DDR3 RAM timings */
static const struct ddr_data ddr3_data = {
.datardsratio0 = MT41K128MJT187E_RD_DQS,
.datawdsratio0 = MT41K128MJT187E_WR_DQS,
.datafwsratio0 = MT41K128MJT187E_PHY_FIFO_WE,
.datawrsratio0 = MT41K128MJT187E_PHY_WR_DATA,
};
static const struct cmd_control ddr3_cmd_ctrl_data = {
.cmd0csratio = MT41K128MJT187E_RATIO,
.cmd0iclkout = MT41K128MJT187E_INVERT_CLKOUT,
.cmd1csratio = MT41K128MJT187E_RATIO,
.cmd1iclkout = MT41K128MJT187E_INVERT_CLKOUT,
.cmd2csratio = MT41K128MJT187E_RATIO,
.cmd2iclkout = MT41K128MJT187E_INVERT_CLKOUT,
};
static struct emif_regs ddr3_emif_reg_data = {
.sdram_config = MT41K128MJT187E_EMIF_SDCFG,
.ref_ctrl = MT41K128MJT187E_EMIF_SDREF,
.sdram_tim1 = MT41K128MJT187E_EMIF_TIM1,
.sdram_tim2 = MT41K128MJT187E_EMIF_TIM2,
.sdram_tim3 = MT41K128MJT187E_EMIF_TIM3,
.zq_config = MT41K128MJT187E_ZQ_CFG,
.emif_ddr_phy_ctlr_1 = MT41K128MJT187E_EMIF_READ_LATENCY |
PHY_EN_DYN_PWRDN,
};
const struct ctrl_ioregs ddr3_ioregs = {
.cm0ioctl = MT41K128MJT187E_IOCTRL_VALUE,
.cm1ioctl = MT41K128MJT187E_IOCTRL_VALUE,
.cm2ioctl = MT41K128MJT187E_IOCTRL_VALUE,
.dt0ioctl = MT41K128MJT187E_IOCTRL_VALUE,
.dt1ioctl = MT41K128MJT187E_IOCTRL_VALUE,
};
#ifdef CONFIG_SPL_OS_BOOT
int spl_start_uboot(void)
{
/* break into full u-boot on 'c' */
return serial_tstc() && serial_getc() == 'c';
}
#endif
#define OSC (V_OSCK/1000000)
const struct dpll_params dpll_ddr_266 = {
266, OSC-1, 1, -1, -1, -1, -1};
const struct dpll_params dpll_ddr_303 = {
303, OSC-1, 1, -1, -1, -1, -1};
const struct dpll_params dpll_ddr_400 = {
400, OSC-1, 1, -1, -1, -1, -1};
void am33xx_spl_board_init(void)
{
/*
* The pengwyn board uses the TPS650250 PMIC without I2C
* interface and will output the following fixed voltages:
* DCDC1=3V3 (IO) DCDC2=1V5 (DDR) DCDC3=1V26 (Vmpu)
* VLDO1=1V8 (IO) VLDO2=1V8(IO)
* Vcore=1V1 is fixed, generated by TPS62231
*/
/* Get the frequency */
dpll_mpu_opp100.m = am335x_get_efuse_mpu_max_freq(cdev);
/* Set CORE Frequencies to OPP100 */
do_setup_dpll(&dpll_core_regs, &dpll_core_opp100);
/* 720MHz cpu, this might change on newer board revisions */
dpll_mpu_opp100.m = MPUPLL_M_720;
do_setup_dpll(&dpll_mpu_regs, &dpll_mpu_opp100);
}
const struct dpll_params *get_dpll_ddr_params(void)
{
/* future configs can return other clock settings */
return &dpll_ddr_303;
}
void set_uart_mux_conf(void)
{
enable_uart0_pin_mux();
}
void set_mux_conf_regs(void)
{
enable_board_pin_mux();
}
void sdram_init(void)
{
config_ddr(303, &ddr3_ioregs, &ddr3_data,
&ddr3_cmd_ctrl_data, &ddr3_emif_reg_data, 0);
}
#endif /* if CONFIG_SPL_BUILD */
/*
* Basic board specific setup. Pinmux has been handled already.
*/
int board_init(void)
{
i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
gpmc_init();
return 0;
}
#ifdef CONFIG_DRIVER_TI_CPSW
static void cpsw_control(int enabled)
{
/* VTP can be added here */
return;
}
static struct cpsw_slave_data cpsw_slaves[] = {
{
.slave_reg_ofs = 0x208,
.sliver_reg_ofs = 0xd80,
.phy_id = 0,
.phy_if = PHY_INTERFACE_MODE_MII,
},
{
.slave_reg_ofs = 0x308,
.sliver_reg_ofs = 0xdc0,
.phy_id = 1,
.phy_if = PHY_INTERFACE_MODE_MII,
},
};
static struct cpsw_platform_data cpsw_data = {
.mdio_base = CPSW_MDIO_BASE,
.cpsw_base = CPSW_BASE,
.mdio_div = 0xff,
.channels = 8,
.cpdma_reg_ofs = 0x800,
.slaves = 1,
.slave_data = cpsw_slaves,
.ale_reg_ofs = 0xd00,
.ale_entries = 1024,
.host_port_reg_ofs = 0x108,
.hw_stats_reg_ofs = 0x900,
.bd_ram_ofs = 0x2000,
.mac_control = (1 << 5),
.control = cpsw_control,
.host_port_num = 0,
.version = CPSW_CTRL_VERSION_2,
};
int board_eth_init(bd_t *bis)
{
int rv, n = 0;
uint8_t mac_addr[6];
uint32_t mac_hi, mac_lo;
if (!eth_getenv_enetaddr("ethaddr", mac_addr)) {
printf("<ethaddr> not set. Reading from E-fuse\n");
/* try reading mac address from efuse */
mac_lo = readl(&cdev->macid0l);
mac_hi = readl(&cdev->macid0h);
mac_addr[0] = mac_hi & 0xFF;
mac_addr[1] = (mac_hi & 0xFF00) >> 8;
mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
mac_addr[4] = mac_lo & 0xFF;
mac_addr[5] = (mac_lo & 0xFF00) >> 8;
if (is_valid_ether_addr(mac_addr))
eth_setenv_enetaddr("ethaddr", mac_addr);
else
return n;
}
writel(MII_MODE_ENABLE, &cdev->miisel);
rv = cpsw_register(&cpsw_data);
if (rv < 0)
printf("Error %d registering CPSW switch\n", rv);
else
n += rv;
return n;
}
#endif /* if CONFIG_DRIVER_TI_CPSW */

View file

@ -0,0 +1,15 @@
/*
* board.h
*
* Copyright (C) 2013 Lothar Felten <lothar.felten@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _BOARD_H_
#define _BOARD_H_
void enable_uart0_pin_mux(void);
void enable_board_pin_mux(void);
#endif

View file

@ -0,0 +1,98 @@
/*
* mux.c
*
* Copyright (C) 2013 Lothar Felten <lothar.felten@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/hardware.h>
#include <asm/arch/mux.h>
#include <asm/io.h>
#include "board.h"
/* UART0 pins E15(rx),E16(tx) [E17(rts),E18(cts)] */
static struct module_pin_mux uart0_pin_mux[] = {
{OFFSET(uart0_rxd), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* UART0_RXD */
{OFFSET(uart0_txd), (MODE(0) | PULLUDEN)}, /* UART0_TXD */
{-1},
};
/* unused: UART1 pins D15(tx),D16(rx),D17(cts),D18(rts) */
/* I2C pins C16(scl)/C17(sda) */
static struct module_pin_mux i2c0_pin_mux[] = {
{OFFSET(i2c0_sda), (MODE(0) | RXACTIVE |
PULLUDEN | SLEWCTRL)}, /* I2C0_DATA */
{OFFSET(i2c0_scl), (MODE(0) | RXACTIVE |
PULLUDEN | SLEWCTRL)}, /* I2C0_SCLK */
{-1},
};
/* MMC0 pins */
static struct module_pin_mux mmc0_pin_mux[] = {
{OFFSET(mmc0_dat3), (MODE(0) | RXACTIVE | PULLUP_EN)}, /* MMC0_DAT3 */
{OFFSET(mmc0_dat2), (MODE(0) | RXACTIVE | PULLUP_EN)}, /* MMC0_DAT2 */
{OFFSET(mmc0_dat1), (MODE(0) | RXACTIVE | PULLUP_EN)}, /* MMC0_DAT1 */
{OFFSET(mmc0_dat0), (MODE(0) | RXACTIVE | PULLUP_EN)}, /* MMC0_DAT0 */
{OFFSET(mmc0_clk), (MODE(0) | RXACTIVE | PULLUP_EN)}, /* MMC0_CLK */
{OFFSET(mmc0_cmd), (MODE(0) | RXACTIVE | PULLUP_EN)}, /* MMC0_CMD */
{OFFSET(spi0_cs1), (MODE(5) | RXACTIVE | PULLUP_EN)}, /* MMC0_CD */
{-1},
};
/* MII pins */
static struct module_pin_mux mii1_pin_mux[] = {
{OFFSET(mii1_rxerr), MODE(0) | RXACTIVE}, /* MII1_RXERR */
{OFFSET(mii1_txen), MODE(0)}, /* MII1_TXEN */
{OFFSET(mii1_rxdv), MODE(0) | RXACTIVE}, /* MII1_RXDV */
{OFFSET(mii1_txd3), MODE(0)}, /* MII1_TXD3 */
{OFFSET(mii1_txd2), MODE(0)}, /* MII1_TXD2 */
{OFFSET(mii1_txd1), MODE(0)}, /* MII1_TXD1 */
{OFFSET(mii1_txd0), MODE(0)}, /* MII1_TXD0 */
{OFFSET(mii1_txclk), MODE(0) | RXACTIVE}, /* MII1_TXCLK */
{OFFSET(mii1_rxclk), MODE(0) | RXACTIVE}, /* MII1_RXCLK */
{OFFSET(mii1_rxd3), MODE(0) | RXACTIVE}, /* MII1_RXD3 */
{OFFSET(mii1_rxd2), MODE(0) | RXACTIVE}, /* MII1_RXD2 */
{OFFSET(mii1_rxd1), MODE(0) | RXACTIVE}, /* MII1_RXD1 */
{OFFSET(mii1_rxd0), MODE(0) | RXACTIVE}, /* MII1_RXD0 */
{OFFSET(mdio_data), MODE(0) | RXACTIVE | PULLUP_EN}, /* MDIO_DATA */
{OFFSET(mdio_clk), MODE(0) | PULLUP_EN}, /* MDIO_CLK */
{-1},
};
/* NAND pins */
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},
};
void enable_uart0_pin_mux(void)
{
configure_module_pin_mux(uart0_pin_mux);
}
void enable_board_pin_mux()
{
configure_module_pin_mux(i2c0_pin_mux);
configure_module_pin_mux(uart0_pin_mux);
configure_module_pin_mux(mii1_pin_mux);
configure_module_pin_mux(mmc0_pin_mux);
configure_module_pin_mux(nand_pin_mux);
}

View file

@ -77,7 +77,12 @@ SECTIONS
*(.__rel_dyn_end) *(.__rel_dyn_end)
} }
_end = .; .end :
{
*(.__end)
}
_image_binary_end = .;
/* /*
* Deprecated: this MMU section is used by pxa at present but * Deprecated: this MMU section is used by pxa at present but
@ -108,7 +113,7 @@ SECTIONS
KEEP(*(.__bss_end)); KEEP(*(.__bss_end));
} }
.dynsym _end : { *(.dynsym) } .dynsym _image_binary_end : { *(.dynsym) }
.dynbss : { *(.dynbss) } .dynbss : { *(.dynbss) }
.dynstr : { *(.dynstr*) } .dynstr : { *(.dynstr*) }
.dynamic : { *(.dynamic*) } .dynamic : { *(.dynamic*) }

View file

@ -346,14 +346,14 @@ static void enable_vtt_regulator(void)
u32 temp; u32 temp;
/* enable module */ /* enable module */
writel(GPIO_CTRL_ENABLEMODULE, AM33XX_GPIO0_BASE + OMAP_GPIO_CTRL); writel(GPIO_CTRL_ENABLEMODULE, AM33XX_GPIO5_BASE + OMAP_GPIO_CTRL);
/* enable output for GPIO0_22 */ /* enable output for GPIO5_7 */
writel(GPIO_SETDATAOUT(GPIO_22), writel(GPIO_SETDATAOUT(7),
AM33XX_GPIO0_BASE + OMAP_GPIO_SETDATAOUT); AM33XX_GPIO5_BASE + OMAP_GPIO_SETDATAOUT);
temp = readl(AM33XX_GPIO0_BASE + OMAP_GPIO_OE); temp = readl(AM33XX_GPIO5_BASE + OMAP_GPIO_OE);
temp = temp & ~(GPIO_OE_ENABLE(GPIO_22)); temp = temp & ~(GPIO_OE_ENABLE(7));
writel(temp, AM33XX_GPIO0_BASE + OMAP_GPIO_OE); writel(temp, AM33XX_GPIO5_BASE + OMAP_GPIO_OE);
} }
void sdram_init(void) void sdram_init(void)

View file

@ -33,8 +33,8 @@ static struct module_pin_mux i2c0_pin_mux[] = {
{-1}, {-1},
}; };
static struct module_pin_mux gpio0_22_pin_mux[] = { static struct module_pin_mux gpio5_7_pin_mux[] = {
{OFFSET(ddr_ba2), (MODE(9) | PULLUP_EN)}, /* GPIO0_22 */ {OFFSET(spi0_cs0), (MODE(7) | PULLUP_EN)}, /* GPIO5_7 */
{-1}, {-1},
}; };
@ -59,7 +59,7 @@ void enable_board_pin_mux(void)
configure_module_pin_mux(i2c0_pin_mux); configure_module_pin_mux(i2c0_pin_mux);
if (board_is_gpevm()) if (board_is_gpevm())
configure_module_pin_mux(gpio0_22_pin_mux); configure_module_pin_mux(gpio5_7_pin_mux);
configure_module_pin_mux(qspi_pin_mux); configure_module_pin_mux(qspi_pin_mux);
} }

View file

@ -18,10 +18,6 @@
#include <./configs/omap1510.h> #include <./configs/omap1510.h>
#endif #endif
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE /* sdram load addr from config.mk */
.globl lowlevel_init .globl lowlevel_init
lowlevel_init: lowlevel_init:

View file

@ -54,7 +54,12 @@ SECTIONS
. = ALIGN(0x800); . = ALIGN(0x800);
_end = .; .end :
{
*(.__end)
}
_image_binary_end = .;
.bss __rel_dyn_start (OVERLAY) : { .bss __rel_dyn_start (OVERLAY) : {
__bss_start = .; __bss_start = .;
@ -63,7 +68,7 @@ SECTIONS
__bss_end = .; __bss_end = .;
} }
.dynsym _end : { *(.dynsym) } .dynsym _image_binary_end : { *(.dynsym) }
.dynbss : { *(.dynbss) } .dynbss : { *(.dynbss) }
.dynstr : { *(.dynstr*) } .dynstr : { *(.dynstr*) }
.dynamic : { *(.dynamic*) } .dynamic : { *(.dynamic*) }

View file

@ -259,6 +259,11 @@ Active arm armv7 am33xx phytec pcm051
Active arm armv7 am33xx siemens dxr2 dxr2 - Roger Meier <r.meier@siemens.com> Active arm armv7 am33xx siemens dxr2 dxr2 - Roger Meier <r.meier@siemens.com>
Active arm armv7 am33xx siemens pxm2 pxm2 - Roger Meier <r.meier@siemens.com> Active arm armv7 am33xx siemens pxm2 pxm2 - Roger Meier <r.meier@siemens.com>
Active arm armv7 am33xx siemens rut rut - Roger Meier <r.meier@siemens.com> Active arm armv7 am33xx siemens rut rut - Roger Meier <r.meier@siemens.com>
Active arm armv7 am33xx silica pengwyn pengwyn - Lothar Felten <lothar.felten@gmail.com>
Active arm armv7 am33xx BuR tseries tseries_nand tseries:SERIAL1,CONS_INDEX=1,NAND Hannes Petermaier <hannes.petermaier@br-automation.com>
Active arm armv7 am33xx BuR tseries tseries_mmc tseries:SERIAL1,CONS_INDEX=1,EMMC_BOOT Hannes Petermaier <hannes.petermaier@br-automation.com>
Active arm armv7 am33xx BuR tseries tseries_spi tseries:SERIAL1,CONS_INDEX=1,SPI_BOOT,EMMC_BOOT Hannes Petermaier <hannes.petermaier@br-automation.com>
Active arm armv7 am33xx BuR kwb kwb kwb:SERIAL1,CONS_INDEX=1 Hannes Petermaier <hannes.petermaier@br-automation.com>
Active arm armv7 am33xx ti am335x am335x_boneblack am335x_evm:SERIAL1,CONS_INDEX=1,EMMC_BOOT Tom Rini <trini@ti.com> Active arm armv7 am33xx ti am335x am335x_boneblack am335x_evm:SERIAL1,CONS_INDEX=1,EMMC_BOOT Tom Rini <trini@ti.com>
Active arm armv7 am33xx ti am335x am335x_evm am335x_evm:SERIAL1,CONS_INDEX=1,NAND Tom Rini <trini@ti.com> Active arm armv7 am33xx ti am335x am335x_evm am335x_evm:SERIAL1,CONS_INDEX=1,NAND Tom Rini <trini@ti.com>
Active arm armv7 am33xx ti am335x am335x_evm_nor am335x_evm:SERIAL1,CONS_INDEX=1,NAND,NOR Tom Rini <trini@ti.com> Active arm armv7 am33xx ti am335x am335x_evm_nor am335x_evm:SERIAL1,CONS_INDEX=1,NAND,NOR Tom Rini <trini@ti.com>
@ -276,6 +281,7 @@ Active arm armv7 am33xx ti ti816x
Active arm armv7 at91 atmel sama5d3xek sama5d3xek_mmc sama5d3xek:SAMA5D3,SYS_USE_MMC Bo Shen <voice.shen@atmel.com> Active arm armv7 at91 atmel sama5d3xek sama5d3xek_mmc sama5d3xek:SAMA5D3,SYS_USE_MMC Bo Shen <voice.shen@atmel.com>
Active arm armv7 at91 atmel sama5d3xek sama5d3xek_nandflash sama5d3xek:SAMA5D3,SYS_USE_NANDFLASH Bo Shen <voice.shen@atmel.com> Active arm armv7 at91 atmel sama5d3xek sama5d3xek_nandflash sama5d3xek:SAMA5D3,SYS_USE_NANDFLASH Bo Shen <voice.shen@atmel.com>
Active arm armv7 at91 atmel sama5d3xek sama5d3xek_spiflash sama5d3xek:SAMA5D3,SYS_USE_SERIALFLASH Bo Shen <voice.shen@atmel.com> Active arm armv7 at91 atmel sama5d3xek sama5d3xek_spiflash sama5d3xek:SAMA5D3,SYS_USE_SERIALFLASH Bo Shen <voice.shen@atmel.com>
Active arm armv7 bcm281xx broadcom bcm28155_ap bcm28155_ap bcm28155_ap Tim Kryger <tim.kryger@linaro.org>
Active arm armv7 exynos samsung arndale arndale - Inderpal Singh <inderpal.singh@linaro.org> Active arm armv7 exynos samsung arndale arndale - Inderpal Singh <inderpal.singh@linaro.org>
Active arm armv7 exynos samsung origen origen - Chander Kashyap <k.chander@samsung.com> Active arm armv7 exynos samsung origen origen - Chander Kashyap <k.chander@samsung.com>
Active arm armv7 exynos samsung smdk5250 smdk5250 - Chander Kashyap <k.chander@samsung.com> Active arm armv7 exynos samsung smdk5250 smdk5250 - Chander Kashyap <k.chander@samsung.com>

View file

@ -238,5 +238,3 @@ obj-y += memsize.o
obj-y += stdio.o obj-y += stdio.o
CFLAGS_env_embedded.o := -Wa,--no-warn -DENV_CRC=$(shell tools/envcrc 2>/dev/null) CFLAGS_env_embedded.o := -Wa,--no-warn -DENV_CRC=$(shell tools/envcrc 2>/dev/null)
CFLAGS_hush.o := $(PLATFORM_NO_UNALIGNED)
CFLAGS_fdt_support.o := $(PLATFORM_NO_UNALIGNED)

View file

@ -149,13 +149,9 @@ static int display_text_info(void)
#ifndef CONFIG_SANDBOX #ifndef CONFIG_SANDBOX
ulong bss_start, bss_end; ulong bss_start, bss_end;
#ifdef CONFIG_SYS_SYM_OFFSETS
bss_start = _bss_start_ofs + _TEXT_BASE;
bss_end = _bss_end_ofs + _TEXT_BASE;
#else
bss_start = (ulong)&__bss_start; bss_start = (ulong)&__bss_start;
bss_end = (ulong)&__bss_end; bss_end = (ulong)&__bss_end;
#endif
debug("U-Boot code: %08X -> %08lX BSS: -> %08lX\n", debug("U-Boot code: %08X -> %08lX BSS: -> %08lX\n",
CONFIG_SYS_TEXT_BASE, bss_start, bss_end); CONFIG_SYS_TEXT_BASE, bss_start, bss_end);
#endif #endif
@ -268,8 +264,8 @@ static int zero_global_data(void)
static int setup_mon_len(void) static int setup_mon_len(void)
{ {
#ifdef CONFIG_SYS_SYM_OFFSETS #ifdef __ARM__
gd->mon_len = _bss_end_ofs; gd->mon_len = (ulong)&__bss_end - (ulong)_start;
#elif defined(CONFIG_SANDBOX) #elif defined(CONFIG_SANDBOX)
gd->mon_len = (ulong)&_end - (ulong)_init; gd->mon_len = (ulong)&_end - (ulong)_init;
#else #else
@ -352,11 +348,7 @@ static int setup_fdt(void)
gd->fdt_blob = __dtb_dt_begin; gd->fdt_blob = __dtb_dt_begin;
#elif defined CONFIG_OF_SEPARATE #elif defined CONFIG_OF_SEPARATE
/* FDT is at end of image */ /* FDT is at end of image */
# ifdef CONFIG_SYS_SYM_OFFSETS
gd->fdt_blob = (void *)(_end_ofs + CONFIG_SYS_TEXT_BASE);
# else
gd->fdt_blob = (ulong *)&_end; gd->fdt_blob = (ulong *)&_end;
# endif
#elif defined(CONFIG_OF_HOSTFILE) #elif defined(CONFIG_OF_HOSTFILE)
if (read_fdt_from_file()) { if (read_fdt_from_file()) {
puts("Failed to read control FDT\n"); puts("Failed to read control FDT\n");

View file

@ -128,8 +128,8 @@ __weak int fixup_cpu(void)
static int initr_reloc_global_data(void) static int initr_reloc_global_data(void)
{ {
#ifdef CONFIG_SYS_SYM_OFFSETS #ifdef __ARM__
monitor_flash_len = _end_ofs; monitor_flash_len = _end - __image_copy_start;
#elif !defined(CONFIG_SANDBOX) #elif !defined(CONFIG_SANDBOX)
monitor_flash_len = (ulong)&__init_end - gd->relocaddr; monitor_flash_len = (ulong)&__init_end - gd->relocaddr;
#endif #endif

View file

@ -45,6 +45,7 @@ static char *from_env(const char *envvar)
return ret; return ret;
} }
#ifdef CONFIG_CMD_NET
/* /*
* Convert an ethaddr from the environment to the format used by pxelinux * Convert an ethaddr from the environment to the format used by pxelinux
* filenames based on mac addresses. Convert's ':' to '-', and adds "01-" to * filenames based on mac addresses. Convert's ':' to '-', and adds "01-" to
@ -75,6 +76,7 @@ static int format_mac_pxe(char *outbuf, size_t outbuf_len)
return 1; return 1;
} }
#endif
/* /*
* Returns the directory the file specified in the bootfile env variable is * Returns the directory the file specified in the bootfile env variable is
@ -120,6 +122,7 @@ static int get_bootfile_path(const char *file_path, char *bootfile_path,
static int (*do_getfile)(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr); static int (*do_getfile)(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr);
#ifdef CONFIG_CMD_NET
static int do_get_tftp(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr) static int do_get_tftp(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr)
{ {
char *tftp_argv[] = {"tftp", NULL, NULL, NULL}; char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
@ -132,6 +135,7 @@ static int do_get_tftp(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr)
return 1; return 1;
} }
#endif
static char *fs_argv[5]; static char *fs_argv[5];
@ -249,6 +253,8 @@ static int get_pxe_file(cmd_tbl_t *cmdtp, const char *file_path, void *file_addr
return 1; return 1;
} }
#ifdef CONFIG_CMD_NET
#define PXELINUX_DIR "pxelinux.cfg/" #define PXELINUX_DIR "pxelinux.cfg/"
/* /*
@ -397,6 +403,7 @@ do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
return 1; return 1;
} }
#endif
/* /*
* Wrapper to make it easier to store the file at file_path in the location * Wrapper to make it easier to store the file at file_path in the location
@ -647,6 +654,7 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
len += strlen(ip_str); len += strlen(ip_str);
} }
#ifdef CONFIG_CMD_NET
if (label->ipappend & 0x2) { if (label->ipappend & 0x2) {
int err; int err;
strcpy(mac_str, " BOOTIF="); strcpy(mac_str, " BOOTIF=");
@ -655,6 +663,7 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
mac_str[0] = '\0'; mac_str[0] = '\0';
len += strlen(mac_str); len += strlen(mac_str);
} }
#endif
if (label->append) if (label->append)
len += strlen(label->append); len += strlen(label->append);
@ -1503,6 +1512,7 @@ static void handle_pxe_menu(cmd_tbl_t *cmdtp, struct pxe_menu *cfg)
boot_unattempted_labels(cmdtp, cfg); boot_unattempted_labels(cmdtp, cfg);
} }
#ifdef CONFIG_CMD_NET
/* /*
* Boots a system using a pxe file * Boots a system using a pxe file
* *
@ -1579,6 +1589,7 @@ U_BOOT_CMD(
"get - try to retrieve a pxe file using tftp\npxe " "get - try to retrieve a pxe file using tftp\npxe "
"boot [pxefile_addr_r] - boot from the pxe file at pxefile_addr_r\n" "boot [pxefile_addr_r] - boot from the pxe file at pxefile_addr_r\n"
); );
#endif
/* /*
* Boots a system using a local disk syslinux/extlinux file * Boots a system using a local disk syslinux/extlinux file

View file

@ -1,122 +0,0 @@
If you are reading this because of a data abort: the following MIGHT
be relevant to your abort, if it was caused by an alignment violation.
In order to determine this, use the PC from the abort dump along with
an objdump -s -S of the u-boot ELF binary to locate the function where
the abort happened; then compare this function with the examples below.
If they match, then you've been hit with a compiler generated unaligned
access, and you should rewrite your code or add -mno-unaligned-access
to the command line of the offending file.
Note that the PC shown in the abort message is relocated. In order to
be able to match it to an address in the ELF binary dump, you will need
to know the relocation offset. If your target defines CONFIG_CMD_BDI
and if you can get to the prompt and enter commands before the abort
happens, then command "bdinfo" will give you the offset. Otherwise you
will need to try a build with DEBUG set, which will display the offset,
or use a debugger and set a breakpoint at relocate_code() to see the
offset (passed as an argument).
*
Since U-Boot runs on a variety of hardware, some only able to perform
unaligned accesses with a strong penalty, some unable to perform them
at all, the policy regarding unaligned accesses is to not perform any,
unless absolutely necessary because of hardware or standards.
Also, on hardware which permits it, the core is configured to throw
data abort exceptions on unaligned accesses in order to catch these
unallowed accesses as early as possible.
Until version 4.7, the gcc default for performing unaligned accesses
(-mno-unaligned-access) is to emulate unaligned accesses using aligned
loads and stores plus shifts and masks. Emulated unaligned accesses
will not be caught by hardware. These accesses may be costly and may
be actually unnecessary. In order to catch these accesses and remove
or optimize them, option -munaligned-access is explicitly set for all
versions of gcc which support it.
From gcc 4.7 onward starting at armv7 architectures, the default for
performing unaligned accesses is to use unaligned native loads and
stores (-munaligned-access), because the cost of unaligned accesses
has dropped on armv7 and beyond. This should not affect U-Boot's
policy of controlling unaligned accesses, however the compiler may
generate uncontrolled unaligned accesses on its own in at least one
known case: when declaring a local initialized char array, e.g.
function foo()
{
char buffer[] = "initial value";
/* or */
char buffer[] = { 'i', 'n', 'i', 't', 0 };
...
}
Under -munaligned-accesses with optimizations on, this declaration
causes the compiler to generate native loads from the literal string
and native stores to the buffer, and the literal string alignment
cannot be controlled. If it is misaligned, then the core will throw
a data abort exception.
Quite probably the same might happen for 16-bit array initializations
where the constant is aligned on a boundary which is a multiple of 2
but not of 4:
function foo()
{
u16 buffer[] = { 1, 2, 3 };
...
}
The long term solution to this issue is to add an option to gcc to
allow controlling the general alignment of data, including constant
initialization values.
However this will only apply to the version of gcc which will have such
an option. For other versions, there are four workarounds:
a) Enforce as a rule that array initializations as described above
are forbidden. This is generally not acceptable as they are valid,
and usual, C constructs. The only case where they could be rejected
is when they actually equate to a const char* declaration, i.e. the
array is initialized and never modified in the function's scope.
b) Drop the requirement on unaligned accesses at least for ARMv7,
i.e. do not throw a data abort exception upon unaligned accesses.
But that will allow adding badly aligned code to U-Boot, only for
it to fail when re-used with a stricter target, possibly once the
bad code is already in mainline.
c) Relax the -munaligned-access rule globally. This will prevent native
unaligned accesses of course, but that will also hide any bug caused
by a bad unaligned access, making it much harder to diagnose it. It
is actually what already happens when building ARM targets with a
pre-4.7 gcc, and it may actually already hide some bugs yet unseen
until the target gets compiled with -munaligned-access.
d) Relax the -munaligned-access rule only for for files susceptible to
the local initialized array issue and for armv7 architectures and
beyond. This minimizes the quantity of code which can hide unwanted
misaligned accesses.
The option retained is d).
Considering that actual occurrences of the issue are rare (as of this
writing, 5 files out of 7840 in U-Boot, or .3%, contain an initialized
local char array which cannot actually be replaced with a const char*),
contributors should not be required to systematically try and detect
the issue in their patches.
Detecting files susceptible to the issue can be automated through a
filter installed as a hook in .git which recognizes local char array
initializations. Automation should err on the false positive side, for
instance flagging non-local arrays as if they were local if they cannot
be told apart.
In any case, detection shall not prevent committing the patch, but
shall pre-populate the commit message with a note to the effect that
this patch contains an initialized local char or 16-bit array and thus
should be protected from the gcc 4.7 issue.
Upon a positive detection, either $(PLATFORM_NO_UNALIGNED) should be
added to CFLAGS for the affected file(s), or if the array is a pseudo
const char*, it should be replaced by an actual one.

View file

@ -0,0 +1,240 @@
Editors note: This document is _heavily_ cribbed from the Linux Kernel, with
really only the section about "Alignment vs. Networking" removed.
UNALIGNED MEMORY ACCESSES
=========================
Linux runs on a wide variety of architectures which have varying behaviour
when it comes to memory access. This document presents some details about
unaligned accesses, why you need to write code that doesn't cause them,
and how to write such code!
The definition of an unaligned access
=====================================
Unaligned memory accesses occur when you try to read N bytes of data starting
from an address that is not evenly divisible by N (i.e. addr % N != 0).
For example, reading 4 bytes of data from address 0x10004 is fine, but
reading 4 bytes of data from address 0x10005 would be an unaligned memory
access.
The above may seem a little vague, as memory access can happen in different
ways. The context here is at the machine code level: certain instructions read
or write a number of bytes to or from memory (e.g. movb, movw, movl in x86
assembly). As will become clear, it is relatively easy to spot C statements
which will compile to multiple-byte memory access instructions, namely when
dealing with types such as u16, u32 and u64.
Natural alignment
=================
The rule mentioned above forms what we refer to as natural alignment:
When accessing N bytes of memory, the base memory address must be evenly
divisible by N, i.e. addr % N == 0.
When writing code, assume the target architecture has natural alignment
requirements.
In reality, only a few architectures require natural alignment on all sizes
of memory access. However, we must consider ALL supported architectures;
writing code that satisfies natural alignment requirements is the easiest way
to achieve full portability.
Why unaligned access is bad
===========================
The effects of performing an unaligned memory access vary from architecture
to architecture. It would be easy to write a whole document on the differences
here; a summary of the common scenarios is presented below:
- Some architectures are able to perform unaligned memory accesses
transparently, but there is usually a significant performance cost.
- Some architectures raise processor exceptions when unaligned accesses
happen. The exception handler is able to correct the unaligned access,
at significant cost to performance.
- Some architectures raise processor exceptions when unaligned accesses
happen, but the exceptions do not contain enough information for the
unaligned access to be corrected.
- Some architectures are not capable of unaligned memory access, but will
silently perform a different memory access to the one that was requested,
resulting in a subtle code bug that is hard to detect!
It should be obvious from the above that if your code causes unaligned
memory accesses to happen, your code will not work correctly on certain
platforms and will cause performance problems on others.
Code that does not cause unaligned access
=========================================
At first, the concepts above may seem a little hard to relate to actual
coding practice. After all, you don't have a great deal of control over
memory addresses of certain variables, etc.
Fortunately things are not too complex, as in most cases, the compiler
ensures that things will work for you. For example, take the following
structure:
struct foo {
u16 field1;
u32 field2;
u8 field3;
};
Let us assume that an instance of the above structure resides in memory
starting at address 0x10000. With a basic level of understanding, it would
not be unreasonable to expect that accessing field2 would cause an unaligned
access. You'd be expecting field2 to be located at offset 2 bytes into the
structure, i.e. address 0x10002, but that address is not evenly divisible
by 4 (remember, we're reading a 4 byte value here).
Fortunately, the compiler understands the alignment constraints, so in the
above case it would insert 2 bytes of padding in between field1 and field2.
Therefore, for standard structure types you can always rely on the compiler
to pad structures so that accesses to fields are suitably aligned (assuming
you do not cast the field to a type of different length).
Similarly, you can also rely on the compiler to align variables and function
parameters to a naturally aligned scheme, based on the size of the type of
the variable.
At this point, it should be clear that accessing a single byte (u8 or char)
will never cause an unaligned access, because all memory addresses are evenly
divisible by one.
On a related topic, with the above considerations in mind you may observe
that you could reorder the fields in the structure in order to place fields
where padding would otherwise be inserted, and hence reduce the overall
resident memory size of structure instances. The optimal layout of the
above example is:
struct foo {
u32 field2;
u16 field1;
u8 field3;
};
For a natural alignment scheme, the compiler would only have to add a single
byte of padding at the end of the structure. This padding is added in order
to satisfy alignment constraints for arrays of these structures.
Another point worth mentioning is the use of __attribute__((packed)) on a
structure type. This GCC-specific attribute tells the compiler never to
insert any padding within structures, useful when you want to use a C struct
to represent some data that comes in a fixed arrangement 'off the wire'.
You might be inclined to believe that usage of this attribute can easily
lead to unaligned accesses when accessing fields that do not satisfy
architectural alignment requirements. However, again, the compiler is aware
of the alignment constraints and will generate extra instructions to perform
the memory access in a way that does not cause unaligned access. Of course,
the extra instructions obviously cause a loss in performance compared to the
non-packed case, so the packed attribute should only be used when avoiding
structure padding is of importance.
Code that causes unaligned access
=================================
With the above in mind, let's move onto a real life example of a function
that can cause an unaligned memory access. The following function taken
from the Linux Kernel's include/linux/etherdevice.h is an optimized routine
to compare two ethernet MAC addresses for equality.
bool ether_addr_equal(const u8 *addr1, const u8 *addr2)
{
#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
u32 fold = ((*(const u32 *)addr1) ^ (*(const u32 *)addr2)) |
((*(const u16 *)(addr1 + 4)) ^ (*(const u16 *)(addr2 + 4)));
return fold == 0;
#else
const u16 *a = (const u16 *)addr1;
const u16 *b = (const u16 *)addr2;
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
#endif
}
In the above function, when the hardware has efficient unaligned access
capability, there is no issue with this code. But when the hardware isn't
able to access memory on arbitrary boundaries, the reference to a[0] causes
2 bytes (16 bits) to be read from memory starting at address addr1.
Think about what would happen if addr1 was an odd address such as 0x10003.
(Hint: it'd be an unaligned access.)
Despite the potential unaligned access problems with the above function, it
is included in the kernel anyway but is understood to only work normally on
16-bit-aligned addresses. It is up to the caller to ensure this alignment or
not use this function at all. This alignment-unsafe function is still useful
as it is a decent optimization for the cases when you can ensure alignment,
which is true almost all of the time in ethernet networking context.
Here is another example of some code that could cause unaligned accesses:
void myfunc(u8 *data, u32 value)
{
[...]
*((u32 *) data) = cpu_to_le32(value);
[...]
}
This code will cause unaligned accesses every time the data parameter points
to an address that is not evenly divisible by 4.
In summary, the 2 main scenarios where you may run into unaligned access
problems involve:
1. Casting variables to types of different lengths
2. Pointer arithmetic followed by access to at least 2 bytes of data
Avoiding unaligned accesses
===========================
The easiest way to avoid unaligned access is to use the get_unaligned() and
put_unaligned() macros provided by the <asm/unaligned.h> header file.
Going back to an earlier example of code that potentially causes unaligned
access:
void myfunc(u8 *data, u32 value)
{
[...]
*((u32 *) data) = cpu_to_le32(value);
[...]
}
To avoid the unaligned memory access, you would rewrite it as follows:
void myfunc(u8 *data, u32 value)
{
[...]
value = cpu_to_le32(value);
put_unaligned(value, (u32 *) data);
[...]
}
The get_unaligned() macro works similarly. Assuming 'data' is a pointer to
memory and you wish to avoid unaligned access, its usage is as follows:
u32 value = get_unaligned((u32 *) data);
These macros work for memory accesses of any length (not just 32 bits as
in the examples above). Be aware that when compared to standard access of
aligned memory, using these macros to access unaligned memory can be costly in
terms of performance.
If use of such macros is not convenient, another option is to use memcpy(),
where the source or destination (or both) are of type u8* or unsigned char*.
Due to the byte-wise nature of this operation, unaligned accesses are avoided.
--
In the Linux Kernel,
Authors: Daniel Drake <dsd@gentoo.org>,
Johannes Berg <johannes@sipsolutions.net>
With help from: Alan Cox, Avuton Olrich, Heikki Orsila, Jan Engelhardt,
Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock, Uli Kunitz,
Vadim Lobanov

View file

@ -8,6 +8,7 @@
obj-$(CONFIG_AT91_GPIO) += at91_gpio.o obj-$(CONFIG_AT91_GPIO) += at91_gpio.o
obj-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o obj-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o
obj-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o obj-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o
obj-$(CONFIG_KONA_GPIO) += kona_gpio.o
obj-$(CONFIG_MARVELL_GPIO) += mvgpio.o obj-$(CONFIG_MARVELL_GPIO) += mvgpio.o
obj-$(CONFIG_MARVELL_MFP) += mvmfp.o obj-$(CONFIG_MARVELL_MFP) += mvmfp.o
obj-$(CONFIG_MXC_GPIO) += mxc_gpio.o obj-$(CONFIG_MXC_GPIO) += mxc_gpio.o

141
drivers/gpio/kona_gpio.c Normal file
View file

@ -0,0 +1,141 @@
/*
* Copyright 2013 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/sysmap.h>
#define GPIO_BASE (void *)GPIO2_BASE_ADDR
#define GPIO_PASSWD 0x00a5a501
#define GPIO_PER_BANK 32
#define GPIO_MAX_BANK_NUM 8
#define GPIO_BANK(gpio) ((gpio) >> 5)
#define GPIO_BITMASK(gpio) \
(1UL << ((gpio) & (GPIO_PER_BANK - 1)))
#define GPIO_OUT_STATUS(bank) (0x00000000 + ((bank) << 2))
#define GPIO_IN_STATUS(bank) (0x00000020 + ((bank) << 2))
#define GPIO_OUT_SET(bank) (0x00000040 + ((bank) << 2))
#define GPIO_OUT_CLEAR(bank) (0x00000060 + ((bank) << 2))
#define GPIO_INT_STATUS(bank) (0x00000080 + ((bank) << 2))
#define GPIO_INT_MASK(bank) (0x000000a0 + ((bank) << 2))
#define GPIO_INT_MSKCLR(bank) (0x000000c0 + ((bank) << 2))
#define GPIO_CONTROL(bank) (0x00000100 + ((bank) << 2))
#define GPIO_PWD_STATUS(bank) (0x00000500 + ((bank) << 2))
#define GPIO_GPPWR_OFFSET 0x00000520
#define GPIO_GPCTR0_DBR_SHIFT 5
#define GPIO_GPCTR0_DBR_MASK 0x000001e0
#define GPIO_GPCTR0_ITR_SHIFT 3
#define GPIO_GPCTR0_ITR_MASK 0x00000018
#define GPIO_GPCTR0_ITR_CMD_RISING_EDGE 0x00000001
#define GPIO_GPCTR0_ITR_CMD_FALLING_EDGE 0x00000002
#define GPIO_GPCTR0_ITR_CMD_BOTH_EDGE 0x00000003
#define GPIO_GPCTR0_IOTR_MASK 0x00000001
#define GPIO_GPCTR0_IOTR_CMD_0UTPUT 0x00000000
#define GPIO_GPCTR0_IOTR_CMD_INPUT 0x00000001
int gpio_request(unsigned gpio, const char *label)
{
unsigned int value, off;
writel(GPIO_PASSWD, GPIO_BASE + GPIO_GPPWR_OFFSET);
off = GPIO_PWD_STATUS(GPIO_BANK(gpio));
value = readl(GPIO_BASE + off) & ~GPIO_BITMASK(gpio);
writel(value, GPIO_BASE + off);
return 0;
}
int gpio_free(unsigned gpio)
{
unsigned int value, off;
writel(GPIO_PASSWD, GPIO_BASE + GPIO_GPPWR_OFFSET);
off = GPIO_PWD_STATUS(GPIO_BANK(gpio));
value = readl(GPIO_BASE + off) | GPIO_BITMASK(gpio);
writel(value, GPIO_BASE + off);
return 0;
}
int gpio_direction_input(unsigned gpio)
{
u32 val;
val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_IOTR_MASK;
val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
writel(val, GPIO_BASE + GPIO_CONTROL(gpio));
return 0;
}
int gpio_direction_output(unsigned gpio, int value)
{
int bank_id = GPIO_BANK(gpio);
int bitmask = GPIO_BITMASK(gpio);
u32 val, off;
val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_IOTR_MASK;
val |= GPIO_GPCTR0_IOTR_CMD_0UTPUT;
writel(val, GPIO_BASE + GPIO_CONTROL(gpio));
off = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
val = readl(GPIO_BASE + off);
val |= bitmask;
writel(val, GPIO_BASE + off);
return 0;
}
int gpio_get_value(unsigned gpio)
{
int bank_id = GPIO_BANK(gpio);
int bitmask = GPIO_BITMASK(gpio);
u32 val, off;
/* determine the GPIO pin direction */
val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
val &= GPIO_GPCTR0_IOTR_MASK;
/* read the GPIO bank status */
off = (GPIO_GPCTR0_IOTR_CMD_INPUT == val) ?
GPIO_IN_STATUS(bank_id) : GPIO_OUT_STATUS(bank_id);
val = readl(GPIO_BASE + off);
/* return the specified bit status */
return !!(val & bitmask);
}
void gpio_set_value(unsigned gpio, int value)
{
int bank_id = GPIO_BANK(gpio);
int bitmask = GPIO_BITMASK(gpio);
u32 val, off;
/* determine the GPIO pin direction */
val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
val &= GPIO_GPCTR0_IOTR_MASK;
/* this function only applies to output pin */
if (GPIO_GPCTR0_IOTR_CMD_INPUT == val) {
printf("%s: Cannot set an input pin %d\n", __func__, gpio);
return;
}
off = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
val = readl(GPIO_BASE + off);
val |= bitmask;
writel(val, GPIO_BASE + off);
}

View file

@ -18,6 +18,7 @@ obj-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
obj-$(CONFIG_SYS_I2C) += i2c_core.o obj-$(CONFIG_SYS_I2C) += i2c_core.o
obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o
obj-$(CONFIG_SYS_I2C_FTI2C010) += fti2c010.o obj-$(CONFIG_SYS_I2C_FTI2C010) += fti2c010.o
obj-$(CONFIG_SYS_I2C_KONA) += kona_i2c.o
obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o
obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o
obj-$(CONFIG_SYS_I2C_OMAP34XX) += omap24xx_i2c.o obj-$(CONFIG_SYS_I2C_OMAP34XX) += omap24xx_i2c.o

730
drivers/i2c/kona_i2c.c Normal file
View file

@ -0,0 +1,730 @@
/*
* Copyright 2013 Broadcom Corporation.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <asm/arch/sysmap.h>
#include <asm/kona-common/clk.h>
#include <i2c.h>
/* Hardware register offsets and field defintions */
#define CS_OFFSET 0x00000020
#define CS_ACK_SHIFT 3
#define CS_ACK_MASK 0x00000008
#define CS_ACK_CMD_GEN_START 0x00000000
#define CS_ACK_CMD_GEN_RESTART 0x00000001
#define CS_CMD_SHIFT 1
#define CS_CMD_CMD_NO_ACTION 0x00000000
#define CS_CMD_CMD_START_RESTART 0x00000001
#define CS_CMD_CMD_STOP 0x00000002
#define CS_EN_SHIFT 0
#define CS_EN_CMD_ENABLE_BSC 0x00000001
#define TIM_OFFSET 0x00000024
#define TIM_PRESCALE_SHIFT 6
#define TIM_P_SHIFT 3
#define TIM_NO_DIV_SHIFT 2
#define TIM_DIV_SHIFT 0
#define DAT_OFFSET 0x00000028
#define TOUT_OFFSET 0x0000002c
#define TXFCR_OFFSET 0x0000003c
#define TXFCR_FIFO_FLUSH_MASK 0x00000080
#define TXFCR_FIFO_EN_MASK 0x00000040
#define IER_OFFSET 0x00000044
#define IER_READ_COMPLETE_INT_MASK 0x00000010
#define IER_I2C_INT_EN_MASK 0x00000008
#define IER_FIFO_INT_EN_MASK 0x00000002
#define IER_NOACK_EN_MASK 0x00000001
#define ISR_OFFSET 0x00000048
#define ISR_RESERVED_MASK 0xffffff60
#define ISR_CMDBUSY_MASK 0x00000080
#define ISR_READ_COMPLETE_MASK 0x00000010
#define ISR_SES_DONE_MASK 0x00000008
#define ISR_ERR_MASK 0x00000004
#define ISR_TXFIFOEMPTY_MASK 0x00000002
#define ISR_NOACK_MASK 0x00000001
#define CLKEN_OFFSET 0x0000004c
#define CLKEN_AUTOSENSE_OFF_MASK 0x00000080
#define CLKEN_M_SHIFT 4
#define CLKEN_N_SHIFT 1
#define CLKEN_CLKEN_MASK 0x00000001
#define FIFO_STATUS_OFFSET 0x00000054
#define FIFO_STATUS_RXFIFO_EMPTY_MASK 0x00000004
#define FIFO_STATUS_TXFIFO_EMPTY_MASK 0x00000010
#define HSTIM_OFFSET 0x00000058
#define HSTIM_HS_MODE_MASK 0x00008000
#define HSTIM_HS_HOLD_SHIFT 10
#define HSTIM_HS_HIGH_PHASE_SHIFT 5
#define HSTIM_HS_SETUP_SHIFT 0
#define PADCTL_OFFSET 0x0000005c
#define PADCTL_PAD_OUT_EN_MASK 0x00000004
#define RXFCR_OFFSET 0x00000068
#define RXFCR_NACK_EN_SHIFT 7
#define RXFCR_READ_COUNT_SHIFT 0
#define RXFIFORDOUT_OFFSET 0x0000006c
/* Locally used constants */
#define MAX_RX_FIFO_SIZE 64U /* bytes */
#define MAX_TX_FIFO_SIZE 64U /* bytes */
#define I2C_TIMEOUT 100000 /* usecs */
#define WAIT_INT_CHK 100 /* usecs */
#if I2C_TIMEOUT % WAIT_INT_CHK
#error I2C_TIMEOUT must be a multiple of WAIT_INT_CHK
#endif
/* Operations that can be commanded to the controller */
enum bcm_kona_cmd_t {
BCM_CMD_NOACTION = 0,
BCM_CMD_START,
BCM_CMD_RESTART,
BCM_CMD_STOP,
};
enum bus_speed_index {
BCM_SPD_100K = 0,
BCM_SPD_400K,
BCM_SPD_1MHZ,
};
/* Internal divider settings for standard mode, fast mode and fast mode plus */
struct bus_speed_cfg {
uint8_t time_m; /* Number of cycles for setup time */
uint8_t time_n; /* Number of cycles for hold time */
uint8_t prescale; /* Prescale divider */
uint8_t time_p; /* Timing coefficient */
uint8_t no_div; /* Disable clock divider */
uint8_t time_div; /* Post-prescale divider */
};
static const struct bus_speed_cfg std_cfg_table[] = {
[BCM_SPD_100K] = {0x01, 0x01, 0x03, 0x06, 0x00, 0x02},
[BCM_SPD_400K] = {0x05, 0x01, 0x03, 0x05, 0x01, 0x02},
[BCM_SPD_1MHZ] = {0x01, 0x01, 0x03, 0x01, 0x01, 0x03},
};
struct bcm_kona_i2c_dev {
void *base;
uint speed;
const struct bus_speed_cfg *std_cfg;
};
/* Keep these two defines in sync */
#define DEF_SPD 100000
#define DEF_SPD_ENUM BCM_SPD_100K
#define DEF_DEVICE(num) \
{(void *)CONFIG_SYS_I2C_BASE##num, DEF_SPD, &std_cfg_table[DEF_SPD_ENUM]}
static struct bcm_kona_i2c_dev g_i2c_devs[CONFIG_SYS_MAX_I2C_BUS] = {
#ifdef CONFIG_SYS_I2C_BASE0
DEF_DEVICE(0),
#endif
#ifdef CONFIG_SYS_I2C_BASE1
DEF_DEVICE(1),
#endif
#ifdef CONFIG_SYS_I2C_BASE2
DEF_DEVICE(2),
#endif
#ifdef CONFIG_SYS_I2C_BASE3
DEF_DEVICE(3),
#endif
#ifdef CONFIG_SYS_I2C_BASE4
DEF_DEVICE(4),
#endif
#ifdef CONFIG_SYS_I2C_BASE5
DEF_DEVICE(5),
#endif
};
#define I2C_M_TEN 0x0010 /* ten bit address */
#define I2C_M_RD 0x0001 /* read data */
#define I2C_M_NOSTART 0x4000 /* no restart between msgs */
struct i2c_msg {
uint16_t addr;
uint16_t flags;
uint16_t len;
uint8_t *buf;
};
static void bcm_kona_i2c_send_cmd_to_ctrl(struct bcm_kona_i2c_dev *dev,
enum bcm_kona_cmd_t cmd)
{
debug("%s, %d\n", __func__, cmd);
switch (cmd) {
case BCM_CMD_NOACTION:
writel((CS_CMD_CMD_NO_ACTION << CS_CMD_SHIFT) |
(CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT),
dev->base + CS_OFFSET);
break;
case BCM_CMD_START:
writel((CS_ACK_CMD_GEN_START << CS_ACK_SHIFT) |
(CS_CMD_CMD_START_RESTART << CS_CMD_SHIFT) |
(CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT),
dev->base + CS_OFFSET);
break;
case BCM_CMD_RESTART:
writel((CS_ACK_CMD_GEN_RESTART << CS_ACK_SHIFT) |
(CS_CMD_CMD_START_RESTART << CS_CMD_SHIFT) |
(CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT),
dev->base + CS_OFFSET);
break;
case BCM_CMD_STOP:
writel((CS_CMD_CMD_STOP << CS_CMD_SHIFT) |
(CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT),
dev->base + CS_OFFSET);
break;
default:
printf("Unknown command %d\n", cmd);
}
}
static void bcm_kona_i2c_enable_clock(struct bcm_kona_i2c_dev *dev)
{
writel(readl(dev->base + CLKEN_OFFSET) | CLKEN_CLKEN_MASK,
dev->base + CLKEN_OFFSET);
}
static void bcm_kona_i2c_disable_clock(struct bcm_kona_i2c_dev *dev)
{
writel(readl(dev->base + CLKEN_OFFSET) & ~CLKEN_CLKEN_MASK,
dev->base + CLKEN_OFFSET);
}
/* Wait until at least one of the mask bit(s) are set */
static unsigned long wait_for_int_timeout(struct bcm_kona_i2c_dev *dev,
unsigned long time_left,
uint32_t mask)
{
uint32_t status;
while (time_left) {
status = readl(dev->base + ISR_OFFSET);
if ((status & ~ISR_RESERVED_MASK) == 0) {
debug("Bogus I2C interrupt 0x%x\n", status);
continue;
}
/* Must flush the TX FIFO when NAK detected */
if (status & ISR_NOACK_MASK)
writel(TXFCR_FIFO_FLUSH_MASK | TXFCR_FIFO_EN_MASK,
dev->base + TXFCR_OFFSET);
writel(status & ~ISR_RESERVED_MASK, dev->base + ISR_OFFSET);
if (status & mask) {
/* We are done since one of the mask bits are set */
return time_left;
}
udelay(WAIT_INT_CHK);
time_left -= WAIT_INT_CHK;
}
return 0;
}
/* Send command to I2C bus */
static int bcm_kona_send_i2c_cmd(struct bcm_kona_i2c_dev *dev,
enum bcm_kona_cmd_t cmd)
{
int rc = 0;
unsigned long time_left = I2C_TIMEOUT;
/* Send the command */
bcm_kona_i2c_send_cmd_to_ctrl(dev, cmd);
/* Wait for transaction to finish or timeout */
time_left = wait_for_int_timeout(dev, time_left, IER_I2C_INT_EN_MASK);
if (!time_left) {
printf("controller timed out\n");
rc = -ETIMEDOUT;
}
/* Clear command */
bcm_kona_i2c_send_cmd_to_ctrl(dev, BCM_CMD_NOACTION);
return rc;
}
/* Read a single RX FIFO worth of data from the i2c bus */
static int bcm_kona_i2c_read_fifo_single(struct bcm_kona_i2c_dev *dev,
uint8_t *buf, unsigned int len,
unsigned int last_byte_nak)
{
unsigned long time_left = I2C_TIMEOUT;
/* Start the RX FIFO */
writel((last_byte_nak << RXFCR_NACK_EN_SHIFT) |
(len << RXFCR_READ_COUNT_SHIFT), dev->base + RXFCR_OFFSET);
/* Wait for FIFO read to complete */
time_left =
wait_for_int_timeout(dev, time_left, IER_READ_COMPLETE_INT_MASK);
if (!time_left) {
printf("RX FIFO time out\n");
return -EREMOTEIO;
}
/* Read data from FIFO */
for (; len > 0; len--, buf++)
*buf = readl(dev->base + RXFIFORDOUT_OFFSET);
return 0;
}
/* Read any amount of data using the RX FIFO from the i2c bus */
static int bcm_kona_i2c_read_fifo(struct bcm_kona_i2c_dev *dev,
struct i2c_msg *msg)
{
unsigned int bytes_to_read = MAX_RX_FIFO_SIZE;
unsigned int last_byte_nak = 0;
unsigned int bytes_read = 0;
int rc;
uint8_t *tmp_buf = msg->buf;
while (bytes_read < msg->len) {
if (msg->len - bytes_read <= MAX_RX_FIFO_SIZE) {
last_byte_nak = 1; /* NAK last byte of transfer */
bytes_to_read = msg->len - bytes_read;
}
rc = bcm_kona_i2c_read_fifo_single(dev, tmp_buf, bytes_to_read,
last_byte_nak);
if (rc < 0)
return -EREMOTEIO;
bytes_read += bytes_to_read;
tmp_buf += bytes_to_read;
}
return 0;
}
/* Write a single byte of data to the i2c bus */
static int bcm_kona_i2c_write_byte(struct bcm_kona_i2c_dev *dev, uint8_t data,
unsigned int nak_expected)
{
unsigned long time_left = I2C_TIMEOUT;
unsigned int nak_received;
/* Clear pending session done interrupt */
writel(ISR_SES_DONE_MASK, dev->base + ISR_OFFSET);
/* Send one byte of data */
writel(data, dev->base + DAT_OFFSET);
time_left = wait_for_int_timeout(dev, time_left, IER_I2C_INT_EN_MASK);
if (!time_left) {
debug("controller timed out\n");
return -ETIMEDOUT;
}
nak_received = readl(dev->base + CS_OFFSET) & CS_ACK_MASK ? 1 : 0;
if (nak_received ^ nak_expected) {
debug("unexpected NAK/ACK\n");
return -EREMOTEIO;
}
return 0;
}
/* Write a single TX FIFO worth of data to the i2c bus */
static int bcm_kona_i2c_write_fifo_single(struct bcm_kona_i2c_dev *dev,
uint8_t *buf, unsigned int len)
{
int k;
unsigned long time_left = I2C_TIMEOUT;
unsigned int fifo_status;
/* Write data into FIFO */
for (k = 0; k < len; k++)
writel(buf[k], (dev->base + DAT_OFFSET));
/* Wait for FIFO to empty */
do {
time_left =
wait_for_int_timeout(dev, time_left,
(IER_FIFO_INT_EN_MASK |
IER_NOACK_EN_MASK));
fifo_status = readl(dev->base + FIFO_STATUS_OFFSET);
} while (time_left && !(fifo_status & FIFO_STATUS_TXFIFO_EMPTY_MASK));
/* Check if there was a NAK */
if (readl(dev->base + CS_OFFSET) & CS_ACK_MASK) {
printf("unexpected NAK\n");
return -EREMOTEIO;
}
/* Check if a timeout occured */
if (!time_left) {
printf("completion timed out\n");
return -EREMOTEIO;
}
return 0;
}
/* Write any amount of data using TX FIFO to the i2c bus */
static int bcm_kona_i2c_write_fifo(struct bcm_kona_i2c_dev *dev,
struct i2c_msg *msg)
{
unsigned int bytes_to_write = MAX_TX_FIFO_SIZE;
unsigned int bytes_written = 0;
int rc;
uint8_t *tmp_buf = msg->buf;
while (bytes_written < msg->len) {
if (msg->len - bytes_written <= MAX_TX_FIFO_SIZE)
bytes_to_write = msg->len - bytes_written;
rc = bcm_kona_i2c_write_fifo_single(dev, tmp_buf,
bytes_to_write);
if (rc < 0)
return -EREMOTEIO;
bytes_written += bytes_to_write;
tmp_buf += bytes_to_write;
}
return 0;
}
/* Send i2c address */
static int bcm_kona_i2c_do_addr(struct bcm_kona_i2c_dev *dev,
struct i2c_msg *msg)
{
unsigned char addr;
if (msg->flags & I2C_M_TEN) {
/* First byte is 11110XX0 where XX is upper 2 bits */
addr = 0xf0 | ((msg->addr & 0x300) >> 7);
if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0)
return -EREMOTEIO;
/* Second byte is the remaining 8 bits */
addr = msg->addr & 0xff;
if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0)
return -EREMOTEIO;
if (msg->flags & I2C_M_RD) {
/* For read, send restart command */
if (bcm_kona_send_i2c_cmd(dev, BCM_CMD_RESTART) < 0)
return -EREMOTEIO;
/* Then re-send the first byte with the read bit set */
addr = 0xf0 | ((msg->addr & 0x300) >> 7) | 0x01;
if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0)
return -EREMOTEIO;
}
} else {
addr = msg->addr << 1;
if (msg->flags & I2C_M_RD)
addr |= 1;
if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0)
return -EREMOTEIO;
}
return 0;
}
static void bcm_kona_i2c_enable_autosense(struct bcm_kona_i2c_dev *dev)
{
writel(readl(dev->base + CLKEN_OFFSET) & ~CLKEN_AUTOSENSE_OFF_MASK,
dev->base + CLKEN_OFFSET);
}
static void bcm_kona_i2c_config_timing(struct bcm_kona_i2c_dev *dev)
{
writel(readl(dev->base + HSTIM_OFFSET) & ~HSTIM_HS_MODE_MASK,
dev->base + HSTIM_OFFSET);
writel((dev->std_cfg->prescale << TIM_PRESCALE_SHIFT) |
(dev->std_cfg->time_p << TIM_P_SHIFT) |
(dev->std_cfg->no_div << TIM_NO_DIV_SHIFT) |
(dev->std_cfg->time_div << TIM_DIV_SHIFT),
dev->base + TIM_OFFSET);
writel((dev->std_cfg->time_m << CLKEN_M_SHIFT) |
(dev->std_cfg->time_n << CLKEN_N_SHIFT) |
CLKEN_CLKEN_MASK, dev->base + CLKEN_OFFSET);
}
/* Master transfer function */
static int bcm_kona_i2c_xfer(struct bcm_kona_i2c_dev *dev,
struct i2c_msg msgs[], int num)
{
struct i2c_msg *pmsg;
int rc = 0;
int i;
/* Enable pad output */
writel(0, dev->base + PADCTL_OFFSET);
/* Enable internal clocks */
bcm_kona_i2c_enable_clock(dev);
/* Send start command */
rc = bcm_kona_send_i2c_cmd(dev, BCM_CMD_START);
if (rc < 0) {
printf("Start command failed rc = %d\n", rc);
goto xfer_disable_pad;
}
/* Loop through all messages */
for (i = 0; i < num; i++) {
pmsg = &msgs[i];
/* Send restart for subsequent messages */
if ((i != 0) && ((pmsg->flags & I2C_M_NOSTART) == 0)) {
rc = bcm_kona_send_i2c_cmd(dev, BCM_CMD_RESTART);
if (rc < 0) {
printf("restart cmd failed rc = %d\n", rc);
goto xfer_send_stop;
}
}
/* Send slave address */
if (!(pmsg->flags & I2C_M_NOSTART)) {
rc = bcm_kona_i2c_do_addr(dev, pmsg);
if (rc < 0) {
debug("NAK from addr %2.2x msg#%d rc = %d\n",
pmsg->addr, i, rc);
goto xfer_send_stop;
}
}
/* Perform data transfer */
if (pmsg->flags & I2C_M_RD) {
rc = bcm_kona_i2c_read_fifo(dev, pmsg);
if (rc < 0) {
printf("read failure\n");
goto xfer_send_stop;
}
} else {
rc = bcm_kona_i2c_write_fifo(dev, pmsg);
if (rc < 0) {
printf("write failure");
goto xfer_send_stop;
}
}
}
rc = num;
xfer_send_stop:
/* Send a STOP command */
bcm_kona_send_i2c_cmd(dev, BCM_CMD_STOP);
xfer_disable_pad:
/* Disable pad output */
writel(PADCTL_PAD_OUT_EN_MASK, dev->base + PADCTL_OFFSET);
/* Stop internal clock */
bcm_kona_i2c_disable_clock(dev);
return rc;
}
static uint bcm_kona_i2c_assign_bus_speed(struct bcm_kona_i2c_dev *dev,
uint speed)
{
switch (speed) {
case 100000:
dev->std_cfg = &std_cfg_table[BCM_SPD_100K];
break;
case 400000:
dev->std_cfg = &std_cfg_table[BCM_SPD_400K];
break;
case 1000000:
dev->std_cfg = &std_cfg_table[BCM_SPD_1MHZ];
break;
default:
printf("%d hz bus speed not supported\n", speed);
return -EINVAL;
}
dev->speed = speed;
return 0;
}
static void bcm_kona_i2c_init(struct bcm_kona_i2c_dev *dev)
{
/* Parse bus speed */
bcm_kona_i2c_assign_bus_speed(dev, dev->speed);
/* Enable internal clocks */
bcm_kona_i2c_enable_clock(dev);
/* Configure internal dividers */
bcm_kona_i2c_config_timing(dev);
/* Disable timeout */
writel(0, dev->base + TOUT_OFFSET);
/* Enable autosense */
bcm_kona_i2c_enable_autosense(dev);
/* Enable TX FIFO */
writel(TXFCR_FIFO_FLUSH_MASK | TXFCR_FIFO_EN_MASK,
dev->base + TXFCR_OFFSET);
/* Mask all interrupts */
writel(0, dev->base + IER_OFFSET);
/* Clear all pending interrupts */
writel(ISR_CMDBUSY_MASK |
ISR_READ_COMPLETE_MASK |
ISR_SES_DONE_MASK |
ISR_ERR_MASK |
ISR_TXFIFOEMPTY_MASK | ISR_NOACK_MASK, dev->base + ISR_OFFSET);
/* Enable the controller but leave it idle */
bcm_kona_i2c_send_cmd_to_ctrl(dev, BCM_CMD_NOACTION);
/* Disable pad output */
writel(PADCTL_PAD_OUT_EN_MASK, dev->base + PADCTL_OFFSET);
}
/*
* uboot layer
*/
struct bcm_kona_i2c_dev *kona_get_dev(struct i2c_adapter *adap)
{
return &g_i2c_devs[adap->hwadapnr];
}
static void kona_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
{
struct bcm_kona_i2c_dev *dev = kona_get_dev(adap);
if (clk_bsc_enable(dev->base))
return;
bcm_kona_i2c_init(dev);
}
static int kona_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
int alen, uchar *buffer, int len)
{
/* msg[0] writes the addr, msg[1] reads the data */
struct i2c_msg msg[2];
unsigned char msgbuf0[64];
struct bcm_kona_i2c_dev *dev = kona_get_dev(adap);
msg[0].addr = chip;
msg[0].flags = 0;
msg[0].len = 1;
msg[0].buf = msgbuf0; /* msgbuf0 contains incrementing reg addr */
msg[1].addr = chip;
msg[1].flags = I2C_M_RD;
/* msg[1].buf dest ptr increments each read */
msgbuf0[0] = (unsigned char)addr;
msg[1].buf = buffer;
msg[1].len = len;
if (bcm_kona_i2c_xfer(dev, msg, 2) < 0) {
/* Sending 2 i2c messages */
kona_i2c_init(adap, adap->speed, adap->slaveaddr);
debug("I2C read: I/O error\n");
return -EIO;
}
return 0;
}
static int kona_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
int alen, uchar *buffer, int len)
{
struct i2c_msg msg[0];
unsigned char msgbuf0[64];
unsigned int i;
struct bcm_kona_i2c_dev *dev = kona_get_dev(adap);
msg[0].addr = chip;
msg[0].flags = 0;
msg[0].len = 2; /* addr byte plus data */
msg[0].buf = msgbuf0;
for (i = 0; i < len; i++) {
msgbuf0[0] = addr++;
msgbuf0[1] = buffer[i];
if (bcm_kona_i2c_xfer(dev, msg, 1) < 0) {
kona_i2c_init(adap, adap->speed, adap->slaveaddr);
debug("I2C write: I/O error\n");
return -EIO;
}
}
return 0;
}
static int kona_i2c_probe(struct i2c_adapter *adap, uchar chip)
{
uchar tmp;
/*
* read addr 0x0 of the given chip.
*/
return kona_i2c_read(adap, chip, 0x0, 1, &tmp, 1);
}
static uint kona_i2c_set_bus_speed(struct i2c_adapter *adap, uint speed)
{
struct bcm_kona_i2c_dev *dev = kona_get_dev(adap);
return bcm_kona_i2c_assign_bus_speed(dev, speed);
}
/*
* Register kona i2c adapters. Keep the order below so
* that the bus number matches the adapter number.
*/
#define DEF_ADAPTER(num) \
U_BOOT_I2C_ADAP_COMPLETE(kona##num, kona_i2c_init, kona_i2c_probe, \
kona_i2c_read, kona_i2c_write, \
kona_i2c_set_bus_speed, DEF_SPD, 0x00, num)
#ifdef CONFIG_SYS_I2C_BASE0
DEF_ADAPTER(0)
#endif
#ifdef CONFIG_SYS_I2C_BASE1
DEF_ADAPTER(1)
#endif
#ifdef CONFIG_SYS_I2C_BASE2
DEF_ADAPTER(2)
#endif
#ifdef CONFIG_SYS_I2C_BASE3
DEF_ADAPTER(3)
#endif
#ifdef CONFIG_SYS_I2C_BASE4
DEF_ADAPTER(4)
#endif
#ifdef CONFIG_SYS_I2C_BASE5
DEF_ADAPTER(5)
#endif

Some files were not shown because too many files have changed in this diff Show more