1be0e2d3eSHaojian Zhuang /* 2be0e2d3eSHaojian Zhuang * Regulators driver for Marvell 88PM8607 3be0e2d3eSHaojian Zhuang * 4be0e2d3eSHaojian Zhuang * Copyright (C) 2009 Marvell International Ltd. 5be0e2d3eSHaojian Zhuang * Haojian Zhuang <haojian.zhuang@marvell.com> 6be0e2d3eSHaojian Zhuang * 7be0e2d3eSHaojian Zhuang * This program is free software; you can redistribute it and/or modify 8be0e2d3eSHaojian Zhuang * it under the terms of the GNU General Public License version 2 as 9be0e2d3eSHaojian Zhuang * published by the Free Software Foundation. 10be0e2d3eSHaojian Zhuang */ 11be0e2d3eSHaojian Zhuang #include <linux/kernel.h> 12be0e2d3eSHaojian Zhuang #include <linux/init.h> 13be0e2d3eSHaojian Zhuang #include <linux/err.h> 1453dbab7aSHaojian Zhuang #include <linux/i2c.h> 152e57d567SHaojian Zhuang #include <linux/of.h> 162e57d567SHaojian Zhuang #include <linux/regulator/of_regulator.h> 17be0e2d3eSHaojian Zhuang #include <linux/platform_device.h> 18be0e2d3eSHaojian Zhuang #include <linux/regulator/driver.h> 19be0e2d3eSHaojian Zhuang #include <linux/regulator/machine.h> 2053dbab7aSHaojian Zhuang #include <linux/mfd/88pm860x.h> 2165602c32SPaul Gortmaker #include <linux/module.h> 22be0e2d3eSHaojian Zhuang 23be0e2d3eSHaojian Zhuang struct pm8607_regulator_info { 24be0e2d3eSHaojian Zhuang struct regulator_desc desc; 2553dbab7aSHaojian Zhuang struct pm860x_chip *chip; 26be0e2d3eSHaojian Zhuang struct regulator_dev *regulator; 2753dbab7aSHaojian Zhuang struct i2c_client *i2c; 28e7a7810aSJett.Zhou struct i2c_client *i2c_8606; 29be0e2d3eSHaojian Zhuang 309f79e9dbSHaojian Zhuang unsigned int *vol_suspend; 319f79e9dbSHaojian Zhuang 32be0e2d3eSHaojian Zhuang int slope_double; 33be0e2d3eSHaojian Zhuang }; 34be0e2d3eSHaojian Zhuang 359f79e9dbSHaojian Zhuang static const unsigned int BUCK1_table[] = { 369f79e9dbSHaojian Zhuang 725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000, 379f79e9dbSHaojian Zhuang 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000, 389f79e9dbSHaojian Zhuang 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, 399f79e9dbSHaojian Zhuang 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000, 409f79e9dbSHaojian Zhuang 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000, 419f79e9dbSHaojian Zhuang 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000, 429f79e9dbSHaojian Zhuang 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000, 439f79e9dbSHaojian Zhuang 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, 449f79e9dbSHaojian Zhuang }; 45be0e2d3eSHaojian Zhuang 469f79e9dbSHaojian Zhuang static const unsigned int BUCK1_suspend_table[] = { 479f79e9dbSHaojian Zhuang 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000, 489f79e9dbSHaojian Zhuang 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000, 499f79e9dbSHaojian Zhuang 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000, 509f79e9dbSHaojian Zhuang 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, 519f79e9dbSHaojian Zhuang 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, 529f79e9dbSHaojian Zhuang 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 539f79e9dbSHaojian Zhuang 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 549f79e9dbSHaojian Zhuang 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000, 559f79e9dbSHaojian Zhuang }; 569f79e9dbSHaojian Zhuang 579f79e9dbSHaojian Zhuang static const unsigned int BUCK2_table[] = { 589f79e9dbSHaojian Zhuang 0, 50000, 100000, 150000, 200000, 250000, 300000, 350000, 599f79e9dbSHaojian Zhuang 400000, 450000, 500000, 550000, 600000, 650000, 700000, 750000, 609f79e9dbSHaojian Zhuang 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000, 619f79e9dbSHaojian Zhuang 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000, 629f79e9dbSHaojian Zhuang 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000, 639f79e9dbSHaojian Zhuang 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000, 649f79e9dbSHaojian Zhuang 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000, 659f79e9dbSHaojian Zhuang 2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000, 669f79e9dbSHaojian Zhuang }; 679f79e9dbSHaojian Zhuang 689f79e9dbSHaojian Zhuang static const unsigned int BUCK2_suspend_table[] = { 699f79e9dbSHaojian Zhuang 0, 50000, 100000, 150000, 200000, 250000, 300000, 350000, 709f79e9dbSHaojian Zhuang 400000, 450000, 500000, 550000, 600000, 650000, 700000, 750000, 719f79e9dbSHaojian Zhuang 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000, 729f79e9dbSHaojian Zhuang 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000, 739f79e9dbSHaojian Zhuang 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000, 749f79e9dbSHaojian Zhuang 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000, 759f79e9dbSHaojian Zhuang 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000, 769f79e9dbSHaojian Zhuang 2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000, 779f79e9dbSHaojian Zhuang }; 789f79e9dbSHaojian Zhuang 799f79e9dbSHaojian Zhuang static const unsigned int BUCK3_table[] = { 809f79e9dbSHaojian Zhuang 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000, 819f79e9dbSHaojian Zhuang 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000, 829f79e9dbSHaojian Zhuang 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000, 839f79e9dbSHaojian Zhuang 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, 849f79e9dbSHaojian Zhuang 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, 859f79e9dbSHaojian Zhuang 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 869f79e9dbSHaojian Zhuang 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 879f79e9dbSHaojian Zhuang 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000, 889f79e9dbSHaojian Zhuang }; 899f79e9dbSHaojian Zhuang 909f79e9dbSHaojian Zhuang static const unsigned int BUCK3_suspend_table[] = { 919f79e9dbSHaojian Zhuang 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000, 929f79e9dbSHaojian Zhuang 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000, 939f79e9dbSHaojian Zhuang 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000, 949f79e9dbSHaojian Zhuang 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, 959f79e9dbSHaojian Zhuang 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, 969f79e9dbSHaojian Zhuang 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 979f79e9dbSHaojian Zhuang 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 989f79e9dbSHaojian Zhuang 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000, 999f79e9dbSHaojian Zhuang }; 1009f79e9dbSHaojian Zhuang 1019f79e9dbSHaojian Zhuang static const unsigned int LDO1_table[] = { 1029f79e9dbSHaojian Zhuang 1800000, 1200000, 2800000, 0, 1039f79e9dbSHaojian Zhuang }; 1049f79e9dbSHaojian Zhuang 1059f79e9dbSHaojian Zhuang static const unsigned int LDO1_suspend_table[] = { 1069f79e9dbSHaojian Zhuang 1800000, 1200000, 0, 0, 1079f79e9dbSHaojian Zhuang }; 1089f79e9dbSHaojian Zhuang 1099f79e9dbSHaojian Zhuang static const unsigned int LDO2_table[] = { 1109f79e9dbSHaojian Zhuang 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000, 1119f79e9dbSHaojian Zhuang }; 1129f79e9dbSHaojian Zhuang 1139f79e9dbSHaojian Zhuang static const unsigned int LDO2_suspend_table[] = { 1149f79e9dbSHaojian Zhuang 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 1159f79e9dbSHaojian Zhuang }; 1169f79e9dbSHaojian Zhuang 1179f79e9dbSHaojian Zhuang static const unsigned int LDO3_table[] = { 1189f79e9dbSHaojian Zhuang 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000, 1199f79e9dbSHaojian Zhuang }; 1209f79e9dbSHaojian Zhuang 1219f79e9dbSHaojian Zhuang static const unsigned int LDO3_suspend_table[] = { 1229f79e9dbSHaojian Zhuang 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 1239f79e9dbSHaojian Zhuang }; 1249f79e9dbSHaojian Zhuang 1259f79e9dbSHaojian Zhuang static const unsigned int LDO4_table[] = { 1269f79e9dbSHaojian Zhuang 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 3300000, 1279f79e9dbSHaojian Zhuang }; 1289f79e9dbSHaojian Zhuang 1299f79e9dbSHaojian Zhuang static const unsigned int LDO4_suspend_table[] = { 1309f79e9dbSHaojian Zhuang 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 2900000, 1319f79e9dbSHaojian Zhuang }; 1329f79e9dbSHaojian Zhuang 1339f79e9dbSHaojian Zhuang static const unsigned int LDO5_table[] = { 1349f79e9dbSHaojian Zhuang 2900000, 3000000, 3100000, 3300000, 1359f79e9dbSHaojian Zhuang }; 1369f79e9dbSHaojian Zhuang 1379f79e9dbSHaojian Zhuang static const unsigned int LDO5_suspend_table[] = { 1389f79e9dbSHaojian Zhuang 2900000, 0, 0, 0, 1399f79e9dbSHaojian Zhuang }; 1409f79e9dbSHaojian Zhuang 1419f79e9dbSHaojian Zhuang static const unsigned int LDO6_table[] = { 1429f79e9dbSHaojian Zhuang 1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 3300000, 1439f79e9dbSHaojian Zhuang }; 1449f79e9dbSHaojian Zhuang 1459f79e9dbSHaojian Zhuang static const unsigned int LDO6_suspend_table[] = { 1469f79e9dbSHaojian Zhuang 1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 2900000, 1479f79e9dbSHaojian Zhuang }; 1489f79e9dbSHaojian Zhuang 1499f79e9dbSHaojian Zhuang static const unsigned int LDO7_table[] = { 1509f79e9dbSHaojian Zhuang 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 1519f79e9dbSHaojian Zhuang }; 1529f79e9dbSHaojian Zhuang 1539f79e9dbSHaojian Zhuang static const unsigned int LDO7_suspend_table[] = { 1549f79e9dbSHaojian Zhuang 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 1559f79e9dbSHaojian Zhuang }; 1569f79e9dbSHaojian Zhuang 1579f79e9dbSHaojian Zhuang static const unsigned int LDO8_table[] = { 1589f79e9dbSHaojian Zhuang 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 1599f79e9dbSHaojian Zhuang }; 1609f79e9dbSHaojian Zhuang 1619f79e9dbSHaojian Zhuang static const unsigned int LDO8_suspend_table[] = { 1629f79e9dbSHaojian Zhuang 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 1639f79e9dbSHaojian Zhuang }; 1649f79e9dbSHaojian Zhuang 1659f79e9dbSHaojian Zhuang static const unsigned int LDO9_table[] = { 1669f79e9dbSHaojian Zhuang 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000, 1679f79e9dbSHaojian Zhuang }; 1689f79e9dbSHaojian Zhuang 1699f79e9dbSHaojian Zhuang static const unsigned int LDO9_suspend_table[] = { 1709f79e9dbSHaojian Zhuang 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 1719f79e9dbSHaojian Zhuang }; 1729f79e9dbSHaojian Zhuang 1739f79e9dbSHaojian Zhuang static const unsigned int LDO10_table[] = { 1749f79e9dbSHaojian Zhuang 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000, 1759f79e9dbSHaojian Zhuang 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1769f79e9dbSHaojian Zhuang }; 1779f79e9dbSHaojian Zhuang 1789f79e9dbSHaojian Zhuang static const unsigned int LDO10_suspend_table[] = { 1799f79e9dbSHaojian Zhuang 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 1809f79e9dbSHaojian Zhuang 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1819f79e9dbSHaojian Zhuang }; 1829f79e9dbSHaojian Zhuang 1839f79e9dbSHaojian Zhuang static const unsigned int LDO12_table[] = { 1849f79e9dbSHaojian Zhuang 1800000, 1900000, 2700000, 2800000, 2900000, 3000000, 3100000, 3300000, 1859f79e9dbSHaojian Zhuang 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1869f79e9dbSHaojian Zhuang }; 1879f79e9dbSHaojian Zhuang 1889f79e9dbSHaojian Zhuang static const unsigned int LDO12_suspend_table[] = { 1899f79e9dbSHaojian Zhuang 1800000, 1900000, 2700000, 2800000, 2900000, 2900000, 2900000, 2900000, 1909f79e9dbSHaojian Zhuang 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1919f79e9dbSHaojian Zhuang }; 1929f79e9dbSHaojian Zhuang 1939f79e9dbSHaojian Zhuang static const unsigned int LDO13_table[] = { 1943380643bSJett.Zhou 1200000, 1300000, 1800000, 2000000, 2500000, 2800000, 3000000, 0, 1959f79e9dbSHaojian Zhuang }; 1969f79e9dbSHaojian Zhuang 1979f79e9dbSHaojian Zhuang static const unsigned int LDO13_suspend_table[] = { 1989f79e9dbSHaojian Zhuang 0, 1999f79e9dbSHaojian Zhuang }; 2009f79e9dbSHaojian Zhuang 2019f79e9dbSHaojian Zhuang static const unsigned int LDO14_table[] = { 2029f79e9dbSHaojian Zhuang 1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 3300000, 2039f79e9dbSHaojian Zhuang }; 2049f79e9dbSHaojian Zhuang 2059f79e9dbSHaojian Zhuang static const unsigned int LDO14_suspend_table[] = { 2069f79e9dbSHaojian Zhuang 1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 2900000, 2079f79e9dbSHaojian Zhuang }; 208be0e2d3eSHaojian Zhuang 209be0e2d3eSHaojian Zhuang static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) 210be0e2d3eSHaojian Zhuang { 211be0e2d3eSHaojian Zhuang struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); 212*2654d368SAxel Lin int ret; 213be0e2d3eSHaojian Zhuang 214*2654d368SAxel Lin ret = regulator_list_voltage_table(rdev, index); 215*2654d368SAxel Lin if (ret < 0) 216*2654d368SAxel Lin return ret; 217*2654d368SAxel Lin 218be0e2d3eSHaojian Zhuang if (info->slope_double) 219be0e2d3eSHaojian Zhuang ret <<= 1; 220*2654d368SAxel Lin 221be0e2d3eSHaojian Zhuang return ret; 222be0e2d3eSHaojian Zhuang } 223be0e2d3eSHaojian Zhuang 22432cb5d30SBhumika Goyal static const struct regulator_ops pm8607_regulator_ops = { 225d3d7bcccSAxel Lin .list_voltage = pm8607_list_voltage, 226c6f0a0efSAxel Lin .set_voltage_sel = regulator_set_voltage_sel_regmap, 227c006b21fSAxel Lin .get_voltage_sel = regulator_get_voltage_sel_regmap, 228ef26e0dbSAxel Lin .enable = regulator_enable_regmap, 229ef26e0dbSAxel Lin .disable = regulator_disable_regmap, 230ef26e0dbSAxel Lin .is_enabled = regulator_is_enabled_regmap, 231be0e2d3eSHaojian Zhuang }; 232be0e2d3eSHaojian Zhuang 23332cb5d30SBhumika Goyal static const struct regulator_ops pm8606_preg_ops = { 234318c658bSAxel Lin .enable = regulator_enable_regmap, 235318c658bSAxel Lin .disable = regulator_disable_regmap, 236318c658bSAxel Lin .is_enabled = regulator_is_enabled_regmap, 237e7a7810aSJett.Zhou }; 238e7a7810aSJett.Zhou 239e7a7810aSJett.Zhou #define PM8606_PREG(ereg, ebit) \ 240e7a7810aSJett.Zhou { \ 241e7a7810aSJett.Zhou .desc = { \ 242e7a7810aSJett.Zhou .name = "PREG", \ 243e7a7810aSJett.Zhou .ops = &pm8606_preg_ops, \ 244e7a7810aSJett.Zhou .type = REGULATOR_CURRENT, \ 245e7a7810aSJett.Zhou .id = PM8606_ID_PREG, \ 246e7a7810aSJett.Zhou .owner = THIS_MODULE, \ 247e7a7810aSJett.Zhou .enable_reg = PM8606_##ereg, \ 248e7a7810aSJett.Zhou .enable_mask = (ebit), \ 249318c658bSAxel Lin .enable_is_inverted = true, \ 250e7a7810aSJett.Zhou }, \ 251e7a7810aSJett.Zhou } 252e7a7810aSJett.Zhou 25353b6949eSAxel Lin #define PM8607_DVC(vreg, ureg, ubit, ereg, ebit) \ 254be0e2d3eSHaojian Zhuang { \ 255be0e2d3eSHaojian Zhuang .desc = { \ 2569f79e9dbSHaojian Zhuang .name = #vreg, \ 257be0e2d3eSHaojian Zhuang .ops = &pm8607_regulator_ops, \ 258be0e2d3eSHaojian Zhuang .type = REGULATOR_VOLTAGE, \ 2599f79e9dbSHaojian Zhuang .id = PM8607_ID_##vreg, \ 260be0e2d3eSHaojian Zhuang .owner = THIS_MODULE, \ 261*2654d368SAxel Lin .volt_table = vreg##_table, \ 26253b6949eSAxel Lin .n_voltages = ARRAY_SIZE(vreg##_table), \ 263c006b21fSAxel Lin .vsel_reg = PM8607_##vreg, \ 264c006b21fSAxel Lin .vsel_mask = ARRAY_SIZE(vreg##_table) - 1, \ 265c6f0a0efSAxel Lin .apply_reg = PM8607_##ureg, \ 266c6f0a0efSAxel Lin .apply_bit = (ubit), \ 267ef26e0dbSAxel Lin .enable_reg = PM8607_##ereg, \ 268ef26e0dbSAxel Lin .enable_mask = 1 << (ebit), \ 269be0e2d3eSHaojian Zhuang }, \ 270be0e2d3eSHaojian Zhuang .slope_double = (0), \ 2719f79e9dbSHaojian Zhuang .vol_suspend = (unsigned int *)&vreg##_suspend_table, \ 272be0e2d3eSHaojian Zhuang } 273be0e2d3eSHaojian Zhuang 27453b6949eSAxel Lin #define PM8607_LDO(_id, vreg, shift, ereg, ebit) \ 275be0e2d3eSHaojian Zhuang { \ 276be0e2d3eSHaojian Zhuang .desc = { \ 277be0e2d3eSHaojian Zhuang .name = "LDO" #_id, \ 278be0e2d3eSHaojian Zhuang .ops = &pm8607_regulator_ops, \ 279be0e2d3eSHaojian Zhuang .type = REGULATOR_VOLTAGE, \ 280be0e2d3eSHaojian Zhuang .id = PM8607_ID_LDO##_id, \ 281be0e2d3eSHaojian Zhuang .owner = THIS_MODULE, \ 282*2654d368SAxel Lin .volt_table = LDO##_id##_table, \ 28353b6949eSAxel Lin .n_voltages = ARRAY_SIZE(LDO##_id##_table), \ 284c006b21fSAxel Lin .vsel_reg = PM8607_##vreg, \ 285c006b21fSAxel Lin .vsel_mask = (ARRAY_SIZE(LDO##_id##_table) - 1) << (shift), \ 286ef26e0dbSAxel Lin .enable_reg = PM8607_##ereg, \ 287ef26e0dbSAxel Lin .enable_mask = 1 << (ebit), \ 288be0e2d3eSHaojian Zhuang }, \ 289be0e2d3eSHaojian Zhuang .slope_double = (0), \ 2909f79e9dbSHaojian Zhuang .vol_suspend = (unsigned int *)&LDO##_id##_suspend_table, \ 291be0e2d3eSHaojian Zhuang } 292be0e2d3eSHaojian Zhuang 293be0e2d3eSHaojian Zhuang static struct pm8607_regulator_info pm8607_regulator_info[] = { 294c6f0a0efSAxel Lin PM8607_DVC(BUCK1, GO, BIT(0), SUPPLIES_EN11, 0), 295c6f0a0efSAxel Lin PM8607_DVC(BUCK2, GO, BIT(1), SUPPLIES_EN11, 1), 296c6f0a0efSAxel Lin PM8607_DVC(BUCK3, GO, BIT(2), SUPPLIES_EN11, 2), 297be0e2d3eSHaojian Zhuang 29853b6949eSAxel Lin PM8607_LDO(1, LDO1, 0, SUPPLIES_EN11, 3), 29953b6949eSAxel Lin PM8607_LDO(2, LDO2, 0, SUPPLIES_EN11, 4), 30053b6949eSAxel Lin PM8607_LDO(3, LDO3, 0, SUPPLIES_EN11, 5), 30153b6949eSAxel Lin PM8607_LDO(4, LDO4, 0, SUPPLIES_EN11, 6), 30253b6949eSAxel Lin PM8607_LDO(5, LDO5, 0, SUPPLIES_EN11, 7), 30353b6949eSAxel Lin PM8607_LDO(6, LDO6, 0, SUPPLIES_EN12, 0), 30453b6949eSAxel Lin PM8607_LDO(7, LDO7, 0, SUPPLIES_EN12, 1), 30553b6949eSAxel Lin PM8607_LDO(8, LDO8, 0, SUPPLIES_EN12, 2), 30653b6949eSAxel Lin PM8607_LDO(9, LDO9, 0, SUPPLIES_EN12, 3), 30753b6949eSAxel Lin PM8607_LDO(10, LDO10, 0, SUPPLIES_EN12, 4), 30853b6949eSAxel Lin PM8607_LDO(12, LDO12, 0, SUPPLIES_EN12, 5), 30953b6949eSAxel Lin PM8607_LDO(13, VIBRATOR_SET, 1, VIBRATOR_SET, 0), 31053b6949eSAxel Lin PM8607_LDO(14, LDO14, 0, SUPPLIES_EN12, 6), 311ff13e9e2SHaojian Zhuang }; 312e7a7810aSJett.Zhou 313ff13e9e2SHaojian Zhuang static struct pm8607_regulator_info pm8606_regulator_info[] = { 314e7a7810aSJett.Zhou PM8606_PREG(PREREGULATORB, 5), 315be0e2d3eSHaojian Zhuang }; 316be0e2d3eSHaojian Zhuang 3172e57d567SHaojian Zhuang #ifdef CONFIG_OF 3182e57d567SHaojian Zhuang static int pm8607_regulator_dt_init(struct platform_device *pdev, 3192e57d567SHaojian Zhuang struct pm8607_regulator_info *info, 3202e57d567SHaojian Zhuang struct regulator_config *config) 3212e57d567SHaojian Zhuang { 3222e57d567SHaojian Zhuang struct device_node *nproot, *np; 323b8b27a44SGuodong Xu nproot = pdev->dev.parent->of_node; 3242e57d567SHaojian Zhuang if (!nproot) 3252e57d567SHaojian Zhuang return -ENODEV; 326ca1e3f33SSachin Kamat nproot = of_get_child_by_name(nproot, "regulators"); 3272e57d567SHaojian Zhuang if (!nproot) { 3282e57d567SHaojian Zhuang dev_err(&pdev->dev, "failed to find regulators node\n"); 3292e57d567SHaojian Zhuang return -ENODEV; 3302e57d567SHaojian Zhuang } 3312e57d567SHaojian Zhuang for_each_child_of_node(nproot, np) { 332c32569e3SRob Herring if (of_node_name_eq(np, info->desc.name)) { 3332e57d567SHaojian Zhuang config->init_data = 334072e78b1SJavier Martinez Canillas of_get_regulator_init_data(&pdev->dev, np, 335072e78b1SJavier Martinez Canillas &info->desc); 3362e57d567SHaojian Zhuang config->of_node = np; 3372e57d567SHaojian Zhuang break; 3382e57d567SHaojian Zhuang } 3392e57d567SHaojian Zhuang } 340c92f5dd2SAxel Lin of_node_put(nproot); 3412e57d567SHaojian Zhuang return 0; 3422e57d567SHaojian Zhuang } 3432e57d567SHaojian Zhuang #else 3442e57d567SHaojian Zhuang #define pm8607_regulator_dt_init(x, y, z) (-1) 3452e57d567SHaojian Zhuang #endif 3462e57d567SHaojian Zhuang 347a5023574SBill Pemberton static int pm8607_regulator_probe(struct platform_device *pdev) 348be0e2d3eSHaojian Zhuang { 34953dbab7aSHaojian Zhuang struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); 350be0e2d3eSHaojian Zhuang struct pm8607_regulator_info *info = NULL; 351dff91d0bSJingoo Han struct regulator_init_data *pdata = dev_get_platdata(&pdev->dev); 352c172708dSMark Brown struct regulator_config config = { }; 353586e1a17SHaojian Zhuang struct resource *res; 35422aad001SHaojian Zhuang int i; 355be0e2d3eSHaojian Zhuang 35602367029SMark Brown res = platform_get_resource(pdev, IORESOURCE_REG, 0); 357ff13e9e2SHaojian Zhuang if (res) { 358ff13e9e2SHaojian Zhuang /* There're resources in 88PM8607 regulator driver */ 35922aad001SHaojian Zhuang for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) { 36022aad001SHaojian Zhuang info = &pm8607_regulator_info[i]; 361a70abacbSHaojian Zhuang if (info->desc.vsel_reg == res->start) 36222aad001SHaojian Zhuang break; 36322aad001SHaojian Zhuang } 36499cd25ceSAxel Lin if (i == ARRAY_SIZE(pm8607_regulator_info)) { 36509969108SRandy Dunlap dev_err(&pdev->dev, "Failed to find regulator %llu\n", 36609969108SRandy Dunlap (unsigned long long)res->start); 367be0e2d3eSHaojian Zhuang return -EINVAL; 368be0e2d3eSHaojian Zhuang } 369ff13e9e2SHaojian Zhuang } else { 370ff13e9e2SHaojian Zhuang /* There's no resource in 88PM8606 PREG regulator driver */ 371ff13e9e2SHaojian Zhuang info = &pm8606_regulator_info[0]; 372ff13e9e2SHaojian Zhuang /* i is used to check regulator ID */ 373ff13e9e2SHaojian Zhuang i = -1; 374ff13e9e2SHaojian Zhuang } 37553dbab7aSHaojian Zhuang info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; 376e7a7810aSJett.Zhou info->i2c_8606 = (chip->id == CHIP_PM8607) ? chip->companion : 377e7a7810aSJett.Zhou chip->client; 378be0e2d3eSHaojian Zhuang info->chip = chip; 379be0e2d3eSHaojian Zhuang 38022aad001SHaojian Zhuang /* check DVC ramp slope double */ 381586e1a17SHaojian Zhuang if ((i == PM8607_ID_BUCK3) && info->chip->buck3_double) 38222aad001SHaojian Zhuang info->slope_double = 1; 38322aad001SHaojian Zhuang 384c172708dSMark Brown config.dev = &pdev->dev; 385c172708dSMark Brown config.driver_data = info; 386c172708dSMark Brown 3872e57d567SHaojian Zhuang if (pm8607_regulator_dt_init(pdev, info, &config)) 3882e57d567SHaojian Zhuang if (pdata) 3892e57d567SHaojian Zhuang config.init_data = pdata; 3902e57d567SHaojian Zhuang 391ef26e0dbSAxel Lin if (chip->id == CHIP_PM8607) 392ef26e0dbSAxel Lin config.regmap = chip->regmap; 393ef26e0dbSAxel Lin else 394ef26e0dbSAxel Lin config.regmap = chip->regmap_companion; 395ef26e0dbSAxel Lin 396bcb5fe44SAxel Lin info->regulator = devm_regulator_register(&pdev->dev, &info->desc, 397bcb5fe44SAxel Lin &config); 398be0e2d3eSHaojian Zhuang if (IS_ERR(info->regulator)) { 399be0e2d3eSHaojian Zhuang dev_err(&pdev->dev, "failed to register regulator %s\n", 400be0e2d3eSHaojian Zhuang info->desc.name); 401be0e2d3eSHaojian Zhuang return PTR_ERR(info->regulator); 402be0e2d3eSHaojian Zhuang } 403be0e2d3eSHaojian Zhuang 404be0e2d3eSHaojian Zhuang platform_set_drvdata(pdev, info); 405be0e2d3eSHaojian Zhuang return 0; 406be0e2d3eSHaojian Zhuang } 407be0e2d3eSHaojian Zhuang 4080cfeddbdSKrzysztof Kozlowski static const struct platform_device_id pm8607_regulator_driver_ids[] = { 409e7a7810aSJett.Zhou { 410e7a7810aSJett.Zhou .name = "88pm860x-regulator", 411e7a7810aSJett.Zhou .driver_data = 0, 412e7a7810aSJett.Zhou }, { 413e7a7810aSJett.Zhou .name = "88pm860x-preg", 414e7a7810aSJett.Zhou .driver_data = 0, 415e7a7810aSJett.Zhou }, 416e7a7810aSJett.Zhou { }, 417e7a7810aSJett.Zhou }; 418e7a7810aSJett.Zhou MODULE_DEVICE_TABLE(platform, pm8607_regulator_driver_ids); 419e7a7810aSJett.Zhou 420192bbb95SHaojian Zhuang static struct platform_driver pm8607_regulator_driver = { 421192bbb95SHaojian Zhuang .driver = { 422192bbb95SHaojian Zhuang .name = "88pm860x-regulator", 423192bbb95SHaojian Zhuang }, 424192bbb95SHaojian Zhuang .probe = pm8607_regulator_probe, 425e7a7810aSJett.Zhou .id_table = pm8607_regulator_driver_ids, 426be0e2d3eSHaojian Zhuang }; 427be0e2d3eSHaojian Zhuang 428be0e2d3eSHaojian Zhuang static int __init pm8607_regulator_init(void) 429be0e2d3eSHaojian Zhuang { 430192bbb95SHaojian Zhuang return platform_driver_register(&pm8607_regulator_driver); 431be0e2d3eSHaojian Zhuang } 432be0e2d3eSHaojian Zhuang subsys_initcall(pm8607_regulator_init); 433be0e2d3eSHaojian Zhuang 434be0e2d3eSHaojian Zhuang static void __exit pm8607_regulator_exit(void) 435be0e2d3eSHaojian Zhuang { 436192bbb95SHaojian Zhuang platform_driver_unregister(&pm8607_regulator_driver); 437be0e2d3eSHaojian Zhuang } 438be0e2d3eSHaojian Zhuang module_exit(pm8607_regulator_exit); 439be0e2d3eSHaojian Zhuang 440be0e2d3eSHaojian Zhuang MODULE_LICENSE("GPL"); 441be0e2d3eSHaojian Zhuang MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); 442be0e2d3eSHaojian Zhuang MODULE_DESCRIPTION("Regulator Driver for Marvell 88PM8607 PMIC"); 443be0e2d3eSHaojian Zhuang MODULE_ALIAS("platform:88pm8607-regulator"); 444