forked from apache/nuttx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
arc/arm64/imx9: Add reset functionality
Add support to generate reset -by ele, sending reset reques -by pmic, making cold reset -by watchdog, using watchdog 3 Read reset reason from PMIC Signed-off-by: Jouni Ukkonen <[email protected]>
- Loading branch information
Showing
3 changed files
with
330 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,324 @@ | ||
/**************************************************************************** | ||
* arch/arm64/src/imx9/imx9_reset.c | ||
* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. The | ||
* ASF licenses this file to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance with the | ||
* License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations | ||
* under the License. | ||
* | ||
****************************************************************************/ | ||
|
||
/**************************************************************************** | ||
* Included Files | ||
****************************************************************************/ | ||
|
||
#include <nuttx/config.h> | ||
|
||
#include <stdint.h> | ||
#include <stdbool.h> | ||
#include <errno.h> | ||
#include <nuttx/arch.h> | ||
#include <nuttx/clock.h> | ||
#include <debug.h> | ||
#include <sys/types.h> | ||
#include <syslog.h> | ||
#include <errno.h> | ||
#include <nuttx/i2c/i2c_master.h> | ||
#include "imx9_lpi2c.h" | ||
#include "chip.h" | ||
#include "arm64_internal.h" | ||
#include "imx9_trdc.h" | ||
|
||
/**************************************************************************** | ||
* Pre-processor Definitions | ||
****************************************************************************/ | ||
|
||
#define ELE_RESET 0xC7 | ||
|
||
/* PCA9451A in IMX9 platform */ | ||
|
||
#define PCA9451A_I2C_ADDR 0x25 | ||
#define REG_SW_RST 0x06 | ||
#define REG_POWERON_STAT 0x05 | ||
#define COLD_RESET 0x64 | ||
#define WARM_RESET 0x35 | ||
|
||
#define WDOG_BASE IMX9_WDOG3_BASE | ||
#define WDOG_CS WDOG_BASE + 0x0 | ||
#define WDOG_CNT WDOG_BASE + 0x4 | ||
#define WDOG_TOUT WDOG_BASE + 0x8 | ||
#define WDOG_WIN WDOG_BASE + 0xc | ||
#define WDOG_REFRESH_WORD0 0xA602 | ||
#define WDOG_REFRESH_WORD1 0xB480 | ||
#define WDOG_UNLOCK_WORD0 0xC520 | ||
#define WDOG_UNLOCK_WORD1 0xD928 | ||
#define WDOG_UNLOCK_WORD 0xD928C520 | ||
#define WDOG_REFRESH_WORD 0xB480A602 | ||
|
||
/**************************************************************************** | ||
* Private Functions | ||
****************************************************************************/ | ||
|
||
/**************************************************************************** | ||
* Name: imx9_ele_sendmsg | ||
* | ||
* Description: | ||
* This function communicates with the Advanced High Assurance Boot (AHAB) | ||
* image that should reside in the particular address. This function | ||
* sends a message to AHAB. | ||
* | ||
* Input Parameters: | ||
* msg - Message to send | ||
* | ||
* Returned Value: | ||
* None | ||
* | ||
****************************************************************************/ | ||
|
||
static void imx9_ele_sendmsg(struct ele_msg *msg) | ||
{ | ||
/* Check that ele is ready to receive */ | ||
|
||
while (!((1) & getreg32(ELE_MU_TSR))); | ||
|
||
/* write header to slog 0 */ | ||
|
||
putreg32(msg->header.data, ELE_MU_TR(0)); | ||
|
||
/* write data */ | ||
|
||
for (int i = 1; i < msg->header.size; i++) | ||
{ | ||
int tx_channel; | ||
|
||
tx_channel = i % ELE_TR_NUM ; | ||
while (!((1 << tx_channel) & getreg32(ELE_MU_TSR))); | ||
|
||
/* Write data */ | ||
|
||
putreg32(msg->data[i - 1], ELE_MU_TR(i)); | ||
} | ||
} | ||
|
||
/**************************************************************************** | ||
* Name: imx9_ele_receivemsg | ||
* | ||
* Description: | ||
* This function communicates with the Advanced High Assurance Boot (AHAB) | ||
* image that should reside in the particular address. This function | ||
* receives message from AHAB. | ||
* | ||
* Input Parameters: | ||
* msg - receive message buffer | ||
* | ||
* Returned Value: | ||
* None | ||
* | ||
****************************************************************************/ | ||
|
||
static void imx9_ele_receivemsg(struct ele_msg *msg) | ||
{ | ||
/* Check if data ready */ | ||
|
||
while (!((1) & getreg32(ELE_MU_RSR))); | ||
|
||
/* Read Header from slot 0 */ | ||
|
||
msg->header.data = getreg32(ELE_MU_RR(0)); | ||
|
||
for (int i = 1; i < msg->header.size; i++) | ||
{ | ||
/* Check if empty */ | ||
|
||
int rx_channel = (i) % ELE_RR_NUM; | ||
while (!((1 << rx_channel) & getreg32(ELE_MU_RSR))); | ||
|
||
/* Read data */ | ||
|
||
msg->data[i - 1] = getreg32(ELE_MU_RR(i)); | ||
} | ||
} | ||
|
||
/**************************************************************************** | ||
* Public Functions | ||
****************************************************************************/ | ||
|
||
/**************************************************************************** | ||
* Name: imx9_ele_reset | ||
* | ||
* Description: | ||
* Reset SoC using ele | ||
* | ||
****************************************************************************/ | ||
|
||
int imx9_ele_reset(void) | ||
{ | ||
static struct ele_msg msg; | ||
|
||
msg.header.version = AHAB_VERSION; | ||
msg.header.tag = AHAB_CMD_TAG; | ||
msg.header.size = 1; | ||
msg.header.command = ELE_RESET; | ||
|
||
imx9_ele_sendmsg(&msg); | ||
imx9_ele_receivemsg(&msg); | ||
|
||
/* We should not reach this point */ | ||
|
||
if ((msg.data[0] & 0xff) == ELE_OK) | ||
{ | ||
return 0; | ||
} | ||
|
||
return -1; | ||
} | ||
|
||
/**************************************************************************** | ||
* Name: imx9_pmic_reset | ||
* | ||
* Description: | ||
* Reset SoC via pmic | ||
* | ||
****************************************************************************/ | ||
|
||
void imx9_pmic_reset(void) | ||
{ | ||
struct i2c_master_s *i2c; | ||
struct i2c_msg_s msg; | ||
uint8_t buffer[2]; | ||
int ret; | ||
|
||
i2c = imx9_i2cbus_initialize(CONFIG_IMX9_PMIC_I2C); | ||
|
||
if (i2c == NULL) | ||
{ | ||
return; | ||
} | ||
|
||
buffer[0] = REG_SW_RST; | ||
buffer[1] = COLD_RESET; | ||
|
||
msg.frequency = 400000; | ||
msg.addr = PCA9451A_I2C_ADDR; | ||
msg.flags = 0; | ||
msg.buffer = buffer; | ||
msg.length = 2; | ||
|
||
ret = I2C_TRANSFER(i2c, &msg, 1); | ||
if (ret < 0) | ||
{ | ||
_err("ERROR: Failed to write reset via I2C2 interface\n"); | ||
} | ||
} | ||
|
||
/**************************************************************************** | ||
* Name: imx9_wdog_reset | ||
* | ||
* Description: | ||
* Reset SoC using wdog | ||
* | ||
****************************************************************************/ | ||
|
||
void imx9_wdog_reset(void) | ||
{ | ||
uint32_t wdog_cs; | ||
uint32_t cmd = 0; | ||
|
||
wdog_cs = getreg32(WDOG_CS); | ||
if (wdog_cs & (1 << 13)) | ||
{ | ||
putreg32(WDOG_UNLOCK_WORD, WDOG_CNT); | ||
cmd = 1 << 13; | ||
} | ||
else | ||
{ | ||
putreg32(WDOG_UNLOCK_WORD0, WDOG_CNT); | ||
putreg32(WDOG_UNLOCK_WORD1, WDOG_CNT); | ||
ARM64_DMB(); | ||
} | ||
|
||
/* Wait unlock */ | ||
|
||
while (!(getreg32(WDOG_CS) & (1 << 11))); | ||
|
||
putreg32(40, WDOG_TOUT); | ||
putreg32(0, WDOG_WIN); | ||
putreg32((cmd | 0x11c0), WDOG_CS); | ||
|
||
/* Wait reconfiguration success */ | ||
|
||
while (!(getreg32(WDOG_CS) & (1 << 10))); | ||
|
||
if (cmd == 0) | ||
{ | ||
putreg32(WDOG_REFRESH_WORD, WDOG_CNT); | ||
} | ||
else | ||
{ | ||
putreg32(WDOG_REFRESH_WORD0, WDOG_CNT); | ||
putreg32(WDOG_REFRESH_WORD1, WDOG_CNT); | ||
ARM64_DMB(); | ||
} | ||
|
||
while (1); | ||
} | ||
|
||
#ifndef CONFIG_IMX9_HAVE_ATF_FIRMWARE | ||
void up_systemreset(void) | ||
{ | ||
imx9_pmic_reset(); | ||
|
||
/* Wait for the reset */ | ||
|
||
while (1); | ||
} | ||
#endif | ||
|
||
uint32_t imx9_get_pmic_reset_reason(void) | ||
{ | ||
struct i2c_master_s *i2c; | ||
struct i2c_msg_s msgs[2]; | ||
uint8_t reg_addr = REG_POWERON_STAT; | ||
uint8_t data; | ||
int ret; | ||
|
||
i2c = imx9_i2cbus_initialize(CONFIG_IMX9_PMIC_I2C); | ||
if (i2c == NULL) | ||
{ | ||
_err("Failed to initialize I2C bus\n"); | ||
return -ENODEV; | ||
} | ||
|
||
msgs[0].frequency = 400000; | ||
msgs[0].addr = PCA9451A_I2C_ADDR; | ||
msgs[0].flags = 0; | ||
msgs[0].buffer = ®_addr; | ||
msgs[0].length = 1; | ||
|
||
msgs[1].frequency = 400000; | ||
msgs[1].addr = PCA9451A_I2C_ADDR; | ||
msgs[1].flags = I2C_M_READ; | ||
msgs[1].buffer = &data; | ||
msgs[1].length = 1; | ||
|
||
ret = I2C_TRANSFER(i2c, msgs, 2); | ||
if (ret < 0) | ||
{ | ||
_err("I2C transfer failed: %d\n", ret); | ||
imx9_i2cbus_uninitialize(i2c); | ||
return ret; | ||
} | ||
|
||
imx9_i2cbus_uninitialize(i2c); | ||
return (uint32_t)data; | ||
} |