mirror of
https://github.com/CTCaer/switch-l4t-atf.git
synced 2024-11-28 04:10:32 +00:00
stm32mp1: Add PMIC support
If a PMIC companion chip is present on board, it has to be configured for regulators supplies. This check is done with board DT configuration. Signed-off-by: Yann Gautier <yann.gautier@st.com> Signed-off-by: Pascal Paillet <p.paillet@st.com>
This commit is contained in:
parent
278c34df06
commit
e4f559ff54
851
drivers/st/pmic/stm32_i2c.c
Normal file
851
drivers/st/pmic/stm32_i2c.c
Normal file
@ -0,0 +1,851 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <delay_timer.h>
|
||||
#include <errno.h>
|
||||
#include <mmio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stm32_i2c.h>
|
||||
|
||||
/* STM32 I2C registers offsets */
|
||||
#define I2C_CR1 0x00U
|
||||
#define I2C_CR2 0x04U
|
||||
#define I2C_OAR1 0x08U
|
||||
#define I2C_OAR2 0x0CU
|
||||
#define I2C_TIMINGR 0x10U
|
||||
#define I2C_TIMEOUTR 0x14U
|
||||
#define I2C_ISR 0x18U
|
||||
#define I2C_ICR 0x1CU
|
||||
#define I2C_PECR 0x20U
|
||||
#define I2C_RXDR 0x24U
|
||||
#define I2C_TXDR 0x28U
|
||||
|
||||
#define MAX_DELAY 0xFFFFFFFFU
|
||||
|
||||
/* I2C TIMING clear register Mask */
|
||||
#define TIMING_CLEAR_MASK 0xF0FFFFFFU
|
||||
/* Timeout 25 ms */
|
||||
#define I2C_TIMEOUT_BUSY 25U
|
||||
|
||||
#define MAX_NBYTE_SIZE 255U
|
||||
|
||||
static int i2c_request_memory_write(struct i2c_handle_s *hi2c,
|
||||
uint16_t dev_addr, uint16_t mem_addr,
|
||||
uint16_t mem_add_size, uint32_t timeout,
|
||||
uint32_t tick_start);
|
||||
static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
|
||||
uint16_t mem_addr, uint16_t mem_add_size,
|
||||
uint32_t timeout, uint32_t tick_start);
|
||||
|
||||
/* Private functions to handle flags during polling transfer */
|
||||
static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag,
|
||||
uint8_t awaited_value, uint32_t timeout,
|
||||
uint32_t tick_start);
|
||||
static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint32_t timeout,
|
||||
uint32_t tick_start);
|
||||
static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint32_t timeout,
|
||||
uint32_t tick_start);
|
||||
static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint32_t timeout,
|
||||
uint32_t tick_start);
|
||||
|
||||
/* Private function to flush TXDR register */
|
||||
static void i2c_flush_txdr(struct i2c_handle_s *hi2c);
|
||||
|
||||
/* Private function to start, restart or stop a transfer */
|
||||
static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr,
|
||||
uint16_t size, uint32_t i2c_mode,
|
||||
uint32_t request);
|
||||
|
||||
/*
|
||||
* @brief Initialize the I2C device.
|
||||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains
|
||||
* the configuration information for the specified I2C.
|
||||
* @retval 0 if OK, negative value else
|
||||
*/
|
||||
int stm32_i2c_init(struct i2c_handle_s *hi2c)
|
||||
{
|
||||
if (hi2c == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (hi2c->i2c_state == I2C_STATE_RESET) {
|
||||
hi2c->lock = 0;
|
||||
}
|
||||
|
||||
hi2c->i2c_state = I2C_STATE_BUSY;
|
||||
|
||||
/* Disable the selected I2C peripheral */
|
||||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
|
||||
|
||||
/* Configure I2Cx: Frequency range */
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR,
|
||||
hi2c->i2c_init.timing & TIMING_CLEAR_MASK);
|
||||
|
||||
/* Disable Own Address1 before set the Own Address1 configuration */
|
||||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN);
|
||||
|
||||
/* Configure I2Cx: Own Address1 and ack own address1 mode */
|
||||
if (hi2c->i2c_init.addressing_mode == I2C_ADDRESSINGMODE_7BIT) {
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
|
||||
I2C_OAR1_OA1EN | hi2c->i2c_init.own_address1);
|
||||
} else { /* I2C_ADDRESSINGMODE_10BIT */
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
|
||||
I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE |
|
||||
hi2c->i2c_init.own_address1);
|
||||
}
|
||||
|
||||
/* Configure I2Cx: Addressing Master mode */
|
||||
if (hi2c->i2c_init.addressing_mode == I2C_ADDRESSINGMODE_10BIT) {
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the AUTOEND by default, and enable NACK
|
||||
* (should be disable only during Slave process)
|
||||
*/
|
||||
mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
|
||||
I2C_CR2_AUTOEND | I2C_CR2_NACK);
|
||||
|
||||
/* Disable Own Address2 before set the Own Address2 configuration */
|
||||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE);
|
||||
|
||||
/* Configure I2Cx: Dual mode and Own Address2 */
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2,
|
||||
hi2c->i2c_init.dual_address_mode |
|
||||
hi2c->i2c_init.own_address2 |
|
||||
(hi2c->i2c_init.own_address2_masks << 8));
|
||||
|
||||
/* Configure I2Cx: Generalcall and NoStretch mode */
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_CR1,
|
||||
hi2c->i2c_init.general_call_mode |
|
||||
hi2c->i2c_init.no_stretch_mode);
|
||||
|
||||
/* Enable the selected I2C peripheral */
|
||||
mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
|
||||
|
||||
hi2c->i2c_err = I2C_ERROR_NONE;
|
||||
hi2c->i2c_state = I2C_STATE_READY;
|
||||
hi2c->i2c_mode = I2C_MODE_NONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Write an amount of data in blocking mode to a specific memory address
|
||||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains
|
||||
* the configuration information for the specified I2C.
|
||||
* @param dev_addr: Target device address
|
||||
* @param mem_addr: Internal memory address
|
||||
* @param mem_add_size: size of internal memory address
|
||||
* @param p_data: Pointer to data buffer
|
||||
* @param size: Amount of data to be sent
|
||||
* @param timeout: timeout duration
|
||||
* @retval 0 if OK, negative value else
|
||||
*/
|
||||
int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
|
||||
uint16_t mem_addr, uint16_t mem_add_size,
|
||||
uint8_t *p_data, uint16_t size, uint32_t timeout)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
|
||||
if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if ((p_data == NULL) || (size == 0U)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hi2c->lock = 1;
|
||||
|
||||
tickstart = (uint32_t)read_cntpct_el0();
|
||||
|
||||
if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, I2C_TIMEOUT_BUSY,
|
||||
tickstart) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
hi2c->i2c_state = I2C_STATE_BUSY_TX;
|
||||
hi2c->i2c_mode = I2C_MODE_MEM;
|
||||
hi2c->i2c_err = I2C_ERROR_NONE;
|
||||
|
||||
hi2c->p_buff = p_data;
|
||||
hi2c->xfer_count = size;
|
||||
|
||||
/* Send Slave Address and Memory Address */
|
||||
if (i2c_request_memory_write(hi2c, dev_addr, mem_addr, mem_add_size,
|
||||
timeout, tickstart) != 0) {
|
||||
hi2c->lock = 0;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set NBYTES to write and reload
|
||||
* if hi2c->xfer_count > MAX_NBYTE_SIZE
|
||||
*/
|
||||
if (hi2c->xfer_count > MAX_NBYTE_SIZE) {
|
||||
hi2c->xfer_size = MAX_NBYTE_SIZE;
|
||||
i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size,
|
||||
I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
|
||||
} else {
|
||||
hi2c->xfer_size = hi2c->xfer_count;
|
||||
i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size,
|
||||
I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
|
||||
}
|
||||
|
||||
do {
|
||||
if (i2c_wait_txis(hi2c, timeout, tickstart) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *hi2c->p_buff);
|
||||
hi2c->p_buff++;
|
||||
hi2c->xfer_count--;
|
||||
hi2c->xfer_size--;
|
||||
|
||||
if ((hi2c->xfer_count != 0U) && (hi2c->xfer_size == 0U)) {
|
||||
/* Wait until TCR flag is set */
|
||||
if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout,
|
||||
tickstart) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (hi2c->xfer_count > MAX_NBYTE_SIZE) {
|
||||
hi2c->xfer_size = MAX_NBYTE_SIZE;
|
||||
i2c_transfer_config(hi2c, dev_addr,
|
||||
hi2c->xfer_size,
|
||||
I2C_RELOAD_MODE,
|
||||
I2C_NO_STARTSTOP);
|
||||
} else {
|
||||
hi2c->xfer_size = hi2c->xfer_count;
|
||||
i2c_transfer_config(hi2c, dev_addr,
|
||||
hi2c->xfer_size,
|
||||
I2C_AUTOEND_MODE,
|
||||
I2C_NO_STARTSTOP);
|
||||
}
|
||||
}
|
||||
|
||||
} while (hi2c->xfer_count > 0U);
|
||||
|
||||
/*
|
||||
* No need to Check TC flag, with AUTOEND mode the stop
|
||||
* is automatically generated.
|
||||
* Wait until STOPF flag is reset.
|
||||
*/
|
||||
if (i2c_wait_stop(hi2c, timeout, tickstart) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
|
||||
|
||||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
|
||||
|
||||
hi2c->i2c_state = I2C_STATE_READY;
|
||||
hi2c->i2c_mode = I2C_MODE_NONE;
|
||||
|
||||
hi2c->lock = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Read an amount of data in blocking mode from a specific memory
|
||||
* address
|
||||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains
|
||||
* the configuration information for the specified I2C.
|
||||
* @param dev_addr: Target device address
|
||||
* @param mem_addr: Internal memory address
|
||||
* @param mem_add_size: size of internal memory address
|
||||
* @param p_data: Pointer to data buffer
|
||||
* @param size: Amount of data to be sent
|
||||
* @param timeout: timeout duration
|
||||
* @retval 0 if OK, negative value else
|
||||
*/
|
||||
int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
|
||||
uint16_t mem_addr, uint16_t mem_add_size,
|
||||
uint8_t *p_data, uint16_t size, uint32_t timeout)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
|
||||
if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if ((p_data == NULL) || (size == 0U)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hi2c->lock = 1;
|
||||
|
||||
tickstart = (uint32_t)read_cntpct_el0();
|
||||
|
||||
if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, I2C_TIMEOUT_BUSY,
|
||||
tickstart) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
hi2c->i2c_state = I2C_STATE_BUSY_RX;
|
||||
hi2c->i2c_mode = I2C_MODE_MEM;
|
||||
hi2c->i2c_err = I2C_ERROR_NONE;
|
||||
|
||||
hi2c->p_buff = p_data;
|
||||
hi2c->xfer_count = size;
|
||||
|
||||
/* Send Slave Address and Memory Address */
|
||||
if (i2c_request_memory_read(hi2c, dev_addr, mem_addr, mem_add_size,
|
||||
timeout, tickstart) != 0) {
|
||||
hi2c->lock = 0;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send Slave Address.
|
||||
* Set NBYTES to write and reload if hi2c->xfer_count > MAX_NBYTE_SIZE
|
||||
* and generate RESTART.
|
||||
*/
|
||||
if (hi2c->xfer_count > MAX_NBYTE_SIZE) {
|
||||
hi2c->xfer_size = MAX_NBYTE_SIZE;
|
||||
i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size,
|
||||
I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
|
||||
} else {
|
||||
hi2c->xfer_size = hi2c->xfer_count;
|
||||
i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size,
|
||||
I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
|
||||
}
|
||||
|
||||
do {
|
||||
if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, timeout,
|
||||
tickstart) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
*hi2c->p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR);
|
||||
hi2c->p_buff++;
|
||||
hi2c->xfer_size--;
|
||||
hi2c->xfer_count--;
|
||||
|
||||
if ((hi2c->xfer_count != 0U) && (hi2c->xfer_size == 0U)) {
|
||||
if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout,
|
||||
tickstart) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (hi2c->xfer_count > MAX_NBYTE_SIZE) {
|
||||
hi2c->xfer_size = MAX_NBYTE_SIZE;
|
||||
i2c_transfer_config(hi2c, dev_addr,
|
||||
hi2c->xfer_size,
|
||||
I2C_RELOAD_MODE,
|
||||
I2C_NO_STARTSTOP);
|
||||
} else {
|
||||
hi2c->xfer_size = hi2c->xfer_count;
|
||||
i2c_transfer_config(hi2c, dev_addr,
|
||||
hi2c->xfer_size,
|
||||
I2C_AUTOEND_MODE,
|
||||
I2C_NO_STARTSTOP);
|
||||
}
|
||||
}
|
||||
} while (hi2c->xfer_count > 0U);
|
||||
|
||||
/*
|
||||
* No need to Check TC flag, with AUTOEND mode the stop
|
||||
* is automatically generated
|
||||
* Wait until STOPF flag is reset
|
||||
*/
|
||||
if (i2c_wait_stop(hi2c, timeout, tickstart) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
|
||||
|
||||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
|
||||
|
||||
hi2c->i2c_state = I2C_STATE_READY;
|
||||
hi2c->i2c_mode = I2C_MODE_NONE;
|
||||
|
||||
hi2c->lock = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Checks if target device is ready for communication.
|
||||
* @note This function is used with Memory devices
|
||||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains
|
||||
* the configuration information for the specified I2C.
|
||||
* @param dev_addr: Target device address
|
||||
* @param trials: Number of trials
|
||||
* @param timeout: timeout duration
|
||||
* @retval 0 if OK, negative value else
|
||||
*/
|
||||
int stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c,
|
||||
uint16_t dev_addr, uint32_t trials,
|
||||
uint32_t timeout)
|
||||
{
|
||||
uint32_t i2c_trials = 0U;
|
||||
|
||||
if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) !=
|
||||
0U) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
hi2c->lock = 1;
|
||||
|
||||
hi2c->i2c_state = I2C_STATE_BUSY;
|
||||
hi2c->i2c_err = I2C_ERROR_NONE;
|
||||
|
||||
do {
|
||||
uint32_t tickstart;
|
||||
|
||||
/* Generate Start */
|
||||
if (hi2c->i2c_init.addressing_mode == I2C_ADDRESSINGMODE_7BIT) {
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
|
||||
(((uint32_t)dev_addr & I2C_CR2_SADD) |
|
||||
I2C_CR2_START | I2C_CR2_AUTOEND) &
|
||||
~I2C_CR2_RD_WRN);
|
||||
} else {
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
|
||||
(((uint32_t)dev_addr & I2C_CR2_SADD) |
|
||||
I2C_CR2_START | I2C_CR2_ADD10) &
|
||||
~I2C_CR2_RD_WRN);
|
||||
}
|
||||
|
||||
/*
|
||||
* No need to Check TC flag, with AUTOEND mode the stop
|
||||
* is automatically generated
|
||||
* Wait until STOPF flag is set or a NACK flag is set
|
||||
*/
|
||||
tickstart = (uint32_t)read_cntpct_el0();
|
||||
while (((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
|
||||
(I2C_FLAG_STOPF | I2C_FLAG_AF)) == 0U) &&
|
||||
(hi2c->i2c_state != I2C_STATE_TIMEOUT)) {
|
||||
if (timeout != MAX_DELAY) {
|
||||
if ((((uint32_t)read_cntpct_el0() - tickstart) >
|
||||
timeout) || (timeout == 0U)) {
|
||||
hi2c->i2c_state = I2C_STATE_READY;
|
||||
|
||||
hi2c->i2c_err |=
|
||||
I2C_ERROR_TIMEOUT;
|
||||
|
||||
hi2c->lock = 0;
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the NACKF flag has not been set */
|
||||
if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
|
||||
I2C_FLAG_AF) == 0U) {
|
||||
if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout,
|
||||
tickstart) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
|
||||
I2C_FLAG_STOPF);
|
||||
|
||||
hi2c->i2c_state = I2C_STATE_READY;
|
||||
|
||||
hi2c->lock = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout,
|
||||
tickstart) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
|
||||
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
|
||||
|
||||
if (i2c_trials == trials) {
|
||||
mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
|
||||
I2C_CR2_STOP);
|
||||
|
||||
if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout,
|
||||
tickstart) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
|
||||
I2C_FLAG_STOPF);
|
||||
}
|
||||
|
||||
i2c_trials++;
|
||||
} while (i2c_trials < trials);
|
||||
|
||||
hi2c->i2c_state = I2C_STATE_READY;
|
||||
|
||||
hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
|
||||
|
||||
hi2c->lock = 0;
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Master sends target device address followed by internal memory
|
||||
* address for write request.
|
||||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains
|
||||
* the configuration information for the specified I2C.
|
||||
* @param dev_addr: Target device address
|
||||
* @param mem_addr: Internal memory address
|
||||
* @param mem_add_size: size of internal memory address
|
||||
* @param timeout: timeout duration
|
||||
* @param tick_start Tick start value
|
||||
* @retval 0 if OK, negative value else
|
||||
*/
|
||||
static int i2c_request_memory_write(struct i2c_handle_s *hi2c,
|
||||
uint16_t dev_addr, uint16_t mem_addr,
|
||||
uint16_t mem_add_size, uint32_t timeout,
|
||||
uint32_t tick_start)
|
||||
{
|
||||
i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE,
|
||||
I2C_GENERATE_START_WRITE);
|
||||
|
||||
if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
|
||||
/* Send Memory Address */
|
||||
mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
|
||||
(uint8_t)(mem_addr & 0x00FFU));
|
||||
} else {
|
||||
/* Send MSB of Memory Address */
|
||||
mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
|
||||
(uint8_t)((mem_addr & 0xFF00U) >> 8));
|
||||
|
||||
/* Wait until TXIS flag is set */
|
||||
if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Send LSB of Memory Address */
|
||||
mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
|
||||
(uint8_t)(mem_addr & 0x00FFU));
|
||||
}
|
||||
|
||||
if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout, tick_start) !=
|
||||
0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Master sends target device address followed by internal memory
|
||||
* address for read request.
|
||||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains
|
||||
* the configuration information for the specified I2C.
|
||||
* @param dev_addr: Target device address
|
||||
* @param mem_addr: Internal memory address
|
||||
* @param mem_add_size: size of internal memory address
|
||||
* @param timeout: timeout duration
|
||||
* @param tick_start Tick start value
|
||||
* @retval 0 if OK, negative value else
|
||||
*/
|
||||
static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
|
||||
uint16_t mem_addr, uint16_t mem_add_size,
|
||||
uint32_t timeout, uint32_t tick_start)
|
||||
{
|
||||
i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE,
|
||||
I2C_GENERATE_START_WRITE);
|
||||
|
||||
if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
|
||||
/* Send Memory Address */
|
||||
mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
|
||||
(uint8_t)(mem_addr & 0x00FFU));
|
||||
} else {
|
||||
/* Send MSB of Memory Address */
|
||||
mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
|
||||
(uint8_t)((mem_addr & 0xFF00U) >> 8));
|
||||
|
||||
/* Wait until TXIS flag is set */
|
||||
if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Send LSB of Memory Address */
|
||||
mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
|
||||
(uint8_t)(mem_addr & 0x00FFU));
|
||||
}
|
||||
|
||||
if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, timeout, tick_start) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief I2C Tx data register flush process.
|
||||
* @param hi2c: I2C handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void i2c_flush_txdr(struct i2c_handle_s *hi2c)
|
||||
{
|
||||
/*
|
||||
* If a pending TXIS flag is set,
|
||||
* write a dummy data in TXDR to clear it.
|
||||
*/
|
||||
if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) !=
|
||||
0U) {
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0);
|
||||
}
|
||||
|
||||
/* Flush TX register if not empty */
|
||||
if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) ==
|
||||
0U) {
|
||||
mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR,
|
||||
I2C_FLAG_TXE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief This function handles I2C Communication timeout.
|
||||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains
|
||||
* the configuration information for the specified I2C.
|
||||
* @param flag: Specifies the I2C flag to check.
|
||||
* @param awaited_value: The awaited bit value for the flag (0 or 1).
|
||||
* @param timeout: timeout duration
|
||||
* @param tick_start: Tick start value
|
||||
* @retval 0 if OK, negative value else
|
||||
*/
|
||||
static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag,
|
||||
uint8_t awaited_value, uint32_t timeout,
|
||||
uint32_t tick_start)
|
||||
{
|
||||
uint8_t flag_check;
|
||||
|
||||
do {
|
||||
flag_check = ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
|
||||
flag) == flag) ? 1U : 0U;
|
||||
|
||||
if (timeout != MAX_DELAY) {
|
||||
if ((((uint32_t)read_cntpct_el0() - tick_start) >
|
||||
timeout) || (timeout == 0U)) {
|
||||
hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
|
||||
hi2c->i2c_state = I2C_STATE_READY;
|
||||
hi2c->i2c_mode = I2C_MODE_NONE;
|
||||
|
||||
hi2c->lock = 0;
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
} while (flag_check == awaited_value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief This function handles I2C Communication timeout for specific usage
|
||||
* of TXIS flag.
|
||||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains
|
||||
* the configuration information for the specified I2C.
|
||||
* @param timeout: timeout duration
|
||||
* @param tick_start: Tick start value
|
||||
* @retval 0 if OK, negative value else
|
||||
*/
|
||||
static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint32_t timeout,
|
||||
uint32_t tick_start)
|
||||
{
|
||||
while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
|
||||
I2C_FLAG_TXIS) == 0U) {
|
||||
if (i2c_ack_failed(hi2c, timeout, tick_start) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (timeout != MAX_DELAY) {
|
||||
if ((((uint32_t)read_cntpct_el0() - tick_start) >
|
||||
timeout) || (timeout == 0U)) {
|
||||
hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
|
||||
hi2c->i2c_state = I2C_STATE_READY;
|
||||
hi2c->i2c_mode = I2C_MODE_NONE;
|
||||
|
||||
hi2c->lock = 0;
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief This function handles I2C Communication timeout for specific
|
||||
* usage of STOP flag.
|
||||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains
|
||||
* the configuration information for the specified I2C.
|
||||
* @param timeout: timeout duration
|
||||
* @param tick_start: Tick start value
|
||||
* @retval 0 if OK, negative value else
|
||||
*/
|
||||
static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint32_t timeout,
|
||||
uint32_t tick_start)
|
||||
{
|
||||
while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
|
||||
I2C_FLAG_STOPF) == 0U) {
|
||||
if (i2c_ack_failed(hi2c, timeout, tick_start) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if ((((uint32_t)read_cntpct_el0() - tick_start) > timeout) ||
|
||||
(timeout == 0U)) {
|
||||
hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
|
||||
hi2c->i2c_state = I2C_STATE_READY;
|
||||
hi2c->i2c_mode = I2C_MODE_NONE;
|
||||
|
||||
hi2c->lock = 0;
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief This function handles Acknowledge failed detection during
|
||||
* an I2C Communication.
|
||||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains
|
||||
* the configuration information for the specified I2C.
|
||||
* @param timeout: timeout duration
|
||||
* @param tick_start: Tick start value
|
||||
* @retval 0 if OK, negative value else
|
||||
*/
|
||||
static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint32_t timeout,
|
||||
uint32_t tick_start)
|
||||
{
|
||||
if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait until STOP Flag is reset.
|
||||
* AutoEnd should be initiate after AF.
|
||||
*/
|
||||
while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
|
||||
I2C_FLAG_STOPF) == 0U) {
|
||||
if (timeout != MAX_DELAY) {
|
||||
if ((((uint32_t)read_cntpct_el0() - tick_start) >
|
||||
timeout) || (timeout == 0U)) {
|
||||
hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
|
||||
hi2c->i2c_state = I2C_STATE_READY;
|
||||
hi2c->i2c_mode = I2C_MODE_NONE;
|
||||
|
||||
hi2c->lock = 0;
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
|
||||
|
||||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
|
||||
|
||||
i2c_flush_txdr(hi2c);
|
||||
|
||||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
|
||||
|
||||
hi2c->i2c_err |= I2C_ERROR_AF;
|
||||
hi2c->i2c_state = I2C_STATE_READY;
|
||||
hi2c->i2c_mode = I2C_MODE_NONE;
|
||||
|
||||
hi2c->lock = 0;
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Handles I2Cx communication when starting transfer or during transfer
|
||||
* (TC or TCR flag are set).
|
||||
* @param hi2c: I2C handle.
|
||||
* @param dev_addr: Specifies the slave address to be programmed.
|
||||
* @param size: Specifies the number of bytes to be programmed.
|
||||
* This parameter must be a value between 0 and 255.
|
||||
* @param i2c_mode: New state of the I2C START condition generation.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref I2C_RELOAD_MODE: Enable Reload mode .
|
||||
* @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode.
|
||||
* @arg @ref I2C_SOFTEND_MODE: Enable Software end mode.
|
||||
* @param request: New state of the I2C START condition generation.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition.
|
||||
* @arg @ref I2C_GENERATE_STOP: Generate stop condition
|
||||
* (size should be set to 0).
|
||||
* @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request.
|
||||
* @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request.
|
||||
* @retval None
|
||||
*/
|
||||
static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr,
|
||||
uint16_t size, uint32_t i2c_mode,
|
||||
uint32_t request)
|
||||
{
|
||||
uint32_t clr_value, set_value;
|
||||
|
||||
clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD |
|
||||
I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) |
|
||||
(I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET)));
|
||||
|
||||
set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) |
|
||||
(((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) |
|
||||
i2c_mode | request;
|
||||
|
||||
mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Configure I2C Analog noise filter.
|
||||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains
|
||||
* the configuration information for the specified I2Cx peripheral
|
||||
* @param analog_filter: New state of the Analog filter.
|
||||
* @retval 0 if OK, negative value else
|
||||
*/
|
||||
int stm32_i2c_config_analog_filter(struct i2c_handle_s *hi2c,
|
||||
uint32_t analog_filter)
|
||||
{
|
||||
if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
hi2c->lock = 1;
|
||||
|
||||
hi2c->i2c_state = I2C_STATE_BUSY;
|
||||
|
||||
/* Disable the selected I2C peripheral */
|
||||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
|
||||
|
||||
/* Reset I2Cx ANOFF bit */
|
||||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_ANFOFF);
|
||||
|
||||
/* Set analog filter bit*/
|
||||
mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, analog_filter);
|
||||
|
||||
/* Enable the selected I2C peripheral */
|
||||
mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
|
||||
|
||||
hi2c->i2c_state = I2C_STATE_READY;
|
||||
|
||||
hi2c->lock = 0;
|
||||
|
||||
return 0;
|
||||
}
|
346
drivers/st/pmic/stm32mp1_pmic.c
Normal file
346
drivers/st/pmic/stm32mp1_pmic.c
Normal file
@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <debug.h>
|
||||
#include <delay_timer.h>
|
||||
#include <errno.h>
|
||||
#include <libfdt.h>
|
||||
#include <mmio.h>
|
||||
#include <mmio.h>
|
||||
#include <platform_def.h>
|
||||
#include <stdbool.h>
|
||||
#include <stm32_gpio.h>
|
||||
#include <stm32mp1_clk.h>
|
||||
#include <stm32mp1_dt.h>
|
||||
#include <stm32mp1_pmic.h>
|
||||
#include <stpmu1.h>
|
||||
#include <utils_def.h>
|
||||
|
||||
/* I2C Timing hard-coded value, for I2C clock source is HSI at 64MHz */
|
||||
#define I2C_TIMING 0x10D07DB5
|
||||
|
||||
#define I2C_TIMEOUT 0xFFFFF
|
||||
|
||||
#define MASK_RESET_BUCK3 BIT(2)
|
||||
|
||||
#define STPMU1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK(6, 2))
|
||||
#define STPMU1_LDO12356_OUTPUT_SHIFT 2
|
||||
#define STPMU1_LDO3_MODE (uint8_t)(BIT(7))
|
||||
#define STPMU1_LDO3_DDR_SEL 31U
|
||||
#define STPMU1_LDO3_1800000 (9U << STPMU1_LDO12356_OUTPUT_SHIFT)
|
||||
|
||||
#define STPMU1_BUCK_OUTPUT_SHIFT 2
|
||||
#define STPMU1_BUCK3_1V8 (39U << STPMU1_BUCK_OUTPUT_SHIFT)
|
||||
|
||||
#define STPMU1_DEFAULT_START_UP_DELAY_MS 1
|
||||
|
||||
static struct i2c_handle_s i2c_handle;
|
||||
static uint32_t pmic_i2c_addr;
|
||||
|
||||
static int dt_get_pmic_node(void *fdt)
|
||||
{
|
||||
return fdt_node_offset_by_compatible(fdt, -1, "st,stpmu1");
|
||||
}
|
||||
|
||||
bool dt_check_pmic(void)
|
||||
{
|
||||
int node;
|
||||
void *fdt;
|
||||
|
||||
if (fdt_get_address(&fdt) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
node = dt_get_pmic_node(fdt);
|
||||
if (node < 0) {
|
||||
VERBOSE("%s: No PMIC node found in DT\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
return fdt_check_status(node);
|
||||
}
|
||||
|
||||
static int dt_pmic_i2c_config(struct dt_node_info *i2c_info)
|
||||
{
|
||||
int pmic_node, i2c_node;
|
||||
void *fdt;
|
||||
const fdt32_t *cuint;
|
||||
|
||||
if (fdt_get_address(&fdt) == 0) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
pmic_node = dt_get_pmic_node(fdt);
|
||||
if (pmic_node < 0) {
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
cuint = fdt_getprop(fdt, pmic_node, "reg", NULL);
|
||||
if (cuint == NULL) {
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1;
|
||||
if (pmic_i2c_addr > UINT16_MAX) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i2c_node = fdt_parent_offset(fdt, pmic_node);
|
||||
if (i2c_node < 0) {
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
dt_fill_device_info(i2c_info, i2c_node);
|
||||
if (i2c_info->base == 0U) {
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
return dt_set_pinctrl_config(i2c_node);
|
||||
}
|
||||
|
||||
int dt_pmic_enable_boot_on_regulators(void)
|
||||
{
|
||||
int pmic_node, regulators_node, regulator_node;
|
||||
void *fdt;
|
||||
|
||||
if (fdt_get_address(&fdt) == 0) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
pmic_node = dt_get_pmic_node(fdt);
|
||||
if (pmic_node < 0) {
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");
|
||||
|
||||
fdt_for_each_subnode(regulator_node, fdt, regulators_node) {
|
||||
const fdt32_t *cuint;
|
||||
const char *node_name;
|
||||
uint16_t voltage;
|
||||
|
||||
if (fdt_getprop(fdt, regulator_node, "regulator-boot-on",
|
||||
NULL) == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cuint = fdt_getprop(fdt, regulator_node,
|
||||
"regulator-min-microvolt", NULL);
|
||||
if (cuint == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* DT uses microvolts, whereas driver awaits millivolts */
|
||||
voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
|
||||
node_name = fdt_get_name(fdt, regulator_node, NULL);
|
||||
|
||||
if (stpmu1_is_regulator_enabled(node_name) == 0U) {
|
||||
int status;
|
||||
|
||||
status = stpmu1_regulator_voltage_set(node_name,
|
||||
voltage);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = stpmu1_regulator_enable(node_name);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void initialize_pmic_i2c(void)
|
||||
{
|
||||
int ret;
|
||||
struct dt_node_info i2c_info;
|
||||
|
||||
if (dt_pmic_i2c_config(&i2c_info) != 0) {
|
||||
ERROR("I2C configuration failed\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
if (stm32mp1_clk_enable((uint32_t)i2c_info.clock) < 0) {
|
||||
ERROR("I2C clock enable failed\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
/* Initialize PMIC I2C */
|
||||
i2c_handle.i2c_base_addr = i2c_info.base;
|
||||
i2c_handle.i2c_init.timing = I2C_TIMING;
|
||||
i2c_handle.i2c_init.own_address1 = pmic_i2c_addr;
|
||||
i2c_handle.i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT;
|
||||
i2c_handle.i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE;
|
||||
i2c_handle.i2c_init.own_address2 = 0;
|
||||
i2c_handle.i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK;
|
||||
i2c_handle.i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE;
|
||||
i2c_handle.i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE;
|
||||
|
||||
ret = stm32_i2c_init(&i2c_handle);
|
||||
if (ret != 0) {
|
||||
ERROR("Cannot initialize I2C %x (%d)\n",
|
||||
i2c_handle.i2c_base_addr, ret);
|
||||
panic();
|
||||
}
|
||||
|
||||
ret = stm32_i2c_config_analog_filter(&i2c_handle,
|
||||
I2C_ANALOGFILTER_ENABLE);
|
||||
if (ret != 0) {
|
||||
ERROR("Cannot initialize I2C analog filter (%d)\n", ret);
|
||||
panic();
|
||||
}
|
||||
|
||||
ret = stm32_i2c_is_device_ready(&i2c_handle, (uint16_t)pmic_i2c_addr, 1,
|
||||
I2C_TIMEOUT);
|
||||
if (ret != 0) {
|
||||
ERROR("I2C device not ready (%d)\n", ret);
|
||||
panic();
|
||||
}
|
||||
|
||||
stpmu1_bind_i2c(&i2c_handle, (uint16_t)pmic_i2c_addr);
|
||||
}
|
||||
|
||||
void initialize_pmic(void)
|
||||
{
|
||||
int status;
|
||||
uint8_t read_val;
|
||||
|
||||
initialize_pmic_i2c();
|
||||
|
||||
status = stpmu1_register_read(VERSION_STATUS_REG, &read_val);
|
||||
if (status != 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
INFO("PMIC version = 0x%x\n", read_val);
|
||||
|
||||
/* Keep VDD on during the reset cycle */
|
||||
status = stpmu1_register_update(MASK_RESET_BUCK_REG,
|
||||
MASK_RESET_BUCK3,
|
||||
MASK_RESET_BUCK3);
|
||||
if (status != 0) {
|
||||
panic();
|
||||
}
|
||||
}
|
||||
|
||||
int pmic_ddr_power_init(enum ddr_type ddr_type)
|
||||
{
|
||||
bool buck3_at_1v8 = false;
|
||||
uint8_t read_val;
|
||||
int status;
|
||||
|
||||
switch (ddr_type) {
|
||||
case STM32MP_DDR3:
|
||||
/* Set LDO3 to sync mode */
|
||||
status = stpmu1_register_read(LDO3_CONTROL_REG, &read_val);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
read_val &= ~STPMU1_LDO3_MODE;
|
||||
read_val &= ~STPMU1_LDO12356_OUTPUT_MASK;
|
||||
read_val |= STPMU1_LDO3_DDR_SEL << STPMU1_LDO12356_OUTPUT_SHIFT;
|
||||
|
||||
status = stpmu1_register_write(LDO3_CONTROL_REG, read_val);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = stpmu1_regulator_voltage_set("buck2", 1350);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = stpmu1_regulator_enable("buck2");
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
status = stpmu1_regulator_enable("vref_ddr");
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
status = stpmu1_regulator_enable("ldo3");
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
|
||||
break;
|
||||
|
||||
case STM32MP_LPDDR2:
|
||||
/*
|
||||
* Set LDO3 to 1.8V
|
||||
* Set LDO3 to bypass mode if BUCK3 = 1.8V
|
||||
* Set LDO3 to normal mode if BUCK3 != 1.8V
|
||||
*/
|
||||
status = stpmu1_register_read(BUCK3_CONTROL_REG, &read_val);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((read_val & STPMU1_BUCK3_1V8) == STPMU1_BUCK3_1V8) {
|
||||
buck3_at_1v8 = true;
|
||||
}
|
||||
|
||||
status = stpmu1_register_read(LDO3_CONTROL_REG, &read_val);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
read_val &= ~STPMU1_LDO3_MODE;
|
||||
read_val &= ~STPMU1_LDO12356_OUTPUT_MASK;
|
||||
read_val |= STPMU1_LDO3_1800000;
|
||||
if (buck3_at_1v8) {
|
||||
read_val |= STPMU1_LDO3_MODE;
|
||||
}
|
||||
|
||||
status = stpmu1_register_write(LDO3_CONTROL_REG, read_val);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = stpmu1_regulator_voltage_set("buck2", 1200);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = stpmu1_regulator_enable("ldo3");
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
status = stpmu1_regulator_enable("buck2");
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
|
||||
|
||||
status = stpmu1_regulator_enable("vref_ddr");
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
600
drivers/st/pmic/stpmu1.c
Normal file
600
drivers/st/pmic/stpmu1.c
Normal file
@ -0,0 +1,600 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <debug.h>
|
||||
#include <platform.h>
|
||||
#include <stpmu1.h>
|
||||
#include <string.h>
|
||||
|
||||
struct regul_struct {
|
||||
const char *dt_node_name;
|
||||
const uint16_t *voltage_table;
|
||||
uint8_t voltage_table_size;
|
||||
uint8_t control_reg;
|
||||
uint8_t low_power_reg;
|
||||
};
|
||||
|
||||
static struct i2c_handle_s *stpmu_i2c_handle;
|
||||
static uint16_t stpmu_i2c_addr;
|
||||
|
||||
/* Voltage tables in mV */
|
||||
static const 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,
|
||||
};
|
||||
|
||||
static const uint16_t buck2_voltage_table[] = {
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1050,
|
||||
1050,
|
||||
1100,
|
||||
1100,
|
||||
1150,
|
||||
1150,
|
||||
1200,
|
||||
1200,
|
||||
1250,
|
||||
1250,
|
||||
1300,
|
||||
1300,
|
||||
1350,
|
||||
1350,
|
||||
1400,
|
||||
1400,
|
||||
1450,
|
||||
1450,
|
||||
1500,
|
||||
};
|
||||
|
||||
static const uint16_t buck3_voltage_table[] = {
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1000,
|
||||
1100,
|
||||
1100,
|
||||
1100,
|
||||
1100,
|
||||
1200,
|
||||
1200,
|
||||
1200,
|
||||
1200,
|
||||
1300,
|
||||
1300,
|
||||
1300,
|
||||
1300,
|
||||
1400,
|
||||
1400,
|
||||
1400,
|
||||
1400,
|
||||
1500,
|
||||
1600,
|
||||
1700,
|
||||
1800,
|
||||
1900,
|
||||
2000,
|
||||
2100,
|
||||
2200,
|
||||
2300,
|
||||
2400,
|
||||
2500,
|
||||
2600,
|
||||
2700,
|
||||
2800,
|
||||
2900,
|
||||
3000,
|
||||
3100,
|
||||
3200,
|
||||
3300,
|
||||
3400,
|
||||
};
|
||||
|
||||
static const 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,
|
||||
1400,
|
||||
1400,
|
||||
1450,
|
||||
1450,
|
||||
1500,
|
||||
1600,
|
||||
1700,
|
||||
1800,
|
||||
1900,
|
||||
2000,
|
||||
2100,
|
||||
2200,
|
||||
2300,
|
||||
2400,
|
||||
2500,
|
||||
2600,
|
||||
2700,
|
||||
2800,
|
||||
2900,
|
||||
3000,
|
||||
3100,
|
||||
3200,
|
||||
3300,
|
||||
3400,
|
||||
3500,
|
||||
3600,
|
||||
3700,
|
||||
3800,
|
||||
3900,
|
||||
};
|
||||
|
||||
static const uint16_t ldo1_voltage_table[] = {
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1800,
|
||||
1900,
|
||||
2000,
|
||||
2100,
|
||||
2200,
|
||||
2300,
|
||||
2400,
|
||||
2500,
|
||||
2600,
|
||||
2700,
|
||||
2800,
|
||||
2900,
|
||||
3000,
|
||||
3100,
|
||||
3200,
|
||||
3300,
|
||||
};
|
||||
|
||||
static const uint16_t ldo2_voltage_table[] = {
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1800,
|
||||
1900,
|
||||
2000,
|
||||
2100,
|
||||
2200,
|
||||
2300,
|
||||
2400,
|
||||
2500,
|
||||
2600,
|
||||
2700,
|
||||
2800,
|
||||
2900,
|
||||
3000,
|
||||
3100,
|
||||
3200,
|
||||
3300,
|
||||
};
|
||||
|
||||
static const uint16_t ldo3_voltage_table[] = {
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1800,
|
||||
1900,
|
||||
2000,
|
||||
2100,
|
||||
2200,
|
||||
2300,
|
||||
2400,
|
||||
2500,
|
||||
2600,
|
||||
2700,
|
||||
2800,
|
||||
2900,
|
||||
3000,
|
||||
3100,
|
||||
3200,
|
||||
3300,
|
||||
3300,
|
||||
3300,
|
||||
3300,
|
||||
3300,
|
||||
3300,
|
||||
3300,
|
||||
0xFFFF, /* VREFDDR */
|
||||
};
|
||||
|
||||
static const uint16_t ldo5_voltage_table[] = {
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1700,
|
||||
1800,
|
||||
1900,
|
||||
2000,
|
||||
2100,
|
||||
2200,
|
||||
2300,
|
||||
2400,
|
||||
2500,
|
||||
2600,
|
||||
2700,
|
||||
2800,
|
||||
2900,
|
||||
3000,
|
||||
3100,
|
||||
3200,
|
||||
3300,
|
||||
3400,
|
||||
3500,
|
||||
3600,
|
||||
3700,
|
||||
3800,
|
||||
3900,
|
||||
};
|
||||
|
||||
static const uint16_t ldo6_voltage_table[] = {
|
||||
900,
|
||||
1000,
|
||||
1100,
|
||||
1200,
|
||||
1300,
|
||||
1400,
|
||||
1500,
|
||||
1600,
|
||||
1700,
|
||||
1800,
|
||||
1900,
|
||||
2000,
|
||||
2100,
|
||||
2200,
|
||||
2300,
|
||||
2400,
|
||||
2500,
|
||||
2600,
|
||||
2700,
|
||||
2800,
|
||||
2900,
|
||||
3000,
|
||||
3100,
|
||||
3200,
|
||||
3300,
|
||||
};
|
||||
|
||||
static const uint16_t ldo4_voltage_table[] = {
|
||||
3300,
|
||||
};
|
||||
|
||||
static const uint16_t vref_ddr_voltage_table[] = {
|
||||
3300,
|
||||
};
|
||||
|
||||
/* Table of Regulators in PMIC SoC */
|
||||
static const struct regul_struct regulators_table[] = {
|
||||
{
|
||||
.dt_node_name = "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,
|
||||
},
|
||||
{
|
||||
.dt_node_name = "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,
|
||||
},
|
||||
{
|
||||
.dt_node_name = "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,
|
||||
},
|
||||
{
|
||||
.dt_node_name = "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,
|
||||
},
|
||||
{
|
||||
.dt_node_name = "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,
|
||||
},
|
||||
{
|
||||
.dt_node_name = "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,
|
||||
},
|
||||
{
|
||||
.dt_node_name = "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,
|
||||
},
|
||||
{
|
||||
.dt_node_name = "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,
|
||||
},
|
||||
{
|
||||
.dt_node_name = "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,
|
||||
},
|
||||
{
|
||||
.dt_node_name = "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,
|
||||
},
|
||||
{
|
||||
.dt_node_name = "vref_ddr",
|
||||
.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,
|
||||
},
|
||||
};
|
||||
|
||||
#define MAX_REGUL ARRAY_SIZE(regulators_table)
|
||||
|
||||
static const struct regul_struct *stpmu1_get_regulator_data(const char *name)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0 ; i < MAX_REGUL ; i++) {
|
||||
if (strncmp(name, regulators_table[i].dt_node_name,
|
||||
strlen(regulators_table[i].dt_node_name)) == 0) {
|
||||
return ®ulators_table[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Regulator not found */
|
||||
panic();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint8_t stpmu1_voltage_find_index(const char *name,
|
||||
uint16_t millivolts)
|
||||
{
|
||||
const struct regul_struct *regul = stpmu1_get_regulator_data(name);
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0 ; i < regul->voltage_table_size ; i++) {
|
||||
if (regul->voltage_table[i] == millivolts) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Voltage not found */
|
||||
panic();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stpmu1_switch_off(void)
|
||||
{
|
||||
return stpmu1_register_update(MAIN_CONTROL_REG, 1,
|
||||
SOFTWARE_SWITCH_OFF_ENABLED);
|
||||
}
|
||||
|
||||
int stpmu1_regulator_enable(const char *name)
|
||||
{
|
||||
const struct regul_struct *regul = stpmu1_get_regulator_data(name);
|
||||
|
||||
return stpmu1_register_update(regul->control_reg, BIT(0), BIT(0));
|
||||
}
|
||||
|
||||
int stpmu1_regulator_disable(const char *name)
|
||||
{
|
||||
const struct regul_struct *regul = stpmu1_get_regulator_data(name);
|
||||
|
||||
return stpmu1_register_update(regul->control_reg, 0, BIT(0));
|
||||
}
|
||||
|
||||
uint8_t stpmu1_is_regulator_enabled(const char *name)
|
||||
{
|
||||
uint8_t val;
|
||||
const struct regul_struct *regul = stpmu1_get_regulator_data(name);
|
||||
|
||||
if (stpmu1_register_read(regul->control_reg, &val) != 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
return (val & 0x1U);
|
||||
}
|
||||
|
||||
int stpmu1_regulator_voltage_set(const char *name, uint16_t millivolts)
|
||||
{
|
||||
uint8_t voltage_index = stpmu1_voltage_find_index(name, millivolts);
|
||||
const struct regul_struct *regul = stpmu1_get_regulator_data(name);
|
||||
|
||||
return stpmu1_register_update(regul->control_reg, voltage_index << 2,
|
||||
0xFC);
|
||||
}
|
||||
|
||||
int stpmu1_register_read(uint8_t register_id, uint8_t *value)
|
||||
{
|
||||
return stm32_i2c_mem_read(stpmu_i2c_handle, stpmu_i2c_addr,
|
||||
(uint16_t)register_id, I2C_MEMADD_SIZE_8BIT,
|
||||
value, 1, 100000);
|
||||
}
|
||||
|
||||
int stpmu1_register_write(uint8_t register_id, uint8_t value)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = stm32_i2c_mem_write(stpmu_i2c_handle, stpmu_i2c_addr,
|
||||
(uint16_t)register_id,
|
||||
I2C_MEMADD_SIZE_8BIT, &value, 1, 100000);
|
||||
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((register_id != WATCHDOG_CONTROL_REG) && (register_id <= 0x40U)) {
|
||||
uint8_t readval;
|
||||
|
||||
status = stpmu1_register_read(register_id, &readval);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (readval != value) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stpmu1_register_update(uint8_t register_id, uint8_t value, uint8_t mask)
|
||||
{
|
||||
int status;
|
||||
uint8_t val;
|
||||
|
||||
status = stpmu1_register_read(register_id, &val);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Clear bits to update */
|
||||
val &= ~mask;
|
||||
|
||||
/* Update appropriate bits*/
|
||||
val |= (value & mask);
|
||||
|
||||
/* Send new value on I2C Bus */
|
||||
return stpmu1_register_write(register_id, val);
|
||||
}
|
||||
|
||||
void stpmu1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr)
|
||||
{
|
||||
stpmu_i2c_handle = i2c_handle;
|
||||
stpmu_i2c_addr = i2c_addr;
|
||||
}
|
300
include/drivers/st/stm32_i2c.h
Normal file
300
include/drivers/st/stm32_i2c.h
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __STM32MP1_I2C_H
|
||||
#define __STM32MP1_I2C_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <utils_def.h>
|
||||
|
||||
/* Bit definition for I2C_CR1 register */
|
||||
#define I2C_CR1_PE BIT(0)
|
||||
#define I2C_CR1_TXIE BIT(1)
|
||||
#define I2C_CR1_RXIE BIT(2)
|
||||
#define I2C_CR1_ADDRIE BIT(3)
|
||||
#define I2C_CR1_NACKIE BIT(4)
|
||||
#define I2C_CR1_STOPIE BIT(5)
|
||||
#define I2C_CR1_TCIE BIT(6)
|
||||
#define I2C_CR1_ERRIE BIT(7)
|
||||
#define I2C_CR1_DNF GENMASK(11, 8)
|
||||
#define I2C_CR1_ANFOFF BIT(12)
|
||||
#define I2C_CR1_SWRST BIT(13)
|
||||
#define I2C_CR1_TXDMAEN BIT(14)
|
||||
#define I2C_CR1_RXDMAEN BIT(15)
|
||||
#define I2C_CR1_SBC BIT(16)
|
||||
#define I2C_CR1_NOSTRETCH BIT(17)
|
||||
#define I2C_CR1_WUPEN BIT(18)
|
||||
#define I2C_CR1_GCEN BIT(19)
|
||||
#define I2C_CR1_SMBHEN BIT(22)
|
||||
#define I2C_CR1_SMBDEN BIT(21)
|
||||
#define I2C_CR1_ALERTEN BIT(22)
|
||||
#define I2C_CR1_PECEN BIT(23)
|
||||
|
||||
/* Bit definition for I2C_CR2 register */
|
||||
#define I2C_CR2_SADD GENMASK(9, 0)
|
||||
#define I2C_CR2_RD_WRN BIT(10)
|
||||
#define I2C_CR2_RD_WRN_OFFSET 10U
|
||||
#define I2C_CR2_ADD10 BIT(11)
|
||||
#define I2C_CR2_HEAD10R BIT(12)
|
||||
#define I2C_CR2_START BIT(13)
|
||||
#define I2C_CR2_STOP BIT(14)
|
||||
#define I2C_CR2_NACK BIT(15)
|
||||
#define I2C_CR2_NBYTES GENMASK(23, 16)
|
||||
#define I2C_CR2_NBYTES_OFFSET 16U
|
||||
#define I2C_CR2_RELOAD BIT(24)
|
||||
#define I2C_CR2_AUTOEND BIT(25)
|
||||
#define I2C_CR2_PECBYTE BIT(26)
|
||||
|
||||
/* Bit definition for I2C_OAR1 register */
|
||||
#define I2C_OAR1_OA1 GENMASK(9, 0)
|
||||
#define I2C_OAR1_OA1MODE BIT(10)
|
||||
#define I2C_OAR1_OA1EN BIT(15)
|
||||
|
||||
/* Bit definition for I2C_OAR2 register */
|
||||
#define I2C_OAR2_OA2 GENMASK(7, 1)
|
||||
#define I2C_OAR2_OA2MSK GENMASK(10, 8)
|
||||
#define I2C_OAR2_OA2NOMASK 0
|
||||
#define I2C_OAR2_OA2MASK01 BIT(8)
|
||||
#define I2C_OAR2_OA2MASK02 BIT(9)
|
||||
#define I2C_OAR2_OA2MASK03 GENMASK(9, 8)
|
||||
#define I2C_OAR2_OA2MASK04 BIT(10)
|
||||
#define I2C_OAR2_OA2MASK05 (BIT(8) | BIT(10))
|
||||
#define I2C_OAR2_OA2MASK06 (BIT(9) | BIT(10))
|
||||
#define I2C_OAR2_OA2MASK07 GENMASK(10, 8)
|
||||
#define I2C_OAR2_OA2EN BIT(15)
|
||||
|
||||
/* Bit definition for I2C_TIMINGR register */
|
||||
#define I2C_TIMINGR_SCLL GENMASK(7, 0)
|
||||
#define I2C_TIMINGR_SCLH GENMASK(15, 8)
|
||||
#define I2C_TIMINGR_SDADEL GENMASK(19, 16)
|
||||
#define I2C_TIMINGR_SCLDEL GENMASK(23, 20)
|
||||
#define I2C_TIMINGR_PRESC GENMASK(31, 28)
|
||||
|
||||
/* Bit definition for I2C_TIMEOUTR register */
|
||||
#define I2C_TIMEOUTR_TIMEOUTA GENMASK(11, 0)
|
||||
#define I2C_TIMEOUTR_TIDLE BIT(12)
|
||||
#define I2C_TIMEOUTR_TIMOUTEN BIT(15)
|
||||
#define I2C_TIMEOUTR_TIMEOUTB GENMASK(27, 16)
|
||||
#define I2C_TIMEOUTR_TEXTEN BIT(31)
|
||||
|
||||
/* Bit definition for I2C_ISR register */
|
||||
#define I2C_ISR_TXE BIT(0)
|
||||
#define I2C_ISR_TXIS BIT(1)
|
||||
#define I2C_ISR_RXNE BIT(2)
|
||||
#define I2C_ISR_ADDR BIT(3)
|
||||
#define I2C_ISR_NACKF BIT(4)
|
||||
#define I2C_ISR_STOPF BIT(5)
|
||||
#define I2C_ISR_TC BIT(6)
|
||||
#define I2C_ISR_TCR BIT(7)
|
||||
#define I2C_ISR_BERR BIT(8)
|
||||
#define I2C_ISR_ARLO BIT(9)
|
||||
#define I2C_ISR_OVR BIT(10)
|
||||
#define I2C_ISR_PECERR BIT(11)
|
||||
#define I2C_ISR_TIMEOUT BIT(12)
|
||||
#define I2C_ISR_ALERT BIT(13)
|
||||
#define I2C_ISR_BUSY BIT(15)
|
||||
#define I2C_ISR_DIR BIT(16)
|
||||
#define I2C_ISR_ADDCODE GENMASK(23, 17)
|
||||
|
||||
/* Bit definition for I2C_ICR register */
|
||||
#define I2C_ICR_ADDRCF BIT(3)
|
||||
#define I2C_ICR_NACKCF BIT(4)
|
||||
#define I2C_ICR_STOPCF BIT(5)
|
||||
#define I2C_ICR_BERRCF BIT(8)
|
||||
#define I2C_ICR_ARLOCF BIT(9)
|
||||
#define I2C_ICR_OVRCF BIT(10)
|
||||
#define I2C_ICR_PECCF BIT(11)
|
||||
#define I2C_ICR_TIMOUTCF BIT(12)
|
||||
#define I2C_ICR_ALERTCF BIT(13)
|
||||
|
||||
struct stm32_i2c_init_s {
|
||||
uint32_t timing; /* Specifies the I2C_TIMINGR_register value
|
||||
* This parameter is calculated by referring
|
||||
* to I2C initialization section in Reference
|
||||
* manual.
|
||||
*/
|
||||
|
||||
uint32_t own_address1; /* Specifies the first device own address.
|
||||
* This parameter can be a 7-bit or 10-bit
|
||||
* address.
|
||||
*/
|
||||
|
||||
uint32_t addressing_mode; /* Specifies if 7-bit or 10-bit addressing
|
||||
* mode is selected.
|
||||
* This parameter can be a value of @ref
|
||||
* I2C_ADDRESSING_MODE.
|
||||
*/
|
||||
|
||||
uint32_t dual_address_mode; /* Specifies if dual addressing mode is
|
||||
* selected.
|
||||
* This parameter can be a value of @ref
|
||||
* I2C_DUAL_ADDRESSING_MODE.
|
||||
*/
|
||||
|
||||
uint32_t own_address2; /* Specifies the second device own address
|
||||
* if dual addressing mode is selected.
|
||||
* This parameter can be a 7-bit address.
|
||||
*/
|
||||
|
||||
uint32_t own_address2_masks; /* Specifies the acknowledge mask address
|
||||
* second device own address if dual
|
||||
* addressing mode is selected.
|
||||
* This parameter can be a value of @ref
|
||||
* I2C_OWN_ADDRESS2_MASKS.
|
||||
*/
|
||||
|
||||
uint32_t general_call_mode; /* Specifies if general call mode is
|
||||
* selected.
|
||||
* This parameter can be a value of @ref
|
||||
* I2C_GENERAL_CALL_ADDRESSING_MODE.
|
||||
*/
|
||||
|
||||
uint32_t no_stretch_mode; /* Specifies if nostretch mode is
|
||||
* selected.
|
||||
* This parameter can be a value of @ref
|
||||
* I2C_NOSTRETCH_MODE.
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
enum i2c_state_e {
|
||||
I2C_STATE_RESET = 0x00U, /* Peripheral is not yet
|
||||
* initialized.
|
||||
*/
|
||||
I2C_STATE_READY = 0x20U, /* Peripheral Initialized
|
||||
* and ready for use.
|
||||
*/
|
||||
I2C_STATE_BUSY = 0x24U, /* An internal process is
|
||||
* ongoing.
|
||||
*/
|
||||
I2C_STATE_BUSY_TX = 0x21U, /* Data Transmission process
|
||||
* is ongoing.
|
||||
*/
|
||||
I2C_STATE_BUSY_RX = 0x22U, /* Data Reception process
|
||||
* is ongoing.
|
||||
*/
|
||||
I2C_STATE_LISTEN = 0x28U, /* Address Listen Mode is
|
||||
* ongoing.
|
||||
*/
|
||||
I2C_STATE_BUSY_TX_LISTEN = 0x29U, /* Address Listen Mode
|
||||
* and Data Transmission
|
||||
* process is ongoing.
|
||||
*/
|
||||
I2C_STATE_BUSY_RX_LISTEN = 0x2AU, /* Address Listen Mode
|
||||
* and Data Reception
|
||||
* process is ongoing.
|
||||
*/
|
||||
I2C_STATE_ABORT = 0x60U, /* Abort user request ongoing. */
|
||||
I2C_STATE_TIMEOUT = 0xA0U, /* Timeout state. */
|
||||
I2C_STATE_ERROR = 0xE0U /* Error. */
|
||||
|
||||
};
|
||||
|
||||
enum i2c_mode_e {
|
||||
I2C_MODE_NONE = 0x00U, /* No I2C communication on going. */
|
||||
I2C_MODE_MASTER = 0x10U, /* I2C communication is in Master Mode. */
|
||||
I2C_MODE_SLAVE = 0x20U, /* I2C communication is in Slave Mode. */
|
||||
I2C_MODE_MEM = 0x40U /* I2C communication is in Memory Mode. */
|
||||
|
||||
};
|
||||
|
||||
#define I2C_ERROR_NONE 0x00000000U /* No error */
|
||||
#define I2C_ERROR_BERR 0x00000001U /* BERR error */
|
||||
#define I2C_ERROR_ARLO 0x00000002U /* ARLO error */
|
||||
#define I2C_ERROR_AF 0x00000004U /* ACKF error */
|
||||
#define I2C_ERROR_OVR 0x00000008U /* OVR error */
|
||||
#define I2C_ERROR_DMA 0x00000010U /* DMA transfer error */
|
||||
#define I2C_ERROR_TIMEOUT 0x00000020U /* Timeout error */
|
||||
#define I2C_ERROR_SIZE 0x00000040U /* Size Management error */
|
||||
|
||||
struct i2c_handle_s {
|
||||
uint32_t i2c_base_addr; /* Registers base address */
|
||||
|
||||
struct stm32_i2c_init_s i2c_init; /* Communication parameters */
|
||||
|
||||
uint8_t *p_buff; /* Pointer to transfer buffer */
|
||||
|
||||
uint16_t xfer_size; /* Transfer size */
|
||||
|
||||
uint16_t xfer_count; /* Transfer counter */
|
||||
|
||||
uint32_t prev_state; /* Communication previous
|
||||
* state
|
||||
*/
|
||||
|
||||
uint8_t lock; /* Locking object */
|
||||
|
||||
enum i2c_state_e i2c_state; /* Communication state */
|
||||
|
||||
enum i2c_mode_e i2c_mode; /* Communication mode */
|
||||
|
||||
uint32_t i2c_err; /* Error code */
|
||||
};
|
||||
|
||||
#define I2C_ADDRESSINGMODE_7BIT 0x00000001U
|
||||
#define I2C_ADDRESSINGMODE_10BIT 0x00000002U
|
||||
|
||||
#define I2C_DUALADDRESS_DISABLE 0x00000000U
|
||||
#define I2C_DUALADDRESS_ENABLE I2C_OAR2_OA2EN
|
||||
|
||||
#define I2C_GENERALCALL_DISABLE 0x00000000U
|
||||
#define I2C_GENERALCALL_ENABLE I2C_CR1_GCEN
|
||||
|
||||
#define I2C_NOSTRETCH_DISABLE 0x00000000U
|
||||
#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH
|
||||
|
||||
#define I2C_MEMADD_SIZE_8BIT 0x00000001U
|
||||
#define I2C_MEMADD_SIZE_16BIT 0x00000002U
|
||||
|
||||
#define I2C_RELOAD_MODE I2C_CR2_RELOAD
|
||||
#define I2C_AUTOEND_MODE I2C_CR2_AUTOEND
|
||||
#define I2C_SOFTEND_MODE 0x00000000U
|
||||
|
||||
#define I2C_NO_STARTSTOP 0x00000000U
|
||||
#define I2C_GENERATE_STOP (BIT(31) | I2C_CR2_STOP)
|
||||
#define I2C_GENERATE_START_READ (BIT(31) | I2C_CR2_START | \
|
||||
I2C_CR2_RD_WRN)
|
||||
#define I2C_GENERATE_START_WRITE (BIT(31) | I2C_CR2_START)
|
||||
|
||||
#define I2C_FLAG_TXE I2C_ISR_TXE
|
||||
#define I2C_FLAG_TXIS I2C_ISR_TXIS
|
||||
#define I2C_FLAG_RXNE I2C_ISR_RXNE
|
||||
#define I2C_FLAG_ADDR I2C_ISR_ADDR
|
||||
#define I2C_FLAG_AF I2C_ISR_NACKF
|
||||
#define I2C_FLAG_STOPF I2C_ISR_STOPF
|
||||
#define I2C_FLAG_TC I2C_ISR_TC
|
||||
#define I2C_FLAG_TCR I2C_ISR_TCR
|
||||
#define I2C_FLAG_BERR I2C_ISR_BERR
|
||||
#define I2C_FLAG_ARLO I2C_ISR_ARLO
|
||||
#define I2C_FLAG_OVR I2C_ISR_OVR
|
||||
#define I2C_FLAG_PECERR I2C_ISR_PECERR
|
||||
#define I2C_FLAG_TIMEOUT I2C_ISR_TIMEOUT
|
||||
#define I2C_FLAG_ALERT I2C_ISR_ALERT
|
||||
#define I2C_FLAG_BUSY I2C_ISR_BUSY
|
||||
#define I2C_FLAG_DIR I2C_ISR_DIR
|
||||
|
||||
#define I2C_RESET_CR2 (I2C_CR2_SADD | I2C_CR2_HEAD10R | \
|
||||
I2C_CR2_NBYTES | I2C_CR2_RELOAD | \
|
||||
I2C_CR2_RD_WRN)
|
||||
|
||||
#define I2C_ANALOGFILTER_ENABLE ((uint32_t)0x00000000U)
|
||||
#define I2C_ANALOGFILTER_DISABLE I2C_CR1_ANFOFF
|
||||
|
||||
int stm32_i2c_init(struct i2c_handle_s *hi2c);
|
||||
|
||||
int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
|
||||
uint16_t mem_addr, uint16_t mem_add_size,
|
||||
uint8_t *p_data, uint16_t size, uint32_t timeout);
|
||||
int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
|
||||
uint16_t mem_addr, uint16_t mem_add_size,
|
||||
uint8_t *p_data, uint16_t size, uint32_t timeout);
|
||||
int stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint16_t dev_addr,
|
||||
uint32_t trials, uint32_t timeout);
|
||||
|
||||
int stm32_i2c_config_analog_filter(struct i2c_handle_s *hi2c,
|
||||
uint32_t analog_filter);
|
||||
|
||||
#endif /* __STM32MP1_I2C_H */
|
18
include/drivers/st/stm32mp1_pmic.h
Normal file
18
include/drivers/st/stm32mp1_pmic.h
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __STM32MP1_PMIC_H__
|
||||
#define __STM32MP1_PMIC_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool dt_check_pmic(void);
|
||||
int dt_pmic_enable_boot_on_regulators(void);
|
||||
void initialize_pmic_i2c(void);
|
||||
void initialize_pmic(void);
|
||||
int pmic_ddr_power_init(enum ddr_type ddr_type);
|
||||
|
||||
#endif /* __STM32MP1_PMIC_H__ */
|
141
include/drivers/st/stpmu1.h
Normal file
141
include/drivers/st/stpmu1.h
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __STPMU1_H__
|
||||
#define __STPMU1_H__
|
||||
|
||||
#include <stm32_i2c.h>
|
||||
#include <utils_def.h>
|
||||
|
||||
#define TURN_ON_REG 0x1U
|
||||
#define TURN_OFF_REG 0x2U
|
||||
#define ICC_LDO_TURN_OFF_REG 0x3U
|
||||
#define ICC_BUCK_TURN_OFF_REG 0x4U
|
||||
#define RESET_STATUS_REG 0x5U
|
||||
#define VERSION_STATUS_REG 0x6U
|
||||
#define MAIN_CONTROL_REG 0x10U
|
||||
#define PADS_PULL_REG 0x11U
|
||||
#define BUCK_PULL_DOWN_REG 0x12U
|
||||
#define LDO14_PULL_DOWN_REG 0x13U
|
||||
#define LDO56_PULL_DOWN_REG 0x14U
|
||||
#define VIN_CONTROL_REG 0x15U
|
||||
#define PONKEY_TIMER_REG 0x16U
|
||||
#define MASK_RANK_BUCK_REG 0x17U
|
||||
#define MASK_RESET_BUCK_REG 0x18U
|
||||
#define MASK_RANK_LDO_REG 0x19U
|
||||
#define MASK_RESET_LDO_REG 0x1AU
|
||||
#define WATCHDOG_CONTROL_REG 0x1BU
|
||||
#define WATCHDOG_TIMER_REG 0x1CU
|
||||
#define BUCK_ICC_TURNOFF_REG 0x1DU
|
||||
#define LDO_ICC_TURNOFF_REG 0x1EU
|
||||
#define BUCK_APM_CONTROL_REG 0x1FU
|
||||
#define BUCK1_CONTROL_REG 0x20U
|
||||
#define BUCK2_CONTROL_REG 0x21U
|
||||
#define BUCK3_CONTROL_REG 0x22U
|
||||
#define BUCK4_CONTROL_REG 0x23U
|
||||
#define VREF_DDR_CONTROL_REG 0x24U
|
||||
#define LDO1_CONTROL_REG 0x25U
|
||||
#define LDO2_CONTROL_REG 0x26U
|
||||
#define LDO3_CONTROL_REG 0x27U
|
||||
#define LDO4_CONTROL_REG 0x28U
|
||||
#define LDO5_CONTROL_REG 0x29U
|
||||
#define LDO6_CONTROL_REG 0x2AU
|
||||
#define BUCK1_PWRCTRL_REG 0x30U
|
||||
#define BUCK2_PWRCTRL_REG 0x31U
|
||||
#define BUCK3_PWRCTRL_REG 0x32U
|
||||
#define BUCK4_PWRCTRL_REG 0x33U
|
||||
#define VREF_DDR_PWRCTRL_REG 0x34U
|
||||
#define LDO1_PWRCTRL_REG 0x35U
|
||||
#define LDO2_PWRCTRL_REG 0x36U
|
||||
#define LDO3_PWRCTRL_REG 0x37U
|
||||
#define LDO4_PWRCTRL_REG 0x38U
|
||||
#define LDO5_PWRCTRL_REG 0x39U
|
||||
#define LDO6_PWRCTRL_REG 0x3AU
|
||||
#define FREQUENCY_SPREADING_REG 0x3BU
|
||||
#define USB_CONTROL_REG 0x40U
|
||||
#define ITLATCH1_REG 0x50U
|
||||
#define ITLATCH2_REG 0x51U
|
||||
#define ITLATCH3_REG 0x52U
|
||||
#define ITLATCH4_REG 0x53U
|
||||
#define ITSETLATCH1_REG 0x60U
|
||||
#define ITSETLATCH2_REG 0x61U
|
||||
#define ITSETLATCH3_REG 0x62U
|
||||
#define ITSETLATCH4_REG 0x63U
|
||||
#define ITCLEARLATCH1_REG 0x70U
|
||||
#define ITCLEARLATCH2_REG 0x71U
|
||||
#define ITCLEARLATCH3_REG 0x72U
|
||||
#define ITCLEARLATCH4_REG 0x73U
|
||||
#define ITMASK1_REG 0x80U
|
||||
#define ITMASK2_REG 0x81U
|
||||
#define ITMASK3_REG 0x82U
|
||||
#define ITMASK4_REG 0x83U
|
||||
#define ITSETMASK1_REG 0x90U
|
||||
#define ITSETMASK2_REG 0x91U
|
||||
#define ITSETMASK3_REG 0x92U
|
||||
#define ITSETMASK4_REG 0x93U
|
||||
#define ITCLEARMASK1_REG 0xA0U
|
||||
#define ITCLEARMASK2_REG 0xA1U
|
||||
#define ITCLEARMASK3_REG 0xA2U
|
||||
#define ITCLEARMASK4_REG 0xA3U
|
||||
#define ITSOURCE1_REG 0xB0U
|
||||
#define ITSOURCE2_REG 0xB1U
|
||||
#define ITSOURCE3_REG 0xB2U
|
||||
#define ITSOURCE4_REG 0xB3U
|
||||
#define LDO_VOLTAGE_MASK 0x7CU
|
||||
#define BUCK_VOLTAGE_MASK 0xFCU
|
||||
#define LDO_BUCK_VOLTAGE_SHIFT 2
|
||||
#define LDO_ENABLE_MASK 0x01U
|
||||
#define BUCK_ENABLE_MASK 0x01U
|
||||
#define BUCK_HPLP_ENABLE_MASK 0x02U
|
||||
#define LDO_HPLP_ENABLE_MASK 0x02U
|
||||
#define LDO_BUCK_HPLP_SHIFT 1
|
||||
#define LDO_BUCK_RANK_MASK 0x01U
|
||||
#define LDO_BUCK_RESET_MASK 0x01U
|
||||
#define LDO_BUCK_PULL_DOWN_MASK 0x03U
|
||||
|
||||
/* Main PMIC Control Register (MAIN_CONTROL_REG) */
|
||||
#define ICC_EVENT_ENABLED BIT(4)
|
||||
#define PWRCTRL_POLARITY_HIGH BIT(3)
|
||||
#define PWRCTRL_PIN_VALID BIT(2)
|
||||
#define RESTART_REQUEST_ENABLED BIT(1)
|
||||
#define SOFTWARE_SWITCH_OFF_ENABLED BIT(0)
|
||||
|
||||
/* Main PMIC PADS Control Register (PADS_PULL_REG) */
|
||||
#define WAKEUP_DETECTOR_DISABLED BIT(4)
|
||||
#define PWRCTRL_PD_ACTIVE BIT(3)
|
||||
#define PWRCTRL_PU_ACTIVE BIT(2)
|
||||
#define WAKEUP_PD_ACTIVE BIT(1)
|
||||
#define PONKEY_PU_ACTIVE BIT(0)
|
||||
|
||||
/* Main PMIC VINLOW Control Register (VIN_CONTROL_REGC DMSC) */
|
||||
#define SWIN_DETECTOR_ENABLED BIT(7)
|
||||
#define SWOUT_DETECTOR_ENABLED BIT(6)
|
||||
#define VINLOW_HYST_MASK 0x3
|
||||
#define VINLOW_HYST_SHIFT 4
|
||||
#define VINLOW_THRESHOLD_MASK 0x7
|
||||
#define VINLOW_THRESHOLD_SHIFT 1
|
||||
#define VINLOW_ENABLED 0x01
|
||||
#define VINLOW_CTRL_REG_MASK 0xFF
|
||||
|
||||
/* USB Control Register */
|
||||
#define BOOST_OVP_DISABLED BIT(7)
|
||||
#define VBUS_OTG_DETECTION_DISABLED BIT(6)
|
||||
#define OCP_LIMIT_HIGH BIT(3)
|
||||
#define SWIN_SWOUT_ENABLED BIT(2)
|
||||
#define USBSW_OTG_SWITCH_ENABLED BIT(1)
|
||||
|
||||
int stpmu1_switch_off(void);
|
||||
int stpmu1_register_read(uint8_t register_id, uint8_t *value);
|
||||
int stpmu1_register_write(uint8_t register_id, uint8_t value);
|
||||
int stpmu1_register_update(uint8_t register_id, uint8_t value, uint8_t mask);
|
||||
int stpmu1_regulator_enable(const char *name);
|
||||
int stpmu1_regulator_disable(const char *name);
|
||||
uint8_t stpmu1_is_regulator_enabled(const char *name);
|
||||
int stpmu1_regulator_voltage_set(const char *name, uint16_t millivolts);
|
||||
void stpmu1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr);
|
||||
|
||||
#endif /* __STPMU1_H__ */
|
@ -18,6 +18,7 @@
|
||||
#include <platform_def.h>
|
||||
#include <stm32mp1_clk.h>
|
||||
#include <stm32mp1_dt.h>
|
||||
#include <stm32mp1_pmic.h>
|
||||
#include <stm32mp1_private.h>
|
||||
#include <stm32mp1_context.h>
|
||||
#include <stm32mp1_pwr.h>
|
||||
@ -34,6 +35,10 @@ void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1,
|
||||
|
||||
void bl2_platform_setup(void)
|
||||
{
|
||||
if (dt_check_pmic()) {
|
||||
initialize_pmic();
|
||||
}
|
||||
|
||||
INFO("BL2 runs SP_MIN setup\n");
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,9 @@ PLAT_BL_COMMON_SOURCES += ${LIBFDT_SRCS} \
|
||||
drivers/st/clk/stm32mp1_clk.c \
|
||||
drivers/st/clk/stm32mp1_clkfunc.c \
|
||||
drivers/st/gpio/stm32_gpio.c \
|
||||
drivers/st/pmic/stm32_i2c.c \
|
||||
drivers/st/pmic/stm32mp1_pmic.c \
|
||||
drivers/st/pmic/stpmu1.c \
|
||||
drivers/st/reset/stm32mp1_reset.c \
|
||||
plat/st/stm32mp1/stm32mp1_context.c \
|
||||
plat/st/stm32mp1/stm32mp1_dt.c \
|
||||
|
Loading…
Reference in New Issue
Block a user