1f1e64f90SGuennadi Liakhovetski /* 2f1e64f90SGuennadi Liakhovetski * AS3711 PMIC regulator driver, using DCDC Step Down and LDO supplies 3f1e64f90SGuennadi Liakhovetski * 4f1e64f90SGuennadi Liakhovetski * Copyright (C) 2012 Renesas Electronics Corporation 5f1e64f90SGuennadi Liakhovetski * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de> 6f1e64f90SGuennadi Liakhovetski * 7f1e64f90SGuennadi Liakhovetski * This program is free software; you can redistribute it and/or modify 8f1e64f90SGuennadi Liakhovetski * it under the terms of the version 2 of the GNU General Public License as 9f1e64f90SGuennadi Liakhovetski * published by the Free Software Foundation 10f1e64f90SGuennadi Liakhovetski */ 11f1e64f90SGuennadi Liakhovetski 12f1e64f90SGuennadi Liakhovetski #include <linux/err.h> 13f1e64f90SGuennadi Liakhovetski #include <linux/init.h> 14f1e64f90SGuennadi Liakhovetski #include <linux/mfd/as3711.h> 15f1e64f90SGuennadi Liakhovetski #include <linux/module.h> 16416d6759SGuennadi Liakhovetski #include <linux/of.h> 17f1e64f90SGuennadi Liakhovetski #include <linux/platform_device.h> 18f1e64f90SGuennadi Liakhovetski #include <linux/regmap.h> 19f1e64f90SGuennadi Liakhovetski #include <linux/regulator/driver.h> 20416d6759SGuennadi Liakhovetski #include <linux/regulator/of_regulator.h> 21f1e64f90SGuennadi Liakhovetski #include <linux/slab.h> 22f1e64f90SGuennadi Liakhovetski 23f1e64f90SGuennadi Liakhovetski struct as3711_regulator_info { 24f1e64f90SGuennadi Liakhovetski struct regulator_desc desc; 25f1e64f90SGuennadi Liakhovetski unsigned int max_uV; 26f1e64f90SGuennadi Liakhovetski }; 27f1e64f90SGuennadi Liakhovetski 28f1e64f90SGuennadi Liakhovetski struct as3711_regulator { 29f1e64f90SGuennadi Liakhovetski struct as3711_regulator_info *reg_info; 30f1e64f90SGuennadi Liakhovetski struct regulator_dev *rdev; 31f1e64f90SGuennadi Liakhovetski }; 32f1e64f90SGuennadi Liakhovetski 33f1e64f90SGuennadi Liakhovetski /* 34f1e64f90SGuennadi Liakhovetski * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and 35f1e64f90SGuennadi Liakhovetski * STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes: 36f1e64f90SGuennadi Liakhovetski * FAST: sdX_fast=1 37f1e64f90SGuennadi Liakhovetski * NORMAL: low_noise=1 38f1e64f90SGuennadi Liakhovetski * IDLE: low_noise=0 39f1e64f90SGuennadi Liakhovetski */ 40f1e64f90SGuennadi Liakhovetski 41f1e64f90SGuennadi Liakhovetski static int as3711_set_mode_sd(struct regulator_dev *rdev, unsigned int mode) 42f1e64f90SGuennadi Liakhovetski { 43f1e64f90SGuennadi Liakhovetski unsigned int fast_bit = rdev->desc->enable_mask, 44f1e64f90SGuennadi Liakhovetski low_noise_bit = fast_bit << 4; 45f1e64f90SGuennadi Liakhovetski u8 val; 46f1e64f90SGuennadi Liakhovetski 47f1e64f90SGuennadi Liakhovetski switch (mode) { 48f1e64f90SGuennadi Liakhovetski case REGULATOR_MODE_FAST: 49f1e64f90SGuennadi Liakhovetski val = fast_bit | low_noise_bit; 50f1e64f90SGuennadi Liakhovetski break; 51f1e64f90SGuennadi Liakhovetski case REGULATOR_MODE_NORMAL: 52f1e64f90SGuennadi Liakhovetski val = low_noise_bit; 53f1e64f90SGuennadi Liakhovetski break; 54f1e64f90SGuennadi Liakhovetski case REGULATOR_MODE_IDLE: 55f1e64f90SGuennadi Liakhovetski val = 0; 56f1e64f90SGuennadi Liakhovetski break; 57f1e64f90SGuennadi Liakhovetski default: 58f1e64f90SGuennadi Liakhovetski return -EINVAL; 59f1e64f90SGuennadi Liakhovetski } 60f1e64f90SGuennadi Liakhovetski 61f1e64f90SGuennadi Liakhovetski return regmap_update_bits(rdev->regmap, AS3711_SD_CONTROL_1, 62f1e64f90SGuennadi Liakhovetski low_noise_bit | fast_bit, val); 63f1e64f90SGuennadi Liakhovetski } 64f1e64f90SGuennadi Liakhovetski 65f1e64f90SGuennadi Liakhovetski static unsigned int as3711_get_mode_sd(struct regulator_dev *rdev) 66f1e64f90SGuennadi Liakhovetski { 67f1e64f90SGuennadi Liakhovetski unsigned int fast_bit = rdev->desc->enable_mask, 68f1e64f90SGuennadi Liakhovetski low_noise_bit = fast_bit << 4, mask = fast_bit | low_noise_bit; 69f1e64f90SGuennadi Liakhovetski unsigned int val; 70f1e64f90SGuennadi Liakhovetski int ret = regmap_read(rdev->regmap, AS3711_SD_CONTROL_1, &val); 71f1e64f90SGuennadi Liakhovetski 72f1e64f90SGuennadi Liakhovetski if (ret < 0) 73f1e64f90SGuennadi Liakhovetski return ret; 74f1e64f90SGuennadi Liakhovetski 75f1e64f90SGuennadi Liakhovetski if ((val & mask) == mask) 76f1e64f90SGuennadi Liakhovetski return REGULATOR_MODE_FAST; 77f1e64f90SGuennadi Liakhovetski 78f1e64f90SGuennadi Liakhovetski if ((val & mask) == low_noise_bit) 79f1e64f90SGuennadi Liakhovetski return REGULATOR_MODE_NORMAL; 80f1e64f90SGuennadi Liakhovetski 81f1e64f90SGuennadi Liakhovetski if (!(val & mask)) 82f1e64f90SGuennadi Liakhovetski return REGULATOR_MODE_IDLE; 83f1e64f90SGuennadi Liakhovetski 84f1e64f90SGuennadi Liakhovetski return -EINVAL; 85f1e64f90SGuennadi Liakhovetski } 86f1e64f90SGuennadi Liakhovetski 87f1e64f90SGuennadi Liakhovetski static struct regulator_ops as3711_sd_ops = { 88f1e64f90SGuennadi Liakhovetski .is_enabled = regulator_is_enabled_regmap, 89f1e64f90SGuennadi Liakhovetski .enable = regulator_enable_regmap, 90f1e64f90SGuennadi Liakhovetski .disable = regulator_disable_regmap, 91f1e64f90SGuennadi Liakhovetski .get_voltage_sel = regulator_get_voltage_sel_regmap, 92f1e64f90SGuennadi Liakhovetski .set_voltage_sel = regulator_set_voltage_sel_regmap, 939234c636SAxel Lin .list_voltage = regulator_list_voltage_linear_range, 949234c636SAxel Lin .map_voltage = regulator_map_voltage_linear_range, 95f1e64f90SGuennadi Liakhovetski .get_mode = as3711_get_mode_sd, 96f1e64f90SGuennadi Liakhovetski .set_mode = as3711_set_mode_sd, 97f1e64f90SGuennadi Liakhovetski }; 98f1e64f90SGuennadi Liakhovetski 99f1e64f90SGuennadi Liakhovetski static struct regulator_ops as3711_aldo_ops = { 100f1e64f90SGuennadi Liakhovetski .is_enabled = regulator_is_enabled_regmap, 101f1e64f90SGuennadi Liakhovetski .enable = regulator_enable_regmap, 102f1e64f90SGuennadi Liakhovetski .disable = regulator_disable_regmap, 103f1e64f90SGuennadi Liakhovetski .get_voltage_sel = regulator_get_voltage_sel_regmap, 104f1e64f90SGuennadi Liakhovetski .set_voltage_sel = regulator_set_voltage_sel_regmap, 1059234c636SAxel Lin .list_voltage = regulator_list_voltage_linear_range, 1069234c636SAxel Lin .map_voltage = regulator_map_voltage_linear_range, 107f1e64f90SGuennadi Liakhovetski }; 108f1e64f90SGuennadi Liakhovetski 109f1e64f90SGuennadi Liakhovetski static struct regulator_ops as3711_dldo_ops = { 110f1e64f90SGuennadi Liakhovetski .is_enabled = regulator_is_enabled_regmap, 111f1e64f90SGuennadi Liakhovetski .enable = regulator_enable_regmap, 112f1e64f90SGuennadi Liakhovetski .disable = regulator_disable_regmap, 113f1e64f90SGuennadi Liakhovetski .get_voltage_sel = regulator_get_voltage_sel_regmap, 114f1e64f90SGuennadi Liakhovetski .set_voltage_sel = regulator_set_voltage_sel_regmap, 1159234c636SAxel Lin .list_voltage = regulator_list_voltage_linear_range, 1169234c636SAxel Lin .map_voltage = regulator_map_voltage_linear_range, 1179234c636SAxel Lin }; 1189234c636SAxel Lin 1199234c636SAxel Lin static const struct regulator_linear_range as3711_sd_ranges[] = { 1208828bae4SAxel Lin REGULATOR_LINEAR_RANGE(612500, 0x1, 0x40, 12500), 1218828bae4SAxel Lin REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000), 1228828bae4SAxel Lin REGULATOR_LINEAR_RANGE(2650000, 0x71, 0x7f, 50000), 1239234c636SAxel Lin }; 1249234c636SAxel Lin 1259234c636SAxel Lin static const struct regulator_linear_range as3711_aldo_ranges[] = { 1268828bae4SAxel Lin REGULATOR_LINEAR_RANGE(1200000, 0, 0xf, 50000), 1278828bae4SAxel Lin REGULATOR_LINEAR_RANGE(1800000, 0x10, 0x1f, 100000), 1289234c636SAxel Lin }; 1299234c636SAxel Lin 1309234c636SAxel Lin static const struct regulator_linear_range as3711_dldo_ranges[] = { 1318828bae4SAxel Lin REGULATOR_LINEAR_RANGE(900000, 0, 0x10, 50000), 1328828bae4SAxel Lin REGULATOR_LINEAR_RANGE(1750000, 0x20, 0x3f, 50000), 133f1e64f90SGuennadi Liakhovetski }; 134f1e64f90SGuennadi Liakhovetski 135f1e64f90SGuennadi Liakhovetski #define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx) \ 136f1e64f90SGuennadi Liakhovetski [AS3711_REGULATOR_ ## _id] = { \ 137f1e64f90SGuennadi Liakhovetski .desc = { \ 138f1e64f90SGuennadi Liakhovetski .name = "as3711-regulator-" # _id, \ 139f1e64f90SGuennadi Liakhovetski .id = AS3711_REGULATOR_ ## _id, \ 140f1e64f90SGuennadi Liakhovetski .n_voltages = (_vmask + 1), \ 141f1e64f90SGuennadi Liakhovetski .ops = &as3711_ ## _sfx ## _ops, \ 142f1e64f90SGuennadi Liakhovetski .type = REGULATOR_VOLTAGE, \ 143f1e64f90SGuennadi Liakhovetski .owner = THIS_MODULE, \ 144f1e64f90SGuennadi Liakhovetski .vsel_reg = AS3711_ ## _id ## _VOLTAGE, \ 145f1e64f90SGuennadi Liakhovetski .vsel_mask = _vmask << _vshift, \ 146f1e64f90SGuennadi Liakhovetski .enable_reg = AS3711_ ## _en_reg, \ 147f1e64f90SGuennadi Liakhovetski .enable_mask = BIT(_en_bit), \ 148f1e64f90SGuennadi Liakhovetski .min_uV = _min_uV, \ 1499234c636SAxel Lin .linear_ranges = as3711_ ## _sfx ## _ranges, \ 1509234c636SAxel Lin .n_linear_ranges = ARRAY_SIZE(as3711_ ## _sfx ## _ranges), \ 151f1e64f90SGuennadi Liakhovetski }, \ 152f1e64f90SGuennadi Liakhovetski .max_uV = _max_uV, \ 153f1e64f90SGuennadi Liakhovetski } 154f1e64f90SGuennadi Liakhovetski 155f1e64f90SGuennadi Liakhovetski static struct as3711_regulator_info as3711_reg_info[] = { 156f1e64f90SGuennadi Liakhovetski AS3711_REG(SD_1, SD_CONTROL, 0, 0x7f, 0, 612500, 3350000, sd), 157f1e64f90SGuennadi Liakhovetski AS3711_REG(SD_2, SD_CONTROL, 1, 0x7f, 0, 612500, 3350000, sd), 158f1e64f90SGuennadi Liakhovetski AS3711_REG(SD_3, SD_CONTROL, 2, 0x7f, 0, 612500, 3350000, sd), 159f1e64f90SGuennadi Liakhovetski AS3711_REG(SD_4, SD_CONTROL, 3, 0x7f, 0, 612500, 3350000, sd), 160f1e64f90SGuennadi Liakhovetski AS3711_REG(LDO_1, LDO_1_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo), 161f1e64f90SGuennadi Liakhovetski AS3711_REG(LDO_2, LDO_2_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo), 162f1e64f90SGuennadi Liakhovetski AS3711_REG(LDO_3, LDO_3_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), 163f1e64f90SGuennadi Liakhovetski AS3711_REG(LDO_4, LDO_4_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), 164f1e64f90SGuennadi Liakhovetski AS3711_REG(LDO_5, LDO_5_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), 165f1e64f90SGuennadi Liakhovetski AS3711_REG(LDO_6, LDO_6_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), 166f1e64f90SGuennadi Liakhovetski AS3711_REG(LDO_7, LDO_7_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), 167f1e64f90SGuennadi Liakhovetski AS3711_REG(LDO_8, LDO_8_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), 168f1e64f90SGuennadi Liakhovetski /* StepUp output voltage depends on supplying regulator */ 169f1e64f90SGuennadi Liakhovetski }; 170f1e64f90SGuennadi Liakhovetski 171f1e64f90SGuennadi Liakhovetski #define AS3711_REGULATOR_NUM ARRAY_SIZE(as3711_reg_info) 172f1e64f90SGuennadi Liakhovetski 173d6c7d731SAxel Lin static struct of_regulator_match 174d6c7d731SAxel Lin as3711_regulator_matches[AS3711_REGULATOR_NUM] = { 175d6c7d731SAxel Lin [AS3711_REGULATOR_SD_1] = { .name = "sd1" }, 176d6c7d731SAxel Lin [AS3711_REGULATOR_SD_2] = { .name = "sd2" }, 177d6c7d731SAxel Lin [AS3711_REGULATOR_SD_3] = { .name = "sd3" }, 178d6c7d731SAxel Lin [AS3711_REGULATOR_SD_4] = { .name = "sd4" }, 179d6c7d731SAxel Lin [AS3711_REGULATOR_LDO_1] = { .name = "ldo1" }, 180d6c7d731SAxel Lin [AS3711_REGULATOR_LDO_2] = { .name = "ldo2" }, 181d6c7d731SAxel Lin [AS3711_REGULATOR_LDO_3] = { .name = "ldo3" }, 182d6c7d731SAxel Lin [AS3711_REGULATOR_LDO_4] = { .name = "ldo4" }, 183d6c7d731SAxel Lin [AS3711_REGULATOR_LDO_5] = { .name = "ldo5" }, 184d6c7d731SAxel Lin [AS3711_REGULATOR_LDO_6] = { .name = "ldo6" }, 185d6c7d731SAxel Lin [AS3711_REGULATOR_LDO_7] = { .name = "ldo7" }, 186d6c7d731SAxel Lin [AS3711_REGULATOR_LDO_8] = { .name = "ldo8" }, 187416d6759SGuennadi Liakhovetski }; 188416d6759SGuennadi Liakhovetski 189416d6759SGuennadi Liakhovetski static int as3711_regulator_parse_dt(struct device *dev, 190416d6759SGuennadi Liakhovetski struct device_node **of_node, const int count) 191416d6759SGuennadi Liakhovetski { 192416d6759SGuennadi Liakhovetski struct as3711_regulator_pdata *pdata = dev_get_platdata(dev); 193416d6759SGuennadi Liakhovetski struct device_node *regulators = 194eecb02c0SSachin Kamat of_get_child_by_name(dev->parent->of_node, "regulators"); 195d6c7d731SAxel Lin struct of_regulator_match *match; 196416d6759SGuennadi Liakhovetski int ret, i; 197416d6759SGuennadi Liakhovetski 198416d6759SGuennadi Liakhovetski if (!regulators) { 199416d6759SGuennadi Liakhovetski dev_err(dev, "regulator node not found\n"); 200416d6759SGuennadi Liakhovetski return -ENODEV; 201416d6759SGuennadi Liakhovetski } 202416d6759SGuennadi Liakhovetski 203d6c7d731SAxel Lin ret = of_regulator_match(dev->parent, regulators, 204d6c7d731SAxel Lin as3711_regulator_matches, count); 205416d6759SGuennadi Liakhovetski of_node_put(regulators); 206416d6759SGuennadi Liakhovetski if (ret < 0) { 207416d6759SGuennadi Liakhovetski dev_err(dev, "Error parsing regulator init data: %d\n", ret); 208416d6759SGuennadi Liakhovetski return ret; 209416d6759SGuennadi Liakhovetski } 210416d6759SGuennadi Liakhovetski 211d6c7d731SAxel Lin for (i = 0, match = as3711_regulator_matches; i < count; i++, match++) 212416d6759SGuennadi Liakhovetski if (match->of_node) { 213416d6759SGuennadi Liakhovetski pdata->init_data[i] = match->init_data; 214416d6759SGuennadi Liakhovetski of_node[i] = match->of_node; 215416d6759SGuennadi Liakhovetski } 216416d6759SGuennadi Liakhovetski 217416d6759SGuennadi Liakhovetski return 0; 218416d6759SGuennadi Liakhovetski } 219416d6759SGuennadi Liakhovetski 220f1e64f90SGuennadi Liakhovetski static int as3711_regulator_probe(struct platform_device *pdev) 221f1e64f90SGuennadi Liakhovetski { 222f1e64f90SGuennadi Liakhovetski struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev); 223f1e64f90SGuennadi Liakhovetski struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent); 224f1e64f90SGuennadi Liakhovetski struct regulator_config config = {.dev = &pdev->dev,}; 225f1e64f90SGuennadi Liakhovetski struct as3711_regulator *reg = NULL; 226f1e64f90SGuennadi Liakhovetski struct as3711_regulator *regs; 227416d6759SGuennadi Liakhovetski struct device_node *of_node[AS3711_REGULATOR_NUM] = {}; 228f1e64f90SGuennadi Liakhovetski struct regulator_dev *rdev; 229f1e64f90SGuennadi Liakhovetski struct as3711_regulator_info *ri; 230f1e64f90SGuennadi Liakhovetski int ret; 231f1e64f90SGuennadi Liakhovetski int id; 232f1e64f90SGuennadi Liakhovetski 233416d6759SGuennadi Liakhovetski if (!pdata) { 234416d6759SGuennadi Liakhovetski dev_err(&pdev->dev, "No platform data...\n"); 235416d6759SGuennadi Liakhovetski return -ENODEV; 236416d6759SGuennadi Liakhovetski } 237416d6759SGuennadi Liakhovetski 238416d6759SGuennadi Liakhovetski if (pdev->dev.parent->of_node) { 239416d6759SGuennadi Liakhovetski ret = as3711_regulator_parse_dt(&pdev->dev, of_node, AS3711_REGULATOR_NUM); 240416d6759SGuennadi Liakhovetski if (ret < 0) { 241416d6759SGuennadi Liakhovetski dev_err(&pdev->dev, "DT parsing failed: %d\n", ret); 242416d6759SGuennadi Liakhovetski return ret; 243416d6759SGuennadi Liakhovetski } 244416d6759SGuennadi Liakhovetski } 245f1e64f90SGuennadi Liakhovetski 246f1e64f90SGuennadi Liakhovetski regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM * 247f1e64f90SGuennadi Liakhovetski sizeof(struct as3711_regulator), GFP_KERNEL); 248f1e64f90SGuennadi Liakhovetski if (!regs) { 249f1e64f90SGuennadi Liakhovetski dev_err(&pdev->dev, "Memory allocation failed exiting..\n"); 250f1e64f90SGuennadi Liakhovetski return -ENOMEM; 251f1e64f90SGuennadi Liakhovetski } 252f1e64f90SGuennadi Liakhovetski 253f1e64f90SGuennadi Liakhovetski for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) { 254f1e64f90SGuennadi Liakhovetski reg = ®s[id]; 255f1e64f90SGuennadi Liakhovetski reg->reg_info = ri; 256f1e64f90SGuennadi Liakhovetski 257f7e9e52fSAxel Lin config.init_data = pdata->init_data[id]; 258f1e64f90SGuennadi Liakhovetski config.driver_data = reg; 259f1e64f90SGuennadi Liakhovetski config.regmap = as3711->regmap; 260416d6759SGuennadi Liakhovetski config.of_node = of_node[id]; 261f1e64f90SGuennadi Liakhovetski 26227447c93SAxel Lin rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config); 263f1e64f90SGuennadi Liakhovetski if (IS_ERR(rdev)) { 264f1e64f90SGuennadi Liakhovetski dev_err(&pdev->dev, "Failed to register regulator %s\n", 265f1e64f90SGuennadi Liakhovetski ri->desc.name); 26627447c93SAxel Lin return PTR_ERR(rdev); 267f1e64f90SGuennadi Liakhovetski } 268f1e64f90SGuennadi Liakhovetski reg->rdev = rdev; 269f1e64f90SGuennadi Liakhovetski } 270f1e64f90SGuennadi Liakhovetski platform_set_drvdata(pdev, regs); 271f1e64f90SGuennadi Liakhovetski return 0; 272f1e64f90SGuennadi Liakhovetski } 273f1e64f90SGuennadi Liakhovetski 274f1e64f90SGuennadi Liakhovetski static struct platform_driver as3711_regulator_driver = { 275f1e64f90SGuennadi Liakhovetski .driver = { 276f1e64f90SGuennadi Liakhovetski .name = "as3711-regulator", 277f1e64f90SGuennadi Liakhovetski .owner = THIS_MODULE, 278f1e64f90SGuennadi Liakhovetski }, 279f1e64f90SGuennadi Liakhovetski .probe = as3711_regulator_probe, 280f1e64f90SGuennadi Liakhovetski }; 281f1e64f90SGuennadi Liakhovetski 282f1e64f90SGuennadi Liakhovetski static int __init as3711_regulator_init(void) 283f1e64f90SGuennadi Liakhovetski { 284f1e64f90SGuennadi Liakhovetski return platform_driver_register(&as3711_regulator_driver); 285f1e64f90SGuennadi Liakhovetski } 286f1e64f90SGuennadi Liakhovetski subsys_initcall(as3711_regulator_init); 287f1e64f90SGuennadi Liakhovetski 288f1e64f90SGuennadi Liakhovetski static void __exit as3711_regulator_exit(void) 289f1e64f90SGuennadi Liakhovetski { 290f1e64f90SGuennadi Liakhovetski platform_driver_unregister(&as3711_regulator_driver); 291f1e64f90SGuennadi Liakhovetski } 292f1e64f90SGuennadi Liakhovetski module_exit(as3711_regulator_exit); 293f1e64f90SGuennadi Liakhovetski 294f1e64f90SGuennadi Liakhovetski MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); 295f1e64f90SGuennadi Liakhovetski MODULE_DESCRIPTION("AS3711 regulator driver"); 296f1e64f90SGuennadi Liakhovetski MODULE_ALIAS("platform:as3711-regulator"); 297f1e64f90SGuennadi Liakhovetski MODULE_LICENSE("GPL v2"); 298