1226 lines
28 KiB
C
1226 lines
28 KiB
C
/**
|
||
******************************************************************************
|
||
* @file stpmic.c
|
||
* @author MCD Application Team
|
||
* @brief This sample code provides hardware semaphore using HSEM for
|
||
* synchronization and mutual exclusion between heterogeneous processors
|
||
* and those not operating under a single, shared operating system.
|
||
******************************************************************************
|
||
* @attention
|
||
*
|
||
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
|
||
* All rights reserved.</center></h2>
|
||
*
|
||
* This software component is licensed by ST under BSD 3-Clause license,
|
||
* the "License"; You may not use this file except in compliance with the
|
||
* License. You may obtain a copy of the License at:
|
||
* opensource.org/licenses/BSD-3-Clause
|
||
*
|
||
******************************************************************************
|
||
*/
|
||
|
||
#include <board.h>
|
||
#include <stpmic.h>
|
||
#include <string.h>
|
||
#include "drv_hard_i2c.h"
|
||
|
||
/* Definition of PMIC <=> stm32mp1 Signals */
|
||
#define PMIC_INTn_PIN GPIO_PIN_0
|
||
#define PMIC_INTn_PORT GPIOA
|
||
#define PMIC_INTn_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
|
||
#define PMIC_INTn_CLK_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE()
|
||
|
||
#define BSP_PMIC_PWRCTRL_PIN_Assert() HAL_GPIO_WritePin(PMIC_PWRCTRL_PORT, PMIC_PWRCTRL_PIN, GPIO_PIN_RESET);
|
||
#define BSP_PMIC_PWRCTRL_PIN_Pull() HAL_GPIO_WritePin(PMIC_PWRCTRL_PORT, PMIC_PWRCTRL_PIN, GPIO_PIN_SET);
|
||
|
||
/**
|
||
* @}
|
||
*/
|
||
|
||
/** @defgroup STM32MP15XX_EVAL_STPMU_Private_Defines Private Defines
|
||
* @{
|
||
*/
|
||
/* Private typedef -----------------------------------------------------------*/
|
||
typedef struct {
|
||
PMIC_RegulId_TypeDef id;
|
||
uint16_t *voltage_table;
|
||
uint8_t voltage_table_size;
|
||
uint8_t control_reg;
|
||
uint8_t low_power_reg;
|
||
uint8_t rank ;
|
||
uint8_t nvm_info ;
|
||
} regul_struct;
|
||
|
||
/* Private define ------------------------------------------------------------*/
|
||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||
|
||
/* Those define should reflect NVM_USER section
|
||
* For ES Eval Configuration this is specified as
|
||
* 0xF7,
|
||
0x92,
|
||
0xC0,
|
||
0x02,
|
||
0xFA,
|
||
0x30,
|
||
0x00,
|
||
0x33,
|
||
* */
|
||
#define NVM_SECTOR3_REGISTER_0 0xF7
|
||
#define NVM_SECTOR3_REGISTER_1 0x92
|
||
#define NVM_SECTOR3_REGISTER_2 0xC0
|
||
#define NVM_SECTOR3_REGISTER_3 0x02
|
||
#define NVM_SECTOR3_REGISTER_4 0xFA
|
||
#define NVM_SECTOR3_REGISTER_5 0x30
|
||
#define NVM_SECTOR3_REGISTER_6 0x00
|
||
#define NVM_SECTOR3_REGISTER_7 0x33
|
||
|
||
/* nvm_vinok_hyst: VINOK hysteresis voltage
|
||
00: 200mV
|
||
01: 300mV
|
||
10: 400mV
|
||
11: 500mV
|
||
*
|
||
* nvm_vinok: VINOK threshold voltage
|
||
00: 3.1v
|
||
01: 3.3v
|
||
10: 3.5v
|
||
11: 4.5v
|
||
Otp_ldo4_forced :
|
||
0: LDO4 ranks following OTP_RANK_LDO4<1:0>
|
||
if VBUS_OTG or SWOUT is turn ON condition
|
||
1: LDO4 follows normal ranking procedure
|
||
|
||
nvm_longkeypress:
|
||
0: Turn OFF on long key press inactive
|
||
1: Turn OFF on long key press active
|
||
|
||
nvm_autoturnon:
|
||
0: PMIC doesnt start automatically on VIN rising
|
||
1: PMIC starts automatically on VIN rising
|
||
|
||
nvm_cc_keepoff :
|
||
0: short circuit does not turn OFF PMIC
|
||
1: short circuit turn OFF PMIC and keep it OFF till CC_flag is reset
|
||
|
||
*
|
||
*/
|
||
#define OTP_VINOK_HYST ((NVM_SECTOR3_REGISTER_0 & 0xC0) >> 6) // nvm_vinok_hyst
|
||
#define OTP_VINOK ((NVM_SECTOR3_REGISTER_0 & 0x30) >> 4) // nvm_vinok
|
||
#define OTP_LDO4_FORCED ((NVM_SECTOR3_REGISTER_0 & 0x08) >> 3) // Otp_ldo4_forced
|
||
#define OTP_LONGKEYPRESSED ((NVM_SECTOR3_REGISTER_0 & 0x04) >> 2) // nvm_longkeypress
|
||
#define OTP_AUTOTURNON ((NVM_SECTOR3_REGISTER_0 & 0x02) >> 1) // nvm_autoturnon
|
||
#define OTP_CC_KEEPOFF ((NVM_SECTOR3_REGISTER_0 & 0x01)) // nvm_cc_keepoff
|
||
|
||
/*
|
||
* nvm_rank_buck4:
|
||
00: rank0
|
||
01: rank1
|
||
10: rank2
|
||
11: rank3
|
||
nvm_rank_buck3:
|
||
00: rank0
|
||
01: rank1
|
||
10: rank2
|
||
11: rank3
|
||
nvm_rank_buck2:
|
||
00: rank0
|
||
01: rank1
|
||
10: rank2
|
||
11: rank3
|
||
nvm_rank_buck1:
|
||
00: rank0
|
||
01: rank1
|
||
10: rank2
|
||
11: rank3
|
||
*
|
||
*/
|
||
#define OTP_RANK_BUCK4 ((NVM_SECTOR3_REGISTER_1 & 0xC0) >> 6) // nvm_rank_buck4
|
||
#define OTP_RANK_BUCK3 ((NVM_SECTOR3_REGISTER_1 & 0x30) >> 4) // nvm_rank_buck3
|
||
#define OTP_RANK_BUCK2 ((NVM_SECTOR3_REGISTER_1 & 0x0C) >> 2) // nvm_rank_buck2
|
||
#define OTP_RANK_BUCK1 ((NVM_SECTOR3_REGISTER_1 & 0x03)) // nvm_rank_buck1
|
||
|
||
|
||
/*
|
||
* nvm_rank_ldo4:
|
||
00: rank0
|
||
01: rank1
|
||
10: rank2
|
||
11: rank3
|
||
nvm_rank_ldo3:
|
||
00: rank0
|
||
01: rank1
|
||
10: rank2
|
||
11: rank3
|
||
nvm_rank_ldo2:
|
||
00: rank0
|
||
01: rank1
|
||
10: rank2
|
||
11: rank3
|
||
nvm_rank_ldo1:
|
||
00: rank0
|
||
01: rank1
|
||
10: rank2
|
||
11: rank3
|
||
*
|
||
*/
|
||
#define OTP_RANK_LDO4 ((NVM_SECTOR3_REGISTER_2 & 0xC0) >> 6) // nvm_rank_ldo4
|
||
#define OTP_RANK_LDO3 ((NVM_SECTOR3_REGISTER_2 & 0x30) >> 4) // nvm_rank_ldo3
|
||
#define OTP_RANK_LDO2 ((NVM_SECTOR3_REGISTER_2 & 0x0C) >> 2) // nvm_rank_ldo2
|
||
#define OTP_RANK_LDO1 ((NVM_SECTOR3_REGISTER_2 & 0x03)) // nvm_rank_ldo1
|
||
|
||
/*
|
||
* nvm_clamp_output_buck: Clamp output value to 1.3V max
|
||
0: output_buck4<5:0> not clamped
|
||
1: output_buck4<5:0> to b011100(1.3V)
|
||
|
||
nvm_bypass_mode_ldo3: LDO3 forced bypass mode
|
||
0: LDO3 not in bypass mode
|
||
1: LDO3 in bypass mode
|
||
|
||
nvm_rank_vrefddr:
|
||
00: rank0
|
||
01: rank1
|
||
10: rank2
|
||
11: rank3
|
||
|
||
nvm_rank_ldo6:
|
||
00: rank0
|
||
01: rank1
|
||
10: rank2
|
||
11: rank3
|
||
|
||
nvm_rank_ldo5:
|
||
00: rank0
|
||
01: rank1
|
||
10: rank2
|
||
11: rank3
|
||
*
|
||
*/
|
||
#define OTP_CLAMP_OUTPUT_BUCK4 ((NVM_SECTOR3_REGISTER_3 & 0x80) >> 7) // nvm_clamp_output_buck4
|
||
#define OTP_BYPASS_MODE_LDO3 ((NVM_SECTOR3_REGISTER_3 & 0x40) >> 6) // nvm_bypass_mode_ldo3
|
||
#define OTP_RANK_VREFDDR ((NVM_SECTOR3_REGISTER_3 & 0x30) >> 4) // nvm_rank_vrefddr
|
||
#define OTP_RANK_LDO6 ((NVM_SECTOR3_REGISTER_3 & 0x0C) >> 2) // nvm_rank_ldo6
|
||
#define OTP_RANK_LDO5 ((NVM_SECTOR3_REGISTER_3 & 0x03)) // nvm_rank_ldo5
|
||
|
||
/*
|
||
* nvm_output_buck4: Buck4 default output selection
|
||
00: 1.15V
|
||
01: 1.2V
|
||
10: 1.8V
|
||
11: 3.3V
|
||
nvm_output_buck3: Buck3 default output selection
|
||
00: 1.2V
|
||
01: 1.8V
|
||
10: 3.0V
|
||
11: 3.3V
|
||
nvm_output_buck2: Buck2 default output selection
|
||
00: 1.1V
|
||
01: 1.2V
|
||
10: 1.35V
|
||
11: 1.5V
|
||
nvm_output_buck1: Buck1 default output selection
|
||
00: 1.1V
|
||
01: 1.15V
|
||
10: 1.2V
|
||
11: 1.25V
|
||
*
|
||
*/
|
||
#define OTP_OUTPUT_BUCK4 ((NVM_SECTOR3_REGISTER_4 & 0xC0) >> 6) // nvm_output_buck4
|
||
#define OTP_OUTPUT_BUCK3 ((NVM_SECTOR3_REGISTER_4 & 0x30) >> 4) // nvm_output_buck3
|
||
#define OTP_OUTPUT_BUCK2 ((NVM_SECTOR3_REGISTER_4 & 0x0C) >> 2) // nvm_output_buck2
|
||
#define OTP_OUTPUT_BUCK1 ((NVM_SECTOR3_REGISTER_4 & 0x03)) // nvm_output_buck1
|
||
|
||
/*
|
||
* [7] OTP_SWOFF_BY_BOOST_OVP:
|
||
0 -> SWOUT will not turnoff bu boost OVP
|
||
1 -> SWOUT will be turnoff by BOOST OVP
|
||
|
||
[6] reserved
|
||
|
||
[5:4] nvm_output_ldo3: LDO3 default output selection
|
||
00: 1.8V
|
||
01: 2.5V
|
||
10: 3.3V
|
||
11: output_buck2<4:0>/2 (VTT termination for DDR3 x32, Analog divider implemented in Analog)
|
||
|
||
[3:2] nvm_output_ldo2: LDO2 default output selection
|
||
00: 1.8V
|
||
01: 2.5V
|
||
10: 2.9V
|
||
11: 3.3V
|
||
|
||
[1:0] nvm_output_ldo1: LDO1 default output selection
|
||
00: 1.8V
|
||
01: 2.5V
|
||
10: 2.9V
|
||
11: 3.3V
|
||
|
||
*
|
||
*/
|
||
#define OTP_SWOFF_BY_BOOST_OVP ((NVM_SECTOR3_REGISTER_5 & 0x80) >> 7) // OTP_SWOFF_BY_BOOST_OVP
|
||
#define OTP_OUTPUT_LDO3 ((NVM_SECTOR3_REGISTER_5 & 0x30) >> 4) // nvm_output_ldo3
|
||
#define OTP_OUTPUT_LDO2 ((NVM_SECTOR3_REGISTER_5 & 0x0C) >> 2) // nvm_output_ldo2
|
||
#define OTP_OUTPUT_LDO1 ((NVM_SECTOR3_REGISTER_5 & 0x03)) // nvm_output_ldo1
|
||
|
||
/*
|
||
* [7:4] reserved
|
||
*
|
||
[3:2] nvm_output_ldo6: LDO6 default output selection
|
||
00: 1.0V
|
||
01: 1.2V
|
||
10: 1.8V
|
||
11: 3.3V
|
||
|
||
[1:0] nvm_output_ldo5: LDO5 default output selection
|
||
00: 1.8V
|
||
01: 2.5V
|
||
10: 2.9V
|
||
11 : 3.3V
|
||
*
|
||
*/
|
||
|
||
#define OTP_OUTPUT_LDO6 ((NVM_SECTOR3_REGISTER_6 & 0x0C) >> 2) // nvm_output_ldo6
|
||
#define OTP_OUTPUT_LDO5 ((NVM_SECTOR3_REGISTER_6 & 0x03)) // nvm_output_ldo5
|
||
|
||
/* Private macro -------------------------------------------------------------*/
|
||
/* Private variables ---------------------------------------------------------*/
|
||
/* I2C handler declaration */
|
||
I2C_HandleTypeDef I2cHandle;
|
||
extern I2C_HandleTypeDef hI2c4;
|
||
|
||
uint16_t buck1_voltage_table[] = {
|
||
600,
|
||
625,
|
||
650,
|
||
675,
|
||
700,
|
||
725,
|
||
750,
|
||
775,
|
||
800,
|
||
825,
|
||
850,
|
||
875,
|
||
900,
|
||
925,
|
||
950,
|
||
975,
|
||
1000,
|
||
1025,
|
||
1050,
|
||
1075,
|
||
1100,
|
||
1125,
|
||
1150,
|
||
1175,
|
||
1200,
|
||
1225,
|
||
1250,
|
||
1275,
|
||
1300,
|
||
1325,
|
||
1350,
|
||
1350,// 31 1,35stm32mp15xx_eval_stpmu1.c
|
||
};
|
||
|
||
uint16_t buck2_voltage_table[] = {
|
||
1000, // 1
|
||
1000, //
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1050, // 1,05
|
||
1050, // 1,05
|
||
1100, // 1,1
|
||
1100, // 1,1
|
||
1150, // 1,15
|
||
1150, // 1,15
|
||
1200, // 1,2
|
||
1200, // 1,2
|
||
1250, // 1,25
|
||
1250, // 1,25
|
||
1300, // 1,3
|
||
1300, // 1,3
|
||
1350, // 1,35
|
||
1350, // 1,35
|
||
1400, // 1,4
|
||
1400, // 1,4
|
||
1450, // 1,45
|
||
1450, // 1,45
|
||
1500, // 1,5
|
||
};
|
||
|
||
uint16_t buck3_voltage_table[] = {
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1000, // 1
|
||
1100, // 1,1
|
||
1100, // 1,1
|
||
1100, // 1,1
|
||
1100, // 1,1
|
||
1200, // 1,2
|
||
1200, // 1,2
|
||
1200, // 1,2
|
||
1200, // 1,2
|
||
1300, // 1,3
|
||
1300, // 1,3
|
||
1300, // 1,3
|
||
1300, // 1,3
|
||
1400, // 1,4
|
||
1400, // 1,4
|
||
1400, // 1,4
|
||
1400, // 1,4
|
||
1500, // 1,5
|
||
1600, // 1,6
|
||
1700, // 1,7
|
||
1800, // 1,8
|
||
1900, // 1,9
|
||
2000, // 2
|
||
2100, // 2,1
|
||
2200, // 2,2
|
||
2300, // 2,3
|
||
2400, // 2,4
|
||
2500, // 2,5
|
||
2600, // 2,6
|
||
2700, // 2,7
|
||
2800, // 2,8
|
||
2900, // 2,9
|
||
3000, // 3
|
||
3100, // 3,1
|
||
3200, // 3,2
|
||
3300, // 3,3
|
||
3400, // 3,4
|
||
};
|
||
|
||
uint16_t buck4_voltage_table[] = {
|
||
600,
|
||
625,
|
||
650,
|
||
675,
|
||
700,
|
||
725,
|
||
750,
|
||
775,
|
||
800,
|
||
825,
|
||
850,
|
||
875,
|
||
900,
|
||
925,
|
||
950,
|
||
975,
|
||
1000,
|
||
1025,
|
||
1050,
|
||
1075,
|
||
1100,
|
||
1125,
|
||
1150,
|
||
1175,
|
||
1200,
|
||
1225,
|
||
1250,
|
||
1275,
|
||
1300,
|
||
1300,
|
||
1350,
|
||
1350,// 31 1,35
|
||
1400,// 32 1,40
|
||
1400,// 33 1,40
|
||
1450,// 34 1,45
|
||
1450,// 35 1,45
|
||
1500,// 36 1,5
|
||
1600,// 37 1,6
|
||
1700,// 38 1,7
|
||
1800,// 39 1,8
|
||
1900,// 40 1,9
|
||
2000,// 41 2,0
|
||
2100,// 42 2,1
|
||
2200,// 43 2,2
|
||
2300,// 44 2,3
|
||
2400,// 45 2,4
|
||
2500,// 46 2,5
|
||
2600,// 47 2,6
|
||
2700,// 48 2,7
|
||
2800,// 49 2,8
|
||
2900,// 50 2,9
|
||
3000,// 51 3,0
|
||
3100,// 52 3,1
|
||
3200,// 53 3,2
|
||
3300,// 54 3,3
|
||
3400,// 55 3,4
|
||
3500,// 56 3,5
|
||
3600,// 57 3,6
|
||
3700,// 58 3,7
|
||
3800,// 59 3,8
|
||
3900,// 60 3,9
|
||
};
|
||
|
||
uint16_t ldo1_voltage_table[] = {
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1800, // 1,8
|
||
1900, // 1,9
|
||
2000, // 2
|
||
2100, // 2,1
|
||
2200, // 2,2
|
||
2300, // 2,3
|
||
2400, // 2,4
|
||
2500, // 2,5
|
||
2600, // 2,6
|
||
2700, // 2,7
|
||
2800, // 2,8
|
||
2900, // 2,9
|
||
3000, // 3
|
||
3100, // 3,1
|
||
3200, // 3,2
|
||
3300, // 3,3
|
||
};
|
||
|
||
uint16_t ldo2_voltage_table[] = {
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1800, // 1,8
|
||
1900, // 1,9
|
||
2000, // 2
|
||
2100, // 2,1
|
||
2200, // 2,2
|
||
2300, // 2,3
|
||
2400, // 2,4
|
||
2500, // 2,5
|
||
2600, // 2,6
|
||
2700, // 2,7
|
||
2800, // 2,8
|
||
2900, // 2,9
|
||
3000, // 3
|
||
3100, // 3,1
|
||
3200, // 3,2
|
||
3300, // 3,3
|
||
};
|
||
|
||
uint16_t ldo3_voltage_table[] = {
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1800, // 1,8
|
||
1900, // 1,9
|
||
2000, // 2
|
||
2100, // 2,1
|
||
2200, // 2,2
|
||
2300, // 2,3
|
||
2400, // 2,4
|
||
2500, // 2,5
|
||
2600, // 2,6
|
||
2700, // 2,7
|
||
2800, // 2,8
|
||
2900, // 2,9
|
||
3000, // 3
|
||
3100, // 3,1
|
||
3200, // 3,2
|
||
3300, // 3,3
|
||
3300, // 3,3
|
||
3300, // 3,3
|
||
3300, // 3,3
|
||
3300, // 3,3
|
||
3300, // 3,3
|
||
3300, // 3,3
|
||
0xFFFF, // VREFDDR
|
||
};
|
||
|
||
|
||
uint16_t ldo5_voltage_table[] = {
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1700, // 1,7
|
||
1800, // 1,8
|
||
1900, // 1,9
|
||
2000, // 2
|
||
2100, // 2,1
|
||
2200, // 2,2
|
||
2300, // 2,3
|
||
2400, // 2,4
|
||
2500, // 2,5
|
||
2600, // 2,6
|
||
2700, // 2,7
|
||
2800, // 2,8
|
||
2900, // 2,9
|
||
3000, // 3
|
||
3100, // 3,1
|
||
3200, // 3,2
|
||
3300, // 3,3
|
||
3400, // 3,4
|
||
3500, // 3,5
|
||
3600, // 3,6
|
||
3700, // 3,7
|
||
3800, // 3,8
|
||
3900, // 3,9
|
||
};
|
||
|
||
uint16_t ldo6_voltage_table[] = {
|
||
900, // 0,9
|
||
1000, // 1,0
|
||
1100, // 1,1
|
||
1200, // 1,2
|
||
1300, // 1,3
|
||
1400, // 1,4
|
||
1500, // 1,5
|
||
1600, // 1,6
|
||
1700, // 1,7
|
||
1800, // 1,8
|
||
1900, // 1,9
|
||
2000, // 2
|
||
2100, // 2,1
|
||
2200, // 2,2
|
||
2300, // 2,3
|
||
2400, // 2,4
|
||
2500, // 2,5
|
||
2600, // 2,6
|
||
2700, // 2,7
|
||
2800, // 2,8
|
||
2900, // 2,9
|
||
3000, // 3
|
||
3100, // 3,1
|
||
3200, // 3,2
|
||
3300, // 3,3
|
||
};
|
||
|
||
|
||
uint16_t ldo4_voltage_table[] = {
|
||
3300, // 3,3
|
||
};
|
||
|
||
uint16_t vref_ddr_voltage_table[] = {
|
||
3300, // 3,3
|
||
};
|
||
|
||
/*
|
||
Table of Regulators in PMIC SoC
|
||
*/
|
||
|
||
|
||
|
||
regul_struct regulators_table[] = {
|
||
{
|
||
.id = STPMU1_BUCK1,
|
||
.voltage_table = buck1_voltage_table,
|
||
.voltage_table_size = ARRAY_SIZE(buck1_voltage_table),
|
||
.control_reg = BUCK1_CONTROL_REG,
|
||
.low_power_reg = BUCK1_PWRCTRL_REG,
|
||
.rank = OTP_RANK_BUCK1,
|
||
},
|
||
{
|
||
.id = STPMU1_BUCK2,
|
||
.voltage_table = buck2_voltage_table,
|
||
.voltage_table_size = ARRAY_SIZE(buck2_voltage_table),
|
||
.control_reg = BUCK2_CONTROL_REG,
|
||
.low_power_reg = BUCK2_PWRCTRL_REG,
|
||
.rank = OTP_RANK_BUCK2,
|
||
},
|
||
{
|
||
.id = STPMU1_BUCK3,
|
||
.voltage_table = buck3_voltage_table,
|
||
.voltage_table_size = ARRAY_SIZE(buck3_voltage_table),
|
||
.control_reg = BUCK3_CONTROL_REG,
|
||
.low_power_reg = BUCK3_PWRCTRL_REG,
|
||
.rank = OTP_RANK_BUCK3,
|
||
},
|
||
{
|
||
.id = STPMU1_BUCK4,
|
||
.voltage_table = buck4_voltage_table,
|
||
.voltage_table_size = ARRAY_SIZE(buck4_voltage_table),
|
||
.control_reg = BUCK4_CONTROL_REG,
|
||
.low_power_reg = BUCK4_PWRCTRL_REG,
|
||
.rank = OTP_RANK_BUCK4,
|
||
},
|
||
{
|
||
.id = STPMU1_LDO1,
|
||
.voltage_table = ldo1_voltage_table,
|
||
.voltage_table_size = ARRAY_SIZE(ldo1_voltage_table),
|
||
.control_reg = LDO1_CONTROL_REG,
|
||
.low_power_reg = LDO1_PWRCTRL_REG,
|
||
.rank = OTP_RANK_LDO1,
|
||
},
|
||
{
|
||
.id = STPMU1_LDO2,
|
||
.voltage_table = ldo2_voltage_table,
|
||
.voltage_table_size = ARRAY_SIZE(ldo2_voltage_table),
|
||
.control_reg = LDO2_CONTROL_REG,
|
||
.low_power_reg = LDO2_PWRCTRL_REG,
|
||
.rank = OTP_RANK_LDO2,
|
||
},
|
||
|
||
{
|
||
.id = STPMU1_LDO3,
|
||
.voltage_table = ldo3_voltage_table,
|
||
.voltage_table_size = ARRAY_SIZE(ldo3_voltage_table),
|
||
.control_reg = LDO3_CONTROL_REG,
|
||
.low_power_reg = LDO3_PWRCTRL_REG,
|
||
.rank = OTP_RANK_LDO3,
|
||
},
|
||
{
|
||
.id = STPMU1_LDO4,
|
||
.voltage_table = ldo4_voltage_table,
|
||
.voltage_table_size = ARRAY_SIZE(ldo4_voltage_table),
|
||
.control_reg = LDO4_CONTROL_REG,
|
||
.low_power_reg = LDO4_PWRCTRL_REG,
|
||
.rank = OTP_RANK_LDO4,
|
||
},
|
||
{
|
||
.id = STPMU1_LDO5,
|
||
.voltage_table = ldo5_voltage_table ,
|
||
.voltage_table_size = ARRAY_SIZE(ldo5_voltage_table),
|
||
.control_reg = LDO5_CONTROL_REG,
|
||
.low_power_reg = LDO5_PWRCTRL_REG,
|
||
.rank = OTP_RANK_LDO5,
|
||
},
|
||
{
|
||
.id = STPMU1_LDO6,
|
||
.voltage_table = ldo6_voltage_table ,
|
||
.voltage_table_size = ARRAY_SIZE(ldo6_voltage_table),
|
||
.control_reg = LDO6_CONTROL_REG,
|
||
.low_power_reg = LDO6_PWRCTRL_REG,
|
||
.rank = OTP_RANK_LDO6,
|
||
},
|
||
{
|
||
.id = STPMU1_VREFDDR,
|
||
.voltage_table = vref_ddr_voltage_table ,
|
||
.voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table),
|
||
.control_reg = VREF_DDR_CONTROL_REG,
|
||
.low_power_reg = VREF_DDR_PWRCTRL_REG,
|
||
.rank = OTP_RANK_VREFDDR,
|
||
},
|
||
};
|
||
|
||
#define MAX_REGUL ARRAY_SIZE(regulators_table)
|
||
|
||
|
||
/* Private function prototypes -----------------------------------------------*/
|
||
void STPMU1_IrqHandler(void);
|
||
void STPMU1_INTn_Callback(PMIC_IRQn IRQn);
|
||
static void My_Error_Handler(void);
|
||
static regul_struct *STPMU1_Get_Regulator_Data(PMIC_RegulId_TypeDef id);
|
||
static uint8_t STPMU1_Voltage_Find_Index(PMIC_RegulId_TypeDef id, uint16_t milivolts);
|
||
|
||
/* Private functions ---------------------------------------------------------*/
|
||
|
||
static regul_struct *STPMU1_Get_Regulator_Data(PMIC_RegulId_TypeDef id)
|
||
{
|
||
uint8_t i ;
|
||
|
||
for (i = 0 ; i < MAX_REGUL ; i++ )
|
||
{
|
||
if (id == regulators_table[i].id)
|
||
return ®ulators_table[i];
|
||
}
|
||
/* id not found */
|
||
My_Error_Handler();
|
||
return NULL;
|
||
}
|
||
|
||
static uint8_t STPMU1_Voltage_Find_Index(PMIC_RegulId_TypeDef id, uint16_t milivolts)
|
||
{
|
||
regul_struct *regul = STPMU1_Get_Regulator_Data(id);
|
||
uint8_t i;
|
||
for ( i = 0 ; i < regul->voltage_table_size ; i++)
|
||
{
|
||
if ( regul->voltage_table[i] == milivolts ) {
|
||
//printf("idx:%d for %dmV\n\r", (int)i, (int)milivolts);
|
||
return i;
|
||
}
|
||
}
|
||
/* voltage not found */
|
||
My_Error_Handler();
|
||
return 0;
|
||
}
|
||
|
||
void STPMU1_Enable_Interrupt(PMIC_IRQn IRQn)
|
||
{
|
||
uint8_t irq_reg , irq_reg_value ;
|
||
|
||
if (IRQn >= IRQ_NR)
|
||
return ;
|
||
|
||
/* IRQ register is IRQ Number divided by 8 */
|
||
irq_reg = IRQn >> 3 ;
|
||
|
||
/* value to be set in IRQ register corresponds to BIT(7-N) where N is the Interrupt id modulo 8 */
|
||
irq_reg_value = 1 << ( 7 - ( IRQn%8 ) );
|
||
|
||
/* Clear previous event stored in latch */
|
||
STPMU1_Register_Write(ITCLEARLATCH1_REG+irq_reg, irq_reg_value );
|
||
|
||
/* Clear relevant mask to enable interrupt */
|
||
STPMU1_Register_Write(ITCLEARMASK1_REG+irq_reg, irq_reg_value );
|
||
|
||
}
|
||
|
||
extern void STPMU1_Disable_Interrupt(PMIC_IRQn IRQn)
|
||
{
|
||
uint8_t irq_reg , irq_reg_value ;
|
||
|
||
if (IRQn >= IRQ_NR)
|
||
return ;
|
||
|
||
/* IRQ register is IRQ Number divided by 8 */
|
||
irq_reg = IRQn >> 3 ;
|
||
|
||
/* value to be set in IRQ register corresponds to BIT(7-N) where N is the Interrupt id modulo 8 */
|
||
irq_reg_value = 1 << ( 7 - ( IRQn%8 ) );
|
||
|
||
/* Clear previous event stored in latch */
|
||
STPMU1_Register_Write(ITCLEARLATCH1_REG+irq_reg, irq_reg_value );
|
||
|
||
/* Set relevant mask to disable interrupt */
|
||
STPMU1_Register_Write(ITSETMASK1_REG+irq_reg, irq_reg_value );
|
||
}
|
||
|
||
|
||
void STPMU1_IrqHandler(void)
|
||
{
|
||
uint8_t irq_reg,mask,latch_events,i;
|
||
|
||
for (irq_reg = 0 ; irq_reg < STM32_PMIC_NUM_IRQ_REGS ; irq_reg++)
|
||
{
|
||
/* Get latch events & active mask from register */
|
||
mask = STPMU1_Register_Read(ITMASK1_REG+irq_reg);
|
||
latch_events = STPMU1_Register_Read(ITLATCH1_REG+irq_reg) & ~mask ;
|
||
|
||
/* Go through all bits for each register */
|
||
for (i = 0 ; i < 8 ; i++ )
|
||
{
|
||
if ( latch_events & ( 1 << i ) )
|
||
{
|
||
/* Callback with parameter computes as "PMIC Interrupt" enum */
|
||
STPMU1_INTn_Callback( (PMIC_IRQn )(irq_reg*8 + (7-i)));
|
||
}
|
||
}
|
||
/* Clear events in appropriate register for the event with mask set */
|
||
STPMU1_Register_Write(ITCLEARLATCH1_REG+irq_reg, latch_events );
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief This function is executed in case of error occurrence.
|
||
* @retval None
|
||
*/
|
||
static void My_Error_Handler(void)
|
||
{
|
||
while(1)
|
||
{
|
||
HAL_Delay(500);
|
||
}
|
||
}
|
||
|
||
|
||
void STPMU1_Sw_Reset(void)
|
||
{
|
||
/* Write 1 in bit 0 of MAIN_CONTROL Register */
|
||
STPMU1_Register_Update(MAIN_CONTROL_REG, SET , SOFTWARE_SWITCH_OFF_ENABLED );
|
||
}
|
||
|
||
void STPMU1_Regulator_Enable(PMIC_RegulId_TypeDef id)
|
||
{
|
||
regul_struct *regul = STPMU1_Get_Regulator_Data(id);
|
||
|
||
STPMU1_Register_Update(regul->control_reg,BIT(0),BIT(0));
|
||
}
|
||
|
||
void STPMU1_Regulator_Disable(PMIC_RegulId_TypeDef id)
|
||
{
|
||
regul_struct *regul = STPMU1_Get_Regulator_Data(id);
|
||
|
||
STPMU1_Register_Update(regul->control_reg,0,BIT(0));
|
||
}
|
||
|
||
uint8_t STPMU1_Is_Regulator_Enabled(PMIC_RegulId_TypeDef id)
|
||
{
|
||
uint8_t val ;
|
||
|
||
regul_struct *regul = STPMU1_Get_Regulator_Data(id);
|
||
|
||
val = STPMU1_Register_Read(regul->control_reg);
|
||
|
||
return (val&0x1);
|
||
}
|
||
|
||
void STPMU1_Regulator_Voltage_Set(PMIC_RegulId_TypeDef id,uint16_t milivolts)
|
||
{
|
||
uint8_t voltage_index = STPMU1_Voltage_Find_Index(id,milivolts);
|
||
regul_struct *regul = STPMU1_Get_Regulator_Data(id);
|
||
STPMU1_Register_Update(regul->control_reg, voltage_index<<2 , 0xFC );
|
||
}
|
||
|
||
/* register direct access */
|
||
uint8_t STPMU1_Register_Read(uint8_t register_id)
|
||
{
|
||
uint32_t status = RT_EOK;
|
||
uint8_t Value = 0;
|
||
|
||
status = BSP_I2C4_ReadReg(STPMU1_I2C_ADDRESS, (uint16_t)register_id, &Value, 1);
|
||
|
||
/* Check the communication status */
|
||
if(status != RT_EOK)
|
||
{
|
||
My_Error_Handler();
|
||
}
|
||
return Value;
|
||
}
|
||
|
||
void STPMU1_Register_Write(uint8_t register_id, uint8_t value)
|
||
{
|
||
uint32_t status = RT_EOK;
|
||
|
||
status = BSP_I2C4_WriteReg(STPMU1_I2C_ADDRESS, (uint16_t)register_id, &value, 1);
|
||
|
||
/* Check the communication status */
|
||
if(status != RT_EOK)
|
||
{
|
||
My_Error_Handler();
|
||
}
|
||
|
||
/* verify register content */
|
||
if ((register_id!=WATCHDOG_CONTROL_REG) && (register_id<=0x40))
|
||
{
|
||
uint8_t readval = STPMU1_Register_Read(register_id);
|
||
if (readval != value)
|
||
{
|
||
My_Error_Handler();
|
||
}
|
||
}
|
||
}
|
||
|
||
void STPMU1_Register_Update(uint8_t register_id, uint8_t value, uint8_t mask)
|
||
{
|
||
uint8_t initial_value ;
|
||
|
||
initial_value = STPMU1_Register_Read(register_id);
|
||
|
||
/* Clear bits to update */
|
||
initial_value &= ~mask;
|
||
|
||
/* Update appropriate bits*/
|
||
initial_value |= ( value & mask );
|
||
|
||
/* Send new value on I2C Bus */
|
||
STPMU1_Register_Write(register_id, initial_value);
|
||
|
||
return ;
|
||
}
|
||
|
||
/*
|
||
*
|
||
* PMIC init
|
||
* pmic provides power supply on this board
|
||
* it is configured to turn off some power supply in standby mode
|
||
*
|
||
*/
|
||
static uint32_t BSP_PMIC_MspInit(I2C_HandleTypeDef *hi2c)
|
||
{
|
||
uint32_t status = RT_EOK;
|
||
GPIO_InitTypeDef GPIO_InitStruct;
|
||
|
||
/*##-1- Configure the I2C clock source, GPIO and Interrupt #*/
|
||
BSP_I2C4_Init();
|
||
|
||
/*##-2- Configure PMIC GPIOs Interface ########################################*/
|
||
|
||
/* INTn - Interrupt Line - Active Low (Falling Edge) */
|
||
PMIC_INTn_CLK_ENABLE();
|
||
GPIO_InitStruct.Pin = PMIC_INTn_PIN;
|
||
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
|
||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||
GPIO_InitStruct.Alternate = 0 ;
|
||
HAL_GPIO_Init(PMIC_INTn_PORT, &GPIO_InitStruct);
|
||
|
||
/* Enable and set INTn EXTI Interrupt */
|
||
#if defined(CORE_CA7)
|
||
IRQ_SetPriority(EXTI0_IRQn, 0);
|
||
IRQ_Enable(EXTI0_IRQn);
|
||
#elif defined(CORE_CM4)
|
||
HAL_NVIC_SetPriority(EXTI0_IRQn, 0x03, 0x00);
|
||
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
|
||
#endif
|
||
|
||
return status;
|
||
}
|
||
|
||
static uint32_t BSP_PMIC_MspDeInit(I2C_HandleTypeDef *hi2c)
|
||
{
|
||
uint32_t status = RT_EOK;
|
||
/*##-1- Reset I2C Clock / Disable peripherals and GPIO Clocks###############*/
|
||
status = BSP_I2C4_DeInit();
|
||
|
||
/*##-2- Disable PMIC clk ###########################################*/
|
||
PMIC_INTn_CLK_DISABLE();
|
||
|
||
/*##-3- Disable the NVIC for PMIC ##########################################*/
|
||
#if defined(CORE_CA7)
|
||
IRQ_Disable(EXTI0_IRQn);
|
||
#elif defined(CORE_CM4)
|
||
HAL_NVIC_DisableIRQ(EXTI0_IRQn);
|
||
#endif
|
||
HAL_GPIO_DeInit(PMIC_INTn_PORT,PMIC_INTn_PIN);
|
||
|
||
return status;
|
||
}
|
||
|
||
uint32_t BSP_PMIC_Is_Device_Ready(void)
|
||
{
|
||
int32_t status = RT_EOK;
|
||
|
||
/* Write the TxBuffer1 at @0, then read @0 when device ready */
|
||
if (BSP_I2C4_IsReady(STPMU1_I2C_ADDRESS, 1) != RT_EOK)
|
||
{
|
||
status = -RT_EBUSY;
|
||
}
|
||
return status ;
|
||
}
|
||
|
||
/* Use Xls I2C COnfiguration Tools with I2C Clock config + output clocks requirement */
|
||
#define I2C_TIMING 0x10805E89
|
||
|
||
uint32_t BSP_PMIC_Init(void)
|
||
{
|
||
int32_t status = RT_EOK;
|
||
PMIC_IRQn irq;
|
||
|
||
/*##-1- Configure the I2C peripheral ######################################*/
|
||
BSP_PMIC_MspInit(&hI2c4);
|
||
|
||
status = BSP_PMIC_Is_Device_Ready();
|
||
if (status != RT_EOK )
|
||
{
|
||
return status;
|
||
}
|
||
|
||
if (STPMU1_Register_Read(VERSION_STATUS_REG) != 0x00)
|
||
{
|
||
status = -RT_EIO;
|
||
return status;
|
||
}
|
||
|
||
STPMU1_Enable_Interrupt(IT_PONKEY_R);
|
||
STPMU1_Enable_Interrupt(IT_PONKEY_F);
|
||
/* enable all irqs */
|
||
for (irq = IT_SWOUT_R; irq < IRQ_NR; irq++)
|
||
{
|
||
STPMU1_Enable_Interrupt(irq);
|
||
}
|
||
|
||
return RT_EOK;
|
||
}
|
||
|
||
uint32_t BSP_PMIC_DeInit(void)
|
||
{
|
||
uint32_t status = RT_EOK;
|
||
if(HAL_I2C_GetState(&hI2c4) != HAL_I2C_STATE_RESET)
|
||
{
|
||
/* Deinit the I2C */
|
||
BSP_PMIC_MspDeInit(&hI2c4);
|
||
}
|
||
return status;
|
||
}
|
||
|
||
/*
|
||
*
|
||
* following are configurations for this board
|
||
* same configuration than linux
|
||
*
|
||
* BSP_PMIC_InitRegulators set the regulators for boot
|
||
* BSP_PMIC_PrepareLpStop set the low power registers for LPSTOP mode
|
||
* should be called by user before entering is CSTOP
|
||
* BSP_PMIC_PrepareLpStop set the low power registers for STANDBY mode
|
||
* should be called by user before entering is STANDBY
|
||
*
|
||
*
|
||
*/
|
||
/* following are configurations */
|
||
uint32_t BSP_PMIC_InitRegulators(void)
|
||
{
|
||
uint32_t status = RT_EOK;
|
||
|
||
STPMU1_Register_Write(MAIN_CONTROL_REG, 0x04);
|
||
STPMU1_Register_Write(VIN_CONTROL_REG, 0xc0);
|
||
STPMU1_Register_Write(USB_CONTROL_REG, 0x30);
|
||
|
||
STPMU1_Register_Write(MASK_RESET_BUCK_REG, 0x04);
|
||
STPMU1_Register_Write(MASK_RESET_LDO_REG, 0x00);
|
||
STPMU1_Register_Write(MASK_RANK_BUCK_REG, 0x00);
|
||
STPMU1_Register_Write(MASK_RANK_LDO_REG, 0x00);
|
||
STPMU1_Register_Write(BUCK_PULL_DOWN_REG, 0x00);
|
||
STPMU1_Register_Write(LDO14_PULL_DOWN_REG, 0x00);
|
||
STPMU1_Register_Write(LDO56_PULL_DOWN_REG, 0x00);
|
||
STPMU1_Register_Write(BUCK_ICC_TURNOFF_REG, 0x30);
|
||
STPMU1_Register_Write(LDO_ICC_TURNOFF_REG, 0x3b);
|
||
|
||
/* vddcore */
|
||
STPMU1_Regulator_Voltage_Set(STPMU1_BUCK1, 1200);
|
||
STPMU1_Regulator_Enable(STPMU1_BUCK1);
|
||
|
||
/* vddddr */
|
||
STPMU1_Regulator_Voltage_Set(STPMU1_BUCK2, 1350);
|
||
STPMU1_Regulator_Enable(STPMU1_BUCK2);
|
||
|
||
/* vdd */
|
||
STPMU1_Regulator_Voltage_Set(STPMU1_BUCK3, 3300);
|
||
STPMU1_Regulator_Enable(STPMU1_BUCK3);
|
||
|
||
/* 3v3 */
|
||
STPMU1_Regulator_Voltage_Set(STPMU1_BUCK4, 3300);
|
||
STPMU1_Regulator_Enable(STPMU1_BUCK4);
|
||
|
||
/* vdda */
|
||
STPMU1_Regulator_Voltage_Set(STPMU1_LDO1, 2900);
|
||
STPMU1_Regulator_Enable(STPMU1_LDO1);
|
||
|
||
/* 2v8 */
|
||
STPMU1_Regulator_Voltage_Set(STPMU1_LDO2, 2800);
|
||
STPMU1_Regulator_Enable(STPMU1_LDO2);
|
||
|
||
/* vtt_ddr lod3 mode buck2/2 */
|
||
STPMU1_Regulator_Voltage_Set(STPMU1_LDO3, 0xFFFF);
|
||
STPMU1_Regulator_Enable(STPMU1_LDO3);
|
||
|
||
/* vdd_usb */
|
||
STPMU1_Regulator_Voltage_Set(STPMU1_LDO4, 3300);
|
||
STPMU1_Regulator_Enable(STPMU1_LDO4);
|
||
|
||
/* vdd_sd */
|
||
STPMU1_Regulator_Voltage_Set(STPMU1_LDO5, 2900);
|
||
STPMU1_Regulator_Enable(STPMU1_LDO5);
|
||
|
||
/* 1v8 */
|
||
STPMU1_Regulator_Voltage_Set(STPMU1_LDO6, 1800);
|
||
STPMU1_Regulator_Enable(STPMU1_LDO6);
|
||
|
||
STPMU1_Regulator_Enable(STPMU1_VREFDDR);
|
||
|
||
return status;
|
||
}
|
||
|
||
uint32_t BSP_PMIC_SwitchOff(void)
|
||
{
|
||
uint32_t status = RT_EOK;
|
||
|
||
STPMU1_Register_Write(MAIN_CONTROL_REG, 0x01);
|
||
return status;
|
||
}
|
||
|
||
__weak void BSP_PMIC_INTn_Callback(PMIC_IRQn IRQn)
|
||
{
|
||
switch (IRQn)
|
||
{
|
||
case IT_PONKEY_F:
|
||
rt_kprintf("IT_PONKEY_F");
|
||
break;
|
||
|
||
case IT_PONKEY_R:
|
||
rt_kprintf("IT_PONKEY_R");
|
||
break;
|
||
|
||
case IT_WAKEUP_F:
|
||
rt_kprintf("IT_WAKEUP_F");
|
||
break;
|
||
|
||
case IT_WAKEUP_R:
|
||
rt_kprintf("IT_WAKEUP_R");
|
||
break;
|
||
|
||
case IT_VBUS_OTG_F:
|
||
rt_kprintf("IT_VBUS_OTG_F");
|
||
break;
|
||
|
||
case IT_SWOUT_F:
|
||
rt_kprintf("IT_SWOUT_F");
|
||
break;
|
||
|
||
case IT_TWARN_R:
|
||
rt_kprintf("IT_TWARN_R");
|
||
break;
|
||
|
||
case IT_TWARN_F:
|
||
rt_kprintf("IT_TWARN_F");
|
||
break;
|
||
|
||
default:
|
||
rt_kprintf("%d",IRQn);
|
||
break;
|
||
}
|
||
rt_kprintf(" Interrupt received\n\r");
|
||
}
|
||
|
||
void STPMU1_INTn_Callback(PMIC_IRQn IRQn)
|
||
{
|
||
BSP_PMIC_INTn_Callback(IRQn);
|
||
}
|
||
|
||
void BSP_PMIC_INTn_IRQHandler(void)
|
||
{
|
||
HAL_GPIO_EXTI_IRQHandler(PMIC_INTn_PIN);
|
||
|
||
STPMU1_IrqHandler();
|
||
}
|
||
|
||
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hI2c4)
|
||
{
|
||
while(1);
|
||
}
|