Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

simplefb: Claim and enable regulators

This claims and enables regulators listed in the simple framebuffer dt
node. This is needed so that regulators powering the display pipeline
and external hardware, described in the device node and known by the
kernel code, will remain properly enabled.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

authored by

Chen-Yu Tsai and committed by
Tomi Valkeinen
814740e7 bd58a390

+119 -1
+119 -1
drivers/video/fbdev/simplefb.c
··· 28 28 #include <linux/platform_device.h> 29 29 #include <linux/clk.h> 30 30 #include <linux/clk-provider.h> 31 + #include <linux/of.h> 31 32 #include <linux/of_platform.h> 33 + #include <linux/parser.h> 34 + #include <linux/regulator/consumer.h> 32 35 33 36 static struct fb_fix_screeninfo simplefb_fix = { 34 37 .id = "simple", ··· 177 174 int clk_count; 178 175 struct clk **clks; 179 176 #endif 177 + #if defined CONFIG_OF && defined CONFIG_REGULATOR 178 + u32 regulator_count; 179 + struct regulator **regulators; 180 + #endif 180 181 }; 181 182 182 183 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK ··· 276 269 static void simplefb_clocks_destroy(struct simplefb_par *par) { } 277 270 #endif 278 271 272 + #if defined CONFIG_OF && defined CONFIG_REGULATOR 273 + 274 + #define SUPPLY_SUFFIX "-supply" 275 + 276 + /* 277 + * Regulator handling code. 278 + * 279 + * Here we handle the num-supplies and vin*-supply properties of our 280 + * "simple-framebuffer" dt node. This is necessary so that we can make sure 281 + * that any regulators needed by the display hardware that the bootloader 282 + * set up for us (and for which it provided a simplefb dt node), stay up, 283 + * for the life of the simplefb driver. 284 + * 285 + * When the driver unloads, we cleanly disable, and then release the 286 + * regulators. 287 + * 288 + * We only complain about errors here, no action is taken as the most likely 289 + * error can only happen due to a mismatch between the bootloader which set 290 + * up simplefb, and the regulator definitions in the device tree. Chances are 291 + * that there are no adverse effects, and if there are, a clean teardown of 292 + * the fb probe will not help us much either. So just complain and carry on, 293 + * and hope that the user actually gets a working fb at the end of things. 294 + */ 295 + static int simplefb_regulators_init(struct simplefb_par *par, 296 + struct platform_device *pdev) 297 + { 298 + struct device_node *np = pdev->dev.of_node; 299 + struct property *prop; 300 + struct regulator *regulator; 301 + const char *p; 302 + int count = 0, i = 0, ret; 303 + 304 + if (dev_get_platdata(&pdev->dev) || !np) 305 + return 0; 306 + 307 + /* Count the number of regulator supplies */ 308 + for_each_property_of_node(np, prop) { 309 + p = strstr(prop->name, SUPPLY_SUFFIX); 310 + if (p && p != prop->name) 311 + count++; 312 + } 313 + 314 + if (!count) 315 + return 0; 316 + 317 + par->regulators = devm_kcalloc(&pdev->dev, count, 318 + sizeof(struct regulator *), GFP_KERNEL); 319 + if (!par->regulators) 320 + return -ENOMEM; 321 + 322 + /* Get all the regulators */ 323 + for_each_property_of_node(np, prop) { 324 + char name[32]; /* 32 is max size of property name */ 325 + 326 + p = strstr(prop->name, SUPPLY_SUFFIX); 327 + if (!p || p == prop->name) 328 + continue; 329 + 330 + strlcpy(name, prop->name, 331 + strlen(prop->name) - strlen(SUPPLY_SUFFIX) + 1); 332 + regulator = devm_regulator_get_optional(&pdev->dev, name); 333 + if (IS_ERR(regulator)) { 334 + if (PTR_ERR(regulator) == -EPROBE_DEFER) 335 + return -EPROBE_DEFER; 336 + dev_err(&pdev->dev, "regulator %s not found: %ld\n", 337 + name, PTR_ERR(regulator)); 338 + continue; 339 + } 340 + par->regulators[i++] = regulator; 341 + } 342 + par->regulator_count = i; 343 + 344 + /* Enable all the regulators */ 345 + for (i = 0; i < par->regulator_count; i++) { 346 + ret = regulator_enable(par->regulators[i]); 347 + if (ret) { 348 + dev_err(&pdev->dev, 349 + "failed to enable regulator %d: %d\n", 350 + i, ret); 351 + devm_regulator_put(par->regulators[i]); 352 + par->regulators[i] = NULL; 353 + } 354 + } 355 + 356 + return 0; 357 + } 358 + 359 + static void simplefb_regulators_destroy(struct simplefb_par *par) 360 + { 361 + int i; 362 + 363 + if (!par->regulators) 364 + return; 365 + 366 + for (i = 0; i < par->regulator_count; i++) 367 + if (par->regulators[i]) 368 + regulator_disable(par->regulators[i]); 369 + } 370 + #else 371 + static int simplefb_regulators_init(struct simplefb_par *par, 372 + struct platform_device *pdev) { return 0; } 373 + static void simplefb_regulators_destroy(struct simplefb_par *par) { } 374 + #endif 375 + 279 376 static int simplefb_probe(struct platform_device *pdev) 280 377 { 281 378 int ret; ··· 451 340 if (ret < 0) 452 341 goto error_unmap; 453 342 343 + ret = simplefb_regulators_init(par, pdev); 344 + if (ret < 0) 345 + goto error_clocks; 346 + 454 347 dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes, mapped to 0x%p\n", 455 348 info->fix.smem_start, info->fix.smem_len, 456 349 info->screen_base); ··· 466 351 ret = register_framebuffer(info); 467 352 if (ret < 0) { 468 353 dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret); 469 - goto error_clocks; 354 + goto error_regulators; 470 355 } 471 356 472 357 dev_info(&pdev->dev, "fb%d: simplefb registered!\n", info->node); 473 358 474 359 return 0; 475 360 361 + error_regulators: 362 + simplefb_regulators_destroy(par); 476 363 error_clocks: 477 364 simplefb_clocks_destroy(par); 478 365 error_unmap: ··· 490 373 struct simplefb_par *par = info->par; 491 374 492 375 unregister_framebuffer(info); 376 + simplefb_regulators_destroy(par); 493 377 simplefb_clocks_destroy(par); 494 378 framebuffer_release(info); 495 379