From 044ad7c3987460ede48ff27afd6bdb0ca05a0432 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 4 Jul 2011 20:52:54 +0200 Subject: import at91lib from at91lib_20100901_softpack_1_9_v_1_0_svn_v15011 it's sad to see that atmel doesn't publish their svn repo or has a centralized location or even puts proper version/release info into the library itself --- boards/at91cap9-stk/board_fpga_init.c | 480 ++++++++++++++++++++++++++++++++++ 1 file changed, 480 insertions(+) create mode 100644 boards/at91cap9-stk/board_fpga_init.c (limited to 'boards/at91cap9-stk/board_fpga_init.c') diff --git a/boards/at91cap9-stk/board_fpga_init.c b/boards/at91cap9-stk/board_fpga_init.c new file mode 100644 index 0000000..f071b77 --- /dev/null +++ b/boards/at91cap9-stk/board_fpga_init.c @@ -0,0 +1,480 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +/* + Title: FPGA / CAP synchronization routines +*/ + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ +#include +#include +#include +#include +#include +#include "board_fpga_init.h" + + +//------------------------------------------------------------------------------ +// FPGA Config done on PC13 (CAP9S3-DKZ only) +//------------------------------------------------------------------------------ +#define PIN_FPGA_CONFDONE {1 << 13, AT91C_BASE_PIOC, AT91C_ID_PIOABCD, PIO_INPUT, PIO_DEGLITCH} +static const Pin pinPC13 = PIN_FPGA_CONFDONE; + + +//------------------------------------------------------------------------------ +// Prototype of internal functions +//------------------------------------------------------------------------------ +unsigned int fpga_synchro_newIF(void); +unsigned int init_mpblock_revC(unsigned char mode); +unsigned int fpga_synchro_revC(void); +void init_mpbs_revC(volatile unsigned int* mpbs,char pun,char lp,char sup); +unsigned int init_mpblock_revB(void); +unsigned int fpga_synchro_revB(void); +void init_mpbs_revB(volatile unsigned int* mpbs,char pun,char lp,char sup); +void wait_slck_periods(int periods); +void wait_for_FPGA_config(void); +void wait_for_FPGA_config_CAP9S3(void); +unsigned int search_last_match(void); +unsigned int search_first_match(void); +int fpga_pattern_ok(void); + +//------------------------------------------------------------------------------ +// Globlal variables +//------------------------------------------------------------------------------ +int delay_status, master_cnt_hold, master_cnt; + + +//------------------------------------------------------------------------------ +// FPGA access initialization +// Returns : programmed clk out delay if success +// error code with pattern CACAB0Fx if fail +//------------------------------------------------------------------------------ +unsigned int BOARD_InitMPBlock(unsigned char mode) +{ + // Switch to external 32KHz if not done + if(!SLCK_Is32k())SLCK_RCto32k(); + + if (!(RSTC_SR_REG&0x00000600)){ + wait_for_FPGA_config_CAP9S3(); // if POR, wait until FPGA is ready + } + + if(CAP9_CHECK_REVISION_REG == REV_B_CHECK_VALUE) { + TRACE_INFO("Init MPBlock rev B\n\r"); + return(init_mpblock_revB()); // CAP9 revB detected + } + else { + if(EXTENDED_CHIP_ID_REG) { + TRACE_INFO("No init MPBlock : it is not a dev chip\n\r"); + return(NOT_A_DEV_CHIP_ERROR); // not a dev chip + } + else { + TRACE_INFO("Init MPBlock rev C\n\r"); + return(init_mpblock_revC(mode)); // CAP9 revC detected + } + } +} + +//------------------------------------------------------------------------------ +// CAP9 / FPGA synchronization loop - CAP9 RevC / new interface +//------------------------------------------------------------------------------ +unsigned int fpga_synchro_newIF (void) +{ + unsigned int time = 0; + unsigned int wait_loop1; + unsigned int wait_loop2; + unsigned int wait_loop3; + unsigned int delay_ctrl, clkin_delay, clkin_delay_max,dw_width; + + + //-- Write in CONFIG_INIT register + //-- - dllin_used bit = 0 (used clock coming from FPGA) + //-- - dllout_used bit = 0 (bypass the DelayLine OUT) + //-- - drive_pad_by_sfr = - (drive pad by register) + CONFIG_INIT_REG &= 0xFFFFFE7F; //outi(0xFDF00000+0x28, (ini(0xFDF00000+0x28) & 0xFFFFFE7F)); + + // clk_in setup + delay_status = DELAY_STATUS_REG; //-- read in DELAY_STATUS register + master_cnt_hold = ((delay_status & 0xFF00) >> 8) + 6; + master_cnt = (delay_status & 0xFF0000) >> 16; + + +//ERr + //clkin_delay = (master_cnt_hold >> 2)-2; //start in data window + clkin_delay = 0; + DELAY_CTRL_REG=(clkin_delay << 16)|0x1; + + //-- FPGA I/F INIT + INIT_ARG_REG = 0x5C00; + INIT_CMD_REG = 0x01; // INIT_CMD = INIT_CMD_START_INIT + wait_loop1 = 5000000;while(wait_loop1--); + wait_loop2 = 5000000;while(wait_loop2--); + wait_loop3 = 5000000;while(wait_loop3--); + + if (fpga_pattern_ok()){ // already in data window + clkin_delay_max = search_last_match(); + clkin_delay = search_first_match(); + dw_width = clkin_delay_max + master_cnt_hold-clkin_delay; + //ERr debug purppose + printf("-I- Data window : 0x%02X to 0x%02X\n\r", clkin_delay,clkin_delay_max); + clkin_delay = (clkin_delay+dw_width/2)%master_cnt_hold; + } + else{ // not in data window + clkin_delay = search_first_match(); + clkin_delay_max = search_last_match(); + dw_width = clkin_delay_max-clkin_delay; + //ERr debug purppose + printf("-I- Data window : 0x%02X to 0x%02X\n\r", clkin_delay,clkin_delay_max); + clkin_delay = (clkin_delay+dw_width/2)%master_cnt_hold; + } + + +// debug purppose + printf("-I- Master count : 0x%02X\n\r", master_cnt); +//clkin_delay = (master_cnt_hold >> 2)-2; //start in data window + printf("-I- clk_in delay : 0x%02X\n\r", clkin_delay); + printf("-I- data window width : 0x%02X (%dns)\n\r", dw_width,(dw_width*10/master_cnt)); + + + // Set clk in delay + delay_ctrl = DELAY_CTRL_REG; + DELAY_CTRL_REG=((delay_ctrl & ~(0xFF << 16)) | clkin_delay << 16); + DELAY_CTRL_REG|=0x1; + + + + // Cycle index select + time = 0; + while((CYCLE_IDX_RESP_R_LSB_REG != 0x0A7014E0)&&time++FPGA_SYNCHRO_TIMEOUT3)return(FPGA_SYNCHRO_ERROR3); + + + // Return the number of iterations + return(time); +} + + + + + +//------------------------------------------------------------------------------ +// FPGA access initialization - CAP9 RevC +//------------------------------------------------------------------------------ +unsigned int init_mpblock_revC(unsigned char mode) +{ +// AT91PS_CCFG pCCFG = (AT91PS_CCFG) AT91C_BASE_CCFG; //not used + unsigned int ret_value; + + // Enable clk + *((unsigned int*)0xFFFFFC00)|=0x4; + init_mpbs_revC(MPBS0,PULLUP_ON,MPIO_LP,MPIO_SUPPLY); + + // User IF pad config + /* + *((unsigned int*)0xFDF00028)&=0xFFFFFFFD; // Drive pad by user if + *((unsigned int*)0xFDF00034)=0x01000000; // MPIOB SUP + *((unsigned int*)0xFDF00038)=0x00000000; // MPIOB SUP + *((unsigned int*)0xFDF0003C)=0x00000000; // MPIOA SUP + *((unsigned int*)0xFDF00040)=0x01000000; // MPIOB LP1 + *((unsigned int*)0xFDF00044)=0x00000000; // MPIOB LP2 + *((unsigned int*)0xFDF00048)=0x00000000; // MPIOA LP + *((unsigned int*)0xFDF0004C)=0x00000000; // MPIOB PU1 + *((unsigned int*)0xFDF00050)=0x00000000; // MPIOB PU2 + *((unsigned int*)0xFDF00054)=0x00000000; // MPIOA PU + */ + + + #ifdef __FPGA_IF_TYPE_DIV3 + FPGA_IF_TYPE_REG = 0x01; + #endif + + // DELAY LINE SETUP + DELAY_CTRL_REG = 0x03; // write in DELAY_CTRL register enable_delay = 1 and update_delay = 1 + while (!(DELAY_STATUS_REG & 0x1)){} // wait master_is_locked = 1 + + + // FPGA IF synchronization loop + TRACE_INFO("FPGA IF synchro loop...\n\r"); + + //#ifdef NEW_INTERFACE + if (mode==NEW_IF){ + ret_value = fpga_synchro_newIF(); + if(ret_value>FPGA_SYNCHRO_TIMEOUT3)return(FPGA_SYNCHRO_ERROR3); + } + else{ + ret_value = fpga_synchro_revC(); + if ((ret_value&0xFFFF0000) == 0xCACA0000)return(ret_value); + } + //#endif + TRACE_INFO("Synchro done\n\r"); + + // Switch to functionnal mode + //outi(0x30DC00, 0xDC00); + INIT_ARG_REG = 0x4C727354; // INIT_ARG = INIT_CMD_START_INIT + INIT_ARG_REG = 0x4C6F634B; // INIT_ARG = INIT_CMD_START_INIT + INIT_CMD_REG = 0x03; // INIT_CMD = INIT_CMD_CYCLE_IDX_LOCKED + + // Return the programmed clock_out_delay value + return(ret_value); +} + +//------------------------------------------------------------------------------ +// FPGA access initialization - CAP9 RevC +//------------------------------------------------------------------------------ +unsigned int fpga_synchro_revC(void) +{ + unsigned char clk_out_delay_mean; + unsigned char clk_out_delay = 0; + unsigned int time = 0; + + INIT_ARG_REG = 0x5C00; // + wait_slck_periods(1); // about 30us (wait 10us for FPGA PLL relock) + INIT_CMD_REG = 0x01; // INIT_CMD = INIT_CMD_START_INIT + + //Search first match value + time = 0; + while(((CYCLE_IDX_RESP_R_LSB_REG != CYCLE_IDX_RESP_F_LSB_REG)||(CYCLE_IDX_RESP_R_MSB_REG != ~CYCLE_IDX_RESP_F_MSB_REG))&&time++ FPGA_SYNCHRO_TIMEOUT1)return(FPGA_SYNCHRO_ERROR1); + clk_out_delay_mean = clk_out_delay; + + //Search last match value + DELAY_CTRL_REG=(clk_out_delay++ << 8)|0x1; + while(((CYCLE_IDX_RESP_R_LSB_REG == CYCLE_IDX_RESP_F_LSB_REG)&&(CYCLE_IDX_RESP_R_MSB_REG == ~CYCLE_IDX_RESP_F_MSB_REG))&&time++FPGA_SYNCHRO_TIMEOUT2)return(FPGA_SYNCHRO_ERROR2); + clk_out_delay_mean = (clk_out_delay_mean + clk_out_delay)/2; + + // Setup to middle match value + DELAY_CTRL_REG = (clk_out_delay_mean << 8) | 0x1; + + + // Cycle index select + time = 0; + while((CYCLE_IDX_RESP_R_LSB_REG != 0x0A7014E0)&&time++FPGA_SYNCHRO_TIMEOUT3)return(FPGA_SYNCHRO_ERROR3); + + // Return the programmed clock_out_delay value + return ((unsigned int)clk_out_delay_mean); +} + +//------------------------------------------------------------------------------ +// Enable CAP to FPGA clock, and configure pads - CAP9 RevC +//------------------------------------------------------------------------------ +// Updated for UMC pads +void init_mpbs_revC(volatile unsigned int* mpbs,char pun,char lp,char sup) +{ + unsigned int value; + + if (mpbs!=MPBS0 && mpbs!=MPBS1 && mpbs!=MPBS2 && mpbs!=MPBS3) + return; + value = *mpbs | MPBS_ENABLE_BIT; + + if (pun==PULLUP_ON) value&= ~(MPIOB_PUN_BIT|MPIOA_PUN_BIT); + else if (pun==PULLUP_OFF) value|= (MPIOB_PUN_BIT|MPIOA_PUN_BIT); + + if (lp==LOWPOWER_OFF) value|= (MPIOB_LP_BIT|MPIOA_LP_BIT); + else if(lp==LOWPOWER_ON)value&= ~(MPIOB_LP_BIT|MPIOA_LP_BIT); + + if (sup==SUPPLY_18) value|= (MPIOB_SUP_BIT|MPIOA_SUP_BIT); + else if(sup==SUPPLY_33)value&= ~(MPIOB_SUP_BIT|MPIOA_SUP_BIT); + + *mpbs = value; +} + +//------------------------------------------------------------------------------ +// FPGA access initialization - CAP9 RevB +//------------------------------------------------------------------------------ +unsigned int init_mpblock_revB(void) +{ +// AT91PS_CCFG pCCFG = (AT91PS_CCFG) AT91C_BASE_CCFG; // not used + unsigned int ret_value; + + // Enable clk + init_mpbs_revB(MPBS0,PULLUP_ON,MPIO_LP,MPIO_SUPPLY); + + TRACE_INFO("FPGA IF synchro loop...\n\r"); + + #ifdef __FPGA_IF_TYPE_DIV3 + FPGA_IF_TYPE_REG = 0x01; + #endif + // DELAY LINE SETUP + DELAY_CTRL_REG = 0x03; // write in DELAY_CTRL register enable_delay = 1 and update_delay = 1 + while (!(DELAY_STATUS_REG & 0x1)){} // wait master_is_locked = 1 + + // FPGA IF synchronization loop + //ret_value = fpga_synchro_old(); + ret_value = fpga_synchro_revB(); + if ((ret_value&0xFFFF0000) == 0xCACA0000)return(ret_value); + + TRACE_INFO("Synchro done\n\r"); + + // Switch to functionnal mode + //outi(0x30DC00, 0xDC00); + INIT_ARG_REG = 0x4C727354; // INIT_ARG = INIT_CMD_START_INIT + INIT_ARG_REG = 0x4C6F634B; // INIT_ARG = INIT_CMD_START_INIT + INIT_CMD_REG = 0x03; // INIT_CMD = INIT_CMD_CYCLE_IDX_LOCKED + + // Return the programmed clock_out_delay value + return(ret_value); +} + +//------------------------------------------------------------------------------ +// CAP9 / FPGA synchronization loop - CAP9 RevB +//------------------------------------------------------------------------------ +unsigned int fpga_synchro_revB(void) +{ + unsigned char clk_out_delay_mean; + unsigned char clk_out_delay = 0; + unsigned int time = 0; + + + INIT_ARG_REG = 0x5C00; // + wait_slck_periods(1); // about 30us (wait 10us for FPGA PLL relock) + INIT_CMD_REG = 0x01; // INIT_CMD = INIT_CMD_START_INIT + + //Search first match value + time = 0; + while(((CYCLE_IDX_RESP_R_LSB_REG != CYCLE_IDX_RESP_F_LSB_REG)||(CYCLE_IDX_RESP_R_MSB_REG != ~CYCLE_IDX_RESP_F_MSB_REG))&&time++ FPGA_SYNCHRO_TIMEOUT1)return(FPGA_SYNCHRO_ERROR1); + clk_out_delay_mean = clk_out_delay; + + //Search last match value + DELAY_CTRL_REG=(clk_out_delay++ << 8)|0x1; + while(((CYCLE_IDX_RESP_R_LSB_REG == CYCLE_IDX_RESP_F_LSB_REG)&&(CYCLE_IDX_RESP_R_MSB_REG == ~CYCLE_IDX_RESP_F_MSB_REG))&&time++FPGA_SYNCHRO_TIMEOUT2)return(FPGA_SYNCHRO_ERROR2); + clk_out_delay_mean = (clk_out_delay_mean + clk_out_delay)/2; + + // Setup to middle match value + DELAY_CTRL_REG = (clk_out_delay_mean << 8) | 0x1; + + // Cycle index select + time = 0; + while((CYCLE_IDX_RESP_R_LSB_REG != 0x0A7014E0)&&time++FPGA_SYNCHRO_TIMEOUT3)return(FPGA_SYNCHRO_ERROR3); + + // Return the programmed clock_out_delay value + return ((unsigned int)clk_out_delay_mean); +} + +//------------------------------------------------------------------------------ +// Enable CAP to FPGA clock, and configure pads - CAP9 RevB +//------------------------------------------------------------------------------ +void init_mpbs_revB(volatile unsigned int* mpbs,char pun,char lp,char sup) +{ + //AT91PS_CCFG pCCFG = (AT91PS_CCFG) AT91C_BASE_CCFG; + //pCCFG->CCFG_MPBS0 |= (1<<31) | (1<<16) | (1<<24); + unsigned int value; + + if (mpbs!=MPBS0 && mpbs!=MPBS1 && mpbs!=MPBS2 && mpbs!=MPBS3) + return; + value = *mpbs | MPBS_ENABLE_BIT; + + if (pun==PULLUP_ON) value&= ~(MPIOB_PUN_BIT|MPIOA_PUN_BIT); + else if (pun==PULLUP_OFF) value|= (MPIOB_PUN_BIT|MPIOA_PUN_BIT); + + if (lp==LOWPOWER_ON) value|= (MPIOB_LP_BIT|MPIOA_LP_BIT); + else if(lp==LOWPOWER_OFF)value&= ~(MPIOB_LP_BIT|MPIOA_LP_BIT); + + if (sup==SUPPLY_33) value|= (MPIOB_SUP_BIT|MPIOA_SUP_BIT); + else if(sup==SUPPLY_18)value&= ~(MPIOB_SUP_BIT|MPIOA_SUP_BIT); + + *mpbs = value; +} + + +//------------------------------------------------------------------------------ +/// Wait specified number of slow clock periods (30.52uS if external 32KHz) +//------------------------------------------------------------------------------ +void wait_slck_periods(int periods) +{ + RTT_SetPrescaler(AT91C_BASE_RTTC, 1); + while(RTT_GetTime(AT91C_BASE_RTTC)!=periods); +} + + +//------------------------------------------------------------------------------ +/// Wait for correct FPGA configuration (used after POR) +//------------------------------------------------------------------------------ +void wait_for_FPGA_config() +{ + int i; + for(i=0;i> 16)&(0xFF); + while (fpga_pattern_ok() && (clkin_delay++ < master_cnt_hold)) + DELAY_CTRL_REG=(clkin_delay << 16)|0x1; + + return clkin_delay; +} + +unsigned int search_first_match() +{ + unsigned int clkin_delay; + + clkin_delay = (DELAY_CTRL_REG >> 16)&(0xFF); + while (!fpga_pattern_ok() && (clkin_delay++ < master_cnt_hold)) + DELAY_CTRL_REG=(clkin_delay << 16)|0x1; + + return clkin_delay; +} + +int fpga_pattern_ok() +{ + return((CYCLE_IDX_RESP_R_LSB_REG == CYCLE_IDX_RESP_F_LSB_REG)&&(CYCLE_IDX_RESP_R_MSB_REG == ~CYCLE_IDX_RESP_F_MSB_REG)); +} + -- cgit v1.2.3