misc: mnh: reduce number of states and ioctls
Also, refactor DDR init, suspend, and resume so it is not performed during power-on sequencing. This allows us to configure MIPI immediately, and do DDR sequencing and booting in parallel with other camera HAL operations. Change-Id: Ie9f16ea4f3e7af42651002f333156b14f832159f Signed-off-by: Trevor Bunker <trevorbunker@google.com>
This commit is contained in:
committed by
Thierry Strudel
parent
9a7e88bf3c
commit
68c04e60ba
@@ -14,6 +14,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
#include "mnh-hwio.h"
|
||||
#include "mnh-hwio-bases.h"
|
||||
#include "mnh-hwio-ddr-ctl.h"
|
||||
@@ -215,7 +217,7 @@ int mnh_ddr_suspend(struct device *dev, struct gpio_desc *iso_n)
|
||||
timeout++;
|
||||
}
|
||||
if (timeout == 10)
|
||||
dev_dbg(dev, "%s: failed to get LP complete\n", __func__);
|
||||
dev_err(dev, "%s: failed to get LP complete\n", __func__);
|
||||
else
|
||||
dev_dbg(dev, "%s got it after %d iterations. 121 is 0x%x",
|
||||
__func__, timeout, MNH_DDR_CTL_INf(121, LP_STATE));
|
||||
@@ -302,8 +304,7 @@ int mnh_ddr_resume(struct device *dev, struct gpio_desc *iso_n)
|
||||
}
|
||||
EXPORT_SYMBOL(mnh_ddr_resume);
|
||||
|
||||
|
||||
int mnh_ddr_po_init(struct device *dev)
|
||||
int mnh_ddr_po_init(struct device *dev, struct gpio_desc *iso_n)
|
||||
{
|
||||
int index;
|
||||
int timeout = 0;
|
||||
@@ -313,6 +314,9 @@ int mnh_ddr_po_init(struct device *dev)
|
||||
|
||||
dev_dbg(dev, "%s start.", __func__);
|
||||
|
||||
/* deassert iso_n */
|
||||
gpiod_set_value_cansleep(iso_n, 1);
|
||||
|
||||
mnh_ddr_init_clocks(dev);
|
||||
|
||||
for (index = 0; index < MNH_DDR_NUM_CTL_REG; index++)
|
||||
|
||||
@@ -48,7 +48,7 @@ struct mnh_ddr_internal_state {
|
||||
u32 fsps[MNH_DDR_NUM_FSPS];
|
||||
};
|
||||
|
||||
int mnh_ddr_po_init(struct device *dev);
|
||||
int mnh_ddr_po_init(struct device *dev, struct gpio_desc *iso_n);
|
||||
int mnh_ddr_resume(struct device *dev, struct gpio_desc *iso_n);
|
||||
int mnh_ddr_suspend(struct device *dev, struct gpio_desc *iso_n);
|
||||
void mnh_ddr_disable_lp(void);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define DEBUG
|
||||
/* #define DEBUG */
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <linux/msm_pcie.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include "mnh-ddr.h"
|
||||
#include "mnh-pcie.h"
|
||||
#include "mnh-pwr.h"
|
||||
|
||||
@@ -59,7 +58,6 @@ struct mnh_pwr_data {
|
||||
/* pins */
|
||||
struct gpio_desc *boot_mode_pin;
|
||||
struct gpio_desc *soc_pwr_good_pin;
|
||||
struct gpio_desc *ddr_pad_iso_n_pin;
|
||||
|
||||
/* pcie device */
|
||||
struct pci_dev *pcidev;
|
||||
@@ -344,9 +342,6 @@ static int mnh_pwr_down(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* assert ddr_pad_iso_n */
|
||||
gpiod_set_value_cansleep(mnh_pwr->ddr_pad_iso_n_pin, 1);
|
||||
|
||||
/* suspend pcie link */
|
||||
ret = mnh_pwr_pcie_suspend();
|
||||
if (ret) {
|
||||
@@ -376,7 +371,7 @@ static int mnh_pwr_down(void)
|
||||
goto fail_pwr_down_sdsr;
|
||||
}
|
||||
|
||||
if ((mnh_pwr->state == MNH_PWR_S0) || (mnh_pwr->state == MNH_PWR_S1)) {
|
||||
if (mnh_pwr->state == MNH_PWR_S0) {
|
||||
ret = regulator_disable(mnh_pwr->asr_supply);
|
||||
if (ret) {
|
||||
dev_err(mnh_pwr->dev,
|
||||
@@ -436,23 +431,10 @@ fail_pwr_down_sdldo:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mnh_pwr_bypass(void)
|
||||
{
|
||||
/* put ddr into self-refresh mode, assert pad isolation */
|
||||
mnh_ddr_suspend(mnh_pwr->dev, mnh_pwr->ddr_pad_iso_n_pin);
|
||||
|
||||
mnh_pwr->state = MNH_PWR_S1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mnh_pwr_suspend(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* put ddr into self-refresh mode, assert pad isolation */
|
||||
mnh_ddr_suspend(mnh_pwr->dev, mnh_pwr->ddr_pad_iso_n_pin);
|
||||
|
||||
/* suspend pcie link */
|
||||
ret = mnh_pwr_pcie_suspend();
|
||||
if (ret) {
|
||||
@@ -494,7 +476,6 @@ static int mnh_pwr_suspend(void)
|
||||
return 0;
|
||||
|
||||
fail_pwr_suspend_pcie:
|
||||
gpiod_set_value_cansleep(mnh_pwr->ddr_pad_iso_n_pin, 1);
|
||||
gpiod_set_value_cansleep(mnh_pwr->soc_pwr_good_pin, 0);
|
||||
if (mnh_pwr->sleep_clk_enabled) {
|
||||
clk_disable_unprepare(mnh_pwr->sleep_clk);
|
||||
@@ -527,10 +508,6 @@ static int mnh_pwr_up(enum mnh_pwr_state next_state)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* if we are in bypass mode, just skip to resume DDR */
|
||||
if (mnh_pwr->state == MNH_PWR_S1)
|
||||
goto pwr_up_resume_ddr;
|
||||
|
||||
/* enable supplies */
|
||||
/* sdldo -> ioldo -> asr -> sdsr */
|
||||
if (mnh_pwr->state == MNH_PWR_S4) {
|
||||
@@ -604,11 +581,6 @@ static int mnh_pwr_up(enum mnh_pwr_state next_state)
|
||||
goto fail_pwr_up_pcie;
|
||||
}
|
||||
|
||||
pwr_up_resume_ddr:
|
||||
/* if ddr is in self-refresh and we are going to S0 state, resume ddr */
|
||||
if ((mnh_pwr->state != MNH_PWR_S4) && (next_state == MNH_PWR_S0))
|
||||
mnh_ddr_resume(mnh_pwr->dev, mnh_pwr->ddr_pad_iso_n_pin);
|
||||
|
||||
mnh_pwr->state = next_state;
|
||||
|
||||
return 0;
|
||||
@@ -736,14 +708,6 @@ static int mnh_pwr_get_resources(void)
|
||||
return PTR_ERR(mnh_pwr->soc_pwr_good_pin);
|
||||
}
|
||||
|
||||
mnh_pwr->ddr_pad_iso_n_pin = devm_gpiod_get(dev, "ddr-pad-iso-n",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(mnh_pwr->ddr_pad_iso_n_pin)) {
|
||||
dev_err(dev, "%s: could not get ddr_pad_iso_n gpio (%ld)\n",
|
||||
__func__, PTR_ERR(mnh_pwr->ddr_pad_iso_n_pin));
|
||||
return PTR_ERR(mnh_pwr->ddr_pad_iso_n_pin);
|
||||
}
|
||||
|
||||
/* request clocks */
|
||||
mnh_pwr->ref_clk = devm_clk_get(dev, "ref_clk");
|
||||
if (IS_ERR(mnh_pwr->ref_clk)) {
|
||||
@@ -774,9 +738,6 @@ int mnh_pwr_set_state(enum mnh_pwr_state system_state)
|
||||
case MNH_PWR_S0:
|
||||
ret = mnh_pwr_up(system_state);
|
||||
break;
|
||||
case MNH_PWR_S1:
|
||||
ret = mnh_pwr_bypass();
|
||||
break;
|
||||
case MNH_PWR_S3:
|
||||
ret = mnh_pwr_suspend();
|
||||
break;
|
||||
@@ -791,9 +752,9 @@ int mnh_pwr_set_state(enum mnh_pwr_state system_state)
|
||||
}
|
||||
|
||||
if (ret)
|
||||
dev_info(mnh_pwr->dev,
|
||||
"%s: state transition failed (%d)\n",
|
||||
__func__, ret);
|
||||
dev_err(mnh_pwr->dev,
|
||||
"%s: state transition failed (%d)\n",
|
||||
__func__, ret);
|
||||
else
|
||||
dev_info(mnh_pwr->dev, "%s done with state: %d\n",
|
||||
__func__, mnh_pwr_get_state());
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
enum mnh_pwr_state {
|
||||
MNH_PWR_S0 = 0, /* active mode */
|
||||
MNH_PWR_S1 = 1, /* bypass mode */
|
||||
MNH_PWR_S3 = 3, /* suspend mode */
|
||||
MNH_PWR_S4 = 4, /* power off */
|
||||
};
|
||||
|
||||
@@ -110,6 +110,12 @@ enum fw_image_state {
|
||||
FW_IMAGE_DOWNLOAD_FAIL
|
||||
};
|
||||
|
||||
enum mnh_ddr_status {
|
||||
MNH_DDR_OFF = 0, /* powered off */
|
||||
MNH_DDR_ACTIVE, /* powered on, active */
|
||||
MNH_DDR_SELF_REFRESH, /* powered on, in self-refresh */
|
||||
};
|
||||
|
||||
struct mnh_sm_device {
|
||||
struct platform_device *pdev;
|
||||
struct device *dev;
|
||||
@@ -135,25 +141,15 @@ struct mnh_sm_device {
|
||||
|
||||
/* completion used for synchronizing with secondary bootloader */
|
||||
struct completion suspend_complete;
|
||||
};
|
||||
|
||||
static struct mnh_mipi_config mnh_mipi_configs[] = {
|
||||
{
|
||||
.txdev = MNH_MUX_DEVICE_TX0,
|
||||
.rxdev = MNH_MUX_DEVICE_RX0,
|
||||
.rx_rate = 1296,
|
||||
.tx_rate = 1296,
|
||||
.vc_en_mask = MNH_MIPI_VC_ALL_EN_MASK,
|
||||
.is_gen3 = 1,
|
||||
},
|
||||
{
|
||||
.txdev = MNH_MUX_DEVICE_TX1,
|
||||
.rxdev = MNH_MUX_DEVICE_RX1,
|
||||
.rx_rate = 648,
|
||||
.tx_rate = 648,
|
||||
.vc_en_mask = MNH_MIPI_VC_ALL_EN_MASK,
|
||||
.is_gen3 = 1,
|
||||
},
|
||||
/* state of the ddr channel */
|
||||
enum mnh_ddr_status ddr_status;
|
||||
|
||||
/* pin used for ddr pad isolation */
|
||||
struct gpio_desc *ddr_pad_iso_n_pin;
|
||||
|
||||
/* flag to know if firmware has already been downloaded */
|
||||
bool firmware_downloaded;
|
||||
};
|
||||
|
||||
static struct mnh_sm_device *mnh_sm_dev;
|
||||
@@ -185,7 +181,7 @@ static ssize_t mnh_sm_poweron_show(struct device *dev,
|
||||
ssize_t strlen = 0;
|
||||
|
||||
dev_dbg(dev, "Entering mnh_sm_poweron_show...\n");
|
||||
mnh_sm_set_state(MNH_STATE_INIT);
|
||||
mnh_sm_set_state(MNH_STATE_PENDING);
|
||||
return strlen;
|
||||
}
|
||||
|
||||
@@ -226,52 +222,6 @@ static ssize_t mnh_sm_poweroff_store(struct device *dev,
|
||||
static DEVICE_ATTR(poweroff, S_IWUSR | S_IRUSR | S_IRGRP,
|
||||
mnh_sm_poweroff_show, mnh_sm_poweroff_store);
|
||||
|
||||
|
||||
static ssize_t mnh_sm_config_mipi_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
ssize_t strlen = 0;
|
||||
|
||||
dev_dbg(dev, "Entering mnh_sm_config_mipi_show...\n");
|
||||
mnh_sm_set_state(MNH_STATE_CONFIG_MIPI);
|
||||
return strlen;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(config_mipi, S_IRUGO,
|
||||
mnh_sm_config_mipi_show, NULL);
|
||||
|
||||
static ssize_t mnh_sm_config_ddr_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
ssize_t strlen = 0;
|
||||
|
||||
dev_dbg(dev, "Entering mnh_sm_config_ddr_show...\n");
|
||||
mnh_sm_set_state(MNH_STATE_CONFIG_DDR);
|
||||
return strlen;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(config_ddr, S_IRUGO,
|
||||
mnh_sm_config_ddr_show, NULL);
|
||||
|
||||
|
||||
static ssize_t mnh_sm_config_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
ssize_t strlen = 0;
|
||||
|
||||
dev_dbg(dev, "Entering mnh_sm_config_show...\n");
|
||||
mnh_sm_set_state(MNH_STATE_CONFIG_MIPI);
|
||||
mnh_sm_set_state(MNH_STATE_CONFIG_DDR);
|
||||
return strlen;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(config, S_IRUGO,
|
||||
mnh_sm_config_show, NULL);
|
||||
|
||||
|
||||
static ssize_t mnh_sm_state_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
@@ -510,6 +460,8 @@ int mnh_download_firmware(void)
|
||||
/* Unregister DMA callback */
|
||||
mnh_reg_irq_callback(NULL, NULL, NULL);
|
||||
|
||||
mnh_sm_dev->firmware_downloaded = true;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_downloading:
|
||||
@@ -551,7 +503,7 @@ static ssize_t mnh_sm_suspend_show(struct device *dev,
|
||||
{
|
||||
ssize_t strlen = 0;
|
||||
|
||||
mnh_sm_set_state(MNH_STATE_SUSPEND_SELF_REFRESH);
|
||||
mnh_sm_set_state(MNH_STATE_SUSPEND);
|
||||
|
||||
return strlen;
|
||||
}
|
||||
@@ -658,17 +610,6 @@ static ssize_t mnh_sm_resume_store(struct device *dev,
|
||||
static DEVICE_ATTR(resume, S_IRUGO | S_IWUSR | S_IWGRP,
|
||||
mnh_sm_resume_show, mnh_sm_resume_store);
|
||||
|
||||
static ssize_t mnh_sm_bypass_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
mnh_sm_set_state(MNH_STATE_BYPASS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(bypass, S_IWUSR | S_IRUGO,
|
||||
mnh_sm_bypass_show, NULL);
|
||||
|
||||
static ssize_t mnh_sm_reset_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
@@ -810,14 +751,10 @@ static DEVICE_ATTR(freeze_state, S_IWUSR | S_IRUGO,
|
||||
static struct attribute *mnh_sm_dev_attributes[] = {
|
||||
&dev_attr_poweron.attr,
|
||||
&dev_attr_poweroff.attr,
|
||||
&dev_attr_config_mipi.attr,
|
||||
&dev_attr_config_ddr.attr,
|
||||
&dev_attr_config.attr,
|
||||
&dev_attr_state.attr,
|
||||
&dev_attr_download.attr,
|
||||
&dev_attr_suspend.attr,
|
||||
&dev_attr_resume.attr,
|
||||
&dev_attr_bypass.attr,
|
||||
&dev_attr_reset.attr,
|
||||
&dev_attr_cpu_clk.attr,
|
||||
&dev_attr_uboot.attr,
|
||||
@@ -876,36 +813,37 @@ static int mnh_sm_poweron(void)
|
||||
*/
|
||||
static int mnh_sm_poweroff(void)
|
||||
{
|
||||
/* Power down MNH */
|
||||
mnh_pwr_set_state(MNH_PWR_S4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* API to initialize MIPI, DDR, DDR training,
|
||||
* and PCIE.
|
||||
* @param[in] Structure argument to configure each boot component.
|
||||
* This structure will be populated within the kernel module.
|
||||
* @return 0 if success or -EINVAL or -EFATAL on failure
|
||||
*/
|
||||
static int mnh_sm_config_mipi(void)
|
||||
{
|
||||
/* Initialze MIPI bypass */
|
||||
/* TODO hardcode the to use the first config */
|
||||
mnh_mipi_config(mnh_sm_dev->dev, mnh_mipi_configs[0]);
|
||||
mnh_mipi_config(mnh_sm_dev->dev, mnh_mipi_configs[1]);
|
||||
|
||||
mnh_sm_dev->ddr_status = MNH_DDR_OFF;
|
||||
mnh_sm_dev->firmware_downloaded = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mnh_sm_config_ddr(void)
|
||||
{
|
||||
/* Initialize DDR */
|
||||
mnh_ddr_po_init(mnh_sm_dev->dev);
|
||||
mnh_ddr_po_init(mnh_sm_dev->dev, mnh_sm_dev->ddr_pad_iso_n_pin);
|
||||
mnh_sm_dev->ddr_status = MNH_DDR_ACTIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mnh_sm_resume_ddr(void)
|
||||
{
|
||||
/* deassert pad isolation, take ddr out of self-refresh mode */
|
||||
mnh_ddr_resume(mnh_sm_dev->dev, mnh_sm_dev->ddr_pad_iso_n_pin);
|
||||
mnh_sm_dev->ddr_status = MNH_DDR_ACTIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mnh_sm_suspend_ddr(void)
|
||||
{
|
||||
/* put ddr into self-refresh mode, assert pad isolation */
|
||||
mnh_ddr_suspend(mnh_sm_dev->dev, mnh_sm_dev->ddr_pad_iso_n_pin);
|
||||
mnh_sm_dev->ddr_status = MNH_DDR_SELF_REFRESH;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* API to download the binary images(SBL, UBoot, Kernel, Ramdisk) for mnh.
|
||||
* The location of the binaries will be located in the AP file system.
|
||||
@@ -980,6 +918,8 @@ static int mnh_sm_suspend(void)
|
||||
dev_dbg(mnh_sm_dev->dev, "%s: resume entry: 0x%x\n", __func__,
|
||||
mnh_resume_addr);
|
||||
|
||||
mnh_sm_suspend_ddr();
|
||||
|
||||
/* Suspend MNH power */
|
||||
mnh_pwr_set_state(MNH_PWR_S3);
|
||||
return 0;
|
||||
@@ -995,11 +935,7 @@ static int mnh_sm_suspend(void)
|
||||
*/
|
||||
static int mnh_sm_resume(void)
|
||||
{
|
||||
/* Initialize MNH Power */
|
||||
mnh_pwr_set_state(MNH_PWR_S0);
|
||||
|
||||
mnh_resume_firmware();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1029,160 +965,6 @@ static int mnh_sm_enable_clock_gating(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mnh_sm_disable_gpio(void)
|
||||
{
|
||||
/* disable GPIO */
|
||||
MNH_SCU_OUTf(RSTC, UART0_RST, 1);
|
||||
MNH_SCU_OUTf(PERIPH_CLK_CTRL, UART0_CLKEN_SW, 0);
|
||||
MNH_SCU_OUTf(PERIPH_CLK_CTRL, GPIO_CLKEN_SW, 0);
|
||||
MNH_SCU_OUTf(SOC_GLOBAL_CONTROL, GLOBAL_PAD_OUTPUT_DISABLE, 0x1);
|
||||
MNH_SCU_OUT(PIN00_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN01_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN02_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN03_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN04_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN05_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN06_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN07_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN08_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN09_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN10_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN11_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN12_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN13_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN14_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN15_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN16_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN17_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN18_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN19_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN20_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN21_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN22_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN23_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN24_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN25_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN26_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN27_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN28_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN29_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN30_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN31_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN32_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN33_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN34_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN35_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN36_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN37_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN38_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN39_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN40_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN41_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN42_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN43_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN44_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN45_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN46_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN47_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN48_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN49_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN50_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN51_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN52_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN53_CFG, 0x0);
|
||||
MNH_SCU_OUT(PIN54_CFG, 0x0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Force clock gating and reset on all devices that are not needed
|
||||
* for mipi bypass.
|
||||
*/
|
||||
static int mnh_sm_force_low_power(void)
|
||||
{
|
||||
/* set cpy freq down */
|
||||
/* set SYS200 clk */
|
||||
mnh_ipu_freq_change(0);
|
||||
mnh_cpu_freq_change(0);
|
||||
mnh_lpddr_freq_change(0);
|
||||
/* perfmon reset and disable clock */
|
||||
dev_dbg(mnh_sm_dev->dev, "Force peripherals off!!!\n");
|
||||
MNH_SCU_OUTf(RSTC, PMON_RST, 1);
|
||||
MNH_SCU_OUTf(CCU_CLK_CTL, PMON_CLKEN, 0);
|
||||
/** ipu sub system reset */
|
||||
MNH_SCU_OUTf(RSTC, IPU_RST, 1);
|
||||
MNH_SCU_OUTf(RSTC, MIPITXPHY_RST, 1);
|
||||
MNH_SCU_OUTf(RSTC, MIPIRXPHY_RST, 1);
|
||||
MNH_SCU_OUTf(CCU_CLK_CTL, IPU_CLKEN, 0);
|
||||
MNH_SCU_OUTf(MEM_PWR_MGMNT, IPU_MEM_SD, 1);
|
||||
/* All i2c masters */
|
||||
MNH_SCU_OUTf(RSTC, I2C0_RST, 1);
|
||||
MNH_SCU_OUTf(RSTC, I2C1_RST, 1);
|
||||
MNH_SCU_OUTf(RSTC, I2C2_RST, 1);
|
||||
MNH_SCU_OUTf(RSTC, I2C3_RST, 1);
|
||||
MNH_SCU_OUTf(PERIPH_CLK_CTRL, I2C0_CLKEN_SW, 0);
|
||||
MNH_SCU_OUTf(PERIPH_CLK_CTRL, I2C1_CLKEN_SW, 0);
|
||||
MNH_SCU_OUTf(PERIPH_CLK_CTRL, I2C2_CLKEN_SW, 0);
|
||||
MNH_SCU_OUTf(PERIPH_CLK_CTRL, I2C3_CLKEN_SW, 0);
|
||||
/* Enable hw control of pcie clk */
|
||||
MNH_SCU_OUTf(PERIPH_CLK_CTRL, PCIE_CLK_MODE, 1);
|
||||
|
||||
/* do we want to set this? */
|
||||
MNH_SCU_OUTf(RSTC, UART1_RST, 1);
|
||||
MNH_SCU_OUTf(PERIPH_CLK_CTRL, UART1_CLKEN_SW, 0);
|
||||
/* spi slave and spi master */
|
||||
MNH_SCU_OUTf(RSTC, SPIS_RST, 1);
|
||||
MNH_SCU_OUTf(RSTC, SPIM_RST, 1);
|
||||
MNH_SCU_OUTf(PERIPH_CLK_CTRL, SPIS_CLKEN_SW, 1);
|
||||
MNH_SCU_OUTf(PERIPH_CLK_CTRL, SPIM_CLKEN_SW, 1);
|
||||
/* peripheral dma */
|
||||
MNH_SCU_OUTf(RSTC, PERI_DMA_RST, 1);
|
||||
MNH_SCU_OUTf(PERIPH_CLK_CTRL, PERI_DMA_CLKEN_SW, 0);
|
||||
/* timer */
|
||||
MNH_SCU_OUTf(RSTC, TIMER_RST, 1);
|
||||
MNH_SCU_OUTf(PERIPH_CLK_CTRL, TIMER_CLKEN_SW, 0);
|
||||
/* WDT */
|
||||
MNH_SCU_OUTf(PERIPH_CLK_CTRL, WDT_CLKEN_SW, 0);
|
||||
/* pvt */
|
||||
/* MNH_SCU_OUTf(PERIPH_CLK_CTRL, PVT_CLKEN, 0); */
|
||||
/* set mipi */
|
||||
MNH_SCU_OUTf(CCU_CLK_CTL, MIPI_TESTCLKEN, 0);
|
||||
/* for now, stop other mipi devices */
|
||||
mnh_mipi_stop_device(mnh_sm_dev->dev, 0);
|
||||
mnh_mipi_stop_device(mnh_sm_dev->dev, 1);
|
||||
mnh_mipi_stop_host(mnh_sm_dev->dev, 0);
|
||||
mnh_mipi_stop_host(mnh_sm_dev->dev, 1);
|
||||
mnh_mipi_stop_host(mnh_sm_dev->dev, 2);
|
||||
|
||||
mnh_sm_enable_clock_gating();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put MNH in bypass state. In bypass mode the DDR will be isolated
|
||||
* and put in self refresh while the CPU is powered.
|
||||
* @return 0 if success or -EINVAL or -EFATAL on failure
|
||||
*/
|
||||
static int mnh_sm_bypass(void)
|
||||
{
|
||||
dev_dbg(mnh_sm_dev->dev, "%s: Entering bypass mode\n", __func__);
|
||||
|
||||
mnh_sm_force_low_power();
|
||||
|
||||
mnh_sm_disable_gpio();
|
||||
|
||||
mnh_pwr_set_state(MNH_PWR_S1);
|
||||
|
||||
MNH_SCU_OUTf(CCU_CLK_CTL, HALT_LP4CG_EN, 1);
|
||||
MNH_SCU_OUTf(CCU_CLK_CTL, HALT_LP4_PLL_BYPCLK_CG_EN, 1);
|
||||
MNH_SCU_OUTf(MEM_PWR_MGMNT, HALT_LP4CMEM_PD_EN, 1);
|
||||
|
||||
mnh_lpddr_sys200_mode();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* API to obtain the state of monette hill.
|
||||
* @return the power states of mnh
|
||||
@@ -1207,47 +989,43 @@ static int mnh_sm_set_state_locked(int state)
|
||||
case MNH_STATE_OFF:
|
||||
ret = mnh_sm_poweroff();
|
||||
break;
|
||||
case MNH_STATE_INIT:
|
||||
ret = mnh_sm_set_state_locked(MNH_STATE_OFF);
|
||||
if (!ret)
|
||||
case MNH_STATE_PENDING:
|
||||
if (mnh_state == MNH_STATE_ACTIVE) {
|
||||
dev_err(mnh_sm_dev->dev,
|
||||
"%s: cannot transition to MNH_STATE_PENDING from state %d\n",
|
||||
__func__, mnh_state);
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
ret = mnh_sm_poweron();
|
||||
break;
|
||||
case MNH_STATE_CONFIG_MIPI:
|
||||
if (mnh_state != MNH_STATE_CONFIG_DDR) {
|
||||
ret = mnh_sm_set_state_locked(MNH_STATE_INIT);
|
||||
if (!ret)
|
||||
ret = mnh_sm_config_mipi();
|
||||
}
|
||||
break;
|
||||
case MNH_STATE_CONFIG_DDR:
|
||||
if (mnh_state != MNH_STATE_CONFIG_MIPI) {
|
||||
ret = mnh_sm_set_state_locked(MNH_STATE_INIT);
|
||||
if (!ret)
|
||||
ret = mnh_sm_config_ddr();
|
||||
}
|
||||
break;
|
||||
case MNH_STATE_BYPASS:
|
||||
mnh_sm_set_state_locked(MNH_STATE_ACTIVE);
|
||||
mnh_sm_bypass();
|
||||
break;
|
||||
case MNH_STATE_ACTIVE:
|
||||
if (mnh_state == MNH_STATE_SUSPEND_SELF_REFRESH) {
|
||||
/* make sure we are powered */
|
||||
if ((mnh_state == MNH_STATE_OFF) ||
|
||||
(mnh_state == MNH_STATE_SUSPEND))
|
||||
ret = mnh_sm_poweron();
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
/* make sure ddr is configured */
|
||||
if (mnh_sm_dev->ddr_status == MNH_DDR_OFF)
|
||||
ret = mnh_sm_config_ddr();
|
||||
else if (mnh_sm_dev->ddr_status == MNH_DDR_SELF_REFRESH)
|
||||
ret = mnh_sm_resume_ddr();
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
/* have we downloaded firmware already? */
|
||||
if (mnh_sm_dev->firmware_downloaded)
|
||||
ret = mnh_sm_resume();
|
||||
} else {
|
||||
ret = mnh_sm_set_state_locked(MNH_STATE_CONFIG_DDR);
|
||||
if (!ret)
|
||||
ret = mnh_sm_download();
|
||||
}
|
||||
else
|
||||
ret = mnh_sm_download();
|
||||
break;
|
||||
case MNH_STATE_SUSPEND_SELF_REFRESH:
|
||||
case MNH_STATE_SUSPEND:
|
||||
ret = mnh_sm_set_state_locked(MNH_STATE_ACTIVE);
|
||||
if (!ret)
|
||||
ret = mnh_sm_suspend();
|
||||
break;
|
||||
case MNH_STATE_SUSPEND_HIBERNATE:
|
||||
dev_err(mnh_sm_dev->dev,
|
||||
"%s: TODO unsupported state %d\n", __func__, state);
|
||||
ret = -EINVAL;
|
||||
default:
|
||||
dev_err(mnh_sm_dev->dev,
|
||||
"%s: invalid state %d\n", __func__, state);
|
||||
@@ -1393,31 +1171,6 @@ static long mnh_sm_ioctl(struct file *file, unsigned int cmd,
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case MNH_SM_IOC_POWERON:
|
||||
mnh_sm_dev->next_mnh_state = MNH_STATE_INIT;
|
||||
schedule_work(&mnh_sm_dev->set_state_work);
|
||||
break;
|
||||
case MNH_SM_IOC_POWEROFF:
|
||||
mnh_sm_dev->next_mnh_state = MNH_STATE_OFF;
|
||||
schedule_work(&mnh_sm_dev->set_state_work);
|
||||
break;
|
||||
case MNH_SM_IOC_CONFIG_MIPI:
|
||||
err = copy_from_user(&mipi_config, (void __user *)arg,
|
||||
sizeof(struct mnh_mipi_config));
|
||||
if (err) {
|
||||
dev_err(mnh_sm_dev->dev,
|
||||
"%s: failed to copy mipi config from userspace (%d)\n",
|
||||
__func__, err);
|
||||
return err;
|
||||
}
|
||||
mnh_mipi_config(mnh_sm_dev->dev, mipi_config);
|
||||
/* TODO */
|
||||
mnh_state = MNH_STATE_CONFIG_MIPI;
|
||||
break;
|
||||
case MNH_SM_IOC_CONFIG_DDR:
|
||||
mnh_sm_dev->next_mnh_state = MNH_STATE_CONFIG_DDR;
|
||||
schedule_work(&mnh_sm_dev->set_state_work);
|
||||
break;
|
||||
case MNH_SM_IOC_GET_STATE:
|
||||
err = copy_to_user((void __user *)arg, &mnh_state,
|
||||
sizeof(mnh_state));
|
||||
@@ -1432,17 +1185,16 @@ static long mnh_sm_ioctl(struct file *file, unsigned int cmd,
|
||||
mnh_sm_dev->next_mnh_state = (int)arg;
|
||||
schedule_work(&mnh_sm_dev->set_state_work);
|
||||
break;
|
||||
case MNH_SM_IOC_DOWNLOAD:
|
||||
mnh_sm_dev->next_mnh_state = MNH_STATE_ACTIVE;
|
||||
schedule_work(&mnh_sm_dev->set_state_work);
|
||||
break;
|
||||
case MNH_SM_IOC_SUSPEND:
|
||||
mnh_sm_dev->next_mnh_state = MNH_STATE_SUSPEND_SELF_REFRESH;
|
||||
schedule_work(&mnh_sm_dev->set_state_work);
|
||||
break;
|
||||
case MNH_SM_IOC_RESUME:
|
||||
mnh_sm_dev->next_mnh_state = MNH_STATE_ACTIVE;
|
||||
schedule_work(&mnh_sm_dev->set_state_work);
|
||||
case MNH_SM_IOC_CONFIG_MIPI:
|
||||
err = copy_from_user(&mipi_config, (void __user *)arg,
|
||||
sizeof(struct mnh_mipi_config));
|
||||
if (err) {
|
||||
dev_err(mnh_sm_dev->dev,
|
||||
"%s: failed to copy mipi config from userspace (%d)\n",
|
||||
__func__, err);
|
||||
return err;
|
||||
}
|
||||
mnh_mipi_config(mnh_sm_dev->dev, mipi_config);
|
||||
break;
|
||||
default:
|
||||
dev_err(mnh_sm_dev->dev,
|
||||
@@ -1590,6 +1342,16 @@ static int mnh_sm_probe(struct platform_device *pdev)
|
||||
goto fail_mnh_pwr_init;
|
||||
}
|
||||
|
||||
/* request ddr pad isolation pin */
|
||||
mnh_sm_dev->ddr_pad_iso_n_pin = devm_gpiod_get(dev, "ddr-pad-iso-n",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(mnh_sm_dev->ddr_pad_iso_n_pin)) {
|
||||
dev_err(dev, "%s: could not get ddr_pad_iso_n gpio (%ld)\n",
|
||||
__func__, PTR_ERR(mnh_sm_dev->ddr_pad_iso_n_pin));
|
||||
error = PTR_ERR(mnh_sm_dev->ddr_pad_iso_n_pin);
|
||||
goto fail_mnh_pwr_init;
|
||||
}
|
||||
|
||||
/* initialize mnh-pwr and get resources there */
|
||||
error = mnh_pwr_init(dev);
|
||||
if (error) {
|
||||
|
||||
@@ -314,7 +314,7 @@ static int mnh_thermal_get_temp(void *data, int *temp_out)
|
||||
int temp_raw = 0;
|
||||
|
||||
mnh_state = mnh_sm_get_state();
|
||||
if ((mnh_state < MNH_STATE_INIT) || (mnh_state > MNH_STATE_BYPASS))
|
||||
if ((mnh_state == MNH_STATE_OFF) || (mnh_state == MNH_STATE_SUSPEND))
|
||||
return -EIO;
|
||||
|
||||
/* Apply 5 bit trim and 2 bit precision to PVT sensor register */
|
||||
|
||||
@@ -33,34 +33,18 @@
|
||||
#define MNH_SM_IOC_MAGIC 'T'
|
||||
#define MNH_SM_MAX 8
|
||||
|
||||
#define MNH_SM_IOC_POWERON \
|
||||
_IO(MNH_SM_IOC_MAGIC, 1)
|
||||
#define MNH_SM_IOC_POWEROFF \
|
||||
_IO(MNH_SM_IOC_MAGIC, 2)
|
||||
#define MNH_SM_IOC_GET_STATE \
|
||||
_IOR(MNH_SM_IOC_MAGIC, 1, int *)
|
||||
#define MNH_SM_IOC_SET_STATE \
|
||||
_IOW(MNH_SM_IOC_MAGIC, 2, int)
|
||||
#define MNH_SM_IOC_CONFIG_MIPI \
|
||||
_IOW(MNH_SM_IOC_MAGIC, 3, struct mnh_mipi_config *)
|
||||
#define MNH_SM_IOC_CONFIG_DDR \
|
||||
_IO(MNH_SM_IOC_MAGIC, 4)
|
||||
#define MNH_SM_IOC_GET_STATE \
|
||||
_IOR(MNH_SM_IOC_MAGIC, 5, int *)
|
||||
#define MNH_SM_IOC_SET_STATE \
|
||||
_IOW(MNH_SM_IOC_MAGIC, 6, int)
|
||||
#define MNH_SM_IOC_DOWNLOAD \
|
||||
_IO(MNH_SM_IOC_MAGIC, 7)
|
||||
#define MNH_SM_IOC_SUSPEND \
|
||||
_IO(MNH_SM_IOC_MAGIC, 8)
|
||||
#define MNH_SM_IOC_RESUME \
|
||||
_IO(MNH_SM_IOC_MAGIC, 9)
|
||||
|
||||
enum mnh_sm_state {
|
||||
MNH_STATE_OFF, /* powered off */
|
||||
MNH_STATE_INIT, /* powered on, unconfigured */
|
||||
MNH_STATE_CONFIG_MIPI, /* powered on, mipi configured */
|
||||
MNH_STATE_CONFIG_DDR, /* powered on, ddr configured */
|
||||
MNH_STATE_PENDING, /* powered on, pcie ready, CPU in PBL */
|
||||
MNH_STATE_ACTIVE, /* powered on and booted */
|
||||
MNH_STATE_SUSPEND_SELF_REFRESH, /* suspended, ddr in self-refresh */
|
||||
MNH_STATE_SUSPEND_HIBERNATE, /* suspended, kernel image in AP DRAM */
|
||||
MNH_STATE_BYPASS, /* CPU and DDR powered on, DDR in self-refresh */
|
||||
MNH_STATE_SUSPEND, /* suspended, ddr in self-refresh */
|
||||
MNH_STATE_MAX,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user