1
1

Initial dump from Zyxel

This commit is contained in:
2026-04-17 17:00:52 +02:00
commit 81fec250f4
23116 changed files with 5231237 additions and 0 deletions
@@ -0,0 +1,237 @@
/*
* (C) Copyright Mindspeed Technologies Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <config.h>
#include <asm/hardware.h>
#ifdef CFG_FLASH_AM040_DRIVER
#define AM29LV040B_SIZE (512 * 1024)
#define AM29LV040B_SECTOR_SIZE (64 * 1024)
#define AM29LV040B_SECTORS (AM29LV040B_SIZE / AM29LV040B_SECTOR_SIZE)
/* Am29LV040B Codes */
#define CMD_RESET 0xF0
#define CMD_AUTO_SELECT 0x90
#define CMD_UNLOCK1 0xAA
#define CMD_UNLOCK2 0x55
#define CMD_ERASE_SETUP 0x80
#define CMD_ERASE_CONFIRM 0x30
#define CMD_PROGRAM 0xA0
#define CMD_UNLOCK_BYPASS 0x20
#define CMD_SECTOR_UNLOCK 0x70
#define MEM_FLASH_ADDR1 0x555
#define MEM_FLASH_ADDR2 0x2AA
#define BIT_ERASE_DONE 0x80
#define BIT_RDY_MASK 0x80
#if defined(CFG_FLASH_PROTECTION)
int am29lv040b_flash_real_protect(flash_info_t *info, long sector, int prot)
{
/* do nothing for now */
return ERR_INVAL;
}
#endif
int am29lv040b_flash_erase(flash_info_t * info, int s_first, int s_last)
{
volatile u8 *base = (u8 *)info->start[0];
volatile u8 *addr = base;
int flag, erased, prot, sect;
ulong start, now, last;
/* first look for protection bits */
prot = 0;
for (sect = s_first; sect <= s_last; ++sect) {
if (info->protect[sect]) {
prot++;
}
}
if (prot) {
printf ("- Warning: %d protected sectors will not be erased!\n", prot);
} else {
printf ("\n");
}
erased = 0;
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
base[MEM_FLASH_ADDR1] = CMD_UNLOCK1;
base[MEM_FLASH_ADDR2] = CMD_UNLOCK2;
base[MEM_FLASH_ADDR1] = CMD_ERASE_SETUP;
base[MEM_FLASH_ADDR1] = CMD_UNLOCK1;
base[MEM_FLASH_ADDR2] = CMD_UNLOCK2;
/* Start erase on unprotected sectors */
for (sect = s_first; sect <= s_last; sect++) {
if (info->protect[sect] == 0) { /* not protected */
addr = (u8 *)(info->start[sect]);
addr[0] = CMD_ERASE_CONFIRM;
erased++;
}
}
/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();
/* wait at least 50us - let's wait 100 us */
udelay (100);
if (erased == 0)
goto out;
printf ("Erasing %d sectors... ", erased);
start = get_timer (0);
last = start;
while ((addr[0] & BIT_ERASE_DONE) != BIT_ERASE_DONE) {
now = get_timer(start);
if (now > (erased * CONFIG_SYS_FLASH_ERASE_TOUT)) {
printf ("timeout\n");
return ERR_TIMOUT;
}
/* show that we're waiting */
if ((now - last) > (1 * CONFIG_SYS_HZ)) { /* every second */
putc ('.');
last = now;
}
}
printf ("ok\n");
out:
/* reset to read mode */
base[0] = CMD_RESET;
return ERR_OK;
}
int am29lv040b_write_buff(flash_info_t *info, uchar *src, ulong dest, ulong cnt)
{
volatile u8 *base = (u8 *)(info->start[0]);
volatile u8 *addr = (u8 *)dest;
u8 *wbuf = src;
ulong last, now, start;
last = get_timer(0);
for (; (cnt > 0); cnt--, addr++, wbuf++) {
if (*addr != *wbuf) {
base[MEM_FLASH_ADDR1] = CMD_UNLOCK1;
base[MEM_FLASH_ADDR2] = CMD_UNLOCK2;
base[MEM_FLASH_ADDR1] = CMD_PROGRAM;
*addr = *wbuf;
start = get_timer (0);
while ((*addr & BIT_RDY_MASK) != (*wbuf & BIT_RDY_MASK)) {
now = get_timer(0);
if ((now - start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
printf ("timeout ");
break;
}
/* show that we're waiting */
if ((now - last) > (1 * CONFIG_SYS_HZ)) { /* every second */
putc ('.');
last = now;
}
}
if (*addr != *wbuf) {
printf("write failed, address %08lx -> %x(%x)\n",
(unsigned long)addr, *wbuf, *addr);
base[0] = CMD_RESET; /* Reset */
return ERR_TIMOUT;
}
}
}
printf("ok\n");
return ERR_OK;
}
static ulong am29lv040b_get_size(flash_info_t *info, ulong base_addr)
{
volatile u8 *base = (u8 *)base_addr;
volatile u8 *addr;
u8 manuf_id, device_id;
int i;
base[MEM_FLASH_ADDR1] = CMD_UNLOCK1;
base[MEM_FLASH_ADDR2] = CMD_UNLOCK2;
base[MEM_FLASH_ADDR1] = CMD_AUTO_SELECT;
manuf_id = base[0];
device_id = base[1];
if (manuf_id != (AMD_MANUFACT & 0xff))
return 0;
if (device_id != AMD_ID_LV040B)
return 0;
printf("found AM29LV040B flash at %08X\n", base_addr);
info->flash_id = FLASH_MAN_AMD | FLASH_AM040;
info->size = AM29LV040B_SIZE;
info->sector_count = AM29LV040B_SECTORS;
memset(info->protect, 0, info->sector_count);
for (i = 0; i < info->sector_count; i++) {
info->start[i] = base_addr + i * AM29LV040B_SECTOR_SIZE;
addr = (u8 *)info->start[i];
info->protect[i] = addr[2] & 0x1;
}
/* Reset flash */
base[0] = CMD_RESET;
return info->size;
}
ulong am29lv040b_flash_init(flash_info_t * info)
{
ulong base_addr[CONFIG_SYS_MAX_FLASH_BANKS] = CONFIG_SYS_FLASH_BANKS_LIST;
ulong size = 0;
int i;
for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
if (info[i].flash_id == FLASH_UNKNOWN)
size += am29lv040b_get_size(&info[i], base_addr[i]);
}
return size;
}
#endif
@@ -0,0 +1,249 @@
/*
* (C) Copyright 2002
* Robert Schwebel, Pengutronix, <r.schwebel@pengutronix.de>
*
* (C) Copyright 2000-2004
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <config.h>
#include <asm/hardware.h>
#ifdef CFG_FLASH_AMLV640U_DRIVER
#define AMLV640U_SECTOR_SIZE 0x00010000 /* 64 KB sectors */
#define AMLV640U_SECTORS (CFG_FLASH_AMLV640U_SIZE / AMLV640U_SECTOR_SIZE)
#define FTIMEOUT 16000000
/* Functions */
int amlv640u_flash_erase (flash_info_t *info, int s_first, int s_last);
int amlv640u_write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt);
#if defined(CFG_FLASH_PROTECTION)
int amlv640u_flash_real_protect(flash_info_t *info, long sector, int prot)
{
/* do nothing for now */
return ERR_INVAL;
}
#endif
/*-----------------------------------------------------------------------
*/
int amlv640u_flash_erase (flash_info_t *info, int s_first, int s_last)
{
volatile u16 *base = (u16 *)info->start[0];
volatile u16 *addr = base;
int flag, prot, sect, erased;
ulong start, now, last;
prot = 0;
for (sect = s_first; sect <= s_last; ++sect) {
if (info->protect[sect]) {
prot++;
}
}
if (prot) {
printf ("- Warning: %d protected sectors will not be erased!\n", prot);
} else {
printf ("\n");
}
erased = 0;
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
base[0x555] = 0xAA;
base[0x2AA] = 0x55;
base[0x555] = 0x80;
base[0x555] = 0xAA;
base[0x2AA] = 0x55;
/* Start erase on unprotected sectors */
for (sect = s_first; sect <= s_last; sect++) {
if (info->protect[sect] == 0) { /* not protected */
addr = (u16 *)info->start[sect];
addr[0] = 0x30;
erased++;
}
}
/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();
/* wait at least 50us - let's wait 100 us */
udelay (100);
if (erased == 0)
goto out;
printf ("Erasing %d sectors... ", erased);
start = get_timer (0);
last = start;
while ((addr[0] & 0x80) != 0x80) {
now = get_timer(start);
if (now > (erased * CONFIG_SYS_FLASH_ERASE_TOUT)) {
printf ("timeout\n");
return ERR_TIMOUT;
}
/* show that we're waiting */
if ((now - last) > (1 * CONFIG_SYS_HZ)) { /* every second */
putc ('.');
last = now;
}
}
printf ("ok\n");
out:
/* reset to read mode */
base[0] = 0xF0;
return ERR_OK;
}
/*-----------------------------------------------------------------------
* Copy memory to flash, returns:
* 0 - OK
* 1 - write timeout
* 2 - Flash not erased
*/
int amlv640u_write_buff (flash_info_t *info, uchar *src, ulong dest, ulong cnt)
{
volatile u16 *base = (u16 *)(info->start[0]);
volatile u16 *addr = (u16 *)dest;
u16 *wbuf = (u16 *)src;
ulong last, now, start;
last = get_timer(0);
for (cnt >>= 1; (cnt > 0); cnt--, addr++, wbuf++) {
if (*addr != *wbuf) {
base[0x555] = 0xAA;
base[0x2AA] = 0x55;
base[0x555] = 0xA0;
*addr = *wbuf;
start = get_timer (0);
while ((*addr & 0x80) != (*wbuf & 0x80)) {
now = get_timer(0);
if ((now - start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
printf ("timeout ");
break;
}
/* show that we're waiting */
if ((now - last) > (1 * CONFIG_SYS_HZ)) { /* every second */
putc ('.');
last = now;
}
}
if (*addr != *wbuf) {
printf("write failed, address %08lx -> %x(%x)\n",
(unsigned long)addr, *wbuf, *addr);
base[0] = 0xF0; /* Reset */
return ERR_TIMOUT;
}
}
}
printf("ok\n");
return ERR_OK;
}
/*
* The following code cannot be run from FLASH!
*/
static ulong amlv640u_get_size (flash_info_t *info, ulong base_addr)
{
volatile u16 *base = (u16 *)base_addr;
volatile u16 *addr;
u16 manuf_id, device_id1, device_id2, device_id3;
int i;
/* Write auto select command: read Manufacturer ID */
base[0x555] = 0xAA;
base[0x2AA] = 0x55;
base[0x555] = 0x90;
manuf_id = base[0];
device_id1 = base[1];
device_id2 = base[14];
device_id3 = base[15];
if (manuf_id != (AMD_MANUFACT & 0xffff))
return 0;
if (device_id1 != (AMD_ID_MIRROR & 0xffff) ||
device_id2 != (AMD_ID_LV640U_2 & 0xffff) ||
device_id3 != (AMD_ID_LV640U_3 & 0xffff))
return 0;
printf("found AMLV640U flash at %08X\n", base_addr);
info->flash_id = FLASH_MAN_AMD | FLASH_AMLV640U;
info->size = CFG_FLASH_AMLV640U_SIZE;
info->sector_count = AMLV640U_SECTORS;
memset (info->protect, 0, info->sector_count);
for (i = 0; i < info->sector_count; i++) {
info->start[i] = base_addr + i * AMLV640U_SECTOR_SIZE;
addr = (u16 *)info->start[i];
info->protect[i] = addr[2] & 0x1;
}
/* Reset flash */
base[0] = 0xF0;
return info->size;
}
ulong amlv640u_flash_init (flash_info_t * info)
{
ulong base_addr[CONFIG_SYS_MAX_FLASH_BANKS] = CONFIG_SYS_FLASH_BANKS_LIST;
ulong size = 0;
int i;
for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
if (info[i].flash_id == FLASH_UNKNOWN) {
size += amlv640u_get_size(&info[i], base_addr[i]);
}
}
return size;
}
#endif
@@ -0,0 +1,48 @@
/*
* (C) Copyright Mindspeed Technologies Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/* This code runs from ARM1 and setups the CPU before jumping to
the beginning of the ARM1 image (usually a Linux zImage).
It must be copied to 0x00000000 before releasing ARM1.
Linker script variables (in u-boot.lds) are used to find the
start and end address of this bit of code */
.globl _arm1_start_addr
.globl _arm1_r0
.globl _arm1_r1
.globl _arm1_r2
ldr r0, _arm1_r0
ldr r1, _arm1_r1
ldr r2, _arm1_r2
ldr pc, _arm1_start_addr
_arm1_start_addr:
.word 0x00000000
_arm1_r0:
.word 0x00000000
_arm1_r1:
.word 0x00000000
_arm1_r2:
.word 0x00000000
@@ -0,0 +1,595 @@
/*
* (C) Copyright 2006
* Mindspeed Technologies, Inc. <www.mindspeed.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <common.h>
#include <config.h>
#include <command.h>
#include <asm/byteorder.h>
#include <asm/hardware.h>
#ifdef CONFIG_CMD_ELF
extern int valid_elf_image (unsigned long addr);
extern unsigned long load_elf_image (unsigned long addr);
#endif
DECLARE_GLOBAL_DATA_PTR;
struct _AIF_HEADER {
u32 BL_DecompressCode;
u32 BL_SelfRelocCode;
u32 BL_DbgInitZeroInit;
u32 EntryPointOffset;
u32 ProgramExitInstr;
u32 ImageReadOnlySize;
u32 ImageReadWriteSize;
u32 ImageDebugSize;
u32 ImageZeroInitSize;
u32 ImageDebugType;
u32 ImageBase;
u32 WorkSpace;
u32 AddressMode;
u32 DataBase;
u32 FirstFatOffset;
u32 Reserved2;
u32 DebugInitInstr;
u32 ZeroInitCode[15];
};
struct _FAT_AIF_HEADER {
u32 NextFatOffset;
u32 LoadAddress;
u32 Size;
u8 region_name[32];
};
/**
* print_axf_hdr -
*
*/
static void print_axf_hdr(ulong addr)
{
struct _AIF_HEADER *aif_hdr = (struct _AIF_HEADER *)(addr);
/* we assume that MSP image in memory is not less than the header size (_AIF_HEADER) */
printf("code_offset=0x80\n");
printf("code_base=%x\n", aif_hdr->ImageBase);
printf("data_offset=%x\n", 0x80 + aif_hdr->ImageReadOnlySize);
printf("code_size=%x\n", aif_hdr->ImageReadOnlySize);
printf("data_base=%x\n", aif_hdr->ImageBase + aif_hdr->ImageReadOnlySize);
printf("data_size=%x\n", aif_hdr->ImageReadWriteSize);
printf("zeroinit_base=%x\n",
aif_hdr->ImageBase + aif_hdr->ImageReadOnlySize + aif_hdr->ImageReadWriteSize);
printf("prog_entry=%x\n", aif_hdr->ImageBase + aif_hdr->EntryPointOffset);
printf(" \n");
printf("AIFHEADER:\n");
printf("BL_DecompressCode=%x\n", aif_hdr->BL_DecompressCode);
printf("BL_SelfRelocCode=%x\n", aif_hdr->BL_SelfRelocCode);
printf("BL_DbgInitZeroInit=%x\n", aif_hdr->BL_DbgInitZeroInit);
printf("EntryPointOffset=%x\n", aif_hdr->EntryPointOffset);
printf("ProgramExitInstr=%x\n", aif_hdr->ProgramExitInstr);
printf("ImageReadOnlySize=%x\n", aif_hdr->ImageReadOnlySize);
printf("ImageReadWriteSize=%x\n", aif_hdr->ImageReadWriteSize);
printf("ImageDebugSize=%x\n", aif_hdr->ImageDebugSize);
printf("ImageZeroInitSize=%x\n", aif_hdr->ImageZeroInitSize);
printf("ImageDebugType=%x\n", aif_hdr->ImageDebugType);
printf("ImageBase=%x\n", aif_hdr->ImageBase);
printf("WorkSpace=%x\n", aif_hdr->WorkSpace);
printf("AddressMode=%x\n", aif_hdr->AddressMode);
printf("DataBase=%x\n", aif_hdr->DataBase);
printf("FirstFatOffset=%x\n", aif_hdr->FirstFatOffset);
printf("Reserved2=%x\n", aif_hdr->Reserved2);
printf("DebugInitInstr=%x\n", aif_hdr->DebugInitInstr);
printf("ZeroInitCode[0]=%x\n", aif_hdr->ZeroInitCode[0]);
}
/**
* check_load_addr -
*
*/
static int check_load_addr(ulong addr)
{
if ((addr > MSP_BOTTOM_MEMORY_RESERVED_SIZE) &&
#if defined(CONFIG_COMCERTO_530)
((addr < ERAM_BASEADDR) || (addr >= IRAM_BASEADDR + IRAM_SIZE))
#elif defined(CONFIG_COMCERTO_515) || defined(CONFIG_COMCERTO_800)
((addr < ERAM_BASEADDR) || (addr >= ARAM_BASEADDR + ARAM_SIZE))
#elif defined(CONFIG_COMCERTO_900)
((addr < ERAM_BASEADDR) || (addr >= CRAM_BASEADDR + CRAM_SIZE))
#else
(1)
#endif
)
return -1;
return 0;
}
/**
* load_axf_zero -
*
*/
static int load_axf_zero(ulong addr)
{
struct _AIF_HEADER *aif_hdr = (struct _AIF_HEADER *)(addr);
u32 m_data_base;
u32 bytes_to_load;
if (aif_hdr->DataBase)
m_data_base = aif_hdr->DataBase;
else
m_data_base = aif_hdr->ImageBase + aif_hdr->ImageReadOnlySize;
m_data_base = m_data_base + aif_hdr->ImageReadWriteSize;
bytes_to_load = aif_hdr->ImageZeroInitSize / 2;
if (check_load_addr(m_data_base + bytes_to_load) < 0) {
printf("data section load address %x outside range\n", m_data_base + bytes_to_load);
goto err;
}
memset((void *)m_data_base, 0, bytes_to_load);
return 0;
err:
return -1;
}
/**
* load_axf_fat -
*/
static int load_axf_fat(ulong addr, ulong size)
{
struct _AIF_HEADER *aif_hdr = (struct _AIF_HEADER *)(addr);
struct _FAT_AIF_HEADER *fat_aif_hdr;
u32 fat_offset;
fat_offset = aif_hdr->FirstFatOffset;
while (fat_offset > 0) {
if ((fat_offset + sizeof(struct _FAT_AIF_HEADER)) > size) {
printf("fat section header at %x outside image %lx\n", fat_offset, size);
goto err;
}
fat_aif_hdr = (struct _FAT_AIF_HEADER *)(addr + fat_offset);
if ((fat_offset + sizeof(struct _FAT_AIF_HEADER) + fat_aif_hdr->Size) > size) {
printf("fat section size %x bigger than image size %lx\n", fat_offset + sizeof(struct _FAT_AIF_HEADER) + fat_aif_hdr->Size, size);
goto err;
}
if (check_load_addr(fat_aif_hdr->LoadAddress + fat_aif_hdr->Size) < 0) {
printf("fat section load address %x outside range\n", fat_aif_hdr->LoadAddress + fat_aif_hdr->Size);
goto err;
}
memcpy((void *)fat_aif_hdr->LoadAddress,
(void *)(addr + fat_offset + sizeof(struct _FAT_AIF_HEADER)), fat_aif_hdr->Size);
fat_offset = fat_aif_hdr->NextFatOffset;
}
return 0;
err:
return -1;
}
/**
* load_axf_data -
*/
static int load_axf_data(ulong addr, ulong size)
{
struct _AIF_HEADER *aif_hdr = (struct _AIF_HEADER *)(addr);
if (aif_hdr->ImageReadWriteSize) {
if ((sizeof(struct _AIF_HEADER) + aif_hdr->ImageReadOnlySize + aif_hdr->ImageReadWriteSize) > size) {
printf("data section size %x bigger than image size %lx\n", aif_hdr->ImageReadWriteSize, size);
goto err;
}
if (aif_hdr->DataBase == 0) {
if (check_load_addr(aif_hdr->ImageBase + aif_hdr->ImageReadOnlySize + aif_hdr->ImageReadWriteSize) < 0) {
printf("data section load address %x outside range\n", aif_hdr->ImageBase + aif_hdr->ImageReadOnlySize + aif_hdr->ImageReadWriteSize);
goto err;
}
memcpy((void *)(aif_hdr->ImageBase + aif_hdr->ImageReadOnlySize),
(void *)(addr + sizeof(struct _AIF_HEADER) + aif_hdr->ImageReadOnlySize),
aif_hdr->ImageReadWriteSize);
} else {
if (check_load_addr(aif_hdr->DataBase + aif_hdr->ImageReadWriteSize) < 0) {
printf("data section load address %x outside range\n", aif_hdr->DataBase + aif_hdr->ImageReadWriteSize);
goto err;
}
memcpy((void *)aif_hdr->DataBase,
(void *)(addr + sizeof(struct _AIF_HEADER) + aif_hdr->ImageReadOnlySize),
aif_hdr->ImageReadWriteSize);
}
} else {
printf("data section size 0\n");
}
return 0;
err:
return -1;
}
/**
* load_axf_code -
*
*/
static int load_axf_code(ulong addr, ulong size)
{
struct _AIF_HEADER *aif_hdr = (struct _AIF_HEADER *)(addr);
if (aif_hdr->ImageReadOnlySize) {
if ((sizeof(struct _AIF_HEADER) + aif_hdr->ImageReadOnlySize) > size) {
printf("code section size %x bigger than image size %lx\n", aif_hdr->ImageReadOnlySize, size);
goto err;
}
if (check_load_addr(aif_hdr->ImageBase + aif_hdr->ImageReadOnlySize) < 0) {
printf("code section load address %x outside range\n", aif_hdr->ImageBase + aif_hdr->ImageReadOnlySize);
goto err;
}
memcpy((void *)aif_hdr->ImageBase, (void *)(addr + sizeof(struct _AIF_HEADER)), aif_hdr->ImageReadOnlySize);
} else {
printf("code section size 0\n");
}
return 0;
err:
return -1;
}
/**
* load_axf_image -
*
*/
static ulong load_axf_image(ulong addr, ulong size)
{
struct _AIF_HEADER *aif_hdr = (struct _AIF_HEADER *) addr;
printf ("## Downloading image at %08lx ...\n", addr);
if (sizeof (struct _AIF_HEADER) > size) {
printf("AXF header %x bigger than image size %lx\n", sizeof (struct _AIF_HEADER), size);
goto err;
}
print_axf_hdr(addr);
if (load_axf_code(addr, size)) {
printf("download code failed\n");
goto err;
}
if (load_axf_data(addr, size)) {
printf("download data failed\n");
goto err;
}
if (load_axf_fat(addr, size)) {
printf("download fat failed\n");
goto err;
}
if (load_axf_zero(addr)) {
printf("zero init failed\n");
goto err;
}
// printf ("## Booting image at %08lx ...\n", aif_hdr->ImageBase + aif_hdr->EntryPointOffset);
return aif_hdr->ImageBase + aif_hdr->EntryPointOffset;
err:
return (ulong)-1;
}
/**
* strtoul_with_check - reads unsigned long hex value from string with checking
*
* ARGUMENTS:
* str: the string to scan value from
* pvalue: pointer to the value location (if be NULL just checking will be
* performed)
* label: optinal label for the typical error message (if NULL no message
* will be printed)
*
* RETURNS:
* 0 success, -1 otherwise
*/
static int strtoul_with_check(const char *str, ulong *pvalue, const char *label)
{
ulong value;
char *end = NULL;
value = simple_strtoul(str, &end, 16);
if (str == end || *end != 0) {
if (label)
printf("Invalid %s given, please provide correct hex value.\n", label);
return -1;
}
if (pvalue)
*pvalue = value;
return 0;
}
/**
* do_loadmsp - loads MSP image, it may be in either ELF or AXF format. If image
* is successfully loaded, stores MSP entry in "msp_start_addr" env. variable.
*
* ARGUMENTS:
* standard set of U-Boot command arguments, user must pass image address
* and size (all in hex).
*
* RETURNS:
* 0 - success, -1 otherwise
*/
static int do_loadmsp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
ulong addr, size;
char buf[32];
if (argc < 3) {
goto err;
}
if (strtoul_with_check(argv[1], &addr, "image address"))
goto err;
if (strtoul_with_check(argv[2], &size, "image size"))
goto err;
#ifdef CONFIG_CMD_ELF
if (valid_elf_image(addr))
addr = load_elf_image(addr);
else
addr = load_axf_image(addr, size);
#else
addr = load_axf_image(addr, size);
#endif
if (addr == (ulong)-1)
goto err;
/* store MSP start addr in environment (we will need it do_bootcomcerto) */
sprintf(buf, "%lx", addr);
setenv("msp_start_addr", buf);
printf("image loaded at %lx\n", addr);
return 0;
err:
printf("error loading image\n");
return -1;
}
U_BOOT_CMD(
loadmsp, 3, 0, do_loadmsp,
"loadmsp - load MSP image (AXF or ELF format) and save MSP start address\n",
"address size\n"
" - 'address' (hex) points to MSP image location.\n"
" 'size' (hex) specifies image size.\n"
" See also 'bootcomcerto' command.\n"
);
extern char __arm1_init_start, __arm1_init_end;
extern u32 _arm1_start_addr, _arm1_r0, _arm1_r1, _arm1_r2;
/**
* set_arm1_init - copies ARM1 startup code to reset location and sets CSP
* image startup address
*
* ARGUMENTS:
* addr: CSP entry point
* r0,r1,r2: values for the corresponding ARM1 registers
*/
static void set_arm1_init(ulong addr, ulong r0, ulong r1, ulong r2)
{
_arm1_start_addr = addr;
_arm1_r0 = r0;
_arm1_r1 = r1;
_arm1_r2 = r2;
printf("Copying ARM1 startup code from %p, start address %08lx\n",
&__arm1_init_start, addr);
memcpy(0, &__arm1_init_start, &__arm1_init_end - &__arm1_init_start);
}
#if !defined(CONFIG_COMCERTO_1000) && !defined(CONFIG_COMCERTO_100)
/* This code only applies to Carrier/Access platforms, where ARM0 is running
* the MSP and ARM1 the CSP
*/
extern image_header_t header;
extern void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
ulong addr, ulong *len_ptr, int verify);
#define BOOT_ETH_BASE_ADDRESS (IRAM_BASEADDR + 0x1250)
#define MAGIC_NUM_ADDRESS_IRAM (BOOT_ETH_BASE_ADDRESS + 0x10)
#define FLAGS_ADDRESS_IRAM (BOOT_ETH_BASE_ADDRESS + 0x14)
#define M1_ADDRESS_IRAM (BOOT_ETH_BASE_ADDRESS + 0x18)
#define M5_ADDRESS_IRAM (BOOT_ETH_BASE_ADDRESS + 0x24)
#define MAGIC_NUM_IRAM 0x98765432
#define ETHADDR_IRAM_MASK (1 << 0)
static void msp_boot_eth_hdr_setup(bd_t * bd)
{
struct eth_hdr {
u8 hostmac[6];
u8 mspmac[6];
u8 padding;
u16 packet_type;
} __attribute__((packed)) *hdr;
/* The MSP expects an ethernet header at this IRAM address */
/* at boot time */
hdr = (struct eth_hdr *)(BOOT_ETH_BASE_ADDRESS + 1);
hdr->hostmac[0] = 0x00;
hdr->hostmac[1] = 0x11;
hdr->hostmac[2] = 0x22;
hdr->hostmac[3] = 0x33;
hdr->hostmac[4] = 0x44;
hdr->hostmac[5] = 0x55;
hdr->mspmac[0] = 0x00;
hdr->mspmac[1] = 0x1a;
hdr->mspmac[2] = 0x1b;
hdr->mspmac[3] = 0x1c;
hdr->mspmac[4] = 0x1d;
hdr->mspmac[5] = 0x1e;
hdr->packet_type = 0x889b;
}
static void msp_iram_flags_setup(bd_t * bd)
{
int i;
ulong reg;
char *s, *e;
char tmp[64];
/* pass miscellaneous params to the MSP via IRAM
Since these are not passed by all boot loaders use a magic number
to tell the MSP that if parameters are present */
*(u32 *)MAGIC_NUM_ADDRESS_IRAM = MAGIC_NUM_IRAM;
/* the next word is a bit-map that tells the MSP which parameters are present,
this allows params to be added and different versions of bootloader and MSP
to inter-operate */
/* always have ethaddr; even if user does not specify it (which is an error), we have a default */
*(u32 *)FLAGS_ADDRESS_IRAM = ETHADDR_IRAM_MASK;
/* write ethernet address */
memcpy((u8 *)M1_ADDRESS_IRAM, bd->bi_enetaddr, 6);
i = getenv_r ("eth1addr", tmp, sizeof (tmp));
s = (i > 0) ? tmp : NULL;
for (reg = 0; reg < 6; ++reg) {
*(u8 *) (M5_ADDRESS_IRAM + reg) = s ? simple_strtoul (s, &e, 16) : 0;
if (s)
s = (*e) ? e + 1 : e;
}
}
/**
* do_bootcomcerto - checks if MSP image was loaded, then loads CSP image which
* may be in either binary or ELF format and boots MSP.
*
* ARGUMENTS:
* standard set of U-Boot command arguments, user must pass CSP image address
*
* RETURNS:
* doesn't return on success
*/
static int do_bootcomcerto (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
ulong csp_start_addr, msp_start_addr;
int csp_is_elf = 0;
bd_t *bd = gd->bd;
char *str;
if (argc < 2) {
return -1;
}
str = getenv("msp_start_addr");
if (!str) {
printf("MSP start address is not set, see 'loadmsp' command\n");
return -1;
}
if (strtoul_with_check(str, &msp_start_addr, NULL)) {
printf("Invalid MSP address, aborting\n");
return -1;
}
if (strtoul_with_check(argv[1], &csp_start_addr, "image address"))
return -1;
#ifdef CONFIG_CMD_ELF
if ((csp_is_elf = valid_elf_image(csp_start_addr)) != 0)
csp_start_addr = load_elf_image(csp_start_addr);
#endif
/* Setup MSP boot args in IRAM */
msp_boot_eth_hdr_setup(bd);
msp_iram_flags_setup(bd);
if (csp_is_elf == 0) {
/* CSP image is in binary format, assuming Linux */
/* Fake header to keep do_bootm_linux() happy
* No ramdisk support for now
*/
header.ih_ep = htonl(msp_start_addr); /* This is actually the MSP entry point */
header.ih_type = IH_TYPE_KERNEL;
#if 0
hdr->ih_magic = htonl(IH_MAGIC);
hdr->ih_hcrc = htonl(0); /* FIXME calculate the checksum */
hdr->ih_size = htonl(0);
#endif
set_arm1_init(csp_start_addr, 0, bd->bi_arch_number, bd->bi_boot_params);
do_bootm_linux(cmdtp, 0, argc, argv, 0, NULL, 0);
}
else {
/* CSP image is in ELF, assuming VxWorks */
set_arm1_init(csp_start_addr, (unsigned int)getenv("bootargs"), 0, 0);
((void(*)(void))msp_start_addr)();
}
printf("Unexpected return to bootloader!\n");
return 0;
}
U_BOOT_CMD(
bootcomcerto, 2, 0, do_bootcomcerto,
"bootcomcerto - load CSP image (binary or ELF format) and start Comcerto device\n",
"address\n"
" - 'address'(hex) points to CSP image location.\n"
" See also 'loadmsp' command, which must be run before this one.\n"
);
#endif
@@ -0,0 +1,236 @@
/*
* (C) Copyright Mindspeed Technologies Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
#ifdef CONFIG_FLASH_CFI_DRIVER
#define FLASH_MAN_CFI 0x01000000
#ifdef CONFIG_SYS_FLASH_PROTECTION
extern int cfi_flash_real_protect(flash_info_t *info, long sector, int prot);
#endif
extern int cfi_flash_erase(flash_info_t * info, int s_first, int s_last);
extern int cfi_write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt);
extern void cfi_flash_print_info(flash_info_t *info);
extern unsigned long cfi_flash_init(void);
#endif
#ifdef CFG_FLASH_AM040_DRIVER
#ifdef CONFIG_SYS_FLASH_PROTECTION
int am29lv040b_flash_real_protect(flash_info_t *info, long sector, int prot);
#endif
int am29lv040b_flash_erase(flash_info_t * info, int s_first, int s_last);
int am29lv040b_write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt);
ulong am29lv040b_flash_init(flash_info_t * info);
#endif
#ifdef CFG_FLASH_AMLV640U_DRIVER
int amlv640u_flash_erase (flash_info_t *info, int s_first, int s_last);
int amlv640u_write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt);
ulong amlv640u_flash_init(flash_info_t * info);
#endif
int flash_erase(flash_info_t * info, int s_first, int s_last)
{
if (info->flash_id == FLASH_UNKNOWN) {
printf ("missing or unknown FLASH type\n");
return ERR_UNKNOWN_FLASH_TYPE;
}
if ((s_first < 0) || (s_first > s_last) || (s_last >= info->sector_count)) {
return ERR_INVAL;
}
#ifdef CONFIG_FLASH_CFI_DRIVER
if (info->flash_id == FLASH_MAN_CFI)
return cfi_flash_erase(info, s_first, s_last);
#endif
#ifdef CFG_FLASH_AM040_DRIVER
if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040)
return am29lv040b_flash_erase(info, s_first, s_last);
#endif
#ifdef CFG_FLASH_AMLV640U_DRIVER
if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV640U)
return amlv640u_flash_erase(info, s_first, s_last);
#endif
return ERR_UNKNOWN_FLASH_TYPE;
}
#ifdef CONFIG_SYS_FLASH_PROTECTION
int flash_real_protect(flash_info_t *info, long sector, int prot)
{
if (info->flash_id == FLASH_UNKNOWN) {
printf ("missing or unknown FLASH type\n");
return ERR_UNKNOWN_FLASH_TYPE;
}
if ((sector < 0) || (sector >= info->sector_count)) {
return ERR_INVAL;
}
#ifdef CONFIG_FLASH_CFI_DRIVER
if (info->flash_id == FLASH_MAN_CFI)
return cfi_flash_real_protect(info, sector, prot);
#endif
#ifdef CFG_FLASH_AM040_DRIVER
if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040)
return am29lv040b_flash_real_protect(info, sector, prot);
#endif
#ifdef CFG_FLASH_AMLV640U_DRIVER
if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV640U)
return amlv640u_flash_real_protect(info, sector, prot);
#endif
return ERR_UNKNOWN_FLASH_TYPE;
}
#endif
int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
if (info->flash_id == FLASH_UNKNOWN) {
printf ("missing or unknown FLASH type\n");
return ERR_UNKNOWN_FLASH_TYPE;
}
#ifdef CONFIG_FLASH_CFI_DRIVER
if (info->flash_id == FLASH_MAN_CFI)
return cfi_write_buff(info, src, addr, cnt);
#endif
#ifdef CFG_FLASH_AM040_DRIVER
if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040)
return am29lv040b_write_buff(info, src, addr, cnt);
#endif
#ifdef CFG_FLASH_AMLV640U_DRIVER
if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV640U)
return amlv640u_write_buff(info, src, addr, cnt);
#endif
return ERR_UNKNOWN_FLASH_TYPE;
}
/*-----------------------------------------------------------------------
*/
void flash_print_info(flash_info_t *info)
{
int i;
if (info->flash_id == FLASH_UNKNOWN) {
printf ("missing or unknown FLASH type\n");
return;
}
#ifdef CONFIG_FLASH_CFI_DRIVER
if (info->flash_id == FLASH_MAN_CFI) {
cfi_flash_print_info(info);
return;
}
#endif
switch (info->flash_id & FLASH_VENDMASK) {
case FLASH_MAN_AMD:
printf ("AMD ");
break;
case FLASH_MAN_FUJ:
printf ("FUJITSU ");
break;
/* Add other supported flash vendors here */
default:
printf ("Unknown Vendor ");
return;
break;
}
switch (info->flash_id & FLASH_TYPEMASK) {
case FLASH_AM040:
printf("AM29LV040B (4Mbit, uniform sector size)\n");
break;
case FLASH_AMLV640U:
printf ("AM29LV640ML/S29GL064M (64Mbit, uniform sector size)\n");
break;
default:
printf ("Unknown Chip Type\n");
return;
break;
}
if ((info->size >> 20) > 0)
printf (" Size: %ld MiB in %d Sectors\n", info->size >> 20, info->sector_count);
else
printf (" Size: %ld KiB in %d Sectors\n", info->size >> 10, info->sector_count);
printf (" Sector Start Addresses:");
for (i = 0; i < info->sector_count; ++i) {
if ((i % 5) == 0)
printf ("\n ");
printf (" %08lX%s",
info->start[i],
info->protect[i] ? " (RO)" : " "
);
}
printf ("\n");
return;
}
unsigned long flash_init(void)
{
unsigned long size = 0;
int i;
printf("Comcerto Flash Subsystem Initialization\n");
/* Init: no Flashes known */
for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
flash_info[i].flash_id = FLASH_UNKNOWN;
}
#ifdef CONFIG_FLASH_CFI_DRIVER
/* CFI compatible flash detection */
/* must be done first */
size += cfi_flash_init();
#endif
#ifdef CFG_FLASH_AM040_DRIVER
size += am29lv040b_flash_init(flash_info);
#endif
#ifdef CFG_FLASH_AMLV640U_DRIVER
size += amlv640u_flash_init(flash_info);
#endif
return size;
}
@@ -0,0 +1,559 @@
/*
* (C) Copyright 2007
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <config.h>
#include <common.h>
#include <asm/hardware.h>
#include <asm/arch/bsp.h>
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
#define MAX_I2C_RETRYS 10
#define I2C_DELAY 1000 /* Should be at least the # of MHz of Tclk */
#define I2C_ADDR (I2C_BASEADDR + 0x00)
#define I2C_DATA (I2C_BASEADDR + 0x04)
#define I2C_CNTR (I2C_BASEADDR + 0x08)
#define I2C_STAT (I2C_BASEADDR + 0x0c)
#define I2C_CCRFS (I2C_BASEADDR + 0x0c)
#define I2C_XADDR (I2C_BASEADDR + 0x10)
#define I2C_CCRH (I2C_BASEADDR + 0x14)
#define I2C_SOFT_RESET (I2C_BASEADDR + 0x1c)
/* CNTR - Control register bits */
#define I2C_IEN (1<<7)
#define I2C_ENAB (1<<6)
#define I2C_STA (1<<5)
#define I2C_STP (1<<4)
#define I2C_IFLG (1<<3)
#define I2C_AAK (1<<2)
/* STAT - Status codes */
#define I2C_BUS_ERROR 0x00 /* Bus error in master mode only */
#define I2C_START_TRANSMIT 0x08 /* Start condition transmitted */
#define I2C_REPEAT_START_TRANSMIT 0x10 /* Repeated Start condition transmited */
#define I2C_ADDRESS_W_ACK 0x18 /* Address + Write bit transmitted, ACK received */
#define I2C_ADDRESS_W_NACK 0x20 /* Address + Write bit transmitted, NACK received */
#define I2C_DATA_TRANSMIT_ACK 0x28 /* Data byte transmitted in master mode , ACK received */
#define I2C_DATA_TRANSMIT_NACK 0x30 /* Data byte transmitted in master mode , NACK received */
#define I2C_ARBIT_LOST 0x38 /* Arbitration lost in address or data byte */
#define I2C_ADDRESS_R_ACK 0x40 /* Address + Read bit transmitted, ACK received */
#define I2C_ADDRESS_R_NACK 0x48 /* Address + Read bit transmitted, NACK received */
#define I2C_DATA_RECEIVE_ACK 0x50 /* Data byte received in master mode, ACK transmitted */
#define I2C_DATA_RECEIVE_NACK 0x58 /* Data byte received in master mode, NACK transmitted*/
#define I2C_ARBIT_LOST_ADDRESS 0x68 /* Arbitration lost in address */
#define I2C_GENERAL_CALL 0x70 /* General Call, ACK transmitted */
#define I2C_NO_RELEVANT_INFO 0xF8 /* No relevant status information, IFLF=0 */
#define I2C_READ_REG(reg) *(volatile u32*)(reg)
#define I2C_WRITE_REG(reg, val) *(volatile u32*)(reg) = val
#define RESET_REG_BITS(reg, val) I2C_WRITE_REG(reg, I2C_READ_REG(reg) & ~(val))
#undef DEBUG_I2C
//#define DEBUG_I2C
#ifdef DEBUG_I2C
#define DP(x) x
#else
#define DP(x)
#endif
/* Assuming that there is only one master on the bus (us) */
void i2c_init (int speed, int slaveaddr)
{
unsigned int n, m, freq, margin, power;
unsigned int actualN = 0, actualM = 0;
unsigned int control, status;
unsigned int minMargin = 0xffffffff;
unsigned int tclk = CONFIG_SYS_TCLK;
unsigned int i2cFreq = speed; /* 100000 max. Fast mode not supported */
DP (puts ("i2c_init\n"));
for (n = 0; n < 8; n++) {
for (m = 0; m < 16; m++) {
power = 1 << n; /* power = 2^(n) */
freq = tclk / (10 * (m + 1) * power);
if (i2cFreq > freq)
margin = i2cFreq - freq;
else
margin = freq - i2cFreq;
if (margin < minMargin) {
minMargin = margin;
actualN = n;
actualM = m;
}
}
}
DP (puts ("setup i2c bus\n"));
/* Setup bus */
I2C_WRITE_REG(I2C_SOFT_RESET, 0);
DP (puts ("udelay...\n"));
udelay (I2C_DELAY);
DP (puts ("set baudrate\n"));
I2C_WRITE_REG(I2C_STAT, (actualM << 3) | actualN);
I2C_WRITE_REG(I2C_CNTR, I2C_AAK | I2C_ENAB);
udelay (I2C_DELAY * 10);
DP (puts ("read control, baudrate\n"));
status = I2C_READ_REG(I2C_STAT);
control = I2C_READ_REG(I2C_CNTR);
}
static uchar i2c_start (void)
{
unsigned int control, status;
int count = 0;
DP (puts ("i2c_start\n"));
/* Set the start bit */
control = I2C_READ_REG(I2C_CNTR);
control |= I2C_STA; /* generate the I2C_START_BIT */
I2C_WRITE_REG(I2C_CNTR, control);
status = I2C_READ_REG(I2C_STAT);
count = 0;
while ((status & 0xff) != I2C_START_TRANSMIT) {
udelay (I2C_DELAY);
if (count > 20) {
I2C_WRITE_REG(I2C_CNTR, I2C_STP); /*stop */
return (status);
}
status = I2C_READ_REG(I2C_STAT);
count++;
}
return (0);
}
static uchar i2c_select_device (uchar dev_addr, uchar read, int ten_bit)
{
unsigned int status, data, bits = 7;
int count = 0;
DP (puts ("i2c_select_device\n"));
/* Output slave address */
if (ten_bit) {
bits = 10;
}
data = (dev_addr << 1);
/* set the read bit */
data |= read;
I2C_WRITE_REG(I2C_DATA, data);
/* assert the address */
RESET_REG_BITS (I2C_CNTR, I2C_IFLG);
udelay (I2C_DELAY);
status = I2C_READ_REG(I2C_STAT);
count = 0;
while (((status & 0xff) != I2C_ADDRESS_R_ACK) && ((status & 0xff) != I2C_ADDRESS_W_ACK)) {
udelay (I2C_DELAY);
if (count > 20) {
I2C_WRITE_REG(I2C_CNTR, I2C_STP); /*stop */
return (status);
}
status = I2C_READ_REG(I2C_STAT);
count++;
}
if (bits == 10) {
printf ("10 bit I2C addressing not yet implemented\n");
return (0xff);
}
return (0);
}
static uchar i2c_get_data (uchar * return_data, int len)
{
unsigned int data, status = 0;
int count = 0;
DP (puts ("i2c_get_data\n"));
while (len) {
/* Get and return the data */
RESET_REG_BITS (I2C_CNTR, I2C_IFLG);
udelay (I2C_DELAY * 5);
status = I2C_READ_REG(I2C_STAT);
count++;
while ((status & 0xff) != I2C_DATA_RECEIVE_ACK) {
udelay (I2C_DELAY);
if (count > 2) {
I2C_WRITE_REG(I2C_CNTR, I2C_STP); /*stop */
return 0;
}
status = I2C_READ_REG(I2C_STAT);
count++;
}
data = I2C_READ_REG(I2C_DATA);
len--;
*return_data = (uchar) data;
return_data++;
}
RESET_REG_BITS (I2C_CNTR, I2C_AAK | I2C_IFLG);
while ((status & 0xff) != I2C_DATA_RECEIVE_NACK) {
udelay (I2C_DELAY);
if (count > 200) {
I2C_WRITE_REG(I2C_CNTR, I2C_STP); /*stop */
return (status);
}
status = I2C_READ_REG(I2C_STAT);
count++;
}
I2C_WRITE_REG(I2C_CNTR, I2C_STP); /* stop */
return (0);
}
static uchar i2c_write_data (unsigned int *data, int len)
{
unsigned int status;
int count = 0;
unsigned int temp;
unsigned int *temp_ptr = data;
DP (puts ("i2c_write_data\n"));
while (len) {
temp = (unsigned int) (*temp_ptr);
I2C_WRITE_REG(I2C_DATA, temp);
RESET_REG_BITS (I2C_CNTR, I2C_IFLG);
udelay (I2C_DELAY);
status = I2C_READ_REG(I2C_STAT);
count++;
while ((status & 0xff) != I2C_DATA_TRANSMIT_ACK) {
udelay (I2C_DELAY);
if (count > 20) {
I2C_WRITE_REG(I2C_CNTR, I2C_STP); /*stop */
return (status);
}
status = I2C_READ_REG(I2C_STAT);
count++;
}
len--;
temp_ptr++;
}
/* Can't have the write issuing a stop command */
/* it's wrong to have a stop bit in read stream or write stream */
/* since we don't know if it's really the end of the command */
/* or whether we have just send the device address + offset */
/* we will push issuing the stop command off to the original */
/* calling function */
/* set the interrupt bit in the control register */
I2C_WRITE_REG(I2C_CNTR, I2C_IFLG);
udelay (I2C_DELAY * 10);
return (0);
}
/* created this function to get the i2c_write() */
/* function working properly. */
/* function to write bytes out on the i2c bus */
/* this is identical to the function i2c_write_data() */
/* except that it requires a buffer that is an */
/* unsigned character array. You can't use */
/* i2c_write_data() to send an array of unsigned characters */
/* since the byte of interest ends up on the wrong end of the bus */
/* aah, the joys of big endian versus little endian! */
/* */
/* returns 0 = success */
/* anything other than zero is failure */
static uchar i2c_write_byte (unsigned char *data, int len)
{
unsigned int status;
int count = 0;
unsigned int temp;
unsigned char *temp_ptr = data;
DP (puts ("i2c_write_byte\n"));
while (len) {
/* Set and assert the data */
temp = *temp_ptr;
I2C_WRITE_REG(I2C_DATA, temp);
RESET_REG_BITS (I2C_CNTR, I2C_IFLG);
udelay (I2C_DELAY*2);
status = I2C_READ_REG(I2C_STAT);
count++;
while ((status & 0xff) != I2C_DATA_TRANSMIT_ACK) {
udelay (I2C_DELAY*2);
if (count > 20) {
I2C_WRITE_REG(I2C_CNTR, I2C_STP); /*stop */
return (status);
}
status = I2C_READ_REG(I2C_STAT);
count++;
}
len--;
temp_ptr++;
}
/* Can't have the write issuing a stop command */
/* it's wrong to have a stop bit in read stream or write stream */
/* since we don't know if it's really the end of the command */
/* or whether we have just send the device address + offset */
/* we will push issuing the stop command off to the original */
/* calling function */
/* I2C_WRITE_REG(I2C_CNTR, I2C_IFLG | I2C_STP);
I2C_WRITE_REG(I2C_CNTR, I2C_STP); */
/* set the interrupt bit in the control register */
I2C_WRITE_REG(I2C_CNTR, I2C_IFLG);
udelay (I2C_DELAY * 10);
return (0);
}
static uchar
i2c_set_dev_offset (uchar dev_addr, unsigned int offset, int ten_bit,
int alen)
{
uchar status;
unsigned int table[2];
/* initialize the table of address offset bytes */
/* utilized for 2 byte address offsets */
/* NOTE: the order is high byte first! */
table[1] = offset & 0xff; /* low byte */
table[0] = offset / 0x100; /* high byte */
DP (puts ("i2c_set_dev_offset\n"));
status = i2c_select_device (dev_addr, 0, ten_bit);
if (status) {
#ifdef DEBUG_I2C
printf ("Failed to select device setting offset: 0x%02x\n",
status);
#endif
return status;
}
/* check the address offset length */
if (alen == 0)
/* no address offset */
return (0);
else if (alen == 1) {
/* 1 byte address offset */
status = i2c_write_data (&offset, 1);
if (status) {
#ifdef DEBUG_I2C
printf ("Failed to write data: 0x%02x\n", status);
#endif
return status;
}
} else if (alen == 2) {
/* 2 bytes address offset */
status = i2c_write_data (table, 2);
if (status) {
#ifdef DEBUG_I2C
printf ("Failed to write data: 0x%02x\n", status);
#endif
return status;
}
} else {
/* address offset unknown or not supported */
printf ("Address length offset %d is not supported\n", alen);
return 1;
}
return 0; /* sucessful completion */
}
uchar
i2c_read (uchar dev_addr, unsigned int offset, int alen, uchar * data,
int len)
{
uchar status = 0;
unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED;
DP (puts ("i2c_read\n"));
i2c_init (i2cFreq, 0); /* set the i2c frequency */
status = i2c_start ();
if (status) {
#ifdef DEBUG_I2C
printf ("Transaction start failed: 0x%02x\n", status);
#endif
return status;
}
status = i2c_set_dev_offset (dev_addr, offset, 0, alen); /* send the slave address + offset */
if (status) {
#ifdef DEBUG_I2C
printf ("Failed to set slave address & offset: 0x%02x\n",
status);
#endif
return status;
}
i2c_init (i2cFreq, 0); /* set the i2c frequency again */
status = i2c_start ();
if (status) {
#ifdef DEBUG_I2C
printf ("Transaction restart failed: 0x%02x\n", status);
#endif
return status;
}
status = i2c_select_device (dev_addr, 1, 0); /* send the slave address */
if (status) {
#ifdef DEBUG_I2C
printf ("Address not acknowledged: 0x%02x\n", status);
#endif
return status;
}
status = i2c_get_data (data, len);
if (status) {
#ifdef DEBUG_I2C
printf ("Data not recieved: 0x%02x\n", status);
#endif
return status;
}
return 0;
}
/* Function to set the I2C stop bit */
void i2c_stop (void)
{
I2C_WRITE_REG(I2C_CNTR, (0x1 << 4));
}
/* I2C write function */
/* dev_addr = device address */
/* offset = address offset */
/* alen = length in bytes of the address offset */
/* data = pointer to buffer to read data into */
/* len = # of bytes to read */
/* */
/* returns 0 = succesful */
/* anything but zero is failure */
uchar
i2c_write (uchar dev_addr, unsigned int offset, int alen, uchar * data,
int len)
{
uchar status = 0;
unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED;
DP (puts ("i2c_write\n"));
i2c_init (i2cFreq, 0); /* set the i2c frequency */
status = i2c_start (); /* send a start bit */
if (status) {
#ifdef DEBUG_I2C
printf ("Transaction start failed: 0x%02x\n", status);
#endif
return status;
}
status = i2c_set_dev_offset (dev_addr, offset, 0, alen); /* send the slave address + offset */
if (status) {
#ifdef DEBUG_I2C
printf ("Failed to set slave address & offset: 0x%02x\n",
status);
#endif
return status;
}
status = i2c_write_byte (data, len); /* write the data */
if (status) {
#ifdef DEBUG_I2C
printf ("Data not written: 0x%02x\n", status);
#endif
return status;
}
/* issue a stop bit */
i2c_stop ();
return 0;
}
/* function to determine if an I2C device is present */
/* chip = device address of chip to check for */
/* */
/* returns 0 = sucessful, the device exists */
/* anything other than zero is failure, no device */
int i2c_probe (uchar chip)
{
/* We are just looking for an <ACK> back. */
/* To see if the device/chip is there */
#ifdef DEBUG_I2C
unsigned int i2c_status;
#endif
uchar status = 0;
unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED;
DP (puts ("i2c_probe\n"));
i2c_init (i2cFreq, 0); /* set the i2c frequency */
status = i2c_start (); /* send a start bit */
if (status) {
#ifdef DEBUG_I2C
printf ("Transaction start failed: 0x%02x\n", status);
#endif
return (int) status;
}
status = i2c_set_dev_offset (chip, 0, 0, 0); /* send the slave address + no offset */
if (status) {
#ifdef DEBUG_I2C
printf ("Failed to set slave address: 0x%02x\n", status);
#endif
return (int) status;
}
#ifdef DEBUG_I2C
i2c_status = I2C_READ_REG(I2C_STAT);
printf ("address %#x returned %#x\n", chip, i2c_status);
#endif
/* issue a stop bit */
i2c_stop ();
return 0; /* successful completion */
}
#endif
@@ -0,0 +1,69 @@
/*
* (C) Copyright 2006
* Mindspeed Technologies, Inc. <www.mindspeed.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <config.h>
#include <common.h>
#include <asm/io.h>
#include <nand.h>
#include <asm/hardware.h>
#include <asm/arch/bsp.h>
/*
* hardware specific access to control-lines
*/
static void comcerto_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtd->priv;
if (ctrl & NAND_CTRL_CHANGE) {
if ( ctrl & NAND_CLE )
SoC_gpio_set_1(SoC_gpio_mask(CFG_NAND_CLE_GPIO));
else
SoC_gpio_set_0(SoC_gpio_mask(CFG_NAND_CLE_GPIO));
if ( ctrl & NAND_ALE )
SoC_gpio_set_1(SoC_gpio_mask(CFG_NAND_ALE_GPIO));
else
SoC_gpio_set_0(SoC_gpio_mask(CFG_NAND_ALE_GPIO));
if ( ctrl & NAND_NCE )
SoC_gpio_set_0(SoC_gpio_mask(CFG_NAND_CE_GPIO));
else
SoC_gpio_set_1(SoC_gpio_mask(CFG_NAND_CE_GPIO));
}
if (cmd != NAND_CMD_NONE)
writeb(cmd, this->IO_ADDR_W);
}
static int comcerto_nand_ready(struct mtd_info *mtd)
{
return SoC_gpio_read(SoC_gpio_mask(CFG_NAND_BR_GPIO)) ? 1 : 0;
}
int board_nand_init(struct nand_chip *nand)
{
printf("board_nand_init nand->IO_ADDR_R =%x\n", nand->IO_ADDR_R);
nand->options = 0;
nand->ecc.mode = NAND_ECC_SOFT;
nand->cmd_ctrl = comcerto_nand_hwcontrol;
nand->dev_ready = comcerto_nand_ready;
nand->chip_delay = 20;
return 0;
}
@@ -0,0 +1,68 @@
/*
* (C) Copyright Mindspeed Technologies Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/* This code is used to setup the boot CS to 16bit so that
the U-boot image can be read from NOR flash. It is compiled into
a special section (and format) using the u-boot.lds linker script and
u16_to_u8.c application */
#include <config.h>
#include <asm/arch/hardware.h>
.globl _start
_start:
adr r0, iram_code_start
ldr r1, iram_addr
adr r2, iram_code_end
copy:
ldmia r0!, {r3-r6} /* copy from source address [r0] */
stmia r1!, {r3-r6} /* copy to target address [r1] */
cmp r0, r2 /* until source end address [r2] */
ble copy
/* Calculate return address, offset is multiplied by 2 */
adr r0, _start
add r1, r2, r2
sub lr, r1, r0
/* Jump to internal RAM */
ldr pc, iram_addr
iram_addr:
.word IRAM_BASEADDR
/* This codes runs from internal RAM and
sets the boot chip select */
iram_code_start:
ldr r0, cs_reg
ldr r1, cs_val
strh r1, [r0]
/* Jump back to flash, now running in 16 bit */
mov pc, lr
cs_reg:
.word SDC0_CSBOOT_CFG
cs_val:
.word 0x081E
iram_code_end:
@@ -0,0 +1,46 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fpi, *fpo;
unsigned char byte;
unsigned short word;
unsigned int nop;
int count;
if (argc < 3)
goto err0;
fpi = fopen(argv[1], "r");
if (!fpi)
goto err0;
fpo = fopen(argv[2], "w");
if (!fpo)
goto err1;
count = 0;
while(fread(&byte, 1, sizeof(unsigned char), fpi) == 1) {
word = byte << 8 | byte;
fwrite(&word, 1, sizeof(unsigned short), fpo);
count++;
}
/* Align to the next 32bytes boundary with nops */
nop = 0xe1a00000;
count = (32 - (count * 2) % 32) / 4;
while (count--)
fwrite(&nop, 1, sizeof(unsigned int), fpo);
fclose(fpi);
fclose(fpo);
return 0;
err1:
fclose(fpi);
err0:
return 1;
}