| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | | - * Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved. |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 5 | | - * it under the terms of the GNU General Public License version 2 and |
|---|
| 6 | | - * only version 2 as published by the Free Software Foundation. |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 9 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 10 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 11 | | - * GNU General Public License for more details. |
|---|
| 3 | + * Copyright (c) 2015, 2017-2018, 2022, The Linux Foundation. All rights reserved. |
|---|
| 12 | 4 | */ |
|---|
| 13 | 5 | |
|---|
| 14 | 6 | #include <linux/bitops.h> |
|---|
| 15 | 7 | #include <linux/delay.h> |
|---|
| 16 | 8 | #include <linux/err.h> |
|---|
| 9 | +#include <linux/export.h> |
|---|
| 17 | 10 | #include <linux/jiffies.h> |
|---|
| 18 | 11 | #include <linux/kernel.h> |
|---|
| 19 | 12 | #include <linux/ktime.h> |
|---|
| 20 | 13 | #include <linux/pm_domain.h> |
|---|
| 21 | 14 | #include <linux/regmap.h> |
|---|
| 15 | +#include <linux/regulator/consumer.h> |
|---|
| 22 | 16 | #include <linux/reset-controller.h> |
|---|
| 23 | 17 | #include <linux/slab.h> |
|---|
| 24 | 18 | #include "gdsc.h" |
|---|
| .. | .. |
|---|
| 36 | 30 | /* CFG_GDSCR */ |
|---|
| 37 | 31 | #define GDSC_POWER_UP_COMPLETE BIT(16) |
|---|
| 38 | 32 | #define GDSC_POWER_DOWN_COMPLETE BIT(15) |
|---|
| 33 | +#define GDSC_RETAIN_FF_ENABLE BIT(11) |
|---|
| 39 | 34 | #define CFG_GDSCR_OFFSET 0x4 |
|---|
| 40 | 35 | |
|---|
| 41 | 36 | /* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */ |
|---|
| 42 | | -#define EN_REST_WAIT_VAL (0x2 << 20) |
|---|
| 43 | | -#define EN_FEW_WAIT_VAL (0x8 << 16) |
|---|
| 44 | | -#define CLK_DIS_WAIT_VAL (0x2 << 12) |
|---|
| 37 | +#define EN_REST_WAIT_VAL 0x2 |
|---|
| 38 | +#define EN_FEW_WAIT_VAL 0x8 |
|---|
| 39 | +#define CLK_DIS_WAIT_VAL 0x2 |
|---|
| 40 | + |
|---|
| 41 | +/* Transition delay shifts */ |
|---|
| 42 | +#define EN_REST_WAIT_SHIFT 20 |
|---|
| 43 | +#define EN_FEW_WAIT_SHIFT 16 |
|---|
| 44 | +#define CLK_DIS_WAIT_SHIFT 12 |
|---|
| 45 | 45 | |
|---|
| 46 | 46 | #define RETAIN_MEM BIT(14) |
|---|
| 47 | 47 | #define RETAIN_PERIPH BIT(13) |
|---|
| .. | .. |
|---|
| 120 | 120 | int ret; |
|---|
| 121 | 121 | u32 val = (status == GDSC_ON) ? 0 : SW_COLLAPSE_MASK; |
|---|
| 122 | 122 | |
|---|
| 123 | + if (status == GDSC_ON && sc->rsupply) { |
|---|
| 124 | + ret = regulator_enable(sc->rsupply); |
|---|
| 125 | + if (ret < 0) |
|---|
| 126 | + return ret; |
|---|
| 127 | + } |
|---|
| 128 | + |
|---|
| 123 | 129 | ret = regmap_update_bits(sc->regmap, sc->gdscr, SW_COLLAPSE_MASK, val); |
|---|
| 124 | 130 | if (ret) |
|---|
| 125 | 131 | return ret; |
|---|
| .. | .. |
|---|
| 149 | 155 | udelay(1); |
|---|
| 150 | 156 | } |
|---|
| 151 | 157 | |
|---|
| 152 | | - return gdsc_poll_status(sc, status); |
|---|
| 158 | + ret = gdsc_poll_status(sc, status); |
|---|
| 159 | + WARN(ret, "%s status stuck at 'o%s'", sc->pd.name, status ? "ff" : "n"); |
|---|
| 160 | + |
|---|
| 161 | + if (!ret && status == GDSC_OFF && sc->rsupply) { |
|---|
| 162 | + ret = regulator_disable(sc->rsupply); |
|---|
| 163 | + if (ret < 0) |
|---|
| 164 | + return ret; |
|---|
| 165 | + } |
|---|
| 166 | + |
|---|
| 167 | + return ret; |
|---|
| 153 | 168 | } |
|---|
| 154 | 169 | |
|---|
| 155 | 170 | static inline int gdsc_deassert_reset(struct gdsc *sc) |
|---|
| .. | .. |
|---|
| 173 | 188 | static inline void gdsc_force_mem_on(struct gdsc *sc) |
|---|
| 174 | 189 | { |
|---|
| 175 | 190 | int i; |
|---|
| 176 | | - u32 mask = RETAIN_MEM | RETAIN_PERIPH; |
|---|
| 191 | + u32 mask = RETAIN_MEM; |
|---|
| 192 | + |
|---|
| 193 | + if (!(sc->flags & NO_RET_PERIPH)) |
|---|
| 194 | + mask |= RETAIN_PERIPH; |
|---|
| 177 | 195 | |
|---|
| 178 | 196 | for (i = 0; i < sc->cxc_count; i++) |
|---|
| 179 | 197 | regmap_update_bits(sc->regmap, sc->cxcs[i], mask, mask); |
|---|
| .. | .. |
|---|
| 182 | 200 | static inline void gdsc_clear_mem_on(struct gdsc *sc) |
|---|
| 183 | 201 | { |
|---|
| 184 | 202 | int i; |
|---|
| 185 | | - u32 mask = RETAIN_MEM | RETAIN_PERIPH; |
|---|
| 203 | + u32 mask = RETAIN_MEM; |
|---|
| 204 | + |
|---|
| 205 | + if (!(sc->flags & NO_RET_PERIPH)) |
|---|
| 206 | + mask |= RETAIN_PERIPH; |
|---|
| 186 | 207 | |
|---|
| 187 | 208 | for (i = 0; i < sc->cxc_count; i++) |
|---|
| 188 | 209 | regmap_update_bits(sc->regmap, sc->cxcs[i], mask, 0); |
|---|
| .. | .. |
|---|
| 208 | 229 | regmap_update_bits(sc->regmap, sc->clamp_io_ctrl, |
|---|
| 209 | 230 | GMEM_RESET_MASK, 0); |
|---|
| 210 | 231 | } |
|---|
| 232 | + |
|---|
| 233 | +static void gdsc_retain_ff_on(struct gdsc *sc) |
|---|
| 234 | +{ |
|---|
| 235 | + u32 mask = GDSC_RETAIN_FF_ENABLE; |
|---|
| 236 | + |
|---|
| 237 | + regmap_update_bits(sc->regmap, sc->gdscr, mask, mask); |
|---|
| 238 | +} |
|---|
| 239 | + |
|---|
| 211 | 240 | static int gdsc_enable(struct generic_pm_domain *domain) |
|---|
| 212 | 241 | { |
|---|
| 213 | 242 | struct gdsc *sc = domain_to_gdsc(domain); |
|---|
| .. | .. |
|---|
| 259 | 288 | */ |
|---|
| 260 | 289 | udelay(1); |
|---|
| 261 | 290 | } |
|---|
| 291 | + |
|---|
| 292 | + if (sc->flags & RETAIN_FF_ENABLE) |
|---|
| 293 | + gdsc_retain_ff_on(sc); |
|---|
| 262 | 294 | |
|---|
| 263 | 295 | return 0; |
|---|
| 264 | 296 | } |
|---|
| .. | .. |
|---|
| 314 | 346 | */ |
|---|
| 315 | 347 | mask = HW_CONTROL_MASK | SW_OVERRIDE_MASK | |
|---|
| 316 | 348 | EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK; |
|---|
| 317 | | - val = EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL; |
|---|
| 349 | + |
|---|
| 350 | + if (!sc->en_rest_wait_val) |
|---|
| 351 | + sc->en_rest_wait_val = EN_REST_WAIT_VAL; |
|---|
| 352 | + if (!sc->en_few_wait_val) |
|---|
| 353 | + sc->en_few_wait_val = EN_FEW_WAIT_VAL; |
|---|
| 354 | + if (!sc->clk_dis_wait_val) |
|---|
| 355 | + sc->clk_dis_wait_val = CLK_DIS_WAIT_VAL; |
|---|
| 356 | + |
|---|
| 357 | + val = sc->en_rest_wait_val << EN_REST_WAIT_SHIFT | |
|---|
| 358 | + sc->en_few_wait_val << EN_FEW_WAIT_SHIFT | |
|---|
| 359 | + sc->clk_dis_wait_val << CLK_DIS_WAIT_SHIFT; |
|---|
| 360 | + |
|---|
| 318 | 361 | ret = regmap_update_bits(sc->regmap, sc->gdscr, mask, val); |
|---|
| 319 | 362 | if (ret) |
|---|
| 320 | 363 | return ret; |
|---|
| .. | .. |
|---|
| 330 | 373 | if (on < 0) |
|---|
| 331 | 374 | return on; |
|---|
| 332 | 375 | |
|---|
| 333 | | - /* |
|---|
| 334 | | - * Votable GDSCs can be ON due to Vote from other masters. |
|---|
| 335 | | - * If a Votable GDSC is ON, make sure we have a Vote. |
|---|
| 336 | | - */ |
|---|
| 337 | | - if ((sc->flags & VOTABLE) && on) |
|---|
| 338 | | - gdsc_enable(&sc->pd); |
|---|
| 376 | + if (on) { |
|---|
| 377 | + /* The regulator must be on, sync the kernel state */ |
|---|
| 378 | + if (sc->rsupply) { |
|---|
| 379 | + ret = regulator_enable(sc->rsupply); |
|---|
| 380 | + if (ret < 0) |
|---|
| 381 | + return ret; |
|---|
| 382 | + } |
|---|
| 339 | 383 | |
|---|
| 340 | | - /* If ALWAYS_ON GDSCs are not ON, turn them ON */ |
|---|
| 341 | | - if (sc->flags & ALWAYS_ON) { |
|---|
| 342 | | - if (!on) |
|---|
| 343 | | - gdsc_enable(&sc->pd); |
|---|
| 384 | + /* |
|---|
| 385 | + * Votable GDSCs can be ON due to Vote from other masters. |
|---|
| 386 | + * If a Votable GDSC is ON, make sure we have a Vote. |
|---|
| 387 | + */ |
|---|
| 388 | + if (sc->flags & VOTABLE) { |
|---|
| 389 | + ret = regmap_update_bits(sc->regmap, sc->gdscr, |
|---|
| 390 | + SW_COLLAPSE_MASK, val); |
|---|
| 391 | + if (ret) |
|---|
| 392 | + return ret; |
|---|
| 393 | + } |
|---|
| 394 | + |
|---|
| 395 | + /* Turn on HW trigger mode if supported */ |
|---|
| 396 | + if (sc->flags & HW_CTRL) { |
|---|
| 397 | + ret = gdsc_hwctrl(sc, true); |
|---|
| 398 | + if (ret < 0) |
|---|
| 399 | + return ret; |
|---|
| 400 | + } |
|---|
| 401 | + |
|---|
| 402 | + /* |
|---|
| 403 | + * Make sure the retain bit is set if the GDSC is already on, |
|---|
| 404 | + * otherwise we end up turning off the GDSC and destroying all |
|---|
| 405 | + * the register contents that we thought we were saving. |
|---|
| 406 | + */ |
|---|
| 407 | + if (sc->flags & RETAIN_FF_ENABLE) |
|---|
| 408 | + gdsc_retain_ff_on(sc); |
|---|
| 409 | + } else if (sc->flags & ALWAYS_ON) { |
|---|
| 410 | + /* If ALWAYS_ON GDSCs are not ON, turn them ON */ |
|---|
| 411 | + gdsc_enable(&sc->pd); |
|---|
| 344 | 412 | on = true; |
|---|
| 345 | | - sc->pd.flags |= GENPD_FLAG_ALWAYS_ON; |
|---|
| 346 | 413 | } |
|---|
| 347 | 414 | |
|---|
| 348 | 415 | if (on || (sc->pwrsts & PWRSTS_RET)) |
|---|
| .. | .. |
|---|
| 350 | 417 | else |
|---|
| 351 | 418 | gdsc_clear_mem_on(sc); |
|---|
| 352 | 419 | |
|---|
| 353 | | - sc->pd.power_off = gdsc_disable; |
|---|
| 354 | | - sc->pd.power_on = gdsc_enable; |
|---|
| 420 | + if (sc->flags & ALWAYS_ON) |
|---|
| 421 | + sc->pd.flags |= GENPD_FLAG_ALWAYS_ON; |
|---|
| 422 | + if (!sc->pd.power_off) |
|---|
| 423 | + sc->pd.power_off = gdsc_disable; |
|---|
| 424 | + if (!sc->pd.power_on) |
|---|
| 425 | + sc->pd.power_on = gdsc_enable; |
|---|
| 355 | 426 | pm_genpd_init(&sc->pd, NULL, !on); |
|---|
| 356 | 427 | |
|---|
| 357 | 428 | return 0; |
|---|
| .. | .. |
|---|
| 374 | 445 | GFP_KERNEL); |
|---|
| 375 | 446 | if (!data->domains) |
|---|
| 376 | 447 | return -ENOMEM; |
|---|
| 448 | + |
|---|
| 449 | + for (i = 0; i < num; i++) { |
|---|
| 450 | + if (!scs[i] || !scs[i]->supply) |
|---|
| 451 | + continue; |
|---|
| 452 | + |
|---|
| 453 | + scs[i]->rsupply = devm_regulator_get(dev, scs[i]->supply); |
|---|
| 454 | + if (IS_ERR(scs[i]->rsupply)) |
|---|
| 455 | + return PTR_ERR(scs[i]->rsupply); |
|---|
| 456 | + } |
|---|
| 377 | 457 | |
|---|
| 378 | 458 | data->num_domains = num; |
|---|
| 379 | 459 | for (i = 0; i < num; i++) { |
|---|
| .. | .. |
|---|
| 414 | 494 | } |
|---|
| 415 | 495 | of_genpd_del_provider(dev->of_node); |
|---|
| 416 | 496 | } |
|---|
| 497 | + |
|---|
| 498 | +/* |
|---|
| 499 | + * On SDM845+ the GPU GX domain is *almost* entirely controlled by the GMU |
|---|
| 500 | + * running in the CX domain so the CPU doesn't need to know anything about the |
|---|
| 501 | + * GX domain EXCEPT.... |
|---|
| 502 | + * |
|---|
| 503 | + * Hardware constraints dictate that the GX be powered down before the CX. If |
|---|
| 504 | + * the GMU crashes it could leave the GX on. In order to successfully bring back |
|---|
| 505 | + * the device the CPU needs to disable the GX headswitch. There being no sane |
|---|
| 506 | + * way to reach in and touch that register from deep inside the GPU driver we |
|---|
| 507 | + * need to set up the infrastructure to be able to ensure that the GPU can |
|---|
| 508 | + * ensure that the GX is off during this super special case. We do this by |
|---|
| 509 | + * defining a GX gdsc with a dummy enable function and a "default" disable |
|---|
| 510 | + * function. |
|---|
| 511 | + * |
|---|
| 512 | + * This allows us to attach with genpd_dev_pm_attach_by_name() in the GPU |
|---|
| 513 | + * driver. During power up, nothing will happen from the CPU (and the GMU will |
|---|
| 514 | + * power up normally but during power down this will ensure that the GX domain |
|---|
| 515 | + * is *really* off - this gives us a semi standard way of doing what we need. |
|---|
| 516 | + */ |
|---|
| 517 | +int gdsc_gx_do_nothing_enable(struct generic_pm_domain *domain) |
|---|
| 518 | +{ |
|---|
| 519 | + /* Do nothing but give genpd the impression that we were successful */ |
|---|
| 520 | + return 0; |
|---|
| 521 | +} |
|---|
| 522 | +EXPORT_SYMBOL_GPL(gdsc_gx_do_nothing_enable); |
|---|