From e762148ff5a02b2bb8daaeb52bcbdab212f764e8 Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Tue, 27 Aug 2013 18:18:38 +0800 Subject: [PATCH] ENGR00276023-2: ARM: imx: support LDO_BYPASS mode for imx6qdl Make code change for LDO_BYPASS mode. In LDO_BYPASS mode gpc will use dummy pu regulator to be notified by xPU driver. Signed-off-by: Robin Gong --- arch/arm/mach-imx/anatop.c | 27 ++++++++++ arch/arm/mach-imx/common.h | 1 + arch/arm/mach-imx/gpc.c | 100 +++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c index 76a830b49d5e..3b304b9a64fd 100644 --- a/arch/arm/mach-imx/anatop.c +++ b/arch/arm/mach-imx/anatop.c @@ -9,6 +9,7 @@ * http://www.gnu.org/copyleft/gpl.html */ +#include #include #include #include @@ -37,6 +38,10 @@ #define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B 0x80000 #define BM_ANADIG_USB_CHRG_DETECT_EN_B 0x100000 +#define ANADIG_REG_TARG_MASK 0x1f +#define ANADIG_REG1_TARG_SHIFT 9 /* VDDPU */ +#define ANADIG_REG2_TARG_SHIFT 18 /* VDDSOC */ + static struct regmap *anatop; static void imx_anatop_enable_weak2p5(bool enable) @@ -103,6 +108,28 @@ static void imx_anatop_usb_chrg_detect_disable(void) BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B); } +void imx_anatop_pu_enable(bool enable) +{ + u32 val; + + regmap_read(anatop, ANADIG_REG_CORE, &val); + val &= ANADIG_REG_TARG_MASK << ANADIG_REG2_TARG_SHIFT; + /* + * set pu regulator only in LDO_BYPASS mode(know by VDDSOC reg 0x1f), + * else handled by anatop regulator driver. + */ + if (((val >> (ANADIG_REG2_TARG_SHIFT)) & ANADIG_REG_TARG_MASK) + == ANADIG_REG_TARG_MASK) { + if (enable) { + regmap_write(anatop, ANADIG_REG_CORE + REG_SET, + ANADIG_REG_TARG_MASK << ANADIG_REG1_TARG_SHIFT); + udelay(70); /* bypass need 70us to be stable */ + } else { + regmap_write(anatop, ANADIG_REG_CORE + REG_CLR, + ANADIG_REG_TARG_MASK << ANADIG_REG1_TARG_SHIFT); + } + } +} void __init imx_init_revision_from_anatop(void) { struct device_node *np; diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index ab19a1f839f6..790ca9678843 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -143,6 +143,7 @@ extern void imx_gpc_restore_all(void); extern void imx_anatop_init(void); extern void imx_anatop_pre_suspend(void); extern void imx_anatop_post_resume(void); +extern void imx_anatop_pu_enable(bool enable); extern int imx6_set_lpm(enum mxc_cpu_pwr_mode mode); extern void imx6_set_cache_lpm_in_wait(bool enable); diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index dc6c099bde2b..2a3646b4d027 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "common.h" #include "hardware.h" @@ -53,6 +55,15 @@ static struct clk *openvg_axi_clk, *vpu_clk, *ipg_clk; static struct device *gpc_dev; struct regulator *pu_reg; struct notifier_block nb; +static struct regulator_dev *pu_dummy_regulator_rdev; +static struct regulator_init_data pu_dummy_initdata = { + .constraints = { + .max_uV = 1450000, /* allign with real max of anatop */ + .valid_ops_mask = REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_VOLTAGE, + }, +}; +static int pu_dummy_enable; void imx_gpc_pre_suspend(bool arm_power_off) { @@ -187,6 +198,7 @@ static void imx_gpc_pu_enable(bool enable) rate = clk_get_rate(ipg_clk); if (enable) { + imx_anatop_pu_enable(true); /* * need to add necessary delay between powering up PU LDO and * disabling PU isolation in PGC, the counter of PU isolation @@ -231,6 +243,7 @@ static void imx_gpc_pu_enable(bool enable) delay_us = (gpu_pdnscr_iso2sw + gpu_pdnscr_iso) * 1000000 / rate + 1; udelay(delay_us); + imx_anatop_pu_enable(false); } } @@ -308,6 +321,86 @@ void __init imx_gpc_init(void) writel_relaxed(val, gpc_base + GPC_PGC_CPU_PDNSCR); } +static int imx_pureg_set_voltage(struct regulator_dev *reg, int min_uV, + int max_uV, unsigned *selector) +{ + return 0; +} + +static int imx_pureg_enable(struct regulator_dev *rdev) +{ + pu_dummy_enable = 1; + + return 0; +} + +static int imx_pureg_disable(struct regulator_dev *rdev) +{ + pu_dummy_enable = 0; + + return 0; +} + +static int imx_pureg_is_enable(struct regulator_dev *rdev) +{ + return pu_dummy_enable; +} + +static int imx_pureg_list_voltage(struct regulator_dev *rdev, + unsigned int selector) +{ + return 0; +} + +static struct regulator_ops pu_dummy_ops = { + .set_voltage = imx_pureg_set_voltage, + .enable = imx_pureg_enable, + .disable = imx_pureg_disable, + .is_enabled = imx_pureg_is_enable, + .list_voltage = imx_pureg_list_voltage, +}; + +static struct regulator_desc pu_dummy_desc = { + .name = "pureg-dummy", + .id = -1, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .ops = &pu_dummy_ops, +}; + +static int pu_dummy_probe(struct platform_device *pdev) +{ + struct regulator_config config = { }; + int ret; + + config.dev = &pdev->dev; + config.init_data = &pu_dummy_initdata; + config.of_node = pdev->dev.of_node; + + pu_dummy_regulator_rdev = regulator_register(&pu_dummy_desc, &config); + if (IS_ERR(pu_dummy_regulator_rdev)) { + ret = PTR_ERR(pu_dummy_regulator_rdev); + dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct of_device_id imx_pudummy_ids[] = { + { .compatible = "fsl,imx6-dummy-pureg" }, +}; +MODULE_DEVICE_TABLE(of, imx_pudummy_ids); + +static struct platform_driver pu_dummy_driver = { + .probe = pu_dummy_probe, + .driver = { + .name = "pu-dummy", + .owner = THIS_MODULE, + .of_match_table = imx_pudummy_ids, + }, +}; + static int imx_gpc_probe(struct platform_device *pdev) { int ret; @@ -315,6 +408,11 @@ static int imx_gpc_probe(struct platform_device *pdev) gpc_dev = &pdev->dev; pu_reg = devm_regulator_get(gpc_dev, "pu"); + if (IS_ERR(pu_reg)) { + ret = PTR_ERR(pu_reg); + dev_info(gpc_dev, "pu regulator not ready.\n"); + return ret; + } nb.notifier_call = &imx_gpc_regulator_notify; /* Get gpu&vpu clk for power up PU by GPC */ @@ -369,6 +467,8 @@ static struct platform_driver imx_gpc_platdrv = { }; module_platform_driver(imx_gpc_platdrv); +module_platform_driver(pu_dummy_driver); + MODULE_AUTHOR("Anson Huang "); MODULE_DESCRIPTION("Freescale i.MX GPC driver"); MODULE_LICENSE("GPL"); -- 2.39.5