1da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown/* 2da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown * wm8350.c -- Voltage and current regulation for the Wolfson WM8350 PMIC 3da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown * 4da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown * Copyright 2007, 2008 Wolfson Microelectronics PLC. 5da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown * 6da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown * Author: Liam Girdwood 7da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown * linux@wolfsonmicro.com 8da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown * 9da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown * This program is free software; you can redistribute it and/or modify it 10da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown * under the terms of the GNU General Public License as published by the 11da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown * Free Software Foundation; either version 2 of the License, or (at your 12da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown * option) any later version. 13da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown */ 14da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 15da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown#include <linux/module.h> 16da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown#include <linux/moduleparam.h> 17da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown#include <linux/init.h> 18da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown#include <linux/bitops.h> 19da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown#include <linux/err.h> 20da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown#include <linux/i2c.h> 21da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown#include <linux/mfd/wm8350/core.h> 22da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown#include <linux/mfd/wm8350/pmic.h> 23da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown#include <linux/platform_device.h> 24da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown#include <linux/regulator/driver.h> 25da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown#include <linux/regulator/machine.h> 26da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 27221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown/* Maximum value possible for VSEL */ 28221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown#define WM8350_DCDC_MAX_VSEL 0x66 29221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown 30da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown/* Microamps */ 31da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic const int isink_cur[] = { 32da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 4, 33da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 5, 34da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 6, 35da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 7, 36da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 8, 37da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 10, 38da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 11, 39da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 14, 40da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 16, 41da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 19, 42da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 23, 43da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 27, 44da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 32, 45da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 39, 46da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 46, 47da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 54, 48da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 65, 49da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 77, 50da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 92, 51da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 109, 52da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 130, 53da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 154, 54da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 183, 55da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 218, 56da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 259, 57da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 308, 58da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 367, 59da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 436, 60da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 518, 61da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 616, 62da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 733, 63da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 872, 64da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1037, 65da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1233, 66da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1466, 67da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1744, 68da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 2073, 69da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 2466, 70da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 2933, 71da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 3487, 72da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 4147, 73da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 4932, 74da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 5865, 75da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 6975, 76da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 8294, 77da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 9864, 78da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 11730, 79da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 13949, 80da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 16589, 81da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 19728, 82da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 23460, 83da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 27899, 84da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 33178, 85da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 39455, 86da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 46920, 87da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 55798, 88da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 66355, 89da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 78910, 90da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 93840, 91da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 111596, 92da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 132710, 93da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 157820, 94da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 187681, 95da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 223191 96da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown}; 97da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 98da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int get_isink_val(int min_uA, int max_uA, u16 *setting) 99da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 100da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int i; 101da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1023a744038b3709cd467b693f3e146c6d5b8120a18Axel Lin for (i = 0; i < ARRAY_SIZE(isink_cur); i++) { 103da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (min_uA <= isink_cur[i] && max_uA >= isink_cur[i]) { 104da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown *setting = i; 105da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 106da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 107da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 108da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 109da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 110da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 111da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic inline int wm8350_ldo_val_to_mvolts(unsigned int val) 112da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 113da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (val < 16) 114da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return (val * 50) + 900; 115da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown else 116da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return ((val - 16) * 100) + 1800; 117da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 118da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 119da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 120da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic inline unsigned int wm8350_ldo_mvolts_to_val(int mV) 121da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 122da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (mV < 1800) 123da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return (mV - 900) / 50; 124da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown else 125da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return ((mV - 1800) / 100) + 16; 126da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 127da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 128da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic inline int wm8350_dcdc_val_to_mvolts(unsigned int val) 129da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 130da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return (val * 25) + 850; 131da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 132da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 133da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic inline unsigned int wm8350_dcdc_mvolts_to_val(int mV) 134da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 135da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return (mV - 850) / 25; 136da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 137da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 138da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_isink_set_current(struct regulator_dev *rdev, int min_uA, 139da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int max_uA) 140da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 141da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 142da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int isink = rdev_get_id(rdev); 143da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val, setting; 144da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int ret; 145da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 146da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown ret = get_isink_val(min_uA, max_uA, &setting); 147da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (ret != 0) 148da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return ret; 149da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 150da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (isink) { 151da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_ISINK_A: 152da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_A) & 153da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown ~WM8350_CS1_ISEL_MASK; 154da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_CURRENT_SINK_DRIVER_A, 155da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val | setting); 156da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 157da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_ISINK_B: 158da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_B) & 159da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown ~WM8350_CS1_ISEL_MASK; 160da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_CURRENT_SINK_DRIVER_B, 161da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val | setting); 162da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 163da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 164da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 165da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 166da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 167da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 168da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 169da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 170da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_isink_get_current(struct regulator_dev *rdev) 171da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 172da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 173da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int isink = rdev_get_id(rdev); 174da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 175da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 176da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (isink) { 177da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_ISINK_A: 178da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_A) & 179da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_CS1_ISEL_MASK; 180da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 181da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_ISINK_B: 182da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_B) & 183da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_CS1_ISEL_MASK; 184da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 185da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 186da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 187da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 188da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 189fa5a97bb0c65cb8d0382b72a55e2b87e15268289Axel Lin return isink_cur[val]; 190da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 191da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 192da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown/* turn on ISINK followed by DCDC */ 193da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_isink_enable(struct regulator_dev *rdev) 194da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 195da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 196da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int isink = rdev_get_id(rdev); 197da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 198da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (isink) { 199da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_ISINK_A: 200da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (wm8350->pmic.isink_A_dcdc) { 201da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_2: 202da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_5: 203da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_set_bits(wm8350, WM8350_POWER_MGMT_7, 204da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_CS1_ENA); 205da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_set_bits(wm8350, WM8350_CSA_FLASH_CONTROL, 206da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_CS1_DRIVE); 207da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 208da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1 << (wm8350->pmic.isink_A_dcdc - 209da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_DCDC_1)); 210da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 211da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 212da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 213da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 214da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 215da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_ISINK_B: 216da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (wm8350->pmic.isink_B_dcdc) { 217da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_2: 218da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_5: 219da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_set_bits(wm8350, WM8350_POWER_MGMT_7, 220da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_CS2_ENA); 221da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_set_bits(wm8350, WM8350_CSB_FLASH_CONTROL, 222da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_CS2_DRIVE); 223da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 224da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1 << (wm8350->pmic.isink_B_dcdc - 225da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_DCDC_1)); 226da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 227da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 228da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 229da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 230da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 231da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 232da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 233da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 234da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 235da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 236da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 237da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_isink_disable(struct regulator_dev *rdev) 238da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 239da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 240da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int isink = rdev_get_id(rdev); 241da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 242da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (isink) { 243da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_ISINK_A: 244da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (wm8350->pmic.isink_A_dcdc) { 245da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_2: 246da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_5: 247da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 248da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1 << (wm8350->pmic.isink_A_dcdc - 249da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_DCDC_1)); 250da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_7, 251da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_CS1_ENA); 252da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 253da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 254da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 255da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 256da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 257da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_ISINK_B: 258da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (wm8350->pmic.isink_B_dcdc) { 259da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_2: 260da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_5: 261da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 262da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1 << (wm8350->pmic.isink_B_dcdc - 263da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_DCDC_1)); 264da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_7, 265da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_CS2_ENA); 266da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 267da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 268da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 269da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 270da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 271da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 272da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 273da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 274da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 275da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 276da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 277da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_isink_is_enabled(struct regulator_dev *rdev) 278da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 279da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 280da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int isink = rdev_get_id(rdev); 281da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 282da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (isink) { 283da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_ISINK_A: 284da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_A) & 285da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 0x8000; 286da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_ISINK_B: 287da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_B) & 288da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 0x8000; 289da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 290da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 291da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 292da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 29375c8ac22e4b8ebea8169a090e64d034a96758644Mark Brownstatic int wm8350_isink_enable_time(struct regulator_dev *rdev) 29475c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown{ 29575c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 29675c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown int isink = rdev_get_id(rdev); 29775c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown int reg; 29875c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown 29975c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown switch (isink) { 30075c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown case WM8350_ISINK_A: 30175c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown reg = wm8350_reg_read(wm8350, WM8350_CSA_FLASH_CONTROL); 30275c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown break; 30375c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown case WM8350_ISINK_B: 30475c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown reg = wm8350_reg_read(wm8350, WM8350_CSB_FLASH_CONTROL); 30575c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown break; 30675c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown default: 30775c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown return -EINVAL; 30875c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown } 30975c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown 31075c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown if (reg & WM8350_CS1_FLASH_MODE) { 31175c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown switch (reg & WM8350_CS1_ON_RAMP_MASK) { 31275c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown case 0: 31375c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown return 0; 31475c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown case 1: 31575c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown return 1950; 31675c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown case 2: 31775c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown return 3910; 31875c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown case 3: 31975c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown return 7800; 32075c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown } 32175c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown } else { 32275c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown switch (reg & WM8350_CS1_ON_RAMP_MASK) { 32375c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown case 0: 32475c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown return 0; 32575c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown case 1: 32675c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown return 250000; 32775c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown case 2: 32875c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown return 500000; 32975c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown case 3: 33075c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown return 1000000; 33175c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown } 33275c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown } 33375c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown 33475c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown return -EINVAL; 33575c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown} 33675c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown 33775c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown 338da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownint wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode, 339da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 trigger, u16 duration, u16 on_ramp, u16 off_ramp, 340da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 drive) 341da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 342da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (isink) { 343da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_ISINK_A: 344da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_CSA_FLASH_CONTROL, 345da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown (mode ? WM8350_CS1_FLASH_MODE : 0) | 346da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown (trigger ? WM8350_CS1_TRIGSRC : 0) | 347da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown duration | on_ramp | off_ramp | drive); 348da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 349da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_ISINK_B: 350da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_CSB_FLASH_CONTROL, 351da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown (mode ? WM8350_CS2_FLASH_MODE : 0) | 352da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown (trigger ? WM8350_CS2_TRIGSRC : 0) | 353da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown duration | on_ramp | off_ramp | drive); 354da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 355da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 356da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 357da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 358da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 359da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 360da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark BrownEXPORT_SYMBOL_GPL(wm8350_isink_set_flash); 361da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 362da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV, 3633a93f2a9f4d8f73d74c0e552feb68a10f778a219Mark Brown int max_uV, unsigned *selector) 364da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 365da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 366da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int volt_reg, dcdc = rdev_get_id(rdev), mV, 367da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown min_mV = min_uV / 1000, max_mV = max_uV / 1000; 368da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 369da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 370da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (min_mV < 850 || min_mV > 4025) 371da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 372da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (max_mV < 850 || max_mV > 4025) 373da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 374da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 375da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* step size is 25mV */ 376da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown mV = (min_mV - 826) / 25; 377da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (wm8350_dcdc_val_to_mvolts(mV) > max_mV) 378da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 379da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown BUG_ON(wm8350_dcdc_val_to_mvolts(mV) < min_mV); 380da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 381da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (dcdc) { 382da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_1: 383da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_DCDC1_CONTROL; 384da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 385da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_3: 386da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_DCDC3_CONTROL; 387da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 388da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_4: 389da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_DCDC4_CONTROL; 390da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 391da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_6: 392da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_DCDC6_CONTROL; 393da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 394da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_2: 395da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_5: 396da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 397da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 398da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 399da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 4003a93f2a9f4d8f73d74c0e552feb68a10f778a219Mark Brown *selector = mV; 4013a93f2a9f4d8f73d74c0e552feb68a10f778a219Mark Brown 402da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* all DCDCs have same mV bits */ 403da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK; 404da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, volt_reg, val | mV); 405da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 406da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 407da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 408c24516a1d674b1d9d847fd736feca444bc249b12Mark Brownstatic int wm8350_dcdc_get_voltage_sel(struct regulator_dev *rdev) 409da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 410da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 411da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int volt_reg, dcdc = rdev_get_id(rdev); 412da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 413da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (dcdc) { 414da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_1: 415da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_DCDC1_CONTROL; 416da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 417da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_3: 418da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_DCDC3_CONTROL; 419da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 420da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_4: 421da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_DCDC4_CONTROL; 422da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 423da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_6: 424da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_DCDC6_CONTROL; 425da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 426da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_2: 427da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_5: 428da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 429da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 430da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 431da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 432da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* all DCDCs have same mV bits */ 433c24516a1d674b1d9d847fd736feca444bc249b12Mark Brown return wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK; 434da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 435da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 436221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brownstatic int wm8350_dcdc_list_voltage(struct regulator_dev *rdev, 437221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown unsigned selector) 438221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown{ 439221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown if (selector > WM8350_DCDC_MAX_VSEL) 440221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown return -EINVAL; 441221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown return wm8350_dcdc_val_to_mvolts(selector) * 1000; 442221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown} 443221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown 444da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV) 445da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 446da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 447da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int volt_reg, mV = uV / 1000, dcdc = rdev_get_id(rdev); 448da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 449da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 450da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, dcdc, mV); 451da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 452da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (mV && (mV < 850 || mV > 4025)) { 453da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown dev_err(wm8350->dev, 454da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown "DCDC%d suspend voltage %d mV out of range\n", 455da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown dcdc, mV); 456da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 457da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 458da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (mV == 0) 459da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown mV = 850; 460da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 461da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (dcdc) { 462da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_1: 463da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_DCDC1_LOW_POWER; 464da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 465da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_3: 466da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_DCDC3_LOW_POWER; 467da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 468da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_4: 469da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_DCDC4_LOW_POWER; 470da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 471da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_6: 472da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_DCDC6_LOW_POWER; 473da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 474da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_2: 475da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_5: 476da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 477da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 478da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 479da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 480da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* all DCDCs have same mV bits */ 481da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK; 482da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, volt_reg, 483da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val | wm8350_dcdc_mvolts_to_val(mV)); 484da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 485da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 486da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 487da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_dcdc_set_suspend_enable(struct regulator_dev *rdev) 488da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 489da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 490da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int dcdc = rdev_get_id(rdev); 491da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 492da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 493da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (dcdc) { 494da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_1: 495da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER) 496da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown & ~WM8350_DCDC_HIB_MODE_MASK; 497da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER, 498eb4168158f79237498e4d3ddcef6e9436db15a4aAxel Lin val | wm8350->pmic.dcdc1_hib_mode); 499da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 500da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_3: 501da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER) 502da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown & ~WM8350_DCDC_HIB_MODE_MASK; 503da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER, 504eb4168158f79237498e4d3ddcef6e9436db15a4aAxel Lin val | wm8350->pmic.dcdc3_hib_mode); 505da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 506da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_4: 507da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER) 508da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown & ~WM8350_DCDC_HIB_MODE_MASK; 509da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER, 510eb4168158f79237498e4d3ddcef6e9436db15a4aAxel Lin val | wm8350->pmic.dcdc4_hib_mode); 511da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 512da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_6: 513da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER) 514da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown & ~WM8350_DCDC_HIB_MODE_MASK; 515da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER, 516eb4168158f79237498e4d3ddcef6e9436db15a4aAxel Lin val | wm8350->pmic.dcdc6_hib_mode); 517da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 518da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_2: 519da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_5: 520da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 521da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 522da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 523da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 524da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 525da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 526da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 527da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_dcdc_set_suspend_disable(struct regulator_dev *rdev) 528da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 529da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 530da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int dcdc = rdev_get_id(rdev); 531da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 532da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 533da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (dcdc) { 534da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_1: 535da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER); 536da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK; 537da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER, 538cee1a799eb044657922c4d63003d7bf71f8c8b8dAxel Lin val | WM8350_DCDC_HIB_MODE_DIS); 539da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 540da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_3: 541da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER); 542da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK; 543da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER, 544cee1a799eb044657922c4d63003d7bf71f8c8b8dAxel Lin val | WM8350_DCDC_HIB_MODE_DIS); 545da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 546da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_4: 547da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER); 548da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK; 549da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER, 550cee1a799eb044657922c4d63003d7bf71f8c8b8dAxel Lin val | WM8350_DCDC_HIB_MODE_DIS); 551da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 552da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_6: 553da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER); 554da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK; 555da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER, 556cee1a799eb044657922c4d63003d7bf71f8c8b8dAxel Lin val | WM8350_DCDC_HIB_MODE_DIS); 557da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 558da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_2: 559da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_5: 560da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 561da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 562da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 563da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 564da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 565da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 566da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 567da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_dcdc25_set_suspend_enable(struct regulator_dev *rdev) 568da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 569da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 570da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int dcdc = rdev_get_id(rdev); 571da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 572da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 573da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (dcdc) { 574da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_2: 575da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL) 576da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown & ~WM8350_DC2_HIB_MODE_MASK; 577da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val | 5789300928692f835f76f5604b3b51c3085977edf68Axel Lin (WM8350_DC2_HIB_MODE_ACTIVE << WM8350_DC2_HIB_MODE_SHIFT)); 579da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 580da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_5: 581da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL) 5829300928692f835f76f5604b3b51c3085977edf68Axel Lin & ~WM8350_DC5_HIB_MODE_MASK; 583da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val | 5849300928692f835f76f5604b3b51c3085977edf68Axel Lin (WM8350_DC5_HIB_MODE_ACTIVE << WM8350_DC5_HIB_MODE_SHIFT)); 585da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 586da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 587da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 588da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 589da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 590da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 591da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 592da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_dcdc25_set_suspend_disable(struct regulator_dev *rdev) 593da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 594da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 595da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int dcdc = rdev_get_id(rdev); 596da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 597da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 598da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (dcdc) { 599da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_2: 600da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL) 601da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown & ~WM8350_DC2_HIB_MODE_MASK; 602da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val | 6039300928692f835f76f5604b3b51c3085977edf68Axel Lin (WM8350_DC2_HIB_MODE_DISABLE << WM8350_DC2_HIB_MODE_SHIFT)); 604da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 605da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_5: 606da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL) 6079300928692f835f76f5604b3b51c3085977edf68Axel Lin & ~WM8350_DC5_HIB_MODE_MASK; 608da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val | 6099300928692f835f76f5604b3b51c3085977edf68Axel Lin (WM8350_DC5_HIB_MODE_DISABLE << WM8350_DC5_HIB_MODE_SHIFT)); 610da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 611da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 612da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 613da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 614da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 615da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 616da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 617da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev, 618da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown unsigned int mode) 619da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 620da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 621da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int dcdc = rdev_get_id(rdev); 622da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 *hib_mode; 623da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 624da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (dcdc) { 625da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_1: 626da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown hib_mode = &wm8350->pmic.dcdc1_hib_mode; 627da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 628da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_3: 629da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown hib_mode = &wm8350->pmic.dcdc3_hib_mode; 630da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 631da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_4: 632da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown hib_mode = &wm8350->pmic.dcdc4_hib_mode; 633da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 634da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_6: 635da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown hib_mode = &wm8350->pmic.dcdc6_hib_mode; 636da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 637da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_2: 638da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_5: 639da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 640da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 641da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 642da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 643da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (mode) { 644da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case REGULATOR_MODE_NORMAL: 645da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown *hib_mode = WM8350_DCDC_HIB_MODE_IMAGE; 646da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 647da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case REGULATOR_MODE_IDLE: 648da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown *hib_mode = WM8350_DCDC_HIB_MODE_STANDBY; 649da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 650da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case REGULATOR_MODE_STANDBY: 651da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown *hib_mode = WM8350_DCDC_HIB_MODE_LDO_IM; 652da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 653da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 654da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 655da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 656da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 657da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 658da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 659da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 660da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV) 661da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 662da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 663da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int volt_reg, mV = uV / 1000, ldo = rdev_get_id(rdev); 664da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 665da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 666da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, ldo, mV); 667da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 668da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (mV < 900 || mV > 3300) { 669da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown dev_err(wm8350->dev, "LDO%d voltage %d mV out of range\n", 670da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown ldo, mV); 671da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 672da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 673da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 674da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (ldo) { 675da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_1: 676da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO1_LOW_POWER; 677da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 678da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_2: 679da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO2_LOW_POWER; 680da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 681da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_3: 682da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO3_LOW_POWER; 683da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 684da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_4: 685da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO4_LOW_POWER; 686da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 687da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 688da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 689da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 690da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 691da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* all LDOs have same mV bits */ 692da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK; 693da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, volt_reg, 694da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val | wm8350_ldo_mvolts_to_val(mV)); 695da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 696da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 697da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 698da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_ldo_set_suspend_enable(struct regulator_dev *rdev) 699da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 700da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 701da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int volt_reg, ldo = rdev_get_id(rdev); 702da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 703da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 704da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (ldo) { 705da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_1: 706da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO1_LOW_POWER; 707da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 708da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_2: 709da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO2_LOW_POWER; 710da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 711da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_3: 712da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO3_LOW_POWER; 713da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 714da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_4: 715da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO4_LOW_POWER; 716da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 717da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 718da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 719da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 720da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 721da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* all LDOs have same mV bits */ 722da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK; 723da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, volt_reg, val); 724da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 725da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 726da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 727da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev) 728da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 729da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 730da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int volt_reg, ldo = rdev_get_id(rdev); 731da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 732da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 733da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (ldo) { 734da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_1: 735da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO1_LOW_POWER; 736da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 737da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_2: 738da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO2_LOW_POWER; 739da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 740da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_3: 741da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO3_LOW_POWER; 742da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 743da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_4: 744da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO4_LOW_POWER; 745da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 746da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 747da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 748da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 749da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 750da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* all LDOs have same mV bits */ 751da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK; 752cee1a799eb044657922c4d63003d7bf71f8c8b8dAxel Lin wm8350_reg_write(wm8350, volt_reg, val | WM8350_LDO1_HIB_MODE_DIS); 753da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 754da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 755da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 756da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV, 7573a93f2a9f4d8f73d74c0e552feb68a10f778a219Mark Brown int max_uV, unsigned *selector) 758da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 759da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 760da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000, 761da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown max_mV = max_uV / 1000; 762da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 763da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 764da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (min_mV < 900 || min_mV > 3300) 765da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 766da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (max_mV < 900 || max_mV > 3300) 767da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 768da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 769da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (min_mV < 1800) { 770da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* step size is 50mV < 1800mV */ 771da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown mV = (min_mV - 851) / 50; 772da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (wm8350_ldo_val_to_mvolts(mV) > max_mV) 773da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 774da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV); 775da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } else { 776da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* step size is 100mV > 1800mV */ 777da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown mV = ((min_mV - 1701) / 100) + 16; 778da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (wm8350_ldo_val_to_mvolts(mV) > max_mV) 779da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 780da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV); 781da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 782da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 783da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (ldo) { 784da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_1: 785da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO1_CONTROL; 786da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 787da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_2: 788da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO2_CONTROL; 789da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 790da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_3: 791da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO3_CONTROL; 792da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 793da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_4: 794da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO4_CONTROL; 795da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 796da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 797da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 798da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 799da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 8003a93f2a9f4d8f73d74c0e552feb68a10f778a219Mark Brown *selector = mV; 8013a93f2a9f4d8f73d74c0e552feb68a10f778a219Mark Brown 802da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* all LDOs have same mV bits */ 803da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK; 804da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, volt_reg, val | mV); 805da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 806da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 807da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 808c24516a1d674b1d9d847fd736feca444bc249b12Mark Brownstatic int wm8350_ldo_get_voltage_sel(struct regulator_dev *rdev) 809da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 810da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 811da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int volt_reg, ldo = rdev_get_id(rdev); 812da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 813da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (ldo) { 814da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_1: 815da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO1_CONTROL; 816da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 817da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_2: 818da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO2_CONTROL; 819da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 820da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_3: 821da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO3_CONTROL; 822da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 823da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_4: 824da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown volt_reg = WM8350_LDO4_CONTROL; 825da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 826da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 827da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 828da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 829da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 830da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* all LDOs have same mV bits */ 831c24516a1d674b1d9d847fd736feca444bc249b12Mark Brown return wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK; 832da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 833da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 834221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brownstatic int wm8350_ldo_list_voltage(struct regulator_dev *rdev, 835221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown unsigned selector) 836221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown{ 837221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown if (selector > WM8350_LDO1_VSEL_MASK) 838221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown return -EINVAL; 839221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown return wm8350_ldo_val_to_mvolts(selector) * 1000; 840221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown} 841221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown 842da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownint wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start, 843da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 stop, u16 fault) 844da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 845da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int slot_reg; 846da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 847da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 848da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown dev_dbg(wm8350->dev, "%s %d start %d stop %d\n", 849da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown __func__, dcdc, start, stop); 850da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 851da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* slot valid ? */ 852da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (start > 15 || stop > 15) 853da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 854da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 855da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (dcdc) { 856da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_1: 857da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown slot_reg = WM8350_DCDC1_TIMEOUTS; 858da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 859da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_2: 860da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown slot_reg = WM8350_DCDC2_TIMEOUTS; 861da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 862da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_3: 863da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown slot_reg = WM8350_DCDC3_TIMEOUTS; 864da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 865da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_4: 866da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown slot_reg = WM8350_DCDC4_TIMEOUTS; 867da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 868da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_5: 869da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown slot_reg = WM8350_DCDC5_TIMEOUTS; 870da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 871da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_6: 872da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown slot_reg = WM8350_DCDC6_TIMEOUTS; 873da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 874da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 875da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 876da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 877da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 878da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, slot_reg) & 879da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown ~(WM8350_DC1_ENSLOT_MASK | WM8350_DC1_SDSLOT_MASK | 880da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_DC1_ERRACT_MASK); 881da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, slot_reg, 882da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val | (start << WM8350_DC1_ENSLOT_SHIFT) | 883da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown (stop << WM8350_DC1_SDSLOT_SHIFT) | 884da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown (fault << WM8350_DC1_ERRACT_SHIFT)); 885da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 886da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 887da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 888da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark BrownEXPORT_SYMBOL_GPL(wm8350_dcdc_set_slot); 889da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 890da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownint wm8350_ldo_set_slot(struct wm8350 *wm8350, int ldo, u16 start, u16 stop) 891da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 892da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int slot_reg; 893da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 894da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 895da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown dev_dbg(wm8350->dev, "%s %d start %d stop %d\n", 896da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown __func__, ldo, start, stop); 897da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 898da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* slot valid ? */ 899da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (start > 15 || stop > 15) 900da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 901da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 902da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (ldo) { 903da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_1: 904da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown slot_reg = WM8350_LDO1_TIMEOUTS; 905da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 906da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_2: 907da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown slot_reg = WM8350_LDO2_TIMEOUTS; 908da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 909da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_3: 910da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown slot_reg = WM8350_LDO3_TIMEOUTS; 911da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 912da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_LDO_4: 913da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown slot_reg = WM8350_LDO4_TIMEOUTS; 914da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 915da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 916da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 917da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 918da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 919da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, slot_reg) & ~WM8350_LDO1_SDSLOT_MASK; 920da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, slot_reg, val | ((start << 10) | (stop << 6))); 921da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 922da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 923da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark BrownEXPORT_SYMBOL_GPL(wm8350_ldo_set_slot); 924da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 925da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownint wm8350_dcdc25_set_mode(struct wm8350 *wm8350, int dcdc, u16 mode, 926da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 ilim, u16 ramp, u16 feedback) 927da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 928da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 929da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 930da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown dev_dbg(wm8350->dev, "%s %d mode: %s %s\n", __func__, dcdc, 931da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown mode ? "normal" : "boost", ilim ? "low" : "normal"); 932da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 933da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (dcdc) { 934da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_2: 935da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL) 936da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown & ~(WM8350_DC2_MODE_MASK | WM8350_DC2_ILIM_MASK | 937da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_DC2_RMP_MASK | WM8350_DC2_FBSRC_MASK); 938da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val | 939da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown (mode << WM8350_DC2_MODE_SHIFT) | 940da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown (ilim << WM8350_DC2_ILIM_SHIFT) | 941da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown (ramp << WM8350_DC2_RMP_SHIFT) | 942da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown (feedback << WM8350_DC2_FBSRC_SHIFT)); 943da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 944da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_5: 945da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL) 946da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown & ~(WM8350_DC5_MODE_MASK | WM8350_DC5_ILIM_MASK | 947da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_DC5_RMP_MASK | WM8350_DC5_FBSRC_MASK); 948da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val | 949da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown (mode << WM8350_DC5_MODE_SHIFT) | 950da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown (ilim << WM8350_DC5_ILIM_SHIFT) | 951da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown (ramp << WM8350_DC5_RMP_SHIFT) | 952da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown (feedback << WM8350_DC5_FBSRC_SHIFT)); 953da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 954da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 955da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 956da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 957da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 958da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 959da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 960da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark BrownEXPORT_SYMBOL_GPL(wm8350_dcdc25_set_mode); 961da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 962da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_dcdc_enable(struct regulator_dev *rdev) 963da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 964da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 965da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int dcdc = rdev_get_id(rdev); 966da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 shift; 967da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 968da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6) 969da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 970da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 971da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown shift = dcdc - WM8350_DCDC_1; 972da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift); 973da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 974da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 975da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 976da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_dcdc_disable(struct regulator_dev *rdev) 977da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 978da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 979da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int dcdc = rdev_get_id(rdev); 980da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 shift; 981da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 982da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6) 983da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 984da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 985da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown shift = dcdc - WM8350_DCDC_1; 986da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift); 987da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 988da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 989da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 990da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 991da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_ldo_enable(struct regulator_dev *rdev) 992da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 993da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 994da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int ldo = rdev_get_id(rdev); 995da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 shift; 996da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 997da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4) 998da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 999da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1000da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown shift = (ldo - WM8350_LDO_1) + 8; 1001da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift); 1002da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 1003da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1004da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1005da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_ldo_disable(struct regulator_dev *rdev) 1006da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 1007da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 1008da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int ldo = rdev_get_id(rdev); 1009da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 shift; 1010da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1011da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4) 1012da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 1013da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1014da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown shift = (ldo - WM8350_LDO_1) + 8; 1015da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift); 1016da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 1017da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1018da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1019da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int force_continuous_enable(struct wm8350 *wm8350, int dcdc, int enable) 1020da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 1021da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int reg = 0, ret; 1022da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1023da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (dcdc) { 1024da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_1: 1025da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown reg = WM8350_DCDC1_FORCE_PWM; 1026da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 1027da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_3: 1028da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown reg = WM8350_DCDC3_FORCE_PWM; 1029da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 1030da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_4: 1031da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown reg = WM8350_DCDC4_FORCE_PWM; 1032da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 1033da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_6: 1034da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown reg = WM8350_DCDC6_FORCE_PWM; 1035da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 1036da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 1037da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 1038da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 1039da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1040da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (enable) 1041da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown ret = wm8350_set_bits(wm8350, reg, 1042da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_DCDC1_FORCE_PWM_ENA); 1043da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown else 1044da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown ret = wm8350_clear_bits(wm8350, reg, 1045da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown WM8350_DCDC1_FORCE_PWM_ENA); 1046da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return ret; 1047da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1048da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1049da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode) 1050da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 1051da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 1052da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int dcdc = rdev_get_id(rdev); 1053da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 1054da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1055da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6) 1056da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 1057da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1058da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (dcdc == WM8350_DCDC_2 || dcdc == WM8350_DCDC_5) 1059da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 1060da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1061da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = 1 << (dcdc - WM8350_DCDC_1); 1062da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1063da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (mode) { 1064da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case REGULATOR_MODE_FAST: 1065da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* force continuous mode */ 1066da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_set_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val); 1067da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val); 1068da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown force_continuous_enable(wm8350, dcdc, 1); 1069da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 1070da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case REGULATOR_MODE_NORMAL: 1071da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* active / pulse skipping */ 1072da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_set_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val); 1073da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val); 1074da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown force_continuous_enable(wm8350, dcdc, 0); 1075da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 1076da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case REGULATOR_MODE_IDLE: 1077da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* standby mode */ 1078da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown force_continuous_enable(wm8350, dcdc, 0); 1079da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val); 1080da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_clear_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val); 1081da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 1082da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case REGULATOR_MODE_STANDBY: 1083da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* LDO mode */ 1084da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown force_continuous_enable(wm8350, dcdc, 0); 1085da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_set_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val); 1086da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 1087da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 1088da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1089da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 1090da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1091da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1092da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic unsigned int wm8350_dcdc_get_mode(struct regulator_dev *rdev) 1093da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 1094da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 1095da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int dcdc = rdev_get_id(rdev); 1096da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 mask, sleep, active, force; 1097da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int mode = REGULATOR_MODE_NORMAL; 109833f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown int reg; 1099da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 110033f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown switch (dcdc) { 110133f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown case WM8350_DCDC_1: 110233f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown reg = WM8350_DCDC1_FORCE_PWM; 110333f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown break; 110433f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown case WM8350_DCDC_3: 110533f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown reg = WM8350_DCDC3_FORCE_PWM; 110633f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown break; 110733f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown case WM8350_DCDC_4: 110833f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown reg = WM8350_DCDC4_FORCE_PWM; 110933f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown break; 111033f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown case WM8350_DCDC_6: 111133f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown reg = WM8350_DCDC6_FORCE_PWM; 111233f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown break; 111333f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown default: 1114da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 111533f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown } 1116da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1117da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown mask = 1 << (dcdc - WM8350_DCDC_1); 1118da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown active = wm8350_reg_read(wm8350, WM8350_DCDC_ACTIVE_OPTIONS) & mask; 111933f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown force = wm8350_reg_read(wm8350, reg) & WM8350_DCDC1_FORCE_PWM_ENA; 1120da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown sleep = wm8350_reg_read(wm8350, WM8350_DCDC_SLEEP_OPTIONS) & mask; 112133f301af0c56971e3c0f4a4eb4b92f7e80230f49Mark Brown 1122da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown dev_dbg(wm8350->dev, "mask %x active %x sleep %x force %x", 1123da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown mask, active, sleep, force); 1124da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1125da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (active && !sleep) { 1126da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (force) 1127da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown mode = REGULATOR_MODE_FAST; 1128da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown else 1129da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown mode = REGULATOR_MODE_NORMAL; 1130da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } else if (!active && !sleep) 1131da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown mode = REGULATOR_MODE_IDLE; 11328ecee36adc9d2cf19471c395af6ef70264dec251Axel Lin else if (sleep) 1133da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown mode = REGULATOR_MODE_STANDBY; 1134da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1135da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return mode; 1136da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1137da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1138da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic unsigned int wm8350_ldo_get_mode(struct regulator_dev *rdev) 1139da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 1140da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return REGULATOR_MODE_NORMAL; 1141da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1142da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1143da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstruct wm8350_dcdc_efficiency { 1144da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int uA_load_min; 1145da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int uA_load_max; 1146da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown unsigned int mode; 1147da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown}; 1148da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1149da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic const struct wm8350_dcdc_efficiency dcdc1_6_efficiency[] = { 1150da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown {0, 10000, REGULATOR_MODE_STANDBY}, /* 0 - 10mA - LDO */ 1151da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown {10000, 100000, REGULATOR_MODE_IDLE}, /* 10mA - 100mA - Standby */ 1152da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown {100000, 1000000, REGULATOR_MODE_NORMAL}, /* > 100mA - Active */ 1153da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown {-1, -1, REGULATOR_MODE_NORMAL}, 1154da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown}; 1155da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1156da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic const struct wm8350_dcdc_efficiency dcdc3_4_efficiency[] = { 1157da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown {0, 10000, REGULATOR_MODE_STANDBY}, /* 0 - 10mA - LDO */ 1158da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown {10000, 100000, REGULATOR_MODE_IDLE}, /* 10mA - 100mA - Standby */ 1159da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown {100000, 800000, REGULATOR_MODE_NORMAL}, /* > 100mA - Active */ 1160da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown {-1, -1, REGULATOR_MODE_NORMAL}, 1161da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown}; 1162da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1163da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic unsigned int get_mode(int uA, const struct wm8350_dcdc_efficiency *eff) 1164da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 1165da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int i = 0; 1166da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1167da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown while (eff[i].uA_load_min != -1) { 1168da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (uA >= eff[i].uA_load_min && uA <= eff[i].uA_load_max) 1169da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return eff[i].mode; 1170da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 1171da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return REGULATOR_MODE_NORMAL; 1172da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1173da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1174da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown/* Query the regulator for it's most efficient mode @ uV,uA 1175da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown * WM8350 regulator efficiency is pretty similar over 1176da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown * different input and output uV. 1177da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown */ 1178da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic unsigned int wm8350_dcdc_get_optimum_mode(struct regulator_dev *rdev, 1179da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int input_uV, int output_uV, 1180da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int output_uA) 1181da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 1182da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int dcdc = rdev_get_id(rdev), mode; 1183da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1184da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (dcdc) { 1185da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_1: 1186da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_6: 1187da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown mode = get_mode(output_uA, dcdc1_6_efficiency); 1188da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 1189da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_3: 1190da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_4: 1191da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown mode = get_mode(output_uA, dcdc3_4_efficiency); 1192da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 1193da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown default: 1194da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown mode = REGULATOR_MODE_NORMAL; 1195da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 1196da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 1197da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return mode; 1198da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1199da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1200da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_dcdc_is_enabled(struct regulator_dev *rdev) 1201da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 1202da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 1203da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int dcdc = rdev_get_id(rdev), shift; 1204da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1205da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6) 1206da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 1207da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1208da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown shift = dcdc - WM8350_DCDC_1; 1209da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED) 1210da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown & (1 << shift); 1211da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1212da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1213da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_ldo_is_enabled(struct regulator_dev *rdev) 1214da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 1215da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 1216da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int ldo = rdev_get_id(rdev), shift; 1217da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1218da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4) 1219da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EINVAL; 1220da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1221da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown shift = (ldo - WM8350_LDO_1) + 8; 1222da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED) 1223da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown & (1 << shift); 1224da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1225da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1226da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic struct regulator_ops wm8350_dcdc_ops = { 1227da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .set_voltage = wm8350_dcdc_set_voltage, 1228c24516a1d674b1d9d847fd736feca444bc249b12Mark Brown .get_voltage_sel = wm8350_dcdc_get_voltage_sel, 1229221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown .list_voltage = wm8350_dcdc_list_voltage, 1230da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .enable = wm8350_dcdc_enable, 1231da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .disable = wm8350_dcdc_disable, 1232da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .get_mode = wm8350_dcdc_get_mode, 1233da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .set_mode = wm8350_dcdc_set_mode, 1234da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .get_optimum_mode = wm8350_dcdc_get_optimum_mode, 1235da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .is_enabled = wm8350_dcdc_is_enabled, 1236da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .set_suspend_voltage = wm8350_dcdc_set_suspend_voltage, 1237da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .set_suspend_enable = wm8350_dcdc_set_suspend_enable, 1238da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .set_suspend_disable = wm8350_dcdc_set_suspend_disable, 1239da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .set_suspend_mode = wm8350_dcdc_set_suspend_mode, 1240da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown}; 1241da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1242da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic struct regulator_ops wm8350_dcdc2_5_ops = { 1243da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .enable = wm8350_dcdc_enable, 1244da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .disable = wm8350_dcdc_disable, 1245da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .is_enabled = wm8350_dcdc_is_enabled, 1246da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .set_suspend_enable = wm8350_dcdc25_set_suspend_enable, 1247da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .set_suspend_disable = wm8350_dcdc25_set_suspend_disable, 1248da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown}; 1249da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1250da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic struct regulator_ops wm8350_ldo_ops = { 1251da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .set_voltage = wm8350_ldo_set_voltage, 1252c24516a1d674b1d9d847fd736feca444bc249b12Mark Brown .get_voltage_sel = wm8350_ldo_get_voltage_sel, 1253221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown .list_voltage = wm8350_ldo_list_voltage, 1254da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .enable = wm8350_ldo_enable, 1255da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .disable = wm8350_ldo_disable, 1256da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .is_enabled = wm8350_ldo_is_enabled, 1257da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .get_mode = wm8350_ldo_get_mode, 1258da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .set_suspend_voltage = wm8350_ldo_set_suspend_voltage, 1259da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .set_suspend_enable = wm8350_ldo_set_suspend_enable, 1260da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .set_suspend_disable = wm8350_ldo_set_suspend_disable, 1261da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown}; 1262da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1263da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic struct regulator_ops wm8350_isink_ops = { 1264da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .set_current_limit = wm8350_isink_set_current, 1265da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .get_current_limit = wm8350_isink_get_current, 1266da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .enable = wm8350_isink_enable, 1267da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .disable = wm8350_isink_disable, 1268da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .is_enabled = wm8350_isink_is_enabled, 126975c8ac22e4b8ebea8169a090e64d034a96758644Mark Brown .enable_time = wm8350_isink_enable_time, 1270da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown}; 1271da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1272da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { 1273da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown { 1274da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .name = "DCDC1", 1275da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .id = WM8350_DCDC_1, 1276da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .ops = &wm8350_dcdc_ops, 1277da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .irq = WM8350_IRQ_UV_DC1, 1278da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .type = REGULATOR_VOLTAGE, 1279221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown .n_voltages = WM8350_DCDC_MAX_VSEL + 1, 1280da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .owner = THIS_MODULE, 1281da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown }, 1282da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown { 1283da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .name = "DCDC2", 1284da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .id = WM8350_DCDC_2, 1285da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .ops = &wm8350_dcdc2_5_ops, 1286da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .irq = WM8350_IRQ_UV_DC2, 1287da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .type = REGULATOR_VOLTAGE, 1288da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .owner = THIS_MODULE, 1289da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown }, 1290da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown { 1291da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .name = "DCDC3", 1292da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .id = WM8350_DCDC_3, 1293da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .ops = &wm8350_dcdc_ops, 1294da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .irq = WM8350_IRQ_UV_DC3, 1295da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .type = REGULATOR_VOLTAGE, 1296221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown .n_voltages = WM8350_DCDC_MAX_VSEL + 1, 1297da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .owner = THIS_MODULE, 1298da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown }, 1299da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown { 1300da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .name = "DCDC4", 1301da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .id = WM8350_DCDC_4, 1302da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .ops = &wm8350_dcdc_ops, 1303da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .irq = WM8350_IRQ_UV_DC4, 1304da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .type = REGULATOR_VOLTAGE, 1305221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown .n_voltages = WM8350_DCDC_MAX_VSEL + 1, 1306da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .owner = THIS_MODULE, 1307da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown }, 1308da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown { 1309da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .name = "DCDC5", 1310da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .id = WM8350_DCDC_5, 1311da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .ops = &wm8350_dcdc2_5_ops, 1312da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .irq = WM8350_IRQ_UV_DC5, 1313da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .type = REGULATOR_VOLTAGE, 1314da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .owner = THIS_MODULE, 1315da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown }, 1316da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown { 1317da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .name = "DCDC6", 1318da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .id = WM8350_DCDC_6, 1319da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .ops = &wm8350_dcdc_ops, 1320da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .irq = WM8350_IRQ_UV_DC6, 1321da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .type = REGULATOR_VOLTAGE, 1322221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown .n_voltages = WM8350_DCDC_MAX_VSEL + 1, 1323da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .owner = THIS_MODULE, 1324da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown }, 1325da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown { 1326da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .name = "LDO1", 1327da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .id = WM8350_LDO_1, 1328da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .ops = &wm8350_ldo_ops, 1329da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .irq = WM8350_IRQ_UV_LDO1, 1330da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .type = REGULATOR_VOLTAGE, 1331221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown .n_voltages = WM8350_LDO1_VSEL_MASK + 1, 1332da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .owner = THIS_MODULE, 1333da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown }, 1334da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown { 1335da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .name = "LDO2", 1336da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .id = WM8350_LDO_2, 1337da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .ops = &wm8350_ldo_ops, 1338da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .irq = WM8350_IRQ_UV_LDO2, 1339da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .type = REGULATOR_VOLTAGE, 1340221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown .n_voltages = WM8350_LDO2_VSEL_MASK + 1, 1341da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .owner = THIS_MODULE, 1342da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown }, 1343da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown { 1344da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .name = "LDO3", 1345da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .id = WM8350_LDO_3, 1346da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .ops = &wm8350_ldo_ops, 1347da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .irq = WM8350_IRQ_UV_LDO3, 1348da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .type = REGULATOR_VOLTAGE, 1349221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown .n_voltages = WM8350_LDO3_VSEL_MASK + 1, 1350da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .owner = THIS_MODULE, 1351da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown }, 1352da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown { 1353da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .name = "LDO4", 1354da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .id = WM8350_LDO_4, 1355da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .ops = &wm8350_ldo_ops, 1356da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .irq = WM8350_IRQ_UV_LDO4, 1357da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .type = REGULATOR_VOLTAGE, 1358221a7c7c9c88bf9d3ea4e191b35c7da709ca30b7Mark Brown .n_voltages = WM8350_LDO4_VSEL_MASK + 1, 1359da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .owner = THIS_MODULE, 1360da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown }, 1361da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown { 1362da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .name = "ISINKA", 1363da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .id = WM8350_ISINK_A, 1364da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .ops = &wm8350_isink_ops, 1365da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .irq = WM8350_IRQ_CS1, 1366da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .type = REGULATOR_CURRENT, 1367da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .owner = THIS_MODULE, 1368da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown }, 1369da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown { 1370da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .name = "ISINKB", 1371da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .id = WM8350_ISINK_B, 1372da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .ops = &wm8350_isink_ops, 1373da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .irq = WM8350_IRQ_CS2, 1374da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .type = REGULATOR_CURRENT, 1375da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .owner = THIS_MODULE, 1376da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown }, 1377da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown}; 1378da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 13795a65edbc12b6b34ef912114f1fc8215786f85b25Mark Brownstatic irqreturn_t pmic_uv_handler(int irq, void *data) 1380da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 1381da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct regulator_dev *rdev = (struct regulator_dev *)data; 13825a65edbc12b6b34ef912114f1fc8215786f85b25Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 1383da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1384b136fb4463d13eea129bf090a8a465bba6bf0003Jonathan Cameron mutex_lock(&rdev->mutex); 1385da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2) 1386da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown regulator_notifier_call_chain(rdev, 1387da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown REGULATOR_EVENT_REGULATION_OUT, 1388da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350); 1389da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown else 1390da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown regulator_notifier_call_chain(rdev, 1391da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown REGULATOR_EVENT_UNDER_VOLTAGE, 1392da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350); 1393b136fb4463d13eea129bf090a8a465bba6bf0003Jonathan Cameron mutex_unlock(&rdev->mutex); 13945a65edbc12b6b34ef912114f1fc8215786f85b25Mark Brown 13955a65edbc12b6b34ef912114f1fc8215786f85b25Mark Brown return IRQ_HANDLED; 1396da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1397da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1398da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_regulator_probe(struct platform_device *pdev) 1399da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 1400da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); 1401da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct regulator_dev *rdev; 1402da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int ret; 1403da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown u16 val; 1404da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1405da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (pdev->id < WM8350_DCDC_1 || pdev->id > WM8350_ISINK_B) 1406da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -ENODEV; 1407da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1408da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* do any regulatior specific init */ 1409da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown switch (pdev->id) { 1410da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_1: 1411da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER); 1412da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK; 1413da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 1414da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_3: 1415da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER); 1416da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK; 1417da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 1418da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_4: 1419da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER); 1420da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK; 1421da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 1422da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown case WM8350_DCDC_6: 1423da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER); 1424da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK; 1425da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown break; 1426da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 1427da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1428da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* register regulator */ 1429da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown rdev = regulator_register(&wm8350_reg[pdev->id], &pdev->dev, 14300527100fd11d9710c7e153d791da78824b7b46faMark Brown pdev->dev.platform_data, 14312c043bcbf287dc69848054d5c02c55c20f7a7bc5Rajendra Nayak dev_get_drvdata(&pdev->dev), NULL); 1432da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (IS_ERR(rdev)) { 1433da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown dev_err(&pdev->dev, "failed to register %s\n", 1434da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg[pdev->id].name); 1435da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return PTR_ERR(rdev); 1436da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 1437da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1438da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown /* register regulator IRQ */ 1439da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown ret = wm8350_register_irq(wm8350, wm8350_reg[pdev->id].irq, 14405a65edbc12b6b34ef912114f1fc8215786f85b25Mark Brown pmic_uv_handler, 0, "UV", rdev); 1441da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (ret < 0) { 1442da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown regulator_unregister(rdev); 1443da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown dev_err(&pdev->dev, "failed to register regulator %s IRQ\n", 1444da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350_reg[pdev->id].name); 1445da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return ret; 1446da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 1447da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1448da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 1449da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1450da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1451da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int wm8350_regulator_remove(struct platform_device *pdev) 1452da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 1453da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct regulator_dev *rdev = platform_get_drvdata(pdev); 1454da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct wm8350 *wm8350 = rdev_get_drvdata(rdev); 1455da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1456f99344fc69c3df46786a39ea4283a4175ea40b3fMark Brown wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq, rdev); 1457da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1458da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown regulator_unregister(rdev); 1459da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1460da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return 0; 1461da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1462da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1463da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownint wm8350_register_regulator(struct wm8350 *wm8350, int reg, 1464da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct regulator_init_data *initdata) 1465da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 1466da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown struct platform_device *pdev; 1467da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown int ret; 14684dee4d441d3f90cd8cec10a9eb222d8a4f2fa2a3Roel Kluin if (reg < 0 || reg >= NUM_WM8350_REGULATORS) 14694dee4d441d3f90cd8cec10a9eb222d8a4f2fa2a3Roel Kluin return -EINVAL; 1470da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1471da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (wm8350->pmic.pdev[reg]) 1472da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -EBUSY; 1473da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1474645524a9c6e1e42dc4fe03217befb20e2fc4d43eMark Brown if (reg >= WM8350_DCDC_1 && reg <= WM8350_DCDC_6 && 1475645524a9c6e1e42dc4fe03217befb20e2fc4d43eMark Brown reg > wm8350->pmic.max_dcdc) 1476645524a9c6e1e42dc4fe03217befb20e2fc4d43eMark Brown return -ENODEV; 1477645524a9c6e1e42dc4fe03217befb20e2fc4d43eMark Brown if (reg >= WM8350_ISINK_A && reg <= WM8350_ISINK_B && 1478645524a9c6e1e42dc4fe03217befb20e2fc4d43eMark Brown reg > wm8350->pmic.max_isink) 1479645524a9c6e1e42dc4fe03217befb20e2fc4d43eMark Brown return -ENODEV; 1480645524a9c6e1e42dc4fe03217befb20e2fc4d43eMark Brown 1481da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown pdev = platform_device_alloc("wm8350-regulator", reg); 1482da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (!pdev) 1483da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return -ENOMEM; 1484da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1485da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350->pmic.pdev[reg] = pdev; 1486da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1487da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown initdata->driver_data = wm8350; 1488da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1489da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown pdev->dev.platform_data = initdata; 1490da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown pdev->dev.parent = wm8350->dev; 1491da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown platform_set_drvdata(pdev, wm8350); 1492da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1493da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown ret = platform_device_add(pdev); 1494da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1495da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown if (ret != 0) { 1496da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown dev_err(wm8350->dev, "Failed to register regulator %d: %d\n", 1497da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown reg, ret); 1498e9a1c5129de1caf4526b8df5f200ff628b2ffab4Axel Lin platform_device_put(pdev); 1499da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown wm8350->pmic.pdev[reg] = NULL; 1500da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown } 1501da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1502da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return ret; 1503da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1504da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark BrownEXPORT_SYMBOL_GPL(wm8350_register_regulator); 1505da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 15060081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown/** 15070081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown * wm8350_register_led - Register a WM8350 LED output 15080081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown * 15090081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown * @param wm8350 The WM8350 device to configure. 15100081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown * @param lednum LED device index to create. 15110081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown * @param dcdc The DCDC to use for the LED. 15120081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown * @param isink The ISINK to use for the LED. 15130081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown * @param pdata Configuration for the LED. 15140081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown * 15150081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown * The WM8350 supports the use of an ISINK together with a DCDC to 15160081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown * provide a power-efficient LED driver. This function registers the 15170081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown * regulators and instantiates the platform device for a LED. The 15180081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown * operating modes for the LED regulators must be configured using 15190081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown * wm8350_isink_set_flash(), wm8350_dcdc25_set_mode() and 15200081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown * wm8350_dcdc_set_slot() prior to calling this function. 15210081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown */ 15220081e8020ebd814a99e45720a10e869a54ee08a6Mark Brownint wm8350_register_led(struct wm8350 *wm8350, int lednum, int dcdc, int isink, 15230081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown struct wm8350_led_platform_data *pdata) 15240081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown{ 15250081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown struct wm8350_led *led; 15260081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown struct platform_device *pdev; 15270081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown int ret; 15280081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown 15298dd2c9e3128a5784a01084b52d5bb7efd4371ac6Roel Kluin if (lednum >= ARRAY_SIZE(wm8350->pmic.led) || lednum < 0) { 15300081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown dev_err(wm8350->dev, "Invalid LED index %d\n", lednum); 15310081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown return -ENODEV; 15320081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown } 15330081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown 15340081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown led = &wm8350->pmic.led[lednum]; 15350081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown 15360081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown if (led->pdev) { 15370081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown dev_err(wm8350->dev, "LED %d already allocated\n", lednum); 15380081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown return -EINVAL; 15390081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown } 15400081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown 15410081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown pdev = platform_device_alloc("wm8350-led", lednum); 15420081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown if (pdev == NULL) { 15430081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown dev_err(wm8350->dev, "Failed to allocate LED %d\n", lednum); 15440081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown return -ENOMEM; 15450081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown } 15460081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown 154734ce8d07e63baa37d21aeca87f3248b008114899Mark Brown led->isink_consumer.dev_name = dev_name(&pdev->dev); 15480081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown led->isink_consumer.supply = "led_isink"; 15490081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown led->isink_init.num_consumer_supplies = 1; 15500081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown led->isink_init.consumer_supplies = &led->isink_consumer; 15510081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown led->isink_init.constraints.min_uA = 0; 15520081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown led->isink_init.constraints.max_uA = pdata->max_uA; 1553a2fad9bf26a1d44a8d31a5c4528108a2b9f468abMark Brown led->isink_init.constraints.valid_ops_mask 1554a2fad9bf26a1d44a8d31a5c4528108a2b9f468abMark Brown = REGULATOR_CHANGE_CURRENT | REGULATOR_CHANGE_STATUS; 15550081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown led->isink_init.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL; 15560081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown ret = wm8350_register_regulator(wm8350, isink, &led->isink_init); 15570081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown if (ret != 0) { 15580081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown platform_device_put(pdev); 15590081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown return ret; 15600081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown } 15610081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown 156234ce8d07e63baa37d21aeca87f3248b008114899Mark Brown led->dcdc_consumer.dev_name = dev_name(&pdev->dev); 15630081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown led->dcdc_consumer.supply = "led_vcc"; 15640081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown led->dcdc_init.num_consumer_supplies = 1; 15650081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown led->dcdc_init.consumer_supplies = &led->dcdc_consumer; 15660081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown led->dcdc_init.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL; 1567a2fad9bf26a1d44a8d31a5c4528108a2b9f468abMark Brown led->dcdc_init.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS; 15680081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown ret = wm8350_register_regulator(wm8350, dcdc, &led->dcdc_init); 15690081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown if (ret != 0) { 15700081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown platform_device_put(pdev); 15710081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown return ret; 15720081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown } 15730081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown 15740081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown switch (isink) { 15750081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown case WM8350_ISINK_A: 15760081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown wm8350->pmic.isink_A_dcdc = dcdc; 15770081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown break; 15780081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown case WM8350_ISINK_B: 15790081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown wm8350->pmic.isink_B_dcdc = dcdc; 15800081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown break; 15810081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown } 15820081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown 15830081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown pdev->dev.platform_data = pdata; 15840081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown pdev->dev.parent = wm8350->dev; 15850081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown ret = platform_device_add(pdev); 15860081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown if (ret != 0) { 15870081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown dev_err(wm8350->dev, "Failed to register LED %d: %d\n", 15880081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown lednum, ret); 15890081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown platform_device_put(pdev); 15900081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown return ret; 15910081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown } 15920081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown 15930081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown led->pdev = pdev; 15940081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown 15950081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown return 0; 15960081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown} 15970081e8020ebd814a99e45720a10e869a54ee08a6Mark BrownEXPORT_SYMBOL_GPL(wm8350_register_led); 15980081e8020ebd814a99e45720a10e869a54ee08a6Mark Brown 1599da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic struct platform_driver wm8350_regulator_driver = { 1600da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .probe = wm8350_regulator_probe, 1601da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .remove = wm8350_regulator_remove, 1602da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .driver = { 1603da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown .name = "wm8350-regulator", 1604da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown }, 1605da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown}; 1606da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1607da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic int __init wm8350_regulator_init(void) 1608da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 1609da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown return platform_driver_register(&wm8350_regulator_driver); 1610da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1611da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownsubsys_initcall(wm8350_regulator_init); 1612da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1613da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownstatic void __exit wm8350_regulator_exit(void) 1614da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown{ 1615da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown platform_driver_unregister(&wm8350_regulator_driver); 1616da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown} 1617da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brownmodule_exit(wm8350_regulator_exit); 1618da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown 1619da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark Brown/* Module information */ 1620da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark BrownMODULE_AUTHOR("Liam Girdwood"); 1621da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark BrownMODULE_DESCRIPTION("WM8350 voltage and current regulator driver"); 1622da09155ac8d3f04c299b3d82a6ab0df8d03da632Mark BrownMODULE_LICENSE("GPL"); 162338c53c89139e6140b895b419b18c586e8593a6e8Mark BrownMODULE_ALIAS("platform:wm8350-regulator"); 1624