162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. 462306a36Sopenharmony_ci * Copyright (c) 2014,2015, Linaro Ltd. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * SAW power controller driver 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/kernel.h> 1062306a36Sopenharmony_ci#include <linux/init.h> 1162306a36Sopenharmony_ci#include <linux/io.h> 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/of.h> 1562306a36Sopenharmony_ci#include <linux/err.h> 1662306a36Sopenharmony_ci#include <linux/platform_device.h> 1762306a36Sopenharmony_ci#include <soc/qcom/spm.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define SPM_CTL_INDEX 0x7f 2062306a36Sopenharmony_ci#define SPM_CTL_INDEX_SHIFT 4 2162306a36Sopenharmony_ci#define SPM_CTL_EN BIT(0) 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cienum spm_reg { 2462306a36Sopenharmony_ci SPM_REG_CFG, 2562306a36Sopenharmony_ci SPM_REG_SPM_CTL, 2662306a36Sopenharmony_ci SPM_REG_DLY, 2762306a36Sopenharmony_ci SPM_REG_PMIC_DLY, 2862306a36Sopenharmony_ci SPM_REG_PMIC_DATA_0, 2962306a36Sopenharmony_ci SPM_REG_PMIC_DATA_1, 3062306a36Sopenharmony_ci SPM_REG_VCTL, 3162306a36Sopenharmony_ci SPM_REG_SEQ_ENTRY, 3262306a36Sopenharmony_ci SPM_REG_SPM_STS, 3362306a36Sopenharmony_ci SPM_REG_PMIC_STS, 3462306a36Sopenharmony_ci SPM_REG_AVS_CTL, 3562306a36Sopenharmony_ci SPM_REG_AVS_LIMIT, 3662306a36Sopenharmony_ci SPM_REG_NR, 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic const u16 spm_reg_offset_v4_1[SPM_REG_NR] = { 4062306a36Sopenharmony_ci [SPM_REG_AVS_CTL] = 0x904, 4162306a36Sopenharmony_ci [SPM_REG_AVS_LIMIT] = 0x908, 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic const struct spm_reg_data spm_reg_660_gold_l2 = { 4562306a36Sopenharmony_ci .reg_offset = spm_reg_offset_v4_1, 4662306a36Sopenharmony_ci .avs_ctl = 0x1010031, 4762306a36Sopenharmony_ci .avs_limit = 0x4580458, 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic const struct spm_reg_data spm_reg_660_silver_l2 = { 5162306a36Sopenharmony_ci .reg_offset = spm_reg_offset_v4_1, 5262306a36Sopenharmony_ci .avs_ctl = 0x101c031, 5362306a36Sopenharmony_ci .avs_limit = 0x4580458, 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic const struct spm_reg_data spm_reg_8998_gold_l2 = { 5762306a36Sopenharmony_ci .reg_offset = spm_reg_offset_v4_1, 5862306a36Sopenharmony_ci .avs_ctl = 0x1010031, 5962306a36Sopenharmony_ci .avs_limit = 0x4700470, 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic const struct spm_reg_data spm_reg_8998_silver_l2 = { 6362306a36Sopenharmony_ci .reg_offset = spm_reg_offset_v4_1, 6462306a36Sopenharmony_ci .avs_ctl = 0x1010031, 6562306a36Sopenharmony_ci .avs_limit = 0x4200420, 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic const u16 spm_reg_offset_v3_0[SPM_REG_NR] = { 6962306a36Sopenharmony_ci [SPM_REG_CFG] = 0x08, 7062306a36Sopenharmony_ci [SPM_REG_SPM_CTL] = 0x30, 7162306a36Sopenharmony_ci [SPM_REG_DLY] = 0x34, 7262306a36Sopenharmony_ci [SPM_REG_SEQ_ENTRY] = 0x400, 7362306a36Sopenharmony_ci}; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci/* SPM register data for 8909 */ 7662306a36Sopenharmony_cistatic const struct spm_reg_data spm_reg_8909_cpu = { 7762306a36Sopenharmony_ci .reg_offset = spm_reg_offset_v3_0, 7862306a36Sopenharmony_ci .spm_cfg = 0x1, 7962306a36Sopenharmony_ci .spm_dly = 0x3C102800, 8062306a36Sopenharmony_ci .seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x10, 0x80, 0x30, 0x90, 8162306a36Sopenharmony_ci 0x5B, 0x60, 0x03, 0x60, 0x76, 0x76, 0x0B, 0x94, 0x5B, 0x80, 8262306a36Sopenharmony_ci 0x10, 0x26, 0x30, 0x0F }, 8362306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_STBY] = 0, 8462306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_SPC] = 5, 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci/* SPM register data for 8916 */ 8862306a36Sopenharmony_cistatic const struct spm_reg_data spm_reg_8916_cpu = { 8962306a36Sopenharmony_ci .reg_offset = spm_reg_offset_v3_0, 9062306a36Sopenharmony_ci .spm_cfg = 0x1, 9162306a36Sopenharmony_ci .spm_dly = 0x3C102800, 9262306a36Sopenharmony_ci .seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x10, 0x80, 0x30, 0x90, 9362306a36Sopenharmony_ci 0x5B, 0x60, 0x03, 0x60, 0x3B, 0x76, 0x76, 0x0B, 0x94, 0x5B, 9462306a36Sopenharmony_ci 0x80, 0x10, 0x26, 0x30, 0x0F }, 9562306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_STBY] = 0, 9662306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_SPC] = 5, 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic const struct spm_reg_data spm_reg_8939_cpu = { 10062306a36Sopenharmony_ci .reg_offset = spm_reg_offset_v3_0, 10162306a36Sopenharmony_ci .spm_cfg = 0x1, 10262306a36Sopenharmony_ci .spm_dly = 0x3C102800, 10362306a36Sopenharmony_ci .seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x50, 0x1B, 0x10, 0x80, 10462306a36Sopenharmony_ci 0x30, 0x90, 0x5B, 0x60, 0x50, 0x03, 0x60, 0x76, 0x76, 0x0B, 10562306a36Sopenharmony_ci 0x50, 0x1B, 0x94, 0x5B, 0x80, 0x10, 0x26, 0x30, 0x50, 0x0F }, 10662306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_STBY] = 0, 10762306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_SPC] = 5, 10862306a36Sopenharmony_ci}; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic const u16 spm_reg_offset_v2_3[SPM_REG_NR] = { 11162306a36Sopenharmony_ci [SPM_REG_CFG] = 0x08, 11262306a36Sopenharmony_ci [SPM_REG_SPM_CTL] = 0x30, 11362306a36Sopenharmony_ci [SPM_REG_DLY] = 0x34, 11462306a36Sopenharmony_ci [SPM_REG_PMIC_DATA_0] = 0x40, 11562306a36Sopenharmony_ci [SPM_REG_PMIC_DATA_1] = 0x44, 11662306a36Sopenharmony_ci}; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci/* SPM register data for 8976 */ 11962306a36Sopenharmony_cistatic const struct spm_reg_data spm_reg_8976_gold_l2 = { 12062306a36Sopenharmony_ci .reg_offset = spm_reg_offset_v2_3, 12162306a36Sopenharmony_ci .spm_cfg = 0x14, 12262306a36Sopenharmony_ci .spm_dly = 0x3c11840a, 12362306a36Sopenharmony_ci .pmic_data[0] = 0x03030080, 12462306a36Sopenharmony_ci .pmic_data[1] = 0x00030000, 12562306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_STBY] = 0, 12662306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_SPC] = 3, 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic const struct spm_reg_data spm_reg_8976_silver_l2 = { 13062306a36Sopenharmony_ci .reg_offset = spm_reg_offset_v2_3, 13162306a36Sopenharmony_ci .spm_cfg = 0x14, 13262306a36Sopenharmony_ci .spm_dly = 0x3c102800, 13362306a36Sopenharmony_ci .pmic_data[0] = 0x03030080, 13462306a36Sopenharmony_ci .pmic_data[1] = 0x00030000, 13562306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_STBY] = 0, 13662306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_SPC] = 2, 13762306a36Sopenharmony_ci}; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic const u16 spm_reg_offset_v2_1[SPM_REG_NR] = { 14062306a36Sopenharmony_ci [SPM_REG_CFG] = 0x08, 14162306a36Sopenharmony_ci [SPM_REG_SPM_CTL] = 0x30, 14262306a36Sopenharmony_ci [SPM_REG_DLY] = 0x34, 14362306a36Sopenharmony_ci [SPM_REG_SEQ_ENTRY] = 0x80, 14462306a36Sopenharmony_ci}; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci/* SPM register data for 8974, 8084 */ 14762306a36Sopenharmony_cistatic const struct spm_reg_data spm_reg_8974_8084_cpu = { 14862306a36Sopenharmony_ci .reg_offset = spm_reg_offset_v2_1, 14962306a36Sopenharmony_ci .spm_cfg = 0x1, 15062306a36Sopenharmony_ci .spm_dly = 0x3C102800, 15162306a36Sopenharmony_ci .seq = { 0x03, 0x0B, 0x0F, 0x00, 0x20, 0x80, 0x10, 0xE8, 0x5B, 0x03, 15262306a36Sopenharmony_ci 0x3B, 0xE8, 0x5B, 0x82, 0x10, 0x0B, 0x30, 0x06, 0x26, 0x30, 15362306a36Sopenharmony_ci 0x0F }, 15462306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_STBY] = 0, 15562306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_SPC] = 3, 15662306a36Sopenharmony_ci}; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci/* SPM register data for 8226 */ 15962306a36Sopenharmony_cistatic const struct spm_reg_data spm_reg_8226_cpu = { 16062306a36Sopenharmony_ci .reg_offset = spm_reg_offset_v2_1, 16162306a36Sopenharmony_ci .spm_cfg = 0x0, 16262306a36Sopenharmony_ci .spm_dly = 0x3C102800, 16362306a36Sopenharmony_ci .seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x10, 0x80, 0x30, 0x90, 16462306a36Sopenharmony_ci 0x5B, 0x60, 0x03, 0x60, 0x3B, 0x76, 0x76, 0x0B, 0x94, 0x5B, 16562306a36Sopenharmony_ci 0x80, 0x10, 0x26, 0x30, 0x0F }, 16662306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_STBY] = 0, 16762306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_SPC] = 5, 16862306a36Sopenharmony_ci}; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic const u16 spm_reg_offset_v1_1[SPM_REG_NR] = { 17162306a36Sopenharmony_ci [SPM_REG_CFG] = 0x08, 17262306a36Sopenharmony_ci [SPM_REG_SPM_CTL] = 0x20, 17362306a36Sopenharmony_ci [SPM_REG_PMIC_DLY] = 0x24, 17462306a36Sopenharmony_ci [SPM_REG_PMIC_DATA_0] = 0x28, 17562306a36Sopenharmony_ci [SPM_REG_PMIC_DATA_1] = 0x2C, 17662306a36Sopenharmony_ci [SPM_REG_SEQ_ENTRY] = 0x80, 17762306a36Sopenharmony_ci}; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci/* SPM register data for 8064 */ 18062306a36Sopenharmony_cistatic const struct spm_reg_data spm_reg_8064_cpu = { 18162306a36Sopenharmony_ci .reg_offset = spm_reg_offset_v1_1, 18262306a36Sopenharmony_ci .spm_cfg = 0x1F, 18362306a36Sopenharmony_ci .pmic_dly = 0x02020004, 18462306a36Sopenharmony_ci .pmic_data[0] = 0x0084009C, 18562306a36Sopenharmony_ci .pmic_data[1] = 0x00A4001C, 18662306a36Sopenharmony_ci .seq = { 0x03, 0x0F, 0x00, 0x24, 0x54, 0x10, 0x09, 0x03, 0x01, 18762306a36Sopenharmony_ci 0x10, 0x54, 0x30, 0x0C, 0x24, 0x30, 0x0F }, 18862306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_STBY] = 0, 18962306a36Sopenharmony_ci .start_index[PM_SLEEP_MODE_SPC] = 2, 19062306a36Sopenharmony_ci}; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic inline void spm_register_write(struct spm_driver_data *drv, 19362306a36Sopenharmony_ci enum spm_reg reg, u32 val) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci if (drv->reg_data->reg_offset[reg]) 19662306a36Sopenharmony_ci writel_relaxed(val, drv->reg_base + 19762306a36Sopenharmony_ci drv->reg_data->reg_offset[reg]); 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci/* Ensure a guaranteed write, before return */ 20162306a36Sopenharmony_cistatic inline void spm_register_write_sync(struct spm_driver_data *drv, 20262306a36Sopenharmony_ci enum spm_reg reg, u32 val) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci u32 ret; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci if (!drv->reg_data->reg_offset[reg]) 20762306a36Sopenharmony_ci return; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci do { 21062306a36Sopenharmony_ci writel_relaxed(val, drv->reg_base + 21162306a36Sopenharmony_ci drv->reg_data->reg_offset[reg]); 21262306a36Sopenharmony_ci ret = readl_relaxed(drv->reg_base + 21362306a36Sopenharmony_ci drv->reg_data->reg_offset[reg]); 21462306a36Sopenharmony_ci if (ret == val) 21562306a36Sopenharmony_ci break; 21662306a36Sopenharmony_ci cpu_relax(); 21762306a36Sopenharmony_ci } while (1); 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic inline u32 spm_register_read(struct spm_driver_data *drv, 22162306a36Sopenharmony_ci enum spm_reg reg) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci return readl_relaxed(drv->reg_base + drv->reg_data->reg_offset[reg]); 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_civoid spm_set_low_power_mode(struct spm_driver_data *drv, 22762306a36Sopenharmony_ci enum pm_sleep_mode mode) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci u32 start_index; 23062306a36Sopenharmony_ci u32 ctl_val; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci start_index = drv->reg_data->start_index[mode]; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci ctl_val = spm_register_read(drv, SPM_REG_SPM_CTL); 23562306a36Sopenharmony_ci ctl_val &= ~(SPM_CTL_INDEX << SPM_CTL_INDEX_SHIFT); 23662306a36Sopenharmony_ci ctl_val |= start_index << SPM_CTL_INDEX_SHIFT; 23762306a36Sopenharmony_ci ctl_val |= SPM_CTL_EN; 23862306a36Sopenharmony_ci spm_register_write_sync(drv, SPM_REG_SPM_CTL, ctl_val); 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic const struct of_device_id spm_match_table[] = { 24262306a36Sopenharmony_ci { .compatible = "qcom,sdm660-gold-saw2-v4.1-l2", 24362306a36Sopenharmony_ci .data = &spm_reg_660_gold_l2 }, 24462306a36Sopenharmony_ci { .compatible = "qcom,sdm660-silver-saw2-v4.1-l2", 24562306a36Sopenharmony_ci .data = &spm_reg_660_silver_l2 }, 24662306a36Sopenharmony_ci { .compatible = "qcom,msm8226-saw2-v2.1-cpu", 24762306a36Sopenharmony_ci .data = &spm_reg_8226_cpu }, 24862306a36Sopenharmony_ci { .compatible = "qcom,msm8909-saw2-v3.0-cpu", 24962306a36Sopenharmony_ci .data = &spm_reg_8909_cpu }, 25062306a36Sopenharmony_ci { .compatible = "qcom,msm8916-saw2-v3.0-cpu", 25162306a36Sopenharmony_ci .data = &spm_reg_8916_cpu }, 25262306a36Sopenharmony_ci { .compatible = "qcom,msm8939-saw2-v3.0-cpu", 25362306a36Sopenharmony_ci .data = &spm_reg_8939_cpu }, 25462306a36Sopenharmony_ci { .compatible = "qcom,msm8974-saw2-v2.1-cpu", 25562306a36Sopenharmony_ci .data = &spm_reg_8974_8084_cpu }, 25662306a36Sopenharmony_ci { .compatible = "qcom,msm8976-gold-saw2-v2.3-l2", 25762306a36Sopenharmony_ci .data = &spm_reg_8976_gold_l2 }, 25862306a36Sopenharmony_ci { .compatible = "qcom,msm8976-silver-saw2-v2.3-l2", 25962306a36Sopenharmony_ci .data = &spm_reg_8976_silver_l2 }, 26062306a36Sopenharmony_ci { .compatible = "qcom,msm8998-gold-saw2-v4.1-l2", 26162306a36Sopenharmony_ci .data = &spm_reg_8998_gold_l2 }, 26262306a36Sopenharmony_ci { .compatible = "qcom,msm8998-silver-saw2-v4.1-l2", 26362306a36Sopenharmony_ci .data = &spm_reg_8998_silver_l2 }, 26462306a36Sopenharmony_ci { .compatible = "qcom,apq8084-saw2-v2.1-cpu", 26562306a36Sopenharmony_ci .data = &spm_reg_8974_8084_cpu }, 26662306a36Sopenharmony_ci { .compatible = "qcom,apq8064-saw2-v1.1-cpu", 26762306a36Sopenharmony_ci .data = &spm_reg_8064_cpu }, 26862306a36Sopenharmony_ci { }, 26962306a36Sopenharmony_ci}; 27062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, spm_match_table); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cistatic int spm_dev_probe(struct platform_device *pdev) 27362306a36Sopenharmony_ci{ 27462306a36Sopenharmony_ci const struct of_device_id *match_id; 27562306a36Sopenharmony_ci struct spm_driver_data *drv; 27662306a36Sopenharmony_ci void __iomem *addr; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); 27962306a36Sopenharmony_ci if (!drv) 28062306a36Sopenharmony_ci return -ENOMEM; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci drv->reg_base = devm_platform_ioremap_resource(pdev, 0); 28362306a36Sopenharmony_ci if (IS_ERR(drv->reg_base)) 28462306a36Sopenharmony_ci return PTR_ERR(drv->reg_base); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci match_id = of_match_node(spm_match_table, pdev->dev.of_node); 28762306a36Sopenharmony_ci if (!match_id) 28862306a36Sopenharmony_ci return -ENODEV; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci drv->reg_data = match_id->data; 29162306a36Sopenharmony_ci platform_set_drvdata(pdev, drv); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci /* Write the SPM sequences first.. */ 29462306a36Sopenharmony_ci addr = drv->reg_base + drv->reg_data->reg_offset[SPM_REG_SEQ_ENTRY]; 29562306a36Sopenharmony_ci __iowrite32_copy(addr, drv->reg_data->seq, 29662306a36Sopenharmony_ci ARRAY_SIZE(drv->reg_data->seq) / 4); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci /* 29962306a36Sopenharmony_ci * ..and then the control registers. 30062306a36Sopenharmony_ci * On some SoC if the control registers are written first and if the 30162306a36Sopenharmony_ci * CPU was held in reset, the reset signal could trigger the SPM state 30262306a36Sopenharmony_ci * machine, before the sequences are completely written. 30362306a36Sopenharmony_ci */ 30462306a36Sopenharmony_ci spm_register_write(drv, SPM_REG_AVS_CTL, drv->reg_data->avs_ctl); 30562306a36Sopenharmony_ci spm_register_write(drv, SPM_REG_AVS_LIMIT, drv->reg_data->avs_limit); 30662306a36Sopenharmony_ci spm_register_write(drv, SPM_REG_CFG, drv->reg_data->spm_cfg); 30762306a36Sopenharmony_ci spm_register_write(drv, SPM_REG_DLY, drv->reg_data->spm_dly); 30862306a36Sopenharmony_ci spm_register_write(drv, SPM_REG_PMIC_DLY, drv->reg_data->pmic_dly); 30962306a36Sopenharmony_ci spm_register_write(drv, SPM_REG_PMIC_DATA_0, 31062306a36Sopenharmony_ci drv->reg_data->pmic_data[0]); 31162306a36Sopenharmony_ci spm_register_write(drv, SPM_REG_PMIC_DATA_1, 31262306a36Sopenharmony_ci drv->reg_data->pmic_data[1]); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci /* Set up Standby as the default low power mode */ 31562306a36Sopenharmony_ci if (drv->reg_data->reg_offset[SPM_REG_SPM_CTL]) 31662306a36Sopenharmony_ci spm_set_low_power_mode(drv, PM_SLEEP_MODE_STBY); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci return 0; 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_cistatic struct platform_driver spm_driver = { 32262306a36Sopenharmony_ci .probe = spm_dev_probe, 32362306a36Sopenharmony_ci .driver = { 32462306a36Sopenharmony_ci .name = "qcom_spm", 32562306a36Sopenharmony_ci .of_match_table = spm_match_table, 32662306a36Sopenharmony_ci }, 32762306a36Sopenharmony_ci}; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cistatic int __init qcom_spm_init(void) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci return platform_driver_register(&spm_driver); 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ciarch_initcall(qcom_spm_init); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 336