162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// Copyright 2014 Embest Technology Co. Ltd. Inc. 462306a36Sopenharmony_ci// bd71815-regulator.c ROHM BD71815 regulator driver 562306a36Sopenharmony_ci// 662306a36Sopenharmony_ci// Author: Tony Luo <luofc@embedinfo.com> 762306a36Sopenharmony_ci// 862306a36Sopenharmony_ci// Partially rewritten at 2021 by 962306a36Sopenharmony_ci// Matti Vaittinen <matti.vaitinen@fi.rohmeurope.com> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci#include <linux/init.h> 1462306a36Sopenharmony_ci#include <linux/err.h> 1562306a36Sopenharmony_ci#include <linux/platform_device.h> 1662306a36Sopenharmony_ci#include <linux/of.h> 1762306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 1862306a36Sopenharmony_ci#include <linux/regulator/driver.h> 1962306a36Sopenharmony_ci#include <linux/delay.h> 2062306a36Sopenharmony_ci#include <linux/slab.h> 2162306a36Sopenharmony_ci#include <linux/mfd/rohm-generic.h> 2262306a36Sopenharmony_ci#include <linux/mfd/rohm-bd71815.h> 2362306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistruct bd71815_regulator { 2662306a36Sopenharmony_ci struct regulator_desc desc; 2762306a36Sopenharmony_ci const struct rohm_dvs_config *dvs; 2862306a36Sopenharmony_ci}; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic const int bd7181x_wled_currents[] = { 3162306a36Sopenharmony_ci 10, 20, 30, 50, 70, 100, 200, 300, 500, 700, 1000, 2000, 3000, 4000, 3262306a36Sopenharmony_ci 5000, 6000, 7000, 8000, 9000, 10000, 11000, 12000, 13000, 14000, 15000, 3362306a36Sopenharmony_ci 16000, 17000, 18000, 19000, 20000, 21000, 22000, 23000, 24000, 25000, 3462306a36Sopenharmony_ci}; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic const struct rohm_dvs_config buck1_dvs = { 3762306a36Sopenharmony_ci .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS | 3862306a36Sopenharmony_ci ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR, 3962306a36Sopenharmony_ci .run_reg = BD71815_REG_BUCK1_VOLT_H, 4062306a36Sopenharmony_ci .run_mask = BD71815_VOLT_MASK, 4162306a36Sopenharmony_ci .run_on_mask = BD71815_BUCK_RUN_ON, 4262306a36Sopenharmony_ci .snvs_on_mask = BD71815_BUCK_SNVS_ON, 4362306a36Sopenharmony_ci .suspend_reg = BD71815_REG_BUCK1_VOLT_L, 4462306a36Sopenharmony_ci .suspend_mask = BD71815_VOLT_MASK, 4562306a36Sopenharmony_ci .suspend_on_mask = BD71815_BUCK_SUSP_ON, 4662306a36Sopenharmony_ci .lpsr_reg = BD71815_REG_BUCK1_VOLT_L, 4762306a36Sopenharmony_ci .lpsr_mask = BD71815_VOLT_MASK, 4862306a36Sopenharmony_ci .lpsr_on_mask = BD71815_BUCK_LPSR_ON, 4962306a36Sopenharmony_ci}; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic const struct rohm_dvs_config buck2_dvs = { 5262306a36Sopenharmony_ci .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS | 5362306a36Sopenharmony_ci ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR, 5462306a36Sopenharmony_ci .run_reg = BD71815_REG_BUCK2_VOLT_H, 5562306a36Sopenharmony_ci .run_mask = BD71815_VOLT_MASK, 5662306a36Sopenharmony_ci .run_on_mask = BD71815_BUCK_RUN_ON, 5762306a36Sopenharmony_ci .snvs_on_mask = BD71815_BUCK_SNVS_ON, 5862306a36Sopenharmony_ci .suspend_reg = BD71815_REG_BUCK2_VOLT_L, 5962306a36Sopenharmony_ci .suspend_mask = BD71815_VOLT_MASK, 6062306a36Sopenharmony_ci .suspend_on_mask = BD71815_BUCK_SUSP_ON, 6162306a36Sopenharmony_ci .lpsr_reg = BD71815_REG_BUCK2_VOLT_L, 6262306a36Sopenharmony_ci .lpsr_mask = BD71815_VOLT_MASK, 6362306a36Sopenharmony_ci .lpsr_on_mask = BD71815_BUCK_LPSR_ON, 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic const struct rohm_dvs_config buck3_dvs = { 6762306a36Sopenharmony_ci .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS | 6862306a36Sopenharmony_ci ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR, 6962306a36Sopenharmony_ci .run_reg = BD71815_REG_BUCK3_VOLT, 7062306a36Sopenharmony_ci .run_mask = BD71815_VOLT_MASK, 7162306a36Sopenharmony_ci .run_on_mask = BD71815_BUCK_RUN_ON, 7262306a36Sopenharmony_ci .snvs_on_mask = BD71815_BUCK_SNVS_ON, 7362306a36Sopenharmony_ci .suspend_on_mask = BD71815_BUCK_SUSP_ON, 7462306a36Sopenharmony_ci .lpsr_on_mask = BD71815_BUCK_LPSR_ON, 7562306a36Sopenharmony_ci}; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic const struct rohm_dvs_config buck4_dvs = { 7862306a36Sopenharmony_ci .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS | 7962306a36Sopenharmony_ci ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR, 8062306a36Sopenharmony_ci .run_reg = BD71815_REG_BUCK4_VOLT, 8162306a36Sopenharmony_ci .run_mask = BD71815_VOLT_MASK, 8262306a36Sopenharmony_ci .run_on_mask = BD71815_BUCK_RUN_ON, 8362306a36Sopenharmony_ci .snvs_on_mask = BD71815_BUCK_SNVS_ON, 8462306a36Sopenharmony_ci .suspend_on_mask = BD71815_BUCK_SUSP_ON, 8562306a36Sopenharmony_ci .lpsr_on_mask = BD71815_BUCK_LPSR_ON, 8662306a36Sopenharmony_ci}; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic const struct rohm_dvs_config ldo1_dvs = { 8962306a36Sopenharmony_ci .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS | 9062306a36Sopenharmony_ci ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR, 9162306a36Sopenharmony_ci .run_reg = BD71815_REG_LDO_MODE1, 9262306a36Sopenharmony_ci .run_mask = BD71815_VOLT_MASK, 9362306a36Sopenharmony_ci .run_on_mask = LDO1_RUN_ON, 9462306a36Sopenharmony_ci .snvs_on_mask = LDO1_SNVS_ON, 9562306a36Sopenharmony_ci .suspend_on_mask = LDO1_SUSP_ON, 9662306a36Sopenharmony_ci .lpsr_on_mask = LDO1_LPSR_ON, 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic const struct rohm_dvs_config ldo2_dvs = { 10062306a36Sopenharmony_ci .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS | 10162306a36Sopenharmony_ci ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR, 10262306a36Sopenharmony_ci .run_reg = BD71815_REG_LDO_MODE2, 10362306a36Sopenharmony_ci .run_mask = BD71815_VOLT_MASK, 10462306a36Sopenharmony_ci .run_on_mask = LDO2_RUN_ON, 10562306a36Sopenharmony_ci .snvs_on_mask = LDO2_SNVS_ON, 10662306a36Sopenharmony_ci .suspend_on_mask = LDO2_SUSP_ON, 10762306a36Sopenharmony_ci .lpsr_on_mask = LDO2_LPSR_ON, 10862306a36Sopenharmony_ci}; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic const struct rohm_dvs_config ldo3_dvs = { 11162306a36Sopenharmony_ci .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS | 11262306a36Sopenharmony_ci ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR, 11362306a36Sopenharmony_ci .run_reg = BD71815_REG_LDO_MODE2, 11462306a36Sopenharmony_ci .run_mask = BD71815_VOLT_MASK, 11562306a36Sopenharmony_ci .run_on_mask = LDO3_RUN_ON, 11662306a36Sopenharmony_ci .snvs_on_mask = LDO3_SNVS_ON, 11762306a36Sopenharmony_ci .suspend_on_mask = LDO3_SUSP_ON, 11862306a36Sopenharmony_ci .lpsr_on_mask = LDO3_LPSR_ON, 11962306a36Sopenharmony_ci}; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistatic const struct rohm_dvs_config ldo4_dvs = { 12262306a36Sopenharmony_ci .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS | 12362306a36Sopenharmony_ci ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR, 12462306a36Sopenharmony_ci .run_reg = BD71815_REG_LDO_MODE3, 12562306a36Sopenharmony_ci .run_mask = BD71815_VOLT_MASK, 12662306a36Sopenharmony_ci .run_on_mask = LDO4_RUN_ON, 12762306a36Sopenharmony_ci .snvs_on_mask = LDO4_SNVS_ON, 12862306a36Sopenharmony_ci .suspend_on_mask = LDO4_SUSP_ON, 12962306a36Sopenharmony_ci .lpsr_on_mask = LDO4_LPSR_ON, 13062306a36Sopenharmony_ci}; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic const struct rohm_dvs_config ldo5_dvs = { 13362306a36Sopenharmony_ci .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS | 13462306a36Sopenharmony_ci ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR, 13562306a36Sopenharmony_ci .run_reg = BD71815_REG_LDO_MODE3, 13662306a36Sopenharmony_ci .run_mask = BD71815_VOLT_MASK, 13762306a36Sopenharmony_ci .run_on_mask = LDO5_RUN_ON, 13862306a36Sopenharmony_ci .snvs_on_mask = LDO5_SNVS_ON, 13962306a36Sopenharmony_ci .suspend_on_mask = LDO5_SUSP_ON, 14062306a36Sopenharmony_ci .lpsr_on_mask = LDO5_LPSR_ON, 14162306a36Sopenharmony_ci}; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic const struct rohm_dvs_config dvref_dvs = { 14462306a36Sopenharmony_ci .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS | 14562306a36Sopenharmony_ci ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR, 14662306a36Sopenharmony_ci .run_on_mask = DVREF_RUN_ON, 14762306a36Sopenharmony_ci .snvs_on_mask = DVREF_SNVS_ON, 14862306a36Sopenharmony_ci .suspend_on_mask = DVREF_SUSP_ON, 14962306a36Sopenharmony_ci .lpsr_on_mask = DVREF_LPSR_ON, 15062306a36Sopenharmony_ci}; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic const struct rohm_dvs_config ldolpsr_dvs = { 15362306a36Sopenharmony_ci .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS | 15462306a36Sopenharmony_ci ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR, 15562306a36Sopenharmony_ci .run_on_mask = DVREF_RUN_ON, 15662306a36Sopenharmony_ci .snvs_on_mask = DVREF_SNVS_ON, 15762306a36Sopenharmony_ci .suspend_on_mask = DVREF_SUSP_ON, 15862306a36Sopenharmony_ci .lpsr_on_mask = DVREF_LPSR_ON, 15962306a36Sopenharmony_ci}; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistatic const struct rohm_dvs_config buck5_dvs = { 16262306a36Sopenharmony_ci .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS | 16362306a36Sopenharmony_ci ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR, 16462306a36Sopenharmony_ci .run_reg = BD71815_REG_BUCK5_VOLT, 16562306a36Sopenharmony_ci .run_mask = BD71815_VOLT_MASK, 16662306a36Sopenharmony_ci .run_on_mask = BD71815_BUCK_RUN_ON, 16762306a36Sopenharmony_ci .snvs_on_mask = BD71815_BUCK_SNVS_ON, 16862306a36Sopenharmony_ci .suspend_on_mask = BD71815_BUCK_SUSP_ON, 16962306a36Sopenharmony_ci .lpsr_on_mask = BD71815_BUCK_LPSR_ON, 17062306a36Sopenharmony_ci}; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic int set_hw_dvs_levels(struct device_node *np, 17362306a36Sopenharmony_ci const struct regulator_desc *desc, 17462306a36Sopenharmony_ci struct regulator_config *cfg) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci struct bd71815_regulator *data; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci data = container_of(desc, struct bd71815_regulator, desc); 17962306a36Sopenharmony_ci return rohm_regulator_set_dvs_levels(data->dvs, np, desc, cfg->regmap); 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci/* 18362306a36Sopenharmony_ci * Bucks 1 and 2 have two voltage selection registers where selected 18462306a36Sopenharmony_ci * voltage can be set. Which of the registers is used can be either controlled 18562306a36Sopenharmony_ci * by a control bit in register - or by HW state. If HW state specific voltages 18662306a36Sopenharmony_ci * are given - then we assume HW state based control should be used. 18762306a36Sopenharmony_ci * 18862306a36Sopenharmony_ci * If volatge value is updated to currently selected register - then output 18962306a36Sopenharmony_ci * voltage is immediately changed no matter what is set as ramp rate. Thus we 19062306a36Sopenharmony_ci * default changing voltage by writing new value to inactive register and 19162306a36Sopenharmony_ci * then updating the 'register selection' bit. This naturally only works when 19262306a36Sopenharmony_ci * HW state machine is not used to select the voltage. 19362306a36Sopenharmony_ci */ 19462306a36Sopenharmony_cistatic int buck12_set_hw_dvs_levels(struct device_node *np, 19562306a36Sopenharmony_ci const struct regulator_desc *desc, 19662306a36Sopenharmony_ci struct regulator_config *cfg) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci struct bd71815_regulator *data; 19962306a36Sopenharmony_ci int ret = 0, val; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci data = container_of(desc, struct bd71815_regulator, desc); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if (of_property_present(np, "rohm,dvs-run-voltage") || 20462306a36Sopenharmony_ci of_property_present(np, "rohm,dvs-suspend-voltage") || 20562306a36Sopenharmony_ci of_property_present(np, "rohm,dvs-lpsr-voltage") || 20662306a36Sopenharmony_ci of_property_present(np, "rohm,dvs-snvs-voltage")) { 20762306a36Sopenharmony_ci ret = regmap_read(cfg->regmap, desc->vsel_reg, &val); 20862306a36Sopenharmony_ci if (ret) 20962306a36Sopenharmony_ci return ret; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci if (!(BD71815_BUCK_STBY_DVS & val) && 21262306a36Sopenharmony_ci !(BD71815_BUCK_DVSSEL & val)) { 21362306a36Sopenharmony_ci int val2; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci /* 21662306a36Sopenharmony_ci * We are currently using voltage from _L. 21762306a36Sopenharmony_ci * We'd better copy it to _H and switch to it to 21862306a36Sopenharmony_ci * avoid shutting us down if LPSR or SUSPEND is set to 21962306a36Sopenharmony_ci * disabled. _L value is at reg _H + 1 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_ci ret = regmap_read(cfg->regmap, desc->vsel_reg + 1, 22262306a36Sopenharmony_ci &val2); 22362306a36Sopenharmony_ci if (ret) 22462306a36Sopenharmony_ci return ret; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci ret = regmap_update_bits(cfg->regmap, desc->vsel_reg, 22762306a36Sopenharmony_ci BD71815_VOLT_MASK | 22862306a36Sopenharmony_ci BD71815_BUCK_DVSSEL, 22962306a36Sopenharmony_ci val2 | BD71815_BUCK_DVSSEL); 23062306a36Sopenharmony_ci if (ret) 23162306a36Sopenharmony_ci return ret; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci ret = rohm_regulator_set_dvs_levels(data->dvs, np, desc, 23462306a36Sopenharmony_ci cfg->regmap); 23562306a36Sopenharmony_ci if (ret) 23662306a36Sopenharmony_ci return ret; 23762306a36Sopenharmony_ci /* 23862306a36Sopenharmony_ci * DVS levels were given => use HW-state machine for voltage 23962306a36Sopenharmony_ci * controls. NOTE: AFAIK, This means that if voltage is changed 24062306a36Sopenharmony_ci * by SW the ramp-rate is not respected. Should we disable 24162306a36Sopenharmony_ci * SW voltage control when the HW state machine is used? 24262306a36Sopenharmony_ci */ 24362306a36Sopenharmony_ci ret = regmap_update_bits(cfg->regmap, desc->vsel_reg, 24462306a36Sopenharmony_ci BD71815_BUCK_STBY_DVS, 24562306a36Sopenharmony_ci BD71815_BUCK_STBY_DVS); 24662306a36Sopenharmony_ci } 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci return ret; 24962306a36Sopenharmony_ci} 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci/* 25262306a36Sopenharmony_ci * BUCK1/2 25362306a36Sopenharmony_ci * BUCK1RAMPRATE[1:0] BUCK1 DVS ramp rate setting 25462306a36Sopenharmony_ci * 00: 10.00mV/usec 10mV 1uS 25562306a36Sopenharmony_ci * 01: 5.00mV/usec 10mV 2uS 25662306a36Sopenharmony_ci * 10: 2.50mV/usec 10mV 4uS 25762306a36Sopenharmony_ci * 11: 1.25mV/usec 10mV 8uS 25862306a36Sopenharmony_ci */ 25962306a36Sopenharmony_cistatic const unsigned int bd7181x_ramp_table[] = { 1250, 2500, 5000, 10000 }; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic int bd7181x_led_set_current_limit(struct regulator_dev *rdev, 26262306a36Sopenharmony_ci int min_uA, int max_uA) 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci int ret; 26562306a36Sopenharmony_ci int onstatus; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci onstatus = regulator_is_enabled_regmap(rdev); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci ret = regulator_set_current_limit_regmap(rdev, min_uA, max_uA); 27062306a36Sopenharmony_ci if (!ret) { 27162306a36Sopenharmony_ci int newstatus; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci newstatus = regulator_is_enabled_regmap(rdev); 27462306a36Sopenharmony_ci if (onstatus != newstatus) { 27562306a36Sopenharmony_ci /* 27662306a36Sopenharmony_ci * HW FIX: spurious led status change detected. Toggle 27762306a36Sopenharmony_ci * state as a workaround 27862306a36Sopenharmony_ci */ 27962306a36Sopenharmony_ci if (onstatus) 28062306a36Sopenharmony_ci ret = regulator_enable_regmap(rdev); 28162306a36Sopenharmony_ci else 28262306a36Sopenharmony_ci ret = regulator_disable_regmap(rdev); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci if (ret) 28562306a36Sopenharmony_ci dev_err(rdev_get_dev(rdev), 28662306a36Sopenharmony_ci "failed to revert the LED state (%d)\n", 28762306a36Sopenharmony_ci ret); 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci return ret; 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cistatic int bd7181x_buck12_get_voltage_sel(struct regulator_dev *rdev) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci int rid = rdev_get_id(rdev); 29762306a36Sopenharmony_ci int ret, regh, regl, val; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci regh = BD71815_REG_BUCK1_VOLT_H + rid * 0x2; 30062306a36Sopenharmony_ci regl = BD71815_REG_BUCK1_VOLT_L + rid * 0x2; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci ret = regmap_read(rdev->regmap, regh, &val); 30362306a36Sopenharmony_ci if (ret) 30462306a36Sopenharmony_ci return ret; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci /* 30762306a36Sopenharmony_ci * If we use HW state machine based voltage reg selection - then we 30862306a36Sopenharmony_ci * return BD71815_REG_BUCK1_VOLT_H which is used at RUN. 30962306a36Sopenharmony_ci * Else we do return the BD71815_REG_BUCK1_VOLT_H or 31062306a36Sopenharmony_ci * BD71815_REG_BUCK1_VOLT_L depending on which is selected to be used 31162306a36Sopenharmony_ci * by BD71815_BUCK_DVSSEL bit 31262306a36Sopenharmony_ci */ 31362306a36Sopenharmony_ci if ((!(val & BD71815_BUCK_STBY_DVS)) && (!(val & BD71815_BUCK_DVSSEL))) 31462306a36Sopenharmony_ci ret = regmap_read(rdev->regmap, regl, &val); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci if (ret) 31762306a36Sopenharmony_ci return ret; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci return val & BD71815_VOLT_MASK; 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci/* 32362306a36Sopenharmony_ci * For Buck 1/2. 32462306a36Sopenharmony_ci */ 32562306a36Sopenharmony_cistatic int bd7181x_buck12_set_voltage_sel(struct regulator_dev *rdev, 32662306a36Sopenharmony_ci unsigned int sel) 32762306a36Sopenharmony_ci{ 32862306a36Sopenharmony_ci int rid = rdev_get_id(rdev); 32962306a36Sopenharmony_ci int ret, val, reg, regh, regl; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci regh = BD71815_REG_BUCK1_VOLT_H + rid*0x2; 33262306a36Sopenharmony_ci regl = BD71815_REG_BUCK1_VOLT_L + rid*0x2; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci ret = regmap_read(rdev->regmap, regh, &val); 33562306a36Sopenharmony_ci if (ret) 33662306a36Sopenharmony_ci return ret; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci /* 33962306a36Sopenharmony_ci * If bucks 1 & 2 are controlled by state machine - then the RUN state 34062306a36Sopenharmony_ci * voltage is set to BD71815_REG_BUCK1_VOLT_H. Changing SUSPEND/LPSR 34162306a36Sopenharmony_ci * voltages at runtime is not supported by this driver. 34262306a36Sopenharmony_ci */ 34362306a36Sopenharmony_ci if (((val & BD71815_BUCK_STBY_DVS))) { 34462306a36Sopenharmony_ci return regmap_update_bits(rdev->regmap, regh, BD71815_VOLT_MASK, 34562306a36Sopenharmony_ci sel); 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci /* Update new voltage to the register which is not selected now */ 34862306a36Sopenharmony_ci if (val & BD71815_BUCK_DVSSEL) 34962306a36Sopenharmony_ci reg = regl; 35062306a36Sopenharmony_ci else 35162306a36Sopenharmony_ci reg = regh; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci ret = regmap_update_bits(rdev->regmap, reg, BD71815_VOLT_MASK, sel); 35462306a36Sopenharmony_ci if (ret) 35562306a36Sopenharmony_ci return ret; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci /* Select the other DVS register to be used */ 35862306a36Sopenharmony_ci return regmap_update_bits(rdev->regmap, regh, BD71815_BUCK_DVSSEL, 35962306a36Sopenharmony_ci ~val); 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_cistatic const struct regulator_ops bd7181x_ldo_regulator_ops = { 36362306a36Sopenharmony_ci .enable = regulator_enable_regmap, 36462306a36Sopenharmony_ci .disable = regulator_disable_regmap, 36562306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 36662306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 36762306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 36862306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 36962306a36Sopenharmony_ci}; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_cistatic const struct regulator_ops bd7181x_fixed_regulator_ops = { 37262306a36Sopenharmony_ci .enable = regulator_enable_regmap, 37362306a36Sopenharmony_ci .disable = regulator_disable_regmap, 37462306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 37562306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 37662306a36Sopenharmony_ci}; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_cistatic const struct regulator_ops bd7181x_buck_regulator_ops = { 37962306a36Sopenharmony_ci .enable = regulator_enable_regmap, 38062306a36Sopenharmony_ci .disable = regulator_disable_regmap, 38162306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 38262306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 38362306a36Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 38462306a36Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 38562306a36Sopenharmony_ci .set_voltage_time_sel = regulator_set_voltage_time_sel, 38662306a36Sopenharmony_ci}; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_cistatic const struct regulator_ops bd7181x_buck12_regulator_ops = { 38962306a36Sopenharmony_ci .enable = regulator_enable_regmap, 39062306a36Sopenharmony_ci .disable = regulator_disable_regmap, 39162306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 39262306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_linear, 39362306a36Sopenharmony_ci .set_voltage_sel = bd7181x_buck12_set_voltage_sel, 39462306a36Sopenharmony_ci .get_voltage_sel = bd7181x_buck12_get_voltage_sel, 39562306a36Sopenharmony_ci .set_voltage_time_sel = regulator_set_voltage_time_sel, 39662306a36Sopenharmony_ci .set_ramp_delay = regulator_set_ramp_delay_regmap, 39762306a36Sopenharmony_ci}; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_cistatic const struct regulator_ops bd7181x_led_regulator_ops = { 40062306a36Sopenharmony_ci .enable = regulator_enable_regmap, 40162306a36Sopenharmony_ci .disable = regulator_disable_regmap, 40262306a36Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 40362306a36Sopenharmony_ci .set_current_limit = bd7181x_led_set_current_limit, 40462306a36Sopenharmony_ci .get_current_limit = regulator_get_current_limit_regmap, 40562306a36Sopenharmony_ci}; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci#define BD71815_FIXED_REG(_name, _id, ereg, emsk, voltage, _dvs) \ 40862306a36Sopenharmony_ci [(_id)] = { \ 40962306a36Sopenharmony_ci .desc = { \ 41062306a36Sopenharmony_ci .name = #_name, \ 41162306a36Sopenharmony_ci .of_match = of_match_ptr(#_name), \ 41262306a36Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), \ 41362306a36Sopenharmony_ci .n_voltages = 1, \ 41462306a36Sopenharmony_ci .ops = &bd7181x_fixed_regulator_ops, \ 41562306a36Sopenharmony_ci .type = REGULATOR_VOLTAGE, \ 41662306a36Sopenharmony_ci .id = (_id), \ 41762306a36Sopenharmony_ci .owner = THIS_MODULE, \ 41862306a36Sopenharmony_ci .min_uV = (voltage), \ 41962306a36Sopenharmony_ci .enable_reg = (ereg), \ 42062306a36Sopenharmony_ci .enable_mask = (emsk), \ 42162306a36Sopenharmony_ci .of_parse_cb = set_hw_dvs_levels, \ 42262306a36Sopenharmony_ci }, \ 42362306a36Sopenharmony_ci .dvs = (_dvs), \ 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci#define BD71815_BUCK_REG(_name, _id, vsel, ereg, min, max, step, _dvs) \ 42762306a36Sopenharmony_ci [(_id)] = { \ 42862306a36Sopenharmony_ci .desc = { \ 42962306a36Sopenharmony_ci .name = #_name, \ 43062306a36Sopenharmony_ci .of_match = of_match_ptr(#_name), \ 43162306a36Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), \ 43262306a36Sopenharmony_ci .n_voltages = ((max) - (min)) / (step) + 1, \ 43362306a36Sopenharmony_ci .ops = &bd7181x_buck_regulator_ops, \ 43462306a36Sopenharmony_ci .type = REGULATOR_VOLTAGE, \ 43562306a36Sopenharmony_ci .id = (_id), \ 43662306a36Sopenharmony_ci .owner = THIS_MODULE, \ 43762306a36Sopenharmony_ci .min_uV = (min), \ 43862306a36Sopenharmony_ci .uV_step = (step), \ 43962306a36Sopenharmony_ci .vsel_reg = (vsel), \ 44062306a36Sopenharmony_ci .vsel_mask = BD71815_VOLT_MASK, \ 44162306a36Sopenharmony_ci .enable_reg = (ereg), \ 44262306a36Sopenharmony_ci .enable_mask = BD71815_BUCK_RUN_ON, \ 44362306a36Sopenharmony_ci .of_parse_cb = set_hw_dvs_levels, \ 44462306a36Sopenharmony_ci }, \ 44562306a36Sopenharmony_ci .dvs = (_dvs), \ 44662306a36Sopenharmony_ci } 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci#define BD71815_BUCK12_REG(_name, _id, vsel, ereg, min, max, step, \ 44962306a36Sopenharmony_ci _dvs) \ 45062306a36Sopenharmony_ci [(_id)] = { \ 45162306a36Sopenharmony_ci .desc = { \ 45262306a36Sopenharmony_ci .name = #_name, \ 45362306a36Sopenharmony_ci .of_match = of_match_ptr(#_name), \ 45462306a36Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), \ 45562306a36Sopenharmony_ci .n_voltages = ((max) - (min)) / (step) + 1, \ 45662306a36Sopenharmony_ci .ops = &bd7181x_buck12_regulator_ops, \ 45762306a36Sopenharmony_ci .type = REGULATOR_VOLTAGE, \ 45862306a36Sopenharmony_ci .id = (_id), \ 45962306a36Sopenharmony_ci .owner = THIS_MODULE, \ 46062306a36Sopenharmony_ci .min_uV = (min), \ 46162306a36Sopenharmony_ci .uV_step = (step), \ 46262306a36Sopenharmony_ci .vsel_reg = (vsel), \ 46362306a36Sopenharmony_ci .vsel_mask = BD71815_VOLT_MASK, \ 46462306a36Sopenharmony_ci .enable_reg = (ereg), \ 46562306a36Sopenharmony_ci .enable_mask = BD71815_BUCK_RUN_ON, \ 46662306a36Sopenharmony_ci .ramp_reg = (ereg), \ 46762306a36Sopenharmony_ci .ramp_mask = BD71815_BUCK_RAMPRATE_MASK, \ 46862306a36Sopenharmony_ci .ramp_delay_table = bd7181x_ramp_table, \ 46962306a36Sopenharmony_ci .n_ramp_values = ARRAY_SIZE(bd7181x_ramp_table),\ 47062306a36Sopenharmony_ci .of_parse_cb = buck12_set_hw_dvs_levels, \ 47162306a36Sopenharmony_ci }, \ 47262306a36Sopenharmony_ci .dvs = (_dvs), \ 47362306a36Sopenharmony_ci } 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci#define BD71815_LED_REG(_name, _id, csel, mask, ereg, emsk, currents) \ 47662306a36Sopenharmony_ci [(_id)] = { \ 47762306a36Sopenharmony_ci .desc = { \ 47862306a36Sopenharmony_ci .name = #_name, \ 47962306a36Sopenharmony_ci .of_match = of_match_ptr(#_name), \ 48062306a36Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), \ 48162306a36Sopenharmony_ci .n_current_limits = ARRAY_SIZE(currents), \ 48262306a36Sopenharmony_ci .ops = &bd7181x_led_regulator_ops, \ 48362306a36Sopenharmony_ci .type = REGULATOR_CURRENT, \ 48462306a36Sopenharmony_ci .id = (_id), \ 48562306a36Sopenharmony_ci .owner = THIS_MODULE, \ 48662306a36Sopenharmony_ci .curr_table = currents, \ 48762306a36Sopenharmony_ci .csel_reg = (csel), \ 48862306a36Sopenharmony_ci .csel_mask = (mask), \ 48962306a36Sopenharmony_ci .enable_reg = (ereg), \ 49062306a36Sopenharmony_ci .enable_mask = (emsk), \ 49162306a36Sopenharmony_ci }, \ 49262306a36Sopenharmony_ci } 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci#define BD71815_LDO_REG(_name, _id, vsel, ereg, emsk, min, max, step, \ 49562306a36Sopenharmony_ci _dvs) \ 49662306a36Sopenharmony_ci [(_id)] = { \ 49762306a36Sopenharmony_ci .desc = { \ 49862306a36Sopenharmony_ci .name = #_name, \ 49962306a36Sopenharmony_ci .of_match = of_match_ptr(#_name), \ 50062306a36Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), \ 50162306a36Sopenharmony_ci .n_voltages = ((max) - (min)) / (step) + 1, \ 50262306a36Sopenharmony_ci .ops = &bd7181x_ldo_regulator_ops, \ 50362306a36Sopenharmony_ci .type = REGULATOR_VOLTAGE, \ 50462306a36Sopenharmony_ci .id = (_id), \ 50562306a36Sopenharmony_ci .owner = THIS_MODULE, \ 50662306a36Sopenharmony_ci .min_uV = (min), \ 50762306a36Sopenharmony_ci .uV_step = (step), \ 50862306a36Sopenharmony_ci .vsel_reg = (vsel), \ 50962306a36Sopenharmony_ci .vsel_mask = BD71815_VOLT_MASK, \ 51062306a36Sopenharmony_ci .enable_reg = (ereg), \ 51162306a36Sopenharmony_ci .enable_mask = (emsk), \ 51262306a36Sopenharmony_ci .of_parse_cb = set_hw_dvs_levels, \ 51362306a36Sopenharmony_ci }, \ 51462306a36Sopenharmony_ci .dvs = (_dvs), \ 51562306a36Sopenharmony_ci } 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cistatic const struct bd71815_regulator bd71815_regulators[] = { 51862306a36Sopenharmony_ci BD71815_BUCK12_REG(buck1, BD71815_BUCK1, BD71815_REG_BUCK1_VOLT_H, 51962306a36Sopenharmony_ci BD71815_REG_BUCK1_MODE, 800000, 2000000, 25000, 52062306a36Sopenharmony_ci &buck1_dvs), 52162306a36Sopenharmony_ci BD71815_BUCK12_REG(buck2, BD71815_BUCK2, BD71815_REG_BUCK2_VOLT_H, 52262306a36Sopenharmony_ci BD71815_REG_BUCK2_MODE, 800000, 2000000, 25000, 52362306a36Sopenharmony_ci &buck2_dvs), 52462306a36Sopenharmony_ci BD71815_BUCK_REG(buck3, BD71815_BUCK3, BD71815_REG_BUCK3_VOLT, 52562306a36Sopenharmony_ci BD71815_REG_BUCK3_MODE, 1200000, 2700000, 50000, 52662306a36Sopenharmony_ci &buck3_dvs), 52762306a36Sopenharmony_ci BD71815_BUCK_REG(buck4, BD71815_BUCK4, BD71815_REG_BUCK4_VOLT, 52862306a36Sopenharmony_ci BD71815_REG_BUCK4_MODE, 1100000, 1850000, 25000, 52962306a36Sopenharmony_ci &buck4_dvs), 53062306a36Sopenharmony_ci BD71815_BUCK_REG(buck5, BD71815_BUCK5, BD71815_REG_BUCK5_VOLT, 53162306a36Sopenharmony_ci BD71815_REG_BUCK5_MODE, 1800000, 3300000, 50000, 53262306a36Sopenharmony_ci &buck5_dvs), 53362306a36Sopenharmony_ci BD71815_LDO_REG(ldo1, BD71815_LDO1, BD71815_REG_LDO1_VOLT, 53462306a36Sopenharmony_ci BD71815_REG_LDO_MODE1, LDO1_RUN_ON, 800000, 3300000, 53562306a36Sopenharmony_ci 50000, &ldo1_dvs), 53662306a36Sopenharmony_ci BD71815_LDO_REG(ldo2, BD71815_LDO2, BD71815_REG_LDO2_VOLT, 53762306a36Sopenharmony_ci BD71815_REG_LDO_MODE2, LDO2_RUN_ON, 800000, 3300000, 53862306a36Sopenharmony_ci 50000, &ldo2_dvs), 53962306a36Sopenharmony_ci /* 54062306a36Sopenharmony_ci * Let's default LDO3 to be enabled by SW. We can override ops if DT 54162306a36Sopenharmony_ci * says LDO3 should be enabled by HW when DCIN is connected. 54262306a36Sopenharmony_ci */ 54362306a36Sopenharmony_ci BD71815_LDO_REG(ldo3, BD71815_LDO3, BD71815_REG_LDO3_VOLT, 54462306a36Sopenharmony_ci BD71815_REG_LDO_MODE2, LDO3_RUN_ON, 800000, 3300000, 54562306a36Sopenharmony_ci 50000, &ldo3_dvs), 54662306a36Sopenharmony_ci BD71815_LDO_REG(ldo4, BD71815_LDO4, BD71815_REG_LDO4_VOLT, 54762306a36Sopenharmony_ci BD71815_REG_LDO_MODE3, LDO4_RUN_ON, 800000, 3300000, 54862306a36Sopenharmony_ci 50000, &ldo4_dvs), 54962306a36Sopenharmony_ci BD71815_LDO_REG(ldo5, BD71815_LDO5, BD71815_REG_LDO5_VOLT_H, 55062306a36Sopenharmony_ci BD71815_REG_LDO_MODE3, LDO5_RUN_ON, 800000, 3300000, 55162306a36Sopenharmony_ci 50000, &ldo5_dvs), 55262306a36Sopenharmony_ci BD71815_FIXED_REG(ldodvref, BD71815_LDODVREF, BD71815_REG_LDO_MODE4, 55362306a36Sopenharmony_ci DVREF_RUN_ON, 3000000, &dvref_dvs), 55462306a36Sopenharmony_ci BD71815_FIXED_REG(ldolpsr, BD71815_LDOLPSR, BD71815_REG_LDO_MODE4, 55562306a36Sopenharmony_ci LDO_LPSR_RUN_ON, 1800000, &ldolpsr_dvs), 55662306a36Sopenharmony_ci BD71815_LED_REG(wled, BD71815_WLED, BD71815_REG_LED_DIMM, LED_DIMM_MASK, 55762306a36Sopenharmony_ci BD71815_REG_LED_CTRL, LED_RUN_ON, 55862306a36Sopenharmony_ci bd7181x_wled_currents), 55962306a36Sopenharmony_ci}; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_cistatic int bd7181x_probe(struct platform_device *pdev) 56262306a36Sopenharmony_ci{ 56362306a36Sopenharmony_ci struct regulator_config config = {}; 56462306a36Sopenharmony_ci int i, ret; 56562306a36Sopenharmony_ci struct gpio_desc *ldo4_en; 56662306a36Sopenharmony_ci struct regmap *regmap; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci regmap = dev_get_regmap(pdev->dev.parent, NULL); 56962306a36Sopenharmony_ci if (!regmap) { 57062306a36Sopenharmony_ci dev_err(&pdev->dev, "No parent regmap\n"); 57162306a36Sopenharmony_ci return -ENODEV; 57262306a36Sopenharmony_ci } 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci ldo4_en = devm_fwnode_gpiod_get(&pdev->dev, 57562306a36Sopenharmony_ci dev_fwnode(pdev->dev.parent), 57662306a36Sopenharmony_ci "rohm,vsel", GPIOD_ASIS, "ldo4-en"); 57762306a36Sopenharmony_ci if (IS_ERR(ldo4_en)) { 57862306a36Sopenharmony_ci ret = PTR_ERR(ldo4_en); 57962306a36Sopenharmony_ci if (ret != -ENOENT) 58062306a36Sopenharmony_ci return ret; 58162306a36Sopenharmony_ci ldo4_en = NULL; 58262306a36Sopenharmony_ci } 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci /* Disable to go to ship-mode */ 58562306a36Sopenharmony_ci ret = regmap_update_bits(regmap, BD71815_REG_PWRCTRL, RESTARTEN, 0); 58662306a36Sopenharmony_ci if (ret) 58762306a36Sopenharmony_ci return ret; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci config.dev = pdev->dev.parent; 59062306a36Sopenharmony_ci config.regmap = regmap; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci for (i = 0; i < BD71815_REGULATOR_CNT; i++) { 59362306a36Sopenharmony_ci const struct regulator_desc *desc; 59462306a36Sopenharmony_ci struct regulator_dev *rdev; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci desc = &bd71815_regulators[i].desc; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci if (i == BD71815_LDO4) 59962306a36Sopenharmony_ci config.ena_gpiod = ldo4_en; 60062306a36Sopenharmony_ci else 60162306a36Sopenharmony_ci config.ena_gpiod = NULL; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci rdev = devm_regulator_register(&pdev->dev, desc, &config); 60462306a36Sopenharmony_ci if (IS_ERR(rdev)) 60562306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, PTR_ERR(rdev), 60662306a36Sopenharmony_ci "failed to register %s regulator\n", 60762306a36Sopenharmony_ci desc->name); 60862306a36Sopenharmony_ci } 60962306a36Sopenharmony_ci return 0; 61062306a36Sopenharmony_ci} 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_cistatic const struct platform_device_id bd7181x_pmic_id[] = { 61362306a36Sopenharmony_ci { "bd71815-pmic", ROHM_CHIP_TYPE_BD71815 }, 61462306a36Sopenharmony_ci { }, 61562306a36Sopenharmony_ci}; 61662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(platform, bd7181x_pmic_id); 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_cistatic struct platform_driver bd7181x_regulator = { 61962306a36Sopenharmony_ci .driver = { 62062306a36Sopenharmony_ci .name = "bd7181x-pmic", 62162306a36Sopenharmony_ci .probe_type = PROBE_PREFER_ASYNCHRONOUS, 62262306a36Sopenharmony_ci }, 62362306a36Sopenharmony_ci .probe = bd7181x_probe, 62462306a36Sopenharmony_ci .id_table = bd7181x_pmic_id, 62562306a36Sopenharmony_ci}; 62662306a36Sopenharmony_cimodule_platform_driver(bd7181x_regulator); 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ciMODULE_AUTHOR("Tony Luo <luofc@embedinfo.com>"); 62962306a36Sopenharmony_ciMODULE_DESCRIPTION("BD71815 voltage regulator driver"); 63062306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 63162306a36Sopenharmony_ciMODULE_ALIAS("platform:bd7181x-pmic"); 632