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