diff options
author | wdenk <wdenk> | 2004-06-07 23:46:25 +0000 |
---|---|---|
committer | wdenk <wdenk> | 2004-06-07 23:46:25 +0000 |
commit | 79fa88f3ede051ca860667d5397e6cdc7e74a6d0 (patch) | |
tree | a720e281e25d5846b9c05cb65e58e7e589591b70 /board | |
parent | cea655a224456d043192156fb2d44a0896194adc (diff) |
Patch by Pantelis Antoniou, 5 May 2004:
- Intracom board update.
- Add Codec POST.
Diffstat (limited to 'board')
-rw-r--r-- | board/netphone/flash.c | 23 | ||||
-rw-r--r-- | board/netphone/phone_console.c | 106 | ||||
-rw-r--r-- | board/netta/Makefile | 2 | ||||
-rw-r--r-- | board/netta/codec.c | 1475 | ||||
-rw-r--r-- | board/netta/dsp.c | 293 | ||||
-rw-r--r-- | board/netta/netta.c | 29 | ||||
-rw-r--r-- | board/netta2/Makefile | 40 | ||||
-rw-r--r-- | board/netta2/config.mk | 28 | ||||
-rw-r--r-- | board/netta2/flash.c | 506 | ||||
-rw-r--r-- | board/netta2/netta2.c | 664 | ||||
-rw-r--r-- | board/netta2/u-boot.lds | 138 | ||||
-rw-r--r-- | board/netta2/u-boot.lds.debug | 135 |
12 files changed, 3311 insertions, 128 deletions
diff --git a/board/netphone/flash.c b/board/netphone/flash.c index adbc28e1014..0c81140f238 100644 --- a/board/netphone/flash.c +++ b/board/netphone/flash.c @@ -87,21 +87,22 @@ unsigned long flash_init(void) #if CONFIG_NETPHONE_VERSION == 2 size1 = flash_get_size((vu_long *) FLASH_BASE4_PRELIM, &flash_info[1]); + if (size1 > 0) { + if (flash_info[1].flash_id == FLASH_UNKNOWN) + printf("## Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n", size1, size1 << 20); - if (flash_info[1].flash_id == FLASH_UNKNOWN && size1 > 0) { - printf("## Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n", size1, size1 << 20); - } - - /* Remap FLASH according to real size */ - memctl->memc_or4 = CFG_OR_TIMING_FLASH | (-size1 & 0xFFFF8000); - memctl->memc_br4 = (CFG_FLASH_BASE4 & BR_BA_MSK) | (memctl->memc_br4 & ~(BR_BA_MSK)); + /* Remap FLASH according to real size */ + memctl->memc_or4 = CFG_OR_TIMING_FLASH | (-size1 & 0xFFFF8000); + memctl->memc_br4 = (CFG_FLASH_BASE4 & BR_BA_MSK) | (memctl->memc_br4 & ~(BR_BA_MSK)); - /* Re-do sizing to get full correct info */ - size1 = flash_get_size((vu_long *) CFG_FLASH_BASE4, &flash_info[1]); + /* Re-do sizing to get full correct info */ + size1 = flash_get_size((vu_long *) CFG_FLASH_BASE4, &flash_info[1]); - flash_get_offsets(CFG_FLASH_BASE4, &flash_info[1]); + flash_get_offsets(CFG_FLASH_BASE4, &flash_info[1]); - size += size1; + size += size1; + } else + memctl->memc_br4 &= ~BR_V; #endif return (size); diff --git a/board/netphone/phone_console.c b/board/netphone/phone_console.c index c6a59af0c39..aa31ed3a70d 100644 --- a/board/netphone/phone_console.c +++ b/board/netphone/phone_console.c @@ -12,7 +12,7 @@ * * 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 + * 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 @@ -52,7 +52,7 @@ /*************************************************************************************************/ #define DISPLAY_BACKLIT_PORT ((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pcdat -#define DISPLAY_BACKLIT_MASK 0x0010 +#define DISPLAY_BACKLIT_MASK 0x0010 /*************************************************************************************************/ @@ -63,23 +63,23 @@ #define KP_IDLE_DELAY_HZ (CFG_HZ/2) /* key was released and idle */ #if CONFIG_NETPHONE_VERSION == 1 -#define KP_SPI_RXD_PORT (((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pcdat) -#define KP_SPI_RXD_MASK 0x0008 +#define KP_SPI_RXD_PORT (((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pcdat) +#define KP_SPI_RXD_MASK 0x0008 -#define KP_SPI_TXD_PORT (((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pcdat) -#define KP_SPI_TXD_MASK 0x0004 +#define KP_SPI_TXD_PORT (((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pcdat) +#define KP_SPI_TXD_MASK 0x0004 -#define KP_SPI_CLK_PORT (((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pcdat) -#define KP_SPI_CLK_MASK 0x0001 +#define KP_SPI_CLK_PORT (((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pcdat) +#define KP_SPI_CLK_MASK 0x0001 #elif CONFIG_NETPHONE_VERSION == 2 -#define KP_SPI_RXD_PORT (((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pbdat) -#define KP_SPI_RXD_MASK 0x00000008 +#define KP_SPI_RXD_PORT (((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pbdat) +#define KP_SPI_RXD_MASK 0x00000008 -#define KP_SPI_TXD_PORT (((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pbdat) -#define KP_SPI_TXD_MASK 0x00000004 +#define KP_SPI_TXD_PORT (((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pbdat) +#define KP_SPI_TXD_MASK 0x00000004 -#define KP_SPI_CLK_PORT (((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pbdat) -#define KP_SPI_CLK_MASK 0x00000002 +#define KP_SPI_CLK_PORT (((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pbdat) +#define KP_SPI_CLK_MASK 0x00000002 #endif #define KP_CS_PORT (((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pedat) @@ -115,8 +115,8 @@ KP_CS_PORT &= ~KP_CS_MASK; \ } while(0) -#define KP_ROWS 7 -#define KP_COLS 4 +#define KP_ROWS 7 +#define KP_COLS 4 #define KP_ROWS_MASK ((1 << KP_ROWS) - 1) #define KP_COLS_MASK ((1 << KP_COLS) - 1) @@ -124,29 +124,29 @@ #define SCAN 0 #define SCAN_FILTER 1 #define SCAN_COL 2 -#define SCAN_COL_FILTER 3 +#define SCAN_COL_FILTER 3 #define PRESSED 4 -#define KP_F1 0 /* leftmost dot (tab) */ -#define KP_F2 1 /* middle left dot */ -#define KP_F3 2 /* up */ -#define KP_F4 3 /* middle right dot */ -#define KP_F5 4 /* rightmost dot */ -#define KP_F6 5 /* C */ -#define KP_F7 6 /* left */ -#define KP_F8 7 /* down */ -#define KP_F9 8 /* right */ -#define KP_F10 9 /* enter */ -#define KP_F11 10 /* R */ -#define KP_F12 11 /* save */ -#define KP_F13 12 /* redial */ -#define KP_F14 13 /* speaker */ -#define KP_F15 14 /* unused */ -#define KP_F16 15 /* unused */ - -#define KP_RELEASE -1 /* key depressed */ -#define KP_FORCE -2 /* key was pressed for more than force hz */ -#define KP_IDLE -3 /* key was released and idle */ +#define KP_F1 0 /* leftmost dot (tab) */ +#define KP_F2 1 /* middle left dot */ +#define KP_F3 2 /* up */ +#define KP_F4 3 /* middle right dot */ +#define KP_F5 4 /* rightmost dot */ +#define KP_F6 5 /* C */ +#define KP_F7 6 /* left */ +#define KP_F8 7 /* down */ +#define KP_F9 8 /* right */ +#define KP_F10 9 /* enter */ +#define KP_F11 10 /* R */ +#define KP_F12 11 /* save */ +#define KP_F13 12 /* redial */ +#define KP_F14 13 /* speaker */ +#define KP_F15 14 /* unused */ +#define KP_F16 15 /* unused */ + +#define KP_RELEASE -1 /* key depressed */ +#define KP_FORCE -2 /* key was pressed for more than force hz */ +#define KP_IDLE -3 /* key was released and idle */ #define KP_1 '1' #define KP_2 '2' @@ -158,8 +158,8 @@ #define KP_8 '8' #define KP_9 '9' #define KP_0 '0' -#define KP_STAR '*' -#define KP_HASH '#' +#define KP_STAR '*' +#define KP_HASH '#' /*************************************************************************************************/ @@ -198,7 +198,7 @@ static const char *whspace = " 0\n"; /* per mode character select (for 2-9) */ static const char *digits_sel[2][8] = { { /* small */ - "abc2", /* 2 */ + "abc2", /* 2 */ "def3", /* 3 */ "ghi4", /* 4 */ "jkl5", /* 5 */ @@ -206,8 +206,8 @@ static const char *digits_sel[2][8] = { "pqrs7", /* 7 */ "tuv8", /* 8 */ "wxyz9", /* 9 */ - }, { /* capital */ - "ABC2", /* 2 */ + }, { /* capital */ + "ABC2", /* 2 */ "DEF3", /* 3 */ "GHI4", /* 4 */ "JKL5", /* 5 */ @@ -810,10 +810,10 @@ static void ensure_visible(int col, int row, int dx, int dy) /* move to easier to use vars */ - x1 = disp_col; y1 = disp_row; + x1 = disp_col; y1 = disp_row; x2 = x1 + width; y2 = y1 + height; - a1 = col; b1 = row; - a2 = a1 + dx; b2 = b1 + dy; + a1 = col; b1 = row; + a2 = a1 + dx; b2 = b1 + dy; /* printf("(%d,%d) - (%d,%d) : (%d, %d) - (%d, %d)\n", x1, y1, x2, y2, a1, b1, a2, b2); */ @@ -891,7 +891,7 @@ void phone_putc(const char c) blink_time = BLINK_HZ; switch (c) { - case '\a': /* ignore bell */ + case '\a': /* ignore bell */ case '\r': /* ignore carriage return */ break; @@ -900,7 +900,7 @@ void phone_putc(const char c) ensure_visible(curs_col, curs_row, 1, 1); break; - case 9: /* tab 8 */ + case 9: /* tab 8 */ /* move to tab */ i = curs_col; i |= 0x0008; @@ -1006,13 +1006,13 @@ unsigned int kp_get_col_mask(unsigned int row_mask) /**************************************************************************************/ static const int kp_scancodes[KP_ROWS * KP_COLS] = { - KP_F1, KP_F3, KP_F4, KP_F2, - KP_F6, KP_F8, KP_F9, KP_F7, - KP_1, KP_3, KP_F11, KP_2, - KP_4, KP_6, KP_F12, KP_5, - KP_7, KP_9, KP_F13, KP_8, + KP_F1, KP_F3, KP_F4, KP_F2, + KP_F6, KP_F8, KP_F9, KP_F7, + KP_1, KP_3, KP_F11, KP_2, + KP_4, KP_6, KP_F12, KP_5, + KP_7, KP_9, KP_F13, KP_8, KP_STAR, KP_HASH, KP_F14, KP_0, - KP_F5, KP_F15, KP_F16, KP_F10, + KP_F5, KP_F15, KP_F16, KP_F10, }; static const int kp_repeats[KP_ROWS * KP_COLS] = { diff --git a/board/netta/Makefile b/board/netta/Makefile index c89e4c58f13..68e24027a47 100644 --- a/board/netta/Makefile +++ b/board/netta/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = lib$(BOARD).a -OBJS = $(BOARD).o flash.o dsp.o +OBJS = $(BOARD).o flash.o dsp.o codec.o $(LIB): .depend $(OBJS) $(AR) crv $@ $(OBJS) diff --git a/board/netta/codec.c b/board/netta/codec.c new file mode 100644 index 00000000000..fb2dab81379 --- /dev/null +++ b/board/netta/codec.c @@ -0,0 +1,1475 @@ +/* + * CODEC + */ + +#include <common.h> +#include <post.h> + +#include "mpc8xx.h" + +/***********************************************/ + +#define MAX_DUSLIC 4 + +#define NUM_CHANNELS 2 +#define MAX_SLICS (MAX_DUSLIC * NUM_CHANNELS) + +/***********************************************/ + +#define SOP_READ_CH_0 0xC4 /* Read SOP Register for Channel A */ +#define SOP_READ_CH_1 0xCC /* Read SOP Register for Channel B */ +#define SOP_WRITE_CH_0 0x44 /* Write SOP Register for Channel A */ +#define SOP_WRITE_CH_1 0x4C /* Write SOP Register for Channel B */ + +#define COP_READ_CH_0 0xC5 +#define COP_READ_CH_1 0xCD +#define COP_WRITE_CH_0 0x45 +#define COP_WRITE_CH_1 0x4D + +#define POP_READ_CH_0 0xC6 +#define POP_READ_CH_1 0xCE +#define POP_WRITE_CH_0 0x46 +#define POP_WRITE_CH_1 0x4E + +#define RST_CMD_DUSLIC_CHIP 0x40 /* OR 0x48 */ +#define RST_CMD_DUSLIC_CH_A 0x41 +#define RST_CMD_DUSLIC_CH_B 0x49 + +#define PCM_RESYNC_CMD_CH_A 0x42 +#define PCM_RESYNC_CMD_CH_B 0x4A + +#define ACTIVE_HOOK_LEV_4 0 +#define ACTIVE_HOOK_LEV_12 1 + +#define SLIC_P_NORMAL 0x01 + +/************************************************/ + +#define CODSP_WR 0x00 +#define CODSP_RD 0x80 +#define CODSP_OP 0x40 +#define CODSP_ADR(x) (((unsigned char)(x) & 7) << 3) +#define CODSP_M(x) ((unsigned char)(x) & 7) +#define CODSP_CMD(x) ((unsigned char)(x) & 7) + +/************************************************/ + +/* command indication ops */ +#define CODSP_M_SLEEP_PWRDN 7 +#define CODSP_M_PWRDN_HIZ 0 +#define CODSP_M_ANY_ACT 2 +#define CODSP_M_RING 5 +#define CODSP_M_ACT_MET 6 +#define CODSP_M_GND_START 4 +#define CODSP_M_RING_PAUSE 1 + +/* single byte commands */ +#define CODSP_CMD_SOFT_RESET CODSP_CMD(0) +#define CODSP_CMD_RESET_CH CODSP_CMD(1) +#define CODSP_CMD_RESYNC CODSP_CMD(2) + +/* two byte commands */ +#define CODSP_CMD_SOP CODSP_CMD(4) +#define CODSP_CMD_COP CODSP_CMD(5) +#define CODSP_CMD_POP CODSP_CMD(6) + +/************************************************/ + +/* read as 4-bytes */ +#define CODSP_INTREG_INT_CH 0x80000000 +#define CODSP_INTREG_HOOK 0x40000000 +#define CODSP_INTREG_GNDK 0x20000000 +#define CODSP_INTREG_GNDP 0x10000000 +#define CODSP_INTREG_ICON 0x08000000 +#define CODSP_INTREG_VRTLIM 0x04000000 +#define CODSP_INTREG_OTEMP 0x02000000 +#define CODSP_INTREG_SYNC_FAIL 0x01000000 +#define CODSP_INTREG_LM_THRES 0x00800000 +#define CODSP_INTREG_READY 0x00400000 +#define CODSP_INTREG_RSTAT 0x00200000 +#define CODSP_INTREG_LM_OK 0x00100000 +#define CODSP_INTREG_IO4_DU 0x00080000 +#define CODSP_INTREG_IO3_DU 0x00040000 +#define CODSP_INTREG_IO2_DU 0x00020000 +#define CODSP_INTREG_IO1_DU 0x00010000 +#define CODSP_INTREG_DTMF_OK 0x00008000 +#define CODSP_INTREG_DTMF_KEY4 0x00004000 +#define CODSP_INTREG_DTMF_KEY3 0x00002000 +#define CODSP_INTREG_DTMF_KEY2 0x00001000 +#define CODSP_INTREG_DTMF_KEY1 0x00000800 +#define CODSP_INTREG_DTMF_KEY0 0x00000400 +#define CODSP_INTREG_UTDR_OK 0x00000200 +#define CODSP_INTREG_UTDX_OK 0x00000100 +#define CODSP_INTREG_EDSP_FAIL 0x00000080 +#define CODSP_INTREG_CIS_BOF 0x00000008 +#define CODSP_INTREG_CIS_BUF 0x00000004 +#define CODSP_INTREG_CIS_REQ 0x00000002 +#define CODSP_INTREG_CIS_ACT 0x00000001 + +/************************************************/ + +/* ======== SOP REG ADDRESSES =======*/ + +#define REVISION_ADDR 0x00 +#define PCMC1_ADDR 0x05 +#define XCR_ADDR 0x06 +#define INTREG1_ADDR 0x07 +#define INTREG2_ADDR 0x08 +#define INTREG3_ADDR 0x09 +#define INTREG4_ADDR 0x0A +#define LMRES1_ADDR 0x0D +#define MASK_ADDR 0x11 +#define IOCTL3_ADDR 0x14 +#define BCR1_ADDR 0x15 +#define BCR2_ADDR 0x16 +#define BCR3_ADDR 0x17 +#define BCR4_ADDR 0x18 +#define BCR5_ADDR 0x19 +#define DSCR_ADDR 0x1A +#define LMCR1_ADDR 0x1C +#define LMCR2_ADDR 0x1D +#define LMCR3_ADDR 0x1E +#define OFR1_ADDR 0x1F +#define PCMR1_ADDR 0x21 +#define PCMX1_ADDR 0x25 +#define TSTR3_ADDR 0x2B +#define TSTR4_ADDR 0x2C +#define TSTR5_ADDR 0x2D + +/* ========= POP REG ADDRESSES ========*/ + +#define CIS_DAT_ADDR 0x00 + +#define LEC_LEN_ADDR 0x3A +#define LEC_POWR_ADDR 0x3B +#define LEC_DELP_ADDR 0x3C +#define LEC_DELQ_ADDR 0x3D +#define LEC_GAIN_XI_ADDR 0x3E +#define LEC_GAIN_RI_ADDR 0x3F +#define LEC_GAIN_XO_ADDR 0x40 +#define LEC_RES_1_ADDR 0x41 +#define LEC_RES_2_ADDR 0x42 + +#define NLP_POW_LPF_ADDR 0x30 +#define NLP_POW_LPS_ADDR 0x31 +#define NLP_BN_LEV_X_ADDR 0x32 +#define NLP_BN_LEV_R_ADDR 0x33 +#define NLP_BN_INC_ADDR 0x34 +#define NLP_BN_DEC_ADDR 0x35 +#define NLP_BN_MAX_ADDR 0x36 +#define NLP_BN_ADJ_ADDR 0x37 +#define NLP_RE_MIN_ERLL_ADDR 0x38 +#define NLP_RE_EST_ERLL_ADDR 0x39 +#define NLP_SD_LEV_X_ADDR 0x3A +#define NLP_SD_LEV_R_ADDR 0x3B +#define NLP_SD_LEV_BN_ADDR 0x3C +#define NLP_SD_LEV_RE_ADDR 0x3D +#define NLP_SD_OT_DT_ADDR 0x3E +#define NLP_ERL_LIN_LP_ADDR 0x3F +#define NLP_ERL_LEC_LP_ADDR 0x40 +#define NLP_CT_LEV_RE_ADDR 0x41 +#define NLP_CTRL_ADDR 0x42 + +#define UTD_CF_H_ADDR 0x4B +#define UTD_CF_L_ADDR 0x4C +#define UTD_BW_H_ADDR 0x4D +#define UTD_BW_L_ADDR 0x4E +#define UTD_NLEV_ADDR 0x4F +#define UTD_SLEV_H_ADDR 0x50 +#define UTD_SLEV_L_ADDR 0x51 +#define UTD_DELT_ADDR 0x52 +#define UTD_RBRK_ADDR 0x53 +#define UTD_RTIME_ADDR 0x54 +#define UTD_EBRK_ADDR 0x55 +#define UTD_ETIME_ADDR 0x56 + +#define DTMF_LEV_ADDR 0x30 +#define DTMF_TWI_ADDR 0x31 +#define DTMF_NCF_H_ADDR 0x32 +#define DTMF_NCF_L_ADDR 0x33 +#define DTMF_NBW_H_ADDR 0x34 +#define DTMF_NBW_L_ADDR 0x35 +#define DTMF_GAIN_ADDR 0x36 +#define DTMF_RES1_ADDR 0x37 +#define DTMF_RES2_ADDR 0x38 +#define DTMF_RES3_ADDR 0x39 + +#define CIS_LEV_H_ADDR 0x43 +#define CIS_LEV_L_ADDR 0x44 +#define CIS_BRS_ADDR 0x45 +#define CIS_SEIZ_H_ADDR 0x46 +#define CIS_SEIZ_L_ADDR 0x47 +#define CIS_MARK_H_ADDR 0x48 +#define CIS_MARK_L_ADDR 0x49 +#define CIS_LEC_MODE_ADDR 0x4A + +/*=====================================*/ + +#define HOOK_LEV_ACT_START_ADDR 0x89 +#define RO1_START_ADDR 0x70 +#define RO2_START_ADDR 0x95 +#define RO3_START_ADDR 0x96 + +#define TG1_FREQ_START_ADDR 0x38 +#define TG1_GAIN_START_ADDR 0x39 +#define TG1_BANDPASS_START_ADDR 0x3B +#define TG1_BANDPASS_END_ADDR 0x3D + +#define TG2_FREQ_START_ADDR 0x40 +#define TG2_GAIN_START_ADDR 0x41 +#define TG2_BANDPASS_START_ADDR 0x43 +#define TG2_BANDPASS_END_ADDR 0x45 + +/*====================================*/ + +#define PCM_HW_B 0x80 +#define PCM_HW_A 0x00 +#define PCM_TIME_SLOT_0 0x00 /* Byte 0 of PCM Frame (by default is assigned to channel A ) */ +#define PCM_TIME_SLOT_1 0x01 /* Byte 1 of PCM Frame (by default is assigned to channel B ) */ +#define PCM_TIME_SLOT_4 0x04 /* Byte 4 of PCM Frame (Corresponds to B1 of the Second GCI ) */ + +#define RX_LEV_ADDR 0x28 +#define TX_LEV_ADDR 0x30 +#define Ik1_ADDR 0x83 + +#define AR_ROW 3 /* Is the row (AR Params) of the ac_Coeff array in SMS_CODEC_Defaults struct */ +#define AX_ROW 6 /* Is the row (AX Params) of the ac_Coeff array in SMS_CODEC_Defaults struct */ +#define DCF_ROW 0 /* Is the row (DCF Params) of the dc_Coeff array in SMS_CODEC_Defaults struct */ + +/* Mark the start byte of Duslic parameters that we use with configurator */ +#define Ik1_START_BYTE 3 +#define RX_LEV_START_BYTE 0 +#define TX_LEV_START_BYTE 0 + +/************************************************/ + +#define INTREG4_CIS_ACT (1 << 0) + +#define BCR1_SLEEP 0x20 +#define BCR1_REVPOL 0x10 +#define BCR1_ACTR 0x08 +#define BCR1_ACTL 0x04 +#define BCR1_SLIC_MASK 0x03 + +#define BCR2_HARD_POL_REV 0x40 +#define BCR2_TTX 0x20 +#define BCR2_TTX_12K 0x10 +#define BCR2_HIMAN 0x08 +#define BCR2_PDOT 0x01 + +#define BCR3_PCMX_EN (1 << 4) + +#define BCR5_DTMF_EN (1 << 0) +#define BCR5_DTMF_SRC (1 << 1) +#define BCR5_LEC_EN (1 << 2) +#define BCR5_LEC_OUT (1 << 3) +#define BCR5_CIS_EN (1 << 4) +#define BCR5_CIS_AUTO (1 << 5) +#define BCR5_UTDX_EN (1 << 6) +#define BCR5_UTDR_EN (1 << 7) + +#define DSCR_TG1_EN (1 << 0) +#define DSCR_TG2_EN (1 << 1) +#define DSCR_PTG (1 << 2) +#define DSCR_COR8 (1 << 3) +#define DSCR_DG_KEY(x) (((x) & 0x0F) << 4) + +#define CIS_LEC_MODE_CIS_V23 (1 << 0) +#define CIS_LEC_MODE_CIS_FRM (1 << 1) +#define CIS_LEC_MODE_NLP_EN (1 << 2) +#define CIS_LEC_MODE_UTDR_SUM (1 << 4) +#define CIS_LEC_MODE_UTDX_SUM (1 << 5) +#define CIS_LEC_MODE_LEC_FREEZE (1 << 6) +#define CIS_LEC_MODE_LEC_ADAPT (1 << 7) + +#define TSTR4_COR_64 (1 << 5) + +#define TSTR3_AC_DLB_8K (1 << 2) +#define TSTR3_AC_DLB_32K (1 << 3) +#define TSTR3_AC_DLB_4M (1 << 5) + + +#define LMCR1_TEST_EN (1 << 7) +#define LMCR1_LM_EN (1 << 6) +#define LMCR1_LM_THM (1 << 5) +#define LMCR1_LM_ONCE (1 << 2) +#define LMCR1_LM_MASK (1 << 1) + +#define LMCR2_LM_RECT (1 << 5) +#define LMCR2_LM_SEL_VDD 0x0D +#define LMCR2_LM_SEL_IO3 0x0A +#define LMCR2_LM_SEL_IO4 0x0B +#define LMCR2_LM_SEL_IO4_MINUS_IO3 0x0F + +#define LMCR3_RTR_SEL (1 << 6) + +#define LMCR3_RNG_OFFSET_NONE 0x00 +#define LMCR3_RNG_OFFSET_1 0x01 +#define LMCR3_RNG_OFFSET_2 0x02 +#define LMCR3_RNG_OFFSET_3 0x03 + +#define TSTR5_DC_HOLD (1 << 3) + +/************************************************/ + +#define TARGET_ONHOOK_BATH_x100 4600 /* 46.0 Volt */ +#define TARGET_ONHOOK_BATL_x100 2500 /* 25.0 Volt */ +#define TARGET_V_DIVIDER_RATIO_x100 21376L /* (R1+R2)/R2 = 213.76 */ +#define DIVIDER_RATIO_ACCURx100 (22 * 100) +#define V_AD_x10000 10834L /* VAD = 1.0834 */ +#define TARGET_VDDx100 330 /* VDD = 3.3 * 10 */ +#define VDD_MAX_DIFFx100 20 /* VDD Accur = 0.2*100 */ + +#define RMS_MULTIPLIERx100 111 /* pi/(2xsqrt(2)) = 1.11*/ +#define K_INTDC_RECT_ON 4 /* When Rectifier is ON this value is necessary(2^4) */ +#define K_INTDC_RECT_OFF 2 /* 2^2 */ +#define RNG_FREQ 25 +#define SAMPLING_FREQ (2000L) +#define N_SAMPLES (SAMPLING_FREQ/RNG_FREQ) /* for Ring Freq =25Hz (40ms Integration Period)[Sampling rate 2KHz -->1 Sample every 500us] */ +#define HOOK_THRESH_RING_START_ADDR 0x8B +#define RING_PARAMS_START_ADDR 0x70 + +#define V_OUT_BATH_MAX_DIFFx100 300 /* 3.0 x100 */ +#define V_OUT_BATL_MAX_DIFFx100 400 /* 4.0 x100 */ +#define MAX_V_RING_MEANx100 50 +#define TARGET_V_RING_RMSx100 2720 +#define V_RMS_RING_MAX_DIFFx100 250 + +#define LM_OK_SRC_IRG_2 (1 << 4) + +/************************************************/ + +#define PORTB (((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pbdat) +#define PORTC (((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pcdat) +#define PORTD (((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pddat) + +#define _PORTD_SET(mask, state) \ + do { \ + if (state) \ + PORTD |= mask; \ + else \ + PORTD &= ~mask; \ + } while (0) + +#define _PORTB_SET(mask, state) \ + do { \ + if (state) \ + PORTB |= mask; \ + else \ + PORTB &= ~mask; \ + } while (0) + +#define _PORTB_TGL(mask) do { PORTB ^= mask; } while (0) +#define _PORTB_GET(mask) (!!(PORTB & mask)) + +#define _PORTC_GET(mask) (!!(PORTC & mask)) + +/* port B */ +#define SPI_RXD (1 << (31 - 28)) +#define SPI_TXD (1 << (31 - 29)) +#define SPI_CLK (1 << (31 - 30)) + +/* port C */ +#define COM_HOOK1 (1 << (15 - 9)) +#define COM_HOOK2 (1 << (15 - 10)) + +#ifndef CONFIG_NETTA_SWAPHOOK + +#define COM_HOOK3 (1 << (15 - 11)) +#define COM_HOOK4 (1 << (15 - 12)) + +#else + +#define COM_HOOK3 (1 << (15 - 12)) +#define COM_HOOK4 (1 << (15 - 11)) + +#endif + +/* port D */ +#define SPIENC1 (1 << (15 - 9)) +#define SPIENC2 (1 << (15 - 10)) +#define SPIENC3 (1 << (15 - 11)) +#define SPIENC4 (1 << (15 - 14)) + +#define SPI_DELAY() udelay(1) + +static inline unsigned int __SPI_Transfer(unsigned int tx) +{ + unsigned int rx; + int b; + + rx = 0; b = 8; + while (--b >= 0) { + _PORTB_SET(SPI_TXD, tx & 0x80); + tx <<= 1; + _PORTB_TGL(SPI_CLK); + SPI_DELAY(); + rx <<= 1; + rx |= _PORTB_GET(SPI_RXD); + _PORTB_TGL(SPI_CLK); + SPI_DELAY(); + } + + return rx; +} + +static const char *codsp_dtmf_map = "D1234567890*#ABC"; + +static const int spienc_mask_tab[4] = { SPIENC1, SPIENC2, SPIENC3, SPIENC4 }; +static const int com_hook_mask_tab[4] = { COM_HOOK1, COM_HOOK2, COM_HOOK3, COM_HOOK4 }; + +static unsigned int codsp_send(int duslic_id, const unsigned char *cmd, int cmdlen, unsigned char *res, int reslen) +{ + unsigned int rx; + int i; + + /* just some sanity checks */ + if (cmd == 0 || cmdlen < 0) + return -1; + + _PORTD_SET(spienc_mask_tab[duslic_id], 0); + + /* first 2 bytes are without response */ + i = 2; + while (i-- > 0 && cmdlen-- > 0) + __SPI_Transfer(*cmd++); + + while (cmdlen-- > 0) { + rx = __SPI_Transfer(*cmd++); + if (res != 0 && reslen-- > 0) + *res++ = (unsigned char)rx; + } + if (res != 0) { + while (reslen-- > 0) + *res++ = __SPI_Transfer(0xFF); + } + + _PORTD_SET(spienc_mask_tab[duslic_id], 1); + + return 0; +} + +/****************************************************************************/ + +void codsp_set_ciop_m(int duslic_id, int channel, unsigned char m) +{ + unsigned char cmd = CODSP_WR | CODSP_ADR(channel) | CODSP_M(m); + codsp_send(duslic_id, &cmd, 1, 0, 0); +} + +void codsp_reset_chip(int duslic_id) +{ + static const unsigned char cmd = CODSP_WR | CODSP_OP | CODSP_CMD_SOFT_RESET; + codsp_send(duslic_id, &cmd, 1, 0, 0); +} + +void codsp_reset_channel(int duslic_id, int channel) +{ + unsigned char cmd = CODSP_WR | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_RESET_CH; + codsp_send(duslic_id, &cmd, 1, 0, 0); +} + +void codsp_resync_channel(int duslic_id, int channel) +{ + unsigned char cmd = CODSP_WR | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_RESYNC; + codsp_send(duslic_id, &cmd, 1, 0, 0); +} + +/****************************************************************************/ + +void codsp_write_sop_char(int duslic_id, int channel, unsigned char regno, unsigned char val) +{ + unsigned char cmd[3]; + + cmd[0] = CODSP_WR | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_SOP; + cmd[1] = regno; + cmd[2] = val; + + codsp_send(duslic_id, cmd, 3, 0, 0); +} + +void codsp_write_sop_short(int duslic_id, int channel, unsigned char regno, unsigned short val) +{ + unsigned char cmd[4]; + + cmd[0] = CODSP_WR | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_SOP; + cmd[1] = regno; + cmd[2] = (unsigned char)(val >> 8); + cmd[3] = (unsigned char)val; + + codsp_send(duslic_id, cmd, 4, 0, 0); +} + +void codsp_write_sop_int(int duslic_id, int channel, unsigned char regno, unsigned int val) +{ + unsigned char cmd[5]; + + cmd[0] = CODSP_WR | CODSP_ADR(channel) | CODSP_CMD_SOP; + cmd[1] = regno; + cmd[2] = (unsigned char)(val >> 24); + cmd[3] = (unsigned char)(val >> 16); + cmd[4] = (unsigned char)(val >> 8); + cmd[5] = (unsigned char)val; + + codsp_send(duslic_id, cmd, 6, 0, 0); +} + +unsigned char codsp_read_sop_char(int duslic_id, int channel, unsigned char regno) +{ + unsigned char cmd[3]; + unsigned char res[2]; + + cmd[0] = CODSP_RD | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_SOP; + cmd[1] = regno; + + codsp_send(duslic_id, cmd, 2, res, 2); + + return res[1]; +} + +unsigned short codsp_read_sop_short(int duslic_id, int channel, unsigned char regno) +{ + unsigned char cmd[2]; + unsigned char res[3]; + + cmd[0] = CODSP_RD | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_SOP; + cmd[1] = regno; + + codsp_send(duslic_id, cmd, 2, res, 3); + + return ((unsigned short)res[1] << 8) | res[2]; +} + +unsigned int codsp_read_sop_int(int duslic_id, int channel, unsigned char regno) +{ + unsigned char cmd[2]; + unsigned char res[5]; + + cmd[0] = CODSP_RD | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_SOP; + cmd[1] = regno; + + codsp_send(duslic_id, cmd, 2, res, 5); + + return ((unsigned int)res[1] << 24) | ((unsigned int)res[2] << 16) | ((unsigned int)res[3] << 8) | res[4]; +} + +/****************************************************************************/ + +void codsp_write_cop_block(int duslic_id, int channel, unsigned char addr, const unsigned char *block) +{ + unsigned char cmd[10]; + + cmd[0] = CODSP_WR | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_COP; + cmd[1] = addr; + memcpy(cmd + 2, block, 8); + codsp_send(duslic_id, cmd, 10, 0, 0); +} + +void codsp_write_cop_char(int duslic_id, int channel, unsigned char addr, unsigned char val) +{ + unsigned char cmd[3]; + + cmd[0] = CODSP_WR | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_COP; + cmd[1] = addr; + cmd[2] = val; + codsp_send(duslic_id, cmd, 3, 0, 0); +} + +void codsp_write_cop_short(int duslic_id, int channel, unsigned char addr, unsigned short val) +{ + unsigned char cmd[3]; + + cmd[0] = CODSP_WR | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_COP; + cmd[1] = addr; + cmd[2] = (unsigned char)(val >> 8); + cmd[3] = (unsigned char)val; + + codsp_send(duslic_id, cmd, 4, 0, 0); +} + +void codsp_read_cop_block(int duslic_id, int channel, unsigned char addr, unsigned char *block) +{ + unsigned char cmd[2]; + unsigned char res[9]; + + cmd[0] = CODSP_RD | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_COP; + cmd[1] = addr; + codsp_send(duslic_id, cmd, 2, res, 9); + memcpy(block, res + 1, 8); +} + +unsigned char codsp_read_cop_char(int duslic_id, int channel, unsigned char addr) +{ + unsigned char cmd[2]; + unsigned char res[2]; + + cmd[0] = CODSP_RD | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_COP; + cmd[1] = addr; + codsp_send(duslic_id, cmd, 2, res, 2); + return res[1]; +} + +unsigned short codsp_read_cop_short(int duslic_id, int channel, unsigned char addr) +{ + unsigned char cmd[2]; + unsigned char res[3]; + + cmd[0] = CODSP_RD | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_COP; + cmd[1] = addr; + + codsp_send(duslic_id, cmd, 2, res, 3); + + return ((unsigned short)res[1] << 8) | res[2]; +} + +/****************************************************************************/ + +#define MAX_POP_BLOCK 50 + +void codsp_write_pop_block(int duslic_id, int channel, unsigned char addr, const unsigned char *block, int len) +{ + unsigned char cmd[2 + MAX_POP_BLOCK]; + + if (len > MAX_POP_BLOCK) /* truncate */ + len = MAX_POP_BLOCK; + + cmd[0] = CODSP_WR | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_POP; + cmd[1] = addr; + memcpy(cmd + 2, block, len); + codsp_send(duslic_id, cmd, 2 + len, 0, 0); +} + +void codsp_write_pop_char(int duslic_id, int channel, unsigned char regno, unsigned char val) +{ + unsigned char cmd[3]; + + cmd[0] = CODSP_WR | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_POP; + cmd[1] = regno; + cmd[2] = val; + + codsp_send(duslic_id, cmd, 3, 0, 0); +} + +void codsp_write_pop_short(int duslic_id, int channel, unsigned char regno, unsigned short val) +{ + unsigned char cmd[4]; + + cmd[0] = CODSP_WR | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_POP; + cmd[1] = regno; + cmd[2] = (unsigned char)(val >> 8); + cmd[3] = (unsigned char)val; + + codsp_send(duslic_id, cmd, 4, 0, 0); +} + +void codsp_write_pop_int(int duslic_id, int channel, unsigned char regno, unsigned int val) +{ + unsigned char cmd[5]; + + cmd[0] = CODSP_WR | CODSP_ADR(channel) | CODSP_CMD_POP; + cmd[1] = regno; + cmd[2] = (unsigned char)(val >> 24); + cmd[3] = (unsigned char)(val >> 16); + cmd[4] = (unsigned char)(val >> 8); + cmd[5] = (unsigned char)val; + + codsp_send(duslic_id, cmd, 6, 0, 0); +} + +unsigned char codsp_read_pop_char(int duslic_id, int channel, unsigned char regno) +{ + unsigned char cmd[3]; + unsigned char res[2]; + + cmd[0] = CODSP_RD | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_POP; + cmd[1] = regno; + + codsp_send(duslic_id, cmd, 2, res, 2); + + return res[1]; +} + +unsigned short codsp_read_pop_short(int duslic_id, int channel, unsigned char regno) +{ + unsigned char cmd[2]; + unsigned char res[3]; + + cmd[0] = CODSP_RD | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_POP; + cmd[1] = regno; + + codsp_send(duslic_id, cmd, 2, res, 3); + + return ((unsigned short)res[1] << 8) | res[2]; +} + +unsigned int codsp_read_pop_int(int duslic_id, int channel, unsigned char regno) +{ + unsigned char cmd[2]; + unsigned char res[5]; + + cmd[0] = CODSP_RD | CODSP_OP | CODSP_ADR(channel) | CODSP_CMD_POP; + cmd[1] = regno; + + codsp_send(duslic_id, cmd, 2, res, 5); + + return ((unsigned int)res[1] << 24) | ((unsigned int)res[2] << 16) | ((unsigned int)res[3] << 8) | res[4]; +} + +/****************************************************************************/ + +struct _coeffs { + unsigned char addr; + unsigned char values[8]; +}; + +struct _coeffs ac_coeffs[11] = { + { 0x60, {0xAD,0xDA,0xB5,0x9B,0xC7,0x2A,0x9D,0x00} }, /* 0x60 IM-Filter part 1 */ + { 0x68, {0x10,0x00,0xA9,0x82,0x0D,0x77,0x0A,0x00} }, /* 0x68 IM-Filter part 2 */ + { 0x18, {0x08,0xC0,0xD2,0xAB,0xA5,0xE2,0xAB,0x07} }, /* 0x18 FRR-Filter */ + { 0x28, {0x44,0x93,0xF5,0x92,0x88,0x00,0x00,0x00} }, /* 0x28 AR-Filter */ + { 0x48, {0x96,0x38,0x29,0x96,0xC9,0x2B,0x8B,0x00} }, /* 0x48 LPR-Filter */ + { 0x20, {0x08,0xB0,0xDA,0x9D,0xA7,0xFA,0x93,0x06} }, /* 0x20 FRX-Filter */ + { 0x30, {0xBA,0xAC,0x00,0x01,0x85,0x50,0xC0,0x1A} }, /* 0x30 AX-Filter */ + { 0x50, {0x96,0x38,0x29,0xF5,0xFA,0x2B,0x8B,0x00} }, /* 0x50 LPX-Filter */ + { 0x00, {0x00,0x08,0x08,0x81,0x00,0x80,0x00,0x08} }, /* 0x00 TH-Filter part 1 */ + { 0x08, {0x81,0x00,0x80,0x00,0xD7,0x33,0xBA,0x01} }, /* 0x08 TH-Filter part 2 */ + { 0x10, {0xB3,0x6C,0xDC,0xA3,0xA4,0xE5,0x88,0x00} } /* 0x10 TH-Filter part 3 */ +}; + +struct _coeffs ac_coeffs_0dB[11] = { + { 0x60, {0xAC,0x2A,0xB5,0x9A,0xB7,0x2A,0x9D,0x00} }, + { 0x68, {0x10,0x00,0xA9,0x82,0x0D,0x83,0x0A,0x00} }, + { 0x18, {0x08,0x20,0xD4,0xA4,0x65,0xEE,0x92,0x07} }, + { 0x28, {0x2B,0xAB,0x36,0xA5,0x88,0x00,0x00,0x00} }, + { 0x48, {0xAB,0xE9,0x4E,0x32,0xAB,0x25,0xA5,0x03} }, + { 0x20, {0x08,0x20,0xDB,0x9C,0xA7,0xFA,0xB4,0x07} }, + { 0x30, {0xF3,0x10,0x07,0x60,0x85,0x40,0xC0,0x1A} }, + { 0x50, {0x96,0x38,0x29,0x97,0x39,0x19,0x8B,0x00} }, + { 0x00, {0x00,0x08,0x08,0x81,0x00,0x80,0x00,0x08} }, + { 0x08, {0x81,0x00,0x80,0x00,0x47,0x3C,0xD2,0x01} }, + { 0x10, {0x62,0xDB,0x4A,0x87,0x73,0x28,0x88,0x00} } +}; + +struct _coeffs dc_coeffs[9] = { + { 0x80, {0x25,0x59,0x9C,0x23,0x24,0x23,0x32,0x1C} }, /* 0x80 DC-Parameter */ + { 0x70, {0x90,0x30,0x1B,0xC0,0x33,0x43,0xAC,0x02} }, /* 0x70 Ringing */ + { 0x90, {0x3F,0xC3,0x2E,0x3A,0x80,0x90,0x00,0x09} }, /* 0x90 LP-Filters */ + { 0x88, {0xAF,0x80,0x27,0x7B,0x01,0x4C,0x7B,0x02} }, /* 0x88 Hook Levels */ + { 0x78, {0x00,0xC0,0x6D,0x7A,0xB3,0x78,0x89,0x00} }, /* 0x78 Ramp Generator */ + { 0x58, {0xA5,0x44,0x34,0xDB,0x0E,0xA2,0x2A,0x00} }, /* 0x58 TTX */ + { 0x38, {0x33,0x49,0x9A,0x65,0xBB,0x00,0x00,0x00} }, /* 0x38 TG1 */ + { 0x40, {0x33,0x49,0x9A,0x65,0xBB,0x00,0x00,0x00} }, /* 0x40 TG2 */ + { 0x98, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} } /* 0x98 Reserved */ +}; + +void program_coeffs(int duslic_id, int channel, struct _coeffs *coeffs, int tab_size) +{ + int i; + + for (i = 0; i < tab_size; i++) + codsp_write_cop_block(duslic_id, channel, coeffs[i].addr, coeffs[i].values); +} + +#define SS_OPEN_CIRCUIT 0 +#define SS_RING_PAUSE 1 +#define SS_ACTIVE 2 +#define SS_ACTIVE_HIGH 3 +#define SS_ACTIVE_RING 4 +#define SS_RINGING 5 +#define SS_ACTIVE_WITH_METERING 6 +#define SS_ONHOOKTRNSM 7 +#define SS_STANDBY 8 +#define SS_MAX 8 + +static void codsp_set_slic(int duslic_id, int channel, int state) +{ + unsigned char v; + + v = codsp_read_sop_char(duslic_id, channel, BCR1_ADDR); + + switch (state) { + + case SS_ACTIVE: + codsp_write_sop_char(duslic_id, channel, BCR1_ADDR, (v & ~BCR1_ACTR) | BCR1_ACTL); + codsp_set_ciop_m(duslic_id, channel, CODSP_M_ANY_ACT); + break; + + case SS_ACTIVE_HIGH: + codsp_write_sop_char(duslic_id, channel, BCR1_ADDR, v & ~(BCR1_ACTR | BCR1_ACTL)); + codsp_set_ciop_m(duslic_id, channel, CODSP_M_ANY_ACT); + break; + + case SS_ACTIVE_RING: + case SS_ONHOOKTRNSM: + codsp_write_sop_char(duslic_id, channel, BCR1_ADDR, (v & ~BCR1_ACTL) | BCR1_ACTR); + codsp_set_ciop_m(duslic_id, channel, CODSP_M_ANY_ACT); + break; + + case SS_STANDBY: + codsp_write_sop_char(duslic_id, channel, BCR1_ADDR, v & ~(BCR1_ACTL | BCR1_ACTR)); + codsp_set_ciop_m(duslic_id, channel, CODSP_M_SLEEP_PWRDN); + break; + + case SS_OPEN_CIRCUIT: + codsp_set_ciop_m(duslic_id, channel, CODSP_M_PWRDN_HIZ); + break; + + case SS_RINGING: + codsp_set_ciop_m(duslic_id, channel, CODSP_M_RING); + break; + + case SS_RING_PAUSE: + codsp_set_ciop_m(duslic_id, channel, CODSP_M_RING_PAUSE); + break; + } +} + +const unsigned char Ring_Sin_28Vrms_25Hz[8] = { 0x90, 0x30, 0x1B, 0xC0, 0xC3, 0x9C, 0x88, 0x00 }; +const unsigned char Max_HookRingTh[3] = { 0x7B, 0x41, 0x62 }; + +void retrieve_slic_state(int slic_id) +{ + int duslic_id = slic_id >> 1; + int channel = slic_id & 1; + + /* Retrieve the state of the SLICs */ + codsp_write_sop_char(duslic_id, channel, LMCR2_ADDR, 0x00); + + /* wait at least 1000us to clear the LM_OK and 500us to set the LM_OK ==> for the LM to make the first Measurement */ + udelay(10000); + + codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK); + codsp_set_slic(duslic_id, channel, SS_ACTIVE_HIGH); + codsp_write_sop_char(duslic_id, channel, LMCR3_ADDR, 0x40); + + /* Program Default Hook Ring thresholds */ + codsp_write_cop_block(duslic_id, channel, dc_coeffs[1].addr, dc_coeffs[1].values); + + /* Now program Hook Threshold while Ring and ac RingTrip to max values */ + codsp_write_cop_block(duslic_id, channel, dc_coeffs[3].addr, dc_coeffs[3].values); + + codsp_write_sop_short(duslic_id, channel, OFR1_ADDR, 0x0000); + + udelay(40000); +} + +int wait_level_metering_finish(int duslic_id, int channel) +{ + int cnt; + + for (cnt = 0; cnt < 1000 && + (codsp_read_sop_char(duslic_id, channel, INTREG2_ADDR) & LM_OK_SRC_IRG_2) == 0; cnt++) { } + + return cnt != 1000; +} + +int measure_on_hook_voltages(int slic_id, long *vdd, + long *v_oh_H, long *v_oh_L, long *ring_mean_v, long *ring_rms_v) +{ + short LM_Result, Offset_Compensation; /* Signed 16 bit */ + long int VDD, VDD_diff, V_in, V_out, Divider_Ratio, Vout_diff ; + unsigned char err_mask = 0; + int duslic_id = slic_id >> 1; + int channel = slic_id & 1; + int i; + + /* measure VDD */ + /* Now select the VDD level Measurement (but first of all Hold the DC characteristic) */ + codsp_write_sop_char(duslic_id, channel, TSTR5_ADDR, TSTR5_DC_HOLD); + + /* Activate Test Mode ==> To Enable DC Hold !!! */ + /* (else the LMRES is treated as Feeding Current and the Feeding voltage changes */ + /* imediatelly (after 500us when the LMRES Registers is updated for the first time after selection of (IO4-IO3) measurement !!!!))*/ + codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, LMCR1_TEST_EN | LMCR1_LM_THM | LMCR1_LM_MASK); + + udelay(40000); + + /* Now I Can select what to measure by DC Level Meter (select IO4-IO3) */ + codsp_write_sop_char(duslic_id, channel, LMCR2_ADDR, LMCR2_LM_SEL_VDD); + + /* wait at least 1000us to clear the LM_OK and 500us to set the LM_OK ==> for the LM to make the first Measurement */ + udelay(10000); + + /* Now Read the LM Result Registers */ + LM_Result = codsp_read_sop_short(duslic_id, channel, LMRES1_ADDR); + VDD = (-1)*((((long int)LM_Result) * 390L ) >> 15) ; /* VDDx100 */ + + *vdd = VDD; + + VDD_diff = VDD - TARGET_VDDx100; + + if (VDD_diff < 0) + VDD_diff = -VDD_diff; + + if (VDD_diff > VDD_MAX_DIFFx100) + err_mask |= 1; + + Divider_Ratio = TARGET_V_DIVIDER_RATIO_x100; + + codsp_write_sop_char(duslic_id, channel, LMCR2_ADDR, 0x00); + codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK); + + codsp_set_slic(duslic_id, channel, SS_ACTIVE_HIGH); /* Go back to ONHOOK Voltage */ + + udelay(40000); + + codsp_write_sop_char(duslic_id, channel, + LMCR1_ADDR, LMCR1_TEST_EN | LMCR1_LM_THM | LMCR1_LM_MASK); + + udelay(40000); + + /* Now I Can select what to measure by DC Level Meter (select IO4-IO3) */ + codsp_write_sop_char(duslic_id, channel, LMCR2_ADDR, LMCR2_LM_SEL_IO4_MINUS_IO3); + + /* wait at least 1000us to clear the LM_OK and 500us to set the LM_OK ==> for the LM to make the first Measurement */ + udelay(10000); + + /* Now Read the LM Result Registers */ + LM_Result = codsp_read_sop_short(duslic_id, channel, LMRES1_ADDR); + V_in = (-1)* ((((long int)LM_Result) * V_AD_x10000 ) >> 15) ; /* Vin x 10000*/ + + V_out = (V_in * Divider_Ratio) / 10000L ; /* Vout x100 */ + + *v_oh_H = V_out; + + Vout_diff = V_out - TARGET_ONHOOK_BATH_x100; + + if (Vout_diff < 0) + Vout_diff = -Vout_diff; + + if (Vout_diff > V_OUT_BATH_MAX_DIFFx100) + err_mask |= 2; + + codsp_set_slic(duslic_id, channel, SS_ACTIVE); /* Go back to ONHOOK Voltage */ + + udelay(40000); + + /* Now Read the LM Result Registers */ + LM_Result = codsp_read_sop_short(duslic_id, channel, LMRES1_ADDR); + + V_in = (-1)* ((((long int)LM_Result) * V_AD_x10000 ) >> 15) ; /* Vin x 10000*/ + + V_out = (V_in * Divider_Ratio) / 10000L ; /* Vout x100 */ + + *v_oh_L = V_out; + + Vout_diff = V_out - TARGET_ONHOOK_BATL_x100; + + if (Vout_diff < 0) + Vout_diff = -Vout_diff; + + if (Vout_diff > V_OUT_BATL_MAX_DIFFx100) + err_mask |= 4; + + /* perform ring tests */ + + codsp_write_sop_char(duslic_id, channel, LMCR2_ADDR, 0x00); + codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK); + + udelay(40000); + + codsp_write_sop_char(duslic_id, channel, LMCR3_ADDR, LMCR3_RTR_SEL | LMCR3_RNG_OFFSET_NONE); + + /* Now program RO1 =0V , Ring Amplitude and frequency and shift factor K = 1 (LMDC=0x0088)*/ + codsp_write_cop_block(duslic_id, channel, RING_PARAMS_START_ADDR, Ring_Sin_28Vrms_25Hz); + + /* By Default RO1 is selected when ringing RNG-OFFSET = 00 */ + + /* Now program Hook Threshold while Ring and ac RingTrip to max values */ + for(i = 0; i < sizeof(Max_HookRingTh); i++) + codsp_write_cop_char(duslic_id, channel, HOOK_THRESH_RING_START_ADDR + i, Max_HookRingTh[i]); + + codsp_write_sop_short(duslic_id, channel, OFR1_ADDR, 0x0000); + + codsp_set_slic(duslic_id, channel, SS_RING_PAUSE); /* Start Ringing */ + + /* select source for the levelmeter to be IO4-IO3 */ + codsp_write_sop_char(duslic_id, channel, LMCR2_ADDR, LMCR2_LM_SEL_IO4_MINUS_IO3); + + udelay(40000); + + /* Before Enabling Level Meter Programm the apropriate shift factor K_INTDC=(4 if Rectifier Enabled and 2 if Rectifier Disabled) */ + codsp_write_cop_char(duslic_id, channel, RING_PARAMS_START_ADDR + 7, K_INTDC_RECT_OFF); + + udelay(10000); + + /* Enable LevelMeter to Integrate only once (Rectifier Disabled) */ + codsp_write_sop_char(duslic_id, channel, + LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK | LMCR1_LM_EN | LMCR1_LM_ONCE); + + udelay(40000); /* Integration Period == Ring Period = 40ms (for 25Hz Ring) */ + + if (wait_level_metering_finish(duslic_id, channel)) { + + udelay(10000); /* To be sure that Integration Results are Valid wait at least 500us !!! */ + + /* Now Read the LM Result Registers (Will be valid until LM_EN becomes zero again( after that the Result is updated every 500us) ) */ + Offset_Compensation = codsp_read_sop_short(duslic_id, channel, LMRES1_ADDR); + Offset_Compensation = (-1) * ((Offset_Compensation * (1 << K_INTDC_RECT_OFF)) / N_SAMPLES); + + /* Disable LevelMeter ==> In order to be able to restart Integrator again (for the next integration) */ + codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK | LMCR1_LM_ONCE); + + /* Now programm Integrator Offset Registers !!! */ + codsp_write_sop_short(duslic_id, channel, OFR1_ADDR, Offset_Compensation); + + codsp_set_slic(duslic_id, channel, SS_RINGING); /* Start Ringing */ + + udelay(40000); + + /* Reenable Level Meter Integrator (The Result will be valid after Integration Period=Ring Period and until LN_EN become zero again) */ + codsp_write_sop_char(duslic_id, channel, + LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK | LMCR1_LM_EN | LMCR1_LM_ONCE); + + udelay(40000); /* Integration Period == Ring Period = 40ms (for 25Hz Ring) */ + + /* Poll the LM_OK bit to see when Integration Result is Ready */ + if (wait_level_metering_finish(duslic_id, channel)) { + + udelay(10000); /* wait at least 500us to be sure that the Integration Result are valid !!! */ + + /* Now Read the LM Result Registers (They will hold their value until LM_EN become zero again */ + /* ==>After that Result Regs will be updated every 500us !!!) */ + LM_Result = codsp_read_sop_short(duslic_id, channel, LMRES1_ADDR); + V_in = (-1) * ( ( (((long int)LM_Result) * V_AD_x10000) / N_SAMPLES) >> (15 - K_INTDC_RECT_OFF)) ; /* Vin x 10000*/ + + V_out = (V_in * Divider_Ratio) / 10000L ; /* Vout x100 */ + + if (V_out < 0) + V_out= -V_out; + + if (V_out > MAX_V_RING_MEANx100) + err_mask |= 8; + + *ring_mean_v = V_out; + } else { + err_mask |= 8; + *ring_mean_v = 0; + } + } else { + err_mask |= 8; + *ring_mean_v = 0; + } + + /* Disable LevelMeter ==> In order to be able to restart Integrator again (for the next integration) */ + codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, + LMCR1_LM_THM | LMCR1_LM_MASK | LMCR1_LM_ONCE); + codsp_write_sop_short(duslic_id, channel, OFR1_ADDR, 0x0000); + + codsp_set_slic(duslic_id, channel, SS_RING_PAUSE); /* Start Ringing */ + + /* Now Enable Rectifier */ + /* select source for the levelmeter to be IO4-IO3 */ + codsp_write_sop_char(duslic_id, channel, LMCR2_ADDR, + LMCR2_LM_SEL_IO4_MINUS_IO3 | LMCR2_LM_RECT); + + /* Program the apropriate shift factor K_INTDC (in order to avoid Overflow at Integtation Result !!!) */ + codsp_write_cop_char(duslic_id, channel, RING_PARAMS_START_ADDR + 7, K_INTDC_RECT_ON); + + udelay(40000); + + /* Reenable Level Meter Integrator (The Result will be valid after Integration Period=Ring Period and until LN_EN become zero again) */ + codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, + LMCR1_LM_THM | LMCR1_LM_MASK | LMCR1_LM_EN | LMCR1_LM_ONCE); + + udelay(40000); + + /* Poll the LM_OK bit to see when Integration Result is Ready */ + if (wait_level_metering_finish(duslic_id, channel)) { + + udelay(10000); + + /* Now Read the LM Result Registers (They will hold their value until LM_EN become zero again */ + /* ==>After that Result Regs will be updated every 500us !!!) */ + Offset_Compensation = codsp_read_sop_short(duslic_id, channel, LMRES1_ADDR); + Offset_Compensation = (-1) * ((Offset_Compensation * (1 << K_INTDC_RECT_ON)) / N_SAMPLES); + + /* Disable LevelMeter ==> In order to be able to restart Integrator again (for the next integration) */ + codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK | LMCR1_LM_ONCE); + + /* Now programm Integrator Offset Registers !!! */ + codsp_write_sop_short(duslic_id, channel, OFR1_ADDR, Offset_Compensation); + + /* Be sure that a Ring is generated !!!! */ + codsp_set_slic(duslic_id, channel, SS_RINGING); /* Start Ringing again */ + + udelay(40000); + + /* Reenable Level Meter Integrator (The Result will be valid after Integration Period=Ring Period and until LN_EN become zero again) */ + codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, + LMCR1_LM_THM | LMCR1_LM_MASK | LMCR1_LM_EN | LMCR1_LM_ONCE); + + udelay(40000); + + /* Poll the LM_OK bit to see when Integration Result is Ready */ + if (wait_level_metering_finish(duslic_id, channel)) { + + udelay(10000); + + /* Now Read the LM Result Registers (They will hold their value until LM_EN become zero again */ + /* ==>After that Result Regs will be updated every 500us !!!) */ + LM_Result = codsp_read_sop_short(duslic_id, channel, LMRES1_ADDR); + V_in = (-1) * ( ( (((long int)LM_Result) * V_AD_x10000) / N_SAMPLES) >> (15 - K_INTDC_RECT_ON) ) ; /* Vin x 10000*/ + + V_out = (((V_in * Divider_Ratio) / 10000L) * RMS_MULTIPLIERx100) / 100 ; /* Vout_RMS x100 */ + if (V_out < 0) + V_out = -V_out; + + Vout_diff = (V_out - TARGET_V_RING_RMSx100); + + if (Vout_diff < 0) + Vout_diff = -Vout_diff; + + if (Vout_diff > V_RMS_RING_MAX_DIFFx100) + err_mask |= 16; + + *ring_rms_v = V_out; + } else { + err_mask |= 16; + *ring_rms_v = 0; + } + } else { + err_mask |= 16; + *ring_rms_v = 0; + } + /* Disable LevelMeter ==> In order to be able to restart Integrator again (for the next integration) */ + codsp_write_sop_char(duslic_id, channel, LMCR1_ADDR, LMCR1_LM_THM | LMCR1_LM_MASK); + + retrieve_slic_state(slic_id); + + return(err_mask); +} + +int test_dtmf(int slic_id) +{ + unsigned char code; + unsigned char b; + unsigned int intreg; + int duslic_id = slic_id >> 1; + int channel = slic_id & 1; + + for (code = 0; code < 16; code++) { + b = codsp_read_sop_char(duslic_id, channel, DSCR_ADDR); + codsp_write_sop_char(duslic_id, channel, DSCR_ADDR, + (b & ~(DSCR_PTG | DSCR_DG_KEY(15))) | DSCR_DG_KEY(code) | DSCR_TG1_EN | DSCR_TG2_EN); + udelay(80000); + + intreg = codsp_read_sop_int(duslic_id, channel, INTREG1_ADDR); + if ((intreg & CODSP_INTREG_INT_CH) == 0) + break; + + if ((intreg & CODSP_INTREG_DTMF_OK) == 0 || + codsp_dtmf_map[(intreg >> 10) & 15] != codsp_dtmf_map[code]) + break; + + b = codsp_read_sop_char(duslic_id, channel, DSCR_ADDR); + codsp_write_sop_char(duslic_id, channel, DSCR_ADDR, + b & ~(DSCR_COR8 | DSCR_TG1_EN | DSCR_TG2_EN)); + + udelay(80000); + + intreg = codsp_read_sop_int(duslic_id, channel, INTREG1_ADDR); /* for dtmf_pause irq */ + } + + if (code != 16) { + b = codsp_read_sop_char(duslic_id, channel, DSCR_ADDR); /* stop dtmf */ + codsp_write_sop_char(duslic_id, channel, DSCR_ADDR, + b & ~(DSCR_COR8 | DSCR_TG1_EN | DSCR_TG2_EN)); + return(1); + } + + return(0); +} + +void data_up_persist_time(int duslic_id, int channel, int time_ms) +{ + unsigned char b; + + b = codsp_read_sop_char(duslic_id, channel, IOCTL3_ADDR); + b = (b & 0x0F) | ((time_ms & 0x0F) << 4); + codsp_write_sop_char(duslic_id, channel, IOCTL3_ADDR, b); +} + +static void program_dtmf_params(int duslic_id, int channel) +{ + unsigned char b; + + codsp_write_pop_char(duslic_id, channel, DTMF_LEV_ADDR, 0x10); + codsp_write_pop_char(duslic_id, channel, DTMF_TWI_ADDR, 0x0C); + codsp_write_pop_char(duslic_id, channel, DTMF_NCF_H_ADDR, 0x79); + codsp_write_pop_char(duslic_id, channel, DTMF_NCF_L_ADDR, 0x10); + codsp_write_pop_char(duslic_id, channel, DTMF_NBW_H_ADDR, 0x02); + codsp_write_pop_char(duslic_id, channel, DTMF_NBW_L_ADDR, 0xFB); + codsp_write_pop_char(duslic_id, channel, DTMF_GAIN_ADDR, 0x91); + codsp_write_pop_char(duslic_id, channel, DTMF_RES1_ADDR, 0x00); + codsp_write_pop_char(duslic_id, channel, DTMF_RES2_ADDR, 0x00); + codsp_write_pop_char(duslic_id, channel, DTMF_RES3_ADDR, 0x00); + + b = codsp_read_sop_char(duslic_id, channel, BCR5_ADDR); + codsp_write_sop_char(duslic_id, channel, BCR5_ADDR, b | BCR5_DTMF_EN); +} + +static void codsp_channel_full_reset(int duslic_id, int channel) +{ + + program_coeffs(duslic_id, channel, ac_coeffs, sizeof(ac_coeffs) / sizeof(struct _coeffs)); + program_coeffs(duslic_id, channel, dc_coeffs, sizeof(dc_coeffs) / sizeof(struct _coeffs)); + + /* program basic configuration registers */ + codsp_write_sop_char(duslic_id, channel, BCR1_ADDR, 0x01); + codsp_write_sop_char(duslic_id, channel, BCR2_ADDR, 0x41); + codsp_write_sop_char(duslic_id, channel, BCR3_ADDR, 0x43); + codsp_write_sop_char(duslic_id, channel, BCR4_ADDR, 0x00); + codsp_write_sop_char(duslic_id, channel, BCR5_ADDR, 0x00); + + codsp_write_sop_char(duslic_id, channel, DSCR_ADDR, 0x04); /* PG */ + + program_dtmf_params(duslic_id, channel); + + codsp_write_sop_char(duslic_id, channel, LMCR3_ADDR, 0x40); /* RingTRip_SEL */ + + data_up_persist_time(duslic_id, channel, 4); + + codsp_write_sop_char(duslic_id, channel, MASK_ADDR, 0xFF); /* All interrupts masked */ + + codsp_set_slic(duslic_id, channel, SS_ACTIVE_HIGH); +} + +static int codsp_chip_full_reset(int duslic_id) +{ + int i, cnt; + int intreg[NUM_CHANNELS]; + unsigned char pcm_resync; + unsigned char revision; + + codsp_reset_chip(duslic_id); + + udelay(2000); + + for (i = 0; i < NUM_CHANNELS; i++) + intreg[i] = codsp_read_sop_int(duslic_id, i, INTREG1_ADDR); + + udelay(1500); + + if (_PORTC_GET(com_hook_mask_tab[duslic_id]) == 0) { + printf("_HOOK(%d) stayed low\n", duslic_id); + return -1; + } + + for (pcm_resync = 0, i = 0; i < NUM_CHANNELS; i++) { + if (intreg[i] & CODSP_INTREG_SYNC_FAIL) + pcm_resync |= 1 << i; + } + + for (cnt = 0; cnt < 5 && pcm_resync; cnt++) { + for (i = 0; i < NUM_CHANNELS; i++) + codsp_resync_channel(duslic_id, i); + + udelay(2000); + + pcm_resync = 0; + + for (i = 0; i < NUM_CHANNELS; i++) { + if (codsp_read_sop_int(duslic_id, i, INTREG1_ADDR) & CODSP_INTREG_SYNC_FAIL) + pcm_resync |= 1 << i; + } + } + + if (cnt == 5) { + printf("PCM_Resync(%u) not completed\n", duslic_id); + return -2; + } + + revision = codsp_read_sop_char(duslic_id, 0, REVISION_ADDR); + printf("DuSLIC#%d hardware version %d.%d\r\n", duslic_id, (revision & 0xF0) >> 4, revision & 0x0F); + + codsp_write_sop_char(duslic_id, 0, XCR_ADDR, 0x80); /* EDSP_EN */ + + for (i = 0; i < NUM_CHANNELS; i++) { + codsp_write_sop_char(duslic_id, i, PCMC1_ADDR, 0x01); + codsp_channel_full_reset(duslic_id, i); + } + + return 0; +} + +int slic_self_test(int duslic_mask) +{ + int slic; + int i; + int r; + long vdd, v_oh_H, v_oh_L, ring_mean_v, ring_rms_v; + const char *err_txt[] = { "VDD", "V_OH_H", "V_OH_L", "V_RING_MEAN", "V_RING_RMS" }; + int error = 0; + + for (slic = 0; slic < MAX_SLICS; slic++) { /* voltages self test */ + if (duslic_mask & (1 << (slic >> 1))) { + r = measure_on_hook_voltages(slic, &vdd, + &v_oh_H, &v_oh_L, &ring_mean_v, &ring_rms_v); + + printf("SLIC %u measured voltages (x100):\n\t" + "VDD = %ld\tV_OH_H = %ld\tV_OH_L = %ld\tV_RING_MEAN = %ld\tV_RING_RMS = %ld\n", + slic, vdd, v_oh_H, v_oh_L, ring_mean_v, ring_rms_v); + + if (r != 0) + error |= 1 << slic; + + for (i = 0; i < 5; i++) + if (r & (1 << i)) + printf("\t%s out of range\n", err_txt[i]); + } + } + + for (slic = 0; slic < MAX_SLICS; slic++) { /* voice path self test */ + if (duslic_mask & (1 << (slic >> 1))) { + printf("SLIC %u VOICE PATH...CHECKING", slic); + printf("\rSLIC %u VOICE PATH...%s\n", slic, + (r = test_dtmf(slic)) != 0 ? "FAILED " : "PASSED "); + + if (r != 0) + error |= 1 << slic; + } + } + + return(error); +} + +#if defined(CONFIG_NETTA_ISDN) + +#define SPIENS1 (1 << (31 - 15)) +#define SPIENS2 (1 << (31 - 19)) + +static const int spiens_mask_tab[2] = { SPIENS1, SPIENS2 }; +int s_initialized = 0; + +static inline unsigned int s_transfer_internal(int s_id, unsigned int address, unsigned int value) +{ + unsigned int rx, v; + + _PORTB_SET(spiens_mask_tab[s_id], 0); + + rx = __SPI_Transfer(address); + + switch (address & 0xF0) { + case 0x60: /* write byte register */ + case 0x70: + rx = __SPI_Transfer(value); + break; + + case 0xE0: /* read R6 register */ + v = __SPI_Transfer(0); + + rx = (rx << 8) | v; + + break; + + case 0xF0: /* read byte register */ + rx = __SPI_Transfer(0); + + break; + } + + _PORTB_SET(spiens_mask_tab[s_id], 1); + + return rx; +} + +static void s_write_BR(int s_id, unsigned int regno, unsigned int val) +{ + unsigned int address; + unsigned int v; + + address = 0x70 | (regno & 15); + val &= 0xff; + + v = s_transfer_internal(s_id, address, val); +} + +static void s_write_OR(int s_id, unsigned int regno, unsigned int val) +{ + unsigned int address; + unsigned int v; + + address = 0x70 | (regno & 15); + val &= 0xff; + + v = s_transfer_internal(s_id, address, val); +} + +static void s_write_NR(int s_id, unsigned int regno, unsigned int val) +{ + unsigned int address; + unsigned int v; + + address = (regno & 7) << 4; + val &= 0xf; + + v = s_transfer_internal(s_id, address | val, 0x00); +} + +#define BR7_IFR 0x08 /* IDL2 free run */ +#define BR7_ICSLSB 0x04 /* IDL2 clock speed LSB */ + +#define BR15_OVRL_REG_EN 0x80 +#define OR7_D3VR 0x80 /* disable 3V regulator */ + +#define OR8_TEME 0x10 /* TE mode enable */ +#define OR8_MME 0x08 /* master mode enable */ + +void s_initialize(void) +{ + int s_id; + + for (s_id = 0; s_id < 2; s_id++) { + s_write_BR(s_id, 7, BR7_IFR | BR7_ICSLSB); + s_write_BR(s_id, 15, BR15_OVRL_REG_EN); + s_write_OR(s_id, 8, OR8_TEME | OR8_MME); + s_write_OR(s_id, 7, OR7_D3VR); + s_write_OR(s_id, 6, 0); + s_write_BR(s_id, 15, 0); + s_write_NR(s_id, 3, 0); + } +} + +#endif + +int board_post_codec(int flags) +{ + int j; + int r; + int duslic_mask; + + printf("board_post_dsp\n"); + +#if defined(CONFIG_NETTA_ISDN) + if (s_initialized == 0) { + s_initialize(); + s_initialized = 1; + + printf("s_initialized\n"); + + udelay(20000); + } +#endif + duslic_mask = 0; + + for (j = 0; j < MAX_DUSLIC; j++) { + if (codsp_chip_full_reset(j) < 0) + printf("Error initializing DuSLIC#%d\n", j); + else + duslic_mask |= 1 << j; + } + + if (duslic_mask != 0) { + printf("Testing SLICs...\n"); + + r = slic_self_test(duslic_mask); + for (j = 0; j < MAX_SLICS; j++) { + if (duslic_mask & (1 << (j >> 1))) + printf("SLIC %u...%s\n", j, r & (1 << j) ? "FAULTY" : "OK"); + } + } + printf("DuSLIC self test finished\n"); + + return 0; /* return -1 on error */ +} diff --git a/board/netta/dsp.c b/board/netta/dsp.c index 2bea3adeae3..66e0b85e6c6 100644 --- a/board/netta/dsp.c +++ b/board/netta/dsp.c @@ -1,5 +1,5 @@ /* - * Intracom TI6711 DSP + * Intracom TI6711/TI6412 DSP */ #include <common.h> @@ -12,6 +12,38 @@ struct ram_range { u32 size; }; +#if defined(CONFIG_NETTA_6412) + +static const struct ram_range int_ram[] = { + { 0x00000000U, 0x00040000U }, +}; + +static const struct ram_range ext_ram[] = { + { 0x80000000U, 0x00100000U }, +}; + +static const struct ram_range ranges[] = { + { 0x00000000U, 0x00040000U }, + { 0x80000000U, 0x00100000U }, +}; + +static inline u16 bit_invert(u16 d) +{ + register u8 i; + register u16 r; + register u16 bit; + + r = 0; + for (i = 0; i < 16; i++) { + bit = d & (1 << i); + if (bit != 0) + r |= 1 << (15 - i); + } + return r; +} + +#else + static const struct ram_range int_ram[] = { { 0x00000000U, 0x00010000U }, }; @@ -25,6 +57,8 @@ static const struct ram_range ranges[] = { { 0x80000000U, 0x00100000U }, }; +#endif + /*******************************************************************************************************/ static inline int addr_in_int_ram(u32 addr) @@ -62,8 +96,11 @@ static volatile u32 *ti6711_delay = &dummy_delay; static inline void dsp_go_slow(void) { volatile memctl8xx_t *memctl = &((immap_t *)CFG_IMMR)->im_memctl; - +#if defined(CONFIG_NETTA_6412) + memctl->memc_or6 |= OR_SCY_15_CLK | OR_TRLX; +#else memctl->memc_or2 |= OR_SCY_15_CLK | OR_TRLX; +#endif memctl->memc_or5 |= OR_SCY_15_CLK | OR_TRLX; ti6711_delay = (u32 *)DUMMY_BASE; @@ -72,8 +109,11 @@ static inline void dsp_go_slow(void) static inline void dsp_go_fast(void) { volatile memctl8xx_t *memctl = &((immap_t *)CFG_IMMR)->im_memctl; - +#if defined(CONFIG_NETTA_6412) + memctl->memc_or6 = (memctl->memc_or6 & ~(OR_SCY_15_CLK | OR_TRLX)) | OR_SCY_0_CLK; +#else memctl->memc_or2 = (memctl->memc_or2 & ~(OR_SCY_15_CLK | OR_TRLX)) | OR_SCY_3_CLK; +#endif memctl->memc_or5 = (memctl->memc_or5 & ~(OR_SCY_15_CLK | OR_TRLX)) | OR_SCY_0_CLK; ti6711_delay = &dummy_delay; @@ -89,62 +129,50 @@ static inline void dsp_delay(void) static inline u16 dsp_read_hpic(void) { +#if defined(CONFIG_NETTA_6412) + return bit_invert(*((volatile u16 *)DSP_BASE)); +#else return *((volatile u16 *)DSP_BASE); +#endif } static inline void dsp_write_hpic(u16 val) { +#if defined(CONFIG_NETTA_6412) + *((volatile u16 *)DSP_BASE) = bit_invert(val); +#else *((volatile u16 *)DSP_BASE) = val; +#endif } static inline void dsp_reset(void) { +#if defined(CONFIG_NETTA_6412) + ((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pddat &= ~(1 << (15 - 15)); + udelay(500); + ((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pddat |= (1 << (15 - 15)); + udelay(500); +#else ((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pddat &= ~(1 << (15 - 7)); udelay(250); ((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pddat |= (1 << (15 - 7)); udelay(250); -} - -static inline void dsp_init_hpic(void) -{ - int i; - volatile u16 *p; - - dsp_go_slow(); - - i = 0; - while (i < 1000 && (dsp_read_hpic() & 0x08) == 0) { - dsp_delay(); - i++; - } - dsp_delay(); - - /* write control register */ - p = (volatile u16 *)DSP_BASE; - p[0] = 0x0000; - dsp_delay(); - p[1] = 0x0000; - dsp_delay(); - - dsp_go_fast(); -} - -static inline void dsp_wait_hrdy(void) -{ - int i; - - i = 0; - while (i < 1000 && (dsp_read_hpic() & 0x08) == 0) { - dsp_delay(); - i++; - } +#endif } static inline u32 dsp_read_hpic_word(u32 addr) { u32 val; volatile u16 *p; +#if defined(CONFIG_NETTA_6412) + p = (volatile u16 *)((volatile u8 *)DSP_BASE + addr); + val = ((u32) bit_invert(p[0]) << 16); + /* dsp_delay(); */ + + val |= bit_invert(p[1]); + /* dsp_delay(); */ +#else p = (volatile u16 *)((volatile u8 *)DSP_BASE + addr); val = ((u32) p[0] << 16); @@ -152,40 +180,80 @@ static inline u32 dsp_read_hpic_word(u32 addr) val |= p[1]; dsp_delay(); - +#endif return val; } static inline u16 dsp_read_hpic_hi_hword(u32 addr) { +#if defined(CONFIG_NETTA_6412) + return bit_invert(*(volatile u16 *)((volatile u8 *)DSP_BASE + addr)); +#else return *(volatile u16 *)((volatile u8 *)DSP_BASE + addr); +#endif } static inline u16 dsp_read_hpic_lo_hword(u32 addr) { +#if defined(CONFIG_NETTA_6412) + return bit_invert(*(volatile u16 *)((volatile u8 *)DSP_BASE + addr + 2)); +#else return *(volatile u16 *)((volatile u8 *)DSP_BASE + addr + 2); +#endif +} + +static inline void dsp_wait_hrdy(void) +{ + int i; + + i = 0; +#if defined(CONFIG_NETTA_6412) + while (i < 1000 && (dsp_read_hpic_word(DSP_HPIC) & 0x08) == 0) { +#else + while (i < 1000 && (dsp_read_hpic() & 0x08) == 0) { +#endif + dsp_delay(); + i++; + } } static inline void dsp_write_hpic_word(u32 addr, u32 val) { volatile u16 *p; +#if defined(CONFIG_NETTA_6412) + p = (volatile u16 *)((volatile u8 *)DSP_BASE + addr); + p[0] = bit_invert((u16)(val >> 16)); + /* dsp_delay(); */ + p[1] = bit_invert((u16)val); + /* dsp_delay(); */ +#else p = (volatile u16 *)((volatile u8 *)DSP_BASE + addr); p[0] = (u16)(val >> 16); dsp_delay(); p[1] = (u16)val; dsp_delay(); +#endif } static inline void dsp_write_hpic_hi_hword(u32 addr, u16 val_h) { +#if defined(CONFIG_NETTA_6412) + *(volatile u16 *)((volatile u8 *)DSP_BASE + addr) = bit_invert(val_h); +#else + *(volatile u16 *)((volatile u8 *)DSP_BASE + addr) = val_h; +#endif } static inline void dsp_write_hpic_lo_hword(u32 addr, u16 val_l) { +#if defined(CONFIG_NETTA_6412) + *(volatile u16 *)((volatile u8 *)DSP_BASE + addr + 2) = bit_invert(val_l); +#else *(volatile u16 *)((volatile u8 *)DSP_BASE + addr + 2) = val_l; +#endif } /********************************************************************/ @@ -193,21 +261,29 @@ static inline void dsp_write_hpic_lo_hword(u32 addr, u16 val_l) static inline void c62_write_word(u32 addr, u32 val) { dsp_write_hpic_hi_hword(DSP_HPIA, (u16)(addr >> 16)); +#if !defined(CONFIG_NETTA_6412) dsp_delay(); +#endif dsp_write_hpic_lo_hword(DSP_HPIA, (u16)addr); +#if !defined(CONFIG_NETTA_6412) dsp_delay(); +#endif dsp_wait_hrdy(); +#if !defined(CONFIG_NETTA_6412) dsp_delay(); - +#endif dsp_write_hpic_hi_hword(DSP_HPID2, (u16)(val >> 16)); +#if !defined(CONFIG_NETTA_6412) dsp_delay(); - dsp_wait_hrdy(); - dsp_delay(); - + /* dsp_wait_hrdy(); + dsp_delay(); */ +#endif dsp_write_hpic_lo_hword(DSP_HPID2, (u16)val); +#if !defined(CONFIG_NETTA_6412) dsp_delay(); +#endif } static u32 c62_read_word(u32 addr) @@ -215,26 +291,36 @@ static u32 c62_read_word(u32 addr) u32 val; dsp_write_hpic_hi_hword(DSP_HPIA, (u16)(addr >> 16)); +#if !defined(CONFIG_NETTA_6412) dsp_delay(); +#endif dsp_write_hpic_lo_hword(DSP_HPIA, (u16)addr); +#if !defined(CONFIG_NETTA_6412) dsp_delay(); +#endif /* FETCH */ +#if defined(CONFIG_NETTA_6412) + dsp_write_hpic_word(DSP_HPIC, 0x00100010); +#else dsp_write_hpic(0x10); dsp_delay(); - +#endif dsp_wait_hrdy(); +#if !defined(CONFIG_NETTA_6412) dsp_delay(); - +#endif val = (u32)dsp_read_hpic_hi_hword(DSP_HPID2) << 16; +#if !defined(CONFIG_NETTA_6412) dsp_delay(); - dsp_wait_hrdy(); - dsp_delay(); - + /* dsp_wait_hrdy(); + dsp_delay(); */ +#endif val |= dsp_read_hpic_lo_hword(DSP_HPID2); +#if !defined(CONFIG_NETTA_6412) dsp_delay(); - +#endif return val; } @@ -300,8 +386,88 @@ static inline int c62_write_validated(u32 addr, const u32 *buffer, int numdata) return 0; } +#if defined(CONFIG_NETTA_6412) + +#define DRAM_REGS_BASE 0x1800000 + +#define GBLCTL DRAM_REGS_BASE +#define CECTL1 (DRAM_REGS_BASE + 0x4) +#define CECTL0 (DRAM_REGS_BASE + 0x8) +#define CECTL2 (DRAM_REGS_BASE + 0x10) +#define CECTL3 (DRAM_REGS_BASE + 0x14) +#define SDCTL (DRAM_REGS_BASE + 0x18) +#define SDTIM (DRAM_REGS_BASE + 0x1C) +#define SDEXT (DRAM_REGS_BASE + 0x20) +#define SESEC1 (DRAM_REGS_BASE + 0x44) +#define SESEC0 (DRAM_REGS_BASE + 0x48) +#define SESEC2 (DRAM_REGS_BASE + 0x50) +#define SESEC3 (DRAM_REGS_BASE + 0x54) + +#define MAR128 0x1848200 +#define MAR129 0x1848204 + +void dsp_dram_initialize(void) +{ + c62_write_word(GBLCTL, 0x120E4); + c62_write_word(CECTL1, 0x18); + c62_write_word(CECTL0, 0xD0); + c62_write_word(CECTL2, 0x18); + c62_write_word(CECTL3, 0x18); + c62_write_word(SDCTL, 0x47115000); + c62_write_word(SDTIM, 1536); + c62_write_word(SDEXT, 0x534A9); +#if 0 + c62_write_word(SESEC1, 0); + c62_write_word(SESEC0, 0); + c62_write_word(SESEC2, 0); + c62_write_word(SESEC3, 0); +#endif + c62_write_word(MAR128, 1); + c62_write_word(MAR129, 0); +} + +#endif + +static inline void dsp_init_hpic(void) +{ + int i; + volatile u16 *p; +#if defined(CONFIG_NETTA_6412) + dsp_go_fast(); +#else + dsp_go_slow(); +#endif + i = 0; +#if defined(CONFIG_NETTA_6412) + while (i < 1000 && (dsp_read_hpic_word(DSP_HPIC) & 0x08) == 0) { +#else + while (i < 1000 && (dsp_read_hpic() & 0x08) == 0) { +#endif + dsp_delay(); + i++; + } + + if (i == 1000) + printf("HRDY stuck\n"); + + dsp_delay(); + + /* write control register */ + p = (volatile u16 *)DSP_BASE; + p[0] = 0x0000; + dsp_delay(); + p[1] = 0x0000; + dsp_delay(); + +#if !defined(CONFIG_NETTA_6412) + dsp_go_fast(); +#endif +} + /***********************************************************************************************************/ +#if !defined(CONFIG_NETTA_6412) + static const u8 bootstrap_rbin[5084] = { 0x52, 0x42, 0x49, 0x4e, 0xc5, 0xa9, 0x9f, 0x1a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, @@ -931,18 +1097,23 @@ static void run_bootstrap(void) dsp_go_fast(); } +#endif + /***********************************************************************************************************/ int board_post_dsp(int flags) { u32 ramS, ramE; u32 data, data2; - int i, j, k, r; - + int i, j, k; +#if !defined(CONFIG_NETTA_6412) + int r; +#endif dsp_reset(); dsp_init_hpic(); +#if !defined(CONFIG_NETTA_6412) dsp_go_slow(); - +#endif data = 0x11223344; dsp_write_hpic_word(DSP_HPIA, data); data2 = dsp_read_hpic_word(DSP_HPIA); @@ -958,7 +1129,9 @@ int board_post_dsp(int flags) printf("HPIA: ** ERROR; wrote 0x%08X read 0x%08X **\n", data, data2); goto err; } - +#if defined(CONFIG_NETTA_6412) + dsp_dram_initialize(); +#else r = load_bootstrap(); if (r < 0) { printf("BOOTSTRAP: ** ERROR ** failed to load\n"); @@ -968,7 +1141,7 @@ int board_post_dsp(int flags) run_bootstrap(); dsp_go_fast(); - +#endif printf(" "); /* test RAMs */ @@ -1001,12 +1174,12 @@ int board_post_dsp(int flags) } printf("\b\b\b\b \b\b\b\bOK\n"); - +#if !defined(CONFIG_NETTA_6412) /* XXX assume that this works */ load_bootstrap(); run_bootstrap(); dsp_go_fast(); - +#endif return 0; err: @@ -1015,10 +1188,14 @@ err: int board_dsp_reset(void) { +#if !defined(CONFIG_NETTA_6412) int r; - +#endif dsp_reset(); dsp_init_hpic(); +#if defined(CONFIG_NETTA_6412) + dsp_dram_initialize(); +#else dsp_go_slow(); r = load_bootstrap(); if (r < 0) @@ -1026,6 +1203,6 @@ int board_dsp_reset(void) run_bootstrap(); dsp_go_fast(); - +#endif return 0; } diff --git a/board/netta/netta.c b/board/netta/netta.c index afb3fe18332..e7024e52d3c 100644 --- a/board/netta/netta.c +++ b/board/netta/netta.c @@ -64,6 +64,11 @@ int checkboard(void) #if defined(CONFIG_NETTA_ISDN) " with ISDN support" #endif +#if defined(CONFIG_NETTA_6412) + " (DSP:TI6412)" +#else + " (DSP:TI6711)" +#endif "\n" ); return (0); @@ -462,10 +467,10 @@ int last_stage_init(void) #define PA_SP_DIRVAL 0 #define PB_GP_INMASK (_B(28) | _B(31)) -#define PB_GP_OUTMASK (_BR(16, 19) | _BR(26, 27) | _BR(29, 30)) +#define PB_GP_OUTMASK (_BR(15, 19) | _BR(26, 27) | _BR(29, 30)) #define PB_SP_MASK (_BR(22, 25)) #define PB_ODR_VAL 0 -#define PB_GP_OUTVAL (_BR(16, 19) | _BR(26, 27) | _BR(29, 31)) +#define PB_GP_OUTVAL (_BR(15, 19) | _BR(26, 27) | _BR(29, 31)) #define PB_SP_DIRVAL 0 #define PC_GP_INMASK (_BW(5) | _BW(7) | _BW(8) | _BWR(9, 11) | _BWR(13, 15)) @@ -479,7 +484,17 @@ int last_stage_init(void) #define PD_GP_INMASK 0 #define PD_GP_OUTMASK _BWR(3, 15) #define PD_SP_MASK 0 + +#if defined(CONFIG_NETTA_6412) + +#define PD_GP_OUTVAL (_BWR(5, 7) | _BW(9) | _BW(11) | _BW(15)) + +#else + #define PD_GP_OUTVAL (_BWR(5, 7) | _BW(9) | _BW(11)) + +#endif + #define PD_SP_DIRVAL 0 int board_early_init_f(void) @@ -492,11 +507,15 @@ int board_early_init_f(void) /* CS1: NAND chip select */ memctl->memc_or1 = ((0xFFFFFFFFLU & ~(NAND_SIZE - 1)) | OR_BI | OR_SCY_2_CLK | OR_TRLX | OR_ACS_DIV2) ; memctl->memc_br1 = ((NAND_BASE & BR_BA_MSK) | BR_PS_8 | BR_V); - +#if !defined(CONFIG_NETTA_6412) /* CS2: DSP */ memctl->memc_or2 = ((0xFFFFFFFFLU & ~(DSP_SIZE - 1)) | OR_CSNT_SAM | OR_BI | OR_SCY_7_CLK | OR_ACS_DIV2); memctl->memc_br2 = ((DSP_BASE & BR_BA_MSK) | BR_PS_16 | BR_V); - +#else + /* CS6: DSP */ + memctl->memc_or6 = ((0xFFFFFFFFLU & ~(DSP_SIZE - 1)) | OR_CSNT_SAM | OR_BI | OR_SCY_7_CLK | OR_ACS_DIV2); + memctl->memc_br6 = ((DSP_BASE & BR_BA_MSK) | BR_PS_16 | BR_V); +#endif /* CS4: External register chip select */ memctl->memc_or4 = ((0xFFFFFFFFLU & ~(ER_SIZE - 1)) | OR_BI | OR_SCY_4_CLK); memctl->memc_br4 = ((ER_BASE & BR_BA_MSK) | BR_PS_32 | BR_V); @@ -525,7 +544,7 @@ int board_early_init_f(void) ioport->iop_pddir = PD_GP_OUTMASK | PD_SP_DIRVAL; ioport->iop_pdpar = PD_SP_MASK; - ioport->iop_pddat |= (1 << (15 - 6)) | (1 << (15 - 7)); + /* ioport->iop_pddat |= (1 << (15 - 6)) | (1 << (15 - 7)); */ return 0; } diff --git a/board/netta2/Makefile b/board/netta2/Makefile new file mode 100644 index 00000000000..d45702091f0 --- /dev/null +++ b/board/netta2/Makefile @@ -0,0 +1,40 @@ +# +# (C) Copyright 2000-2004 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o flash.o + +$(LIB): .depend $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/netta2/config.mk b/board/netta2/config.mk new file mode 100644 index 00000000000..8497ebc812b --- /dev/null +++ b/board/netta2/config.mk @@ -0,0 +1,28 @@ +# +# (C) Copyright 2000-2004 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +# +# netVia Boards +# + +TEXT_BASE = 0x40000000 diff --git a/board/netta2/flash.c b/board/netta2/flash.c new file mode 100644 index 00000000000..a1c87f51310 --- /dev/null +++ b/board/netta2/flash.c @@ -0,0 +1,506 @@ +/* + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc8xx.h> + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size(vu_long * addr, flash_info_t * info); +static int write_byte(flash_info_t * info, ulong dest, uchar data); +static void flash_get_offsets(ulong base, flash_info_t * info); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init(void) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + unsigned long size; + int i; + + /* Init: no FLASHes known */ + for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) + flash_info[i].flash_id = FLASH_UNKNOWN; + + size = flash_get_size((vu_long *) FLASH_BASE0_PRELIM, &flash_info[0]); + + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", + size, size << 20); + } + + /* Remap FLASH according to real size */ + memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size & 0xFFFF8000); + memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | (memctl->memc_br0 & ~(BR_BA_MSK)); + + /* Re-do sizing to get full correct info */ + size = flash_get_size((vu_long *) CFG_FLASH_BASE, &flash_info[0]); + + flash_get_offsets(CFG_FLASH_BASE, &flash_info[0]); + + /* monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_FLASH_BASE, CFG_FLASH_BASE + monitor_flash_len - 1, + &flash_info[0]); + + flash_protect ( FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SIZE - 1, + &flash_info[0]); + +#ifdef CFG_ENV_ADDR_REDUND + flash_protect ( FLAG_PROTECT_SET, + CFG_ENV_ADDR_REDUND, + CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1, + &flash_info[0]); +#endif + + flash_info[0].size = size; + + return (size); +} + +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets(ulong base, flash_info_t * info) +{ + int i; + + /* set up sector start address table */ + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) { + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00010000); + } + } else if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00010000) - 0x00030000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + } +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info(flash_info_t * info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_AMD: + printf("AMD "); + break; + case FLASH_MAN_FUJ: + printf("FUJITSU "); + break; + case FLASH_MAN_MX: + printf("MXIC "); + break; + default: + printf("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM040: + printf("AM29LV040B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM400B: + printf("AM29LV400B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM400T: + printf("AM29LV400T (4 Mbit, top boot sector)\n"); + break; + case FLASH_AM800B: + printf("AM29LV800B (8 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM800T: + printf("AM29LV800T (8 Mbit, top boot sector)\n"); + break; + case FLASH_AM160B: + printf("AM29LV160B (16 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM160T: + printf("AM29LV160T (16 Mbit, top boot sector)\n"); + break; + case FLASH_AM320B: + printf("AM29LV320B (32 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM320T: + printf("AM29LV320T (32 Mbit, top boot sector)\n"); + break; + default: + printf("Unknown Chip Type\n"); + break; + } + + printf(" Size: %ld MB in %d Sectors\n", info->size >> 20, info->sector_count); + + printf(" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; ++i) { + if ((i % 5) == 0) + printf("\n "); + printf(" %08lX%s", info->start[i], info->protect[i] ? " (RO)" : " "); + } + printf("\n"); +} + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ + +static ulong flash_get_size(vu_long * addr, flash_info_t * info) +{ + short i; + uchar mid; + uchar pid; + vu_char *caddr = (vu_char *) addr; + ulong base = (ulong) addr; + + /* Write auto select command: read Manufacturer ID */ + caddr[0x0555] = 0xAA; + caddr[0x02AA] = 0x55; + caddr[0x0555] = 0x90; + + mid = caddr[0]; + switch (mid) { + case (AMD_MANUFACT & 0xFF): + info->flash_id = FLASH_MAN_AMD; + break; + case (FUJ_MANUFACT & 0xFF): + info->flash_id = FLASH_MAN_FUJ; + break; + case (MX_MANUFACT & 0xFF): + info->flash_id = FLASH_MAN_MX; + break; + case (STM_MANUFACT & 0xFF): + info->flash_id = FLASH_MAN_STM; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + + pid = caddr[1]; /* device ID */ + switch (pid) { + case (AMD_ID_LV400T & 0xFF): + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 512 kB */ + + case (AMD_ID_LV400B & 0xFF): + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 512 kB */ + + case (AMD_ID_LV800T & 0xFF): + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (AMD_ID_LV800B & 0xFF): + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (AMD_ID_LV160T & 0xFF): + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (AMD_ID_LV160B & 0xFF): + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (AMD_ID_LV040B & 0xFF): + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x00080000; + break; + + case (STM_ID_M29W040B & 0xFF): + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x00080000; + break; + +#if 0 /* enable when device IDs are available */ + case (AMD_ID_LV320T & 0xFF): + info->flash_id += FLASH_AM320T; + info->sector_count = 67; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (AMD_ID_LV320B & 0xFF): + info->flash_id += FLASH_AM320B; + info->sector_count = 67; + info->size = 0x00400000; + break; /* => 4 MB */ +#endif + default: + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + + } + + printf(" "); + /* set up sector start address table */ + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) { + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00010000); + } + } else if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00010000) - 0x00030000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + } + + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) { + /* read sector protection: D0 = 1 if protected */ + caddr = (volatile unsigned char *)(info->start[i]); + info->protect[i] = caddr[2] & 1; + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { + caddr = (vu_char *) info->start[0]; + + caddr[0x0555] = 0xAA; + caddr[0x02AA] = 0x55; + caddr[0x0555] = 0xF0; + + udelay(20000); + } + + return (info->size); +} + + +/*----------------------------------------------------------------------- + */ + +int flash_erase(flash_info_t * info, int s_first, int s_last) +{ + vu_char *addr = (vu_char *) (info->start[0]); + int flag, prot, sect, l_sect; + ulong start, now, last; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf("- missing\n"); + } else { + printf("- no sectors to erase\n"); + } + return 1; + } + + if ((info->flash_id == FLASH_UNKNOWN) || + (info->flash_id > FLASH_AMD_COMP)) { + printf("Can't erase unknown flash type %08lx - aborted\n", info->flash_id); + 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"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr[0x0555] = 0xAA; + addr[0x02AA] = 0x55; + addr[0x0555] = 0x80; + addr[0x0555] = 0xAA; + addr[0x02AA] = 0x55; + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr = (vu_char *) (info->start[sect]); + addr[0] = 0x30; + l_sect = sect; + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay(1000); + + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + + start = get_timer(0); + last = start; + addr = (vu_char *) (info->start[l_sect]); + while ((addr[0] & 0x80) != 0x80) { + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf("Timeout\n"); + return 1; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc('.'); + last = now; + } + } + +DONE: + /* reset to read mode */ + addr = (vu_char *) info->start[0]; + addr[0] = 0xF0; /* reset bank */ + + printf(" done\n"); + return 0; +} + +/*----------------------------------------------------------------------- + * 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) +{ + int rc; + + while (cnt > 0) { + if ((rc = write_byte(info, addr++, *src++)) != 0) { + return (rc); + } + --cnt; + } + + return (0); +} + +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_byte(flash_info_t * info, ulong dest, uchar data) +{ + vu_char *addr = (vu_char *) (info->start[0]); + ulong start; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if ((*((vu_char *) dest) & data) != data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr[0x0555] = 0xAA; + addr[0x02AA] = 0x55; + addr[0x0555] = 0xA0; + + *((vu_char *) dest) = data; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer(0); + while ((*((vu_char *) dest) & 0x80) != (data & 0x80)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + return (0); +} diff --git a/board/netta2/netta2.c b/board/netta2/netta2.c new file mode 100644 index 00000000000..f4ce7a4946e --- /dev/null +++ b/board/netta2/netta2.c @@ -0,0 +1,664 @@ +/* + * (C) Copyright 2000-2004 + * Pantelis Antoniou, Intracom S.A., panto@intracom.gr + * 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 + */ + +/* + * Pantelis Antoniou, Intracom S.A., panto@intracom.gr + * U-Boot port on NetTA4 board + */ + +#include <common.h> +#include <miiphy.h> + +#include "mpc8xx.h" + +#ifdef CONFIG_HW_WATCHDOG +#include <watchdog.h> +#endif + +/****************************************************************/ + +/* some sane bit macros */ +#define _BD(_b) (1U << (31-(_b))) +#define _BDR(_l, _h) (((((1U << (31-(_l))) - 1) << 1) | 1) & ~((1U << (31-(_h))) - 1)) + +#define _BW(_b) (1U << (15-(_b))) +#define _BWR(_l, _h) (((((1U << (15-(_l))) - 1) << 1) | 1) & ~((1U << (15-(_h))) - 1)) + +#define _BB(_b) (1U << (7-(_b))) +#define _BBR(_l, _h) (((((1U << (7-(_l))) - 1) << 1) | 1) & ~((1U << (7-(_h))) - 1)) + +#define _B(_b) _BD(_b) +#define _BR(_l, _h) _BDR(_l, _h) + +/****************************************************************/ + +/* + * Check Board Identity: + * + * Return 1 always. + */ + +int checkboard(void) +{ + printf ("Intracom NetTA2 V%d\n", CONFIG_NETTA2_VERSION); + return (0); +} + +/****************************************************************/ + +#define _NOT_USED_ 0xFFFFFFFF + +/****************************************************************/ + +#define CS_0000 0x00000000 +#define CS_0001 0x10000000 +#define CS_0010 0x20000000 +#define CS_0011 0x30000000 +#define CS_0100 0x40000000 +#define CS_0101 0x50000000 +#define CS_0110 0x60000000 +#define CS_0111 0x70000000 +#define CS_1000 0x80000000 +#define CS_1001 0x90000000 +#define CS_1010 0xA0000000 +#define CS_1011 0xB0000000 +#define CS_1100 0xC0000000 +#define CS_1101 0xD0000000 +#define CS_1110 0xE0000000 +#define CS_1111 0xF0000000 + +#define BS_0000 0x00000000 +#define BS_0001 0x01000000 +#define BS_0010 0x02000000 +#define BS_0011 0x03000000 +#define BS_0100 0x04000000 +#define BS_0101 0x05000000 +#define BS_0110 0x06000000 +#define BS_0111 0x07000000 +#define BS_1000 0x08000000 +#define BS_1001 0x09000000 +#define BS_1010 0x0A000000 +#define BS_1011 0x0B000000 +#define BS_1100 0x0C000000 +#define BS_1101 0x0D000000 +#define BS_1110 0x0E000000 +#define BS_1111 0x0F000000 + +#define GPL0_AAAA 0x00000000 +#define GPL0_AAA0 0x00200000 +#define GPL0_AAA1 0x00300000 +#define GPL0_000A 0x00800000 +#define GPL0_0000 0x00A00000 +#define GPL0_0001 0x00B00000 +#define GPL0_111A 0x00C00000 +#define GPL0_1110 0x00E00000 +#define GPL0_1111 0x00F00000 + +#define GPL1_0000 0x00000000 +#define GPL1_0001 0x00040000 +#define GPL1_1110 0x00080000 +#define GPL1_1111 0x000C0000 + +#define GPL2_0000 0x00000000 +#define GPL2_0001 0x00010000 +#define GPL2_1110 0x00020000 +#define GPL2_1111 0x00030000 + +#define GPL3_0000 0x00000000 +#define GPL3_0001 0x00004000 +#define GPL3_1110 0x00008000 +#define GPL3_1111 0x0000C000 + +#define GPL4_0000 0x00000000 +#define GPL4_0001 0x00001000 +#define GPL4_1110 0x00002000 +#define GPL4_1111 0x00003000 + +#define GPL5_0000 0x00000000 +#define GPL5_0001 0x00000400 +#define GPL5_1110 0x00000800 +#define GPL5_1111 0x00000C00 +#define LOOP 0x00000080 + +#define EXEN 0x00000040 + +#define AMX_COL 0x00000000 +#define AMX_ROW 0x00000020 +#define AMX_MAR 0x00000030 + +#define NA 0x00000008 + +#define UTA 0x00000004 + +#define TODT 0x00000002 + +#define LAST 0x00000001 + +#define A10_AAAA GPL0_AAAA +#define A10_AAA0 GPL0_AAA0 +#define A10_AAA1 GPL0_AAA1 +#define A10_000A GPL0_000A +#define A10_0000 GPL0_0000 +#define A10_0001 GPL0_0001 +#define A10_111A GPL0_111A +#define A10_1110 GPL0_1110 +#define A10_1111 GPL0_1111 + +#define RAS_0000 GPL1_0000 +#define RAS_0001 GPL1_0001 +#define RAS_1110 GPL1_1110 +#define RAS_1111 GPL1_1111 + +#define CAS_0000 GPL2_0000 +#define CAS_0001 GPL2_0001 +#define CAS_1110 GPL2_1110 +#define CAS_1111 GPL2_1111 + +#define WE_0000 GPL3_0000 +#define WE_0001 GPL3_0001 +#define WE_1110 GPL3_1110 +#define WE_1111 GPL3_1111 + +/* #define CAS_LATENCY 3 */ +#define CAS_LATENCY 2 + +const uint sdram_table[0x40] = { + +#if CAS_LATENCY == 3 + /* RSS */ + CS_0001 | BS_1111 | A10_AAAA | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* ACT */ + CS_1111 | BS_1111 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */ + CS_0000 | BS_1111 | A10_0001 | RAS_1111 | CAS_0001 | WE_1111 | AMX_COL | UTA, /* READ */ + CS_0001 | BS_0001 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL | UTA, /* PALL */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA | TODT | LAST, /* NOP */ + _NOT_USED_, _NOT_USED_, + + /* RBS */ + CS_0001 | BS_1111 | A10_AAAA | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* ACT */ + CS_1111 | BS_1111 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */ + CS_0001 | BS_1111 | A10_0001 | RAS_1111 | CAS_0001 | WE_1111 | AMX_COL | UTA, /* READ */ + CS_1111 | BS_0000 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */ + CS_1111 | BS_0000 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_1111 | BS_0000 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_0001 | BS_0001 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL, /* PALL */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | TODT | LAST, /* NOP */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* WSS */ + CS_0001 | BS_1111 | A10_AAAA | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* ACT */ + CS_1111 | BS_1111 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_0000 | BS_0001 | A10_0000 | RAS_1111 | CAS_0001 | WE_0000 | AMX_COL | UTA, /* WRITE */ + CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL | UTA, /* PALL */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA | TODT | LAST, /* NOP */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* WBS */ + CS_0001 | BS_1111 | A10_AAAA | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* ACT */ + CS_1111 | BS_1111 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_0001 | BS_0000 | A10_0000 | RAS_1111 | CAS_0001 | WE_0000 | AMX_COL, /* WRITE */ + CS_1111 | BS_0000 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_1111 | BS_0000 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_1111 | BS_0001 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */ + CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL | UTA, /* PALL */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA | TODT | LAST, /* NOP */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, +#endif + +#if CAS_LATENCY == 2 + /* RSS */ + CS_0001 | BS_1111 | A10_AAAA | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* ACT */ + CS_1110 | BS_1110 | A10_0000 | RAS_1111 | CAS_1110 | WE_1111 | AMX_COL | UTA, /* NOP */ + CS_0001 | BS_0001 | A10_0000 | RAS_1111 | CAS_0001 | WE_1111 | AMX_COL | UTA, /* READ */ + CS_1110 | BS_1111 | A10_0001 | RAS_1110 | CAS_1111 | WE_1110 | AMX_COL, /* NOP */ + CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL | UTA | TODT | LAST, /* PALL */ + _NOT_USED_, + _NOT_USED_, _NOT_USED_, + + /* RBS */ + CS_0001 | BS_1111 | A10_AAAA | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* ACT */ + CS_1110 | BS_1110 | A10_0000 | RAS_1111 | CAS_1110 | WE_1111 | AMX_COL | UTA, /* NOP */ + CS_0001 | BS_0000 | A10_0000 | RAS_1111 | CAS_0001 | WE_1111 | AMX_COL | UTA, /* READ */ + CS_1111 | BS_0000 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_1111 | BS_0000 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_1111 | BS_0001 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_1110 | BS_1111 | A10_0001 | RAS_1110 | CAS_1111 | WE_1110 | AMX_COL, /* NOP */ + CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL | UTA | TODT | LAST, /* PALL */ + _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* WSS */ + CS_0001 | BS_1111 | A10_AAA0 | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* ACT */ + CS_1110 | BS_1110 | A10_0000 | RAS_1111 | CAS_1110 | WE_1110 | AMX_COL, /* NOP */ + CS_0000 | BS_0001 | A10_0001 | RAS_1110 | CAS_0001 | WE_0000 | AMX_COL | UTA, /* WRITE */ + CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL | UTA | TODT | LAST, /* PALL */ + _NOT_USED_, + _NOT_USED_, _NOT_USED_, + _NOT_USED_, + + /* WBS */ + CS_0001 | BS_1111 | A10_AAAA | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* ACT */ + CS_1110 | BS_1110 | A10_0000 | RAS_1111 | CAS_1110 | WE_1110 | AMX_COL, /* NOP */ + CS_0001 | BS_0000 | A10_0000 | RAS_1111 | CAS_0001 | WE_0001 | AMX_COL, /* WRITE */ + CS_1111 | BS_0000 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_1111 | BS_0000 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_1110 | BS_0001 | A10_0001 | RAS_1110 | CAS_1111 | WE_1110 | AMX_COL | UTA, /* NOP */ + CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL | UTA | TODT | LAST, /* PALL */ + _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, + +#endif + + /* UPT */ + CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_0001 | WE_1111 | AMX_COL | UTA | LOOP, /* ATRFR */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA | LOOP, /* NOP */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA | TODT | LAST, /* NOP */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, + + /* EXC */ + CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL | UTA | LAST, + _NOT_USED_, + + /* REG */ + CS_1110 | BS_1111 | A10_1110 | RAS_1110 | CAS_1110 | WE_1110 | AMX_MAR | UTA, + CS_0001 | BS_1111 | A10_0001 | RAS_0001 | CAS_0001 | WE_0001 | AMX_MAR | UTA | LAST, +}; + +#if CONFIG_NETTA2_VERSION == 2 +static const uint nandcs_table[0x40] = { + /* RSS */ + CS_1000 | GPL4_1111 | GPL5_1111 | UTA, + CS_0000 | GPL4_1110 | GPL5_1111 | UTA, + CS_0000 | GPL4_0000 | GPL5_1111 | UTA, + CS_0000 | GPL4_0000 | GPL5_1111 | UTA, + CS_0000 | GPL4_0000 | GPL5_1111, + CS_0000 | GPL4_0001 | GPL5_1111 | UTA, + CS_0000 | GPL4_1111 | GPL5_1111 | UTA, + CS_0011 | GPL4_1111 | GPL5_1111 | UTA | LAST, /* NOP */ + + /* RBS */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* WSS */ + CS_1000 | GPL4_1111 | GPL5_1110 | UTA, + CS_0000 | GPL4_1111 | GPL5_0000 | UTA, + CS_0000 | GPL4_1111 | GPL5_0000 | UTA, + CS_0000 | GPL4_1111 | GPL5_0000 | UTA, + CS_0000 | GPL4_1111 | GPL5_0001 | UTA, + CS_0000 | GPL4_1111 | GPL5_1111 | UTA, + CS_0000 | GPL4_1111 | GPL5_1111, + CS_0011 | GPL4_1111 | GPL5_1111 | UTA | LAST, + + /* WBS */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* UPT */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* EXC */ + CS_0001 | LAST, + _NOT_USED_, + + /* REG */ + CS_1110 , + CS_0001 | LAST, +}; +#endif + +/* 0xC8 = 0b11001000 , CAS3, >> 2 = 0b00 11 0 010 */ +/* 0x88 = 0b10001000 , CAS2, >> 2 = 0b00 10 0 010 */ +#define MAR_SDRAM_INIT ((CAS_LATENCY << 6) | 0x00000008LU) + +/* 8 */ +#define CFG_MAMR ((CFG_MAMR_PTA << MAMR_PTA_SHIFT) | MAMR_PTAE | \ + MAMR_AMA_TYPE_0 | MAMR_DSA_1_CYCL | MAMR_G0CLA_A11 | \ + MAMR_RLFA_1X | MAMR_WLFA_1X | MAMR_TLFA_4X) + +void check_ram(unsigned int addr, unsigned int size) +{ + unsigned int i, j, v, vv; + volatile unsigned int *p; + unsigned int pv; + + p = (unsigned int *)addr; + pv = (unsigned int)p; + for (i = 0; i < size / sizeof(unsigned int); i++, pv += sizeof(unsigned int)) + *p++ = pv; + + p = (unsigned int *)addr; + for (i = 0; i < size / sizeof(unsigned int); i++) { + v = (unsigned int)p; + vv = *p; + if (vv != v) { + printf("%p: read %08x instead of %08x\n", p, vv, v); + hang(); + } + p++; + } + + for (j = 0; j < 5; j++) { + switch (j) { + case 0: v = 0x00000000; break; + case 1: v = 0xffffffff; break; + case 2: v = 0x55555555; break; + case 3: v = 0xaaaaaaaa; break; + default:v = 0xdeadbeef; break; + } + p = (unsigned int *)addr; + for (i = 0; i < size / sizeof(unsigned int); i++) { + *p = v; + vv = *p; + if (vv != v) { + printf("%p: read %08x instead of %08x\n", p, vv, v); + hang(); + } + *p = ~v; + p++; + } + } +} + +long int initdram(int board_type) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + long int size; + + upmconfig(UPMB, (uint *) sdram_table, sizeof(sdram_table) / sizeof(sdram_table[0])); + + /* + * Preliminary prescaler for refresh + */ + memctl->memc_mptpr = MPTPR_PTP_DIV8; + + memctl->memc_mar = MAR_SDRAM_INIT; /* 32-bit address to be output on the address bus if AMX = 0b11 */ + + /* + * Map controller bank 3 to the SDRAM bank at preliminary address. + */ + memctl->memc_or3 = CFG_OR3_PRELIM; + memctl->memc_br3 = CFG_BR3_PRELIM; + + memctl->memc_mbmr = CFG_MAMR & ~MAMR_PTAE; /* no refresh yet */ + + udelay(200); + + /* perform SDRAM initialisation sequence */ + memctl->memc_mcr = MCR_OP_RUN | MCR_UPM_B | MCR_MB_CS3 | MCR_MLCF(1) | MCR_MAD(0x3C); /* precharge all */ + udelay(1); + + memctl->memc_mcr = MCR_OP_RUN | MCR_UPM_B | MCR_MB_CS3 | MCR_MLCF(2) | MCR_MAD(0x30); /* refresh 2 times(0) */ + udelay(1); + + memctl->memc_mcr = MCR_OP_RUN | MCR_UPM_B | MCR_MB_CS3 | MCR_MLCF(1) | MCR_MAD(0x3E); /* exception program (write mar)*/ + udelay(1); + + memctl->memc_mbmr |= MAMR_PTAE; /* enable refresh */ + + udelay(10000); + + { + u32 d1, d2; + + d1 = 0xAA55AA55; + *(volatile u32 *)0 = d1; + d2 = *(volatile u32 *)0; + if (d1 != d2) { + printf("DRAM fails: wrote 0x%08x read 0x%08x\n", d1, d2); + hang(); + } + + d1 = 0x55AA55AA; + *(volatile u32 *)0 = d1; + d2 = *(volatile u32 *)0; + if (d1 != d2) { + printf("DRAM fails: wrote 0x%08x read 0x%08x\n", d1, d2); + hang(); + } + } + + size = get_ram_size((long *)0, SDRAM_MAX_SIZE); + + if (size == 0) { + printf("SIZE is zero: LOOP on 0\n"); + for (;;) { + *(volatile u32 *)0 = 0; + (void)*(volatile u32 *)0; + } + } + + return size; +} + +/* ------------------------------------------------------------------------- */ + +void reset_phys(void) +{ + int phyno; + unsigned short v; + + udelay(10000); + /* reset the damn phys */ + mii_init(); + + for (phyno = 0; phyno < 32; ++phyno) { + miiphy_read(phyno, PHY_PHYIDR1, &v); + if (v == 0xFFFF) + continue; + miiphy_write(phyno, PHY_BMCR, PHY_BMCR_POWD); + udelay(10000); + miiphy_write(phyno, PHY_BMCR, PHY_BMCR_RESET | PHY_BMCR_AUTON); + udelay(10000); + } +} + +/* ------------------------------------------------------------------------- */ + +/* GP = general purpose, SP = special purpose (on chip peripheral) */ + +/* bits that can have a special purpose or can be configured as inputs/outputs */ +#define PA_GP_INMASK 0 +#define PA_GP_OUTMASK (_BW(3) | _BW(7) | _BW(10) | _BW(14) | _BW(15)) +#define PA_SP_MASK 0 +#define PA_ODR_VAL 0 +#define PA_GP_OUTVAL (_BW(3) | _BW(14) | _BW(15)) +#define PA_SP_DIRVAL 0 + +#define PB_GP_INMASK _B(28) +#define PB_GP_OUTMASK (_B(19) | _B(23) | _B(26) | _B(27) | _B(29) | _B(30)) +#define PB_SP_MASK (_BR(22, 25)) +#define PB_ODR_VAL 0 +#define PB_GP_OUTVAL (_B(26) | _B(27) | _B(29) | _B(30)) +#define PB_SP_DIRVAL 0 + +#if CONFIG_NETTA2_VERSION == 1 +#define PC_GP_INMASK _BW(12) +#define PC_GP_OUTMASK (_BW(10) | _BW(11) | _BW(13) | _BW(15)) +#elif CONFIG_NETTA2_VERSION == 2 +#define PC_GP_INMASK (_BW(13) | _BW(15)) +#define PC_GP_OUTMASK (_BW(10) | _BW(11) | _BW(12)) +#endif +#define PC_SP_MASK 0 +#define PC_SOVAL 0 +#define PC_INTVAL 0 +#define PC_GP_OUTVAL (_BW(10) | _BW(11)) +#define PC_SP_DIRVAL 0 + +#if CONFIG_NETTA2_VERSION == 1 +#define PE_GP_INMASK _B(31) +#define PE_GP_OUTMASK (_B(17) | _B(18) |_B(20) | _B(24) | _B(27) | _B(28) | _B(29) | _B(30)) +#define PE_GP_OUTVAL (_B(20) | _B(24) | _B(27) | _B(28)) +#elif CONFIG_NETTA2_VERSION == 2 +#define PE_GP_INMASK _BR(28, 31) +#define PE_GP_OUTMASK (_B(17) | _B(18) |_B(20) | _B(24) | _B(27)) +#define PE_GP_OUTVAL (_B(20) | _B(24) | _B(27)) +#endif +#define PE_SP_MASK 0 +#define PE_ODR_VAL 0 +#define PE_SP_DIRVAL 0 + +int board_early_init_f(void) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile iop8xx_t *ioport = &immap->im_ioport; + volatile cpm8xx_t *cpm = &immap->im_cpm; + volatile memctl8xx_t *memctl = &immap->im_memctl; + + /* NAND chip select */ +#if CONFIG_NETTA2_VERSION == 1 + memctl->memc_or1 = ((0xFFFFFFFFLU & ~(NAND_SIZE - 1)) | OR_CSNT_SAM | OR_BI | OR_SCY_8_CLK | OR_EHTR | OR_TRLX); + memctl->memc_br1 = ((NAND_BASE & BR_BA_MSK) | BR_PS_8 | BR_V); +#elif CONFIG_NETTA2_VERSION == 2 + upmconfig(UPMA, (uint *) nandcs_table, sizeof(nandcs_table) / sizeof(nandcs_table[0])); + memctl->memc_or1 = ((0xFFFFFFFFLU & ~(NAND_SIZE - 1)) | OR_BI | OR_G5LS); + memctl->memc_br1 = ((NAND_BASE & BR_BA_MSK) | BR_PS_8 | BR_V | BR_MS_UPMA); + memctl->memc_mamr = 0; /* all clear */ +#endif + + /* DSP chip select */ + memctl->memc_or2 = ((0xFFFFFFFFLU & ~(DSP_SIZE - 1)) | OR_CSNT_SAM | OR_BI | OR_ACS_DIV2 | OR_SETA | OR_TRLX); + memctl->memc_br2 = ((DSP_BASE & BR_BA_MSK) | BR_PS_16 | BR_V); + +#if CONFIG_NETTA2_VERSION == 1 + memctl->memc_br4 &= ~BR_V; +#endif + memctl->memc_br5 &= ~BR_V; + memctl->memc_br6 &= ~BR_V; + memctl->memc_br7 &= ~BR_V; + + ioport->iop_padat = PA_GP_OUTVAL; + ioport->iop_paodr = PA_ODR_VAL; + ioport->iop_padir = PA_GP_OUTMASK | PA_SP_DIRVAL; + ioport->iop_papar = PA_SP_MASK; + + cpm->cp_pbdat = PB_GP_OUTVAL; + cpm->cp_pbodr = PB_ODR_VAL; + cpm->cp_pbdir = PB_GP_OUTMASK | PB_SP_DIRVAL; + cpm->cp_pbpar = PB_SP_MASK; + + ioport->iop_pcdat = PC_GP_OUTVAL; + ioport->iop_pcdir = PC_GP_OUTMASK | PC_SP_DIRVAL; + ioport->iop_pcso = PC_SOVAL; + ioport->iop_pcint = PC_INTVAL; + ioport->iop_pcpar = PC_SP_MASK; + + cpm->cp_pedat = PE_GP_OUTVAL; + cpm->cp_peodr = PE_ODR_VAL; + cpm->cp_pedir = PE_GP_OUTMASK | PE_SP_DIRVAL; + cpm->cp_pepar = PE_SP_MASK; + + return 0; +} + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) + +#include <linux/mtd/nand.h> + +extern ulong nand_probe(ulong physadr); +extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE]; + +void nand_init(void) +{ + unsigned long totlen; + + totlen = nand_probe(CFG_NAND_BASE); + printf ("%4lu MB\n", totlen >> 20); +} +#endif + +#ifdef CONFIG_HW_WATCHDOG + +void hw_watchdog_reset(void) +{ + /* XXX add here the really funky stuff */ +} + +#endif + +#ifdef CONFIG_SHOW_ACTIVITY + +/* called from timer interrupt every 1/CFG_HZ sec */ +void board_show_activity(ulong timestamp) +{ +} + +/* called when looping */ +void show_activity(int arg) +{ +} + +#endif + +#if defined(CFG_CONSOLE_IS_IN_ENV) && defined(CFG_CONSOLE_OVERWRITE_ROUTINE) +int overwrite_console(void) +{ + /* printf("overwrite_console called\n"); */ + return 0; +} +#endif + +extern int drv_phone_init(void); +extern int drv_phone_use_me(void); +extern int drv_phone_is_idle(void); + +int misc_init_r(void) +{ + return 0; +} + +int last_stage_init(void) +{ +#if CONFIG_NETTA2_VERSION == 2 + int i; +#endif + +#if CONFIG_NETTA2_VERSION == 2 + /* assert peripheral reset */ + ((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pcdat &= ~_BW(12); + for (i = 0; i < 10; i++) + udelay(1000); + ((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pcdat |= _BW(12); +#endif + reset_phys(); + + return 0; +} diff --git a/board/netta2/u-boot.lds b/board/netta2/u-boot.lds new file mode 100644 index 00000000000..c3dac0ef4a5 --- /dev/null +++ b/board/netta2/u-boot.lds @@ -0,0 +1,138 @@ +/* + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +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/mpc8xx/start.o (.text) + cpu/mpc8xx/traps.o (.text) + common/dlmalloc.o (.text) + lib_ppc/ppcstring.o (.text) + lib_generic/vsprintf.o (.text) + lib_generic/crc32.o (.text) + lib_generic/zlib.o (.text) + lib_ppc/cache.o (.text) + lib_ppc/time.o (.text) + + . = DEFINED(env_offset) ? 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 = .); +} diff --git a/board/netta2/u-boot.lds.debug b/board/netta2/u-boot.lds.debug new file mode 100644 index 00000000000..21b7e6aabc0 --- /dev/null +++ b/board/netta2/u-boot.lds.debug @@ -0,0 +1,135 @@ +/* + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +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 : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + + cpu/mpc8xx/start.o (.text) + common/dlmalloc.o (.text) + lib_generic/vsprintf.o (.text) + lib_generic/crc32.o (.text) + + . = env_offset; + common/environment.o(.text) + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _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(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} |