Commit 1032fbfd792f2b384ac16a63993b8fae5eea9083

Authored by Bengt Jonsson
Committed by Linus Walleij
1 parent f0e733f32e

mach-ux500: voltage domain regulators for DB8500

The DB8500 has ePOD:s (electronic power domains) which are possible
to switch on/off to deactivate silicon blocks on the DB8500 SoC
by cutting their power without retention. We model these as simple
regulators with one bit on/off settings.

Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
Signed-off-by: Sundar Iyer <sundar.iyer@stericsson.com>
Signed-off-by: Jonas Aberg <jonas.aberg@stericsson.com>
Signed-off-by: Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>
Signed-off-by: Martin Persson <martin.persson@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

Showing 6 changed files with 791 additions and 0 deletions Side-by-side Diff

arch/arm/mach-ux500/Kconfig
... ... @@ -17,6 +17,7 @@
17 17 config UX500_SOC_DB8500
18 18 bool "DB8500"
19 19 select MFD_DB8500_PRCMU
  20 + select REGULATOR_DB8500_PRCMU
20 21  
21 22 endmenu
22 23  
drivers/mfd/db8500-prcmu.c
... ... @@ -28,6 +28,8 @@
28 28 #include <linux/uaccess.h>
29 29 #include <linux/mfd/core.h>
30 30 #include <linux/mfd/db8500-prcmu.h>
  31 +#include <linux/regulator/db8500-prcmu.h>
  32 +#include <linux/regulator/machine.h>
