| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Regulator driver for tps65090 power management chip. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. |
|---|
| 5 | 6 | |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 7 | | - * under the terms and conditions of the GNU General Public License, |
|---|
| 8 | | - * version 2, as published by the Free Software Foundation. |
|---|
| 9 | | - |
|---|
| 10 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
|---|
| 11 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 12 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 13 | | - * more details. |
|---|
| 14 | | - |
|---|
| 15 | | - * You should have received a copy of the GNU General Public License |
|---|
| 16 | | - * along with this program. If not, see <http://www.gnu.org/licenses/> |
|---|
| 17 | 7 | */ |
|---|
| 18 | 8 | |
|---|
| 19 | 9 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 57 | 47 | int overcurrent_wait; |
|---|
| 58 | 48 | }; |
|---|
| 59 | 49 | |
|---|
| 60 | | -static struct regulator_ops tps65090_ext_control_ops = { |
|---|
| 50 | +static const struct regulator_ops tps65090_ext_control_ops = { |
|---|
| 61 | 51 | }; |
|---|
| 62 | 52 | |
|---|
| 63 | 53 | /** |
|---|
| .. | .. |
|---|
| 177 | 167 | return ret; |
|---|
| 178 | 168 | } |
|---|
| 179 | 169 | |
|---|
| 180 | | -static struct regulator_ops tps65090_reg_control_ops = { |
|---|
| 170 | +static const struct regulator_ops tps65090_reg_control_ops = { |
|---|
| 181 | 171 | .enable = regulator_enable_regmap, |
|---|
| 182 | 172 | .disable = regulator_disable_regmap, |
|---|
| 183 | 173 | .is_enabled = regulator_is_enabled_regmap, |
|---|
| 184 | 174 | }; |
|---|
| 185 | 175 | |
|---|
| 186 | | -static struct regulator_ops tps65090_fet_control_ops = { |
|---|
| 176 | +static const struct regulator_ops tps65090_fet_control_ops = { |
|---|
| 187 | 177 | .enable = tps65090_fet_enable, |
|---|
| 188 | 178 | .disable = regulator_disable_regmap, |
|---|
| 189 | 179 | .is_enabled = regulator_is_enabled_regmap, |
|---|
| 190 | 180 | }; |
|---|
| 191 | 181 | |
|---|
| 192 | | -static struct regulator_ops tps65090_ldo_ops = { |
|---|
| 182 | +static const struct regulator_ops tps65090_ldo_ops = { |
|---|
| 193 | 183 | }; |
|---|
| 194 | 184 | |
|---|
| 195 | 185 | #define tps65090_REG_DESC(_id, _sname, _en_reg, _en_bits, _nvolt, _volt, _ops) \ |
|---|
| .. | .. |
|---|
| 356 | 346 | for (idx = 0; idx < ARRAY_SIZE(tps65090_matches); idx++) { |
|---|
| 357 | 347 | struct regulator_init_data *ri_data; |
|---|
| 358 | 348 | struct tps65090_regulator_plat_data *rpdata; |
|---|
| 349 | + struct device_node *np; |
|---|
| 359 | 350 | |
|---|
| 360 | 351 | rpdata = ®_pdata[idx]; |
|---|
| 361 | 352 | ri_data = tps65090_matches[idx].init_data; |
|---|
| 362 | | - if (!ri_data || !tps65090_matches[idx].of_node) |
|---|
| 353 | + if (!ri_data) |
|---|
| 354 | + continue; |
|---|
| 355 | + |
|---|
| 356 | + np = tps65090_matches[idx].of_node; |
|---|
| 357 | + if (!np) |
|---|
| 363 | 358 | continue; |
|---|
| 364 | 359 | |
|---|
| 365 | 360 | rpdata->reg_init_data = ri_data; |
|---|
| 366 | | - rpdata->enable_ext_control = of_property_read_bool( |
|---|
| 367 | | - tps65090_matches[idx].of_node, |
|---|
| 368 | | - "ti,enable-ext-control"); |
|---|
| 361 | + rpdata->enable_ext_control = of_property_read_bool(np, |
|---|
| 362 | + "ti,enable-ext-control"); |
|---|
| 369 | 363 | if (rpdata->enable_ext_control) { |
|---|
| 370 | 364 | enum gpiod_flags gflags; |
|---|
| 371 | 365 | |
|---|
| .. | .. |
|---|
| 374 | 368 | gflags = GPIOD_OUT_HIGH; |
|---|
| 375 | 369 | else |
|---|
| 376 | 370 | gflags = GPIOD_OUT_LOW; |
|---|
| 371 | + gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE; |
|---|
| 377 | 372 | |
|---|
| 378 | | - rpdata->gpiod = devm_gpiod_get_from_of_node(&pdev->dev, |
|---|
| 379 | | - tps65090_matches[idx].of_node, |
|---|
| 380 | | - "dcdc-ext-control-gpios", 0, |
|---|
| 381 | | - gflags, |
|---|
| 382 | | - "tps65090"); |
|---|
| 383 | | - if (IS_ERR(rpdata->gpiod)) |
|---|
| 384 | | - return ERR_CAST(rpdata->gpiod); |
|---|
| 385 | | - if (!rpdata->gpiod) |
|---|
| 373 | + rpdata->gpiod = devm_fwnode_gpiod_get( |
|---|
| 374 | + &pdev->dev, |
|---|
| 375 | + of_fwnode_handle(np), |
|---|
| 376 | + "dcdc-ext-control", |
|---|
| 377 | + gflags, |
|---|
| 378 | + "tps65090"); |
|---|
| 379 | + if (PTR_ERR(rpdata->gpiod) == -ENOENT) { |
|---|
| 386 | 380 | dev_err(&pdev->dev, |
|---|
| 387 | 381 | "could not find DCDC external control GPIO\n"); |
|---|
| 382 | + rpdata->gpiod = NULL; |
|---|
| 383 | + } else if (IS_ERR(rpdata->gpiod)) |
|---|
| 384 | + return ERR_CAST(rpdata->gpiod); |
|---|
| 388 | 385 | } |
|---|
| 389 | 386 | |
|---|
| 390 | | - if (of_property_read_u32(tps65090_matches[idx].of_node, |
|---|
| 391 | | - "ti,overcurrent-wait", |
|---|
| 387 | + if (of_property_read_u32(np, "ti,overcurrent-wait", |
|---|
| 392 | 388 | &rpdata->overcurrent_wait) == 0) |
|---|
| 393 | 389 | rpdata->overcurrent_wait_valid = true; |
|---|
| 394 | 390 | |
|---|
| .. | .. |
|---|
| 479 | 475 | else |
|---|
| 480 | 476 | config.of_node = NULL; |
|---|
| 481 | 477 | |
|---|
| 478 | + /* |
|---|
| 479 | + * Hand the GPIO descriptor management over to the regulator |
|---|
| 480 | + * core, remove it from devres management. |
|---|
| 481 | + */ |
|---|
| 482 | + if (config.ena_gpiod) |
|---|
| 483 | + devm_gpiod_unhinge(&pdev->dev, config.ena_gpiod); |
|---|
| 482 | 484 | rdev = devm_regulator_register(&pdev->dev, ri->desc, &config); |
|---|
| 483 | 485 | if (IS_ERR(rdev)) { |
|---|
| 484 | 486 | dev_err(&pdev->dev, "failed to register regulator %s\n", |
|---|