/*********************************************************************
 *
 *  Copyright (C) 2005  Freescale Semiconductors, Inc.
 *
 ********************************************************************/
/*********************************************************************
 *  FILE: rio_local_cfg.c
 *
 *  DESCRIPTION :
 *    Contains a number of functions used to set up the local processor
 *    before any attempt is made to generate RapidIO traffic.
 *    rio_local_cfg : performs all the steps required to get the local
 *     processor ready to generate RapidIO maintance transactions
 *    setup_local_rio_maint_window : creates an outbound window on the
 *     local processor which will be used to generate maintenance
 *     transactions
 *    setup_tlb_and_law : sets up a local area window and a TLB entry
 *     to cover the area of the memory map which will be used for
 *     RapidIO transactions.
 *
 * NOTES :
 *
 * HISTORY
 * Version    Date     Auth.,Loc.     Comments
 *   0.1    27-Jul-04  LM, EKB        First released version
 *   0.2    14-Apr-05  LM, EKB        Updated for SRIO on MPC8548
 ********************************************************************/

#include <common.h>
#include <syscall.h>
#include <asm-ppc/immap_85xx.h>
#include <asm-ppc/mmu.h>

//#include "rio_regs.h"
#include "rio_bringup.h"

#ifdef CFG_TLB_AND_LAW
void setup_tlb_and_law (void);
#endif
void setup_local_rio_maint_window (void);

extern volatile ccsr_srio_t *local_srio;
extern volatile immap_t *local_imm;
extern volatile ccsr_local_ecm_t *local_ecm;
extern volatile srio_device_t *srio_device;
extern u32 hostdeviceid, nextdevid;

int
rio_local_config (void)
{
#ifdef CFG_TLB_AND_LAW

  /************************************************************
  STEP 1: Set up a TLB entry and Local Area Window to cover
  the area of memory which we will use for RapidIO. This step
  may not be required if the bootloader does it
  ************************************************************/
  setup_tlb_and_law ();
#endif

  /************************************************************
  STEP 2 : Ensure that this code is running on a MPC8560 by examining
  the DIDCAR (also verifies that we have assumed the corect CCSRBAR
  value)
  ************************************************************/
  if (local_srio->didcar == MPC8548_DIDCAR_VALUE)
  {
    printf("Checked DIDCAR of local device is MPC8548 \n");
  }
  else
  {
    printf ("ERROR : Check CCSBAR local DIDCAR read as 0x%08x \n",
            local_srio->didcar);
    return UNKNOWN_DEVICE;
  }
  
  /***********************************************************
  STEP 3: Ensure that this code is running on a RapidIO host
  ************************************************************/
  if (local_srio->pgccsr == DEVICE_CONFIG_HOST)
    printf ("This device is configured as a RIO host \n");
  else {
    printf ("ERROR : This device is not configured as host, pgccsr=0x%08x \n",
            local_srio->pgccsr);
    return NOT_HOST_PROCESSOR;
  }

  /***********************************************************
  STEP 4: Ensure that this processor has a device ID of 0. This
  necessary as it affects the switch routing (in fabric systems)
  If not, change it (!), init global variables. 
  ***********************************************************/
  printf ("This device initially has RIO device ID 0x%08x \n",
          (local_srio->bdidcsr >> SHIFT_BDIDCSR_TO_DEVICEID));
  
  local_srio->bdidcsr = 0; 

  printf ("This device has been allocated RIO device ID 0x%08x \n",
          (local_srio->bdidcsr >> SHIFT_BDIDCSR_TO_DEVICEID));	  	  
 
  hostdeviceid = local_srio->bdidcsr >> SHIFT_BDIDCSR_TO_DEVICEID;
  
  /* software will start allocating device ID upwards from here - up to max deviceid */
  nextdevid = hostdeviceid + 1;
  
  /*also fill in the information into the relevant entry in the array */
  srio_device[hostdeviceid].imm = local_imm;
  srio_device[hostdeviceid].srio = local_srio;
  srio_device[hostdeviceid].ecm = local_ecm;
  srio_device[hostdeviceid].mem_block = (u32 *)(REMOTEMEMBASE + (hostdeviceid * MBYTE * 4));
 
	    
	    
  

  /************************************************************
  STEP5: Ensure that the RIO port is trained
  If the local RapidIO port is not trained to the switch then there
  is no point in continuing. Report error and exit.
  ************************************************************/
 if ((local_srio->p0escsr & LOCAL_RIO_TRAINED) == LOCAL_RIO_TRAINED) {
    printf ("RapidIO port is trained OK \n", local_srio->p0ccsr);
    if((local_srio->p0ccsr & PWIDTH_MASK) == PWIDTH1L0)
       printf("RapidIO port trained 1x on lane 0\n");
    if((local_srio->p0ccsr & PWIDTH_MASK) == PWIDTH1L2)
       printf("RapidIO port trained 1x on lane 2\n");
    if((local_srio->p0ccsr & PWIDTH_MASK) == PWIDTH4)
       printf("RapidIO port trained 4x \n");

       
  }
  else {
    printf
      ("ERROR : Rapidio is not trained. local pescsr = 0x%08x \n",
       local_srio->p0escsr);
    printf ("Exiting\n");
    return RIO_NOT_TRAINED;
  }

  /************************************************************
  STEP 6: Set up a RapidIO Outbound Window which will create the
  maintenance transactions we need for the initial system
  discovery
  ************************************************************/
  setup_local_rio_maint_window ();
}

