parent
1bc0f14143
commit
771e05be07
@ -0,0 +1,53 @@ |
||||
/*
|
||||
* (C) Copyright 2003 |
||||
* Ingo Assmus <ingo.assmus@keymile.com> |
||||
* for cpci750 Reinhard Arlt |
||||
* |
||||
* 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 |
||||
*/ |
||||
|
||||
/*
|
||||
* main board support/init for the cpci750. |
||||
*/ |
||||
|
||||
#ifndef __64360_H__ |
||||
#define __64360_H__ |
||||
|
||||
/* CPU Configuration bits */ |
||||
#define CPU_CONF_ADDR_MISS_EN (1 << 8) |
||||
#define CPU_CONF_SINGLE_CPU (1 << 11) |
||||
#define CPU_CONF_ENDIANESS (1 << 12) |
||||
#define CPU_CONF_PIPELINE (1 << 13) |
||||
#define CPU_CONF_STOP_RETRY (1 << 17) |
||||
#define CPU_CONF_MULTI_DECODE (1 << 18) |
||||
#define CPU_CONF_DP_VALID (1 << 19) |
||||
#define CPU_CONF_PERR_PROP (1 << 22) |
||||
#define CPU_CONF_AACK_DELAY_2 (1 << 25) |
||||
#define CPU_CONF_AP_VALID (1 << 26) |
||||
#define CPU_CONF_REMAP_WR_DIS (1 << 27) |
||||
|
||||
/* CPU Master Control bits */ |
||||
#define CPU_MAST_CTL_ARB_EN (1 << 8) |
||||
#define CPU_MAST_CTL_MASK_BR_1 (1 << 9) |
||||
#define CPU_MAST_CTL_M_WR_TRIG (1 << 10) |
||||
#define CPU_MAST_CTL_M_RD_TRIG (1 << 11) |
||||
#define CPU_MAST_CTL_CLEAN_BLK (1 << 12) |
||||
#define CPU_MAST_CTL_FLUSH_BLK (1 << 13) |
||||
|
||||
#endif /* __64360_H__ */ |
@ -0,0 +1,44 @@ |
||||
#
|
||||
# (C) Copyright 2001
|
||||
# Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
|
||||
#
|
||||
# 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 $(TOPDIR)/config.mk |
||||
|
||||
LIB = lib$(BOARD).a
|
||||
|
||||
SOBJS = misc.o
|
||||
|
||||
OBJS = $(BOARD).o serial.o ../../Marvell/common/memory.o pci.o \
|
||||
mv_eth.o mpsc.o i2c.o \
|
||||
sdram_init.o strataflash.o ide.o
|
||||
|
||||
$(LIB): .depend $(OBJS) $(SOBJS) |
||||
$(AR) crv $@ $(OBJS) $(SOBJS)
|
||||
|
||||
#########################################################################
|
||||
|
||||
.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) |
||||
$(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
|
||||
|
||||
sinclude .depend |
||||
|
||||
#########################################################################
|
@ -0,0 +1,28 @@ |
||||
#
|
||||
# (C) Copyright 2004
|
||||
# Reinhard Arlt <reinhard.arlt@esd-electronics.com>
|
||||
#
|
||||
# See file CREDITS for list of people who contributed to this
|
||||
# project.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
#
|
||||
# cpci750 board
|
||||
#
|
||||
|
||||
TEXT_BASE = 0xfff00000
|
@ -0,0 +1,885 @@ |
||||
/*
|
||||
* (C) Copyright 2001 |
||||
* Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. |
||||
* |
||||
* 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 |
||||
* |
||||
* modifications for the DB64360 eval board based by Ingo.Assmus@keymile.com |
||||
* modifications for the cpci750 by reinhard.arlt@esd-electronics.com |
||||
*/ |
||||
|
||||
/*
|
||||
* cpci750.c - main board support/init for the esd cpci750. |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <74xx_7xx.h> |
||||
#include "../../Marvell/include/memory.h" |
||||
#include "../../Marvell/include/pci.h" |
||||
#include "../../Marvell/include/mv_gen_reg.h" |
||||
#include <net.h> |
||||
|
||||
#include "eth.h" |
||||
#include "mpsc.h" |
||||
#include "i2c.h" |
||||
#include "64360.h" |
||||
#include "mv_regs.h" |
||||
|
||||
#undef DEBUG |
||||
/*#define DEBUG */ |
||||
|
||||
#ifdef CONFIG_PCI |
||||
#define MAP_PCI |
||||
#endif /* of CONFIG_PCI */ |
||||
|
||||
#ifdef DEBUG |
||||
#define DP(x) x |
||||
#else |
||||
#define DP(x) |
||||
#endif |
||||
|
||||
extern void flush_data_cache (void); |
||||
extern void invalidate_l1_instruction_cache (void); |
||||
|
||||
/* ------------------------------------------------------------------------- */ |
||||
|
||||
/* this is the current GT register space location */ |
||||
/* it starts at CFG_DFL_GT_REGS but moves later to CFG_GT_REGS */ |
||||
|
||||
/* Unfortunately, we cant change it while we are in flash, so we initialize it
|
||||
* to the "final" value. This means that any debug_led calls before |
||||
* board_early_init_f wont work right (like in cpu_init_f). |
||||
* See also my_remap_gt_regs below. (NTL) |
||||
*/ |
||||
|
||||
void board_prebootm_init (void); |
||||
unsigned int INTERNAL_REG_BASE_ADDR = CFG_GT_REGS; |
||||
int display_mem_map (void); |
||||
|
||||
/* ------------------------------------------------------------------------- */ |
||||
|
||||
/*
|
||||
* This is a version of the GT register space remapping function that |
||||
* doesn't touch globals (meaning, it's ok to run from flash.) |
||||
* |
||||
* Unfortunately, this has the side effect that a writable |
||||
* INTERNAL_REG_BASE_ADDR is impossible. Oh well. |
||||
*/ |
||||
|
||||
void my_remap_gt_regs (u32 cur_loc, u32 new_loc) |
||||
{ |
||||
u32 temp; |
||||
|
||||
/* check and see if it's already moved */ |
||||
|
||||
/* original ppcboot 1.1.6 source
|
||||
|
||||
temp = in_le32((u32 *)(new_loc + INTERNAL_SPACE_DECODE)); |
||||
if ((temp & 0xffff) == new_loc >> 20) |
||||
return; |
||||
|
||||
temp = (in_le32((u32 *)(cur_loc + INTERNAL_SPACE_DECODE)) & |
||||
0xffff0000) | (new_loc >> 20); |
||||
|
||||
out_le32((u32 *)(cur_loc + INTERNAL_SPACE_DECODE), temp); |
||||
|
||||
while (GTREGREAD(INTERNAL_SPACE_DECODE) != temp); |
||||
original ppcboot 1.1.6 source end */ |
||||
|
||||
temp = in_le32 ((u32 *) (new_loc + INTERNAL_SPACE_DECODE)); |
||||
if ((temp & 0xffff) == new_loc >> 16) |
||||
return; |
||||
|
||||
temp = (in_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE)) & |
||||
0xffff0000) | (new_loc >> 16); |
||||
|
||||
out_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE), temp); |
||||
|
||||
while (GTREGREAD (INTERNAL_SPACE_DECODE) != temp); |
||||
} |
||||
|
||||
#ifdef CONFIG_PCI |
||||
|
||||
static void gt_pci_config (void) |
||||
{ |
||||
unsigned int stat; |
||||
unsigned int val = 0x00fff864; /* DINK32: BusNum 23:16, DevNum 15:11, FuncNum 10:8, RegNum 7:2 */ |
||||
|
||||
/* In PCIX mode devices provide their own bus and device numbers. We query the Discovery II's
|
||||
* config registers by writing ones to the bus and device. |
||||
* We then update the Virtual register with the correct value for the bus and device. |
||||
*/ |
||||
if ((GTREGREAD (PCI_0_MODE) & (BIT4 | BIT5)) != 0) { /*if PCI-X */ |
||||
GT_REG_WRITE (PCI_0_CONFIG_ADDR, BIT31 | val); |
||||
|
||||
GT_REG_READ (PCI_0_CONFIG_DATA_VIRTUAL_REG, &stat); |
||||
|
||||
GT_REG_WRITE (PCI_0_CONFIG_ADDR, BIT31 | val); |
||||
GT_REG_WRITE (PCI_0_CONFIG_DATA_VIRTUAL_REG, |
||||
(stat & 0xffff0000) | CFG_PCI_IDSEL); |
||||
|
||||
} |
||||
if ((GTREGREAD (PCI_1_MODE) & (BIT4 | BIT5)) != 0) { /*if PCI-X */ |
||||
GT_REG_WRITE (PCI_1_CONFIG_ADDR, BIT31 | val); |
||||
GT_REG_READ (PCI_1_CONFIG_DATA_VIRTUAL_REG, &stat); |
||||
|
||||
GT_REG_WRITE (PCI_1_CONFIG_ADDR, BIT31 | val); |
||||
GT_REG_WRITE (PCI_1_CONFIG_DATA_VIRTUAL_REG, |
||||
(stat & 0xffff0000) | CFG_PCI_IDSEL); |
||||
} |
||||
|
||||
/* Enable master */ |
||||
PCI_MASTER_ENABLE (0, SELF); |
||||
PCI_MASTER_ENABLE (1, SELF); |
||||
|
||||
/* Enable PCI0/1 Mem0 and IO 0 disable all others */ |
||||
GT_REG_READ (BASE_ADDR_ENABLE, &stat); |
||||
stat |= (1 << 11) | (1 << 12) | (1 << 13) | (1 << 16) | (1 << 17) | (1 |
||||
<< |
||||
18); |
||||
stat &= ~((1 << 9) | (1 << 10) | (1 << 14) | (1 << 15)); |
||||
GT_REG_WRITE (BASE_ADDR_ENABLE, stat); |
||||
|
||||
/* ronen- add write to pci remap registers for 64460.
|
||||
in 64360 when writing to pci base go and overide remap automaticaly, |
||||
in 64460 it doesn't */ |
||||
GT_REG_WRITE (PCI_0_IO_BASE_ADDR, CFG_PCI0_IO_SPACE >> 16); |
||||
GT_REG_WRITE (PCI_0I_O_ADDRESS_REMAP, CFG_PCI0_IO_SPACE_PCI >> 16); |
||||
GT_REG_WRITE (PCI_0_IO_SIZE, (CFG_PCI0_IO_SIZE - 1) >> 16); |
||||
|
||||
GT_REG_WRITE (PCI_0_MEMORY0_BASE_ADDR, CFG_PCI0_MEM_BASE >> 16); |
||||
GT_REG_WRITE (PCI_0MEMORY0_ADDRESS_REMAP, CFG_PCI0_MEM_BASE >> 16); |
||||
GT_REG_WRITE (PCI_0_MEMORY0_SIZE, (CFG_PCI0_MEM_SIZE - 1) >> 16); |
||||
|
||||
GT_REG_WRITE (PCI_1_IO_BASE_ADDR, CFG_PCI1_IO_SPACE >> 16); |
||||
GT_REG_WRITE (PCI_1I_O_ADDRESS_REMAP, CFG_PCI1_IO_SPACE_PCI >> 16); |
||||
GT_REG_WRITE (PCI_1_IO_SIZE, (CFG_PCI1_IO_SIZE - 1) >> 16); |
||||
|
||||
GT_REG_WRITE (PCI_1_MEMORY0_BASE_ADDR, CFG_PCI1_MEM_BASE >> 16); |
||||
GT_REG_WRITE (PCI_1MEMORY0_ADDRESS_REMAP, CFG_PCI1_MEM_BASE >> 16); |
||||
GT_REG_WRITE (PCI_1_MEMORY0_SIZE, (CFG_PCI1_MEM_SIZE - 1) >> 16); |
||||
|
||||
/* PCI interface settings */ |
||||
/* Timeout set to retry forever */ |
||||
GT_REG_WRITE (PCI_0TIMEOUT_RETRY, 0x0); |
||||
GT_REG_WRITE (PCI_1TIMEOUT_RETRY, 0x0); |
||||
|
||||
/* ronen - enable only CS0 and Internal reg!! */ |
||||
GT_REG_WRITE (PCI_0BASE_ADDRESS_REGISTERS_ENABLE, 0xfffffdfe); |
||||
GT_REG_WRITE (PCI_1BASE_ADDRESS_REGISTERS_ENABLE, 0xfffffdfe); |
||||
|
||||
/*ronen update the pci internal registers base address.*/ |
||||
#ifdef MAP_PCI |
||||
for (stat = 0; stat <= PCI_HOST1; stat++) |
||||
pciWriteConfigReg (stat, |
||||
PCI_INTERNAL_REGISTERS_MEMORY_MAPPED_BASE_ADDRESS, |
||||
SELF, CFG_GT_REGS); |
||||
#endif |
||||
|
||||
} |
||||
#endif |
||||
|
||||
/* Setup CPU interface paramaters */ |
||||
static void gt_cpu_config (void) |
||||
{ |
||||
cpu_t cpu = get_cpu_type (); |
||||
ulong tmp; |
||||
|
||||
/* cpu configuration register */ |
||||
tmp = GTREGREAD (CPU_CONFIGURATION); |
||||
|
||||
/* set the SINGLE_CPU bit see MV64360 P.399 */ |
||||
#ifndef CFG_GT_DUAL_CPU /* SINGLE_CPU seems to cause JTAG problems */ |
||||
tmp |= CPU_CONF_SINGLE_CPU; |
||||
#endif |
||||
|
||||
tmp &= ~CPU_CONF_AACK_DELAY_2; |
||||
|
||||
tmp |= CPU_CONF_DP_VALID; |
||||
tmp |= CPU_CONF_AP_VALID; |
||||
|
||||
tmp |= CPU_CONF_PIPELINE; |
||||
|
||||
GT_REG_WRITE (CPU_CONFIGURATION, tmp); /* Marvell (VXWorks) writes 0x20220FF */ |
||||
|
||||
/* CPU master control register */ |
||||
tmp = GTREGREAD (CPU_MASTER_CONTROL); |
||||
|
||||
tmp |= CPU_MAST_CTL_ARB_EN; |
||||
|
||||
if ((cpu == CPU_7400) || |
||||
(cpu == CPU_7410) || (cpu == CPU_7455) || (cpu == CPU_7450)) { |
||||
|
||||
tmp |= CPU_MAST_CTL_CLEAN_BLK; |
||||
tmp |= CPU_MAST_CTL_FLUSH_BLK; |
||||
|
||||
} else { |
||||
/* cleanblock must be cleared for CPUs
|
||||
* that do not support this command (603e, 750) |
||||
* see Res#1 */ |
||||
tmp &= ~CPU_MAST_CTL_CLEAN_BLK; |
||||
tmp &= ~CPU_MAST_CTL_FLUSH_BLK; |
||||
} |
||||
GT_REG_WRITE (CPU_MASTER_CONTROL, tmp); |
||||
} |
||||
|
||||
/*
|
||||
* board_early_init_f. |
||||
* |
||||
* set up gal. device mappings, etc. |
||||
*/ |
||||
int board_early_init_f (void) |
||||
{ |
||||
|
||||
/*
|
||||
* set up the GT the way the kernel wants it |
||||
* the call to move the GT register space will obviously |
||||
* fail if it has already been done, but we're going to assume |
||||
* that if it's not at the power-on location, it's where we put |
||||
* it last time. (huber) |
||||
*/ |
||||
|
||||
my_remap_gt_regs (CFG_DFL_GT_REGS, CFG_GT_REGS); |
||||
|
||||
/* No PCI in first release of Port To_do: enable it. */ |
||||
#ifdef CONFIG_PCI |
||||
gt_pci_config (); |
||||
#endif |
||||
/* mask all external interrupt sources */ |
||||
GT_REG_WRITE (CPU_INTERRUPT_MASK_REGISTER_LOW, 0); |
||||
GT_REG_WRITE (CPU_INTERRUPT_MASK_REGISTER_HIGH, 0); |
||||
/* new in MV6436x */ |
||||
GT_REG_WRITE (CPU_INTERRUPT_1_MASK_REGISTER_LOW, 0); |
||||
GT_REG_WRITE (CPU_INTERRUPT_1_MASK_REGISTER_HIGH, 0); |
||||
/* --------------------- */ |
||||
GT_REG_WRITE (PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0); |
||||
GT_REG_WRITE (PCI_0INTERRUPT_CAUSE_MASK_REGISTER_HIGH, 0); |
||||
GT_REG_WRITE (PCI_1INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0); |
||||
GT_REG_WRITE (PCI_1INTERRUPT_CAUSE_MASK_REGISTER_HIGH, 0); |
||||
/* does not exist in MV6436x
|
||||
GT_REG_WRITE(CPU_INT_0_MASK, 0); |
||||
GT_REG_WRITE(CPU_INT_1_MASK, 0); |
||||
GT_REG_WRITE(CPU_INT_2_MASK, 0); |
||||
GT_REG_WRITE(CPU_INT_3_MASK, 0); |
||||
--------------------- */ |
||||
|
||||
|
||||
/* ----- DEVICE BUS SETTINGS ------ */ |
||||
|
||||
/*
|
||||
* EVB |
||||
* 0 - SRAM ???? |
||||
* 1 - RTC ???? |
||||
* 2 - UART ???? |
||||
* 3 - Flash checked 32Bit Intel Strata |
||||
* boot - BootCS checked 8Bit 29LV040B |
||||
* |
||||
*/ |
||||
|
||||
/*
|
||||
* the dual 7450 module requires burst access to the boot |
||||
* device, so the serial rom copies the boot device to the |
||||
* on-board sram on the eval board, and updates the correct |
||||
* registers to boot from the sram. (device0) |
||||
*/ |
||||
|
||||
memoryMapDeviceSpace (DEVICE0, CFG_DEV0_SPACE, CFG_DEV0_SIZE); |
||||
memoryMapDeviceSpace (DEVICE1, CFG_DEV1_SPACE, CFG_DEV1_SIZE); |
||||
memoryMapDeviceSpace (DEVICE2, CFG_DEV2_SPACE, CFG_DEV2_SIZE); |
||||
memoryMapDeviceSpace (DEVICE3, CFG_DEV3_SPACE, CFG_DEV3_SIZE); |
||||
|
||||
|
||||
/* configure device timing */ |
||||
GT_REG_WRITE (DEVICE_BANK0PARAMETERS, CFG_DEV0_PAR); |
||||
GT_REG_WRITE (DEVICE_BANK1PARAMETERS, CFG_DEV1_PAR); |
||||
GT_REG_WRITE (DEVICE_BANK2PARAMETERS, CFG_DEV2_PAR); |
||||
GT_REG_WRITE (DEVICE_BANK3PARAMETERS, CFG_DEV3_PAR); |
||||
|
||||
#ifdef CFG_32BIT_BOOT_PAR /* set port parameters for Flash device module access */ |
||||
/* detect if we are booting from the 32 bit flash */ |
||||
if (GTREGREAD (DEVICE_BOOT_BANK_PARAMETERS) & (0x3 << 20)) { |
||||
/* 32 bit boot flash */ |
||||
GT_REG_WRITE (DEVICE_BANK3PARAMETERS, CFG_8BIT_BOOT_PAR); |
||||
GT_REG_WRITE (DEVICE_BOOT_BANK_PARAMETERS, |
||||
CFG_32BIT_BOOT_PAR); |
||||
} else { |
||||
/* 8 bit boot flash */ |
||||
GT_REG_WRITE (DEVICE_BANK3PARAMETERS, CFG_32BIT_BOOT_PAR); |
||||
GT_REG_WRITE (DEVICE_BOOT_BANK_PARAMETERS, CFG_8BIT_BOOT_PAR); |
||||
} |
||||
#else |
||||
/* 8 bit boot flash only */ |
||||
/* GT_REG_WRITE(DEVICE_BOOT_BANK_PARAMETERS, CFG_8BIT_BOOT_PAR);*/ |
||||
#endif |
||||
|
||||
|
||||
gt_cpu_config (); |
||||
|
||||
/* MPP setup */ |
||||
GT_REG_WRITE (MPP_CONTROL0, CFG_MPP_CONTROL_0); |
||||
GT_REG_WRITE (MPP_CONTROL1, CFG_MPP_CONTROL_1); |
||||
GT_REG_WRITE (MPP_CONTROL2, CFG_MPP_CONTROL_2); |
||||
GT_REG_WRITE (MPP_CONTROL3, CFG_MPP_CONTROL_3); |
||||
|
||||
GT_REG_WRITE (GPP_LEVEL_CONTROL, CFG_GPP_LEVEL_CONTROL); |
||||
DEBUG_LED0_ON (); |
||||
DEBUG_LED1_ON (); |
||||
DEBUG_LED2_ON (); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/* various things to do after relocation */ |
||||
|
||||
int misc_init_r () |
||||
{ |
||||
icache_enable (); |
||||
#ifdef CFG_L2 |
||||
l2cache_enable (); |
||||
#endif |
||||
#ifdef CONFIG_MPSC |
||||
|
||||
mpsc_sdma_init (); |
||||
mpsc_init2 (); |
||||
#endif |
||||
|
||||
#if 0 |
||||
/* disable the dcache and MMU */ |
||||
dcache_lock (); |
||||
#endif |
||||
return 0; |
||||
} |
||||
|
||||
void after_reloc (ulong dest_addr, gd_t * gd) |
||||
{ |
||||
|
||||
memoryMapDeviceSpace (BOOT_DEVICE, CFG_BOOT_SPACE, CFG_BOOT_SIZE); |
||||
|
||||
display_mem_map (); |
||||
/* now, jump to the main ppcboot board init code */ |
||||
board_init_r (gd, dest_addr); |
||||
/* NOTREACHED */ |
||||
} |
||||
|
||||
/* ------------------------------------------------------------------------- */ |
||||
|
||||
/*
|
||||
* Check Board Identity: |
||||
* |
||||
* right now, assume borad type. (there is just one...after all) |
||||
*/ |
||||
|
||||
int checkboard (void) |
||||
{ |
||||
int l_type = 0; |
||||
|
||||
printf ("BOARD: %s\n", CFG_BOARD_NAME); |
||||
return (l_type); |
||||
} |
||||
|
||||
/* utility functions */ |
||||
void debug_led (int led, int mode) |
||||
{ |
||||
} |
||||
|
||||
int display_mem_map (void) |
||||
{ |
||||
int i, j; |
||||
unsigned int base, size, width; |
||||
|
||||
/* SDRAM */ |
||||
printf ("SD (DDR) RAM\n"); |
||||
for (i = 0; i <= BANK3; i++) { |
||||
base = memoryGetBankBaseAddress (i); |
||||
size = memoryGetBankSize (i); |
||||
if (size != 0) { |
||||
printf ("BANK%d: base - 0x%08x\tsize - %dM bytes\n", |
||||
i, base, size >> 20); |
||||
} |
||||
} |
||||
#ifdef CONFIG_PCI |
||||
/* CPU's PCI windows */ |
||||
for (i = 0; i <= PCI_HOST1; i++) { |
||||
printf ("\nCPU's PCI %d windows\n", i); |
||||
base = pciGetSpaceBase (i, PCI_IO); |
||||
size = pciGetSpaceSize (i, PCI_IO); |
||||
printf (" IO: base - 0x%08x\tsize - %dM bytes\n", base, |
||||
size >> 20); |
||||
for (j = 0; |
||||
j <= |
||||
PCI_REGION0 |
||||
/*ronen currently only first PCI MEM is used 3 */ ; |
||||
j++) { |
||||
base = pciGetSpaceBase (i, j); |
||||
size = pciGetSpaceSize (i, j); |
||||
printf ("MEMORY %d: base - 0x%08x\tsize - %dM bytes\n", j, base, size >> 20); |
||||
} |
||||
} |
||||
#endif /* of CONFIG_PCI */ |
||||
/* Devices */ |
||||
printf ("\nDEVICES\n"); |
||||
for (i = 0; i <= DEVICE3; i++) { |
||||
base = memoryGetDeviceBaseAddress (i); |
||||
size = memoryGetDeviceSize (i); |
||||
width = memoryGetDeviceWidth (i) * 8; |
||||
printf ("DEV %d: base - 0x%08x size - %dM bytes\twidth - %d bits", i, base, size >> 20, width); |
||||
if (i == 0) |
||||
printf ("\t- FLASH\n"); |
||||
else if (i == 1) |
||||
printf ("\t- FLASH\n"); |
||||
else if (i == 2) |
||||
printf ("\t- FLASH\n"); |
||||
else |
||||
printf ("\t- RTC/REGS/CAN\n"); |
||||
} |
||||
|
||||
/* Bootrom */ |
||||
base = memoryGetDeviceBaseAddress (BOOT_DEVICE); /* Boot */ |
||||
size = memoryGetDeviceSize (BOOT_DEVICE); |
||||
width = memoryGetDeviceWidth (BOOT_DEVICE) * 8; |
||||
printf (" BOOT: base - 0x%08x size - %dM bytes\twidth - %d bits\t- FLASH\n", |
||||
base, size >> 20, width); |
||||
return (0); |
||||
} |
||||
|
||||
/* DRAM check routines copied from gw8260 */ |
||||
|
||||
#if defined (CFG_DRAM_TEST) |
||||
|
||||
/*********************************************************************/ |
||||
/* NAME: move64() - moves a double word (64-bit) */ |
||||
/* */ |
||||
/* DESCRIPTION: */ |
||||
/* this function performs a double word move from the data at */ |
||||
/* the source pointer to the location at the destination pointer. */ |
||||
/* */ |
||||
/* INPUTS: */ |
||||
/* unsigned long long *src - pointer to data to move */ |
||||
/* */ |
||||
/* OUTPUTS: */ |
||||
/* unsigned long long *dest - pointer to locate to move data */ |
||||
/* */ |
||||
/* RETURNS: */ |
||||
/* None */ |
||||
/* */ |
||||
/* RESTRICTIONS/LIMITATIONS: */ |
||||
/* May cloober fr0. */ |
||||
/* */ |
||||
/*********************************************************************/ |
||||
static void move64 (unsigned long long *src, unsigned long long *dest) |
||||
{ |
||||
asm ("lfd 0, 0(3)\n\t" /* fpr0 = *scr */ |
||||
"stfd 0, 0(4)" /* *dest = fpr0 */ |
||||
: : : "fr0"); /* Clobbers fr0 */ |
||||
return; |
||||
} |
||||
|
||||
|
||||
#if defined (CFG_DRAM_TEST_DATA) |
||||
|
||||
unsigned long long pattern[] = { |
||||
0xaaaaaaaaaaaaaaaa, |
||||
0xcccccccccccccccc, |
||||
0xf0f0f0f0f0f0f0f0, |
||||
0xff00ff00ff00ff00, |
||||
0xffff0000ffff0000, |
||||
0xffffffff00000000, |
||||
0x00000000ffffffff, |
||||
0x0000ffff0000ffff, |
||||
0x00ff00ff00ff00ff, |
||||
0x0f0f0f0f0f0f0f0f, |
||||
0x3333333333333333, |
||||
0x5555555555555555 |
||||
}; |
||||
|
||||
/*********************************************************************/ |
||||
/* NAME: mem_test_data() - test data lines for shorts and opens */ |
||||
/* */ |
||||
/* DESCRIPTION: */ |
||||
/* Tests data lines for shorts and opens by forcing adjacent data */ |
||||
/* to opposite states. Because the data lines could be routed in */ |
||||
/* an arbitrary manner the must ensure test patterns ensure that */ |
||||
/* every case is tested. By using the following series of binary */ |
||||
/* patterns every combination of adjacent bits is test regardless */ |
||||
/* of routing. */ |
||||
/* */ |
||||
/* ...101010101010101010101010 */ |
||||
/* ...110011001100110011001100 */ |
||||
/* ...111100001111000011110000 */ |
||||
/* ...111111110000000011111111 */ |
||||
/* */ |
||||
/* Carrying this out, gives us six hex patterns as follows: */ |
||||
/* */ |
||||
/* 0xaaaaaaaaaaaaaaaa */ |
||||
/* 0xcccccccccccccccc */ |
||||
/* 0xf0f0f0f0f0f0f0f0 */ |
||||
/* 0xff00ff00ff00ff00 */ |
||||
/* 0xffff0000ffff0000 */ |
||||
/* 0xffffffff00000000 */ |
||||
/* */ |
||||
/* The number test patterns will always be given by: */ |
||||
/* */ |
||||
/* log(base 2)(number data bits) = log2 (64) = 6 */ |
||||
/* */ |
||||
/* To test for short and opens to other signals on our boards. we */ |
||||
/* simply */ |
||||
/* test with the 1's complemnt of the paterns as well. */ |
||||
/* */ |
||||
/* OUTPUTS: */ |
||||
/* Displays failing test pattern */ |
||||
/* */ |
||||
/* RETURNS: */ |
||||
/* 0 - Passed test */ |
||||
/* 1 - Failed test */ |
||||
/* */ |
||||
/* RESTRICTIONS/LIMITATIONS: */ |
||||
/* Assumes only one one SDRAM bank */ |
||||
/* */ |
||||
/*********************************************************************/ |
||||
int mem_test_data (void) |
||||
{ |
||||
unsigned long long *pmem = (unsigned long long *) CFG_MEMTEST_START; |
||||
unsigned long long temp64; |
||||
int num_patterns = sizeof (pattern) / sizeof (pattern[0]); |
||||
int i; |
||||
unsigned int hi, lo; |
||||
|
||||
for (i = 0; i < num_patterns; i++) { |
||||
move64 (&(pattern[i]), pmem); |
||||
move64 (pmem, &temp64); |
||||
|
||||
/* hi = (temp64>>32) & 0xffffffff; */ |
||||
/* lo = temp64 & 0xffffffff; */ |
||||
/* printf("\ntemp64 = 0x%08x%08x", hi, lo); */ |
||||
|
||||
hi = (pattern[i] >> 32) & 0xffffffff; |
||||
lo = pattern[i] & 0xffffffff; |
||||
/* printf("\npattern[%d] = 0x%08x%08x", i, hi, lo); */ |
||||
|
||||
if (temp64 != pattern[i]) { |
||||
printf ("\n Data Test Failed, pattern 0x%08x%08x", |
||||
hi, lo); |
||||
return 1; |
||||
} |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
#endif /* CFG_DRAM_TEST_DATA */ |
||||
|
||||
#if defined (CFG_DRAM_TEST_ADDRESS) |
||||
/*********************************************************************/ |
||||
/* NAME: mem_test_address() - test address lines */ |
||||
/* */ |
||||
/* DESCRIPTION: */ |
||||
/* This function performs a test to verify that each word im */ |
||||
/* memory is uniquly addressable. The test sequence is as follows: */ |
||||
/* */ |
||||
/* 1) write the address of each word to each word. */ |
||||
/* 2) verify that each location equals its address */ |
||||
/* */ |
||||
/* OUTPUTS: */ |
||||
/* Displays failing test pattern and address */ |
||||
/* */ |
||||
/* RETURNS: */ |
||||
/* 0 - Passed test */ |
||||
/* 1 - Failed test */ |
||||
/* */ |
||||
/* RESTRICTIONS/LIMITATIONS: */ |
||||
/* */ |
||||
/* */ |
||||
/*********************************************************************/ |
||||
int mem_test_address (void) |
||||
{ |
||||
volatile unsigned int *pmem = |
||||
(volatile unsigned int *) CFG_MEMTEST_START; |
||||
const unsigned int size = (CFG_MEMTEST_END - CFG_MEMTEST_START) / 4; |
||||
unsigned int i; |
||||
|
||||
/* write address to each location */ |
||||
for (i = 0; i < size; i++) { |
||||
pmem[i] = i; |
||||
} |
||||
|
||||
/* verify each loaction */ |
||||
for (i = 0; i < size; i++) { |
||||
if (pmem[i] != i) { |
||||
printf ("\n Address Test Failed at 0x%x", i); |
||||
return 1; |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
#endif /* CFG_DRAM_TEST_ADDRESS */ |
||||
|
||||
#if defined (CFG_DRAM_TEST_WALK) |
||||
/*********************************************************************/ |
||||
/* NAME: mem_march() - memory march */ |
||||
/* */ |
||||
/* DESCRIPTION: */ |
||||
/* Marches up through memory. At each location verifies rmask if */ |
||||
/* read = 1. At each location write wmask if write = 1. Displays */ |
||||
/* failing address and pattern. */ |
||||
/* */ |
||||
/* INPUTS: */ |
||||
/* volatile unsigned long long * base - start address of test */ |
||||
/* unsigned int size - number of dwords(64-bit) to test */ |
||||
/* unsigned long long rmask - read verify mask */ |
||||
/* unsigned long long wmask - wrtie verify mask */ |
||||
/* short read - verifies rmask if read = 1 */ |
||||
/* short write - writes wmask if write = 1 */ |
||||
/* */ |
||||
/* OUTPUTS: */ |
||||
/* Displays failing test pattern and address */ |
||||
/* */ |
||||
/* RETURNS: */ |
||||
/* 0 - Passed test */ |
||||
/* 1 - Failed test */ |
||||
/* */ |
||||
/* RESTRICTIONS/LIMITATIONS: */ |
||||
/* */ |
||||
/* */ |
||||
/*********************************************************************/ |
||||
int mem_march (volatile unsigned long long *base, |
||||
unsigned int size, |
||||
unsigned long long rmask, |
||||
unsigned long long wmask, short read, short write) |
||||
{ |
||||
unsigned int i; |
||||
unsigned long long temp; |
||||
unsigned int hitemp, lotemp, himask, lomask; |
||||
|
||||
for (i = 0; i < size; i++) { |
||||
if (read != 0) { |
||||
/* temp = base[i]; */ |
||||
move64 ((unsigned long long *) &(base[i]), &temp); |
||||
if (rmask != temp) { |
||||
hitemp = (temp >> 32) & 0xffffffff; |
||||
lotemp = temp & 0xffffffff; |
||||
himask = (rmask >> 32) & 0xffffffff; |
||||
lomask = rmask & 0xffffffff; |
||||
|
||||
printf ("\n Walking one's test failed: address = 0x%08x," "\n\texpected 0x%08x%08x, found 0x%08x%08x", i << 3, himask, lomask, hitemp, lotemp); |
||||
return 1; |
||||
} |
||||
} |
||||
if (write != 0) { |
||||
/* base[i] = wmask; */ |
||||
move64 (&wmask, (unsigned long long *) &(base[i])); |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
#endif /* CFG_DRAM_TEST_WALK */ |
||||
|
||||
/*********************************************************************/ |
||||
/* NAME: mem_test_walk() - a simple walking ones test */ |
||||
/* */ |
||||
/* DESCRIPTION: */ |
||||
/* Performs a walking ones through entire physical memory. The */ |
||||
/* test uses as series of memory marches, mem_march(), to verify */ |
||||
/* and write the test patterns to memory. The test sequence is as */ |
||||
/* follows: */ |
||||
/* 1) march writing 0000...0001 */ |
||||
/* 2) march verifying 0000...0001 , writing 0000...0010 */ |
||||
/* 3) repeat step 2 shifting masks left 1 bit each time unitl */ |
||||
/* the write mask equals 1000...0000 */ |
||||
/* 4) march verifying 1000...0000 */ |
||||
/* The test fails if any of the memory marches return a failure. */ |
||||
/* */ |
||||
/* OUTPUTS: */ |
||||
/* Displays which pass on the memory test is executing */ |
||||
/* */ |
||||
/* RETURNS: */ |
||||
/* 0 - Passed test */ |
||||
/* 1 - Failed test */ |
||||
/* */ |
||||
/* RESTRICTIONS/LIMITATIONS: */ |
||||
/* */ |
||||
/* */ |
||||
/*********************************************************************/ |
||||
int mem_test_walk (void) |
||||
{ |
||||
unsigned long long mask; |
||||
volatile unsigned long long *pmem = |
||||
(volatile unsigned long long *) CFG_MEMTEST_START; |
||||
const unsigned long size = (CFG_MEMTEST_END - CFG_MEMTEST_START) / 8; |
||||
|
||||
unsigned int i; |
||||
|
||||
mask = 0x01; |
||||
|
||||
printf ("Initial Pass"); |
||||
mem_march (pmem, size, 0x0, 0x1, 0, 1); |
||||
|
||||
printf ("\b\b\b\b\b\b\b\b\b\b\b\b"); |
||||
printf (" "); |
||||
printf (" "); |
||||
printf ("\b\b\b\b\b\b\b\b\b\b\b\b"); |
||||
|
||||
for (i = 0; i < 63; i++) { |
||||
printf ("Pass %2d", i + 2); |
||||
if (mem_march (pmem, size, mask, mask << 1, 1, 1) != 0) { |
||||
/*printf("mask: 0x%x, pass: %d, ", mask, i); */ |
||||
return 1; |
||||
} |
||||
mask = mask << 1; |
||||
printf ("\b\b\b\b\b\b\b"); |
||||
} |
||||
|
||||
printf ("Last Pass"); |
||||
if (mem_march (pmem, size, 0, mask, 0, 1) != 0) { |
||||
/* printf("mask: 0x%x", mask); */ |
||||
return 1; |
||||
} |
||||
printf ("\b\b\b\b\b\b\b\b\b"); |
||||
printf (" "); |
||||
printf ("\b\b\b\b\b\b\b\b\b"); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/*********************************************************************/ |
||||
/* NAME: testdram() - calls any enabled memory tests */ |
||||
/* */ |
||||
/* DESCRIPTION: */ |
||||
/* Runs memory tests if the environment test variables are set to */ |
||||
/* 'y'. */ |
||||
/* */ |
||||
/* INPUTS: */ |
||||
/* testdramdata - If set to 'y', data test is run. */ |
||||
/* testdramaddress - If set to 'y', address test is run. */ |
||||
/* testdramwalk - If set to 'y', walking ones test is run */ |
||||
/* */ |
||||
/* OUTPUTS: */ |
||||
/* None */ |
||||
/* */ |
||||
/* RETURNS: */ |
||||
/* 0 - Passed test */ |
||||
/* 1 - Failed test */ |
||||
/* */ |
||||
/* RESTRICTIONS/LIMITATIONS: */ |
||||
/* */ |
||||
/* */ |
||||
/*********************************************************************/ |
||||
int testdram (void) |
||||
{ |
||||
char *s; |
||||
int rundata = 0; |
||||
int runaddress = 0; |
||||
int runwalk = 0; |
||||
|
||||
#ifdef CFG_DRAM_TEST_DATA |
||||
s = getenv ("testdramdata"); |
||||
rundata = (s && (*s == 'y')) ? 1 : 0; |
||||
#endif |
||||
#ifdef CFG_DRAM_TEST_ADDRESS |
||||
s = getenv ("testdramaddress"); |
||||
runaddress = (s && (*s == 'y')) ? 1 : 0; |
||||
#endif |
||||
#ifdef CFG_DRAM_TEST_WALK |
||||
s = getenv ("testdramwalk"); |
||||
runwalk = (s && (*s == 'y')) ? 1 : 0; |
||||
#endif |
||||
|
||||
if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) { |
||||
printf ("Testing RAM from 0x%08x to 0x%08x ... (don't panic... that will take a moment !!!!)\n", CFG_MEMTEST_START, CFG_MEMTEST_END); |
||||
} |
||||
#ifdef CFG_DRAM_TEST_DATA |
||||
if (rundata == 1) { |
||||
printf ("Test DATA ... "); |
||||
if (mem_test_data () == 1) { |
||||
printf ("failed \n"); |
||||
return 1; |
||||
} else |
||||
printf ("ok \n"); |
||||
} |
||||
#endif |
||||
#ifdef CFG_DRAM_TEST_ADDRESS |
||||
if (runaddress == 1) { |
||||
printf ("Test ADDRESS ... "); |
||||
if (mem_test_address () == 1) { |
||||
printf ("failed \n"); |
||||
return 1; |
||||
} else |
||||
printf ("ok \n"); |
||||
} |
||||
#endif |
||||
#ifdef CFG_DRAM_TEST_WALK |
||||
if (runwalk == 1) { |
||||
printf ("Test WALKING ONEs ... "); |
||||
if (mem_test_walk () == 1) { |
||||
printf ("failed \n"); |
||||
return 1; |
||||
} else |
||||
printf ("ok \n"); |
||||
} |
||||
#endif |
||||
if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) { |
||||
printf ("passed\n"); |
||||
} |
||||
return 0; |
||||
|
||||
} |
||||
#endif /* CFG_DRAM_TEST */ |
||||
|
||||
/* ronen - the below functions are used by the bootm function */ |
||||
/* - we map the base register to fbe00000 (same mapping as in the LSP) */ |
||||
/* - we turn off the RX gig dmas - to prevent the dma from overunning */ |
||||
/* the kernel data areas. */ |
||||
/* - we diable and invalidate the icache and dcache. */ |
||||
void my_remap_gt_regs_bootm (u32 cur_loc, u32 new_loc) |
||||
{ |
||||
u32 temp; |
||||
|
||||
temp = in_le32 ((u32 *) (new_loc + INTERNAL_SPACE_DECODE)); |
||||
if ((temp & 0xffff) == new_loc >> 16) |
||||
return; |
||||
|
||||
temp = (in_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE)) & |
||||
0xffff0000) | (new_loc >> 16); |
||||
|
||||
out_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE), temp); |
||||
|
||||
while ((WORD_SWAP (*((volatile unsigned int *) (NONE_CACHEABLE | |
||||
new_loc | |
||||
(INTERNAL_SPACE_DECODE))))) |
||||
!= temp); |
||||
|
||||
} |
||||
|
||||
void board_prebootm_init () |
||||
{ |
||||
|
||||
/* change window size of PCI1 IO in order tp prevent overlaping with REG BASE. */ |
||||
GT_REG_WRITE (PCI_1_IO_SIZE, (_64K - 1) >> 16); |
||||
|
||||
/* Stop GigE Rx DMA engines */ |
||||
GT_REG_WRITE (MV64360_ETH_RECEIVE_QUEUE_COMMAND_REG (0), 0x0000ff00); |
||||
/* GT_REG_WRITE (MV64360_ETH_RECEIVE_QUEUE_COMMAND_REG (1), 0x0000ff00); */ |
||||
/* GV_REG_WRITE (MV64360_ETH_RECEIVE_QUEUE_COMMAND_REG (2), 0x0000ff00); */ |
||||
|
||||
/* Relocate MV64360 internal regs */ |
||||
my_remap_gt_regs_bootm (CFG_GT_REGS, CFG_DFL_GT_REGS); |
||||
|
||||
icache_disable (); |
||||
invalidate_l1_instruction_cache (); |
||||
flush_data_cache (); |
||||
dcache_disable (); |
||||
} |
@ -0,0 +1,43 @@ |
||||
/*
|
||||
* (C) Copyright 2001 |
||||
* Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. |
||||
* |
||||
* 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 |
||||
*/ |
||||
|
||||
/*
|
||||
* eth.h - header file for the polled mode GT ethernet driver |
||||
*/ |
||||
|
||||
#ifndef __EVB64360_ETH_H__ |
||||
#define __EVB64360_ETH_H__ |
||||
|
||||
#include <asm/types.h> |
||||
#include <asm/io.h> |
||||
#include <asm/byteorder.h> |
||||
#include <common.h> |
||||
|
||||
|
||||
int db64360_eth0_poll(void); |
||||
int db64360_eth0_transmit(unsigned int s, volatile char *p); |
||||
void db64360_eth0_disable(void); |
||||
bool network_start(bd_t *bis); |
||||
|
||||
|
||||
#endif /* __EVB64360_ETH_H__ */ |
@ -0,0 +1,487 @@ |
||||
/*
|
||||
* (C) Copyright 2000 |
||||
* 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 |
||||
* |
||||
* Hacked for the DB64360 board by Ingo.Assmus@keymile.com |
||||
* extra improvments by Brain Waite |
||||
* for cpci750 by reinhard.arlt@esd-electronics.com |
||||
*/ |
||||
#include <common.h> |
||||
#include <mpc8xx.h> |
||||
#include <malloc.h> |
||||
#include "../../Marvell/include/mv_gen_reg.h" |
||||
#include "../../Marvell/include/core.h" |
||||
|
||||
#define I2C_DELAY 100 |
||||
#undef 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) */ |
||||
|
||||
static void i2c_init (int speed, int slaveaddr) |
||||
{ |
||||
unsigned int n, m, freq, margin, power; |
||||
unsigned int actualN = 0, actualM = 0; |
||||
unsigned int minMargin = 0xffffffff; |
||||
unsigned int tclk = CFG_TCLK; |
||||
unsigned int i2cFreq = speed; /* 100000 max. Fast mode not supported */ |
||||
|
||||
DP (puts ("i2c_init\n")); |
||||
/* gtI2cMasterInit */ |
||||
for (n = 0; n < 8; n++) { |
||||
for (m = 0; m < 16; m++) { |
||||
power = 2 << n; /* power = 2^(n+1) */ |
||||
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 */ |
||||
/* gtI2cReset */ |
||||
GT_REG_WRITE (I2C_SOFT_RESET, 0); |
||||
asm(" sync"); |
||||
GT_REG_WRITE (I2C_CONTROL, 0); |
||||
asm(" sync"); |
||||
|
||||
DP (puts ("set baudrate\n")); |
||||
|
||||
GT_REG_WRITE (I2C_STATUS_BAUDE_RATE, (actualM << 3) | actualN); |
||||
asm(" sync"); |
||||
|
||||
DP (puts ("udelay...\n")); |
||||
|
||||
udelay (I2C_DELAY); |
||||
|
||||
GT_REG_WRITE (I2C_CONTROL, (0x1 << 2) | (0x1 << 6)); |
||||
asm(" sync"); |
||||
} |
||||
|
||||
|
||||
static uchar i2c_select_device (uchar dev_addr, uchar read, int ten_bit) |
||||
{ |
||||
unsigned int status, data, bits = 7; |
||||
unsigned int control; |
||||
int count = 0; |
||||
|
||||
DP (puts ("i2c_select_device\n")); |
||||
|
||||
/* Output slave address */ |
||||
|
||||
if (ten_bit) { |
||||
bits = 10; |
||||
} |
||||
|
||||
GT_REG_READ (I2C_CONTROL, &control); |
||||
control |= (0x1 << 2); |
||||
GT_REG_WRITE (I2C_CONTROL, control); |
||||
asm(" sync"); |
||||
|
||||
GT_REG_READ (I2C_CONTROL, &control); |
||||
control |= (0x1 << 5); /* generate the I2C_START_BIT */ |
||||
GT_REG_WRITE (I2C_CONTROL, control); |
||||
asm(" sync"); |
||||
RESET_REG_BITS (I2C_CONTROL, (0x01 << 3)); |
||||
asm(" sync"); |
||||
|
||||
GT_REG_READ (I2C_CONTROL, &status); |
||||
while ((status & 0x08) != 0x08) { |
||||
GT_REG_READ (I2C_CONTROL, &status); |
||||
} |
||||
|
||||
|
||||
count = 0; |
||||
|
||||
GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); |
||||
while (((status & 0xff) != 0x08) && ((status & 0xff) != 0x10)){ |
||||
if (count > 200) { |
||||
#ifdef DEBUG_I2C |
||||
printf ("Failed to set startbit: 0x%02x\n", status); |
||||
#endif |
||||
GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ |
||||
asm(" sync"); |
||||
return (status); |
||||
} |
||||
GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); |
||||
count++; |
||||
} |
||||
|
||||
DP (puts ("i2c_select_device:write addr byte\n")); |
||||
|
||||
/* assert the address */ |
||||
|
||||
data = (dev_addr << 1); |
||||
/* set the read bit */ |
||||
data |= read; |
||||
GT_REG_WRITE (I2C_DATA, data); |
||||
asm(" sync"); |
||||
RESET_REG_BITS (I2C_CONTROL, BIT3); |
||||
asm(" sync"); |
||||
|
||||
GT_REG_READ (I2C_CONTROL, &status); |
||||
while ((status & 0x08) != 0x08) { |
||||
GT_REG_READ (I2C_CONTROL, &status); |
||||
} |
||||
|
||||
GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); |
||||
count = 0; |
||||
while (((status & 0xff) != 0x40) && ((status & 0xff) != 0x18)) { |
||||
if (count > 200) { |
||||
#ifdef DEBUG_I2C |
||||
printf ("Failed to write address: 0x%02x\n", status); |
||||
#endif |
||||
GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ |
||||
return (status); |
||||
} |
||||
GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); |
||||
asm(" sync"); |
||||
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; |
||||
int count = 0; |
||||
|
||||
DP (puts ("i2c_get_data\n")); |
||||
|
||||
while (len) { |
||||
|
||||
RESET_REG_BITS (I2C_CONTROL, BIT3); |
||||
asm(" sync"); |
||||
|
||||
/* Get and return the data */ |
||||
|
||||
GT_REG_READ (I2C_CONTROL, &status); |
||||
while ((status & 0x08) != 0x08) { |
||||
GT_REG_READ (I2C_CONTROL, &status); |
||||
} |
||||
|
||||
GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); |
||||
count++; |
||||
while ((status & 0xff) != 0x50) { |
||||
if (count > 20) { |
||||
#ifdef DEBUG_I2C |
||||
printf ("Failed to get data len status: 0x%02x\n", status); |
||||
#endif |
||||
GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ |
||||
asm(" sync"); |
||||
return 0; |
||||
} |
||||
GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); |
||||
count++; |
||||
} |
||||
GT_REG_READ (I2C_DATA, &data); |
||||
len--; |
||||
*return_data = (uchar) data; |
||||
return_data++; |
||||
|
||||
} |
||||
RESET_REG_BITS (I2C_CONTROL, BIT2 | BIT3); |
||||
asm(" sync"); |
||||
count = 0; |
||||
|
||||
GT_REG_READ (I2C_CONTROL, &status); |
||||
while ((status & 0x08) != 0x08) { |
||||
GT_REG_READ (I2C_CONTROL, &status); |
||||
} |
||||
|
||||
while ((status & 0xff) != 0x58) { |
||||
if (count > 2000) { |
||||
GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ |
||||
return (status); |
||||
} |
||||
GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); |
||||
count++; |
||||
} |
||||
GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /* stop */ |
||||
asm(" sync"); |
||||
RESET_REG_BITS (I2C_CONTROL, (0x1 << 3)); |
||||
asm(" sync"); |
||||
|
||||
return (0); |
||||
} |
||||
|
||||
|
||||
static uchar i2c_write_data (unsigned int *data, int len) |
||||
{ |
||||
unsigned int status; |
||||
int count; |
||||
unsigned int temp; |
||||
unsigned int *temp_ptr = data; |
||||
|
||||
DP (puts ("i2c_write_data\n")); |
||||
|
||||
while (len) { |
||||
count = 0; |
||||
temp = (unsigned int) (*temp_ptr); |
||||
GT_REG_WRITE (I2C_DATA, temp); |
||||
asm(" sync"); |
||||
RESET_REG_BITS (I2C_CONTROL, (0x1 << 3)); |
||||
asm(" sync"); |
||||
|
||||
GT_REG_READ (I2C_CONTROL, &status); |
||||
while ((status & 0x08) != 0x08) { |
||||
GT_REG_READ (I2C_CONTROL, &status); |
||||
} |
||||
|
||||
GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); |
||||
count++; |
||||
while ((status & 0xff) != 0x28) { |
||||
if (count > 200) { |
||||
GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ |
||||
asm(" sync"); |
||||
return (status); |
||||
} |
||||
GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); |
||||
count++; |
||||
} |
||||
len--; |
||||
temp_ptr++; |
||||
} |
||||
return (0); |
||||
} |
||||
|
||||
|
||||
static uchar i2c_write_byte (unsigned char *data, int len) |
||||
{ |
||||
unsigned int status; |
||||
int count; |
||||
unsigned int temp; |
||||
unsigned char *temp_ptr = data; |
||||
|
||||
DP (puts ("i2c_write_byte\n")); |
||||
|
||||
while (len) { |
||||
count = 0; |
||||
/* Set and assert the data */ |
||||
temp = *temp_ptr; |
||||
GT_REG_WRITE (I2C_DATA, temp); |
||||
asm(" sync"); |
||||
RESET_REG_BITS (I2C_CONTROL, (0x1 << 3)); |
||||
asm(" sync"); |
||||
|
||||
|
||||
GT_REG_READ (I2C_CONTROL, &status); |
||||
while ((status & 0x08) != 0x08) { |
||||
GT_REG_READ (I2C_CONTROL, &status); |
||||
} |
||||
|
||||
GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); |
||||
count++; |
||||
while ((status & 0xff) != 0x28) { |
||||
if (count > 200) { |
||||
GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ |
||||
asm(" sync"); |
||||
return (status); |
||||
} |
||||
GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); |
||||
count++; |
||||
} |
||||
len--; |
||||
temp_ptr++; |
||||
} |
||||
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]; |
||||
|
||||
table[1] = (offset ) & 0x0ff; /* low byte */ |
||||
table[0] = (offset >> 8) & 0x0ff; /* high byte */ |
||||
|
||||
DP (puts ("i2c_set_dev_offset\n")); |
||||
|
||||
status = i2c_select_device (dev_addr, 0, ten_bit); |
||||
if (status) { |
||||
#ifdef DEBUG_I2C |
||||
22 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 = CFG_I2C_SPEED; |
||||
|
||||
DP (puts ("i2c_read\n")); |
||||
|
||||
i2c_init (i2cFreq, 0); /* set the i2c frequency */ |
||||
|
||||
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_select_device (dev_addr, 1, 0); |
||||
if (status) { |
||||
#ifdef DEBUG_I2C |
||||
printf ("Failed to select device for data read: 0x%02x\n", |
||||
status); |
||||
#endif |
||||
return status; |
||||
} |
||||
|
||||
status = i2c_get_data (data, len); |
||||
if (status) { |
||||
#ifdef DEBUG_I2C |
||||
printf ("Data not read: 0x%02x\n", status); |
||||
#endif |
||||
return status; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
|
||||
void i2c_stop (void) |
||||
{ |
||||
GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); |
||||
asm(" sync"); |
||||
} |
||||
|
||||
|
||||
uchar |
||||
i2c_write (uchar dev_addr, unsigned int offset, int alen, uchar * data, |
||||
int len) |
||||
{ |
||||
uchar status = 0; |
||||
unsigned int i2cFreq = CFG_I2C_SPEED; |
||||
|
||||
DP (puts ("i2c_write\n")); |
||||
|
||||
i2c_init (i2cFreq, 0); /* set the i2c frequency */ |
||||
|
||||
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; |
||||
} |
||||
|
||||
|
||||
int i2c_probe (uchar chip) |
||||
{ |
||||
|
||||
#ifdef DEBUG_I2C |
||||
unsigned int i2c_status; |
||||
#endif |
||||
uchar status = 0; |
||||
unsigned int i2cFreq = CFG_I2C_SPEED; |
||||
|
||||
DP (puts ("i2c_probe\n")); |
||||
|
||||
i2c_init (i2cFreq, 0); /* set the i2c frequency */ |
||||
|
||||
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 |
||||
GT_REG_READ (I2C_STATUS_BAUDE_RATE, &i2c_status); |
||||
printf ("address %#x returned %#x\n", chip, i2c_status); |
||||
#endif |
||||
/* issue a stop bit */ |
||||
i2c_stop (); |
||||
return 0; /* successful completion */ |
||||
} |
@ -0,0 +1,32 @@ |
||||
/*
|
||||
* (C) Copyright 2000 |
||||
* 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 |
||||
* |
||||
* Hacked for the DB64360 board by Ingo.Assmus@keymile.com |
||||
*/ |
||||
|
||||
#ifndef __I2C_H__ |
||||
#define __I2C_H__ |
||||
|
||||
/* function declarations */ |
||||
uchar i2c_read(uchar, unsigned int, int, uchar*, int); |
||||
|
||||
#endif |
@ -0,0 +1,72 @@ |
||||
/*
|
||||
* (C) Copyright 2000 |
||||
* 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 |
||||
* |
||||
*/ |
||||
/* ide.c - ide support functions */ |
||||
|
||||
|
||||
#include <common.h> |
||||
#ifdef CFG_CMD_IDE |
||||
#include <ata.h> |
||||
#include <ide.h> |
||||
#include <pci.h> |
||||
|
||||
extern ulong ide_bus_offset[CFG_IDE_MAXBUS]; |
||||
|
||||
int ide_preinit |
||||
( |
||||
void |
||||
) |
||||
{ |
||||
int status; |
||||
pci_dev_t devbusfn; |
||||
int l; |
||||
|
||||
status = 1; |
||||
for(l=0;l<CFG_IDE_MAXBUS;l++) |
||||
{ |
||||
ide_bus_offset[l] = -ATA_STATUS; |
||||
} |
||||
devbusfn = pci_find_device(0x1103, 0x0004, 0); |
||||
if (devbusfn != -1) |
||||
{ |
||||
status = 0; |
||||
|
||||
pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, (u32 *)&ide_bus_offset[0]); |
||||
ide_bus_offset[0] &= 0xfffffffe; |
||||
ide_bus_offset[0] += CFG_PCI0_IO_SPACE; |
||||
pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_2, (u32 *)&ide_bus_offset[1]); |
||||
ide_bus_offset[1] &= 0xfffffffe; |
||||
ide_bus_offset[1] += CFG_PCI0_IO_SPACE; |
||||
} |
||||
return(status); |
||||
} |
||||
|
||||
void ide_set_reset |
||||
( |
||||
int flag |
||||
) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
#endif /* of CONFIG_CMDS_IDE */ |
@ -0,0 +1,83 @@ |
||||
/*
|
||||
* (C) Copyright 2003 |
||||
* Ingo Assmus <ingo.assmus@keymile.com>
|
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
/*
|
||||
* include/local.h - local configuration options, board specific |
||||
*/ |
||||
|
||||
#ifndef __LOCAL_H |
||||
#define __LOCAL_H |
||||
|
||||
/*
|
||||
* High Level Configuration Options |
||||
* (easy to change) |
||||
*/ |
||||
|
||||
/* This tells PPCBoot that the config options are compiled in */ |
||||
/* #undef ENV_IS_EMBEDDED */ |
||||
/* Don't touch this! PPCBOOT figures this out based on other
|
||||
* magic. */ |
||||
|
||||
/* Uncomment and define any of the below options */ |
||||
|
||||
/* #define CONFIG_750CX */ /* The 750CX doesn't support as many things in L2CR */ |
||||
#define CONFIG_750FX /* The 750FX doesn't support as many things in L2CR like 750CX*/ |
||||
|
||||
/* These want string arguments */ |
||||
/* #define CONFIG_BOOTARGS */ |
||||
/* #define CONFIG_BOOTCOMMAND */ |
||||
/* #define CONFIG_RAMBOOTCOMMAND */ |
||||
/* #define CONFIG_NFSBOOTCOMMAND */ |
||||
/* #define CFG_AUTOLOAD */ |
||||
/* #define CONFIG_PREBOOT */ |
||||
|
||||
/* These don't */ |
||||
|
||||
/* #define CONFIG_BOOTDELAY */ |
||||
/* #define CONFIG_BAUDRATE */ |
||||
/* #define CONFIG_LOADS_ECHO */ |
||||
/* #define CONFIG_ETHADDR */ |
||||
/* #define CONFIG_ETH2ADDR */ |
||||
/* #define CONFIG_ETH3ADDR */ |
||||
/* #define CONFIG_IPADDR */ |
||||
/* #define CONFIG_SERVERIP */ |
||||
/* #define CONFIG_ROOTPATH */ |
||||
/* #define CONFIG_GATEWAYIP */ |
||||
/* #define CONFIG_NETMASK */ |
||||
/* #define CONFIG_HOSTNAME */ |
||||
/* #define CONFIG_BOOTFILE */ |
||||
/* #define CONFIG_LOADADDR */ |
||||
|
||||
/* these hardware addresses are pretty bogus, please change them to
|
||||
suit your needs */ |
||||
|
||||
/* first ethernet */ |
||||
/* #define CONFIG_ETHADDR 86:06:2d:7e:c6:53 */ |
||||
#define CONFIG_ETHADDR 64:36:00:00:00:01 |
||||
|
||||
/* next two ethernet hwaddrs */ |
||||
#define CONFIG_ETH1ADDR 86:06:2d:7e:c6:54 |
||||
#define CONFIG_ETH2ADDR 86:06:2d:7e:c6:55 |
||||
|
||||
#define CONFIG_ENV_OVERWRITE |
||||
#endif /* __CONFIG_H */ |
@ -0,0 +1,245 @@ |
||||
#include <config.h> |
||||
#include <74xx_7xx.h> |
||||
#include "version.h" |
||||
|
||||
#include <ppc_asm.tmpl> |
||||
#include <ppc_defs.h> |
||||
|
||||
#include <asm/cache.h> |
||||
#include <asm/mmu.h> |
||||
|
||||
#include "../../Marvell/include/mv_gen_reg.h" |
||||
|
||||
#ifdef CONFIG_ECC |
||||
/* Galileo specific asm code for initializing ECC */ |
||||
.globl board_relocate_rom
|
||||
board_relocate_rom: |
||||
mflr r7 |
||||
/* update the location of the GT registers */ |
||||
lis r11, CFG_GT_REGS@h
|
||||
/* if we're using ECC, we must use the DMA engine to copy ourselves */ |
||||
bl start_idma_transfer_0 |
||||
bl wait_for_idma_0 |
||||
bl stop_idma_engine_0 |
||||
|
||||
mtlr r7 |
||||
blr |
||||
|
||||
.globl board_init_ecc
|
||||
board_init_ecc: |
||||
mflr r7 |
||||
/* NOTE: r10 still contains the location we've been relocated to |
||||
* which happens to be TOP_OF_RAM - CFG_MONITOR_LEN */ |
||||
|
||||
/* now that we're running from ram, init the rest of main memory |
||||
* for ECC use */ |
||||
lis r8, CFG_MONITOR_LEN@h
|
||||
ori r8, r8, CFG_MONITOR_LEN@l
|
||||
|
||||
divw r3, r10, r8 |
||||
|
||||
/* set up the counter, and init the starting address */ |
||||
mtctr r3 |
||||
li r12, 0 |
||||
|
||||
/* bytes per transfer */ |
||||
mr r5, r8 |
||||
about_to_init_ecc: |
||||
1: mr r3, r12 |
||||
mr r4, r12 |
||||
bl start_idma_transfer_0 |
||||
bl wait_for_idma_0 |
||||
bl stop_idma_engine_0 |
||||
add r12, r12, r8 |
||||
bdnz 1b |
||||
|
||||
mtlr r7 |
||||
blr |
||||
|
||||
/* r3: dest addr |
||||
* r4: source addr |
||||
* r5: byte count |
||||
* r11: gt regbase |
||||
* trashes: r6, r5 |
||||
*/ |
||||
start_idma_transfer_0: |
||||
/* set the byte count, including the OWN bit */ |
||||
mr r6, r11 |
||||
ori r6, r6, CHANNEL0_DMA_BYTE_COUNT |
||||
stwbrx r5, 0, (r6) |
||||
|
||||
/* set the source address */ |
||||
mr r6, r11 |
||||
ori r6, r6, CHANNEL0_DMA_SOURCE_ADDRESS |
||||
stwbrx r4, 0, (r6) |
||||
|
||||
/* set the dest address */ |
||||
mr r6, r11 |
||||
ori r6, r6, CHANNEL0_DMA_DESTINATION_ADDRESS |
||||
stwbrx r3, 0, (r6) |
||||
|
||||
/* set the next record pointer */ |
||||
li r5, 0 |
||||
mr r6, r11 |
||||
ori r6, r6, CHANNEL0NEXT_RECORD_POINTER |
||||
stwbrx r5, 0, (r6) |
||||
|
||||
/* set the low control register */ |
||||
/* bit 9 is NON chained mode, bit 31 is new style descriptors. |
||||
bit 12 is channel enable */ |
||||
ori r5, r5, (1 << 12) | (1 << 12) | (1 << 11) |
||||
/* 15 shifted by 16 (oris) == bit 31 */ |
||||
oris r5, r5, (1 << 15) |
||||
mr r6, r11 |
||||
ori r6, r6, CHANNEL0CONTROL |
||||
stwbrx r5, 0, (r6) |
||||
|
||||
blr |
||||
|
||||
/* this waits for the bytecount to return to zero, indicating |
||||
* that the trasfer is complete */ |
||||
wait_for_idma_0: |
||||
mr r5, r11 |
||||
lis r6, 0xff |
||||
ori r6, r6, 0xffff |
||||
ori r5, r5, CHANNEL0_DMA_BYTE_COUNT |
||||
1: lwbrx r4, 0, (r5) |
||||
and. r4, r4, r6 |
||||
bne 1b |
||||
|
||||
blr |
||||
|
||||
/* this turns off channel 0 of the idma engine */ |
||||
stop_idma_engine_0: |
||||
/* shut off the DMA engine */ |
||||
li r5, 0 |
||||
mr r6, r11 |
||||
ori r6, r6, CHANNEL0CONTROL |
||||
stwbrx r5, 0, (r6) |
||||
|
||||
blr |
||||
#endif |
||||
|
||||
#ifdef CFG_BOARD_ASM_INIT |
||||
/* NOTE: trashes r3-r7 */ |
||||
.globl board_asm_init
|
||||
board_asm_init: |
||||
/* just move the GT registers to where they belong */ |
||||
lis r3, CFG_DFL_GT_REGS@h
|
||||
ori r3, r3, CFG_DFL_GT_REGS@l
|
||||
lis r4, CFG_GT_REGS@h
|
||||
ori r4, r4, CFG_GT_REGS@l
|
||||
li r5, INTERNAL_SPACE_DECODE |
||||
|
||||
/* test to see if we've already moved */ |
||||
lwbrx r6, r5, r4 |
||||
andi. r6, r6, 0xffff |
||||
/* check loading of R7 is: 0x0F80 should: 0xf800: DONE */ |
||||
/* rlwinm r7, r4, 8, 16, 31 |
||||
rlwinm r7, r4, 12, 16, 31 */ /* original */ |
||||
rlwinm r7, r4, 16, 16, 31 |
||||
/* -----------------------------------------------------*/ |
||||
cmp cr0, r7, r6 |
||||
beqlr |
||||
|
||||
/* nope, have to move the registers */ |
||||
lwbrx r6, r5, r3 |
||||
andis. r6, r6, 0xffff |
||||
or r6, r6, r7 |
||||
stwbrx r6, r5, r3 |
||||
|
||||
/* now, poll for the change */ |
||||
1: lwbrx r7, r5, r4 |
||||
cmp cr0, r7, r6 |
||||
bne 1b |
||||
|
||||
lis r3, CFG_INT_SRAM_BASE@h
|
||||
ori r3, r3, CFG_INT_SRAM_BASE@l
|
||||
rlwinm r3, r3, 16, 16, 31 |
||||
lis r4, CFG_GT_REGS@h
|
||||
ori r4, r4, CFG_GT_REGS@l
|
||||
li r5, INTEGRATED_SRAM_BASE_ADDR |
||||
stwbrx r3, r5, r4 |
||||
|
||||
2: lwbrx r6, r5, r4 |
||||
cmp cr0, r3, r6 |
||||
bne 2b
|
||||
|
||||
/* done! */ |
||||
blr |
||||
#endif |
||||
|
||||
/* For use of the debug LEDs */ |
||||
.global led_on0_relocated
|
||||
led_on0_relocated: |
||||
xor r21, r21, r21 |
||||
xor r18, r18, r18 |
||||
lis r18, 0xFC80 |
||||
ori r18, r18, 0x8000 |
||||
/* stw r21, 0x0(r18) */ |
||||
sync |
||||
blr |
||||
|
||||
.global led_off0_relocated
|
||||
led_off0_relocated: |
||||
xor r21, r21, r21 |
||||
xor r18, r18, r18 |
||||
lis r18, 0xFC81 |
||||
ori r18, r18, 0x4000 |
||||
/* stw r21, 0x0(r18) */ |
||||
sync |
||||
blr |
||||
|
||||
.global led_on0
|
||||
led_on0: |
||||
xor r18, r18, r18 |
||||
lis r18, 0x1c80 |
||||
ori r18, r18, 0x8000 |
||||
/* stw r18, 0x0(r18) */ |
||||
sync |
||||
blr |
||||
|
||||
.global led_off0
|
||||
led_off0: |
||||
xor r18, r18, r18 |
||||
lis r18, 0x1c81 |
||||
ori r18, r18, 0x4000 |
||||
/* stw r18, 0x0(r18) */ |
||||
sync |
||||
blr |
||||
|
||||
.global led_on1
|
||||
led_on1: |
||||
xor r18, r18, r18 |
||||
lis r18, 0x1c80 |
||||
ori r18, r18, 0xc000 |
||||
/* stw r18, 0x0(r18) */ |
||||
sync |
||||
blr |
||||
|
||||
.global led_off1
|
||||
led_off1: |
||||
xor r18, r18, r18 |
||||
lis r18, 0x1c81 |
||||
ori r18, r18, 0x8000 |
||||
/* stw r18, 0x0(r18) */ |
||||
sync |
||||
blr |
||||
|
||||
.global led_on2
|
||||
led_on2: |
||||
xor r18, r18, r18 |
||||
lis r18, 0x1c81 |
||||
ori r18, r18, 0x0000 |
||||
/* stw r18, 0x0(r18) */ |
||||
sync |
||||
blr |
||||
|
||||
.global led_off2
|
||||
led_off2: |
||||
xor r18, r18, r18 |
||||
lis r18, 0x1c81 |
||||
ori r18, r18, 0xc000 |
||||
/* stw r18, 0x0(r18) */ |
||||
sync |
||||
blr |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,156 @@ |
||||
/*
|
||||
* (C) Copyright 2001 |
||||
* John Clemens <clemens@mclx.com>, Mission Critical Linux, Inc. |
||||
* |
||||
* 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 |
||||
*/ |
||||
|
||||
/*************************************************************************
|
||||
* changes for Marvell DB64360 eval board 2003 by Ingo Assmus <ingo.assmus@keymile.com> |
||||
* |
||||
************************************************************************/ |
||||
|
||||
|
||||
/*
|
||||
* mpsc.h - header file for MPSC in uart mode (console driver) |
||||
*/ |
||||
|
||||
#ifndef __MPSC_H__ |
||||
#define __MPSC_H__ |
||||
|
||||
/* include actual Galileo defines */ |
||||
#include "../../Marvell/include/mv_gen_reg.h" |
||||
|
||||
/* driver related defines */ |
||||
|
||||
int mpsc_init(int baud); |
||||
void mpsc_sdma_init(void); |
||||
void mpsc_init2(void); |
||||
int galbrg_set_baudrate(int channel, int rate); |
||||
|
||||
int mpsc_putchar_early(char ch); |
||||
char mpsc_getchar_debug(void); |
||||
int mpsc_test_char_debug(void); |
||||
|
||||
int mpsc_test_char_sdma(void); |
||||
|
||||
extern int (*mpsc_putchar)(char ch); |
||||
extern char (*mpsc_getchar)(void); |
||||
extern int (*mpsc_test_char)(void); |
||||
|
||||
#define CHANNEL CONFIG_MPSC_PORT |
||||
|
||||
#define TX_DESC 5 |
||||
#define RX_DESC 20 |
||||
|
||||
#define DESC_FIRST 0x00010000 |
||||
#define DESC_LAST 0x00020000 |
||||
#define DESC_OWNER_BIT 0x80000000 |
||||
|
||||
#define TX_DEMAND 0x00800000 |
||||
#define TX_STOP 0x00010000 |
||||
#define RX_ENABLE 0x00000080 |
||||
|
||||
#define SDMA_RX_ABORT (1 << 15) |
||||
#define SDMA_TX_ABORT (1 << 31) |
||||
#define MPSC_TX_ABORT (1 << 7) |
||||
#define MPSC_RX_ABORT (1 << 23) |
||||
#define MPSC_ENTER_HUNT (1 << 31) |
||||
|
||||
/* MPSC defines */ |
||||
|
||||
#define GALMPSC_CONNECT 0x1 |
||||
#define GALMPSC_DISCONNECT 0x0 |
||||
|
||||
#define GALMPSC_UART 0x1 |
||||
|
||||
#define GALMPSC_STOP_BITS_1 0x0 |
||||
#define GALMPSC_STOP_BITS_2 0x1 |
||||
#define GALMPSC_CHAR_LENGTH_8 0x3 |
||||
#define GALMPSC_CHAR_LENGTH_7 0x2 |
||||
|
||||
#define GALMPSC_PARITY_ODD 0x0 |
||||
#define GALMPSC_PARITY_EVEN 0x2 |
||||
#define GALMPSC_PARITY_MARK 0x3 |
||||
#define GALMPSC_PARITY_SPACE 0x1 |
||||
#define GALMPSC_PARITY_NONE -1 |
||||
|
||||
#define GALMPSC_SERIAL_MULTIPLEX SERIAL_PORT_MULTIPLEX /* 0xf010 */ |
||||
#define GALMPSC_ROUTING_REGISTER MAIN_ROUTING_REGISTER /* 0xb400 */ |
||||
#define GALMPSC_RxC_ROUTE RECEIVE_CLOCK_ROUTING_REGISTER /* 0xb404 */ |
||||
#define GALMPSC_TxC_ROUTE TRANSMIT_CLOCK_ROUTING_REGISTER /* 0xb408 */ |
||||
#define GALMPSC_MCONF_LOW MPSC0_MAIN_CONFIGURATION_LOW /* 0x8000 */ |
||||
#define GALMPSC_MCONF_HIGH MPSC0_MAIN_CONFIGURATION_HIGH /* 0x8004 */ |
||||
#define GALMPSC_PROTOCONF_REG MPSC0_PROTOCOL_CONFIGURATION /* 0x8008 */ |
||||
|
||||
#define GALMPSC_REG_GAP 0x1000 |
||||
|
||||
#define GALMPSC_MCONF_CHREG_BASE CHANNEL0_REGISTER1 /* 0x800c */ |
||||
#define GALMPSC_CHANNELREG_1 CHANNEL0_REGISTER1 /* 0x800c */ |
||||
#define GALMPSC_CHANNELREG_2 CHANNEL0_REGISTER2 /* 0x8010 */ |
||||
#define GALMPSC_CHANNELREG_3 CHANNEL0_REGISTER3 /* 0x8014 */ |
||||
#define GALMPSC_CHANNELREG_4 CHANNEL0_REGISTER4 /* 0x8018 */ |
||||
#define GALMPSC_CHANNELREG_5 CHANNEL0_REGISTER5 /* 0x801c */ |
||||
#define GALMPSC_CHANNELREG_6 CHANNEL0_REGISTER6 /* 0x8020 */ |
||||
#define GALMPSC_CHANNELREG_7 CHANNEL0_REGISTER7 /* 0x8024 */ |
||||
#define GALMPSC_CHANNELREG_8 CHANNEL0_REGISTER8 /* 0x8028 */ |
||||
#define GALMPSC_CHANNELREG_9 CHANNEL0_REGISTER9 /* 0x802c */ |
||||
#define GALMPSC_CHANNELREG_10 CHANNEL0_REGISTER10 /* 0x8030 */ |
||||
#define GALMPSC_CHANNELREG_11 CHANNEL0_REGISTER11 /* 0x8034 */ |
||||
|
||||
#define GALSDMA_COMMAND_FIRST (1 << 16) |
||||
#define GALSDMA_COMMAND_LAST (1 << 17) |
||||
#define GALSDMA_COMMAND_ENABLEINT (1 << 23) |
||||
#define GALSDMA_COMMAND_AUTO (1 << 30) |
||||
#define GALSDMA_COMMAND_OWNER (1 << 31) |
||||
|
||||
#define GALSDMA_RX 0 |
||||
#define GALSDMA_TX 1 |
||||
|
||||
/* CHANNEL2 should be CHANNEL1, according to documentation,
|
||||
* but to work with the current GTREGS file... |
||||
*/ |
||||
#define GALSDMA_0_CONF_REG CHANNEL0_CONFIGURATION_REGISTER /* 0x4000 */ |
||||
#define GALSDMA_1_CONF_REG CHANNEL2_CONFIGURATION_REGISTER /* 0x6000 */ |
||||
#define GALSDMA_0_COM_REG CHANNEL0_COMMAND_REGISTER /* 0x4008 */ |
||||
#define GALSDMA_1_COM_REG CHANNEL2_COMMAND_REGISTER /* 0x6008 */ |
||||
#define GALSDMA_0_CUR_RX_PTR CHANNEL0_CURRENT_RX_DESCRIPTOR_POINTER /* 0x4810 */ |
||||
#define GALSDMA_0_CUR_TX_PTR CHANNEL0_CURRENT_TX_DESCRIPTOR_POINTER /* 0x4c10 */ |
||||
#define GALSDMA_0_FIR_TX_PTR CHANNEL0_FIRST_TX_DESCRIPTOR_POINTER /* 0x4c14 */ |
||||
#define GALSDMA_1_CUR_RX_PTR CHANNEL2_CURRENT_RX_DESCRIPTOR_POINTER /* 0x6810 */ |
||||
#define GALSDMA_1_CUR_TX_PTR CHANNEL2_CURRENT_TX_DESCRIPTOR_POINTER /* 0x6c10 */ |
||||
#define GALSDMA_1_FIR_TX_PTR CHANNEL2_FIRST_TX_DESCRIPTOR_POINTER /* 0x6c14 */ |
||||
#define GALSDMA_REG_DIFF 0x2000 |
||||
|
||||
/* WRONG in gt64260R.h */ |
||||
#define GALSDMA_INT_CAUSE 0xb800 /* SDMA_CAUSE */ |
||||
#define GALSDMA_INT_MASK 0xb880 /* SDMA_MASK */ |
||||
#define GALMPSC_0_INT_CAUSE 0xb804 |
||||
#define GALMPSC_0_INT_MASK 0xb884 |
||||
|
||||
#define GALSDMA_MODE_UART 0 |
||||
#define GALSDMA_MODE_BISYNC 1 |
||||
#define GALSDMA_MODE_HDLC 2 |
||||
#define GALSDMA_MODE_TRANSPARENT 3 |
||||
|
||||
#define GALBRG_0_CONFREG BRG0_CONFIGURATION_REGISTER /* 0xb200 */ |
||||
#define GALBRG_REG_GAP 0x0008 |
||||
#define GALBRG_0_BTREG BRG0_BAUDE_TUNING_REGISTER /* 0xb204 */ |
||||
|
||||
#endif /* __MPSC_H__ */ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,844 @@ |
||||
/*
|
||||
* (C) Copyright 2003 |
||||
* Ingo Assmus <ingo.assmus@keymile.com> |
||||
* |
||||
* based on - Driver for MV64360X ethernet ports |
||||
* Copyright (C) 2002 rabeeh@galileo.co.il |
||||
* |
||||
* 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 |
||||
*/ |
||||
|
||||
/*
|
||||
* mv_eth.h - header file for the polled mode GT ethernet driver |
||||
*/ |
||||
|
||||
#ifndef __DB64360_ETH_H__ |
||||
#define __DB64360_ETH_H__ |
||||
|
||||
#include <asm/types.h> |
||||
#include <asm/io.h> |
||||
#include <asm/byteorder.h> |
||||
#include <common.h> |
||||
#include <net.h> |
||||
#include "mv_regs.h" |
||||
#include "../../Marvell/common/ppc_error_no.h" |
||||
|
||||
|
||||
/*************************************************************************
|
||||
************************************************************************** |
||||
************************************************************************** |
||||
* The first part is the high level driver of the gigE ethernet ports. * |
||||
************************************************************************** |
||||
************************************************************************** |
||||
*************************************************************************/ |
||||
#ifndef TRUE |
||||
#define TRUE 1 |
||||
#endif |
||||
#ifndef FALSE |
||||
#define FALSE 0 |
||||
#endif |
||||
|
||||
/* In case not using SG on Tx, define MAX_SKB_FRAGS as 0 */ |
||||
#ifndef MAX_SKB_FRAGS |
||||
#define MAX_SKB_FRAGS 0 |
||||
#endif |
||||
|
||||
/* Port attributes */ |
||||
/*#define MAX_RX_QUEUE_NUM 8*/ |
||||
/*#define MAX_TX_QUEUE_NUM 8*/ |
||||
#define MAX_RX_QUEUE_NUM 1 |
||||
#define MAX_TX_QUEUE_NUM 1 |
||||
|
||||
|
||||
/* Use one TX queue and one RX queue */ |
||||
#define MV64360_TX_QUEUE_NUM 1 |
||||
#define MV64360_RX_QUEUE_NUM 1 |
||||
|
||||
/*
|
||||
* Number of RX / TX descriptors on RX / TX rings. |
||||
* Note that allocating RX descriptors is done by allocating the RX |
||||
* ring AND a preallocated RX buffers (skb's) for each descriptor. |
||||
* The TX descriptors only allocates the TX descriptors ring, |
||||
* with no pre allocated TX buffers (skb's are allocated by higher layers. |
||||
*/ |
||||
|
||||
/* Default TX ring size is 10 descriptors */ |
||||
#ifdef CONFIG_MV64360_ETH_TXQUEUE_SIZE |
||||
#define MV64360_TX_QUEUE_SIZE CONFIG_MV64360_ETH_TXQUEUE_SIZE |
||||
#else |
||||
#define MV64360_TX_QUEUE_SIZE 4 |
||||
#endif |
||||
|
||||
/* Default RX ring size is 4 descriptors */ |
||||
#ifdef CONFIG_MV64360_ETH_RXQUEUE_SIZE |
||||
#define MV64360_RX_QUEUE_SIZE CONFIG_MV64360_ETH_RXQUEUE_SIZE |
||||
#else |
||||
#define MV64360_RX_QUEUE_SIZE 4 |
||||
#endif |
||||
|
||||
#ifdef CONFIG_RX_BUFFER_SIZE |
||||
#define MV64360_RX_BUFFER_SIZE CONFIG_RX_BUFFER_SIZE |
||||
#else |
||||
#define MV64360_RX_BUFFER_SIZE 1600 |
||||
#endif |
||||
|
||||
#ifdef CONFIG_TX_BUFFER_SIZE |
||||
#define MV64360_TX_BUFFER_SIZE CONFIG_TX_BUFFER_SIZE |
||||
#else |
||||
#define MV64360_TX_BUFFER_SIZE 1600 |
||||
#endif |
||||
|
||||
|
||||
/*
|
||||
* Network device statistics. Akin to the 2.0 ether stats but |
||||
* with byte counters. |
||||
*/ |
||||
|
||||
struct net_device_stats |
||||
{ |
||||
unsigned long rx_packets; /* total packets received */ |
||||
unsigned long tx_packets; /* total packets transmitted */ |
||||
unsigned long rx_bytes; /* total bytes received */ |
||||
unsigned long tx_bytes; /* total bytes transmitted */ |
||||
unsigned long rx_errors; /* bad packets received */ |
||||
unsigned long tx_errors; /* packet transmit problems */ |
||||
unsigned long rx_dropped; /* no space in linux buffers */ |
||||
unsigned long tx_dropped; /* no space available in linux */ |
||||
unsigned long multicast; /* multicast packets received */ |
||||
unsigned long collisions; |
||||
|
||||
/* detailed rx_errors: */ |
||||
unsigned long rx_length_errors; |
||||
unsigned long rx_over_errors; /* receiver ring buff overflow */ |
||||
unsigned long rx_crc_errors; /* recved pkt with crc error */ |
||||
unsigned long rx_frame_errors; /* recv'd frame alignment error */ |
||||
unsigned long rx_fifo_errors; /* recv'r fifo overrun */ |
||||
unsigned long rx_missed_errors; /* receiver missed packet */ |
||||
|
||||
/* detailed tx_errors */ |
||||
unsigned long tx_aborted_errors; |
||||
unsigned long tx_carrier_errors; |
||||
unsigned long tx_fifo_errors; |
||||
unsigned long tx_heartbeat_errors; |
||||
unsigned long tx_window_errors; |
||||
|
||||
/* for cslip etc */ |
||||
unsigned long rx_compressed; |
||||
unsigned long tx_compressed; |
||||
}; |
||||
|
||||
|
||||
/* Private data structure used for ethernet device */ |
||||
struct mv64360_eth_priv { |
||||
unsigned int port_num; |
||||
struct net_device_stats *stats; |
||||
|
||||
/* to buffer area aligned */ |
||||
char * p_eth_tx_buffer[MV64360_TX_QUEUE_SIZE+1]; /*pointers to alligned tx buffs in memory space */ |
||||
char * p_eth_rx_buffer[MV64360_RX_QUEUE_SIZE+1]; /*pointers to allinged rx buffs in memory space */ |
||||
|
||||
/* Size of Tx Ring per queue */ |
||||
unsigned int tx_ring_size [MAX_TX_QUEUE_NUM]; |
||||
|
||||
|
||||
/* Size of Rx Ring per queue */ |
||||
unsigned int rx_ring_size [MAX_RX_QUEUE_NUM]; |
||||
|
||||
/* Magic Number for Ethernet running */ |
||||
unsigned int eth_running; |
||||
|
||||
}; |
||||
|
||||
|
||||
int mv64360_eth_init (struct eth_device *dev); |
||||
int mv64360_eth_stop (struct eth_device *dev); |
||||
int mv64360_eth_start_xmit (struct eth_device*, volatile void* packet, int length); |
||||
/* return db64360_eth0_poll(); */ |
||||
|
||||
int mv64360_eth_open (struct eth_device *dev); |
||||
|
||||
|
||||
/*************************************************************************
|
||||
************************************************************************** |
||||
************************************************************************** |
||||
* The second part is the low level driver of the gigE ethernet ports. * |
||||
************************************************************************** |
||||
************************************************************************** |
||||
*************************************************************************/ |
||||
|
||||
|
||||
/********************************************************************************
|
||||
* Header File for : MV-643xx network interface header |
||||
* |
||||
* DESCRIPTION: |
||||
* This header file contains macros typedefs and function declaration for |
||||
* the Marvell Gig Bit Ethernet Controller. |
||||
* |
||||
* DEPENDENCIES: |
||||
* None. |
||||
* |
||||
*******************************************************************************/ |
||||
|
||||
|
||||
#ifdef CONFIG_SPECIAL_CONSISTENT_MEMORY |
||||
#ifdef CONFIG_MV64360_SRAM_CACHEABLE |
||||
/* In case SRAM is cacheable but not cache coherent */ |
||||
#define D_CACHE_FLUSH_LINE(addr, offset) \ |
||||
{ \
|
||||
__asm__ __volatile__ ("dcbf %0,%1" : : "r" (addr), "r" (offset)); \
|
||||
} |
||||
#else |
||||
/* In case SRAM is cache coherent or non-cacheable */ |
||||
#define D_CACHE_FLUSH_LINE(addr, offset) ; |
||||
#endif |
||||
#else |
||||
#ifdef CONFIG_NOT_COHERENT_CACHE |
||||
/* In case of descriptors on DDR but not cache coherent */ |
||||
#define D_CACHE_FLUSH_LINE(addr, offset) \ |
||||
{ \
|
||||
__asm__ __volatile__ ("dcbf %0,%1" : : "r" (addr), "r" (offset)); \
|
||||
} |
||||
#else |
||||
/* In case of descriptors on DDR and cache coherent */ |
||||
#define D_CACHE_FLUSH_LINE(addr, offset) ; |
||||
#endif /* CONFIG_NOT_COHERENT_CACHE */ |
||||
#endif /* CONFIG_SPECIAL_CONSISTENT_MEMORY */ |
||||
|
||||
|
||||
#define CPU_PIPE_FLUSH \ |
||||
{ \
|
||||
__asm__ __volatile__ ("eieio"); \
|
||||
} |
||||
|
||||
|
||||
/* defines */ |
||||
|
||||
/* Default port configuration value */ |
||||
#define PORT_CONFIG_VALUE \ |
||||
ETH_UNICAST_NORMAL_MODE | \
|
||||
ETH_DEFAULT_RX_QUEUE_0 | \
|
||||
ETH_DEFAULT_RX_ARP_QUEUE_0 | \
|
||||
ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP | \
|
||||
ETH_RECEIVE_BC_IF_IP | \
|
||||
ETH_RECEIVE_BC_IF_ARP | \
|
||||
ETH_CAPTURE_TCP_FRAMES_DIS | \
|
||||
ETH_CAPTURE_UDP_FRAMES_DIS | \
|
||||
ETH_DEFAULT_RX_TCP_QUEUE_0 | \
|
||||
ETH_DEFAULT_RX_UDP_QUEUE_0 | \
|
||||
ETH_DEFAULT_RX_BPDU_QUEUE_0 |
||||
|
||||
/* Default port extend configuration value */ |
||||
#define PORT_CONFIG_EXTEND_VALUE \ |
||||
ETH_SPAN_BPDU_PACKETS_AS_NORMAL | \
|
||||
ETH_PARTITION_DISABLE |
||||
|
||||
|
||||
/* Default sdma control value */ |
||||
#ifdef CONFIG_NOT_COHERENT_CACHE |
||||
#define PORT_SDMA_CONFIG_VALUE \ |
||||
ETH_RX_BURST_SIZE_16_64BIT | \
|
||||
GT_ETH_IPG_INT_RX(0) | \
|
||||
ETH_TX_BURST_SIZE_16_64BIT; |
||||
#else |
||||
#define PORT_SDMA_CONFIG_VALUE \ |
||||
ETH_RX_BURST_SIZE_4_64BIT | \
|
||||
GT_ETH_IPG_INT_RX(0) | \
|
||||
ETH_TX_BURST_SIZE_4_64BIT; |
||||
#endif |
||||
|
||||
#define GT_ETH_IPG_INT_RX(value) \ |
||||
((value & 0x3fff) << 8) |
||||
|
||||
/* Default port serial control value */ |
||||
#define PORT_SERIAL_CONTROL_VALUE \ |
||||
ETH_FORCE_LINK_PASS | \
|
||||
ETH_ENABLE_AUTO_NEG_FOR_DUPLX | \
|
||||
ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | \
|
||||
ETH_ADV_SYMMETRIC_FLOW_CTRL | \
|
||||
ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX | \
|
||||
ETH_FORCE_BP_MODE_NO_JAM | \
|
||||
BIT9 | \
|
||||
ETH_DO_NOT_FORCE_LINK_FAIL | \
|
||||
ETH_RETRANSMIT_16_ETTEMPTS | \
|
||||
ETH_ENABLE_AUTO_NEG_SPEED_GMII | \
|
||||
ETH_DTE_ADV_0 | \
|
||||
ETH_DISABLE_AUTO_NEG_BYPASS | \
|
||||
ETH_AUTO_NEG_NO_CHANGE | \
|
||||
ETH_MAX_RX_PACKET_1552BYTE | \
|
||||
ETH_CLR_EXT_LOOPBACK | \
|
||||
ETH_SET_FULL_DUPLEX_MODE | \
|
||||
ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX; |
||||
|
||||
#define RX_BUFFER_MAX_SIZE 0xFFFF |
||||
#define TX_BUFFER_MAX_SIZE 0xFFFF /* Buffer are limited to 64k */ |
||||
|
||||
#define RX_BUFFER_MIN_SIZE 0x8 |
||||
#define TX_BUFFER_MIN_SIZE 0x8 |
||||
|
||||
/* Tx WRR confoguration macros */ |
||||
#define PORT_MAX_TRAN_UNIT 0x24 /* MTU register (default) 9KByte */ |
||||
#define PORT_MAX_TOKEN_BUCKET_SIZE 0x_fFFF /* PMTBS register (default) */ |
||||
#define PORT_TOKEN_RATE 1023 /* PTTBRC register (default) */ |
||||
|
||||
/* MAC accepet/reject macros */ |
||||
#define ACCEPT_MAC_ADDR 0 |
||||
#define REJECT_MAC_ADDR 1 |
||||
|
||||
/* Size of a Tx/Rx descriptor used in chain list data structure */ |
||||
#define RX_DESC_ALIGNED_SIZE 0x20 |
||||
#define TX_DESC_ALIGNED_SIZE 0x20 |
||||
|
||||
/* An offest in Tx descriptors to store data for buffers less than 8 Bytes */ |
||||
#define TX_BUF_OFFSET_IN_DESC 0x18 |
||||
/* Buffer offset from buffer pointer */ |
||||
#define RX_BUF_OFFSET 0x2 |
||||
|
||||
/* Gap define */ |
||||
#define ETH_BAR_GAP 0x8 |
||||
#define ETH_SIZE_REG_GAP 0x8 |
||||
#define ETH_HIGH_ADDR_REMAP_REG_GAP 0x4 |
||||
#define ETH_PORT_ACCESS_CTRL_GAP 0x4 |
||||
|
||||
/* Gigabit Ethernet Unit Global Registers */ |
||||
|
||||
/* MIB Counters register definitions */ |
||||
#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW 0x0 |
||||
#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH 0x4 |
||||
#define ETH_MIB_BAD_OCTETS_RECEIVED 0x8 |
||||
#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR 0xc |
||||
#define ETH_MIB_GOOD_FRAMES_RECEIVED 0x10 |
||||
#define ETH_MIB_BAD_FRAMES_RECEIVED 0x14 |
||||
#define ETH_MIB_BROADCAST_FRAMES_RECEIVED 0x18 |
||||
#define ETH_MIB_MULTICAST_FRAMES_RECEIVED 0x1c |
||||
#define ETH_MIB_FRAMES_64_OCTETS 0x20 |
||||
#define ETH_MIB_FRAMES_65_TO_127_OCTETS 0x24 |
||||
#define ETH_MIB_FRAMES_128_TO_255_OCTETS 0x28 |
||||
#define ETH_MIB_FRAMES_256_TO_511_OCTETS 0x2c |
||||
#define ETH_MIB_FRAMES_512_TO_1023_OCTETS 0x30 |
||||
#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS 0x34 |
||||
#define ETH_MIB_GOOD_OCTETS_SENT_LOW 0x38 |
||||
#define ETH_MIB_GOOD_OCTETS_SENT_HIGH 0x3c |
||||
#define ETH_MIB_GOOD_FRAMES_SENT 0x40 |
||||
#define ETH_MIB_EXCESSIVE_COLLISION 0x44 |
||||
#define ETH_MIB_MULTICAST_FRAMES_SENT 0x48 |
||||
#define ETH_MIB_BROADCAST_FRAMES_SENT 0x4c |
||||
#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED 0x50 |
||||
#define ETH_MIB_FC_SENT 0x54 |
||||
#define ETH_MIB_GOOD_FC_RECEIVED 0x58 |
||||
#define ETH_MIB_BAD_FC_RECEIVED 0x5c |
||||
#define ETH_MIB_UNDERSIZE_RECEIVED 0x60 |
||||
#define ETH_MIB_FRAGMENTS_RECEIVED 0x64 |
||||
#define ETH_MIB_OVERSIZE_RECEIVED 0x68 |
||||
#define ETH_MIB_JABBER_RECEIVED 0x6c |
||||
#define ETH_MIB_MAC_RECEIVE_ERROR 0x70 |
||||
#define ETH_MIB_BAD_CRC_EVENT 0x74 |
||||
#define ETH_MIB_COLLISION 0x78 |
||||
#define ETH_MIB_LATE_COLLISION 0x7c |
||||
|
||||
/* Port serial status reg (PSR) */ |
||||
#define ETH_INTERFACE_GMII_MII 0 |
||||
#define ETH_INTERFACE_PCM BIT0 |
||||
#define ETH_LINK_IS_DOWN 0 |
||||
#define ETH_LINK_IS_UP BIT1 |
||||
#define ETH_PORT_AT_HALF_DUPLEX 0 |
||||
#define ETH_PORT_AT_FULL_DUPLEX BIT2 |
||||
#define ETH_RX_FLOW_CTRL_DISABLED 0 |
||||
#define ETH_RX_FLOW_CTRL_ENBALED BIT3 |
||||
#define ETH_GMII_SPEED_100_10 0 |
||||
#define ETH_GMII_SPEED_1000 BIT4 |
||||
#define ETH_MII_SPEED_10 0 |
||||
#define ETH_MII_SPEED_100 BIT5 |
||||
#define ETH_NO_TX 0 |
||||
#define ETH_TX_IN_PROGRESS BIT7 |
||||
#define ETH_BYPASS_NO_ACTIVE 0 |
||||
#define ETH_BYPASS_ACTIVE BIT8 |
||||
#define ETH_PORT_NOT_AT_PARTITION_STATE 0 |
||||
#define ETH_PORT_AT_PARTITION_STATE BIT9 |
||||
#define ETH_PORT_TX_FIFO_NOT_EMPTY 0 |
||||
#define ETH_PORT_TX_FIFO_EMPTY BIT10 |
||||
|
||||
|
||||
/* These macros describes the Port configuration reg (Px_cR) bits */ |
||||
#define ETH_UNICAST_NORMAL_MODE 0 |
||||
#define ETH_UNICAST_PROMISCUOUS_MODE BIT0 |
||||
#define ETH_DEFAULT_RX_QUEUE_0 0 |
||||
#define ETH_DEFAULT_RX_QUEUE_1 BIT1 |
||||
#define ETH_DEFAULT_RX_QUEUE_2 BIT2 |
||||
#define ETH_DEFAULT_RX_QUEUE_3 (BIT2 | BIT1) |
||||
#define ETH_DEFAULT_RX_QUEUE_4 BIT3 |
||||
#define ETH_DEFAULT_RX_QUEUE_5 (BIT3 | BIT1) |
||||
#define ETH_DEFAULT_RX_QUEUE_6 (BIT3 | BIT2) |
||||
#define ETH_DEFAULT_RX_QUEUE_7 (BIT3 | BIT2 | BIT1) |
||||
#define ETH_DEFAULT_RX_ARP_QUEUE_0 0 |
||||
#define ETH_DEFAULT_RX_ARP_QUEUE_1 BIT4 |
||||
#define ETH_DEFAULT_RX_ARP_QUEUE_2 BIT5 |
||||
#define ETH_DEFAULT_RX_ARP_QUEUE_3 (BIT5 | BIT4) |
||||
#define ETH_DEFAULT_RX_ARP_QUEUE_4 BIT6 |
||||
#define ETH_DEFAULT_RX_ARP_QUEUE_5 (BIT6 | BIT4) |
||||
#define ETH_DEFAULT_RX_ARP_QUEUE_6 (BIT6 | BIT5) |
||||
#define ETH_DEFAULT_RX_ARP_QUEUE_7 (BIT6 | BIT5 | BIT4) |
||||
#define ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP 0 |
||||
#define ETH_REJECT_BC_IF_NOT_IP_OR_ARP BIT7 |
||||
#define ETH_RECEIVE_BC_IF_IP 0 |
||||
#define ETH_REJECT_BC_IF_IP BIT8 |
||||
#define ETH_RECEIVE_BC_IF_ARP 0 |
||||
#define ETH_REJECT_BC_IF_ARP BIT9 |
||||
#define ETH_TX_AM_NO_UPDATE_ERROR_SUMMARY BIT12 |
||||
#define ETH_CAPTURE_TCP_FRAMES_DIS 0 |
||||
#define ETH_CAPTURE_TCP_FRAMES_EN BIT14 |
||||
#define ETH_CAPTURE_UDP_FRAMES_DIS 0 |
||||
#define ETH_CAPTURE_UDP_FRAMES_EN BIT15 |
||||
#define ETH_DEFAULT_RX_TCP_QUEUE_0 0 |
||||
#define ETH_DEFAULT_RX_TCP_QUEUE_1 BIT16 |
||||
#define ETH_DEFAULT_RX_TCP_QUEUE_2 BIT17 |
||||
#define ETH_DEFAULT_RX_TCP_QUEUE_3 (BIT17 | BIT16) |
||||
#define ETH_DEFAULT_RX_TCP_QUEUE_4 BIT18 |
||||
#define ETH_DEFAULT_RX_TCP_QUEUE_5 (BIT18 | BIT16) |
||||
#define ETH_DEFAULT_RX_TCP_QUEUE_6 (BIT18 | BIT17) |
||||
#define ETH_DEFAULT_RX_TCP_QUEUE_7 (BIT18 | BIT17 | BIT16) |
||||
#define ETH_DEFAULT_RX_UDP_QUEUE_0 0 |
||||
#define ETH_DEFAULT_RX_UDP_QUEUE_1 BIT19 |
||||
#define ETH_DEFAULT_RX_UDP_QUEUE_2 BIT20 |
||||
#define ETH_DEFAULT_RX_UDP_QUEUE_3 (BIT20 | BIT19) |
||||
#define ETH_DEFAULT_RX_UDP_QUEUE_4 (BIT21 |
||||
#define ETH_DEFAULT_RX_UDP_QUEUE_5 (BIT21 | BIT19) |
||||
#define ETH_DEFAULT_RX_UDP_QUEUE_6 (BIT21 | BIT20) |
||||
#define ETH_DEFAULT_RX_UDP_QUEUE_7 (BIT21 | BIT20 | BIT19) |
||||
#define ETH_DEFAULT_RX_BPDU_QUEUE_0 0 |
||||
#define ETH_DEFAULT_RX_BPDU_QUEUE_1 BIT22 |
||||
#define ETH_DEFAULT_RX_BPDU_QUEUE_2 BIT23 |
||||
#define ETH_DEFAULT_RX_BPDU_QUEUE_3 (BIT23 | BIT22) |
||||
#define ETH_DEFAULT_RX_BPDU_QUEUE_4 BIT24 |
||||
#define ETH_DEFAULT_RX_BPDU_QUEUE_5 (BIT24 | BIT22) |
||||
#define ETH_DEFAULT_RX_BPDU_QUEUE_6 (BIT24 | BIT23) |
||||
#define ETH_DEFAULT_RX_BPDU_QUEUE_7 (BIT24 | BIT23 | BIT22) |
||||
|
||||
|
||||
/* These macros describes the Port configuration extend reg (Px_cXR) bits*/ |
||||
#define ETH_CLASSIFY_EN BIT0 |
||||
#define ETH_SPAN_BPDU_PACKETS_AS_NORMAL 0 |
||||
#define ETH_SPAN_BPDU_PACKETS_TO_RX_QUEUE_7 BIT1 |
||||
#define ETH_PARTITION_DISABLE 0 |
||||
#define ETH_PARTITION_ENABLE BIT2 |
||||
|
||||
|
||||
/* Tx/Rx queue command reg (RQCR/TQCR)*/ |
||||
#define ETH_QUEUE_0_ENABLE BIT0 |
||||
#define ETH_QUEUE_1_ENABLE BIT1 |
||||
#define ETH_QUEUE_2_ENABLE BIT2 |
||||
#define ETH_QUEUE_3_ENABLE BIT3 |
||||
#define ETH_QUEUE_4_ENABLE BIT4 |
||||
#define ETH_QUEUE_5_ENABLE BIT5 |
||||
#define ETH_QUEUE_6_ENABLE BIT6 |
||||
#define ETH_QUEUE_7_ENABLE BIT7 |
||||
#define ETH_QUEUE_0_DISABLE BIT8 |
||||
#define ETH_QUEUE_1_DISABLE BIT9 |
||||
#define ETH_QUEUE_2_DISABLE BIT10 |
||||
#define ETH_QUEUE_3_DISABLE BIT11 |
||||
#define ETH_QUEUE_4_DISABLE BIT12 |
||||
#define ETH_QUEUE_5_DISABLE BIT13 |
||||
#define ETH_QUEUE_6_DISABLE BIT14 |
||||
#define ETH_QUEUE_7_DISABLE BIT15 |
||||
|
||||
|
||||
/* These macros describes the Port Sdma configuration reg (SDCR) bits */ |
||||
#define ETH_RIFB BIT0 |
||||
#define ETH_RX_BURST_SIZE_1_64BIT 0 |
||||
#define ETH_RX_BURST_SIZE_2_64BIT BIT1 |
||||
#define ETH_RX_BURST_SIZE_4_64BIT BIT2 |
||||
#define ETH_RX_BURST_SIZE_8_64BIT (BIT2 | BIT1) |
||||
#define ETH_RX_BURST_SIZE_16_64BIT BIT3 |
||||
#define ETH_BLM_RX_NO_SWAP BIT4 |
||||
#define ETH_BLM_RX_BYTE_SWAP 0 |
||||
#define ETH_BLM_TX_NO_SWAP BIT5 |
||||
#define ETH_BLM_TX_BYTE_SWAP 0 |
||||
#define ETH_DESCRIPTORS_BYTE_SWAP BIT6 |
||||
#define ETH_DESCRIPTORS_NO_SWAP 0 |
||||
#define ETH_TX_BURST_SIZE_1_64BIT 0 |
||||
#define ETH_TX_BURST_SIZE_2_64BIT BIT22 |
||||
#define ETH_TX_BURST_SIZE_4_64BIT BIT23 |
||||
#define ETH_TX_BURST_SIZE_8_64BIT (BIT23 | BIT22) |
||||
#define ETH_TX_BURST_SIZE_16_64BIT BIT24 |
||||
|
||||
|
||||
/* These macros describes the Port serial control reg (PSCR) bits */ |
||||
#define ETH_SERIAL_PORT_DISABLE 0 |
||||
#define ETH_SERIAL_PORT_ENABLE BIT0 |
||||
#define ETH_FORCE_LINK_PASS BIT1 |
||||
#define ETH_DO_NOT_FORCE_LINK_PASS 0 |
||||
#define ETH_ENABLE_AUTO_NEG_FOR_DUPLX 0 |
||||
#define ETH_DISABLE_AUTO_NEG_FOR_DUPLX BIT2 |
||||
#define ETH_ENABLE_AUTO_NEG_FOR_FLOW_CTRL 0 |
||||
#define ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL BIT3 |
||||
#define ETH_ADV_NO_FLOW_CTRL 0 |
||||
#define ETH_ADV_SYMMETRIC_FLOW_CTRL BIT4 |
||||
#define ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX 0 |
||||
#define ETH_FORCE_FC_MODE_TX_PAUSE_DIS BIT5 |
||||
#define ETH_FORCE_BP_MODE_NO_JAM 0 |
||||
#define ETH_FORCE_BP_MODE_JAM_TX BIT7 |
||||
#define ETH_FORCE_BP_MODE_JAM_TX_ON_RX_ERR BIT8 |
||||
#define ETH_FORCE_LINK_FAIL 0 |
||||
#define ETH_DO_NOT_FORCE_LINK_FAIL BIT10 |
||||
#define ETH_RETRANSMIT_16_ETTEMPTS 0 |
||||
#define ETH_RETRANSMIT_FOREVER BIT11 |
||||
#define ETH_DISABLE_AUTO_NEG_SPEED_GMII BIT13 |
||||
#define ETH_ENABLE_AUTO_NEG_SPEED_GMII 0 |
||||
#define ETH_DTE_ADV_0 0 |
||||
#define ETH_DTE_ADV_1 BIT14 |
||||
#define ETH_DISABLE_AUTO_NEG_BYPASS 0 |
||||
#define ETH_ENABLE_AUTO_NEG_BYPASS BIT15 |
||||
#define ETH_AUTO_NEG_NO_CHANGE 0 |
||||
#define ETH_RESTART_AUTO_NEG BIT16 |
||||
#define ETH_MAX_RX_PACKET_1518BYTE 0 |
||||
#define ETH_MAX_RX_PACKET_1522BYTE BIT17 |
||||
#define ETH_MAX_RX_PACKET_1552BYTE BIT18 |
||||
#define ETH_MAX_RX_PACKET_9022BYTE (BIT18 | BIT17) |
||||
#define ETH_MAX_RX_PACKET_9192BYTE BIT19 |
||||
#define ETH_MAX_RX_PACKET_9700BYTE (BIT19 | BIT17) |
||||
#define ETH_SET_EXT_LOOPBACK BIT20 |
||||
#define ETH_CLR_EXT_LOOPBACK 0 |
||||
#define ETH_SET_FULL_DUPLEX_MODE BIT21 |
||||
#define ETH_SET_HALF_DUPLEX_MODE 0 |
||||
#define ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX BIT22 |
||||
#define ETH_DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX 0 |
||||
#define ETH_SET_GMII_SPEED_TO_10_100 0 |
||||
#define ETH_SET_GMII_SPEED_TO_1000 BIT23 |
||||
#define ETH_SET_MII_SPEED_TO_10 0 |
||||
#define ETH_SET_MII_SPEED_TO_100 BIT24 |
||||
|
||||
|
||||
/* SMI reg */ |
||||
#define ETH_SMI_BUSY BIT28 /* 0 - Write, 1 - Read */ |
||||
#define ETH_SMI_READ_VALID BIT27 /* 0 - Write, 1 - Read */ |
||||
#define ETH_SMI_OPCODE_WRITE 0 /* Completion of Read operation */ |
||||
#define ETH_SMI_OPCODE_READ BIT26 /* Operation is in progress */ |
||||
|
||||
/* SDMA command status fields macros */ |
||||
|
||||
/* Tx & Rx descriptors status */ |
||||
#define ETH_ERROR_SUMMARY (BIT0) |
||||
|
||||
/* Tx & Rx descriptors command */ |
||||
#define ETH_BUFFER_OWNED_BY_DMA (BIT31) |
||||
|
||||
/* Tx descriptors status */ |
||||
#define ETH_LC_ERROR (0 ) |
||||
#define ETH_UR_ERROR (BIT1 ) |
||||
#define ETH_RL_ERROR (BIT2 ) |
||||
#define ETH_LLC_SNAP_FORMAT (BIT9 ) |
||||
|
||||
/* Rx descriptors status */ |
||||
#define ETH_CRC_ERROR (0 ) |
||||
#define ETH_OVERRUN_ERROR (BIT1 ) |
||||
#define ETH_MAX_FRAME_LENGTH_ERROR (BIT2 ) |
||||
#define ETH_RESOURCE_ERROR ((BIT2 | BIT1)) |
||||
#define ETH_VLAN_TAGGED (BIT19) |
||||
#define ETH_BPDU_FRAME (BIT20) |
||||
#define ETH_TCP_FRAME_OVER_IP_V_4 (0 ) |
||||
#define ETH_UDP_FRAME_OVER_IP_V_4 (BIT21) |
||||
#define ETH_OTHER_FRAME_TYPE (BIT22) |
||||
#define ETH_LAYER_2_IS_ETH_V_2 (BIT23) |
||||
#define ETH_FRAME_TYPE_IP_V_4 (BIT24) |
||||
#define ETH_FRAME_HEADER_OK (BIT25) |
||||
#define ETH_RX_LAST_DESC (BIT26) |
||||
#define ETH_RX_FIRST_DESC (BIT27) |
||||
#define ETH_UNKNOWN_DESTINATION_ADDR (BIT28) |
||||
#define ETH_RX_ENABLE_INTERRUPT (BIT29) |
||||
#define ETH_LAYER_4_CHECKSUM_OK (BIT30) |
||||
|
||||
/* Rx descriptors byte count */ |
||||
#define ETH_FRAME_FRAGMENTED (BIT2) |
||||
|
||||
/* Tx descriptors command */ |
||||
#define ETH_LAYER_4_CHECKSUM_FIRST_DESC (BIT10) |
||||
#define ETH_FRAME_SET_TO_VLAN (BIT15) |
||||
#define ETH_TCP_FRAME (0 ) |
||||
#define ETH_UDP_FRAME (BIT16) |
||||
#define ETH_GEN_TCP_UDP_CHECKSUM (BIT17) |
||||
#define ETH_GEN_IP_V_4_CHECKSUM (BIT18) |
||||
#define ETH_ZERO_PADDING (BIT19) |
||||
#define ETH_TX_LAST_DESC (BIT20) |
||||
#define ETH_TX_FIRST_DESC (BIT21) |
||||
#define ETH_GEN_CRC (BIT22) |
||||
#define ETH_TX_ENABLE_INTERRUPT (BIT23) |
||||
#define ETH_AUTO_MODE (BIT30) |
||||
|
||||
/* Address decode parameters */ |
||||
/* Ethernet Base Address Register bits */ |
||||
#define EBAR_TARGET_DRAM 0x00000000 |
||||
#define EBAR_TARGET_DEVICE 0x00000001 |
||||
#define EBAR_TARGET_CBS 0x00000002 |
||||
#define EBAR_TARGET_PCI0 0x00000003 |
||||
#define EBAR_TARGET_PCI1 0x00000004 |
||||
#define EBAR_TARGET_CUNIT 0x00000005 |
||||
#define EBAR_TARGET_AUNIT 0x00000006 |
||||
#define EBAR_TARGET_GUNIT 0x00000007 |
||||
|
||||
/* Window attributes */ |
||||
#define EBAR_ATTR_DRAM_CS0 0x00000E00 |
||||
#define EBAR_ATTR_DRAM_CS1 0x00000D00 |
||||
#define EBAR_ATTR_DRAM_CS2 0x00000B00 |
||||
#define EBAR_ATTR_DRAM_CS3 0x00000700 |
||||
|
||||
/* DRAM Target interface */ |
||||
#define EBAR_ATTR_DRAM_NO_CACHE_COHERENCY 0x00000000 |
||||
#define EBAR_ATTR_DRAM_CACHE_COHERENCY_WT 0x00001000 |
||||
#define EBAR_ATTR_DRAM_CACHE_COHERENCY_WB 0x00002000 |
||||
|
||||
/* Device Bus Target interface */ |
||||
#define EBAR_ATTR_DEVICE_DEVCS0 0x00001E00 |
||||
#define EBAR_ATTR_DEVICE_DEVCS1 0x00001D00 |
||||
#define EBAR_ATTR_DEVICE_DEVCS2 0x00001B00 |
||||
#define EBAR_ATTR_DEVICE_DEVCS3 0x00001700 |
||||
#define EBAR_ATTR_DEVICE_BOOTCS3 0x00000F00 |
||||
|
||||
/* PCI Target interface */ |
||||
#define EBAR_ATTR_PCI_BYTE_SWAP 0x00000000 |
||||
#define EBAR_ATTR_PCI_NO_SWAP 0x00000100 |
||||
#define EBAR_ATTR_PCI_BYTE_WORD_SWAP 0x00000200 |
||||
#define EBAR_ATTR_PCI_WORD_SWAP 0x00000300 |
||||
#define EBAR_ATTR_PCI_NO_SNOOP_NOT_ASSERT 0x00000000 |
||||
#define EBAR_ATTR_PCI_NO_SNOOP_ASSERT 0x00000400 |
||||
#define EBAR_ATTR_PCI_IO_SPACE 0x00000000 |
||||
#define EBAR_ATTR_PCI_MEMORY_SPACE 0x00000800 |
||||
#define EBAR_ATTR_PCI_REQ64_FORCE 0x00000000 |
||||
#define EBAR_ATTR_PCI_REQ64_SIZE 0x00001000 |
||||
|
||||
/* CPU 60x bus or internal SRAM interface */ |
||||
#define EBAR_ATTR_CBS_SRAM_BLOCK0 0x00000000 |
||||
#define EBAR_ATTR_CBS_SRAM_BLOCK1 0x00000100 |
||||
#define EBAR_ATTR_CBS_SRAM 0x00000000 |
||||
#define EBAR_ATTR_CBS_CPU_BUS 0x00000800 |
||||
|
||||
/* Window access control */ |
||||
#define EWIN_ACCESS_NOT_ALLOWED 0 |
||||
#define EWIN_ACCESS_READ_ONLY BIT0 |
||||
#define EWIN_ACCESS_FULL (BIT1 | BIT0) |
||||
#define EWIN0_ACCESS_MASK 0x0003 |
||||
#define EWIN1_ACCESS_MASK 0x000C |
||||
#define EWIN2_ACCESS_MASK 0x0030 |
||||
#define EWIN3_ACCESS_MASK 0x00C0 |
||||
|
||||
/* typedefs */ |
||||
|
||||
typedef enum _eth_port |
||||
{ |
||||
ETH_0 = 0, |
||||
ETH_1 = 1, |
||||
ETH_2 = 2 |
||||
}ETH_PORT; |
||||
|
||||
typedef enum _eth_func_ret_status |
||||
{ |
||||
ETH_OK, /* Returned as expected. */ |
||||
ETH_ERROR, /* Fundamental error. */ |
||||
ETH_RETRY, /* Could not process request. Try later. */ |
||||
ETH_END_OF_JOB, /* Ring has nothing to process. */ |
||||
ETH_QUEUE_FULL, /* Ring resource error. */ |
||||
ETH_QUEUE_LAST_RESOURCE /* Ring resources about to exhaust. */ |
||||
}ETH_FUNC_RET_STATUS; |
||||
|
||||
typedef enum _eth_queue |
||||
{ |
||||
ETH_Q0 = 0, |
||||
ETH_Q1 = 1, |
||||
ETH_Q2 = 2, |
||||
ETH_Q3 = 3, |
||||
ETH_Q4 = 4, |
||||
ETH_Q5 = 5, |
||||
ETH_Q6 = 6, |
||||
ETH_Q7 = 7 |
||||
} ETH_QUEUE; |
||||
|
||||
typedef enum _addr_win |
||||
{ |
||||
ETH_WIN0, |
||||
ETH_WIN1, |
||||
ETH_WIN2, |
||||
ETH_WIN3, |
||||
ETH_WIN4, |
||||
ETH_WIN5 |
||||
} ETH_ADDR_WIN; |
||||
|
||||
typedef enum _eth_target |
||||
{ |
||||
ETH_TARGET_DRAM , |
||||
ETH_TARGET_DEVICE, |
||||
ETH_TARGET_CBS , |
||||
ETH_TARGET_PCI0 , |
||||
ETH_TARGET_PCI1 |
||||
}ETH_TARGET; |
||||
|
||||
typedef struct _eth_rx_desc |
||||
{ |
||||
unsigned short byte_cnt ; /* Descriptor buffer byte count */ |
||||
unsigned short buf_size ; /* Buffer size */ |
||||
unsigned int cmd_sts ; /* Descriptor command status */ |
||||
unsigned int next_desc_ptr; /* Next descriptor pointer */ |
||||
unsigned int buf_ptr ; /* Descriptor buffer pointer */ |
||||
unsigned int return_info ; /* User resource return information */ |
||||
} ETH_RX_DESC; |
||||
|
||||
|
||||
typedef struct _eth_tx_desc |
||||
{ |
||||
unsigned short byte_cnt ; /* Descriptor buffer byte count */ |
||||
unsigned short l4i_chk ; /* CPU provided TCP Checksum */ |
||||
unsigned int cmd_sts ; /* Descriptor command status */ |
||||
unsigned int next_desc_ptr; /* Next descriptor pointer */ |
||||
unsigned int buf_ptr ; /* Descriptor buffer pointer */ |
||||
unsigned int return_info ; /* User resource return information */ |
||||
} ETH_TX_DESC; |
||||
|
||||
/* Unified struct for Rx and Tx operations. The user is not required to */ |
||||
/* be familier with neither Tx nor Rx descriptors. */ |
||||
typedef struct _pkt_info |
||||
{ |
||||
unsigned short byte_cnt ; /* Descriptor buffer byte count */ |
||||
unsigned short l4i_chk ; /* Tx CPU provided TCP Checksum */ |
||||
unsigned int cmd_sts ; /* Descriptor command status */ |
||||
unsigned int buf_ptr ; /* Descriptor buffer pointer */ |
||||
unsigned int return_info ; /* User resource return information */ |
||||
} PKT_INFO; |
||||
|
||||
|
||||
typedef struct _eth_win_param |
||||
{ |
||||
ETH_ADDR_WIN win; /* Window number. See ETH_ADDR_WIN enum */ |
||||
ETH_TARGET target; /* System targets. See ETH_TARGET enum */ |
||||
unsigned short attributes; /* BAR attributes. See above macros. */ |
||||
unsigned int base_addr; /* Window base address in unsigned int form */ |
||||
unsigned int high_addr; /* Window high address in unsigned int form */ |
||||
unsigned int size; /* Size in MBytes. Must be % 64Kbyte. */ |
||||
bool enable; /* Enable/disable access to the window. */ |
||||
unsigned short access_ctrl; /* Access ctrl register. see above macros */ |
||||
} ETH_WIN_PARAM; |
||||
|
||||
|
||||
/* Ethernet port specific infomation */ |
||||
|
||||
typedef struct _eth_port_ctrl |
||||
{ |
||||
ETH_PORT port_num; /* User Ethernet port number */ |
||||
int port_phy_addr; /* User phy address of Ethrnet port */ |
||||
unsigned char port_mac_addr[6]; /* User defined port MAC address. */ |
||||
unsigned int port_config; /* User port configuration value */ |
||||
unsigned int port_config_extend; /* User port config extend value */ |
||||
unsigned int port_sdma_config; /* User port SDMA config value */ |
||||
unsigned int port_serial_control; /* User port serial control value */ |
||||
unsigned int port_tx_queue_command; /* Port active Tx queues summary */ |
||||
unsigned int port_rx_queue_command; /* Port active Rx queues summary */ |
||||
|
||||
/* User function to cast virtual address to CPU bus address */ |
||||
unsigned int (*port_virt_to_phys)(unsigned int addr); |
||||
/* User scratch pad for user specific data structures */ |
||||
void *port_private; |
||||
|
||||
bool rx_resource_err[MAX_RX_QUEUE_NUM]; /* Rx ring resource error flag */ |
||||
bool tx_resource_err[MAX_TX_QUEUE_NUM]; /* Tx ring resource error flag */ |
||||
|
||||
/* Tx/Rx rings managment indexes fields. For driver use */ |
||||
|
||||
/* Next available Rx resource */ |
||||
volatile ETH_RX_DESC *p_rx_curr_desc_q[MAX_RX_QUEUE_NUM]; |
||||
/* Returning Rx resource */ |
||||
volatile ETH_RX_DESC *p_rx_used_desc_q[MAX_RX_QUEUE_NUM]; |
||||
|
||||
/* Next available Tx resource */ |
||||
volatile ETH_TX_DESC *p_tx_curr_desc_q[MAX_TX_QUEUE_NUM]; |
||||
/* Returning Tx resource */ |
||||
volatile ETH_TX_DESC *p_tx_used_desc_q[MAX_TX_QUEUE_NUM]; |
||||
/* An extra Tx index to support transmit of multiple buffers per packet */ |
||||
volatile ETH_TX_DESC *p_tx_first_desc_q[MAX_TX_QUEUE_NUM]; |
||||
|
||||
/* Tx/Rx rings size and base variables fields. For driver use */ |
||||
|
||||
volatile ETH_RX_DESC *p_rx_desc_area_base[MAX_RX_QUEUE_NUM]; |
||||
unsigned int rx_desc_area_size[MAX_RX_QUEUE_NUM]; |
||||
char *p_rx_buffer_base[MAX_RX_QUEUE_NUM]; |
||||
|
||||
volatile ETH_TX_DESC *p_tx_desc_area_base[MAX_TX_QUEUE_NUM]; |
||||
unsigned int tx_desc_area_size[MAX_TX_QUEUE_NUM]; |
||||
char *p_tx_buffer_base[MAX_TX_QUEUE_NUM]; |
||||
|
||||
} ETH_PORT_INFO; |
||||
|
||||
|
||||
/* ethernet.h API list */ |
||||
|
||||
/* Port operation control routines */ |
||||
static void eth_port_init (ETH_PORT_INFO *p_eth_port_ctrl); |
||||
static void eth_port_reset(ETH_PORT eth_port_num); |
||||
static bool eth_port_start(ETH_PORT_INFO *p_eth_port_ctrl); |
||||
|
||||
|
||||
/* Port MAC address routines */ |
||||
static void eth_port_uc_addr_set (ETH_PORT eth_port_num, |
||||
unsigned char *p_addr, |
||||
ETH_QUEUE queue); |
||||
#if 0 /* FIXME */
|
||||
static void eth_port_mc_addr (ETH_PORT eth_port_num, |
||||
unsigned char *p_addr, |
||||
ETH_QUEUE queue, |
||||
int option); |
||||
#endif |
||||
|
||||
/* PHY and MIB routines */ |
||||
static bool ethernet_phy_reset(ETH_PORT eth_port_num); |
||||
|
||||
static bool eth_port_write_smi_reg(ETH_PORT eth_port_num, |
||||
unsigned int phy_reg, |
||||
unsigned int value); |
||||
|
||||
static bool eth_port_read_smi_reg(ETH_PORT eth_port_num, |
||||
unsigned int phy_reg, |
||||
unsigned int* value); |
||||
|
||||
static void eth_clear_mib_counters(ETH_PORT eth_port_num); |
||||
|
||||
/* Port data flow control routines */ |
||||
static ETH_FUNC_RET_STATUS eth_port_send (ETH_PORT_INFO *p_eth_port_ctrl, |
||||
ETH_QUEUE tx_queue, |
||||
PKT_INFO *p_pkt_info); |
||||
static ETH_FUNC_RET_STATUS eth_tx_return_desc(ETH_PORT_INFO *p_eth_port_ctrl, |
||||
ETH_QUEUE tx_queue, |
||||
PKT_INFO *p_pkt_info); |
||||
static ETH_FUNC_RET_STATUS eth_port_receive (ETH_PORT_INFO *p_eth_port_ctrl, |
||||
ETH_QUEUE rx_queue, |
||||
PKT_INFO *p_pkt_info); |
||||
static ETH_FUNC_RET_STATUS eth_rx_return_buff(ETH_PORT_INFO *p_eth_port_ctrl, |
||||
ETH_QUEUE rx_queue, |
||||
PKT_INFO *p_pkt_info); |
||||
|
||||
|
||||
static bool ether_init_tx_desc_ring(ETH_PORT_INFO *p_eth_port_ctrl, |
||||
ETH_QUEUE tx_queue, |
||||
int tx_desc_num, |
||||
int tx_buff_size, |
||||
unsigned int tx_desc_base_addr, |
||||
unsigned int tx_buff_base_addr); |
||||
|
||||
static bool ether_init_rx_desc_ring(ETH_PORT_INFO *p_eth_port_ctrl, |
||||
ETH_QUEUE rx_queue, |
||||
int rx_desc_num, |
||||
int rx_buff_size, |
||||
unsigned int rx_desc_base_addr, |
||||
unsigned int rx_buff_base_addr); |
||||
|
||||
#endif /* MV64360_ETH_ */ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,961 @@ |
||||
/*
|
||||
* (C) Copyright 2000 |
||||
* 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 |
||||
* |
||||
*/ |
||||
/* PCI.c - PCI functions */ |
||||
|
||||
|
||||
#include <common.h> |
||||
#ifdef CONFIG_PCI |
||||
#include <pci.h> |
||||
|
||||
#ifdef CONFIG_PCI_PNP |
||||
void pciauto_config_init(struct pci_controller *hose); |
||||
int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned int *bar); |
||||
#endif |
||||
|
||||
#include "../../Marvell/include/pci.h" |
||||
|
||||
#undef DEBUG |
||||
#undef IDE_SET_NATIVE_MODE |
||||
static unsigned int local_buses[] = { 0, 0 }; |
||||
|
||||
static const unsigned char pci_irq_swizzle[2][PCI_MAX_DEVICES] = { |
||||
{0, 0, 0, 0, 0, 0, 0, 27, 27, [9 ... PCI_MAX_DEVICES - 1] = 0 }, |
||||
{0, 0, 0, 0, 0, 0, 0, 29, 29, [9 ... PCI_MAX_DEVICES - 1] = 0 }, |
||||
}; |
||||
|
||||
|
||||
#ifdef DEBUG |
||||
static const unsigned int pci_bus_list[] = { PCI_0_MODE, PCI_1_MODE }; |
||||
static void gt_pci_bus_mode_display (PCI_HOST host) |
||||
{ |
||||
unsigned int mode; |
||||
|
||||
|
||||
mode = (GTREGREAD (pci_bus_list[host]) & (BIT4 | BIT5)) >> 4; |
||||
switch (mode) { |
||||
case 0: |
||||
printf ("PCI %d bus mode: Conventional PCI\n", host); |
||||
break; |
||||
case 1: |
||||
printf ("PCI %d bus mode: 66 Mhz PCIX\n", host); |
||||
break; |
||||
case 2: |
||||
printf ("PCI %d bus mode: 100 Mhz PCIX\n", host); |
||||
break; |
||||
case 3: |
||||
printf ("PCI %d bus mode: 133 Mhz PCIX\n", host); |
||||
break; |
||||
default: |
||||
printf ("Unknown BUS %d\n", mode); |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
static const unsigned int pci_p2p_configuration_reg[] = { |
||||
PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION |
||||
}; |
||||
|
||||
static const unsigned int pci_configuration_address[] = { |
||||
PCI_0CONFIGURATION_ADDRESS, PCI_1CONFIGURATION_ADDRESS |
||||
}; |
||||
|
||||
static const unsigned int pci_configuration_data[] = { |
||||
PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER, |
||||
PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER |
||||
}; |
||||
|
||||
static const unsigned int pci_error_cause_reg[] = { |
||||
PCI_0ERROR_CAUSE, PCI_1ERROR_CAUSE |
||||
}; |
||||
|
||||
static const unsigned int pci_arbiter_control[] = { |
||||
PCI_0ARBITER_CONTROL, PCI_1ARBITER_CONTROL |
||||
}; |
||||
|
||||
static const unsigned int pci_address_space_en[] = { |
||||
PCI_0_BASE_ADDR_REG_ENABLE, PCI_1_BASE_ADDR_REG_ENABLE |
||||
}; |
||||
|
||||
static const unsigned int pci_snoop_control_base_0_low[] = { |
||||
PCI_0SNOOP_CONTROL_BASE_0_LOW, PCI_1SNOOP_CONTROL_BASE_0_LOW |
||||
}; |
||||
static const unsigned int pci_snoop_control_top_0[] = { |
||||
PCI_0SNOOP_CONTROL_TOP_0, PCI_1SNOOP_CONTROL_TOP_0 |
||||
}; |
||||
|
||||
static const unsigned int pci_access_control_base_0_low[] = { |
||||
PCI_0ACCESS_CONTROL_BASE_0_LOW, PCI_1ACCESS_CONTROL_BASE_0_LOW |
||||
}; |
||||
static const unsigned int pci_access_control_top_0[] = { |
||||
PCI_0ACCESS_CONTROL_TOP_0, PCI_1ACCESS_CONTROL_TOP_0 |
||||
}; |
||||
|
||||
static const unsigned int pci_scs_bank_size[2][4] = { |
||||
{PCI_0SCS_0_BANK_SIZE, PCI_0SCS_1_BANK_SIZE, |
||||
PCI_0SCS_2_BANK_SIZE, PCI_0SCS_3_BANK_SIZE}, |
||||
{PCI_1SCS_0_BANK_SIZE, PCI_1SCS_1_BANK_SIZE, |
||||
PCI_1SCS_2_BANK_SIZE, PCI_1SCS_3_BANK_SIZE} |
||||
}; |
||||
|
||||
static const unsigned int pci_p2p_configuration[] = { |
||||
PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION |
||||
}; |
||||
|
||||
|
||||
/********************************************************************
|
||||
* pciWriteConfigReg - Write to a PCI configuration register |
||||
* - Make sure the GT is configured as a master before writing |
||||
* to another device on the PCI. |
||||
* - The function takes care of Big/Little endian conversion. |
||||
* |
||||
* |
||||
* Inputs: unsigned int regOffset: The register offset as it apears in the GT spec |
||||
* (or any other PCI device spec) |
||||
* pciDevNum: The device number needs to be addressed. |
||||
* |
||||
* Configuration Address 0xCF8: |
||||
* |
||||
* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number |
||||
* |congif|Reserved| Bus |Device|Function|Register|00| |
||||
* |Enable| |Number|Number| Number | Number | | <=field Name |
||||
* |
||||
*********************************************************************/ |
||||
void pciWriteConfigReg (PCI_HOST host, unsigned int regOffset, |
||||
unsigned int pciDevNum, unsigned int data) |
||||
{ |
||||
volatile unsigned int DataForAddrReg; |
||||
unsigned int functionNum; |
||||
unsigned int busNum = 0; |
||||
unsigned int addr; |
||||
|
||||
if (pciDevNum > 32) /* illegal device Number */ |
||||
return; |
||||
if (pciDevNum == SELF) { /* configure our configuration space. */ |
||||
pciDevNum = |
||||
(GTREGREAD (pci_p2p_configuration_reg[host]) >> 24) & |
||||
0x1f; |
||||
busNum = GTREGREAD (pci_p2p_configuration_reg[host]) & |
||||
0xff0000; |
||||
} |
||||
functionNum = regOffset & 0x00000700; |
||||
pciDevNum = pciDevNum << 11; |
||||
regOffset = regOffset & 0xfc; |
||||
DataForAddrReg = |
||||
(regOffset | pciDevNum | functionNum | busNum) | BIT31; |
||||
GT_REG_WRITE (pci_configuration_address[host], DataForAddrReg); |
||||
GT_REG_READ (pci_configuration_address[host], &addr); |
||||
if (addr != DataForAddrReg) |
||||
return; |
||||
GT_REG_WRITE (pci_configuration_data[host], data); |
||||
} |
||||
|
||||
/********************************************************************
|
||||
* pciReadConfigReg - Read from a PCI0 configuration register |
||||
* - Make sure the GT is configured as a master before reading |
||||
* from another device on the PCI. |
||||
* - The function takes care of Big/Little endian conversion. |
||||
* INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI |
||||
* spec) |
||||
* pciDevNum: The device number needs to be addressed. |
||||
* RETURNS: data , if the data == 0xffffffff check the master abort bit in the |
||||
* cause register to make sure the data is valid |
||||
* |
||||
* Configuration Address 0xCF8: |
||||
* |
||||
* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number |
||||
* |congif|Reserved| Bus |Device|Function|Register|00| |
||||
* |Enable| |Number|Number| Number | Number | | <=field Name |
||||
* |
||||
*********************************************************************/ |
||||
unsigned int pciReadConfigReg (PCI_HOST host, unsigned int regOffset, |
||||
unsigned int pciDevNum) |
||||
{ |
||||
volatile unsigned int DataForAddrReg; |
||||
unsigned int data; |
||||
unsigned int functionNum; |
||||
unsigned int busNum = 0; |
||||
|
||||
if (pciDevNum > 32) /* illegal device Number */ |
||||
return 0xffffffff; |
||||
if (pciDevNum == SELF) { /* configure our configuration space. */ |
||||
pciDevNum = |
||||
(GTREGREAD (pci_p2p_configuration_reg[host]) >> 24) & |
||||
0x1f; |
||||
busNum = GTREGREAD (pci_p2p_configuration_reg[host]) & |
||||
0xff0000; |
||||
} |
||||
functionNum = regOffset & 0x00000700; |
||||
pciDevNum = pciDevNum << 11; |
||||
regOffset = regOffset & 0xfc; |
||||
DataForAddrReg = |
||||
(regOffset | pciDevNum | functionNum | busNum) | BIT31; |
||||
GT_REG_WRITE (pci_configuration_address[host], DataForAddrReg); |
||||
GT_REG_READ (pci_configuration_address[host], &data); |
||||
if (data != DataForAddrReg) |
||||
return 0xffffffff; |
||||
GT_REG_READ (pci_configuration_data[host], &data); |
||||
return data; |
||||
} |
||||
|
||||
/********************************************************************
|
||||
* pciOverBridgeWriteConfigReg - Write to a PCI configuration register where |
||||
* the agent is placed on another Bus. For more |
||||
* information read P2P in the PCI spec. |
||||
* |
||||
* Inputs: unsigned int regOffset - The register offset as it apears in the |
||||
* GT spec (or any other PCI device spec). |
||||
* unsigned int pciDevNum - The device number needs to be addressed. |
||||
* unsigned int busNum - On which bus does the Target agent connect |
||||
* to. |
||||
* unsigned int data - data to be written. |
||||
* |
||||
* Configuration Address 0xCF8: |
||||
* |
||||
* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number |
||||
* |congif|Reserved| Bus |Device|Function|Register|01| |
||||
* |Enable| |Number|Number| Number | Number | | <=field Name |
||||
* |
||||
* The configuration Address is configure as type-I (bits[1:0] = '01') due to |
||||
* PCI spec referring to P2P. |
||||
* |
||||
*********************************************************************/ |
||||
void pciOverBridgeWriteConfigReg (PCI_HOST host, |
||||
unsigned int regOffset, |
||||
unsigned int pciDevNum, |
||||
unsigned int busNum, unsigned int data) |
||||
{ |
||||
unsigned int DataForReg; |
||||
unsigned int functionNum; |
||||
|
||||
functionNum = regOffset & 0x00000700; |
||||
pciDevNum = pciDevNum << 11; |
||||
regOffset = regOffset & 0xff; |
||||
busNum = busNum << 16; |
||||
if (pciDevNum == SELF) { /* This board */ |
||||
DataForReg = (regOffset | pciDevNum | functionNum) | BIT0; |
||||
} else { |
||||
DataForReg = (regOffset | pciDevNum | functionNum | busNum) | |
||||
BIT31 | BIT0; |
||||
} |
||||
GT_REG_WRITE (pci_configuration_address[host], DataForReg); |
||||
GT_REG_WRITE (pci_configuration_data[host], data); |
||||
} |
||||
|
||||
|
||||
/********************************************************************
|
||||
* pciOverBridgeReadConfigReg - Read from a PCIn configuration register where |
||||
* the agent target locate on another PCI bus. |
||||
* - Make sure the GT is configured as a master |
||||
* before reading from another device on the PCI. |
||||
* - The function takes care of Big/Little endian |
||||
* conversion. |
||||
* INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI |
||||
* spec). (configuration register offset.) |
||||
* pciDevNum: The device number needs to be addressed. |
||||
* busNum: the Bus number where the agent is place. |
||||
* RETURNS: data , if the data == 0xffffffff check the master abort bit in the |
||||
* cause register to make sure the data is valid |
||||
* |
||||
* Configuration Address 0xCF8: |
||||
* |
||||
* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number |
||||
* |congif|Reserved| Bus |Device|Function|Register|01| |
||||
* |Enable| |Number|Number| Number | Number | | <=field Name |
||||
* |
||||
*********************************************************************/ |
||||
unsigned int pciOverBridgeReadConfigReg (PCI_HOST host, |
||||
unsigned int regOffset, |
||||
unsigned int pciDevNum, |
||||
unsigned int busNum) |
||||
{ |
||||
unsigned int DataForReg; |
||||
unsigned int data; |
||||
unsigned int functionNum; |
||||
|
||||
functionNum = regOffset & 0x00000700; |
||||
pciDevNum = pciDevNum << 11; |
||||
regOffset = regOffset & 0xff; |
||||
busNum = busNum << 16; |
||||
if (pciDevNum == SELF) { /* This board */ |
||||
DataForReg = (regOffset | pciDevNum | functionNum) | BIT31; |
||||
} else { /* agent on another bus */ |
||||
|
||||
DataForReg = (regOffset | pciDevNum | functionNum | busNum) | |
||||
BIT0 | BIT31; |
||||
} |
||||
GT_REG_WRITE (pci_configuration_address[host], DataForReg); |
||||
GT_REG_READ (pci_configuration_data[host], &data); |
||||
return data; |
||||
} |
||||
|
||||
|
||||
/********************************************************************
|
||||
* pciGetRegOffset - Gets the register offset for this region config. |
||||
* |
||||
* INPUT: Bus, Region - The bus and region we ask for its base address. |
||||
* OUTPUT: N/A |
||||
* RETURNS: PCI register base address |
||||
*********************************************************************/ |
||||
static unsigned int pciGetRegOffset (PCI_HOST host, PCI_REGION region) |
||||
{ |
||||
switch (host) { |
||||
case PCI_HOST0: |
||||
switch (region) { |
||||
case PCI_IO: |
||||
return PCI_0I_O_LOW_DECODE_ADDRESS; |
||||
case PCI_REGION0: |
||||
return PCI_0MEMORY0_LOW_DECODE_ADDRESS; |
||||
case PCI_REGION1: |
||||
return PCI_0MEMORY1_LOW_DECODE_ADDRESS; |
||||
case PCI_REGION2: |
||||
return PCI_0MEMORY2_LOW_DECODE_ADDRESS; |
||||
case PCI_REGION3: |
||||
return PCI_0MEMORY3_LOW_DECODE_ADDRESS; |
||||
} |
||||
case PCI_HOST1: |
||||
switch (region) { |
||||
case PCI_IO: |
||||
return PCI_1I_O_LOW_DECODE_ADDRESS; |
||||
case PCI_REGION0: |
||||
return PCI_1MEMORY0_LOW_DECODE_ADDRESS; |
||||
case PCI_REGION1: |
||||
return PCI_1MEMORY1_LOW_DECODE_ADDRESS; |
||||
case PCI_REGION2: |
||||
return PCI_1MEMORY2_LOW_DECODE_ADDRESS; |
||||
case PCI_REGION3: |
||||
return PCI_1MEMORY3_LOW_DECODE_ADDRESS; |
||||
} |
||||
} |
||||
return PCI_0MEMORY0_LOW_DECODE_ADDRESS; |
||||
} |
||||
|
||||
static unsigned int pciGetRemapOffset (PCI_HOST host, PCI_REGION region) |
||||
{ |
||||
switch (host) { |
||||
case PCI_HOST0: |
||||
switch (region) { |
||||
case PCI_IO: |
||||
return PCI_0I_O_ADDRESS_REMAP; |
||||
case PCI_REGION0: |
||||
return PCI_0MEMORY0_ADDRESS_REMAP; |
||||
case PCI_REGION1: |
||||
return PCI_0MEMORY1_ADDRESS_REMAP; |
||||
case PCI_REGION2: |
||||
return PCI_0MEMORY2_ADDRESS_REMAP; |
||||
case PCI_REGION3: |
||||
return PCI_0MEMORY3_ADDRESS_REMAP; |
||||
} |
||||
case PCI_HOST1: |
||||
switch (region) { |
||||
case PCI_IO: |
||||
return PCI_1I_O_ADDRESS_REMAP; |
||||
case PCI_REGION0: |
||||
return PCI_1MEMORY0_ADDRESS_REMAP; |
||||
case PCI_REGION1: |
||||
return PCI_1MEMORY1_ADDRESS_REMAP; |
||||
case PCI_REGION2: |
||||
return PCI_1MEMORY2_ADDRESS_REMAP; |
||||
case PCI_REGION3: |
||||
return PCI_1MEMORY3_ADDRESS_REMAP; |
||||
} |
||||
} |
||||
return PCI_0MEMORY0_ADDRESS_REMAP; |
||||
} |
||||
|
||||
/********************************************************************
|
||||
* pciGetBaseAddress - Gets the base address of a PCI. |
||||
* - If the PCI size is 0 then this base address has no meaning!!! |
||||
* |
||||
* |
||||
* INPUT: Bus, Region - The bus and region we ask for its base address. |
||||
* OUTPUT: N/A |
||||
* RETURNS: PCI base address. |
||||
*********************************************************************/ |
||||
unsigned int pciGetBaseAddress (PCI_HOST host, PCI_REGION region) |
||||
{ |
||||
unsigned int regBase; |
||||
unsigned int regEnd; |
||||
unsigned int regOffset = pciGetRegOffset (host, region); |
||||
|
||||
GT_REG_READ (regOffset, ®Base); |
||||
GT_REG_READ (regOffset + 8, ®End); |
||||
|
||||
if (regEnd <= regBase) |
||||
return 0xffffffff; /* ERROR !!! */ |
||||
|
||||
regBase = regBase << 16; |
||||
return regBase; |
||||
} |
||||
|
||||
bool pciMapSpace (PCI_HOST host, PCI_REGION region, unsigned int remapBase, |
||||
unsigned int bankBase, unsigned int bankLength) |
||||
{ |
||||
unsigned int low = 0xfff; |
||||
unsigned int high = 0x0; |
||||
unsigned int regOffset = pciGetRegOffset (host, region); |
||||
unsigned int remapOffset = pciGetRemapOffset (host, region); |
||||
|
||||
if (bankLength != 0) { |
||||
low = (bankBase >> 16) & 0xffff; |
||||
high = ((bankBase + bankLength) >> 16) - 1; |
||||
} |
||||
|
||||
GT_REG_WRITE (regOffset, low | (1 << 24)); /* no swapping */ |
||||
GT_REG_WRITE (regOffset + 8, high); |
||||
|
||||
if (bankLength != 0) { /* must do AFTER writing maps */ |
||||
GT_REG_WRITE (remapOffset, remapBase >> 16); /* sorry, 32 bits only.
|
||||
dont support upper 32 |
||||
in this driver */ |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
unsigned int pciGetSpaceBase (PCI_HOST host, PCI_REGION region) |
||||
{ |
||||
unsigned int low; |
||||
unsigned int regOffset = pciGetRegOffset (host, region); |
||||
|
||||
GT_REG_READ (regOffset, &low); |
||||
return (low & 0xffff) << 16; |
||||
} |
||||
|
||||
unsigned int pciGetSpaceSize (PCI_HOST host, PCI_REGION region) |
||||
{ |
||||
unsigned int low, high; |
||||
unsigned int regOffset = pciGetRegOffset (host, region); |
||||
|
||||
GT_REG_READ (regOffset, &low); |
||||
GT_REG_READ (regOffset + 8, &high); |
||||
return ((high & 0xffff) + 1) << 16; |
||||
} |
||||
|
||||
|
||||
/* ronen - 7/Dec/03*/ |
||||
/********************************************************************
|
||||
* gtPciDisable/EnableInternalBAR - This function enable/disable PCI BARS. |
||||
* Inputs: one of the PCI BAR |
||||
*********************************************************************/ |
||||
void gtPciEnableInternalBAR (PCI_HOST host, PCI_INTERNAL_BAR pciBAR) |
||||
{ |
||||
RESET_REG_BITS (pci_address_space_en[host], BIT0 << pciBAR); |
||||
} |
||||
|
||||
void gtPciDisableInternalBAR (PCI_HOST host, PCI_INTERNAL_BAR pciBAR) |
||||
{ |
||||
SET_REG_BITS (pci_address_space_en[host], BIT0 << pciBAR); |
||||
} |
||||
|
||||
/********************************************************************
|
||||
* pciMapMemoryBank - Maps PCI_host memory bank "bank" for the slave. |
||||
* |
||||
* Inputs: base and size of PCI SCS |
||||
*********************************************************************/ |
||||
void pciMapMemoryBank (PCI_HOST host, MEMORY_BANK bank, |
||||
unsigned int pciDramBase, unsigned int pciDramSize) |
||||
{ |
||||
/*ronen different function for 3rd bank. */ |
||||
unsigned int offset = (bank < 2) ? bank * 8 : 0x100 + (bank - 2) * 8; |
||||
|
||||
pciDramBase = pciDramBase & 0xfffff000; |
||||
pciDramBase = pciDramBase | (pciReadConfigReg (host, |
||||
PCI_SCS_0_BASE_ADDRESS |
||||
+ offset, |
||||
SELF) & 0x00000fff); |
||||
pciWriteConfigReg (host, PCI_SCS_0_BASE_ADDRESS + offset, SELF, |
||||
pciDramBase); |
||||
if (pciDramSize == 0) |
||||
pciDramSize++; |
||||
GT_REG_WRITE (pci_scs_bank_size[host][bank], pciDramSize - 1); |
||||
gtPciEnableInternalBAR (host, bank); |
||||
} |
||||
|
||||
/********************************************************************
|
||||
* pciSetRegionFeatures - This function modifys one of the 8 regions with |
||||
* feature bits given as an input. |
||||
* - Be advised to check the spec before modifying them. |
||||
* Inputs: PCI_PROTECT_REGION region - one of the eight regions. |
||||
* unsigned int features - See file: pci.h there are defintion for those |
||||
* region features. |
||||
* unsigned int baseAddress - The region base Address. |
||||
* unsigned int topAddress - The region top Address. |
||||
* Returns: false if one of the parameters is erroneous true otherwise. |
||||
*********************************************************************/ |
||||
bool pciSetRegionFeatures (PCI_HOST host, PCI_ACCESS_REGIONS region, |
||||
unsigned int features, unsigned int baseAddress, |
||||
unsigned int regionLength) |
||||
{ |
||||
unsigned int accessLow; |
||||
unsigned int accessHigh; |
||||
unsigned int accessTop = baseAddress + regionLength; |
||||
|
||||
if (regionLength == 0) { /* close the region. */ |
||||
pciDisableAccessRegion (host, region); |
||||
return true; |
||||
} |
||||
/* base Address is store is bits [11:0] */ |
||||
accessLow = (baseAddress & 0xfff00000) >> 20; |
||||
/* All the features are update according to the defines in pci.h (to be on
|
||||
the safe side we disable bits: [11:0] */ |
||||
accessLow = accessLow | (features & 0xfffff000); |
||||
/* write to the Low Access Region register */ |
||||
GT_REG_WRITE (pci_access_control_base_0_low[host] + 0x10 * region, |
||||
accessLow); |
||||
|
||||
accessHigh = (accessTop & 0xfff00000) >> 20; |
||||
|
||||
/* write to the High Access Region register */ |
||||
GT_REG_WRITE (pci_access_control_top_0[host] + 0x10 * region, |
||||
accessHigh - 1); |
||||
return true; |
||||
} |
||||
|
||||
/********************************************************************
|
||||
* pciDisableAccessRegion - Disable The given Region by writing MAX size |
||||
* to its low Address and MIN size to its high Address. |
||||
* |
||||
* Inputs: PCI_ACCESS_REGIONS region - The region we to be Disabled. |
||||
* Returns: N/A. |
||||
*********************************************************************/ |
||||
void pciDisableAccessRegion (PCI_HOST host, PCI_ACCESS_REGIONS region) |
||||
{ |
||||
/* writing back the registers default values. */ |
||||
GT_REG_WRITE (pci_access_control_base_0_low[host] + 0x10 * region, |
||||
0x01001fff); |
||||
GT_REG_WRITE (pci_access_control_top_0[host] + 0x10 * region, 0); |
||||
} |
||||
|
||||
/********************************************************************
|
||||
* pciArbiterEnable - Enables PCI-0`s Arbitration mechanism. |
||||
* |
||||
* Inputs: N/A |
||||
* Returns: true. |
||||
*********************************************************************/ |
||||
bool pciArbiterEnable (PCI_HOST host) |
||||
{ |
||||
unsigned int regData; |
||||
|
||||
GT_REG_READ (pci_arbiter_control[host], ®Data); |
||||
GT_REG_WRITE (pci_arbiter_control[host], regData | BIT31); |
||||
return true; |
||||
} |
||||
|
||||
/********************************************************************
|
||||
* pciArbiterDisable - Disable PCI-0`s Arbitration mechanism. |
||||
* |
||||
* Inputs: N/A |
||||
* Returns: true |
||||
*********************************************************************/ |
||||
bool pciArbiterDisable (PCI_HOST host) |
||||
{ |
||||
unsigned int regData; |
||||
|
||||
GT_REG_READ (pci_arbiter_control[host], ®Data); |
||||
GT_REG_WRITE (pci_arbiter_control[host], regData & 0x7fffffff); |
||||
return true; |
||||
} |
||||
|
||||
/********************************************************************
|
||||
* pciSetArbiterAgentsPriority - Priority setup for the PCI agents (Hi or Low) |
||||
* |
||||
* Inputs: PCI_AGENT_PRIO internalAgent - priotity for internal agent. |
||||
* PCI_AGENT_PRIO externalAgent0 - priotity for external#0 agent. |
||||
* PCI_AGENT_PRIO externalAgent1 - priotity for external#1 agent. |
||||
* PCI_AGENT_PRIO externalAgent2 - priotity for external#2 agent. |
||||
* PCI_AGENT_PRIO externalAgent3 - priotity for external#3 agent. |
||||
* PCI_AGENT_PRIO externalAgent4 - priotity for external#4 agent. |
||||
* PCI_AGENT_PRIO externalAgent5 - priotity for external#5 agent. |
||||
* Returns: true |
||||
*********************************************************************/ |
||||
bool pciSetArbiterAgentsPriority (PCI_HOST host, PCI_AGENT_PRIO internalAgent, |
||||
PCI_AGENT_PRIO externalAgent0, |
||||
PCI_AGENT_PRIO externalAgent1, |
||||
PCI_AGENT_PRIO externalAgent2, |
||||
PCI_AGENT_PRIO externalAgent3, |
||||
PCI_AGENT_PRIO externalAgent4, |
||||
PCI_AGENT_PRIO externalAgent5) |
||||
{ |
||||
unsigned int regData; |
||||
unsigned int writeData; |
||||
|
||||
GT_REG_READ (pci_arbiter_control[host], ®Data); |
||||
writeData = (internalAgent << 7) + (externalAgent0 << 8) + |
||||
(externalAgent1 << 9) + (externalAgent2 << 10) + |
||||
(externalAgent3 << 11) + (externalAgent4 << 12) + |
||||
(externalAgent5 << 13); |
||||
regData = (regData & 0xffffc07f) | writeData; |
||||
GT_REG_WRITE (pci_arbiter_control[host], regData & regData); |
||||
return true; |
||||
} |
||||
|
||||
/********************************************************************
|
||||
* pciParkingDisable - Park on last option disable, with this function you can |
||||
* disable the park on last mechanism for each agent. |
||||
* disabling this option for all agents results parking |
||||
* on the internal master. |
||||
* |
||||
* Inputs: PCI_AGENT_PARK internalAgent - parking Disable for internal agent. |
||||
* PCI_AGENT_PARK externalAgent0 - parking Disable for external#0 agent. |
||||
* PCI_AGENT_PARK externalAgent1 - parking Disable for external#1 agent. |
||||
* PCI_AGENT_PARK externalAgent2 - parking Disable for external#2 agent. |
||||
* PCI_AGENT_PARK externalAgent3 - parking Disable for external#3 agent. |
||||
* PCI_AGENT_PARK externalAgent4 - parking Disable for external#4 agent. |
||||
* PCI_AGENT_PARK externalAgent5 - parking Disable for external#5 agent. |
||||
* Returns: true |
||||
*********************************************************************/ |
||||
bool pciParkingDisable (PCI_HOST host, PCI_AGENT_PARK internalAgent, |
||||
PCI_AGENT_PARK externalAgent0, |
||||
PCI_AGENT_PARK externalAgent1, |
||||
PCI_AGENT_PARK externalAgent2, |
||||
PCI_AGENT_PARK externalAgent3, |
||||
PCI_AGENT_PARK externalAgent4, |
||||
PCI_AGENT_PARK externalAgent5) |
||||
{ |
||||
unsigned int regData; |
||||
unsigned int writeData; |
||||
|
||||
GT_REG_READ (pci_arbiter_control[host], ®Data); |
||||
writeData = (internalAgent << 14) + (externalAgent0 << 15) + |
||||
(externalAgent1 << 16) + (externalAgent2 << 17) + |
||||
(externalAgent3 << 18) + (externalAgent4 << 19) + |
||||
(externalAgent5 << 20); |
||||
regData = (regData & ~(0x7f << 14)) | writeData; |
||||
GT_REG_WRITE (pci_arbiter_control[host], regData); |
||||
return true; |
||||
} |
||||
|
||||
/********************************************************************
|
||||
* pciEnableBrokenAgentDetection - A master is said to be broken if it fails to |
||||
* respond to grant assertion within a window specified in |
||||
* the input value: 'brokenValue'. |
||||
* |
||||
* Inputs: unsigned char brokenValue - A value which limits the Master to hold the |
||||
* grant without asserting frame. |
||||
* Returns: Error for illegal broken value otherwise true. |
||||
*********************************************************************/ |
||||
bool pciEnableBrokenAgentDetection (PCI_HOST host, unsigned char brokenValue) |
||||
{ |
||||
unsigned int data; |
||||
unsigned int regData; |
||||
|
||||
if (brokenValue > 0xf) |
||||
return false; /* brokenValue must be 4 bit */ |
||||
data = brokenValue << 3; |
||||
GT_REG_READ (pci_arbiter_control[host], ®Data); |
||||
regData = (regData & 0xffffff87) | data; |
||||
GT_REG_WRITE (pci_arbiter_control[host], regData | BIT1); |
||||
return true; |
||||
} |
||||
|
||||
/********************************************************************
|
||||
* pciDisableBrokenAgentDetection - This function disable the Broken agent |
||||
* Detection mechanism. |
||||
* NOTE: This operation may cause a dead lock on the |
||||
* pci0 arbitration. |
||||
* |
||||
* Inputs: N/A |
||||
* Returns: true. |
||||
*********************************************************************/ |
||||
bool pciDisableBrokenAgentDetection (PCI_HOST host) |
||||
{ |
||||
unsigned int regData; |
||||
|
||||
GT_REG_READ (pci_arbiter_control[host], ®Data); |
||||
regData = regData & 0xfffffffd; |
||||
GT_REG_WRITE (pci_arbiter_control[host], regData); |
||||
return true; |
||||
} |
||||
|
||||
/********************************************************************
|
||||
* pciP2PConfig - This function set the PCI_n P2P configurate. |
||||
* For more information on the P2P read PCI spec. |
||||
* |
||||
* Inputs: unsigned int SecondBusLow - Secondery PCI interface Bus Range Lower |
||||
* Boundry. |
||||
* unsigned int SecondBusHigh - Secondry PCI interface Bus Range upper |
||||
* Boundry. |
||||
* unsigned int busNum - The CPI bus number to which the PCI interface |
||||
* is connected. |
||||
* unsigned int devNum - The PCI interface's device number. |
||||
* |
||||
* Returns: true. |
||||
*********************************************************************/ |
||||
bool pciP2PConfig (PCI_HOST host, unsigned int SecondBusLow, |
||||
unsigned int SecondBusHigh, |
||||
unsigned int busNum, unsigned int devNum) |
||||
{ |
||||
unsigned int regData; |
||||
|
||||
regData = (SecondBusLow & 0xff) | ((SecondBusHigh & 0xff) << 8) | |
||||
((busNum & 0xff) << 16) | ((devNum & 0x1f) << 24); |
||||
GT_REG_WRITE (pci_p2p_configuration[host], regData); |
||||
return true; |
||||
} |
||||
|
||||
/********************************************************************
|
||||
* pciSetRegionSnoopMode - This function modifys one of the 4 regions which |
||||
* supports Cache Coherency in the PCI_n interface. |
||||
* Inputs: region - One of the four regions. |
||||
* snoopType - There is four optional Types: |
||||
* 1. No Snoop. |
||||
* 2. Snoop to WT region. |
||||
* 3. Snoop to WB region. |
||||
* 4. Snoop & Invalidate to WB region. |
||||
* baseAddress - Base Address of this region. |
||||
* regionLength - Region length. |
||||
* Returns: false if one of the parameters is wrong otherwise return true. |
||||
*********************************************************************/ |
||||
bool pciSetRegionSnoopMode (PCI_HOST host, PCI_SNOOP_REGION region, |
||||
PCI_SNOOP_TYPE snoopType, |
||||
unsigned int baseAddress, |
||||
unsigned int regionLength) |
||||
{ |
||||
unsigned int snoopXbaseAddress; |
||||
unsigned int snoopXtopAddress; |
||||
unsigned int data; |
||||
unsigned int snoopHigh = baseAddress + regionLength; |
||||
|
||||
if ((region > PCI_SNOOP_REGION3) || (snoopType > PCI_SNOOP_WB)) |
||||
return false; |
||||
snoopXbaseAddress = |
||||
pci_snoop_control_base_0_low[host] + 0x10 * region; |
||||
snoopXtopAddress = pci_snoop_control_top_0[host] + 0x10 * region; |
||||
if (regionLength == 0) { /* closing the region */ |
||||
GT_REG_WRITE (snoopXbaseAddress, 0x0000ffff); |
||||
GT_REG_WRITE (snoopXtopAddress, 0); |
||||
return true; |
||||
} |
||||
baseAddress = baseAddress & 0xfff00000; /* Granularity of 1MByte */ |
||||
data = (baseAddress >> 20) | snoopType << 12; |
||||
GT_REG_WRITE (snoopXbaseAddress, data); |
||||
snoopHigh = (snoopHigh & 0xfff00000) >> 20; |
||||
GT_REG_WRITE (snoopXtopAddress, snoopHigh - 1); |
||||
return true; |
||||
} |
||||
|
||||
static int gt_read_config_dword (struct pci_controller *hose, |
||||
pci_dev_t dev, int offset, u32 * value) |
||||
{ |
||||
int bus = PCI_BUS (dev); |
||||
|
||||
if ((bus == local_buses[0]) || (bus == local_buses[1])) { |
||||
*value = pciReadConfigReg ((PCI_HOST) hose->cfg_addr, offset, |
||||
PCI_DEV (dev)); |
||||
} else { |
||||
*value = pciOverBridgeReadConfigReg ((PCI_HOST) hose-> |
||||
cfg_addr, offset, |
||||
PCI_DEV (dev), bus); |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int gt_write_config_dword (struct pci_controller *hose, |
||||
pci_dev_t dev, int offset, u32 value) |
||||
{ |
||||
int bus = PCI_BUS (dev); |
||||
|
||||
if ((bus == local_buses[0]) || (bus == local_buses[1])) { |
||||
pciWriteConfigReg ((PCI_HOST) hose->cfg_addr, offset, |
||||
PCI_DEV (dev), value); |
||||
} else { |
||||
pciOverBridgeWriteConfigReg ((PCI_HOST) hose->cfg_addr, |
||||
offset, PCI_DEV (dev), bus, |
||||
value); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
static void gt_setup_ide (struct pci_controller *hose, |
||||
pci_dev_t dev, struct pci_config_table *entry) |
||||
{ |
||||
static const int ide_bar[] = { 8, 4, 8, 4, 0, 0 }; |
||||
u32 bar_response, bar_value; |
||||
int bar; |
||||
|
||||
for (bar = 0; bar < 6; bar++) { |
||||
/*ronen different function for 3rd bank. */ |
||||
unsigned int offset = |
||||
(bar < 2) ? bar * 8 : 0x100 + (bar - 2) * 8; |
||||
|
||||
pci_write_config_dword (dev, PCI_BASE_ADDRESS_0 + offset, |
||||
0x0); |
||||
pci_read_config_dword (dev, PCI_BASE_ADDRESS_0 + offset, |
||||
&bar_response); |
||||
|
||||
pciauto_region_allocate (bar_response & |
||||
PCI_BASE_ADDRESS_SPACE_IO ? hose-> |
||||
pci_io : hose->pci_mem, ide_bar[bar], |
||||
&bar_value); |
||||
|
||||
pci_write_config_dword (dev, PCI_BASE_ADDRESS_0 + bar * 4, |
||||
bar_value); |
||||
} |
||||
} |
||||
|
||||
|
||||
/* TODO BJW: Change this for DB64360. This was pulled from the EV64260 */ |
||||
/* and is curently not called *. */ |
||||
#if 0 |
||||
static void gt_fixup_irq (struct pci_controller *hose, pci_dev_t dev) |
||||
{ |
||||
unsigned char pin, irq; |
||||
|
||||
pci_read_config_byte (dev, PCI_INTERRUPT_PIN, &pin); |
||||
|
||||
if (pin == 1) { /* only allow INT A */ |
||||
irq = pci_irq_swizzle[(PCI_HOST) hose-> |
||||
cfg_addr][PCI_DEV (dev)]; |
||||
if (irq) |
||||
pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq); |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
struct pci_config_table gt_config_table[] = { |
||||
{PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE, |
||||
PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, gt_setup_ide}, |
||||
|
||||
{} |
||||
}; |
||||
|
||||
struct pci_controller pci0_hose = { |
||||
/* fixup_irq: gt_fixup_irq, */ |
||||
config_table:gt_config_table, |
||||
}; |
||||
|
||||
struct pci_controller pci1_hose = { |
||||
/* fixup_irq: gt_fixup_irq, */ |
||||
config_table:gt_config_table, |
||||
}; |
||||
|
||||
void pci_init_board (void) |
||||
{ |
||||
unsigned int command; |
||||
#ifdef CONFIG_PCI_PNP |
||||
unsigned int bar; |
||||
#endif |
||||
|
||||
#ifdef DEBUG |
||||
gt_pci_bus_mode_display (PCI_HOST0); |
||||
#endif |
||||
|
||||
pci0_hose.first_busno = 0; |
||||
pci0_hose.last_busno = 0xff; |
||||
local_buses[0] = pci0_hose.first_busno; |
||||
|
||||
/* PCI memory space */ |
||||
pci_set_region (pci0_hose.regions + 0, |
||||
CFG_PCI0_0_MEM_SPACE, |
||||
CFG_PCI0_0_MEM_SPACE, |
||||
CFG_PCI0_MEM_SIZE, PCI_REGION_MEM); |
||||
|
||||
/* PCI I/O space */ |
||||
pci_set_region (pci0_hose.regions + 1, |
||||
CFG_PCI0_IO_SPACE_PCI, |
||||
CFG_PCI0_IO_SPACE, CFG_PCI0_IO_SIZE, PCI_REGION_IO); |
||||
|
||||
pci_set_ops (&pci0_hose, |
||||
pci_hose_read_config_byte_via_dword, |
||||
pci_hose_read_config_word_via_dword, |
||||
gt_read_config_dword, |
||||
pci_hose_write_config_byte_via_dword, |
||||
pci_hose_write_config_word_via_dword, |
||||
gt_write_config_dword); |
||||
pci0_hose.region_count = 2; |
||||
|
||||
pci0_hose.cfg_addr = (unsigned int *) PCI_HOST0; |
||||
|
||||
pci_register_hose (&pci0_hose); |
||||
pciArbiterEnable (PCI_HOST0); |
||||
pciParkingDisable (PCI_HOST0, 1, 1, 1, 1, 1, 1, 1); |
||||
command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF); |
||||
command |= PCI_COMMAND_MASTER; |
||||
pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command); |
||||
command = pciReadConfigReg (PCI_HOST0, PCI_COMMAND, SELF); |
||||
command |= PCI_COMMAND_MEMORY; |
||||
pciWriteConfigReg (PCI_HOST0, PCI_COMMAND, SELF, command); |
||||
|
||||
#ifdef CONFIG_PCI_PNP |
||||
pciauto_config_init(&pci0_hose); |
||||
pciauto_region_allocate(pci0_hose.pci_io, 0x400, &bar); |
||||
#endif |
||||
#ifdef CONFIG_PCI_SCAN_SHOW |
||||
printf("PCI: Bus Dev VenId DevId Class Int\n"); |
||||
#endif |
||||
pci0_hose.last_busno = pci_hose_scan_bus (&pci0_hose, pci0_hose.first_busno); |
||||
|
||||
#ifdef DEBUG |
||||
gt_pci_bus_mode_display (PCI_HOST1); |
||||
#endif |
||||
pci1_hose.first_busno = pci0_hose.last_busno + 1; |
||||
pci1_hose.last_busno = 0xff; |
||||
pci1_hose.current_busno = pci1_hose.first_busno; |
||||
local_buses[1] = pci1_hose.first_busno; |
||||
|
||||
/* PCI memory space */ |
||||
pci_set_region (pci1_hose.regions + 0, |
||||
CFG_PCI1_0_MEM_SPACE, |
||||
CFG_PCI1_0_MEM_SPACE, |
||||
CFG_PCI1_MEM_SIZE, PCI_REGION_MEM); |
||||
|
||||
/* PCI I/O space */ |
||||
pci_set_region (pci1_hose.regions + 1, |
||||
CFG_PCI1_IO_SPACE_PCI, |
||||
CFG_PCI1_IO_SPACE, CFG_PCI1_IO_SIZE, PCI_REGION_IO); |
||||
|
||||
pci_set_ops (&pci1_hose, |
||||
pci_hose_read_config_byte_via_dword, |
||||
pci_hose_read_config_word_via_dword, |
||||
gt_read_config_dword, |
||||
pci_hose_write_config_byte_via_dword, |
||||
pci_hose_write_config_word_via_dword, |
||||
gt_write_config_dword); |
||||
|
||||
pci1_hose.region_count = 2; |
||||
|
||||
pci1_hose.cfg_addr = (unsigned int *) PCI_HOST1; |
||||
|
||||
pci_register_hose (&pci1_hose); |
||||
|
||||
pciArbiterEnable (PCI_HOST1); |
||||
pciParkingDisable (PCI_HOST1, 1, 1, 1, 1, 1, 1, 1); |
||||
|
||||
command = pciReadConfigReg (PCI_HOST1, PCI_COMMAND, SELF); |
||||
command |= PCI_COMMAND_MASTER; |
||||
pciWriteConfigReg (PCI_HOST1, PCI_COMMAND, SELF, command); |
||||
|
||||
#ifdef CONFIG_PCI_PNP |
||||
pciauto_config_init(&pci1_hose); |
||||
pciauto_region_allocate(pci1_hose.pci_io, 0x400, &bar); |
||||
#endif |
||||
pci1_hose.last_busno = pci_hose_scan_bus (&pci1_hose, pci1_hose.first_busno); |
||||
|
||||
command = pciReadConfigReg (PCI_HOST1, PCI_COMMAND, SELF); |
||||
command |= PCI_COMMAND_MEMORY; |
||||
pciWriteConfigReg (PCI_HOST1, PCI_COMMAND, SELF, command); |
||||
|
||||
} |
||||
#endif /* of CONFIG_PCI */ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,110 @@ |
||||
/*
|
||||
* (C) Copyright 2001 |
||||
* Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. |
||||
* |
||||
* modified for marvell db64360 eval board by |
||||
* Ingo Assmus <ingo.assmus@keymile.com> |
||||
*
|
||||
* modified for cpci750 board by |
||||
* Reinhard Arlt <reinhard.arlt@esd-electronics.com> |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
/*
|
||||
* serial.c - serial support for esd cpci750 board |
||||
*/ |
||||
|
||||
/* supports the MPSC */ |
||||
|
||||
#include <common.h> |
||||
#include <command.h> |
||||
#include "../../Marvell/include/memory.h" |
||||
#include "serial.h" |
||||
|
||||
|
||||
#include "mpsc.h" |
||||
|
||||
int serial_init (void) |
||||
{ |
||||
DECLARE_GLOBAL_DATA_PTR; |
||||
|
||||
mpsc_init (gd->baudrate); |
||||
|
||||
return (0); |
||||
} |
||||
|
||||
void serial_putc (const char c) |
||||
{ |
||||
if (c == '\n') |
||||
mpsc_putchar ('\r'); |
||||
|
||||
mpsc_putchar (c); |
||||
} |
||||
|
||||
int serial_getc (void) |
||||
{ |
||||
return mpsc_getchar (); |
||||
} |
||||
|
||||
int serial_tstc (void) |
||||
{ |
||||
return mpsc_test_char (); |
||||
} |
||||
|
||||
void serial_setbrg (void) |
||||
{ |
||||
DECLARE_GLOBAL_DATA_PTR; |
||||
|
||||
galbrg_set_baudrate (CONFIG_MPSC_PORT, gd->baudrate); |
||||
} |
||||
|
||||
|
||||
void serial_puts (const char *s) |
||||
{ |
||||
while (*s) { |
||||
serial_putc (*s++); |
||||
} |
||||
} |
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB) |
||||
void kgdb_serial_init (void) |
||||
{ |
||||
} |
||||
|
||||
void putDebugChar (int c) |
||||
{ |
||||
serial_putc (c); |
||||
} |
||||
|
||||
void putDebugStr (const char *str) |
||||
{ |
||||
serial_puts (str); |
||||
} |
||||
|
||||
int getDebugChar (void) |
||||
{ |
||||
return serial_getc (); |
||||
} |
||||
|
||||
void kgdb_interruptible (int yes) |
||||
{ |
||||
return; |
||||
} |
||||
#endif /* CFG_CMD_KGDB */ |
@ -0,0 +1,89 @@ |
||||
/*
|
||||
* (C) Copyright 2001 |
||||
* Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. |
||||
* |
||||
* modified for marvell db64360 eval board by |
||||
* Ingo Assmus <ingo.assmus@keymile.com> |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
/* serial.h - mostly useful for DUART serial_init in serial.c */ |
||||
|
||||
#ifndef __SERIAL_H__ |
||||
#define __SERIAL_H__ |
||||
|
||||
#if 0 |
||||
|
||||
#define B230400 1 |
||||
#define B115200 2 |
||||
#define B57600 4 |
||||
#define B38400 82 |
||||
#define B19200 163 |
||||
#define B9600 24 |
||||
#define B4800 651 |
||||
#define B2400 1302 |
||||
#define B1200 2604 |
||||
#define B600 5208 |
||||
#define B300 10417 |
||||
#define B150 20833 |
||||
#define B110 28409 |
||||
#define BDEFAULT B115200 |
||||
|
||||
/* this stuff is important to initialize
|
||||
the DUART channels */ |
||||
|
||||
#define Scale 0x01L /* distance between port addresses */ |
||||
#define COM1 0x000003f8 /* Keyboard */ |
||||
#define COM2 0x000002f8 /* Host */ |
||||
|
||||
|
||||
/* Port Definitions relative to base COM port addresses */ |
||||
#define DataIn (0x00*Scale) /* data input port */ |
||||
#define DataOut (0x00*Scale) /* data output port */ |
||||
#define BaudLsb (0x00*Scale) /* baud rate divisor least significant byte */ |
||||
#define BaudMsb (0x01*Scale) /* baud rate divisor most significant byte */ |
||||
#define Ier (0x01*Scale) /* interrupt enable register */ |
||||
#define Iir (0x02*Scale) /* interrupt identification register */ |
||||
#define Lcr (0x03*Scale) /* line control register */ |
||||
#define Mcr (0x04*Scale) /* modem control register */ |
||||
#define Lsr (0x05*Scale) /* line status register */ |
||||
#define Msr (0x06*Scale) /* modem status register */ |
||||
|
||||
/* Bit Definitions for above ports */ |
||||
#define LcrDlab 0x80 /* b7: enable baud rate divisor registers */ |
||||
#define LcrDflt 0x03 /* b6-0: no parity, 1 stop, 8 data */ |
||||
|
||||
#define McrRts 0x02 /* b1: request to send (I am ready to xmit) */ |
||||
#define McrDtr 0x01 /* b0: data terminal ready (I am alive ready to rcv) */ |
||||
#define McrDflt (McrRts|McrDtr) |
||||
|
||||
#define LsrTxD 0x6000 /* b5: transmit holding register empty (i.e. xmit OK!)*/ |
||||
/* b6: transmitter empty */ |
||||
#define LsrRxD 0x0100 /* b0: received data ready (i.e. got a byte!) */ |
||||
|
||||
#define MsrRi 0x0040 /* b6: ring indicator (other guy is ready to rcv) */ |
||||
#define MsrDsr 0x0020 /* b5: data set ready (other guy is alive ready to rcv */ |
||||
#define MsrCts 0x0010 /* b4: clear to send (other guy is ready to rcv) */ |
||||
|
||||
#define IerRda 0xf /* b0: Enable received data available interrupt */ |
||||
|
||||
#endif |
||||
|
||||
#endif /* __SERIAL_H__ */ |
@ -0,0 +1,763 @@ |
||||
/*
|
||||
* (C) Copyright 2002 |
||||
* Brad Kemp, Seranoa Networks, Brad.Kemp@seranoa.com |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <asm/processor.h> |
||||
#include <asm/cache.h> |
||||
|
||||
#undef DEBUG_FLASH |
||||
/*
|
||||
* This file implements a Common Flash Interface (CFI) driver for U-Boot. |
||||
* The width of the port and the width of the chips are determined at initialization. |
||||
* These widths are used to calculate the address for access CFI data structures. |
||||
* It has been tested on an Intel Strataflash implementation. |
||||
* |
||||
* References |
||||
* JEDEC Standard JESD68 - Common Flash Interface (CFI) |
||||
* JEDEC Standard JEP137-A Common Flash Interface (CFI) ID Codes |
||||
* Intel Application Note 646 Common Flash Interface (CFI) and Command Sets |
||||
* Intel 290667-008 3 Volt Intel StrataFlash Memory datasheet |
||||
* |
||||
* TODO |
||||
* Use Primary Extended Query table (PRI) and Alternate Algorithm Query Table (ALT) to determine if protection is available |
||||
* Add support for other command sets Use the PRI and ALT to determine command set |
||||
* Verify erase and program timeouts. |
||||
*/ |
||||
|
||||
#define FLASH_CMD_CFI 0x98 |
||||
#define FLASH_CMD_READ_ID 0x90 |
||||
#define FLASH_CMD_RESET 0xff |
||||
#define FLASH_CMD_BLOCK_ERASE 0x20 |
||||
#define FLASH_CMD_ERASE_CONFIRM 0xD0 |
||||
#define FLASH_CMD_WRITE 0x40 |
||||
#define FLASH_CMD_PROTECT 0x60 |
||||
#define FLASH_CMD_PROTECT_SET 0x01 |
||||
#define FLASH_CMD_PROTECT_CLEAR 0xD0 |
||||
#define FLASH_CMD_CLEAR_STATUS 0x50 |
||||
#define FLASH_CMD_WRITE_TO_BUFFER 0xE8 |
||||
#define FLASH_CMD_WRITE_BUFFER_CONFIRM 0xD0 |
||||
|
||||
#define FLASH_STATUS_DONE 0x80 |
||||
#define FLASH_STATUS_ESS 0x40 |
||||
#define FLASH_STATUS_ECLBS 0x20 |
||||
#define FLASH_STATUS_PSLBS 0x10 |
||||
#define FLASH_STATUS_VPENS 0x08 |
||||
#define FLASH_STATUS_PSS 0x04 |
||||
#define FLASH_STATUS_DPS 0x02 |
||||
#define FLASH_STATUS_R 0x01 |
||||
#define FLASH_STATUS_PROTECT 0x01 |
||||
|
||||
#define FLASH_OFFSET_CFI 0x55 |
||||
#define FLASH_OFFSET_CFI_RESP 0x10 |
||||
#define FLASH_OFFSET_WTOUT 0x1F |
||||
#define FLASH_OFFSET_WBTOUT 0x20 |
||||
#define FLASH_OFFSET_ETOUT 0x21 |
||||
#define FLASH_OFFSET_CETOUT 0x22 |
||||
#define FLASH_OFFSET_WMAX_TOUT 0x23 |
||||
#define FLASH_OFFSET_WBMAX_TOUT 0x24 |
||||
#define FLASH_OFFSET_EMAX_TOUT 0x25 |
||||
#define FLASH_OFFSET_CEMAX_TOUT 0x26 |
||||
#define FLASH_OFFSET_SIZE 0x27 |
||||
#define FLASH_OFFSET_INTERFACE 0x28 |
||||
#define FLASH_OFFSET_BUFFER_SIZE 0x2A |
||||
#define FLASH_OFFSET_NUM_ERASE_REGIONS 0x2C |
||||
#define FLASH_OFFSET_ERASE_REGIONS 0x2D |
||||
#define FLASH_OFFSET_PROTECT 0x02 |
||||
#define FLASH_OFFSET_USER_PROTECTION 0x85 |
||||
#define FLASH_OFFSET_INTEL_PROTECTION 0x81 |
||||
|
||||
|
||||
#define FLASH_MAN_CFI 0x01000000 |
||||
|
||||
|
||||
typedef union { |
||||
unsigned char c; |
||||
unsigned short w; |
||||
unsigned long l; |
||||
} cfiword_t; |
||||
|
||||
typedef union { |
||||
unsigned char * cp; |
||||
unsigned short *wp; |
||||
unsigned long *lp; |
||||
} cfiptr_t; |
||||
|
||||
#define NUM_ERASE_REGIONS 4 |
||||
|
||||
flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ |
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Functions |
||||
*/ |
||||
|
||||
|
||||
static void flash_add_byte(flash_info_t *info, cfiword_t * cword, uchar c); |
||||
static void flash_make_cmd(flash_info_t * info, uchar cmd, void * cmdbuf); |
||||
static void flash_write_cmd(flash_info_t * info, int sect, uchar offset, uchar cmd); |
||||
static int flash_isequal(flash_info_t * info, int sect, uchar offset, uchar cmd); |
||||
static int flash_isset(flash_info_t * info, int sect, uchar offset, uchar cmd); |
||||
static int flash_detect_cfi(flash_info_t * info); |
||||
static ulong flash_get_size (ulong base, int banknum); |
||||
static int flash_write_cfiword (flash_info_t *info, ulong dest, cfiword_t cword); |
||||
static int flash_full_status_check(flash_info_t * info, ulong sector, ulong tout, char * prompt); |
||||
#ifdef CFG_FLASH_USE_BUFFER_WRITE |
||||
static int flash_write_cfibuffer(flash_info_t * info, ulong dest, uchar * cp, int len); |
||||
#endif |
||||
/*-----------------------------------------------------------------------
|
||||
* create an address based on the offset and the port width |
||||
*/ |
||||
inline uchar * flash_make_addr(flash_info_t * info, int sect, int offset) |
||||
{ |
||||
return ((uchar *)(info->start[sect] + (offset * info->portwidth))); |
||||
} |
||||
/*-----------------------------------------------------------------------
|
||||
* read a character at a port width address |
||||
*/ |
||||
inline uchar flash_read_uchar(flash_info_t * info, uchar offset) |
||||
{ |
||||
uchar *cp; |
||||
cp = flash_make_addr(info, 0, offset); |
||||
return (cp[info->portwidth - 1]); |
||||
} |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* read a short word by swapping for ppc format. |
||||
*/ |
||||
ushort flash_read_ushort(flash_info_t * info, int sect, uchar offset) |
||||
{ |
||||
uchar * addr; |
||||
|
||||
addr = flash_make_addr(info, sect, offset); |
||||
return ((addr[(2*info->portwidth) - 1] << 8) | addr[info->portwidth - 1]); |
||||
|
||||
} |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* read a long word by picking the least significant byte of each maiximum |
||||
* port size word. Swap for ppc format. |
||||
*/ |
||||
ulong flash_read_long(flash_info_t * info, int sect, uchar offset) |
||||
{ |
||||
uchar * addr; |
||||
|
||||
addr = flash_make_addr(info, sect, offset); |
||||
return ( (addr[(2*info->portwidth) - 1] << 24 ) | (addr[(info->portwidth) -1] << 16) | |
||||
(addr[(4*info->portwidth) - 1] << 8) | addr[(3*info->portwidth) - 1]); |
||||
|
||||
} |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/ |
||||
unsigned long flash_init (void) |
||||
{ |
||||
unsigned long size; |
||||
int i; |
||||
unsigned long address; |
||||
|
||||
|
||||
/* The flash is positioned back to back, with the demultiplexing of the chip
|
||||
* based on the A24 address line. |
||||
* |
||||
*/ |
||||
|
||||
address = CFG_FLASH_BASE; |
||||
size = 0; |
||||
|
||||
/* Init: no FLASHes known */ |
||||
for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { |
||||
flash_info[i].flash_id = FLASH_UNKNOWN; |
||||
size += flash_info[i].size = flash_get_size(address, i); |
||||
address += CFG_FLASH_INCREMENT; |
||||
if (flash_info[i].flash_id == FLASH_UNKNOWN) { |
||||
printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",i, |
||||
flash_info[0].size, flash_info[i].size<<20); |
||||
} |
||||
} |
||||
|
||||
#if 0 /* test-only */
|
||||
/* Monitor protection ON by default */ |
||||
#if (CFG_MONITOR_BASE >= CFG_FLASH_BASE) |
||||
for(i=0; flash_info[0].start[i] < CFG_MONITOR_BASE+monitor_flash_len-1; i++) |
||||
(void)flash_real_protect(&flash_info[0], i, 1); |
||||
#endif |
||||
#endif |
||||
|
||||
return (size); |
||||
} |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/ |
||||
int flash_erase (flash_info_t *info, int s_first, int s_last) |
||||
{ |
||||
int rcode = 0; |
||||
int prot; |
||||
int sect; |
||||
|
||||
if( info->flash_id != FLASH_MAN_CFI) { |
||||
printf ("Can't erase unknown flash type - aborted\n"); |
||||
return 1; |
||||
} |
||||
if ((s_first < 0) || (s_first > s_last)) { |
||||
printf ("- no sectors to erase\n"); |
||||
return 1; |
||||
} |
||||
|
||||
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"); |
||||
} |
||||
|
||||
|
||||
for (sect = s_first; sect<=s_last; sect++) { |
||||
if (info->protect[sect] == 0) { /* not protected */ |
||||
flash_write_cmd(info, sect, 0, FLASH_CMD_CLEAR_STATUS); |
||||
flash_write_cmd(info, sect, 0, FLASH_CMD_BLOCK_ERASE); |
||||
flash_write_cmd(info, sect, 0, FLASH_CMD_ERASE_CONFIRM); |
||||
|
||||
if(flash_full_status_check(info, sect, info->erase_blk_tout, "erase")) { |
||||
rcode = 1; |
||||
} else |
||||
printf("."); |
||||
} |
||||
} |
||||
printf (" done\n"); |
||||
return rcode; |
||||
} |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/ |
||||
void flash_print_info (flash_info_t *info) |
||||
{ |
||||
int i; |
||||
|
||||
if (info->flash_id != FLASH_MAN_CFI) { |
||||
printf ("missing or unknown FLASH type\n"); |
||||
return; |
||||
} |
||||
|
||||
printf("CFI conformant FLASH (%d x %d)", |
||||
(info->portwidth << 3 ), (info->chipwidth << 3 )); |
||||
printf (" Size: %ld MB in %d Sectors\n", |
||||
info->size >> 20, info->sector_count); |
||||
printf(" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n", |
||||
info->erase_blk_tout, info->write_tout, info->buffer_write_tout, info->buffer_size); |
||||
|
||||
printf (" Sector Start Addresses:"); |
||||
for (i=0; i<info->sector_count; ++i) { |
||||
if ((i % 5) == 0) |
||||
printf ("\n"); |
||||
printf (" %08lX%5s", |
||||
info->start[i], |
||||
info->protect[i] ? " (RO)" : " " |
||||
); |
||||
} |
||||
printf ("\n"); |
||||
return; |
||||
} |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Copy memory to flash, returns: |
||||
* 0 - OK |
||||
* 1 - write timeout |
||||
* 2 - Flash not erased |
||||
*/ |
||||
int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) |
||||
{ |
||||
ulong wp; |
||||
ulong cp; |
||||
int aln; |
||||
cfiword_t cword; |
||||
int i, rc; |
||||
|
||||
/* get lower aligned address */ |
||||
wp = (addr & ~(info->portwidth - 1)); |
||||
|
||||
/* handle unaligned start */ |
||||
if((aln = addr - wp) != 0) { |
||||
cword.l = 0; |
||||
cp = wp; |
||||
for(i=0;i<aln; ++i, ++cp) |
||||
flash_add_byte(info, &cword, (*(uchar *)cp)); |
||||
|
||||
for(; (i< info->portwidth) && (cnt > 0) ; i++) { |
||||
flash_add_byte(info, &cword, *src++); |
||||
cnt--; |
||||
cp++; |
||||
} |
||||
for(; (cnt == 0) && (i < info->portwidth); ++i, ++cp) |
||||
flash_add_byte(info, &cword, (*(uchar *)cp)); |
||||
if((rc = flash_write_cfiword(info, wp, cword)) != 0) |
||||
return rc; |
||||
wp = cp; |
||||
} |
||||
|
||||
#ifdef CFG_FLASH_USE_BUFFER_WRITE |
||||
while(cnt >= info->portwidth) { |
||||
i = info->buffer_size > cnt? cnt: info->buffer_size; |
||||
if((rc = flash_write_cfibuffer(info, wp, src,i)) != ERR_OK) |
||||
return rc; |
||||
wp += i; |
||||
src += i; |
||||
cnt -=i; |
||||
} |
||||
#else |
||||
/* handle the aligned part */ |
||||
while(cnt >= info->portwidth) { |
||||
cword.l = 0; |
||||
for(i = 0; i < info->portwidth; i++) { |
||||
flash_add_byte(info, &cword, *src++); |
||||
} |
||||
if((rc = flash_write_cfiword(info, wp, cword)) != 0) |
||||
return rc; |
||||
wp += info->portwidth; |
||||
cnt -= info->portwidth; |
||||
} |
||||
#endif /* CFG_FLASH_USE_BUFFER_WRITE */ |
||||
if (cnt == 0) { |
||||
return (0); |
||||
} |
||||
|
||||
/*
|
||||
* handle unaligned tail bytes |
||||
*/ |
||||
cword.l = 0; |
||||
for (i=0, cp=wp; (i<info->portwidth) && (cnt>0); ++i, ++cp) { |
||||
flash_add_byte(info, &cword, *src++); |
||||
--cnt; |
||||
} |
||||
for (; i<info->portwidth; ++i, ++cp) { |
||||
flash_add_byte(info, & cword, (*(uchar *)cp)); |
||||
} |
||||
|
||||
return flash_write_cfiword(info, wp, cword); |
||||
} |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/ |
||||
int flash_real_protect(flash_info_t *info, long sector, int prot) |
||||
{ |
||||
int retcode = 0; |
||||
|
||||
flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS); |
||||
flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT); |
||||
if(prot) |
||||
flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_SET); |
||||
else |
||||
flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_CLEAR); |
||||
|
||||
if((retcode = flash_full_status_check(info, sector, info->erase_blk_tout, |
||||
prot?"protect":"unprotect")) == 0) { |
||||
|
||||
info->protect[sector] = prot; |
||||
/* Intel's unprotect unprotects all locking */ |
||||
if(prot == 0) { |
||||
int i; |
||||
for(i = 0 ; i<info->sector_count; i++) { |
||||
if(info->protect[i]) |
||||
flash_real_protect(info, i, 1); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return retcode; |
||||
} |
||||
/*-----------------------------------------------------------------------
|
||||
* wait for XSR.7 to be set. Time out with an error if it does not. |
||||
* This routine does not set the flash to read-array mode. |
||||
*/ |
||||
static int flash_status_check(flash_info_t * info, ulong sector, ulong tout, char * prompt) |
||||
{ |
||||
ulong start; |
||||
|
||||
/* Wait for command completion */ |
||||
start = get_timer (0); |
||||
while(!flash_isset(info, sector, 0, FLASH_STATUS_DONE)) { |
||||
if (get_timer(start) > info->erase_blk_tout) { |
||||
printf("Flash %s timeout at address %lx\n", prompt, info->start[sector]); |
||||
flash_write_cmd(info, sector, 0, FLASH_CMD_RESET); |
||||
return ERR_TIMOUT; |
||||
} |
||||
} |
||||
return ERR_OK; |
||||
} |
||||
/*-----------------------------------------------------------------------
|
||||
* Wait for XSR.7 to be set, if it times out print an error, otherwise do a full status check. |
||||
* This routine sets the flash to read-array mode. |
||||
*/ |
||||
static int flash_full_status_check(flash_info_t * info, ulong sector, ulong tout, char * prompt) |
||||
{ |
||||
int retcode; |
||||
retcode = flash_status_check(info, sector, tout, prompt); |
||||
if((retcode == ERR_OK) && !flash_isequal(info,sector, 0, FLASH_STATUS_DONE)) { |
||||
retcode = ERR_INVAL; |
||||
printf("Flash %s error at address %lx\n", prompt,info->start[sector]); |
||||
if(flash_isset(info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)){ |
||||
printf("Command Sequence Error.\n"); |
||||
} else if(flash_isset(info, sector, 0, FLASH_STATUS_ECLBS)){ |
||||
printf("Block Erase Error.\n"); |
||||
retcode = ERR_NOT_ERASED; |
||||
} else if (flash_isset(info, sector, 0, FLASH_STATUS_PSLBS)) { |
||||
printf("Locking Error\n"); |
||||
} |
||||
if(flash_isset(info, sector, 0, FLASH_STATUS_DPS)){ |
||||
printf("Block locked.\n"); |
||||
retcode = ERR_PROTECTED; |
||||
} |
||||
if(flash_isset(info, sector, 0, FLASH_STATUS_VPENS)) |
||||
printf("Vpp Low Error.\n"); |
||||
} |
||||
flash_write_cmd(info, sector, 0, FLASH_CMD_RESET); |
||||
return retcode; |
||||
} |
||||
/*-----------------------------------------------------------------------
|
||||
*/ |
||||
static void flash_add_byte(flash_info_t *info, cfiword_t * cword, uchar c) |
||||
{ |
||||
switch(info->portwidth) { |
||||
case FLASH_CFI_8BIT: |
||||
cword->c = c; |
||||
break; |
||||
case FLASH_CFI_16BIT: |
||||
cword->w = (cword->w << 8) | c; |
||||
break; |
||||
case FLASH_CFI_32BIT: |
||||
cword->l = (cword->l << 8) | c; |
||||
} |
||||
} |
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* make a proper sized command based on the port and chip widths |
||||
*/ |
||||
static void flash_make_cmd(flash_info_t * info, uchar cmd, void * cmdbuf) |
||||
{ |
||||
int i; |
||||
uchar *cp = (uchar *)cmdbuf; |
||||
for(i=0; i< info->portwidth; i++) |
||||
*cp++ = ((i+1) % info->chipwidth) ? '\0':cmd; |
||||
} |
||||
|
||||
/*
|
||||
* Write a proper sized command to the correct address |
||||
*/ |
||||
static void flash_write_cmd(flash_info_t * info, int sect, uchar offset, uchar cmd) |
||||
{ |
||||
|
||||
volatile cfiptr_t addr; |
||||
cfiword_t cword; |
||||
addr.cp = flash_make_addr(info, sect, offset); |
||||
flash_make_cmd(info, cmd, &cword); |
||||
switch(info->portwidth) { |
||||
case FLASH_CFI_8BIT: |
||||
*addr.cp = cword.c; |
||||
break; |
||||
case FLASH_CFI_16BIT: |
||||
*addr.wp = cword.w; |
||||
break; |
||||
case FLASH_CFI_32BIT: |
||||
*addr.lp = cword.l; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/ |
||||
static int flash_isequal(flash_info_t * info, int sect, uchar offset, uchar cmd) |
||||
{ |
||||
cfiptr_t cptr; |
||||
cfiword_t cword; |
||||
int retval; |
||||
cptr.cp = flash_make_addr(info, sect, offset); |
||||
flash_make_cmd(info, cmd, &cword); |
||||
switch(info->portwidth) { |
||||
case FLASH_CFI_8BIT: |
||||
retval = (cptr.cp[0] == cword.c); |
||||
break; |
||||
case FLASH_CFI_16BIT: |
||||
retval = (cptr.wp[0] == cword.w); |
||||
break; |
||||
case FLASH_CFI_32BIT: |
||||
retval = (cptr.lp[0] == cword.l); |
||||
break; |
||||
default: |
||||
retval = 0; |
||||
break; |
||||
} |
||||
return retval; |
||||
} |
||||
/*-----------------------------------------------------------------------
|
||||
*/ |
||||
static int flash_isset(flash_info_t * info, int sect, uchar offset, uchar cmd) |
||||
{ |
||||
cfiptr_t cptr; |
||||
cfiword_t cword; |
||||
int retval; |
||||
cptr.cp = flash_make_addr(info, sect, offset); |
||||
flash_make_cmd(info, cmd, &cword); |
||||
switch(info->portwidth) { |
||||
case FLASH_CFI_8BIT: |
||||
retval = ((cptr.cp[0] & cword.c) == cword.c); |
||||
break; |
||||
case FLASH_CFI_16BIT: |
||||
retval = ((cptr.wp[0] & cword.w) == cword.w); |
||||
break; |
||||
case FLASH_CFI_32BIT: |
||||
retval = ((cptr.lp[0] & cword.l) == cword.l); |
||||
break; |
||||
default: |
||||
retval = 0; |
||||
break; |
||||
} |
||||
return retval; |
||||
} |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* detect if flash is compatible with the Common Flash Interface (CFI) |
||||
* http://www.jedec.org/download/search/jesd68.pdf
|
||||
* |
||||
*/ |
||||
static int flash_detect_cfi(flash_info_t * info) |
||||
{ |
||||
|
||||
for(info->portwidth=FLASH_CFI_8BIT; info->portwidth <= FLASH_CFI_32BIT; |
||||
info->portwidth <<= 1) { |
||||
for(info->chipwidth =FLASH_CFI_BY8; |
||||
info->chipwidth <= info->portwidth; |
||||
info->chipwidth <<= 1) { |
||||
flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); |
||||
flash_write_cmd(info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI); |
||||
if(flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP,'Q') && |
||||
flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R') && |
||||
flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) |
||||
return 1; |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
/*
|
||||
* The following code cannot be run from FLASH! |
||||
* |
||||
*/ |
||||
static ulong flash_get_size (ulong base, int banknum) |
||||
{ |
||||
flash_info_t * info = &flash_info[banknum]; |
||||
int i, j; |
||||
int sect_cnt; |
||||
unsigned long sector; |
||||
unsigned long tmp; |
||||
int size_ratio = 0; |
||||
uchar num_erase_regions; |
||||
int erase_region_size; |
||||
int erase_region_count; |
||||
|
||||
info->start[0] = base; |
||||
|
||||
invalidate_dcache_range(base, base+0x400); |
||||
|
||||
if(flash_detect_cfi(info)){ |
||||
|
||||
size_ratio = info->portwidth / info->chipwidth; |
||||
num_erase_regions = flash_read_uchar(info, FLASH_OFFSET_NUM_ERASE_REGIONS); |
||||
|
||||
sect_cnt = 0; |
||||
sector = base; |
||||
for(i = 0 ; i < num_erase_regions; i++) { |
||||
if(i > NUM_ERASE_REGIONS) { |
||||
printf("%d erase regions found, only %d used\n", |
||||
num_erase_regions, NUM_ERASE_REGIONS); |
||||
break; |
||||
} |
||||
tmp = flash_read_long(info, 0, FLASH_OFFSET_ERASE_REGIONS); |
||||
erase_region_size = (tmp & 0xffff)? ((tmp & 0xffff) * 256): 128; |
||||
tmp >>= 16; |
||||
erase_region_count = (tmp & 0xffff) +1; |
||||
for(j = 0; j< erase_region_count; j++) { |
||||
info->start[sect_cnt] = sector; |
||||
sector += (erase_region_size * size_ratio); |
||||
info->protect[sect_cnt] = flash_isset(info, sect_cnt, FLASH_OFFSET_PROTECT, FLASH_STATUS_PROTECT); |
||||
sect_cnt++; |
||||
} |
||||
} |
||||
|
||||
info->sector_count = sect_cnt; |
||||
/* multiply the size by the number of chips */ |
||||
info->size = (1 << flash_read_uchar(info, FLASH_OFFSET_SIZE)) * size_ratio; |
||||
info->buffer_size = (1 << flash_read_ushort(info, 0, FLASH_OFFSET_BUFFER_SIZE)); |
||||
tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_ETOUT); |
||||
info->erase_blk_tout = (tmp * (1 << flash_read_uchar(info, FLASH_OFFSET_EMAX_TOUT))); |
||||
tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_WBTOUT); |
||||
info->buffer_write_tout = (tmp * (1 << flash_read_uchar(info, FLASH_OFFSET_WBMAX_TOUT))); |
||||
tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_WTOUT); |
||||
info->write_tout = (tmp * (1 << flash_read_uchar(info, FLASH_OFFSET_WMAX_TOUT)))/ 1000; |
||||
info->flash_id = FLASH_MAN_CFI; |
||||
} |
||||
|
||||
flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); |
||||
#ifdef DEBUG_FLASH |
||||
printf("portwidth=%d chipwidth=%d\n", info->portwidth, info->chipwidth); /* test-only */ |
||||
#endif |
||||
#ifdef DEBUG_FLASH |
||||
printf("found %d erase regions\n", num_erase_regions); |
||||
#endif |
||||
#ifdef DEBUG_FLASH |
||||
printf("size=%08x sectors=%08x \n", info->size, info->sector_count); |
||||
#endif |
||||
return(info->size); |
||||
} |
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/ |
||||
static int flash_write_cfiword (flash_info_t *info, ulong dest, cfiword_t cword) |
||||
{ |
||||
|
||||
cfiptr_t ctladdr; |
||||
cfiptr_t cptr; |
||||
int flag; |
||||
|
||||
ctladdr.cp = flash_make_addr(info, 0, 0); |
||||
cptr.cp = (uchar *)dest; |
||||
|
||||
|
||||
/* Check if Flash is (sufficiently) erased */ |
||||
switch(info->portwidth) { |
||||
case FLASH_CFI_8BIT: |
||||
flag = ((cptr.cp[0] & cword.c) == cword.c); |
||||
break; |
||||
case FLASH_CFI_16BIT: |
||||
flag = ((cptr.wp[0] & cword.w) == cword.w); |
||||
break; |
||||
case FLASH_CFI_32BIT: |
||||
flag = ((cptr.lp[0] & cword.l) == cword.l); |
||||
break; |
||||
default: |
||||
return 2; |
||||
} |
||||
if(!flag) |
||||
return 2; |
||||
|
||||
/* Disable interrupts which might cause a timeout here */ |
||||
flag = disable_interrupts(); |
||||
|
||||
flash_write_cmd(info, 0, 0, FLASH_CMD_CLEAR_STATUS); |
||||
flash_write_cmd(info, 0, 0, FLASH_CMD_WRITE); |
||||
|
||||
switch(info->portwidth) { |
||||
case FLASH_CFI_8BIT: |
||||
cptr.cp[0] = cword.c; |
||||
break; |
||||
case FLASH_CFI_16BIT: |
||||
cptr.wp[0] = cword.w; |
||||
break; |
||||
case FLASH_CFI_32BIT: |
||||
cptr.lp[0] = cword.l; |
||||
break; |
||||
} |
||||
|
||||
/* re-enable interrupts if necessary */ |
||||
if(flag) |
||||
enable_interrupts(); |
||||
|
||||
return flash_full_status_check(info, 0, info->write_tout, "write"); |
||||
} |
||||
|
||||
#ifdef CFG_FLASH_USE_BUFFER_WRITE |
||||
|
||||
/* loop through the sectors from the highest address
|
||||
* when the passed address is greater or equal to the sector address |
||||
* we have a match |
||||
*/ |
||||
static int find_sector(flash_info_t *info, ulong addr) |
||||
{ |
||||
int sector; |
||||
for(sector = info->sector_count - 1; sector >= 0; sector--) { |
||||
if(addr >= info->start[sector]) |
||||
break; |
||||
} |
||||
return sector; |
||||
} |
||||
|
||||
static int flash_write_cfibuffer(flash_info_t * info, ulong dest, uchar * cp, int len) |
||||
{ |
||||
|
||||
int sector; |
||||
int cnt; |
||||
int retcode; |
||||
volatile cfiptr_t src; |
||||
volatile cfiptr_t dst; |
||||
|
||||
src.cp = cp; |
||||
dst.cp = (uchar *)dest; |
||||
sector = find_sector(info, dest); |
||||
flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS); |
||||
flash_write_cmd(info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER); |
||||
if((retcode = flash_status_check(info, sector, info->buffer_write_tout, |
||||
"write to buffer")) == ERR_OK) { |
||||
switch(info->portwidth) { |
||||
case FLASH_CFI_8BIT: |
||||
cnt = len; |
||||
break; |
||||
case FLASH_CFI_16BIT: |
||||
cnt = len >> 1; |
||||
break; |
||||
case FLASH_CFI_32BIT: |
||||
cnt = len >> 2; |
||||
break; |
||||
default: |
||||
return ERR_INVAL; |
||||
break; |
||||
} |
||||
flash_write_cmd(info, sector, 0, (uchar)cnt-1); |
||||
while(cnt-- > 0) { |
||||
switch(info->portwidth) { |
||||
case FLASH_CFI_8BIT: |
||||
*dst.cp++ = *src.cp++; |
||||
break; |
||||
case FLASH_CFI_16BIT: |
||||
*dst.wp++ = *src.wp++; |
||||
break; |
||||
case FLASH_CFI_32BIT: |
||||
*dst.lp++ = *src.lp++; |
||||
break; |
||||
default: |
||||
return ERR_INVAL; |
||||
break; |
||||
} |
||||
} |
||||
flash_write_cmd(info, sector, 0, FLASH_CMD_WRITE_BUFFER_CONFIRM); |
||||
retcode = flash_full_status_check(info, sector, info->buffer_write_tout, |
||||
"buffer write"); |
||||
} |
||||
flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS); |
||||
return retcode; |
||||
} |
||||
#endif /* CFG_USE_FLASH_BUFFER_WRITE */ |
@ -0,0 +1,135 @@ |
||||
/* |
||||
* (C) Copyright 2001 |
||||
* Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. |
||||
* |
||||
* 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 |
||||
*/ |
||||
|
||||
/* |
||||
* u-boot.lds - linker script for U-Boot on the Galileo Eval Board. |
||||
*/ |
||||
|
||||
OUTPUT_ARCH(powerpc) |
||||
SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); |
||||
/* Do we need any of these for elf? |
||||
__DYNAMIC = 0; */ |
||||
SECTIONS |
||||
{ |
||||
/* Read-only sections, merged into text segment: */ |
||||
. = + SIZEOF_HEADERS; |
||||
.interp : { *(.interp) } |
||||
.hash : { *(.hash) } |
||||
.dynsym : { *(.dynsym) } |
||||
.dynstr : { *(.dynstr) } |
||||
.rel.text : { *(.rel.text) } |
||||
.rela.text : { *(.rela.text) } |
||||
.rel.data : { *(.rel.data) } |
||||
.rela.data : { *(.rela.data) } |
||||
.rel.rodata : { *(.rel.rodata) } |
||||
.rela.rodata : { *(.rela.rodata) } |
||||
.rel.got : { *(.rel.got) } |
||||
.rela.got : { *(.rela.got) } |
||||
.rel.ctors : { *(.rel.ctors) } |
||||
.rela.ctors : { *(.rela.ctors) } |
||||
.rel.dtors : { *(.rel.dtors) } |
||||
.rela.dtors : { *(.rela.dtors) } |
||||
.rel.bss : { *(.rel.bss) } |
||||
.rela.bss : { *(.rela.bss) } |
||||
.rel.plt : { *(.rel.plt) } |
||||
.rela.plt : { *(.rela.plt) } |
||||
.init : { *(.init) } |
||||
.plt : { *(.plt) } |
||||
.text : |
||||
{ |
||||
cpu/74xx_7xx/start.o (.text) |
||||
|
||||
/* store the environment in a seperate sector in the boot flash */ |
||||
/* . = env_offset; */ |
||||
/* common/environment.o(.text) */ |
||||
|
||||
*(.text) |
||||
*(.fixup) |
||||
*(.got1) |
||||
} |
||||
_etext = .; |
||||
PROVIDE (etext = .); |
||||
.rodata : |
||||
{ |
||||
*(.rodata) |
||||
*(.rodata1) |
||||
*(.rodata.str1.4) |
||||
} |
||||
.fini : { *(.fini) } =0 |
||||
.ctors : { *(.ctors) } |
||||
.dtors : { *(.dtors) } |
||||
|
||||
/* Read-write section, merged into data segment: */ |
||||
. = (. + 0x00FF) & 0xFFFFFF00; |
||||
_erotext = .; |
||||
PROVIDE (erotext = .); |
||||
.reloc : |
||||
{ |
||||
*(.got) |
||||
_GOT2_TABLE_ = .; |
||||
*(.got2) |
||||
_FIXUP_TABLE_ = .; |
||||
*(.fixup) |
||||
} |
||||
__got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; |
||||
__fixup_entries = (. - _FIXUP_TABLE_)>>2; |
||||
|
||||
.data : |
||||
{ |
||||
*(.data) |
||||
*(.data1) |
||||
*(.sdata) |
||||
*(.sdata2) |
||||
*(.dynamic) |
||||
CONSTRUCTORS |
||||
} |
||||
_edata = .; |
||||
PROVIDE (edata = .); |
||||
|
||||
__u_boot_cmd_start = .; |
||||
.u_boot_cmd : { *(.u_boot_cmd) } |
||||
__u_boot_cmd_end = .; |
||||
|
||||
|
||||
__start___ex_table = .; |
||||
__ex_table : { *(__ex_table) } |
||||
__stop___ex_table = .; |
||||
|
||||
. = ALIGN(256); |
||||
__init_begin = .; |
||||
.text.init : { *(.text.init) } |
||||
.data.init : { *(.data.init) } |
||||
. = ALIGN(256); |
||||
__init_end = .; |
||||
|
||||
__bss_start = .; |
||||
.bss : |
||||
{ |
||||
*(.sbss) *(.scommon) |
||||
*(.dynbss) |
||||
*(.bss) |
||||
*(COMMON) |
||||
} |
||||
_end = . ; |
||||
PROVIDE (end = .); |
||||
} |
Loading…
Reference in new issue