Commit ae691e57 authored by Stefan Roese's avatar Stefan Roese Committed by Shinya Kuribayashi

MIPS: Add VCT board series support (Part 2/3)

Signed-off-by: default avatarStefan Roese <sr@denx.de>
parent 50752790
/*
* (C) Copyright 2009 Stefan Roese <sr@denx.de>, DENX Software Engineering
*
* Original Author Guenter Gebhardt
* Copyright (C) 2006 Micronas GmbH
*
* 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 "vct.h"
int vct_ehci_hcd_init(u32 *hccr, u32 *hcor)
{
int retval;
u32 val;
u32 addr;
dcgu_set_reset_switch(DCGU_HW_MODULE_USB_24, DCGU_SWITCH_ON);
dcgu_set_reset_switch(DCGU_HW_MODULE_USB_60, DCGU_SWITCH_ON);
dcgu_set_clk_switch(DCGU_HW_MODULE_USB_24, DCGU_SWITCH_ON);
dcgu_set_clk_switch(DCGU_HW_MODULE_USB_PLL, DCGU_SWITCH_ON);
dcgu_set_reset_switch(DCGU_HW_MODULE_USB_24, DCGU_SWITCH_OFF);
/* Wait until (DCGU_USBPHY_STAT == 7) */
addr = DCGU_USBPHY_STAT(DCGU_BASE);
val = reg_read(addr);
while (val != 7)
val = reg_read(addr);
dcgu_set_clk_switch(DCGU_HW_MODULE_USB_60, DCGU_SWITCH_ON);
dcgu_set_reset_switch(DCGU_HW_MODULE_USB_60, DCGU_SWITCH_OFF);
retval = scc_reset(SCC_USB_RW, 0);
if (retval) {
printf("scc_reset(SCC_USB_RW, 0) returned: 0x%x\n", retval);
return retval;
} else {
retval = scc_reset(SCC_CPU1_SPDMA_RW, 0);
if (retval) {
printf("scc_reset(SCC_CPU1_SPDMA_RW, 0) returned: 0x%x\n",
retval);
return retval;
}
}
if (!retval) {
/*
* For the AGU bypass, where the SCC client provides full
* physical address
*/
scc_set_usb_address_generation_mode(1);
scc_setup_dma(SCC_USB_RW, BCU_USB_BUFFER_1, DMA_LINEAR,
USE_NO_FH, DMA_READ, 0);
scc_setup_dma(SCC_CPU1_SPDMA_RW, BCU_USB_BUFFER_1, DMA_LINEAR,
USE_NO_FH, DMA_WRITE, 0);
scc_setup_dma(SCC_USB_RW, BCU_USB_BUFFER_0, DMA_LINEAR,
USE_NO_FH, DMA_WRITE, 0);
scc_setup_dma(SCC_CPU1_SPDMA_RW, BCU_USB_BUFFER_0, DMA_LINEAR,
USE_NO_FH, DMA_READ, 0);
/* Enable memory interface */
scc_enable(SCC_USB_RW, 1);
/* Start (start_cmd=0) DMAs */
scc_dma_cmd(SCC_USB_RW, DMA_START, 0, DMA_READ);
scc_dma_cmd(SCC_USB_RW, DMA_START, 0, DMA_WRITE);
} else {
printf("Cannot configure USB memory channel.\n");
printf("USB can not access RAM. SCC configuration failed.\n");
return retval;
}
/* Wait a short while */
udelay(300000);
reg_write(USBH_BURSTSIZE(USBH_BASE), 0x00001c1c);
/* Set EHCI structures and DATA in RAM */
reg_write(USBH_USBHMISC(USBH_BASE), 0x00840003);
/* Set USBMODE to bigendian and set host mode */
reg_write(USBH_USBMODE(USBH_BASE), 0x00000007);
/*
* USBH_BURSTSIZE MUST EQUAL 0x00001c1c in order for
* 512 byte USB transfers on the bulk pipe to work properly.
* Set USBH_BURSTSIZE to 0x00001c1c
*/
reg_write(USBH_BURSTSIZE(USBH_BASE), 0x00001c1c);
/* Insert access register addresses */
*hccr = REG_GLOBAL_START_ADDR + USBH_CAPLENGTH(USBH_BASE);
*hcor = REG_GLOBAL_START_ADDR + USBH_USBCMD(USBH_BASE);
return 0;
}
/*
* (C) Copyright 2008 Stefan Roese <sr@denx.de>, DENX Software Engineering
*
* 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 <asm/io.h>
#include "vct.h"
/*
* Find out to which of the 2 gpio modules the pin specified in the
* argument belongs:
* GPIO_MODULE yields 0 for pins 0 to 31,
* 1 for pins 32 to 63
*/
#define GPIO_MODULE(pin) ((pin) >> 5)
/*
* Bit position within a 32-bit peripheral register (where every
* bit is one bitslice)
*/
#define MASK(pin) (1 << ((pin) & 0x1F))
#define BASE_ADDR(mod) module_base[mod]
/*
* Lookup table for transforming gpio module number 0 to 2 to
* address offsets
*/
static u32 module_base[] = {
GPIO1_BASE,
GPIO2_BASE
};
static void clrsetbits(u32 addr, u32 and_mask, u32 or_mask)
{
reg_write(addr, (reg_read(addr) & ~and_mask) | or_mask);
}
int vct_gpio_dir(int pin, int dir)
{
u32 gpio_base;
gpio_base = BASE_ADDR(GPIO_MODULE(pin));
if (dir == 0)
clrsetbits(GPIO_SWPORTA_DDR(gpio_base), MASK(pin), 0);
else
clrsetbits(GPIO_SWPORTA_DDR(gpio_base), 0, MASK(pin));
return 0;
}
void vct_gpio_set(int pin, int val)
{
u32 gpio_base;
gpio_base = BASE_ADDR(GPIO_MODULE(pin));
if (val == 0)
clrsetbits(GPIO_SWPORTA_DR(gpio_base), MASK(pin), 0);
else
clrsetbits(GPIO_SWPORTA_DR(gpio_base), 0, MASK(pin));
}
int vct_gpio_get(int pin)
{
u32 gpio_base;
u32 value;
gpio_base = BASE_ADDR(GPIO_MODULE(pin));
value = reg_read(GPIO_EXT_PORTA(gpio_base));
return ((value & MASK(pin)) ? 1 : 0);
}
This diff is collapsed.
/*
* (C) Copyright 2009 Stefan Roese <sr@denx.de>, DENX Software Engineering
*
* Copyright (C) 2006 Micronas GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#ifndef _SCC_H
#define _SCC_H
#define DMA_READ 0 /* SCC read DMA */
#define DMA_WRITE 1 /* SCC write DMA */
#define DMA_LINEAR 0 /* DMA linear buffer access method */
#define DMA_CYCLIC 1 /* DMA cyclic buffer access method */
#define DMA_START 0 /* DMA command - start DMA */
#define DMA_STOP 1 /* DMA command - stop DMA */
#define DMA_START_FH_RESET 2 /* DMA command - start DMA reset FH */
#define DMA_TAKEOVER 15 /* DMA command - commit the DMA conf */
#define AGU_ACTIVE 0 /* enable AGU address calculation */
#define AGU_BYPASS 1 /* set AGU to bypass mode */
#define USE_NO_FH 0 /* order the DMA to not use FH */
#define USE_FH 1 /* order the DMA to work with FH*/
#define SCC_DBG_IDLE 0 /* DEBUG status (idle interfaces) */
#define SCC_DBG_SYNC_RES 0x0001 /* synchronuous reset */
#define SCC_TO_IMMEDIATE 1 /* takeover command issued immediately*/
#define TO_DMA_CFG 2 /* takeover command for the DMA config*/
#define DMA_CMD_RESET 0
#define DMA_CMD_SETUP 1
#define DMA_CMD_START 2
#define DMA_CMD_STOP 3
#define DMA_STATE_RESET 0
#define DMA_STATE_SETUP 1
#define DMA_STATE_START 2
#define DMA_STATE_ERROR 3
#define SRMD 0
#define STRM_D 1
#define STRM_P 2
/*
* Slowest Monterey domain is DVP 27 MHz (324/27 = 12; 12*16 = 192 CPU clocks)
*/
#define RESET_TIME 2 /* cycle calc see in SCC_Reset */
struct scc_descriptor {
char *pu_name; /* PU identifier */
char *scc_instance; /* SCC Name */
u32 profile; /* SCC VCI_D profile */
u32 base_address; /* base address of the SCC unit reg shell*/
/* SCS Interconnect configuration */
u32 p_scc_id; /* instance number of SCC unit */
u32 p_mci_id; /* memory channel ID */
/* DMA Registers configuration */
u32 p_dma_channels_rd; /* Number of Read DMA channels */
u32 p_dma_channels_wr; /* Number of Write DMA channels */
u32 p_dma_packet_desc; /* Number of packet descriptors */
u32 p_dma_mci_desc; /* Number of MCI_CFG Descriptors */
int use_fh; /* the flag tells if SCC uses an FH */
int p_si2ocp_id; /* instance number of SI2OCP unit */
int hw_dma_cfg; /* HW or SW DMA config flag */
int hw_dma_start; /* HW or SW DMA start/stop flag */
u32 *buffer_tag_list; /* list of the buffer tags available */
u32 *csize_list; /* list of the valid CSIZE values */
};
struct scc_dma_state {
u32 scc_id:8; /* SCC id */
u32 dma_id:8; /* DMA id, used for match with array idx*/
u32 buffer_tag:8; /* mem buf tag, assigned to this DMA */
u32 dma_status:2; /* state of DMA, of the DMA_STATE_ const*/
u32 dma_drs:2; /* DMA dir, either DMA_READ or DMA_WRITE*/
u32 dma_cmd:4; /* last executed command on this DMA */
};
union scc_cmd {
u32 reg;
struct {
u32 res1:19; /* reserved */
u32 drs:1; /* DMA Register Set */
u32 rid:2; /* Register Identifier */
u32 id:6; /* DMA Identifier */
u32 action:4; /* DMA Command encoding */
} bits;
};
union scc_dma_cfg {
u32 reg;
struct {
u32 res1:17; /* reserved */
u32 agu_mode:1; /* AGU Mode */
u32 res2:1; /* reserved */
u32 fh_mode:1; /* Fifo Handler */
u32 buffer_type:1; /* Defines type of mem buffers */
u32 mci_cfg_id:1; /* MCI_CFG register selector */
u32 packet_cfg_id:1; /* PACKET_CFG register selector */
u32 buffer_id:8; /* DMA Buffer Identifier */
} bits;
};
union scc_debug {
u32 reg;
struct {
u32 res1:20; /* reserved */
u32 arg:8; /* SCC Debug Command Argument (#) */
u32 cmd:4; /* SCC Debug Command Register */
} bits;
};
union scc_softwareconfiguration {
u32 reg;
struct {
u32 res1:28; /* reserved */
u32 clock_status:1; /* clock on/off */
u32 packet_select:1; /* active SCC packet id */
u32 enable_status:1; /* enabled [1/0] */
u32 active_status:1; /* 1=active 0=reset */
} bits;
};
/*
* System on Chip Channel ID
*/
enum scc_id {
SCC_NULL = -1, /* illegal SCC identifier */
SCC_FE_3DCOMB_WR, /* SCC_FE_3DCOMB Write channel */
SCC_FE_3DCOMB_RD, /* SCC_FE_3DCOMB Read channel */
SCC_DI_TNR_WR, /* SCC_DI_TNR Write channel */
SCC_DI_TNR_FIELD_RD, /* SCC_DI_TNR_FIELD Read channel */
SCC_DI_TNR_FRAME_RD, /* SCC_DI_TNR_FRAME Read channel */
SCC_DI_MVAL_WR, /* SCC_DI_MVAL Write channel */
SCC_DI_MVAL_RD, /* SCC_DI_MVAL Read channel */
SCC_RC_FRAME_WR, /* SCC_RC_FRAME Write channel */
SCC_RC_FRAME0_RD, /* SCC_RC_FRAME0 Read channel */
SCC_OPT_FIELD0_RD, /* SCC_OPT_FIELD0 Read channel */
SCC_OPT_FIELD1_RD, /* SCC_OPT_FIELD1 Read channel */
SCC_OPT_FIELD2_RD, /* SCC_OPT_FIELD2 Read channel */
SCC_PIP_FRAME_WR, /* SCC_PIP_FRAME Write channel */
SCC_PIP_FRAME_RD, /* SCC_PIP_FRAME Read channel */
SCC_DP_AGPU_RD, /* SCC_DP_AGPU Read channel */
SCC_EWARP_RW, /* SCC_EWARP Read/Write channel */
SCC_DP_OSD_RD, /* SCC_DP_OSD Read channel */
SCC_DP_GRAPHIC_RD, /* SCC_DP_GRAPHIC Read channel */
SCC_DVP_OSD_RD, /* SCC_DVP_OSD Read channel */
SCC_DVP_VBI_RD, /* SCC_DVP_VBI Read channel */
SCC_TSIO_WR, /* SCC_TSIO Write channel */
SCC_TSIO_RD, /* SCC_TSIO Read channel */
SCC_TSD_WR, /* SCC_TSD Write channel */
SCC_VD_UD_ST_RW, /* SCC_VD_UD_ST Read/Write channel */
SCC_VD_FRR_RD, /* SCC_VD_FRR Read channel */
SCC_VD_FRW_DISP_WR, /* SCC_VD_FRW_DISP Write channel */
SCC_MR_VD_M_Y_RD, /* SCC_MR_VD_M_Y Read channel */
SCC_MR_VD_M_C_RD, /* SCC_MR_VD_M_C Read channel */
SCC_MR_VD_S_Y_RD, /* SCC_MR_VD_S_Y Read channel */
SCC_MR_VD_S_C_RD, /* SCC_MR_VD_S_C Read channel */
SCC_GA_WR, /* SCC_GA Write channel */
SCC_GA_SRC1_RD, /* SCC_GA_SRC1 Read channel */
SCC_GA_SRC2_RD, /* SCC_GA_SRC2 Read channel */
SCC_AD_RD, /* SCC_AD Read channel */
SCC_AD_WR, /* SCC_AD Write channel */
SCC_ABP_RD, /* SCC_ABP Read channel */
SCC_ABP_WR, /* SCC_ABP Write channel */
SCC_EBI_RW, /* SCC_EBI Read/Write channel */
SCC_USB_RW, /* SCC_USB Read/Write channel */
SCC_CPU1_SPDMA_RW, /* SCC_CPU1_SPDMA Read/Write channel */
SCC_CPU1_BRIDGE_RW, /* SCC_CPU1_BRIDGE Read/Write channel */
SCC_MAX /* maximum limit on the SCC id */
};
int scc_set_usb_address_generation_mode(u32 agu_mode);
int scc_dma_cmd(enum scc_id id, u32 cmd, u32 dma_id, u32 drs);
int scc_setup_dma(enum scc_id id, u32 buffer_tag,
u32 type, u32 fh_mode, u32 drs, u32 dma_id);
int scc_enable(enum scc_id id, u32 value);
int scc_reset(enum scc_id id, u32 value);
#endif /* _SCC_H */
/*
* (C) Copyright 2008 Stefan Roese <sr@denx.de>, DENX Software Engineering
*
* Copyright 2005, Seagate Technology LLC
*
* 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 version 2 as
* published by the Free Software Foundation.
*
* 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
*
*/
#undef DEBUG
#include <common.h>
#include <command.h>
#include <config.h>
#include <net.h>
#include "vct.h"
#define SMSC9118_BASE CONFIG_DRIVER_SMC911X_BASE
#define BYTE_TEST (SMSC9118_BASE + 0x64)
#define GPIO_CFG (SMSC9118_BASE + 0x88)
#define MAC_CSR_CMD (SMSC9118_BASE + 0xA4)
#define MAC_CSR_CMD_CSR_BUSY (0x80000000)
#define MAC_CSR_CMD_RNW (0x40000000)
#define MAC_RD_CMD(reg) ((reg & 0x000000FF) | \
(MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_RNW))
#define MAC_WR_CMD(reg) ((reg & 0x000000FF) | \
(MAC_CSR_CMD_CSR_BUSY))
#define MAC_CSR_DATA (SMSC9118_BASE + 0xA8)
#define E2P_CMD (SMSC9118_BASE + 0xB0)
#define E2P_CMD_EPC_BUSY_ (0x80000000UL) /* Self Clearing */
#define E2P_CMD_EPC_CMD_ (0x70000000UL) /* R/W */
#define E2P_CMD_EPC_CMD_READ_ (0x00000000UL) /* R/W */
#define E2P_CMD_EPC_CMD_EWDS_ (0x10000000UL) /* R/W */
#define E2P_CMD_EPC_CMD_EWEN_ (0x20000000UL) /* R/W */
#define E2P_CMD_EPC_CMD_WRITE_ (0x30000000UL) /* R/W */
#define E2P_CMD_EPC_CMD_WRAL_ (0x40000000UL) /* R/W */
#define E2P_CMD_EPC_CMD_ERASE_ (0x50000000UL) /* R/W */
#define E2P_CMD_EPC_CMD_ERAL_ (0x60000000UL) /* R/W */
#define E2P_CMD_EPC_CMD_RELOAD_ (0x70000000UL) /* R/W */
#define E2P_CMD_EPC_TIMEOUT_ (0x00000200UL) /* R */
#define E2P_CMD_MAC_ADDR_LOADED_ (0x00000100UL) /* RO */
#define E2P_CMD_EPC_ADDR_ (0x000000FFUL) /* R/W */
#define E2P_DATA (SMSC9118_BASE + 0xB4)
#define MAC_ADDRH (0x2)
#define MAC_ADDRL (0x3)
#define MAC_TIMEOUT 200
#define HIBYTE(word) ((u8)(((u16)(word)) >> 8))
#define LOBYTE(word) ((u8)(((u16)(word)) & 0x00FFU))
#define HIWORD(dword) ((u16)(((u32)(dword)) >> 16))
#define LOWORD(dword) ((u16)(((u32)(dword)) & 0x0000FFFFUL))
static int mac_busy(int req_to)
{
int timeout = req_to;
while (timeout--) {
if (!(smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY))
goto done;
}
return 1; /* Timeout */
done:
return 0; /* No timeout */
}
static ulong get_mac_reg(int reg)
{
ulong reg_val = 0xffffffff;
if (smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) {
printf("get_mac_reg: previous command not complete\n");
goto done;
}
smc911x_reg_write(MAC_CSR_CMD, MAC_RD_CMD(reg));
udelay(10000);
if (mac_busy(MAC_TIMEOUT) == 1) {
printf("get_mac_reg: timeout waiting for response from MAC\n");
goto done;
}
reg_val = smc911x_reg_read(MAC_CSR_DATA);
done:
return (reg_val);
}
static ulong eeprom_enable_access(void)
{
ulong gpio;
gpio = smc911x_reg_read(GPIO_CFG);
debug("%s: gpio= 0x%08lx ---> 0x%08lx\n", __func__, gpio,
(gpio & 0xFF0FFFFFUL));
smc911x_reg_write(GPIO_CFG, (gpio & 0xFF0FFFFFUL));
return gpio;
}
static void eeprom_disable_access(ulong gpio)
{
debug("%s: gpio= 0x%08lx\n", __func__, gpio);
smc911x_reg_write(GPIO_CFG, gpio);
}
static int eeprom_is_mac_address_loaded(void)
{
int ret;
ret = smc911x_reg_read(MAC_CSR_CMD) & E2P_CMD_MAC_ADDR_LOADED_;
debug("%s: ret = %x\n", __func__, ret);
return ret;
}
static int eeprom_read_location(unchar address, u8 *data)
{
ulong timeout = 100000;
ulong temp = 0;
if ((temp = smc911x_reg_read(E2P_CMD)) & E2P_CMD_EPC_BUSY_) {
printf("%s: Busy at start, E2P_CMD=0x%08lX\n", __func__, temp);
return 0;
}
smc911x_reg_write(E2P_CMD,
(E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_READ_ |
((ulong) address)));
while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) {
udelay(10);
timeout--;
}
if (timeout == 0) {
printf("Timeout\n");
return 0;
}
(*data) = (unchar) (smc911x_reg_read(E2P_DATA));
debug("%s: ret = %x\n", __func__, (*data));
return 1;
}
static int eeprom_enable_erase_and_write(void)
{
ulong timeout = 100000;
if (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_) {
printf("%s: Busy at start\n", __func__);
return 0;
}
smc911x_reg_write(E2P_CMD, (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_EWEN_));
while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) {
udelay(10);
timeout--;
}
if (timeout == 0) {
printf("Timeout[1]\n");
return 0;
}
return 1;
}
static int eeprom_disable_erase_and_write(void)
{
ulong timeout = 100000;
if (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_) {
printf("%s: Busy at start\n", __func__);
return 0;
}
smc911x_reg_write(E2P_CMD, (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_EWDS_));
while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) {
udelay(10);
timeout--;
}
if (timeout == 0) {
printf("Timeout[2]\n");
return 0;
}
return 1;
}
static int eeprom_write_location(unchar address, unchar data)
{
ulong timeout = 100000;
debug("%s: address: %x data = %x\n", __func__, address, data);
if (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_) {
printf("%s: Busy at start\n", __func__);
return 0;
}
smc911x_reg_write(E2P_DATA, ((ulong) data));
smc911x_reg_write(E2P_CMD,
(E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_WRITE_ |
((ulong) address)));
while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) {
udelay(10);
timeout--;
}
if (timeout == 0) {
printf("Timeout[3]\n");
return 0;
}
return 1;
}
static int eeprom_erase_all(void)
{
ulong timeout = 100000;
if (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_) {
printf("%s: Busy at start\n", __func__);
return 0;
}
smc911x_reg_write(E2P_CMD, (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_ERAL_));
while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) {
udelay(10);
timeout--;
}
if (timeout == 0) {
printf("Timeout[4]\n");
return 0;
}
return 1;
}
static int eeprom_reload(void)
{
ulong timeout = 100000;
if (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_) {
printf("%s: Busy at start\n", __func__);
return -1;
}
smc911x_reg_write(E2P_CMD,
(E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_RELOAD_));
while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) {
udelay(10);
timeout--;
}
if (timeout == 0)
return 0;
return 1;
}
static int eeprom_save_mac_address(ulong dwHi16, ulong dwLo32)
{
int result = 0;
debug("%s: dwHI: 0x%08lx dwLO: %08lx, \n", __func__, dwHi16, dwLo32);
if (!eeprom_enable_erase_and_write())
goto DONE;
if (!eeprom_erase_all())
goto DONE;
if (!eeprom_write_location(0, 0xA5))
goto DONE;
if (!eeprom_write_location(1, LOBYTE(LOWORD(dwLo32))))
goto DONE;
if (!eeprom_write_location(2, HIBYTE(LOWORD(dwLo32))))
goto DONE;
if (!eeprom_write_location(3, LOBYTE(HIWORD(dwLo32))))
goto DONE;
if (!eeprom_write_location(4, HIBYTE(HIWORD(dwLo32))))
goto DONE;
if (!eeprom_write_location(5, LOBYTE(LOWORD(dwHi16))))
goto DONE;
if (!eeprom_write_location(6, HIBYTE(LOWORD(dwHi16))))
goto DONE;
if (!eeprom_disable_erase_and_write())
goto DONE;
result = 1;
DONE:
return result;
}
static int do_eeprom_dump(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
unchar data = 0, index = 0;
ulong gpio_old_val;
gpio_old_val = eeprom_enable_access();
printf("EEPROM content: \n");
for (index = 0; index < 8; index++) {
if (eeprom_read_location(index, &data))
printf("%02x ", data);
else
printf("FAILED");
}
eeprom_disable_access(gpio_old_val);
printf("\n");
return 0;
}
</