1d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/* 2d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * drivers/regulator/ab3100.c 3d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * 4d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * Copyright (C) 2008-2009 ST-Ericsson AB 5d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * License terms: GNU General Public License (GPL) version 2 6d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * Low-level control of the AB3100 IC Low Dropout (LDO) 7d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * regulators, external regulator and buck converter 8d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * Author: Mattias Wallin <mattias.wallin@stericsson.com> 9d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * Author: Linus Walleij <linus.walleij@stericsson.com> 10d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */ 11d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 12d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#include <linux/module.h> 13d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#include <linux/kernel.h> 14d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#include <linux/init.h> 15d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#include <linux/err.h> 16d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#include <linux/delay.h> 17d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#include <linux/platform_device.h> 18d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#include <linux/regulator/driver.h> 19812f9e9d424dde9ccb35975c0281edb6f8543735Linus Walleij#include <linux/mfd/abx500.h> 20d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 21d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/* LDO registers and some handy masking definitions for AB3100 */ 22d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_A 0x40 23d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_C 0x41 24d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_D 0x42 25d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_E 0x43 26d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_E_SLEEP 0x44 27d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_F 0x45 28d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_G 0x46 29d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_H 0x47 30d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_H_SLEEP_MODE 0 31d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_H_SLEEP_EN 2 32d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_ON 4 33d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_H_VSEL_AC 5 34d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_K 0x48 35d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_LDO_EXT 0x49 36d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_BUCK 0x4A 37d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_BUCK_SLEEP 0x4B 38d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define AB3100_REG_ON_MASK 0x10 39d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 40d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/** 41d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * struct ab3100_regulator 42d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * A struct passed around the individual regulator functions 43d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * @platform_device: platform device holding this regulator 44fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin * @dev: handle to the device 45d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * @plfdata: AB3100 platform data passed in at probe time 46d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * @regreg: regulator register number in the AB3100 47d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * @fixed_voltage: a fixed voltage for this regulator, if this 48d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * 0 the voltages array is used instead. 49d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * @typ_voltages: an array of available typical voltages for 50d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * this regulator 51d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * @voltages_len: length of the array of available voltages 52d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */ 53d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstruct ab3100_regulator { 54d619bc143e311a738113dbbe7792bd032403939fLinus Walleij struct regulator_dev *rdev; 55fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin struct device *dev; 56d619bc143e311a738113dbbe7792bd032403939fLinus Walleij struct ab3100_platform_data *plfdata; 57d619bc143e311a738113dbbe7792bd032403939fLinus Walleij u8 regreg; 58d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int fixed_voltage; 59d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int const *typ_voltages; 60d619bc143e311a738113dbbe7792bd032403939fLinus Walleij u8 voltages_len; 61d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}; 62d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 63d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/* The order in which registers are initialized */ 64d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic const u8 ab3100_reg_init_order[AB3100_NUM_REGULATORS+2] = { 65d619bc143e311a738113dbbe7792bd032403939fLinus Walleij AB3100_LDO_A, 66d619bc143e311a738113dbbe7792bd032403939fLinus Walleij AB3100_LDO_C, 67d619bc143e311a738113dbbe7792bd032403939fLinus Walleij AB3100_LDO_E, 68d619bc143e311a738113dbbe7792bd032403939fLinus Walleij AB3100_LDO_E_SLEEP, 69d619bc143e311a738113dbbe7792bd032403939fLinus Walleij AB3100_LDO_F, 70d619bc143e311a738113dbbe7792bd032403939fLinus Walleij AB3100_LDO_G, 71d619bc143e311a738113dbbe7792bd032403939fLinus Walleij AB3100_LDO_H, 72d619bc143e311a738113dbbe7792bd032403939fLinus Walleij AB3100_LDO_K, 73d619bc143e311a738113dbbe7792bd032403939fLinus Walleij AB3100_LDO_EXT, 74d619bc143e311a738113dbbe7792bd032403939fLinus Walleij AB3100_BUCK, 75d619bc143e311a738113dbbe7792bd032403939fLinus Walleij AB3100_BUCK_SLEEP, 76d619bc143e311a738113dbbe7792bd032403939fLinus Walleij AB3100_LDO_D, 77d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}; 78d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 79d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/* Preset (hardware defined) voltages for these regulators */ 80d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define LDO_A_VOLTAGE 2750000 81d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define LDO_C_VOLTAGE 2650000 82d619bc143e311a738113dbbe7792bd032403939fLinus Walleij#define LDO_D_VOLTAGE 2650000 83d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 849992ef40ff2e16559e49ff1ae63d133cb9849e8fMark Brownstatic const int ldo_e_buck_typ_voltages[] = { 85d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1800000, 86d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1400000, 87d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1300000, 88d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1200000, 89d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1100000, 90d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1050000, 91d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 900000, 92d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}; 93d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 949992ef40ff2e16559e49ff1ae63d133cb9849e8fMark Brownstatic const int ldo_f_typ_voltages[] = { 95d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1800000, 96d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1400000, 97d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1300000, 98d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1200000, 99d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1100000, 100d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1050000, 101d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 2500000, 102d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 2650000, 103d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}; 104d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1059992ef40ff2e16559e49ff1ae63d133cb9849e8fMark Brownstatic const int ldo_g_typ_voltages[] = { 106d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 2850000, 107d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 2750000, 108d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1800000, 109d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1500000, 110d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}; 111d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1129992ef40ff2e16559e49ff1ae63d133cb9849e8fMark Brownstatic const int ldo_h_typ_voltages[] = { 113d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 2750000, 114d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1800000, 115d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1500000, 116d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1200000, 117d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}; 118d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1199992ef40ff2e16559e49ff1ae63d133cb9849e8fMark Brownstatic const int ldo_k_typ_voltages[] = { 120d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 2750000, 121d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 1800000, 122d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}; 123d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 124d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 125d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/* The regulator devices */ 126d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic struct ab3100_regulator 127d619bc143e311a738113dbbe7792bd032403939fLinus Walleijab3100_regulators[AB3100_NUM_REGULATORS] = { 128d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 129d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .regreg = AB3100_LDO_A, 130d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .fixed_voltage = LDO_A_VOLTAGE, 131d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 132d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 133d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .regreg = AB3100_LDO_C, 134d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .fixed_voltage = LDO_C_VOLTAGE, 135d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 136d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 137d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .regreg = AB3100_LDO_D, 138d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .fixed_voltage = LDO_D_VOLTAGE, 139d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 140d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 141d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .regreg = AB3100_LDO_E, 142d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .typ_voltages = ldo_e_buck_typ_voltages, 143d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .voltages_len = ARRAY_SIZE(ldo_e_buck_typ_voltages), 144d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 145d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 146d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .regreg = AB3100_LDO_F, 147d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .typ_voltages = ldo_f_typ_voltages, 148d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .voltages_len = ARRAY_SIZE(ldo_f_typ_voltages), 149d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 150d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 151d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .regreg = AB3100_LDO_G, 152d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .typ_voltages = ldo_g_typ_voltages, 153d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .voltages_len = ARRAY_SIZE(ldo_g_typ_voltages), 154d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 155d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 156d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .regreg = AB3100_LDO_H, 157d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .typ_voltages = ldo_h_typ_voltages, 158d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .voltages_len = ARRAY_SIZE(ldo_h_typ_voltages), 159d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 160d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 161d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .regreg = AB3100_LDO_K, 162d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .typ_voltages = ldo_k_typ_voltages, 163d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .voltages_len = ARRAY_SIZE(ldo_k_typ_voltages), 164d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 165d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 166d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .regreg = AB3100_LDO_EXT, 167d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* No voltages for the external regulator */ 168d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 169d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 170d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .regreg = AB3100_BUCK, 171d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .typ_voltages = ldo_e_buck_typ_voltages, 172d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .voltages_len = ARRAY_SIZE(ldo_e_buck_typ_voltages), 173d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 174d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}; 175d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 176d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/* 177d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * General functions for enable, disable and is_enabled used for 178d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * LDO: A,C,E,F,G,H,K,EXT and BUCK 179d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */ 180d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_enable_regulator(struct regulator_dev *reg) 181d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{ 182d619bc143e311a738113dbbe7792bd032403939fLinus Walleij struct ab3100_regulator *abreg = reg->reg_data; 183d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int err; 184d619bc143e311a738113dbbe7792bd032403939fLinus Walleij u8 regval; 185d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 186fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg, 187d619bc143e311a738113dbbe7792bd032403939fLinus Walleij ®val); 188d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (err) { 189d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_warn(®->dev, "failed to get regid %d value\n", 190d619bc143e311a738113dbbe7792bd032403939fLinus Walleij abreg->regreg); 191d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return err; 192d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 193d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 194d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* The regulator is already on, no reason to go further */ 195d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (regval & AB3100_REG_ON_MASK) 196d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return 0; 197d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 198d619bc143e311a738113dbbe7792bd032403939fLinus Walleij regval |= AB3100_REG_ON_MASK; 199d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 200fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin err = abx500_set_register_interruptible(abreg->dev, 0, abreg->regreg, 201d619bc143e311a738113dbbe7792bd032403939fLinus Walleij regval); 202d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (err) { 203d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_warn(®->dev, "failed to set regid %d value\n", 204d619bc143e311a738113dbbe7792bd032403939fLinus Walleij abreg->regreg); 205d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return err; 206d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 207d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 208d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return 0; 209d619bc143e311a738113dbbe7792bd032403939fLinus Walleij} 210d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 211d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_disable_regulator(struct regulator_dev *reg) 212d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{ 213d619bc143e311a738113dbbe7792bd032403939fLinus Walleij struct ab3100_regulator *abreg = reg->reg_data; 214d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int err; 215d619bc143e311a738113dbbe7792bd032403939fLinus Walleij u8 regval; 216d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 217d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* 218d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * LDO D is a special regulator. When it is disabled, the entire 219d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * system is shut down. So this is handled specially. 220d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */ 221176f45b9c9b7e451ac46becb92110f5e2de02d8cLinus Walleij pr_info("Called ab3100_disable_regulator\n"); 222d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (abreg->regreg == AB3100_LDO_D) { 223d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_info(®->dev, "disabling LDO D - shut down system\n"); 224d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* Setting LDO D to 0x00 cuts the power to the SoC */ 225fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin return abx500_set_register_interruptible(abreg->dev, 0, 226d619bc143e311a738113dbbe7792bd032403939fLinus Walleij AB3100_LDO_D, 0x00U); 227d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 228d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 229d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* 230d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * All other regulators are handled here 231d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */ 232fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg, 233d619bc143e311a738113dbbe7792bd032403939fLinus Walleij ®val); 234d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (err) { 235d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_err(®->dev, "unable to get register 0x%x\n", 236d619bc143e311a738113dbbe7792bd032403939fLinus Walleij abreg->regreg); 237d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return err; 238d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 239d619bc143e311a738113dbbe7792bd032403939fLinus Walleij regval &= ~AB3100_REG_ON_MASK; 240fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin return abx500_set_register_interruptible(abreg->dev, 0, abreg->regreg, 241d619bc143e311a738113dbbe7792bd032403939fLinus Walleij regval); 242d619bc143e311a738113dbbe7792bd032403939fLinus Walleij} 243d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 244d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_is_enabled_regulator(struct regulator_dev *reg) 245d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{ 246d619bc143e311a738113dbbe7792bd032403939fLinus Walleij struct ab3100_regulator *abreg = reg->reg_data; 247d619bc143e311a738113dbbe7792bd032403939fLinus Walleij u8 regval; 248d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int err; 249d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 250fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg, 251d619bc143e311a738113dbbe7792bd032403939fLinus Walleij ®val); 252d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (err) { 253d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_err(®->dev, "unable to get register 0x%x\n", 254d619bc143e311a738113dbbe7792bd032403939fLinus Walleij abreg->regreg); 255d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return err; 256d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 257d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 258d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return regval & AB3100_REG_ON_MASK; 259d619bc143e311a738113dbbe7792bd032403939fLinus Walleij} 260d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 261d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_list_voltage_regulator(struct regulator_dev *reg, 262d619bc143e311a738113dbbe7792bd032403939fLinus Walleij unsigned selector) 263d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{ 264d619bc143e311a738113dbbe7792bd032403939fLinus Walleij struct ab3100_regulator *abreg = reg->reg_data; 265d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 266979da89a9c230381ca55ea0764428a5d42a01e7fAxel Lin if (selector >= abreg->voltages_len) 267d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return -EINVAL; 268d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return abreg->typ_voltages[selector]; 269d619bc143e311a738113dbbe7792bd032403939fLinus Walleij} 270d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 271d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_get_voltage_regulator(struct regulator_dev *reg) 272d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{ 273d619bc143e311a738113dbbe7792bd032403939fLinus Walleij struct ab3100_regulator *abreg = reg->reg_data; 274d619bc143e311a738113dbbe7792bd032403939fLinus Walleij u8 regval; 275d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int err; 276d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 277d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* Return the voltage for fixed regulators immediately */ 278d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (abreg->fixed_voltage) 279d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return abreg->fixed_voltage; 280d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 281d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* 282d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * For variable types, read out setting and index into 283d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * supplied voltage list. 284d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */ 285fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin err = abx500_get_register_interruptible(abreg->dev, 0, 286d619bc143e311a738113dbbe7792bd032403939fLinus Walleij abreg->regreg, ®val); 287d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (err) { 288d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_warn(®->dev, 289d619bc143e311a738113dbbe7792bd032403939fLinus Walleij "failed to get regulator value in register %02x\n", 290d619bc143e311a738113dbbe7792bd032403939fLinus Walleij abreg->regreg); 291d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return err; 292d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 293d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 294d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* The 3 highest bits index voltages */ 295d619bc143e311a738113dbbe7792bd032403939fLinus Walleij regval &= 0xE0; 296d619bc143e311a738113dbbe7792bd032403939fLinus Walleij regval >>= 5; 297d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 298979da89a9c230381ca55ea0764428a5d42a01e7fAxel Lin if (regval >= abreg->voltages_len) { 299d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_err(®->dev, 300d619bc143e311a738113dbbe7792bd032403939fLinus Walleij "regulator register %02x contains an illegal voltage setting\n", 301d619bc143e311a738113dbbe7792bd032403939fLinus Walleij abreg->regreg); 302d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return -EINVAL; 303d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 304d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 305d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return abreg->typ_voltages[regval]; 306d619bc143e311a738113dbbe7792bd032403939fLinus Walleij} 307d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 308d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_get_best_voltage_index(struct regulator_dev *reg, 309d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int min_uV, int max_uV) 310d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{ 311d619bc143e311a738113dbbe7792bd032403939fLinus Walleij struct ab3100_regulator *abreg = reg->reg_data; 312d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int i; 313d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int bestmatch; 314d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int bestindex; 315d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 316d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* 317d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * Locate the minimum voltage fitting the criteria on 318d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * this regulator. The switchable voltages are not 319d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * in strict falling order so we need to check them 320d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * all for the best match. 321d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */ 322d619bc143e311a738113dbbe7792bd032403939fLinus Walleij bestmatch = INT_MAX; 323d619bc143e311a738113dbbe7792bd032403939fLinus Walleij bestindex = -1; 324d619bc143e311a738113dbbe7792bd032403939fLinus Walleij for (i = 0; i < abreg->voltages_len; i++) { 325d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (abreg->typ_voltages[i] <= max_uV && 326d619bc143e311a738113dbbe7792bd032403939fLinus Walleij abreg->typ_voltages[i] >= min_uV && 327d619bc143e311a738113dbbe7792bd032403939fLinus Walleij abreg->typ_voltages[i] < bestmatch) { 328d619bc143e311a738113dbbe7792bd032403939fLinus Walleij bestmatch = abreg->typ_voltages[i]; 329d619bc143e311a738113dbbe7792bd032403939fLinus Walleij bestindex = i; 330d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 331d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 332d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 333d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (bestindex < 0) { 334d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_warn(®->dev, "requested %d<=x<=%d uV, out of range!\n", 335d619bc143e311a738113dbbe7792bd032403939fLinus Walleij min_uV, max_uV); 336d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return -EINVAL; 337d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 338d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return bestindex; 339d619bc143e311a738113dbbe7792bd032403939fLinus Walleij} 340d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 341d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_set_voltage_regulator(struct regulator_dev *reg, 3423a93f2a9f4d8f73d74c0e552feb68a10f778a219Mark Brown int min_uV, int max_uV, 3433a93f2a9f4d8f73d74c0e552feb68a10f778a219Mark Brown unsigned *selector) 344d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{ 345d619bc143e311a738113dbbe7792bd032403939fLinus Walleij struct ab3100_regulator *abreg = reg->reg_data; 346d619bc143e311a738113dbbe7792bd032403939fLinus Walleij u8 regval; 347d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int err; 348d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int bestindex; 349d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 350d619bc143e311a738113dbbe7792bd032403939fLinus Walleij bestindex = ab3100_get_best_voltage_index(reg, min_uV, max_uV); 351d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (bestindex < 0) 352d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return bestindex; 353d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 3543a93f2a9f4d8f73d74c0e552feb68a10f778a219Mark Brown *selector = bestindex; 3553a93f2a9f4d8f73d74c0e552feb68a10f778a219Mark Brown 356fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin err = abx500_get_register_interruptible(abreg->dev, 0, 357d619bc143e311a738113dbbe7792bd032403939fLinus Walleij abreg->regreg, ®val); 358d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (err) { 359d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_warn(®->dev, 360d619bc143e311a738113dbbe7792bd032403939fLinus Walleij "failed to get regulator register %02x\n", 361d619bc143e311a738113dbbe7792bd032403939fLinus Walleij abreg->regreg); 362d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return err; 363d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 364d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 365d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* The highest three bits control the variable regulators */ 366d619bc143e311a738113dbbe7792bd032403939fLinus Walleij regval &= ~0xE0; 367d619bc143e311a738113dbbe7792bd032403939fLinus Walleij regval |= (bestindex << 5); 368d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 369fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin err = abx500_set_register_interruptible(abreg->dev, 0, 370d619bc143e311a738113dbbe7792bd032403939fLinus Walleij abreg->regreg, regval); 371d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (err) 372d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_warn(®->dev, "failed to set regulator register %02x\n", 373d619bc143e311a738113dbbe7792bd032403939fLinus Walleij abreg->regreg); 374d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 375d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return err; 376d619bc143e311a738113dbbe7792bd032403939fLinus Walleij} 377d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 378d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg, 379d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int uV) 380d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{ 381d619bc143e311a738113dbbe7792bd032403939fLinus Walleij struct ab3100_regulator *abreg = reg->reg_data; 382d619bc143e311a738113dbbe7792bd032403939fLinus Walleij u8 regval; 383d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int err; 384d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int bestindex; 385d619bc143e311a738113dbbe7792bd032403939fLinus Walleij u8 targetreg; 386d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 387d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (abreg->regreg == AB3100_LDO_E) 388d619bc143e311a738113dbbe7792bd032403939fLinus Walleij targetreg = AB3100_LDO_E_SLEEP; 389d619bc143e311a738113dbbe7792bd032403939fLinus Walleij else if (abreg->regreg == AB3100_BUCK) 390d619bc143e311a738113dbbe7792bd032403939fLinus Walleij targetreg = AB3100_BUCK_SLEEP; 391d619bc143e311a738113dbbe7792bd032403939fLinus Walleij else 392d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return -EINVAL; 393d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 394d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* LDO E and BUCK have special suspend voltages you can set */ 395d619bc143e311a738113dbbe7792bd032403939fLinus Walleij bestindex = ab3100_get_best_voltage_index(reg, uV, uV); 396d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 397fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin err = abx500_get_register_interruptible(abreg->dev, 0, 398d619bc143e311a738113dbbe7792bd032403939fLinus Walleij targetreg, ®val); 399d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (err) { 400d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_warn(®->dev, 401d619bc143e311a738113dbbe7792bd032403939fLinus Walleij "failed to get regulator register %02x\n", 402d619bc143e311a738113dbbe7792bd032403939fLinus Walleij targetreg); 403d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return err; 404d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 405d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 406d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* The highest three bits control the variable regulators */ 407d619bc143e311a738113dbbe7792bd032403939fLinus Walleij regval &= ~0xE0; 408d619bc143e311a738113dbbe7792bd032403939fLinus Walleij regval |= (bestindex << 5); 409d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 410fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin err = abx500_set_register_interruptible(abreg->dev, 0, 411d619bc143e311a738113dbbe7792bd032403939fLinus Walleij targetreg, regval); 412d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (err) 413d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_warn(®->dev, "failed to set regulator register %02x\n", 414d619bc143e311a738113dbbe7792bd032403939fLinus Walleij abreg->regreg); 415d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 416d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return err; 417d619bc143e311a738113dbbe7792bd032403939fLinus Walleij} 418d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 419d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/* 420d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * The external regulator can just define a fixed voltage. 421d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */ 422d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic int ab3100_get_voltage_regulator_external(struct regulator_dev *reg) 423d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{ 424d619bc143e311a738113dbbe7792bd032403939fLinus Walleij struct ab3100_regulator *abreg = reg->reg_data; 425d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 426d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return abreg->plfdata->external_voltage; 427d619bc143e311a738113dbbe7792bd032403939fLinus Walleij} 428d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 42919c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleijstatic int ab3100_enable_time_regulator(struct regulator_dev *reg) 43019c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij{ 43119c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij struct ab3100_regulator *abreg = reg->reg_data; 43219c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij 43319c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij /* Per-regulator power on delay from spec */ 43419c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij switch (abreg->regreg) { 43519c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij case AB3100_LDO_A: /* Fallthrough */ 43619c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij case AB3100_LDO_C: /* Fallthrough */ 43719c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij case AB3100_LDO_D: /* Fallthrough */ 43819c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij case AB3100_LDO_E: /* Fallthrough */ 43919c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij case AB3100_LDO_H: /* Fallthrough */ 44019c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij case AB3100_LDO_K: 44119c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij return 200; 44219c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij case AB3100_LDO_F: 44319c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij return 600; 44419c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij case AB3100_LDO_G: 44519c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij return 400; 44619c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij case AB3100_BUCK: 44719c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij return 1000; 44819c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij default: 44919c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij break; 45019c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij } 45119c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij return 0; 45219c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij} 45319c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij 454d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic struct regulator_ops regulator_ops_fixed = { 455d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .enable = ab3100_enable_regulator, 456d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .disable = ab3100_disable_regulator, 457d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .is_enabled = ab3100_is_enabled_regulator, 458d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .get_voltage = ab3100_get_voltage_regulator, 45919c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij .enable_time = ab3100_enable_time_regulator, 460d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}; 461d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 462d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic struct regulator_ops regulator_ops_variable = { 463d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .enable = ab3100_enable_regulator, 464d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .disable = ab3100_disable_regulator, 465d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .is_enabled = ab3100_is_enabled_regulator, 466d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .get_voltage = ab3100_get_voltage_regulator, 467d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .set_voltage = ab3100_set_voltage_regulator, 468d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .list_voltage = ab3100_list_voltage_regulator, 46919c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij .enable_time = ab3100_enable_time_regulator, 470d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}; 471d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 472d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic struct regulator_ops regulator_ops_variable_sleepable = { 473d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .enable = ab3100_enable_regulator, 474d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .disable = ab3100_disable_regulator, 475d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .is_enabled = ab3100_is_enabled_regulator, 476d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .get_voltage = ab3100_get_voltage_regulator, 477d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .set_voltage = ab3100_set_voltage_regulator, 478d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .set_suspend_voltage = ab3100_set_suspend_voltage_regulator, 479d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .list_voltage = ab3100_list_voltage_regulator, 48019c98825941cb10b59c9953665fc4495bc82c0aeLinus Walleij .enable_time = ab3100_enable_time_regulator, 481d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}; 482d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 483d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/* 484d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * LDO EXT is an external regulator so it is really 485d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * not possible to set any voltage locally here, AB3100 486d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * is an on/off switch plain an simple. The external 487d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * voltage is defined in the board set-up if any. 488d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */ 489d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic struct regulator_ops regulator_ops_external = { 490d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .enable = ab3100_enable_regulator, 491d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .disable = ab3100_disable_regulator, 492d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .is_enabled = ab3100_is_enabled_regulator, 493d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .get_voltage = ab3100_get_voltage_regulator_external, 494d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}; 495d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 496d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic struct regulator_desc 497d619bc143e311a738113dbbe7792bd032403939fLinus Walleijab3100_regulator_desc[AB3100_NUM_REGULATORS] = { 498d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 499d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .name = "LDO_A", 500d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .id = AB3100_LDO_A, 501d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .ops = ®ulator_ops_fixed, 502d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .type = REGULATOR_VOLTAGE, 50364714354a45a58a072cfc926db0a078611a63d43Axel Lin .owner = THIS_MODULE, 504d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 505d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 506d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .name = "LDO_C", 507d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .id = AB3100_LDO_C, 508d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .ops = ®ulator_ops_fixed, 509d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .type = REGULATOR_VOLTAGE, 51064714354a45a58a072cfc926db0a078611a63d43Axel Lin .owner = THIS_MODULE, 511d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 512d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 513d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .name = "LDO_D", 514d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .id = AB3100_LDO_D, 515d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .ops = ®ulator_ops_fixed, 516d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .type = REGULATOR_VOLTAGE, 51764714354a45a58a072cfc926db0a078611a63d43Axel Lin .owner = THIS_MODULE, 518d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 519d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 520d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .name = "LDO_E", 521d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .id = AB3100_LDO_E, 522d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .ops = ®ulator_ops_variable_sleepable, 52375f2ba8f0006440e720e47ae14c917e07c452d72Linus Walleij .n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages), 524d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .type = REGULATOR_VOLTAGE, 52564714354a45a58a072cfc926db0a078611a63d43Axel Lin .owner = THIS_MODULE, 526d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 527d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 528d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .name = "LDO_F", 529d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .id = AB3100_LDO_F, 530d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .ops = ®ulator_ops_variable, 53175f2ba8f0006440e720e47ae14c917e07c452d72Linus Walleij .n_voltages = ARRAY_SIZE(ldo_f_typ_voltages), 532d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .type = REGULATOR_VOLTAGE, 53364714354a45a58a072cfc926db0a078611a63d43Axel Lin .owner = THIS_MODULE, 534d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 535d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 536d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .name = "LDO_G", 537d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .id = AB3100_LDO_G, 538d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .ops = ®ulator_ops_variable, 53975f2ba8f0006440e720e47ae14c917e07c452d72Linus Walleij .n_voltages = ARRAY_SIZE(ldo_g_typ_voltages), 540d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .type = REGULATOR_VOLTAGE, 54164714354a45a58a072cfc926db0a078611a63d43Axel Lin .owner = THIS_MODULE, 542d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 543d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 544d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .name = "LDO_H", 545d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .id = AB3100_LDO_H, 546d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .ops = ®ulator_ops_variable, 54775f2ba8f0006440e720e47ae14c917e07c452d72Linus Walleij .n_voltages = ARRAY_SIZE(ldo_h_typ_voltages), 548d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .type = REGULATOR_VOLTAGE, 54964714354a45a58a072cfc926db0a078611a63d43Axel Lin .owner = THIS_MODULE, 550d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 551d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 552d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .name = "LDO_K", 553d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .id = AB3100_LDO_K, 554d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .ops = ®ulator_ops_variable, 55575f2ba8f0006440e720e47ae14c917e07c452d72Linus Walleij .n_voltages = ARRAY_SIZE(ldo_k_typ_voltages), 556d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .type = REGULATOR_VOLTAGE, 55764714354a45a58a072cfc926db0a078611a63d43Axel Lin .owner = THIS_MODULE, 558d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 559d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 560d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .name = "LDO_EXT", 561d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .id = AB3100_LDO_EXT, 562d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .ops = ®ulator_ops_external, 563d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .type = REGULATOR_VOLTAGE, 56464714354a45a58a072cfc926db0a078611a63d43Axel Lin .owner = THIS_MODULE, 565d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 566d619bc143e311a738113dbbe7792bd032403939fLinus Walleij { 567d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .name = "BUCK", 568d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .id = AB3100_BUCK, 569d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .ops = ®ulator_ops_variable_sleepable, 57075f2ba8f0006440e720e47ae14c917e07c452d72Linus Walleij .n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages), 571d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .type = REGULATOR_VOLTAGE, 57264714354a45a58a072cfc926db0a078611a63d43Axel Lin .owner = THIS_MODULE, 573d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 574d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}; 575d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 576d619bc143e311a738113dbbe7792bd032403939fLinus Walleij/* 577d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * NOTE: the following functions are regulators pluralis - it is the 578d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * binding to the AB3100 core driver and the parent platform device 579d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * for all the different regulators. 580d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */ 581d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 58298bf7c057b35eaf418ac063c4aba4f9f86220b09Dmitry Torokhovstatic int __devinit ab3100_regulators_probe(struct platform_device *pdev) 583d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{ 584a771e36e16e9fdacb2bb8d3b9be50be68f211b82Samuel Ortiz struct ab3100_platform_data *plfdata = pdev->dev.platform_data; 585d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int err = 0; 586d619bc143e311a738113dbbe7792bd032403939fLinus Walleij u8 data; 587d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int i; 588d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 589d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* Check chip state */ 590fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin err = abx500_get_register_interruptible(&pdev->dev, 0, 591d619bc143e311a738113dbbe7792bd032403939fLinus Walleij AB3100_LDO_D, &data); 592d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (err) { 593d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_err(&pdev->dev, "could not read initial status of LDO_D\n"); 594d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return err; 595d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 596d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (data & 0x10) 597d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_notice(&pdev->dev, 598d619bc143e311a738113dbbe7792bd032403939fLinus Walleij "chip is already in active mode (Warm start)\n"); 599d619bc143e311a738113dbbe7792bd032403939fLinus Walleij else 600d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_notice(&pdev->dev, 601d619bc143e311a738113dbbe7792bd032403939fLinus Walleij "chip is in inactive mode (Cold start)\n"); 602d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 603d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* Set up regulators */ 604d619bc143e311a738113dbbe7792bd032403939fLinus Walleij for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) { 605fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin err = abx500_set_register_interruptible(&pdev->dev, 0, 606d619bc143e311a738113dbbe7792bd032403939fLinus Walleij ab3100_reg_init_order[i], 607d619bc143e311a738113dbbe7792bd032403939fLinus Walleij plfdata->reg_initvals[i]); 608d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (err) { 609d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_err(&pdev->dev, "regulator initialization failed with error %d\n", 610d619bc143e311a738113dbbe7792bd032403939fLinus Walleij err); 611d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return err; 612d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 613d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 614d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 615d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* Register the regulators */ 616d619bc143e311a738113dbbe7792bd032403939fLinus Walleij for (i = 0; i < AB3100_NUM_REGULATORS; i++) { 617d619bc143e311a738113dbbe7792bd032403939fLinus Walleij struct ab3100_regulator *reg = &ab3100_regulators[i]; 618d619bc143e311a738113dbbe7792bd032403939fLinus Walleij struct regulator_dev *rdev; 619d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 620d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* 621d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * Initialize per-regulator struct. 622d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * Inherit platform data, this comes down from the 623d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * i2c boarddata, from the machine. So if you want to 624d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * see what it looks like for a certain machine, go 625d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * into the machine I2C setup. 626d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */ 627fa661258a27aa74aaf741882053d195291cefb75Mattias Wallin reg->dev = &pdev->dev; 628d619bc143e311a738113dbbe7792bd032403939fLinus Walleij reg->plfdata = plfdata; 629d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 630d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* 631d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * Register the regulator, pass around 632d619bc143e311a738113dbbe7792bd032403939fLinus Walleij * the ab3100_regulator struct 633d619bc143e311a738113dbbe7792bd032403939fLinus Walleij */ 634d619bc143e311a738113dbbe7792bd032403939fLinus Walleij rdev = regulator_register(&ab3100_regulator_desc[i], 635d619bc143e311a738113dbbe7792bd032403939fLinus Walleij &pdev->dev, 636d619bc143e311a738113dbbe7792bd032403939fLinus Walleij &plfdata->reg_constraints[i], 6372c043bcbf287dc69848054d5c02c55c20f7a7bc5Rajendra Nayak reg, NULL); 638d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 639d619bc143e311a738113dbbe7792bd032403939fLinus Walleij if (IS_ERR(rdev)) { 640d619bc143e311a738113dbbe7792bd032403939fLinus Walleij err = PTR_ERR(rdev); 641d619bc143e311a738113dbbe7792bd032403939fLinus Walleij dev_err(&pdev->dev, 642d619bc143e311a738113dbbe7792bd032403939fLinus Walleij "%s: failed to register regulator %s err %d\n", 643d619bc143e311a738113dbbe7792bd032403939fLinus Walleij __func__, ab3100_regulator_desc[i].name, 644d619bc143e311a738113dbbe7792bd032403939fLinus Walleij err); 645d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* remove the already registered regulators */ 646b3fcf3e576749b911e984e752b6b390c326efb76Axel Lin while (--i >= 0) 647d619bc143e311a738113dbbe7792bd032403939fLinus Walleij regulator_unregister(ab3100_regulators[i].rdev); 648d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return err; 649d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 650d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 651d619bc143e311a738113dbbe7792bd032403939fLinus Walleij /* Then set a pointer back to the registered regulator */ 652d619bc143e311a738113dbbe7792bd032403939fLinus Walleij reg->rdev = rdev; 653d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 654d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 655d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return 0; 656d619bc143e311a738113dbbe7792bd032403939fLinus Walleij} 657d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 65898bf7c057b35eaf418ac063c4aba4f9f86220b09Dmitry Torokhovstatic int __devexit ab3100_regulators_remove(struct platform_device *pdev) 659d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{ 660d619bc143e311a738113dbbe7792bd032403939fLinus Walleij int i; 661d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 662d619bc143e311a738113dbbe7792bd032403939fLinus Walleij for (i = 0; i < AB3100_NUM_REGULATORS; i++) { 663d619bc143e311a738113dbbe7792bd032403939fLinus Walleij struct ab3100_regulator *reg = &ab3100_regulators[i]; 664d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 665d619bc143e311a738113dbbe7792bd032403939fLinus Walleij regulator_unregister(reg->rdev); 666d619bc143e311a738113dbbe7792bd032403939fLinus Walleij } 667d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return 0; 668d619bc143e311a738113dbbe7792bd032403939fLinus Walleij} 669d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 670d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic struct platform_driver ab3100_regulators_driver = { 671d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .driver = { 672d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .name = "ab3100-regulators", 673d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .owner = THIS_MODULE, 674d619bc143e311a738113dbbe7792bd032403939fLinus Walleij }, 675d619bc143e311a738113dbbe7792bd032403939fLinus Walleij .probe = ab3100_regulators_probe, 67698bf7c057b35eaf418ac063c4aba4f9f86220b09Dmitry Torokhov .remove = __devexit_p(ab3100_regulators_remove), 677d619bc143e311a738113dbbe7792bd032403939fLinus Walleij}; 678d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 679d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic __init int ab3100_regulators_init(void) 680d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{ 681d619bc143e311a738113dbbe7792bd032403939fLinus Walleij return platform_driver_register(&ab3100_regulators_driver); 682d619bc143e311a738113dbbe7792bd032403939fLinus Walleij} 683d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 684d619bc143e311a738113dbbe7792bd032403939fLinus Walleijstatic __exit void ab3100_regulators_exit(void) 685d619bc143e311a738113dbbe7792bd032403939fLinus Walleij{ 686176f45b9c9b7e451ac46becb92110f5e2de02d8cLinus Walleij platform_driver_unregister(&ab3100_regulators_driver); 687d619bc143e311a738113dbbe7792bd032403939fLinus Walleij} 688d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 689d619bc143e311a738113dbbe7792bd032403939fLinus Walleijsubsys_initcall(ab3100_regulators_init); 690d619bc143e311a738113dbbe7792bd032403939fLinus Walleijmodule_exit(ab3100_regulators_exit); 691d619bc143e311a738113dbbe7792bd032403939fLinus Walleij 692d619bc143e311a738113dbbe7792bd032403939fLinus WalleijMODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>"); 693d619bc143e311a738113dbbe7792bd032403939fLinus WalleijMODULE_DESCRIPTION("AB3100 Regulator driver"); 694d619bc143e311a738113dbbe7792bd032403939fLinus WalleijMODULE_LICENSE("GPL"); 695d619bc143e311a738113dbbe7792bd032403939fLinus WalleijMODULE_ALIAS("platform:ab3100-regulators"); 696