linux/arch/arm/mach-omap2/omap_twl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/**
   3 * OMAP and TWL PMIC specific initializations.
   4 *
   5 * Copyright (C) 2010 Texas Instruments Incorporated.
   6 * Thara Gopinath
   7 * Copyright (C) 2009 Texas Instruments Incorporated.
   8 * Nishanth Menon
   9 * Copyright (C) 2009 Nokia Corporation
  10 * Paul Walmsley
  11 */
  12
  13#include <linux/err.h>
  14#include <linux/io.h>
  15#include <linux/kernel.h>
  16#include <linux/mfd/twl.h>
  17
  18#include "soc.h"
  19#include "voltage.h"
  20
  21#include "pm.h"
  22
  23#define OMAP3_SRI2C_SLAVE_ADDR          0x12
  24#define OMAP3_VDD_MPU_SR_CONTROL_REG    0x00
  25#define OMAP3_VDD_CORE_SR_CONTROL_REG   0x01
  26#define OMAP3_VP_CONFIG_ERROROFFSET     0x00
  27#define OMAP3_VP_VSTEPMIN_VSTEPMIN      0x1
  28#define OMAP3_VP_VSTEPMAX_VSTEPMAX      0x04
  29#define OMAP3_VP_VLIMITTO_TIMEOUT_US    200
  30
  31#define OMAP4_SRI2C_SLAVE_ADDR          0x12
  32#define OMAP4_VDD_MPU_SR_VOLT_REG       0x55
  33#define OMAP4_VDD_MPU_SR_CMD_REG        0x56
  34#define OMAP4_VDD_IVA_SR_VOLT_REG       0x5B
  35#define OMAP4_VDD_IVA_SR_CMD_REG        0x5C
  36#define OMAP4_VDD_CORE_SR_VOLT_REG      0x61
  37#define OMAP4_VDD_CORE_SR_CMD_REG       0x62
  38
  39#define OMAP4_VP_CONFIG_ERROROFFSET     0x00
  40#define OMAP4_VP_VSTEPMIN_VSTEPMIN      0x01
  41#define OMAP4_VP_VSTEPMAX_VSTEPMAX      0x04
  42#define OMAP4_VP_VLIMITTO_TIMEOUT_US    200
  43
  44static bool is_offset_valid;
  45static u8 smps_offset;
  46
  47#define REG_SMPS_OFFSET         0xE0
  48
  49static unsigned long twl4030_vsel_to_uv(const u8 vsel)
  50{
  51        return (((vsel * 125) + 6000)) * 100;
  52}
  53
  54static u8 twl4030_uv_to_vsel(unsigned long uv)
  55{
  56        return DIV_ROUND_UP(uv - 600000, 12500);
  57}
  58
  59static unsigned long twl6030_vsel_to_uv(const u8 vsel)
  60{
  61        /*
  62         * In TWL6030 depending on the value of SMPS_OFFSET
  63         * efuse register the voltage range supported in
  64         * standard mode can be either between 0.6V - 1.3V or
  65         * 0.7V - 1.4V. In TWL6030 ES1.0 SMPS_OFFSET efuse
  66         * is programmed to all 0's where as starting from
  67         * TWL6030 ES1.1 the efuse is programmed to 1
  68         */
  69        if (!is_offset_valid) {
  70                twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset,
  71                                REG_SMPS_OFFSET);
  72                is_offset_valid = true;
  73        }
  74
  75        if (!vsel)
  76                return 0;
  77        /*
  78         * There is no specific formula for voltage to vsel
  79         * conversion above 1.3V. There are special hardcoded
  80         * values for voltages above 1.3V. Currently we are
  81         * hardcoding only for 1.35 V which is used for 1GH OPP for
  82         * OMAP4430.
  83         */
  84        if (vsel == 0x3A)
  85                return 1350000;
  86
  87        if (smps_offset & 0x8)
  88                return ((((vsel - 1) * 1266) + 70900)) * 10;
  89        else
  90                return ((((vsel - 1) * 1266) + 60770)) * 10;
  91}
  92
  93static u8 twl6030_uv_to_vsel(unsigned long uv)
  94{
  95        /*
  96         * In TWL6030 depending on the value of SMPS_OFFSET
  97         * efuse register the voltage range supported in
  98         * standard mode can be either between 0.6V - 1.3V or
  99         * 0.7V - 1.4V. In TWL6030 ES1.0 SMPS_OFFSET efuse
 100         * is programmed to all 0's where as starting from
 101         * TWL6030 ES1.1 the efuse is programmed to 1
 102         */
 103        if (!is_offset_valid) {
 104                twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset,
 105                                REG_SMPS_OFFSET);
 106                is_offset_valid = true;
 107        }
 108
 109        if (!uv)
 110                return 0x00;
 111        /*
 112         * There is no specific formula for voltage to vsel
 113         * conversion above 1.3V. There are special hardcoded
 114         * values for voltages above 1.3V. Currently we are
 115         * hardcoding only for 1.35 V which is used for 1GH OPP for
 116         * OMAP4430.
 117         */
 118        if (uv > twl6030_vsel_to_uv(0x39)) {
 119                if (uv == 1350000)
 120                        return 0x3A;
 121                pr_err("%s:OUT OF RANGE! non mapped vsel for %ld Vs max %ld\n",
 122                        __func__, uv, twl6030_vsel_to_uv(0x39));
 123                return 0x3A;
 124        }
 125
 126        if (smps_offset & 0x8)
 127                return DIV_ROUND_UP(uv - 709000, 12660) + 1;
 128        else
 129                return DIV_ROUND_UP(uv - 607700, 12660) + 1;
 130}
 131
 132static struct omap_voltdm_pmic omap3_mpu_pmic = {
 133        .slew_rate              = 4000,
 134        .step_size              = 12500,
 135        .vp_erroroffset         = OMAP3_VP_CONFIG_ERROROFFSET,
 136        .vp_vstepmin            = OMAP3_VP_VSTEPMIN_VSTEPMIN,
 137        .vp_vstepmax            = OMAP3_VP_VSTEPMAX_VSTEPMAX,
 138        .vddmin                 = 600000,
 139        .vddmax                 = 1450000,
 140        .vp_timeout_us          = OMAP3_VP_VLIMITTO_TIMEOUT_US,
 141        .i2c_slave_addr         = OMAP3_SRI2C_SLAVE_ADDR,
 142        .volt_reg_addr          = OMAP3_VDD_MPU_SR_CONTROL_REG,
 143        .i2c_high_speed         = true,
 144        .vsel_to_uv             = twl4030_vsel_to_uv,
 145        .uv_to_vsel             = twl4030_uv_to_vsel,
 146};
 147
 148static struct omap_voltdm_pmic omap3_core_pmic = {
 149        .slew_rate              = 4000,
 150        .step_size              = 12500,
 151        .vp_erroroffset         = OMAP3_VP_CONFIG_ERROROFFSET,
 152        .vp_vstepmin            = OMAP3_VP_VSTEPMIN_VSTEPMIN,
 153        .vp_vstepmax            = OMAP3_VP_VSTEPMAX_VSTEPMAX,
 154        .vddmin                 = 600000,
 155        .vddmax                 = 1450000,
 156        .vp_timeout_us          = OMAP3_VP_VLIMITTO_TIMEOUT_US,
 157        .i2c_slave_addr         = OMAP3_SRI2C_SLAVE_ADDR,
 158        .volt_reg_addr          = OMAP3_VDD_CORE_SR_CONTROL_REG,
 159        .i2c_high_speed         = true,
 160        .vsel_to_uv             = twl4030_vsel_to_uv,
 161        .uv_to_vsel             = twl4030_uv_to_vsel,
 162};
 163
 164static struct omap_voltdm_pmic omap4_mpu_pmic = {
 165        .slew_rate              = 4000,
 166        .step_size              = 12660,
 167        .vp_erroroffset         = OMAP4_VP_CONFIG_ERROROFFSET,
 168        .vp_vstepmin            = OMAP4_VP_VSTEPMIN_VSTEPMIN,
 169        .vp_vstepmax            = OMAP4_VP_VSTEPMAX_VSTEPMAX,
 170        .vddmin                 = 0,
 171        .vddmax                 = 2100000,
 172        .vp_timeout_us          = OMAP4_VP_VLIMITTO_TIMEOUT_US,
 173        .i2c_slave_addr         = OMAP4_SRI2C_SLAVE_ADDR,
 174        .volt_reg_addr          = OMAP4_VDD_MPU_SR_VOLT_REG,
 175        .cmd_reg_addr           = OMAP4_VDD_MPU_SR_CMD_REG,
 176        .i2c_high_speed         = true,
 177        .i2c_pad_load           = 3,
 178        .vsel_to_uv             = twl6030_vsel_to_uv,
 179        .uv_to_vsel             = twl6030_uv_to_vsel,
 180};
 181
 182static struct omap_voltdm_pmic omap4_iva_pmic = {
 183        .slew_rate              = 4000,
 184        .step_size              = 12660,
 185        .vp_erroroffset         = OMAP4_VP_CONFIG_ERROROFFSET,
 186        .vp_vstepmin            = OMAP4_VP_VSTEPMIN_VSTEPMIN,
 187        .vp_vstepmax            = OMAP4_VP_VSTEPMAX_VSTEPMAX,
 188        .vddmin                 = 0,
 189        .vddmax                 = 2100000,
 190        .vp_timeout_us          = OMAP4_VP_VLIMITTO_TIMEOUT_US,
 191        .i2c_slave_addr         = OMAP4_SRI2C_SLAVE_ADDR,
 192        .volt_reg_addr          = OMAP4_VDD_IVA_SR_VOLT_REG,
 193        .cmd_reg_addr           = OMAP4_VDD_IVA_SR_CMD_REG,
 194        .i2c_high_speed         = true,
 195        .i2c_pad_load           = 3,
 196        .vsel_to_uv             = twl6030_vsel_to_uv,
 197        .uv_to_vsel             = twl6030_uv_to_vsel,
 198};
 199
 200static struct omap_voltdm_pmic omap4_core_pmic = {
 201        .slew_rate              = 4000,
 202        .step_size              = 12660,
 203        .vp_erroroffset         = OMAP4_VP_CONFIG_ERROROFFSET,
 204        .vp_vstepmin            = OMAP4_VP_VSTEPMIN_VSTEPMIN,
 205        .vp_vstepmax            = OMAP4_VP_VSTEPMAX_VSTEPMAX,
 206        .vddmin                 = 0,
 207        .vddmax                 = 2100000,
 208        .vp_timeout_us          = OMAP4_VP_VLIMITTO_TIMEOUT_US,
 209        .i2c_slave_addr         = OMAP4_SRI2C_SLAVE_ADDR,
 210        .volt_reg_addr          = OMAP4_VDD_CORE_SR_VOLT_REG,
 211        .cmd_reg_addr           = OMAP4_VDD_CORE_SR_CMD_REG,
 212        .i2c_high_speed         = true,
 213        .i2c_pad_load           = 3,
 214        .vsel_to_uv             = twl6030_vsel_to_uv,
 215        .uv_to_vsel             = twl6030_uv_to_vsel,
 216};
 217
 218int __init omap4_twl_init(void)
 219{
 220        struct voltagedomain *voltdm;
 221
 222        if (!cpu_is_omap44xx())
 223                return -ENODEV;
 224
 225        voltdm = voltdm_lookup("mpu");
 226        omap_voltage_register_pmic(voltdm, &omap4_mpu_pmic);
 227
 228        voltdm = voltdm_lookup("iva");
 229        omap_voltage_register_pmic(voltdm, &omap4_iva_pmic);
 230
 231        voltdm = voltdm_lookup("core");
 232        omap_voltage_register_pmic(voltdm, &omap4_core_pmic);
 233
 234        return 0;
 235}
 236
 237int __init omap3_twl_init(void)
 238{
 239        struct voltagedomain *voltdm;
 240
 241        if (!cpu_is_omap34xx())
 242                return -ENODEV;
 243
 244        voltdm = voltdm_lookup("mpu_iva");
 245        omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic);
 246
 247        voltdm = voltdm_lookup("core");
 248        omap_voltage_register_pmic(voltdm, &omap3_core_pmic);
 249
 250        return 0;
 251}
 252