162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2022 Analog Devices, Inc. 462306a36Sopenharmony_ci * ADI Regulator driver for the MAX77540 and MAX77541 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/mfd/max77541.h> 862306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 962306a36Sopenharmony_ci#include <linux/platform_device.h> 1062306a36Sopenharmony_ci#include <linux/regmap.h> 1162306a36Sopenharmony_ci#include <linux/regulator/driver.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic const struct regulator_ops max77541_buck_ops = { 1462306a36Sopenharmony_ci .enable = regulator_enable_regmap, 1562306a36Sopenharmony_ci .disable = regulator_disable_regmap, 1662306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 1762306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_pickable_linear_range, 1862306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, 1962306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap, 2062306a36Sopenharmony_ci}; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic const struct linear_range max77540_buck_ranges[] = { 2362306a36Sopenharmony_ci /* Ranges when VOLT_SEL bits are 0x00 */ 2462306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(500000, 0x00, 0x8B, 5000), 2562306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(1200000, 0x8C, 0xFF, 0), 2662306a36Sopenharmony_ci /* Ranges when VOLT_SEL bits are 0x40 */ 2762306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x8B, 10000), 2862306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(2400000, 0x8C, 0xFF, 0), 2962306a36Sopenharmony_ci /* Ranges when VOLT_SEL bits are 0x80 */ 3062306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(2000000, 0x00, 0x9F, 20000), 3162306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(5200000, 0xA0, 0xFF, 0), 3262306a36Sopenharmony_ci}; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic const struct linear_range max77541_buck_ranges[] = { 3562306a36Sopenharmony_ci /* Ranges when VOLT_SEL bits are 0x00 */ 3662306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(300000, 0x00, 0xB3, 5000), 3762306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(1200000, 0xB4, 0xFF, 0), 3862306a36Sopenharmony_ci /* Ranges when VOLT_SEL bits are 0x40 */ 3962306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x8B, 10000), 4062306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(2400000, 0x8C, 0xFF, 0), 4162306a36Sopenharmony_ci /* Ranges when VOLT_SEL bits are 0x80 */ 4262306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(2000000, 0x00, 0x9F, 20000), 4362306a36Sopenharmony_ci REGULATOR_LINEAR_RANGE(5200000, 0xA0, 0xFF, 0), 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistatic const unsigned int max77541_buck_volt_range_sel[] = { 4762306a36Sopenharmony_ci 0x0, 0x0, 0x1, 0x1, 0x2, 0x2, 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cienum max77541_regulators { 5162306a36Sopenharmony_ci MAX77541_BUCK1 = 1, 5262306a36Sopenharmony_ci MAX77541_BUCK2, 5362306a36Sopenharmony_ci}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define MAX77540_BUCK(_id, _ops) \ 5662306a36Sopenharmony_ci { .id = MAX77541_BUCK ## _id, \ 5762306a36Sopenharmony_ci .name = "buck"#_id, \ 5862306a36Sopenharmony_ci .of_match = "buck"#_id, \ 5962306a36Sopenharmony_ci .regulators_node = "regulators", \ 6062306a36Sopenharmony_ci .enable_reg = MAX77541_REG_EN_CTRL, \ 6162306a36Sopenharmony_ci .enable_mask = MAX77541_BIT_M ## _id ## _EN, \ 6262306a36Sopenharmony_ci .ops = &(_ops), \ 6362306a36Sopenharmony_ci .type = REGULATOR_VOLTAGE, \ 6462306a36Sopenharmony_ci .linear_ranges = max77540_buck_ranges, \ 6562306a36Sopenharmony_ci .n_linear_ranges = ARRAY_SIZE(max77540_buck_ranges), \ 6662306a36Sopenharmony_ci .vsel_reg = MAX77541_REG_M ## _id ## _VOUT, \ 6762306a36Sopenharmony_ci .vsel_mask = MAX77541_BITS_MX_VOUT, \ 6862306a36Sopenharmony_ci .vsel_range_reg = MAX77541_REG_M ## _id ## _CFG1, \ 6962306a36Sopenharmony_ci .vsel_range_mask = MAX77541_BITS_MX_CFG1_RNG, \ 7062306a36Sopenharmony_ci .linear_range_selectors_bitfield = max77541_buck_volt_range_sel, \ 7162306a36Sopenharmony_ci .owner = THIS_MODULE, \ 7262306a36Sopenharmony_ci } 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#define MAX77541_BUCK(_id, _ops) \ 7562306a36Sopenharmony_ci { .id = MAX77541_BUCK ## _id, \ 7662306a36Sopenharmony_ci .name = "buck"#_id, \ 7762306a36Sopenharmony_ci .of_match = "buck"#_id, \ 7862306a36Sopenharmony_ci .regulators_node = "regulators", \ 7962306a36Sopenharmony_ci .enable_reg = MAX77541_REG_EN_CTRL, \ 8062306a36Sopenharmony_ci .enable_mask = MAX77541_BIT_M ## _id ## _EN, \ 8162306a36Sopenharmony_ci .ops = &(_ops), \ 8262306a36Sopenharmony_ci .type = REGULATOR_VOLTAGE, \ 8362306a36Sopenharmony_ci .linear_ranges = max77541_buck_ranges, \ 8462306a36Sopenharmony_ci .n_linear_ranges = ARRAY_SIZE(max77541_buck_ranges), \ 8562306a36Sopenharmony_ci .vsel_reg = MAX77541_REG_M ## _id ## _VOUT, \ 8662306a36Sopenharmony_ci .vsel_mask = MAX77541_BITS_MX_VOUT, \ 8762306a36Sopenharmony_ci .vsel_range_reg = MAX77541_REG_M ## _id ## _CFG1, \ 8862306a36Sopenharmony_ci .vsel_range_mask = MAX77541_BITS_MX_CFG1_RNG, \ 8962306a36Sopenharmony_ci .linear_range_selectors_bitfield = max77541_buck_volt_range_sel, \ 9062306a36Sopenharmony_ci .owner = THIS_MODULE, \ 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic const struct regulator_desc max77540_regulators_desc[] = { 9462306a36Sopenharmony_ci MAX77540_BUCK(1, max77541_buck_ops), 9562306a36Sopenharmony_ci MAX77540_BUCK(2, max77541_buck_ops), 9662306a36Sopenharmony_ci}; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistatic const struct regulator_desc max77541_regulators_desc[] = { 9962306a36Sopenharmony_ci MAX77541_BUCK(1, max77541_buck_ops), 10062306a36Sopenharmony_ci MAX77541_BUCK(2, max77541_buck_ops), 10162306a36Sopenharmony_ci}; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic int max77541_regulator_probe(struct platform_device *pdev) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci struct regulator_config config = {}; 10662306a36Sopenharmony_ci const struct regulator_desc *desc; 10762306a36Sopenharmony_ci struct device *dev = &pdev->dev; 10862306a36Sopenharmony_ci struct regulator_dev *rdev; 10962306a36Sopenharmony_ci struct max77541 *max77541 = dev_get_drvdata(dev->parent); 11062306a36Sopenharmony_ci unsigned int i; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci config.dev = dev->parent; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci switch (max77541->id) { 11562306a36Sopenharmony_ci case MAX77540: 11662306a36Sopenharmony_ci desc = max77540_regulators_desc; 11762306a36Sopenharmony_ci break; 11862306a36Sopenharmony_ci case MAX77541: 11962306a36Sopenharmony_ci desc = max77541_regulators_desc; 12062306a36Sopenharmony_ci break; 12162306a36Sopenharmony_ci default: 12262306a36Sopenharmony_ci return -EINVAL; 12362306a36Sopenharmony_ci } 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci for (i = 0; i < MAX77541_MAX_REGULATORS; i++) { 12662306a36Sopenharmony_ci rdev = devm_regulator_register(dev, &desc[i], &config); 12762306a36Sopenharmony_ci if (IS_ERR(rdev)) 12862306a36Sopenharmony_ci return dev_err_probe(dev, PTR_ERR(rdev), 12962306a36Sopenharmony_ci "Failed to register regulator\n"); 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci return 0; 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic const struct platform_device_id max77541_regulator_platform_id[] = { 13662306a36Sopenharmony_ci { "max77540-regulator" }, 13762306a36Sopenharmony_ci { "max77541-regulator" }, 13862306a36Sopenharmony_ci { } 13962306a36Sopenharmony_ci}; 14062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(platform, max77541_regulator_platform_id); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic struct platform_driver max77541_regulator_driver = { 14362306a36Sopenharmony_ci .driver = { 14462306a36Sopenharmony_ci .name = "max77541-regulator", 14562306a36Sopenharmony_ci }, 14662306a36Sopenharmony_ci .probe = max77541_regulator_probe, 14762306a36Sopenharmony_ci .id_table = max77541_regulator_platform_id, 14862306a36Sopenharmony_ci}; 14962306a36Sopenharmony_cimodule_platform_driver(max77541_regulator_driver); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ciMODULE_AUTHOR("Okan Sahin <Okan.Sahin@analog.com>"); 15262306a36Sopenharmony_ciMODULE_DESCRIPTION("MAX77540/MAX77541 regulator driver"); 15362306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 154