1 // SPDX-License-Identifier: GPL-2.0+ 2 // 3 // Copyright (c) 2019 Mantas Pucka <mantas@8devices.com> 4 // Copyright (c) 2019 Robert Marko <robert.marko@sartura.hr> 5 // 6 // Driver for IPQ4019 SD/MMC controller's I/O LDO voltage regulator 7 8 #include <linux/io.h> 9 #include <linux/module.h> 10 #include <linux/of.h> 11 #include <linux/platform_device.h> 12 #include <linux/regmap.h> 13 #include <linux/regulator/driver.h> 14 #include <linux/regulator/machine.h> 15 #include <linux/regulator/of_regulator.h> 16 17 static const unsigned int ipq4019_vmmc_voltages[] = { 18 1500000, 1800000, 2500000, 3000000, 19 }; 20 21 static const struct regulator_ops ipq4019_regulator_voltage_ops = { 22 .list_voltage = regulator_list_voltage_table, 23 .map_voltage = regulator_map_voltage_ascend, 24 .get_voltage_sel = regulator_get_voltage_sel_regmap, 25 .set_voltage_sel = regulator_set_voltage_sel_regmap, 26 }; 27 28 static const struct regulator_desc vmmc_regulator = { 29 .name = "vmmcq", 30 .ops = &ipq4019_regulator_voltage_ops, 31 .type = REGULATOR_VOLTAGE, 32 .owner = THIS_MODULE, 33 .volt_table = ipq4019_vmmc_voltages, 34 .n_voltages = ARRAY_SIZE(ipq4019_vmmc_voltages), 35 .vsel_reg = 0, 36 .vsel_mask = 0x3, 37 }; 38 39 static const struct regmap_config ipq4019_vmmcq_regmap_config = { 40 .reg_bits = 32, 41 .reg_stride = 4, 42 .val_bits = 32, 43 }; 44 45 static int ipq4019_regulator_probe(struct platform_device *pdev) 46 { 47 struct device *dev = &pdev->dev; 48 struct regulator_init_data *init_data; 49 struct regulator_config cfg = {}; 50 struct regulator_dev *rdev; 51 struct resource *res; 52 struct regmap *rmap; 53 void __iomem *base; 54 55 init_data = of_get_regulator_init_data(dev, dev->of_node, 56 &vmmc_regulator); 57 if (!init_data) 58 return -EINVAL; 59 60 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 61 base = devm_ioremap_resource(dev, res); 62 if (IS_ERR(base)) 63 return PTR_ERR(base); 64 65 rmap = devm_regmap_init_mmio(dev, base, &ipq4019_vmmcq_regmap_config); 66 if (IS_ERR(rmap)) 67 return PTR_ERR(rmap); 68 69 cfg.dev = dev; 70 cfg.init_data = init_data; 71 cfg.of_node = dev->of_node; 72 cfg.regmap = rmap; 73 74 rdev = devm_regulator_register(dev, &vmmc_regulator, &cfg); 75 if (IS_ERR(rdev)) { 76 dev_err(dev, "Failed to register regulator: %ld\n", 77 PTR_ERR(rdev)); 78 return PTR_ERR(rdev); 79 } 80 platform_set_drvdata(pdev, rdev); 81 82 return 0; 83 } 84 85 static const struct of_device_id regulator_ipq4019_of_match[] = { 86 { .compatible = "qcom,vqmmc-ipq4019-regulator", }, 87 {}, 88 }; 89 90 static struct platform_driver ipq4019_regulator_driver = { 91 .probe = ipq4019_regulator_probe, 92 .driver = { 93 .name = "vqmmc-ipq4019-regulator", 94 .of_match_table = of_match_ptr(regulator_ipq4019_of_match), 95 }, 96 }; 97 module_platform_driver(ipq4019_regulator_driver); 98 99 MODULE_LICENSE("GPL"); 100 MODULE_AUTHOR("Mantas Pucka <mantas@8devices.com>"); 101 MODULE_DESCRIPTION("IPQ4019 VQMMC voltage regulator"); 102