/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */

/*
 * ----------------------------------------------------------------------------------
 * The code in this file is copied (with a slight modifications and additions) from:
 *     mmu_iram.cpp
 * ----------------------------------------------------------------------------------
 * Copyright 2020 M Hightower
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 * limitations under the License.
 * ----------------------------------------------------------------------------------
 */


#include <user_interface.h>

#include "SysMMUIRAM.h"


extern "C" {


#if (MMU_ICACHE_SIZE == 0x4000)
    #define SOC_CACHE_SIZE 0 // 16KB
#else
    #define SOC_CACHE_SIZE 1 // 32KB
#endif


#if (MMU_ICACHE_SIZE == 0x4000)


// Override ROM function
#ifndef ROM_Cache_Read_Enable
    #define ROM_Cache_Read_Enable 0x40004678U
#endif

typedef void (*ROM_Cache_Read_Enable_t)(uint8_t map, uint8_t p, uint8_t v);

void IRAM_ATTR Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t /*v*/)
{ (*reinterpret_cast<ROM_Cache_Read_Enable_t>(ROM_Cache_Read_Enable))(map, p, SOC_CACHE_SIZE); }


#ifdef DEV_DEBUG_PRINT

/*
 * Early adjustment for CPU crystal frequency, so debug printing will work.
 *
 * Inspired by:
 *     https://github.com/pvvx/esp8266web/blob/2e25559bc489487747205db2ef171d48326b32d4/app/sdklib/system/app_main.c#L581-L591
 */
extern "C" uint8_t rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add);
extern "C" void rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data);

extern "C" void IRAM_ATTR set_pll()
{
#ifndef F_CRYSTAL
    #define F_CRYSTAL 26000000
#endif

    // At boot ROM start, assumes a 40 MHz crystal or a 26 MHz crystal;
    // there is no support for 24 MHz crystal at this time
    if(F_CRYSTAL != 40000000) {
        // Check if the ROM states that it is not a 26 MHz crystal (8 = 40 MHz ; 136 = 26 MHz)
        if( rom_i2c_readReg(103, 4, 1) != 136 ) {
            // Assume a 26 MHz crystal and set 80 MHz PLL CPU (soc_param0 : 0 = 40 MHz ; 1 = 26 MHz ; 2 : 24 MHz)
            rom_i2c_writeReg(103, 4, 1, 136);
            rom_i2c_writeReg(103, 4, 2, 145);
        }
    }
}

// This was used to probe at different stages of boot the state of the PLL register
extern "C" void IRAM_ATTR dbg_set_pll()
{
    const char r103_4_1 = rom_i2c_readReg(103, 4, 1);
    const char r103_4_2 = rom_i2c_readReg(103, 4, 2);

    set_pll();

    ets_uart_printf( "\nrom_i2c_readReg(103, 4, 1) = %u\n", r103_4_1 );
    ets_uart_printf(   "rom_i2c_readReg(103, 4, 2) = %u\n", r103_4_2 );
}

#endif // #ifdef DEV_DEBUG_PRINT


#endif // (MMU_ICACHE_SIZE == 0x4000)


} // extern "C"