/********************************************************************
void setup_local_rio_maint_window(void)
This function sets up ROW 1 on the local (host) device to map to
maintenance transactions. This function sets up a default deviceID,
HopCount etc. However, the code must program this ROWTAR before each
set of transcations to ensure that they are directed to the correct
device in the system
********************************************************************/
void
setup_local_rio_maint_window (void)
{

  /********************************************************************
  set up an outbound window to execute maintenance reads and writes
  ********************************************************************/
  local_srio->rowbar1 = ROW_ADDR2BA ((u32) START_OF_MAINT_WINDOW);
  local_srio->rowar1 = ROWAR_MAINT_DEFAULTS;

  /********************************************************************
  set up deviceid, hopcount etc for the transactions
  to the adjacent device  - this will change with each
  transaction, so just set up initial values
  ********************************************************************/
  local_srio->rowtar1 = (0xFF << ROW_DEV_ID_Shift);

  printf ("\nSet up the outbound rio maintenance window \n");
  printf ("rowbar1 = 0x%08x, rowar1 = 0x%08x, rowtar1 = 0x%08x\n",
          local_srio->rowbar1, local_srio->rowar1, local_srio->rowtar1);
}

/*********************************************************************
We only need this function if we are going to download the
code through u-boot , because u-boot doen't set up a lawbar or
tlb entry for RapidIO. If we are going to download this code using
any other method, then the configuration file should do this for you.

WARNING : Care must be taken with the version of u-boot to ensure
that this code and this TLB entry location remains valid
**********************************************************************/
#ifdef CFG_TLB_AND_LAW
void
setup_tlb_and_law (void)
{
  printf ("Check LAWs before setting up\n");
  printf ("lawbar0 = 0x%08x, lawar0 = 0x%08x \n", local_ecm->lawbar0, local_ecm->lawar0);
  printf ("lawbar1 = 0x%08x, lawar1 = 0x%08x \n", local_ecm->lawbar1, local_ecm->lawar1);
  printf ("lawbar2 = 0x%08x, lawar2 = 0x%08x \n", local_ecm->lawbar2, local_ecm->lawar2);
  printf ("lawbar3 = 0x%08x, lawar3 = 0x%08x \n", local_ecm->lawbar3, local_ecm->lawar3);
  printf ("lawbar4 = 0x%08x, lawar4 = 0x%08x \n", local_ecm->lawbar4, local_ecm->lawar4);
  printf ("lawbar5 = 0x%08x, lawar5 = 0x%08x \n", local_ecm->lawbar5, local_ecm->lawar5);
  printf ("lawbar6 = 0x%08x, lawar6 = 0x%08x \n", local_ecm->lawbar6, local_ecm->lawar6);
  printf ("lawbar7 = 0x%08x, lawar7 = 0x%08x \n", local_ecm->lawbar7, local_ecm->lawar7);

  /***********************************************************************
  set up the special purpose registers to create a TLB entry to cover the
  RapidIO window.
  using entry no 3
  ************************************************************************/
  asm ("lis 3,0x1003");
  asm ("ori 3,3,0x0000");
  asm ("mtspr 0x270,3");

  /***********************************************************************
  size 256 MBytes
  ***********************************************************************/
  asm ("lis 3,0x8000");
  asm ("ori 3,3,0x0900");
  asm ("mtspr 0x271,3");

  /***********************************************************************
  effective address 0xC0000000
  ***********************************************************************/
  asm ("lis 3,0xC000");
  asm ("ori 3,3,0x0008");
  asm ("mtspr 0x272,3");

  /**********************************************************************
  real address 0xC0000000
  **********************************************************************/
  asm ("lis 3,0xC000");
  asm ("ori 3,3,0x003f");
  asm ("mtspr 0x273,3");

  asm ("sync");

  asm ("tlbwe");

  asm ("sync");

  /**********************************************************************
  now set up a LAW to cover the RapidIO area
  **********************************************************************/
  local_ecm->lawbar5 = START_OF_RIO_WINDOW >> 12;
  local_ecm->lawar5 = LAWAR_DEFAULTS;

  printf ("Completed the setup of TLBs and lawbars \n");
  printf ("lawbar5 = 0x%08x, lawar5 = 0x%08x \n\n", local_ecm->lawbar5, local_ecm->lawar5);
}

#endif /* CFG_TLB_AND_LAW */