31 33 #include <mach/hardware.h>
32 34 #include <mach/irqs.h>
33 35 #include <mach/db8500-regs.h>
34 36  
... ... @@ -1824,9 +1826,186 @@
1824 1826 }
1825 1827 }
1826 1828  
  1829 +/*
  1830 + * Power domain switches (ePODs) modeled as regulators for the DB8500 SoC
  1831 + */
  1832 +static struct regulator_consumer_supply db8500_vape_consumers[] = {
  1833 + REGULATOR_SUPPLY("v-ape", NULL),
  1834 + REGULATOR_SUPPLY("v-i2c", "nmk-i2c.0"),
  1835 + REGULATOR_SUPPLY("v-i2c", "nmk-i2c.1"),
  1836 + REGULATOR_SUPPLY("v-i2c", "nmk-i2c.2"),
  1837 + REGULATOR_SUPPLY("v-i2c", "nmk-i2c.3"),
  1838 + /* "v-mmc" changed to "vcore" in the mainline kernel */
  1839 + REGULATOR_SUPPLY("vcore", "sdi0"),
  1840 + REGULATOR_SUPPLY("vcore", "sdi1"),
  1841 + REGULATOR_SUPPLY("vcore", "sdi2"),
  1842 + REGULATOR_SUPPLY("vcore", "sdi3"),
  1843 + REGULATOR_SUPPLY("vcore", "sdi4"),
  1844 + REGULATOR_SUPPLY("v-dma", "dma40.0"),
  1845 + REGULATOR_SUPPLY("v-ape", "ab8500-usb.0"),
  1846 + /* "v-uart" changed to "vcore" in the mainline kernel */
  1847 + REGULATOR_SUPPLY("vcore", "uart0"),
  1848 + REGULATOR_SUPPLY("vcore", "uart1"),
  1849 + REGULATOR_SUPPLY("vcore", "uart2"),
  1850 + REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"),
  1851 +};
  1852 +
  1853 +static struct regulator_consumer_supply db8500_vsmps2_consumers[] = {
  1854 + /* CG2900 and CW1200 power to off-chip peripherals */
  1855 + REGULATOR_SUPPLY("gbf_1v8", "cg2900-uart.0"),
  1856 + REGULATOR_SUPPLY("wlan_1v8", "cw1200.0"),
  1857 + REGULATOR_SUPPLY("musb_1v8", "ab8500-usb.0"),
  1858 + /* AV8100 regulator */
  1859 + REGULATOR_SUPPLY("hdmi_1v8", "0-0070"),
  1860 +};
  1861 +
  1862 +static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = {
  1863 + REGULATOR_SUPPLY("vsupply", "b2r2.0"),
  1864 + REGULATOR_SUPPLY("vsupply", "mcde.0"),
  1865 +};
  1866 +
  1867 +static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
  1868 + [DB8500_REGULATOR_VAPE] = {
  1869 + .constraints = {
  1870 + .name = "db8500-vape",
  1871 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1872 + },
  1873 + .consumer_supplies = db8500_vape_consumers,
  1874 + .num_consumer_supplies = ARRAY_SIZE(db8500_vape_consumers),
  1875 + },
  1876 + [DB8500_REGULATOR_VARM] = {
  1877 + .constraints = {
  1878 + .name = "db8500-varm",
  1879 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1880 + },
  1881 + },
  1882 + [DB8500_REGULATOR_VMODEM] = {
  1883 + .constraints = {
  1884 + .name = "db8500-vmodem",
  1885 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1886 + },
  1887 + },
  1888 + [DB8500_REGULATOR_VPLL] = {
  1889 + .constraints = {
  1890 + .name = "db8500-vpll",
  1891 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1892 + },
  1893 + },
  1894 + [DB8500_REGULATOR_VSMPS1] = {
  1895 + .constraints = {
  1896 + .name = "db8500-vsmps1",
  1897 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1898 + },
  1899 + },
  1900 + [DB8500_REGULATOR_VSMPS2] = {
  1901 + .constraints = {
  1902 + .name = "db8500-vsmps2",
  1903 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1904 + },
  1905 + .consumer_supplies = db8500_vsmps2_consumers,
  1906 + .num_consumer_supplies = ARRAY_SIZE(db8500_vsmps2_consumers),
  1907 + },
  1908 + [DB8500_REGULATOR_VSMPS3] = {
  1909 + .constraints = {
  1910 + .name = "db8500-vsmps3",
  1911 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1912 + },
  1913 + },
  1914 + [DB8500_REGULATOR_VRF1] = {
  1915 + .constraints = {
  1916 + .name = "db8500-vrf1",
  1917 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1918 + },
  1919 + },
  1920 + [DB8500_REGULATOR_SWITCH_SVAMMDSP] = {
  1921 + .supply_regulator = "db8500-vape",
  1922 + .constraints = {
  1923 + .name = "db8500-sva-mmdsp",
  1924 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1925 + },
  1926 + },
  1927 + [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = {
  1928 + .constraints = {
  1929 + /* "ret" means "retention" */
  1930 + .name = "db8500-sva-mmdsp-ret",
  1931 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1932 + },
  1933 + },
  1934 + [DB8500_REGULATOR_SWITCH_SVAPIPE] = {
  1935 + .supply_regulator = "db8500-vape",
  1936 + .constraints = {
  1937 + .name = "db8500-sva-pipe",
  1938 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1939 + },
  1940 + },
  1941 + [DB8500_REGULATOR_SWITCH_SIAMMDSP] = {
  1942 + .supply_regulator = "db8500-vape",
  1943 + .constraints = {
  1944 + .name = "db8500-sia-mmdsp",
  1945 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1946 + },
  1947 + },
  1948 + [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = {
  1949 + .constraints = {
  1950 + .name = "db8500-sia-mmdsp-ret",
  1951 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1952 + },
  1953 + },
  1954 + [DB8500_REGULATOR_SWITCH_SIAPIPE] = {
  1955 + .supply_regulator = "db8500-vape",
  1956 + .constraints = {
  1957 + .name = "db8500-sia-pipe",
  1958 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1959 + },
  1960 + },
  1961 + [DB8500_REGULATOR_SWITCH_SGA] = {
  1962 + .supply_regulator = "db8500-vape",
  1963 + .constraints = {
  1964 + .name = "db8500-sga",
  1965 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1966 + },
  1967 + },
  1968 + [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = {
  1969 + .supply_regulator = "db8500-vape",
  1970 + .constraints = {
  1971 + .name = "db8500-b2r2-mcde",
  1972 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1973 + },
  1974 + .consumer_supplies = db8500_b2r2_mcde_consumers,
  1975 + .num_consumer_supplies = ARRAY_SIZE(db8500_b2r2_mcde_consumers),
  1976 + },
  1977 + [DB8500_REGULATOR_SWITCH_ESRAM12] = {
  1978 + .supply_regulator = "db8500-vape",
  1979 + .constraints = {
  1980 + .name = "db8500-esram12",
  1981 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1982 + },
  1983 + },
  1984 + [DB8500_REGULATOR_SWITCH_ESRAM12RET] = {
  1985 + .constraints = {
  1986 + .name = "db8500-esram12-ret",
  1987 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1988 + },
  1989 + },
  1990 + [DB8500_REGULATOR_SWITCH_ESRAM34] = {
  1991 + .supply_regulator = "db8500-vape",
  1992 + .constraints = {
  1993 + .name = "db8500-esram34",
  1994 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  1995 + },
  1996 + },
  1997 + [DB8500_REGULATOR_SWITCH_ESRAM34RET] = {
  1998 + .constraints = {
  1999 + .name = "db8500-esram34-ret",
  2000 + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
  2001 + },
  2002 + },
  2003 +};
  2004 +
1827 2005 static struct mfd_cell db8500_prcmu_devs[] = {
1828 2006 {
1829 2007 .name = "db8500-prcmu-regulators",
  2008 + .mfd_data = &db8500_regulators,
1830 2009 },
1831 2010 {
1832 2011 .name = "cpufreq-u8500",
drivers/regulator/Kconfig
... ... @@ -274,6 +274,13 @@
274 274 This driver supports the regulators found on the ST-Ericsson mixed
275 275 signal AB8500 PMIC
276 276  
  277 +config REGULATOR_DB8500_PRCMU
  278 + bool "ST-Ericsson DB8500 Voltage Domain Regulators"
  279 + depends on MFD_DB8500_PRCMU
  280 + help
  281 + This driver supports the voltage domain regulators controlled by the
  282 + DB8500 PRCMU
  283 +
277 284 config REGULATOR_TPS6586X
278 285 tristate "TI TPS6586X Power regulators"
279 286 depends on MFD_TPS6586X
drivers/regulator/Makefile
... ... @@ -41,6 +41,7 @@
41 41 obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
42 42 obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
43 43 obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
  44 +obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
44 45  
45 46 ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
drivers/regulator/db8500-prcmu.c
  1 +/*
  2 + * Copyright (C) ST-Ericsson SA 2010
  3 + *
  4 + * License Terms: GNU General Public License v2
  5 + * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
  6 + * Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
  7 + *
  8 + * Power domain regulators on DB8500
  9 + */
  10 +
  11 +#include <linux/kernel.h>
  12 +#include <linux/init.h>
  13 +#include <linux/err.h>
  14 +#include <linux/spinlock.h>
  15 +#include <linux/platform_device.h>
  16 +#include <linux/mfd/core.h>
  17 +#include <linux/mfd/db8500-prcmu.h>
  18 +#include <linux/regulator/driver.h>
  19 +#include <linux/regulator/machine.h>
  20 +#include <linux/regulator/db8500-prcmu.h>
  21 +
  22 +/*
  23 + * power state reference count
  24 + */
  25 +static int power_state_active_cnt; /* will initialize to zero */
  26 +static DEFINE_SPINLOCK(power_state_active_lock);
  27 +
  28 +static void power_state_active_enable(void)
  29 +{
  30 + unsigned long flags;
  31 +
  32 + spin_lock_irqsave(&power_state_active_lock, flags);
  33 + power_state_active_cnt++;
  34 + spin_unlock_irqrestore(&power_state_active_lock, flags);
  35 +}
  36 +
  37 +static int power_state_active_disable(void)
  38 +{
  39 + int ret = 0;
  40 + unsigned long flags;
  41 +
  42 + spin_lock_irqsave(&power_state_active_lock, flags);
  43 + if (power_state_active_cnt <= 0) {
  44 + pr_err("power state: unbalanced enable/disable calls\n");
  45 + ret = -EINVAL;
  46 + goto out;
  47 + }
  48 +
  49 + power_state_active_cnt--;
  50 +out:
  51 + spin_unlock_irqrestore(&power_state_active_lock, flags);
  52 + return ret;
  53 +}
  54 +
  55 +/*
  56 + * Exported interface for CPUIdle only. This function is called when interrupts
  57 + * are turned off. Hence, no locking.
  58 + */
  59 +int power_state_active_is_enabled(void)
  60 +{
  61 + return (power_state_active_cnt > 0);
  62 +}
  63 +
  64 +/**
  65 + * struct db8500_regulator_info - db8500 regulator information
  66 + * @dev: device pointer
  67 + * @desc: regulator description
  68 + * @rdev: regulator device pointer
  69 + * @is_enabled: status of the regulator
  70 + * @epod_id: id for EPOD (power domain)
  71 + * @is_ramret: RAM retention switch for EPOD (power domain)
  72 + * @operating_point: operating point (only for vape, to be removed)
  73 + *
  74 + */
  75 +struct db8500_regulator_info {
  76 + struct device *dev;
  77 + struct regulator_desc desc;
  78 + struct regulator_dev *rdev;
  79 + bool is_enabled;
  80 + u16 epod_id;
  81 + bool is_ramret;
  82 + bool exclude_from_power_state;
  83 + unsigned int operating_point;
  84 +};
  85 +
  86 +static int db8500_regulator_enable(struct regulator_dev *rdev)
  87 +{
  88 + struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
  89 +
  90 + if (info == NULL)
  91 + return -EINVAL;
  92 +
  93 + dev_vdbg(rdev_get_dev(rdev), "regulator-%s-enable\n",
  94 + info->desc.name);
  95 +
  96 + info->is_enabled = true;
  97 + if (!info->exclude_from_power_state)
  98 + power_state_active_enable();
  99 +
  100 + return 0;
  101 +}
  102 +
  103 +static int db8500_regulator_disable(struct regulator_dev *rdev)
  104 +{
  105 + struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
  106 + int ret = 0;
  107 +
  108 + if (info == NULL)
  109 + return -EINVAL;
  110 +
  111 + dev_vdbg(rdev_get_dev(rdev), "regulator-%s-disable\n",
  112 + info->desc.name);
  113 +
  114 + info->is_enabled = false;
  115 + if (!info->exclude_from_power_state)
  116 + ret = power_state_active_disable();
  117 +
  118 + return ret;
  119 +}
  120 +
  121 +static int db8500_regulator_is_enabled(struct regulator_dev *rdev)
  122 +{
  123 + struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
  124 +
  125 + if (info == NULL)
  126 + return -EINVAL;
  127 +
  128 + dev_vdbg(rdev_get_dev(rdev), "regulator-%s-is_enabled (is_enabled):"
  129 + " %i\n", info->desc.name, info->is_enabled);
  130 +
  131 + return info->is_enabled;
  132 +}
  133 +
  134 +/* db8500 regulator operations */
  135 +static struct regulator_ops db8500_regulator_ops = {
  136 + .enable = db8500_regulator_enable,
  137 + .disable = db8500_regulator_disable,
  138 + .is_enabled = db8500_regulator_is_enabled,
  139 +};
  140 +
  141 +/*
  142 + * EPOD control
  143 + */
  144 +static bool epod_on[NUM_EPOD_ID];
  145 +static bool epod_ramret[NUM_EPOD_ID];
  146 +
  147 +static int enable_epod(u16 epod_id, bool ramret)
  148 +{
  149 + int ret;
  150 +
  151 + if (ramret) {
  152 + if (!epod_on[epod_id]) {
  153 + ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
  154 + if (ret < 0)
  155 + return ret;
  156 + }
  157 + epod_ramret[epod_id] = true;
  158 + } else {
  159 + ret = prcmu_set_epod(epod_id, EPOD_STATE_ON);
  160 + if (ret < 0)
  161 + return ret;
  162 + epod_on[epod_id] = true;
  163 + }
  164 +
  165 + return 0;
  166 +}
  167 +
  168 +static int disable_epod(u16 epod_id, bool ramret)
  169 +{
  170 + int ret;
  171 +
  172 + if (ramret) {
  173 + if (!epod_on[epod_id]) {
  174 + ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF);
  175 + if (ret < 0)
  176 + return ret;
  177 + }
  178 + epod_ramret[epod_id] = false;
  179 + } else {
  180 + if (epod_ramret[epod_id]) {
  181 + ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
  182 + if (ret < 0)
  183 + return ret;
  184 + } else {
  185 + ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF);
  186 + if (ret < 0)
  187 + return ret;
  188 + }
  189 + epod_on[epod_id] = false;
  190 + }
  191 +
  192 + return 0;
  193 +}
  194 +
  195 +/*
  196 + * Regulator switch
  197 + */
  198 +static int db8500_regulator_switch_enable(struct regulator_dev *rdev)
  199 +{
  200 + struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
  201 + int ret;
  202 +
  203 + if (info == NULL)
  204 + return -EINVAL;
  205 +
  206 + dev_vdbg(rdev_get_dev(rdev), "regulator-switch-%s-enable\n",
  207 + info->desc.name);
  208 +
  209 + ret = enable_epod(info->epod_id, info->is_ramret);
  210 + if (ret < 0) {
  211 + dev_err(rdev_get_dev(rdev),
  212 + "regulator-switch-%s-enable: prcmu call failed\n",
  213 + info->desc.name);
  214 + goto out;
  215 + }
  216 +
  217 + info->is_enabled = true;
  218 +out:
  219 + return ret;
  220 +}
  221 +
  222 +static int db8500_regulator_switch_disable(struct regulator_dev *rdev)
  223 +{
  224 + struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
  225 + int ret;
  226 +
  227 + if (info == NULL)
  228 + return -EINVAL;
  229 +
  230 + dev_vdbg(rdev_get_dev(rdev), "regulator-switch-%s-disable\n",
  231 + info->desc.name);
  232 +
  233 + ret = disable_epod(info->epod_id, info->is_ramret);
  234 + if (ret < 0) {
  235 + dev_err(rdev_get_dev(rdev),
  236 + "regulator_switch-%s-disable: prcmu call failed\n",
  237 + info->desc.name);
  238 + goto out;
  239 + }
  240 +
  241 + info->is_enabled = 0;
  242 +out:
  243 + return ret;
  244 +}
  245 +
  246 +static int db8500_regulator_switch_is_enabled(struct regulator_dev *rdev)
  247 +{
  248 + struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
  249 +
  250 + if (info == NULL)
  251 + return -EINVAL;
  252 +
  253 + dev_vdbg(rdev_get_dev(rdev),
  254 + "regulator-switch-%s-is_enabled (is_enabled): %i\n",
  255 + info->desc.name, info->is_enabled);
  256 +
  257 + return info->is_enabled;
  258 +}
  259 +
  260 +static struct regulator_ops db8500_regulator_switch_ops = {
  261 + .enable = db8500_regulator_switch_enable,
  262 + .disable = db8500_regulator_switch_disable,
  263 + .is_enabled = db8500_regulator_switch_is_enabled,
  264 +};
  265 +
  266 +/*
  267 + * Regulator information
  268 + */
  269 +static struct db8500_regulator_info
  270 + db8500_regulator_info[DB8500_NUM_REGULATORS] = {
  271 + [DB8500_REGULATOR_VAPE] = {
  272 + .desc = {
  273 + .name = "db8500-vape",
  274 + .id = DB8500_REGULATOR_VAPE,
  275 + .ops = &db8500_regulator_ops,
  276 + .type = REGULATOR_VOLTAGE,
  277 + .owner = THIS_MODULE,
  278 + },
  279 + },
  280 + [DB8500_REGULATOR_VARM] = {
  281 + .desc = {
  282 + .name = "db8500-varm",
  283 + .id = DB8500_REGULATOR_VARM,
  284 + .ops = &db8500_regulator_ops,
  285 + .type = REGULATOR_VOLTAGE,
  286 + .owner = THIS_MODULE,
  287 + },
  288 + },
  289 + [DB8500_REGULATOR_VMODEM] = {
  290 + .desc = {
  291 + .name = "db8500-vmodem",
  292 + .id = DB8500_REGULATOR_VMODEM,
  293 + .ops = &db8500_regulator_ops,
  294 + .type = REGULATOR_VOLTAGE,
  295 + .owner = THIS_MODULE,
  296 + },
  297 + },
  298 + [DB8500_REGULATOR_VPLL] = {
  299 + .desc = {
  300 + .name = "db8500-vpll",
  301 + .id = DB8500_REGULATOR_VPLL,
  302 + .ops = &db8500_regulator_ops,
  303 + .type = REGULATOR_VOLTAGE,
  304 + .owner = THIS_MODULE,
  305 + },
  306 + },
  307 + [DB8500_REGULATOR_VSMPS1] = {
  308 + .desc = {
  309 + .name = "db8500-vsmps1",
  310 + .id = DB8500_REGULATOR_VSMPS1,
  311 + .ops = &db8500_regulator_ops,
  312 + .type = REGULATOR_VOLTAGE,
  313 + .owner = THIS_MODULE,
  314 + },
  315 + },
  316 + [DB8500_REGULATOR_VSMPS2] = {
  317 + .desc = {
  318 + .name = "db8500-vsmps2",
  319 + .id = DB8500_REGULATOR_VSMPS2,
  320 + .ops = &db8500_regulator_ops,
  321 + .type = REGULATOR_VOLTAGE,
  322 + .owner = THIS_MODULE,
  323 + },
  324 + .exclude_from_power_state = true,
  325 + },
  326 + [DB8500_REGULATOR_VSMPS3] = {
  327 + .desc = {
  328 + .name = "db8500-vsmps3",
  329 + .id = DB8500_REGULATOR_VSMPS3,
  330 + .ops = &db8500_regulator_ops,
  331 + .type = REGULATOR_VOLTAGE,
  332 + .owner = THIS_MODULE,
  333 + },
  334 + },
  335 + [DB8500_REGULATOR_VRF1] = {
  336 + .desc = {
  337 + .name = "db8500-vrf1",
  338 + .id = DB8500_REGULATOR_VRF1,
  339 + .ops = &db8500_regulator_ops,
  340 + .type = REGULATOR_VOLTAGE,
  341 + .owner = THIS_MODULE,
  342 + },
  343 + },
  344 + [DB8500_REGULATOR_SWITCH_SVAMMDSP] = {
  345 + .desc = {
  346 + .name = "db8500-sva-mmdsp",
  347 + .id = DB8500_REGULATOR_SWITCH_SVAMMDSP,
  348 + .ops = &db8500_regulator_switch_ops,
  349 + .type = REGULATOR_VOLTAGE,
  350 + .owner = THIS_MODULE,
  351 + },
  352 + .epod_id = EPOD_ID_SVAMMDSP,
  353 + },
  354 + [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = {
  355 + .desc = {
  356 + .name = "db8500-sva-mmdsp-ret",
  357 + .id = DB8500_REGULATOR_SWITCH_SVAMMDSPRET,
  358 + .ops = &db8500_regulator_switch_ops,
  359 + .type = REGULATOR_VOLTAGE,
  360 + .owner = THIS_MODULE,
  361 + },
  362 + .epod_id = EPOD_ID_SVAMMDSP,
  363 + .is_ramret = true,
  364 + },
  365 + [DB8500_REGULATOR_SWITCH_SVAPIPE] = {
  366 + .desc = {
  367 + .name = "db8500-sva-pipe",
  368 + .id = DB8500_REGULATOR_SWITCH_SVAPIPE,
  369 + .ops = &db8500_regulator_switch_ops,
  370 + .type = REGULATOR_VOLTAGE,
  371 + .owner = THIS_MODULE,
  372 + },
  373 + .epod_id = EPOD_ID_SVAPIPE,
  374 + },
  375 + [DB8500_REGULATOR_SWITCH_SIAMMDSP] = {
  376 + .desc = {
  377 + .name = "db8500-sia-mmdsp",
  378 + .id = DB8500_REGULATOR_SWITCH_SIAMMDSP,
  379 + .ops = &db8500_regulator_switch_ops,
  380 + .type = REGULATOR_VOLTAGE,
  381 + .owner = THIS_MODULE,
  382 + },
  383 + .epod_id = EPOD_ID_SIAMMDSP,
  384 + },
  385 + [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = {
  386 + .desc = {
  387 + .name = "db8500-sia-mmdsp-ret",
  388 + .id = DB8500_REGULATOR_SWITCH_SIAMMDSPRET,
  389 + .ops = &db8500_regulator_switch_ops,
  390 + .type = REGULATOR_VOLTAGE,
  391 + .owner = THIS_MODULE,
  392 + },
  393 + .epod_id = EPOD_ID_SIAMMDSP,
  394 + .is_ramret = true,
  395 + },
  396 + [DB8500_REGULATOR_SWITCH_SIAPIPE] = {
  397 + .desc = {
  398 + .name = "db8500-sia-pipe",
  399 + .id = DB8500_REGULATOR_SWITCH_SIAPIPE,
  400 + .ops = &db8500_regulator_switch_ops,
  401 + .type = REGULATOR_VOLTAGE,
  402 + .owner = THIS_MODULE,
  403 + },
  404 + .epod_id = EPOD_ID_SIAPIPE,
  405 + },
  406 + [DB8500_REGULATOR_SWITCH_SGA] = {
  407 + .desc = {
  408 + .name = "db8500-sga",
  409 + .id = DB8500_REGULATOR_SWITCH_SGA,
  410 + .ops = &db8500_regulator_switch_ops,
  411 + .type = REGULATOR_VOLTAGE,
  412 + .owner = THIS_MODULE,
  413 + },
  414 + .epod_id = EPOD_ID_SGA,
  415 + },
  416 + [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = {
  417 + .desc = {
  418 + .name = "db8500-b2r2-mcde",
  419 + .id = DB8500_REGULATOR_SWITCH_B2R2_MCDE,
  420 + .ops = &db8500_regulator_switch_ops,
  421 + .type = REGULATOR_VOLTAGE,
  422 + .owner = THIS_MODULE,
  423 + },
  424 + .epod_id = EPOD_ID_B2R2_MCDE,
  425 + },
  426 + [DB8500_REGULATOR_SWITCH_ESRAM12] = {
  427 + .desc = {
  428 + .name = "db8500-esram12",
  429 + .id = DB8500_REGULATOR_SWITCH_ESRAM12,
  430 + .ops = &db8500_regulator_switch_ops,
  431 + .type = REGULATOR_VOLTAGE,
  432 + .owner = THIS_MODULE,
  433 + },
  434 + .epod_id = EPOD_ID_ESRAM12,
  435 + .is_enabled = true,
  436 + },
  437 + [DB8500_REGULATOR_SWITCH_ESRAM12RET] = {
  438 + .desc = {
  439 + .name = "db8500-esram12-ret",
  440 + .id = DB8500_REGULATOR_SWITCH_ESRAM12RET,
  441 + .ops = &db8500_regulator_switch_ops,
  442 + .type = REGULATOR_VOLTAGE,
  443 + .owner = THIS_MODULE,
  444 + },
  445 + .epod_id = EPOD_ID_ESRAM12,
  446 + .is_ramret = true,
  447 + },
  448 + [DB8500_REGULATOR_SWITCH_ESRAM34] = {
  449 + .desc = {
  450 + .name = "db8500-esram34",
  451 + .id = DB8500_REGULATOR_SWITCH_ESRAM34,
  452 + .ops = &db8500_regulator_switch_ops,
  453 + .type = REGULATOR_VOLTAGE,
  454 + .owner = THIS_MODULE,
  455 + },
  456 + .epod_id = EPOD_ID_ESRAM34,
  457 + .is_enabled = true,
  458 + },
  459 + [DB8500_REGULATOR_SWITCH_ESRAM34RET] = {
  460 + .desc = {
  461 + .name = "db8500-esram34-ret",
  462 + .id = DB8500_REGULATOR_SWITCH_ESRAM34RET,
  463 + .ops = &db8500_regulator_switch_ops,
  464 + .type = REGULATOR_VOLTAGE,
  465 + .owner = THIS_MODULE,
  466 + },
  467 + .epod_id = EPOD_ID_ESRAM34,
  468 + .is_ramret = true,
  469 + },
  470 +};
  471 +
  472 +static int __devinit db8500_regulator_probe(struct platform_device *pdev)
  473 +{
  474 + struct regulator_init_data *db8500_init_data = mfd_get_data(pdev);
  475 + int i, err;
  476 +
  477 + /* register all regulators */
  478 + for (i = 0; i < ARRAY_SIZE(db8500_regulator_info); i++) {
  479 + struct db8500_regulator_info *info;
  480 + struct regulator_init_data *init_data = &db8500_init_data[i];
  481 +
  482 + /* assign per-regulator data */
  483 + info = &db8500_regulator_info[i];
  484 + info->dev = &pdev->dev;
  485 +
  486 + /* register with the regulator framework */
  487 + info->rdev = regulator_register(&info->desc, &pdev->dev,
  488 + init_data, info);
  489 + if (IS_ERR(info->rdev)) {
  490 + err = PTR_ERR(info->rdev);
  491 + dev_err(&pdev->dev, "failed to register %s: err %i\n",
  492 + info->desc.name, err);
  493 +
  494 + /* if failing, unregister all earlier regulators */
  495 + i--;
  496 + while (i >= 0) {
  497 + info = &db8500_regulator_info[i];
  498 + regulator_unregister(info->rdev);
  499 + i--;
  500 + }
  501 + return err;
  502 + }
  503 +
  504 + dev_dbg(rdev_get_dev(info->rdev),
  505 + "regulator-%s-probed\n", info->desc.name);
  506 + }
  507 +
  508 + return 0;
  509 +}
  510 +
  511 +static int __exit db8500_regulator_remove(struct platform_device *pdev)
  512 +{
  513 + int i;
  514 +
  515 + for (i = 0; i < ARRAY_SIZE(db8500_regulator_info); i++) {
  516 + struct db8500_regulator_info *info;
  517 + info = &db8500_regulator_info[i];
  518 +
  519 + dev_vdbg(rdev_get_dev(info->rdev),
  520 + "regulator-%s-remove\n", info->desc.name);
  521 +
  522 + regulator_unregister(info->rdev);
  523 + }
  524 +
  525 + return 0;
  526 +}
  527 +
  528 +static struct platform_driver db8500_regulator_driver = {
  529 + .driver = {
  530 + .name = "db8500-prcmu-regulators",
  531 + .owner = THIS_MODULE,
  532 + },
  533 + .probe = db8500_regulator_probe,
  534 + .remove = __exit_p(db8500_regulator_remove),
  535 +};
  536 +
  537 +static int __init db8500_regulator_init(void)
  538 +{
  539 + int ret;
  540 +
  541 + ret = platform_driver_register(&db8500_regulator_driver);
  542 + if (ret < 0)
  543 + return -ENODEV;
  544 +
  545 + return 0;
  546 +}
  547 +
  548 +static void __exit db8500_regulator_exit(void)
  549 +{
  550 + platform_driver_unregister(&db8500_regulator_driver);
  551 +}
  552 +
  553 +arch_initcall(db8500_regulator_init);
  554 +module_exit(db8500_regulator_exit);
  555 +
  556 +MODULE_AUTHOR("STMicroelectronics/ST-Ericsson");
  557 +MODULE_DESCRIPTION("DB8500 regulator driver");
  558 +MODULE_LICENSE("GPL v2");
include/linux/regulator/db8500-prcmu.h
  1 +/*
  2 + * Copyright (C) ST-Ericsson SA 2010
  3 + *
  4 + * License Terms: GNU General Public License v2
  5 + *
  6 + * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
  7 + *
  8 + * Interface to power domain regulators on DB8500
  9 + */
  10 +
  11 +#ifndef __REGULATOR_H__
  12 +#define __REGULATOR_H__
  13 +
  14 +/* Number of DB8500 regulators and regulator enumeration */
  15 +enum db8500_regulator_id {
  16 + DB8500_REGULATOR_VAPE,
  17 + DB8500_REGULATOR_VARM,
  18 + DB8500_REGULATOR_VMODEM,
  19 + DB8500_REGULATOR_VPLL,
  20 + DB8500_REGULATOR_VSMPS1,
  21 + DB8500_REGULATOR_VSMPS2,
  22 + DB8500_REGULATOR_VSMPS3,
  23 + DB8500_REGULATOR_VRF1,
  24 + DB8500_REGULATOR_SWITCH_SVAMMDSP,
  25 + DB8500_REGULATOR_SWITCH_SVAMMDSPRET,
  26 + DB8500_REGULATOR_SWITCH_SVAPIPE,
  27 + DB8500_REGULATOR_SWITCH_SIAMMDSP,
  28 + DB8500_REGULATOR_SWITCH_SIAMMDSPRET,
  29 + DB8500_REGULATOR_SWITCH_SIAPIPE,
  30 + DB8500_REGULATOR_SWITCH_SGA,
  31 + DB8500_REGULATOR_SWITCH_B2R2_MCDE,
  32 + DB8500_REGULATOR_SWITCH_ESRAM12,
  33 + DB8500_REGULATOR_SWITCH_ESRAM12RET,
  34 + DB8500_REGULATOR_SWITCH_ESRAM34,
  35 + DB8500_REGULATOR_SWITCH_ESRAM34RET,
  36 + DB8500_NUM_REGULATORS
  37 +};
  38 +
  39 +/*
  40 + * Exported interface for CPUIdle only. This function is called with all
  41 + * interrupts turned off.
  42 + */
  43 +int power_state_active_is_enabled(void);
  44 +
  45 +#endif