mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +00:00
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:
commit
eeb72e6761
121 changed files with 5959 additions and 607 deletions
8
README
8
README
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 :
|
||||||
{
|
{
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -50,5 +50,8 @@ SECTIONS
|
||||||
.bss : { *(.bss*) }
|
.bss : { *(.bss*) }
|
||||||
__bss_end = .;
|
__bss_end = .;
|
||||||
|
|
||||||
_end = .;
|
.end :
|
||||||
|
{
|
||||||
|
*(.__end)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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*) }
|
||||||
|
|
|
@ -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*) }
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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/
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -38,7 +38,11 @@ SECTIONS
|
||||||
|
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
__image_copy_end = .;
|
__image_copy_end = .;
|
||||||
_end = .;
|
|
||||||
|
.end :
|
||||||
|
{
|
||||||
|
*(.__end)
|
||||||
|
} >.sram
|
||||||
|
|
||||||
.bss :
|
.bss :
|
||||||
{
|
{
|
||||||
|
|
11
arch/arm/cpu/armv7/bcm281xx/Makefile
Normal file
11
arch/arm/cpu/armv7/bcm281xx/Makefile
Normal 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
|
523
arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c
Normal file
523
arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c
Normal 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);
|
52
arch/arm/cpu/armv7/bcm281xx/clk-bsc.c
Normal file
52
arch/arm/cpu/armv7/bcm281xx/clk-bsc.c
Normal 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;
|
||||||
|
}
|
513
arch/arm/cpu/armv7/bcm281xx/clk-core.c
Normal file
513
arch/arm/cpu/armv7/bcm281xx/clk-core.c
Normal 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);
|
||||||
|
*/
|
495
arch/arm/cpu/armv7/bcm281xx/clk-core.h
Normal file
495
arch/arm/cpu/armv7/bcm281xx/clk-core.h
Normal 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);
|
73
arch/arm/cpu/armv7/bcm281xx/clk-sdio.c
Normal file
73
arch/arm/cpu/armv7/bcm281xx/clk-sdio.c
Normal 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;
|
||||||
|
}
|
27
arch/arm/cpu/armv7/bcm281xx/reset.c
Normal file
27
arch/arm/cpu/armv7/bcm281xx/reset.c
Normal 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 */
|
||||||
|
}
|
|
@ -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)
|
||||||
|
|
9
arch/arm/cpu/armv7/kona-common/Makefile
Normal file
9
arch/arm/cpu/armv7/kona-common/Makefile
Normal 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
|
21
arch/arm/cpu/armv7/kona-common/clk-stubs.c
Normal file
21
arch/arm/cpu/armv7/kona-common/clk-stubs.c
Normal 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;
|
||||||
|
}
|
16
arch/arm/cpu/armv7/kona-common/hwinit-common.c
Normal file
16
arch/arm/cpu/armv7/kona-common/hwinit-common.c
Normal 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
|
12
arch/arm/cpu/armv7/kona-common/s_init.c
Normal file
12
arch/arm/cpu/armv7/kona-common/s_init.c
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Broadcom Corporation.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Early system init. Currently empty.
|
||||||
|
*/
|
||||||
|
void s_init(void)
|
||||||
|
{
|
||||||
|
}
|
|
@ -39,7 +39,11 @@ SECTIONS
|
||||||
|
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
__image_copy_end = .;
|
__image_copy_end = .;
|
||||||
_end = .;
|
|
||||||
|
.end :
|
||||||
|
{
|
||||||
|
*(.__end)
|
||||||
|
}
|
||||||
|
|
||||||
.bss :
|
.bss :
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -28,7 +28,11 @@ SECTIONS
|
||||||
|
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
__image_copy_end = .;
|
__image_copy_end = .;
|
||||||
_end = .;
|
|
||||||
|
.end :
|
||||||
|
{
|
||||||
|
*(.__end)
|
||||||
|
}
|
||||||
|
|
||||||
.bss : {
|
.bss : {
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -37,7 +37,11 @@ SECTIONS
|
||||||
|
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
__image_copy_end = .;
|
__image_copy_end = .;
|
||||||
_end = .;
|
|
||||||
|
.end :
|
||||||
|
{
|
||||||
|
*(.__end)
|
||||||
|
} >.sram
|
||||||
|
|
||||||
.bss :
|
.bss :
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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*) }
|
||||||
|
|
|
@ -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*) }
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
15
arch/arm/include/asm/arch-bcm281xx/gpio.h
Normal file
15
arch/arm/include/asm/arch-bcm281xx/gpio.h
Normal 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
|
25
arch/arm/include/asm/arch-bcm281xx/sysmap.h
Normal file
25
arch/arm/include/asm/arch-bcm281xx/sysmap.h
Normal 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
|
29
arch/arm/include/asm/kona-common/clk.h
Normal file
29
arch/arm/include/asm/kona-common/clk.h
Normal 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
|
12
arch/arm/include/asm/kona-common/kona_sdhci.h
Normal file
12
arch/arm/include/asm/kona-common/kona_sdhci.h
Normal 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
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")));
|
||||||
|
|
|
@ -49,5 +49,9 @@ SECTIONS
|
||||||
} >.sram
|
} >.sram
|
||||||
|
|
||||||
__image_copy_end = .;
|
__image_copy_end = .;
|
||||||
_end = .;
|
|
||||||
|
.end :
|
||||||
|
{
|
||||||
|
*(.__end)
|
||||||
|
} >.sram
|
||||||
}
|
}
|
||||||
|
|
22
board/BuR/common/bur_common.h
Normal file
22
board/BuR/common/bur_common.h
Normal 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
216
board/BuR/common/common.c
Normal 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
12
board/BuR/kwb/Makefile
Normal 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
240
board/BuR/kwb/board.c
Normal 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
195
board/BuR/kwb/mux.c
Normal 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);
|
||||||
|
}
|
14
board/BuR/tseries/Makefile
Normal file
14
board/BuR/tseries/Makefile
Normal 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
147
board/BuR/tseries/board.c
Normal 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
225
board/BuR/tseries/mux.c
Normal 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);
|
||||||
|
}
|
|
@ -48,5 +48,9 @@ SECTIONS
|
||||||
} >.sram
|
} >.sram
|
||||||
|
|
||||||
__image_copy_end = .;
|
__image_copy_end = .;
|
||||||
_end = .;
|
|
||||||
|
.end :
|
||||||
|
{
|
||||||
|
*(.__end)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
7
board/broadcom/bcm28155_ap/Makefile
Normal file
7
board/broadcom/bcm28155_ap/Makefile
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#
|
||||||
|
# Copyright 2013 Broadcom Corporation.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
#
|
||||||
|
|
||||||
|
obj-y += $(BOARD).o
|
87
board/broadcom/bcm28155_ap/bcm28155_ap.c
Normal file
87
board/broadcom/bcm28155_ap/bcm28155_ap.c
Normal 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
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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*) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,5 +49,9 @@ SECTIONS
|
||||||
} >.sram
|
} >.sram
|
||||||
|
|
||||||
__image_copy_end = .;
|
__image_copy_end = .;
|
||||||
_end = .;
|
|
||||||
|
.end :
|
||||||
|
{
|
||||||
|
*(.__end)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,5 +61,8 @@ SECTIONS
|
||||||
__bss_end = .;
|
__bss_end = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
_end = .;
|
.end :
|
||||||
|
{
|
||||||
|
*(.__end)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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*) }
|
||||||
|
|
|
@ -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)) \
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -42,7 +42,11 @@ SECTIONS
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
|
|
||||||
__image_copy_end = .;
|
__image_copy_end = .;
|
||||||
_end = .;
|
|
||||||
|
.end :
|
||||||
|
{
|
||||||
|
*(.__end)
|
||||||
|
} >.sram
|
||||||
|
|
||||||
.bss :
|
.bss :
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
13
board/silica/pengwyn/Makefile
Normal file
13
board/silica/pengwyn/Makefile
Normal 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
|
207
board/silica/pengwyn/board.c
Normal file
207
board/silica/pengwyn/board.c
Normal 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 */
|
15
board/silica/pengwyn/board.h
Normal file
15
board/silica/pengwyn/board.h
Normal 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
|
98
board/silica/pengwyn/mux.c
Normal file
98
board/silica/pengwyn/mux.c
Normal 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);
|
||||||
|
}
|
|
@ -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*) }
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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*) }
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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)
|
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
|
240
doc/README.unaligned-memory-access.txt
Normal file
240
doc/README.unaligned-memory-access.txt
Normal 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
|
|
@ -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
141
drivers/gpio/kona_gpio.c
Normal 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);
|
||||||
|
}
|
|
@ -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
730
drivers/i2c/kona_i2c.c
Normal 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
Loading…
Reference in a new issue