1f18792714608a670c2762d22f695d77d02fc965eSachin Kamat/* 2f18792714608a670c2762d22f695d77d02fc965eSachin Kamat * Copyright (c) 2013 Samsung Electronics Co., Ltd 3f18792714608a670c2762d22f695d77d02fc965eSachin Kamat * http://www.samsung.com 4f18792714608a670c2762d22f695d77d02fc965eSachin Kamat * 5f18792714608a670c2762d22f695d77d02fc965eSachin Kamat * This program is free software; you can redistribute it and/or modify it 6f18792714608a670c2762d22f695d77d02fc965eSachin Kamat * under the terms of the GNU General Public License as published by the 7f18792714608a670c2762d22f695d77d02fc965eSachin Kamat * Free Software Foundation; either version 2 of the License, or (at your 8f18792714608a670c2762d22f695d77d02fc965eSachin Kamat * option) any later version. 9f18792714608a670c2762d22f695d77d02fc965eSachin Kamat * 10f18792714608a670c2762d22f695d77d02fc965eSachin Kamat */ 11f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 12f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#include <linux/bug.h> 13f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#include <linux/err.h> 14f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#include <linux/gpio.h> 15f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#include <linux/slab.h> 16f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#include <linux/module.h> 17f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#include <linux/of.h> 18f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#include <linux/regmap.h> 19f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#include <linux/platform_device.h> 20f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#include <linux/regulator/driver.h> 21f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#include <linux/regulator/machine.h> 22f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#include <linux/regulator/of_regulator.h> 23f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#include <linux/mfd/samsung/core.h> 24f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#include <linux/mfd/samsung/s2mpa01.h> 25f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 26f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#define S2MPA01_REGULATOR_CNT ARRAY_SIZE(regulators) 27f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 28f18792714608a670c2762d22f695d77d02fc965eSachin Kamatstruct s2mpa01_info { 29f18792714608a670c2762d22f695d77d02fc965eSachin Kamat int ramp_delay24; 30f18792714608a670c2762d22f695d77d02fc965eSachin Kamat int ramp_delay3; 31f18792714608a670c2762d22f695d77d02fc965eSachin Kamat int ramp_delay5; 32f18792714608a670c2762d22f695d77d02fc965eSachin Kamat int ramp_delay16; 33f18792714608a670c2762d22f695d77d02fc965eSachin Kamat int ramp_delay7; 34f18792714608a670c2762d22f695d77d02fc965eSachin Kamat int ramp_delay8910; 35f18792714608a670c2762d22f695d77d02fc965eSachin Kamat}; 36f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 37f18792714608a670c2762d22f695d77d02fc965eSachin Kamatstatic int get_ramp_delay(int ramp_delay) 38f18792714608a670c2762d22f695d77d02fc965eSachin Kamat{ 39f18792714608a670c2762d22f695d77d02fc965eSachin Kamat unsigned char cnt = 0; 40f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 41f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_delay /= 6250; 42f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 43f18792714608a670c2762d22f695d77d02fc965eSachin Kamat while (true) { 44f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_delay = ramp_delay >> 1; 45f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (ramp_delay == 0) 46f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 47f18792714608a670c2762d22f695d77d02fc965eSachin Kamat cnt++; 48f18792714608a670c2762d22f695d77d02fc965eSachin Kamat } 49f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 50f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (cnt > 3) 51f18792714608a670c2762d22f695d77d02fc965eSachin Kamat cnt = 3; 52f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 53f18792714608a670c2762d22f695d77d02fc965eSachin Kamat return cnt; 54f18792714608a670c2762d22f695d77d02fc965eSachin Kamat} 55f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 56f18792714608a670c2762d22f695d77d02fc965eSachin Kamatstatic int s2mpa01_regulator_set_voltage_time_sel(struct regulator_dev *rdev, 57f18792714608a670c2762d22f695d77d02fc965eSachin Kamat unsigned int old_selector, 58f18792714608a670c2762d22f695d77d02fc965eSachin Kamat unsigned int new_selector) 59f18792714608a670c2762d22f695d77d02fc965eSachin Kamat{ 60f18792714608a670c2762d22f695d77d02fc965eSachin Kamat struct s2mpa01_info *s2mpa01 = rdev_get_drvdata(rdev); 61f18792714608a670c2762d22f695d77d02fc965eSachin Kamat unsigned int ramp_delay = 0; 62f18792714608a670c2762d22f695d77d02fc965eSachin Kamat int old_volt, new_volt; 63f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 640608032a9067c165e5ed75c56311a08cbb28564fKrzysztof Kozlowski switch (rdev_get_id(rdev)) { 65f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK2: 66f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK4: 67f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_delay = s2mpa01->ramp_delay24; 68f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 69f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK3: 70f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_delay = s2mpa01->ramp_delay3; 71f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 72f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK5: 73f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_delay = s2mpa01->ramp_delay5; 74f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 75f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK1: 76f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK6: 77f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_delay = s2mpa01->ramp_delay16; 78f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 79f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK7: 80f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_delay = s2mpa01->ramp_delay7; 81f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 82f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK8: 83f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK9: 84f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK10: 85f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_delay = s2mpa01->ramp_delay8910; 86f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 87f18792714608a670c2762d22f695d77d02fc965eSachin Kamat } 88f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 89f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (ramp_delay == 0) 90f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_delay = rdev->desc->ramp_delay; 91f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 92f18792714608a670c2762d22f695d77d02fc965eSachin Kamat old_volt = rdev->desc->min_uV + (rdev->desc->uV_step * old_selector); 93f18792714608a670c2762d22f695d77d02fc965eSachin Kamat new_volt = rdev->desc->min_uV + (rdev->desc->uV_step * new_selector); 94f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 95f18792714608a670c2762d22f695d77d02fc965eSachin Kamat return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); 96f18792714608a670c2762d22f695d77d02fc965eSachin Kamat} 97f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 98f18792714608a670c2762d22f695d77d02fc965eSachin Kamatstatic int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) 99f18792714608a670c2762d22f695d77d02fc965eSachin Kamat{ 100f18792714608a670c2762d22f695d77d02fc965eSachin Kamat struct s2mpa01_info *s2mpa01 = rdev_get_drvdata(rdev); 101f18792714608a670c2762d22f695d77d02fc965eSachin Kamat unsigned int ramp_val, ramp_shift, ramp_reg = S2MPA01_REG_RAMP2; 102f18792714608a670c2762d22f695d77d02fc965eSachin Kamat unsigned int ramp_enable = 1, enable_shift = 0; 103f18792714608a670c2762d22f695d77d02fc965eSachin Kamat int ret; 104f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 1050608032a9067c165e5ed75c56311a08cbb28564fKrzysztof Kozlowski switch (rdev_get_id(rdev)) { 106f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK1: 107f18792714608a670c2762d22f695d77d02fc965eSachin Kamat enable_shift = S2MPA01_BUCK1_RAMP_EN_SHIFT; 108f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (!ramp_delay) { 109f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_enable = 0; 110f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 111f18792714608a670c2762d22f695d77d02fc965eSachin Kamat } 112f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 113f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (ramp_delay > s2mpa01->ramp_delay16) 114f18792714608a670c2762d22f695d77d02fc965eSachin Kamat s2mpa01->ramp_delay16 = ramp_delay; 115f18792714608a670c2762d22f695d77d02fc965eSachin Kamat else 116f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_delay = s2mpa01->ramp_delay16; 117f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 118f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT; 119f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 120f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK2: 121f18792714608a670c2762d22f695d77d02fc965eSachin Kamat enable_shift = S2MPA01_BUCK2_RAMP_EN_SHIFT; 122f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (!ramp_delay) { 123f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_enable = 0; 124f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 125f18792714608a670c2762d22f695d77d02fc965eSachin Kamat } 126f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 127f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (ramp_delay > s2mpa01->ramp_delay24) 128f18792714608a670c2762d22f695d77d02fc965eSachin Kamat s2mpa01->ramp_delay24 = ramp_delay; 129f18792714608a670c2762d22f695d77d02fc965eSachin Kamat else 130f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_delay = s2mpa01->ramp_delay24; 131f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 132f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_shift = S2MPA01_BUCK24_RAMP_SHIFT; 133f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_reg = S2MPA01_REG_RAMP1; 134f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 135f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK3: 136f18792714608a670c2762d22f695d77d02fc965eSachin Kamat enable_shift = S2MPA01_BUCK3_RAMP_EN_SHIFT; 137f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (!ramp_delay) { 138f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_enable = 0; 139f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 140f18792714608a670c2762d22f695d77d02fc965eSachin Kamat } 141f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 142f18792714608a670c2762d22f695d77d02fc965eSachin Kamat s2mpa01->ramp_delay3 = ramp_delay; 143f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_shift = S2MPA01_BUCK3_RAMP_SHIFT; 144f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_reg = S2MPA01_REG_RAMP1; 145f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 146f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK4: 147f18792714608a670c2762d22f695d77d02fc965eSachin Kamat enable_shift = S2MPA01_BUCK4_RAMP_EN_SHIFT; 148f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (!ramp_delay) { 149f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_enable = 0; 150f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 151f18792714608a670c2762d22f695d77d02fc965eSachin Kamat } 152f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 153f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (ramp_delay > s2mpa01->ramp_delay24) 154f18792714608a670c2762d22f695d77d02fc965eSachin Kamat s2mpa01->ramp_delay24 = ramp_delay; 155f18792714608a670c2762d22f695d77d02fc965eSachin Kamat else 156f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_delay = s2mpa01->ramp_delay24; 157f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 158f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_shift = S2MPA01_BUCK24_RAMP_SHIFT; 159f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_reg = S2MPA01_REG_RAMP1; 160f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 161f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK5: 162f18792714608a670c2762d22f695d77d02fc965eSachin Kamat s2mpa01->ramp_delay5 = ramp_delay; 163f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_shift = S2MPA01_BUCK5_RAMP_SHIFT; 164f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 165f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK6: 166f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (ramp_delay > s2mpa01->ramp_delay16) 167f18792714608a670c2762d22f695d77d02fc965eSachin Kamat s2mpa01->ramp_delay16 = ramp_delay; 168f18792714608a670c2762d22f695d77d02fc965eSachin Kamat else 169f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_delay = s2mpa01->ramp_delay16; 170f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 171f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT; 172f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 173f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK7: 174f18792714608a670c2762d22f695d77d02fc965eSachin Kamat s2mpa01->ramp_delay7 = ramp_delay; 175f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_shift = S2MPA01_BUCK7_RAMP_SHIFT; 176f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 177f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK8: 178f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK9: 179f18792714608a670c2762d22f695d77d02fc965eSachin Kamat case S2MPA01_BUCK10: 180f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (ramp_delay > s2mpa01->ramp_delay8910) 181f18792714608a670c2762d22f695d77d02fc965eSachin Kamat s2mpa01->ramp_delay8910 = ramp_delay; 182f18792714608a670c2762d22f695d77d02fc965eSachin Kamat else 183f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_delay = s2mpa01->ramp_delay8910; 184f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 185f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_shift = S2MPA01_BUCK8910_RAMP_SHIFT; 186f18792714608a670c2762d22f695d77d02fc965eSachin Kamat break; 187f18792714608a670c2762d22f695d77d02fc965eSachin Kamat default: 188f18792714608a670c2762d22f695d77d02fc965eSachin Kamat return 0; 189f18792714608a670c2762d22f695d77d02fc965eSachin Kamat } 190f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 191f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (!ramp_enable) 192f18792714608a670c2762d22f695d77d02fc965eSachin Kamat goto ramp_disable; 193f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 19451e2fc0a251ba64c68207e4c6f6ac33c891b2465Krzysztof Kozlowski /* Ramp delay can be enabled/disabled only for buck[1234] */ 19551e2fc0a251ba64c68207e4c6f6ac33c891b2465Krzysztof Kozlowski if (rdev_get_id(rdev) >= S2MPA01_BUCK1 && 19651e2fc0a251ba64c68207e4c6f6ac33c891b2465Krzysztof Kozlowski rdev_get_id(rdev) <= S2MPA01_BUCK4) { 19751e2fc0a251ba64c68207e4c6f6ac33c891b2465Krzysztof Kozlowski ret = regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1, 19851e2fc0a251ba64c68207e4c6f6ac33c891b2465Krzysztof Kozlowski 1 << enable_shift, 1 << enable_shift); 19951e2fc0a251ba64c68207e4c6f6ac33c891b2465Krzysztof Kozlowski if (ret) { 20051e2fc0a251ba64c68207e4c6f6ac33c891b2465Krzysztof Kozlowski dev_err(&rdev->dev, "failed to enable ramp rate\n"); 20151e2fc0a251ba64c68207e4c6f6ac33c891b2465Krzysztof Kozlowski return ret; 20251e2fc0a251ba64c68207e4c6f6ac33c891b2465Krzysztof Kozlowski } 203f18792714608a670c2762d22f695d77d02fc965eSachin Kamat } 204f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 205f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_val = get_ramp_delay(ramp_delay); 206f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 207f18792714608a670c2762d22f695d77d02fc965eSachin Kamat return regmap_update_bits(rdev->regmap, ramp_reg, 0x3 << ramp_shift, 208f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ramp_val << ramp_shift); 209f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 210f18792714608a670c2762d22f695d77d02fc965eSachin Kamatramp_disable: 211f18792714608a670c2762d22f695d77d02fc965eSachin Kamat return regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1, 212f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 1 << enable_shift, 0); 213f18792714608a670c2762d22f695d77d02fc965eSachin Kamat} 214f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 215f18792714608a670c2762d22f695d77d02fc965eSachin Kamatstatic struct regulator_ops s2mpa01_ldo_ops = { 216f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .list_voltage = regulator_list_voltage_linear, 217f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .map_voltage = regulator_map_voltage_linear, 218f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .is_enabled = regulator_is_enabled_regmap, 219f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .enable = regulator_enable_regmap, 220f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .disable = regulator_disable_regmap, 221f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .get_voltage_sel = regulator_get_voltage_sel_regmap, 222f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .set_voltage_sel = regulator_set_voltage_sel_regmap, 223f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .set_voltage_time_sel = regulator_set_voltage_time_sel, 224f18792714608a670c2762d22f695d77d02fc965eSachin Kamat}; 225f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 226f18792714608a670c2762d22f695d77d02fc965eSachin Kamatstatic struct regulator_ops s2mpa01_buck_ops = { 227f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .list_voltage = regulator_list_voltage_linear, 228f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .map_voltage = regulator_map_voltage_linear, 229f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .is_enabled = regulator_is_enabled_regmap, 230f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .enable = regulator_enable_regmap, 231f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .disable = regulator_disable_regmap, 232f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .get_voltage_sel = regulator_get_voltage_sel_regmap, 233f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .set_voltage_sel = regulator_set_voltage_sel_regmap, 234f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .set_voltage_time_sel = s2mpa01_regulator_set_voltage_time_sel, 235f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .set_ramp_delay = s2mpa01_set_ramp_delay, 236f18792714608a670c2762d22f695d77d02fc965eSachin Kamat}; 237f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 238d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap#define regulator_desc_ldo(num, step) { \ 239f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .name = "LDO"#num, \ 240f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .id = S2MPA01_LDO##num, \ 241f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .ops = &s2mpa01_ldo_ops, \ 242f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .type = REGULATOR_VOLTAGE, \ 243f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .owner = THIS_MODULE, \ 2440e4f417857083f399769491f6e7773d111debd0fAmit Daniel Kachhap .min_uV = MIN_800_MV, \ 245d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap .uV_step = step, \ 246f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .n_voltages = S2MPA01_LDO_N_VOLTAGES, \ 247f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .vsel_reg = S2MPA01_REG_L1CTRL + num - 1, \ 248f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .vsel_mask = S2MPA01_LDO_VSEL_MASK, \ 249f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .enable_reg = S2MPA01_REG_L1CTRL + num - 1, \ 250f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .enable_mask = S2MPA01_ENABLE_MASK \ 251f18792714608a670c2762d22f695d77d02fc965eSachin Kamat} 252f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 253f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#define regulator_desc_buck1_4(num) { \ 254f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .name = "BUCK"#num, \ 255f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .id = S2MPA01_BUCK##num, \ 256f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .ops = &s2mpa01_buck_ops, \ 257f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .type = REGULATOR_VOLTAGE, \ 258f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .owner = THIS_MODULE, \ 2590e4f417857083f399769491f6e7773d111debd0fAmit Daniel Kachhap .min_uV = MIN_600_MV, \ 2600e4f417857083f399769491f6e7773d111debd0fAmit Daniel Kachhap .uV_step = STEP_6_25_MV, \ 261f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ 262f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .ramp_delay = S2MPA01_RAMP_DELAY, \ 263f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .vsel_reg = S2MPA01_REG_B1CTRL2 + (num - 1) * 2, \ 264f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \ 265f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .enable_reg = S2MPA01_REG_B1CTRL1 + (num - 1) * 2, \ 266f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .enable_mask = S2MPA01_ENABLE_MASK \ 267f18792714608a670c2762d22f695d77d02fc965eSachin Kamat} 268f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 269f18792714608a670c2762d22f695d77d02fc965eSachin Kamat#define regulator_desc_buck5 { \ 270f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .name = "BUCK5", \ 271f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .id = S2MPA01_BUCK5, \ 272f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .ops = &s2mpa01_buck_ops, \ 273f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .type = REGULATOR_VOLTAGE, \ 274f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .owner = THIS_MODULE, \ 2750e4f417857083f399769491f6e7773d111debd0fAmit Daniel Kachhap .min_uV = MIN_800_MV, \ 2760e4f417857083f399769491f6e7773d111debd0fAmit Daniel Kachhap .uV_step = STEP_6_25_MV, \ 277f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ 278f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .ramp_delay = S2MPA01_RAMP_DELAY, \ 279f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .vsel_reg = S2MPA01_REG_B5CTRL2, \ 280f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \ 281f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .enable_reg = S2MPA01_REG_B5CTRL1, \ 282f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .enable_mask = S2MPA01_ENABLE_MASK \ 283f18792714608a670c2762d22f695d77d02fc965eSachin Kamat} 284f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 285d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap#define regulator_desc_buck6_10(num, min, step) { \ 286f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .name = "BUCK"#num, \ 287f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .id = S2MPA01_BUCK##num, \ 288f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .ops = &s2mpa01_buck_ops, \ 289f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .type = REGULATOR_VOLTAGE, \ 290f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .owner = THIS_MODULE, \ 291d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap .min_uV = min, \ 292d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap .uV_step = step, \ 293f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ 294f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .ramp_delay = S2MPA01_RAMP_DELAY, \ 295f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .vsel_reg = S2MPA01_REG_B6CTRL2 + (num - 6) * 2, \ 296f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \ 297f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .enable_reg = S2MPA01_REG_B6CTRL1 + (num - 6) * 2, \ 298f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .enable_mask = S2MPA01_ENABLE_MASK \ 299f18792714608a670c2762d22f695d77d02fc965eSachin Kamat} 300f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 301f18792714608a670c2762d22f695d77d02fc965eSachin Kamatstatic struct regulator_desc regulators[] = { 302d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(1, STEP_25_MV), 303d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(2, STEP_50_MV), 304d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(3, STEP_50_MV), 305d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(4, STEP_50_MV), 306d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(5, STEP_50_MV), 307d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(6, STEP_25_MV), 308d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(7, STEP_50_MV), 309d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(8, STEP_50_MV), 310d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(9, STEP_50_MV), 311d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(10, STEP_50_MV), 312d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(11, STEP_25_MV), 313d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(12, STEP_50_MV), 314d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(13, STEP_50_MV), 315d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(14, STEP_50_MV), 316d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(15, STEP_50_MV), 317d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(16, STEP_50_MV), 318d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(17, STEP_50_MV), 319d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(18, STEP_50_MV), 320d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(19, STEP_50_MV), 321d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(20, STEP_50_MV), 322d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(21, STEP_50_MV), 323d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(22, STEP_25_MV), 324d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(23, STEP_25_MV), 325d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(24, STEP_50_MV), 326d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(25, STEP_50_MV), 327d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_ldo(26, STEP_50_MV), 328f18792714608a670c2762d22f695d77d02fc965eSachin Kamat regulator_desc_buck1_4(1), 329f18792714608a670c2762d22f695d77d02fc965eSachin Kamat regulator_desc_buck1_4(2), 330f18792714608a670c2762d22f695d77d02fc965eSachin Kamat regulator_desc_buck1_4(3), 331f18792714608a670c2762d22f695d77d02fc965eSachin Kamat regulator_desc_buck1_4(4), 332f18792714608a670c2762d22f695d77d02fc965eSachin Kamat regulator_desc_buck5, 333d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_buck6_10(6, MIN_600_MV, STEP_6_25_MV), 334d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_buck6_10(7, MIN_600_MV, STEP_6_25_MV), 335d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_buck6_10(8, MIN_800_MV, STEP_12_5_MV), 336d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_buck6_10(9, MIN_1500_MV, STEP_12_5_MV), 337d264fd4541753bf3fe2613805b3cab95b54a3f32Amit Daniel Kachhap regulator_desc_buck6_10(10, MIN_1000_MV, STEP_12_5_MV), 338f18792714608a670c2762d22f695d77d02fc965eSachin Kamat}; 339f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 340f18792714608a670c2762d22f695d77d02fc965eSachin Kamatstatic int s2mpa01_pmic_probe(struct platform_device *pdev) 341f18792714608a670c2762d22f695d77d02fc965eSachin Kamat{ 342f18792714608a670c2762d22f695d77d02fc965eSachin Kamat struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); 343f18792714608a670c2762d22f695d77d02fc965eSachin Kamat struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); 344282179105d5403d991d2510ec74d1031695b3ef0Javier Martinez Canillas struct of_regulator_match rdata[S2MPA01_REGULATOR_MAX] = { }; 345f18792714608a670c2762d22f695d77d02fc965eSachin Kamat struct device_node *reg_np = NULL; 346f18792714608a670c2762d22f695d77d02fc965eSachin Kamat struct regulator_config config = { }; 347f18792714608a670c2762d22f695d77d02fc965eSachin Kamat struct s2mpa01_info *s2mpa01; 348f18792714608a670c2762d22f695d77d02fc965eSachin Kamat int i; 349f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 350f18792714608a670c2762d22f695d77d02fc965eSachin Kamat s2mpa01 = devm_kzalloc(&pdev->dev, sizeof(*s2mpa01), GFP_KERNEL); 351f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (!s2mpa01) 352f18792714608a670c2762d22f695d77d02fc965eSachin Kamat return -ENOMEM; 353f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 354f18792714608a670c2762d22f695d77d02fc965eSachin Kamat for (i = 0; i < S2MPA01_REGULATOR_CNT; i++) 355f18792714608a670c2762d22f695d77d02fc965eSachin Kamat rdata[i].name = regulators[i].name; 356f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 357f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (iodev->dev->of_node) { 358f18792714608a670c2762d22f695d77d02fc965eSachin Kamat reg_np = of_get_child_by_name(iodev->dev->of_node, 359f18792714608a670c2762d22f695d77d02fc965eSachin Kamat "regulators"); 360f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (!reg_np) { 361f18792714608a670c2762d22f695d77d02fc965eSachin Kamat dev_err(&pdev->dev, 362f18792714608a670c2762d22f695d77d02fc965eSachin Kamat "could not find regulators sub-node\n"); 363f18792714608a670c2762d22f695d77d02fc965eSachin Kamat return -EINVAL; 364f18792714608a670c2762d22f695d77d02fc965eSachin Kamat } 365f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 366f18792714608a670c2762d22f695d77d02fc965eSachin Kamat of_regulator_match(&pdev->dev, reg_np, rdata, 367f18792714608a670c2762d22f695d77d02fc965eSachin Kamat S2MPA01_REGULATOR_MAX); 368f18792714608a670c2762d22f695d77d02fc965eSachin Kamat of_node_put(reg_np); 369f18792714608a670c2762d22f695d77d02fc965eSachin Kamat } 370f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 371f18792714608a670c2762d22f695d77d02fc965eSachin Kamat platform_set_drvdata(pdev, s2mpa01); 372f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 373f18792714608a670c2762d22f695d77d02fc965eSachin Kamat config.dev = &pdev->dev; 374f18792714608a670c2762d22f695d77d02fc965eSachin Kamat config.regmap = iodev->regmap_pmic; 375f18792714608a670c2762d22f695d77d02fc965eSachin Kamat config.driver_data = s2mpa01; 376f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 377f18792714608a670c2762d22f695d77d02fc965eSachin Kamat for (i = 0; i < S2MPA01_REGULATOR_MAX; i++) { 378f18792714608a670c2762d22f695d77d02fc965eSachin Kamat struct regulator_dev *rdev; 379f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (pdata) 380f18792714608a670c2762d22f695d77d02fc965eSachin Kamat config.init_data = pdata->regulators[i].initdata; 381f18792714608a670c2762d22f695d77d02fc965eSachin Kamat else 382f18792714608a670c2762d22f695d77d02fc965eSachin Kamat config.init_data = rdata[i].init_data; 383f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 384f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (reg_np) 385f18792714608a670c2762d22f695d77d02fc965eSachin Kamat config.of_node = rdata[i].of_node; 386f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 387f18792714608a670c2762d22f695d77d02fc965eSachin Kamat rdev = devm_regulator_register(&pdev->dev, 388f18792714608a670c2762d22f695d77d02fc965eSachin Kamat ®ulators[i], &config); 389f18792714608a670c2762d22f695d77d02fc965eSachin Kamat if (IS_ERR(rdev)) { 390f18792714608a670c2762d22f695d77d02fc965eSachin Kamat dev_err(&pdev->dev, "regulator init failed for %d\n", 391f18792714608a670c2762d22f695d77d02fc965eSachin Kamat i); 392f18792714608a670c2762d22f695d77d02fc965eSachin Kamat return PTR_ERR(rdev); 393f18792714608a670c2762d22f695d77d02fc965eSachin Kamat } 394f18792714608a670c2762d22f695d77d02fc965eSachin Kamat } 395f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 396f18792714608a670c2762d22f695d77d02fc965eSachin Kamat return 0; 397f18792714608a670c2762d22f695d77d02fc965eSachin Kamat} 398f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 399f18792714608a670c2762d22f695d77d02fc965eSachin Kamatstatic const struct platform_device_id s2mpa01_pmic_id[] = { 400f18792714608a670c2762d22f695d77d02fc965eSachin Kamat { "s2mpa01-pmic", 0}, 401f18792714608a670c2762d22f695d77d02fc965eSachin Kamat { }, 402f18792714608a670c2762d22f695d77d02fc965eSachin Kamat}; 403f18792714608a670c2762d22f695d77d02fc965eSachin KamatMODULE_DEVICE_TABLE(platform, s2mpa01_pmic_id); 404f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 405f18792714608a670c2762d22f695d77d02fc965eSachin Kamatstatic struct platform_driver s2mpa01_pmic_driver = { 406f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .driver = { 407f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .name = "s2mpa01-pmic", 408f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .owner = THIS_MODULE, 409f18792714608a670c2762d22f695d77d02fc965eSachin Kamat }, 410f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .probe = s2mpa01_pmic_probe, 411f18792714608a670c2762d22f695d77d02fc965eSachin Kamat .id_table = s2mpa01_pmic_id, 412f18792714608a670c2762d22f695d77d02fc965eSachin Kamat}; 413f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 414f18792714608a670c2762d22f695d77d02fc965eSachin Kamatmodule_platform_driver(s2mpa01_pmic_driver); 415f18792714608a670c2762d22f695d77d02fc965eSachin Kamat 416f18792714608a670c2762d22f695d77d02fc965eSachin Kamat/* Module information */ 417f18792714608a670c2762d22f695d77d02fc965eSachin KamatMODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); 418f18792714608a670c2762d22f695d77d02fc965eSachin KamatMODULE_AUTHOR("Sachin Kamat <sachin.kamat@samsung.com>"); 419f18792714608a670c2762d22f695d77d02fc965eSachin KamatMODULE_DESCRIPTION("SAMSUNG S2MPA01 Regulator Driver"); 420f18792714608a670c2762d22f695d77d02fc965eSachin KamatMODULE_LICENSE("GPL"); 421