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:
Trevor Bunker
2017-03-08 23:45:51 -08:00
committed by Thierry Strudel
parent 9a7e88bf3c
commit 68c04e60ba
7 changed files with 107 additions and 397 deletions

View File

@@ -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++)

View File

@@ -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);

View File

@@ -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());

View File

@@ -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 */
};

View File

@@ -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) {

View File

@@ -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 */

View File

@@ -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,
};