Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:53

0001 /*
0002  * RTEMS generic MPC83xx BSP
0003  *
0004  * This file contains the code to initialize the cpu.
0005  */
0006 
0007 /*
0008  * Copyright (c) 2003 IPR Engineering
0009  * Copyright (c) 2005 embedded brains GmbH & Co. KG
0010  *
0011  * The license and distribution terms for this file may be
0012  * found in the file LICENSE in this distribution or at
0013  * http://www.rtems.org/license/LICENSE.
0014  */
0015 
0016 #include <stdbool.h>
0017 #include <string.h>
0018 
0019 #include <libcpu/powerpc-utility.h>
0020 #include <libcpu/mmu.h>
0021 
0022 #include <mpc83xx/mpc83xx.h>
0023 
0024 #include <bsp.h>
0025 #include <bsp/u-boot.h>
0026 
0027 #define SET_DBAT( n, uv, lv) \
0028   do { \
0029     PPC_SET_SPECIAL_PURPOSE_REGISTER( DBAT##n##L, lv); \
0030     PPC_SET_SPECIAL_PURPOSE_REGISTER( DBAT##n##U, uv); \
0031   } while (0)
0032 
0033 #define SET_IBAT( n, uv, lv) \
0034   do { \
0035     PPC_SET_SPECIAL_PURPOSE_REGISTER( IBAT##n##L, lv); \
0036     PPC_SET_SPECIAL_PURPOSE_REGISTER( IBAT##n##U, uv); \
0037   } while (0)
0038 
0039 static void calc_dbat_regvals(
0040   BAT *bat_ptr,
0041   uint32_t base_addr,
0042   uint32_t size,
0043   bool flg_w,
0044   bool flg_i,
0045   bool flg_m,
0046   bool flg_g,
0047   uint32_t flg_bpp
0048 )
0049 {
0050   uint32_t block_mask = 0xffffffff;
0051   uint32_t end_addr = base_addr + size - 1;
0052 
0053   /* Determine block mask, that overlaps the whole block */
0054   while ((end_addr & block_mask) != (base_addr & block_mask)) {
0055     block_mask <<= 1;
0056   }
0057 
0058   bat_ptr->batu.bepi = base_addr >> (32 - 15);
0059   bat_ptr->batu.bl   = ~(block_mask >> (28 - 11));
0060   bat_ptr->batu.vs   = 1;
0061   bat_ptr->batu.vp   = 1;
0062 
0063   bat_ptr->batl.brpn = base_addr  >> (32 - 15);
0064   bat_ptr->batl.w    = flg_w;
0065   bat_ptr->batl.i    = flg_i;
0066   bat_ptr->batl.m    = flg_m;
0067   bat_ptr->batl.g    = flg_g;
0068   bat_ptr->batl.pp   = flg_bpp;
0069 }
0070 
0071 static void clear_mmu_regs( void)
0072 {
0073   uint32_t i;
0074 
0075   /* Clear segment registers */
0076   for (i = 0;i < 16;i++) {
0077     __asm__ volatile( "mtsrin %0, %1\n" : : "r" (i * 0x1000), "r" (i << (31 - 3)));
0078   }
0079 
0080   /* Clear TLBs */
0081   for (i = 0;i < 32;i++) {
0082     __asm__ volatile( "tlbie %0, 0\n" : : "r" (i << (31 - 19)));
0083   }
0084 }
0085 
0086 void cpu_init( void)
0087 {
0088   BAT dbat, ibat;
0089   uint32_t msr;
0090   uint32_t hid0;
0091 
0092   /* Clear MMU and segment registers */
0093   clear_mmu_regs();
0094 
0095   /* Clear caches */
0096   PPC_SPECIAL_PURPOSE_REGISTER(HID0, hid0);
0097   if ((hid0 & (HID0_ICE | HID0_DCE)) == 0) {
0098     hid0 &= ~(HID0_ILOCK | HID0_DLOCK | HID0_ICE | HID0_DCE);
0099     PPC_SET_SPECIAL_PURPOSE_REGISTER(HID0, hid0);
0100     hid0 |= HID0_ICFI | HID0_DCI;
0101     PPC_SET_SPECIAL_PURPOSE_REGISTER(HID0, hid0);
0102     hid0 &= ~(HID0_ICFI | HID0_DCI);
0103     PPC_SET_SPECIAL_PURPOSE_REGISTER(HID0, hid0);
0104   }
0105 
0106   /*
0107    * Set up IBAT registers in MMU
0108    */
0109 
0110   memset(&ibat, 0, sizeof( ibat));
0111   SET_IBAT( 2, ibat.batu, ibat.batl);
0112   SET_IBAT( 3, ibat.batu, ibat.batl);
0113   SET_IBAT( 4, ibat.batu, ibat.batl);
0114   SET_IBAT( 5, ibat.batu, ibat.batl);
0115   SET_IBAT( 6, ibat.batu, ibat.batl);
0116   SET_IBAT( 7, ibat.batu, ibat.batl);
0117 
0118   calc_dbat_regvals(
0119     &ibat,
0120     #ifdef HAS_UBOOT
0121       bsp_uboot_board_info.bi_memstart,
0122       bsp_uboot_board_info.bi_memsize,
0123     #else /* HAS_UBOOT */
0124       (uint32_t) bsp_ram_start,
0125       (uint32_t) bsp_ram_size,
0126     #endif /* HAS_UBOOT */
0127     false,
0128     false,
0129     false,
0130     false,
0131     BPP_RX
0132   );
0133   SET_IBAT( 0, ibat.batu, ibat.batl);
0134 
0135   calc_dbat_regvals(
0136     &ibat,
0137     #ifdef HAS_UBOOT
0138       bsp_uboot_board_info.bi_flashstart,
0139       bsp_uboot_board_info.bi_flashsize,
0140     #else /* HAS_UBOOT */
0141       (uint32_t) bsp_rom_start,
0142       (uint32_t) bsp_rom_size,
0143     #endif /* HAS_UBOOT */
0144     false,
0145     false,
0146     false,
0147     false,
0148     BPP_RX
0149   );
0150   SET_IBAT( 1, ibat.batu, ibat.batl);
0151 
0152   /*
0153    * Set up DBAT registers in MMU
0154    */
0155 
0156   memset(&dbat, 0, sizeof( dbat));
0157   SET_DBAT( 3, dbat.batu, dbat.batl);
0158   SET_DBAT( 4, dbat.batu, dbat.batl);
0159   SET_DBAT( 5, dbat.batu, dbat.batl);
0160   SET_DBAT( 6, dbat.batu, dbat.batl);
0161   SET_DBAT( 7, dbat.batu, dbat.batl);
0162 
0163   calc_dbat_regvals(
0164     &dbat,
0165     #ifdef HAS_UBOOT
0166       bsp_uboot_board_info.bi_memstart,
0167       bsp_uboot_board_info.bi_memsize,
0168     #else /* HAS_UBOOT */
0169       (uint32_t) bsp_ram_start,
0170       (uint32_t) bsp_ram_size,
0171     #endif /* HAS_UBOOT */
0172     false,
0173     false,
0174     false,
0175     false,
0176     BPP_RW
0177   );
0178   SET_DBAT( 0, dbat.batu, dbat.batl);
0179 
0180   calc_dbat_regvals(
0181     &dbat,
0182     #ifdef HAS_UBOOT
0183       bsp_uboot_board_info.bi_flashstart,
0184       bsp_uboot_board_info.bi_flashsize,
0185     #else /* HAS_UBOOT */
0186       (uint32_t) bsp_rom_start,
0187       (uint32_t) bsp_rom_size,
0188     #endif /* HAS_UBOOT */
0189     #ifdef MPC83XX_HAS_NAND_LP_FLASH_ON_CS0
0190       false,
0191       true,
0192       false,
0193       true,
0194       BPP_RW
0195     #else
0196       true,
0197       false,
0198       false,
0199       false,
0200       BPP_RX
0201     #endif
0202   );
0203   SET_DBAT( 1, dbat.batu, dbat.batl);
0204 
0205   calc_dbat_regvals(
0206     &dbat,
0207     #ifdef HAS_UBOOT
0208       bsp_uboot_board_info.bi_immrbar,
0209     #else /* HAS_UBOOT */
0210       (uint32_t) IMMRBAR,
0211     #endif /* HAS_UBOOT */
0212     #if MPC83XX_CHIP_TYPE / 10 == 830
0213       2 * 1024 * 1024,
0214     #else
0215       1024 * 1024,
0216     #endif
0217     false,
0218     true,
0219     false,
0220     true,
0221     BPP_RW
0222   );
0223   SET_DBAT( 2, dbat.batu, dbat.batl);
0224 
0225 #if defined(MPC83XX_BOARD_HSC_CM01)
0226   calc_dbat_regvals(
0227     &dbat,
0228     FPGA_START,
0229     FPGA_SIZE,
0230     true,
0231     true,
0232     true,
0233     false,
0234     BPP_RW
0235   );
0236   SET_DBAT(3,dbat.batu,dbat.batl);
0237 #endif
0238 
0239 #ifdef MPC83XX_BOARD_MPC8313ERDB
0240   /* Enhanced Local Bus Controller (eLBC) */
0241   calc_dbat_regvals(
0242     &dbat,
0243     0xfa000000,
0244     128 * 1024,
0245     false,
0246     true,
0247     false,
0248     true,
0249     BPP_RW
0250   );
0251   SET_DBAT( 3, dbat.batu, dbat.batl);
0252 #endif /* MPC83XX_BOARD_MPC8313ERDB */
0253 
0254   /* Read MSR */
0255   msr = ppc_machine_state_register();
0256 
0257   /* Enable data and instruction MMU in MSR */
0258   msr |= MSR_DR | MSR_IR;
0259 
0260   /* Enable FPU in MSR */
0261   msr |= MSR_FP;
0262 
0263   /* Update MSR */
0264   ppc_set_machine_state_register( msr);
0265 
0266   /*
0267    * In HID0:
0268    *  - Enable dynamic power management
0269    *  - Enable machine check interrupts
0270    */
0271   PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( HID0, HID0_EMCP | HID0_DPM);
0272 
0273   /* Enable timebase clock */
0274   mpc83xx.syscon.spcr |= M83xx_SYSCON_SPCR_TBEN;
0275 }