.. | .. |
---|
35 | 35 | #include <linux/pm_runtime.h> |
---|
36 | 36 | #include <linux/delay.h> |
---|
37 | 37 | #include <linux/rockchip/cpu.h> |
---|
| 38 | +#include <soc/rockchip/rockchip_ipa.h> |
---|
38 | 39 | #include <soc/rockchip/rockchip_opp_select.h> |
---|
39 | 40 | |
---|
40 | 41 | #include <linux/mali/mali_utgard.h> |
---|
.. | .. |
---|
232 | 233 | static u32 static_coefficient; |
---|
233 | 234 | static s32 ts[4]; |
---|
234 | 235 | static struct thermal_zone_device *gpu_tz; |
---|
235 | | - |
---|
236 | | -static int power_model_simple_init(struct platform_device *pdev) |
---|
237 | | -{ |
---|
238 | | - struct device_node *power_model_node; |
---|
239 | | - const char *tz_name; |
---|
240 | | - u32 static_power, dynamic_power; |
---|
241 | | - u32 voltage, voltage_squared, voltage_cubed, frequency; |
---|
242 | | - |
---|
243 | | - power_model_node = of_get_child_by_name(pdev->dev.of_node, |
---|
244 | | - "power_model"); |
---|
245 | | - if (!power_model_node) { |
---|
246 | | - dev_err(&pdev->dev, "could not find power_model node\n"); |
---|
247 | | - return -ENODEV; |
---|
248 | | - } |
---|
249 | | - if (!of_device_is_compatible(power_model_node, |
---|
250 | | - "arm,mali-simple-power-model")) { |
---|
251 | | - dev_err(&pdev->dev, "power_model incompatible with simple power model\n"); |
---|
252 | | - return -ENODEV; |
---|
253 | | - } |
---|
254 | | - |
---|
255 | | - if (of_property_read_string(power_model_node, "thermal-zone", |
---|
256 | | - &tz_name)) { |
---|
257 | | - dev_err(&pdev->dev, "ts in power_model not available\n"); |
---|
258 | | - return -EINVAL; |
---|
259 | | - } |
---|
260 | | - |
---|
261 | | - gpu_tz = thermal_zone_get_zone_by_name(tz_name); |
---|
262 | | - if (IS_ERR(gpu_tz)) { |
---|
263 | | - pr_warn_ratelimited("Error getting gpu thermal zone '%s'(%ld), not yet ready?\n", |
---|
264 | | - tz_name, |
---|
265 | | - PTR_ERR(gpu_tz)); |
---|
266 | | - gpu_tz = NULL; |
---|
267 | | - } |
---|
268 | | - |
---|
269 | | - if (of_property_read_u32(power_model_node, "static-power", |
---|
270 | | - &static_power)) { |
---|
271 | | - dev_err(&pdev->dev, "static-power in power_model not available\n"); |
---|
272 | | - return -EINVAL; |
---|
273 | | - } |
---|
274 | | - if (of_property_read_u32(power_model_node, "dynamic-power", |
---|
275 | | - &dynamic_power)) { |
---|
276 | | - dev_err(&pdev->dev, "dynamic-power in power_model not available\n"); |
---|
277 | | - return -EINVAL; |
---|
278 | | - } |
---|
279 | | - if (of_property_read_u32(power_model_node, "voltage", |
---|
280 | | - &voltage)) { |
---|
281 | | - dev_err(&pdev->dev, "voltage in power_model not available\n"); |
---|
282 | | - return -EINVAL; |
---|
283 | | - } |
---|
284 | | - if (of_property_read_u32(power_model_node, "frequency", |
---|
285 | | - &frequency)) { |
---|
286 | | - dev_err(&pdev->dev, "frequency in power_model not available\n"); |
---|
287 | | - return -EINVAL; |
---|
288 | | - } |
---|
289 | | - voltage_squared = (voltage * voltage) / 1000; |
---|
290 | | - voltage_cubed = voltage * voltage * voltage; |
---|
291 | | - static_coefficient = (static_power << 20) / (voltage_cubed >> 10); |
---|
292 | | - dynamic_coefficient = (((dynamic_power * 1000) / voltage_squared) |
---|
293 | | - * 1000) / frequency; |
---|
294 | | - |
---|
295 | | - if (of_property_read_u32_array(power_model_node, "ts", (u32 *)ts, 4)) { |
---|
296 | | - dev_err(&pdev->dev, "ts in power_model not available\n"); |
---|
297 | | - return -EINVAL; |
---|
298 | | - } |
---|
299 | | - |
---|
300 | | - return 0; |
---|
301 | | -} |
---|
| 236 | +static struct ipa_power_model_data *model_data; |
---|
302 | 237 | |
---|
303 | 238 | /* Calculate gpu static power example for reference */ |
---|
304 | 239 | static unsigned long rk_model_static_power(struct devfreq *devfreq, |
---|
.. | .. |
---|
360 | 295 | return dynamic_power; |
---|
361 | 296 | } |
---|
362 | 297 | |
---|
363 | | -struct devfreq_cooling_power rk_cooling_ops = { |
---|
| 298 | +static struct devfreq_cooling_power rk_cooling_ops = { |
---|
364 | 299 | .get_static_power = rk_model_static_power, |
---|
365 | 300 | .get_dynamic_power = rk_model_dynamic_power, |
---|
366 | 301 | }; |
---|
| 302 | + |
---|
| 303 | +static unsigned long mali_devfreq_get_static_power(struct devfreq *devfreq, |
---|
| 304 | + unsigned long voltage) |
---|
| 305 | +{ |
---|
| 306 | + return rockchip_ipa_get_static_power(model_data, voltage); |
---|
| 307 | +} |
---|
| 308 | + |
---|
| 309 | +static int power_model_simple_init(struct platform_device *pdev) |
---|
| 310 | +{ |
---|
| 311 | + struct device_node *power_model_node; |
---|
| 312 | + const char *tz_name; |
---|
| 313 | + u32 static_power, dynamic_power; |
---|
| 314 | + u32 voltage, voltage_squared, voltage_cubed, frequency; |
---|
| 315 | + |
---|
| 316 | + if (of_find_compatible_node(pdev->dev.of_node, NULL, "simple-power-model")) { |
---|
| 317 | + of_property_read_u32(pdev->dev.of_node, |
---|
| 318 | + "dynamic-power-coefficient", |
---|
| 319 | + (u32 *)&rk_cooling_ops.dyn_power_coeff); |
---|
| 320 | + model_data = rockchip_ipa_power_model_init(&pdev->dev, |
---|
| 321 | + "gpu_leakage"); |
---|
| 322 | + if (IS_ERR_OR_NULL(model_data)) { |
---|
| 323 | + model_data = NULL; |
---|
| 324 | + dev_err(&pdev->dev, "failed to initialize power model\n"); |
---|
| 325 | + } else if (model_data->dynamic_coefficient) { |
---|
| 326 | + rk_cooling_ops.dyn_power_coeff = |
---|
| 327 | + model_data->dynamic_coefficient; |
---|
| 328 | + rk_cooling_ops.get_dynamic_power = NULL; |
---|
| 329 | + rk_cooling_ops.get_static_power = mali_devfreq_get_static_power; |
---|
| 330 | + } |
---|
| 331 | + if (!rk_cooling_ops.dyn_power_coeff) { |
---|
| 332 | + dev_err(&pdev->dev, "failed to get dynamic-coefficient\n"); |
---|
| 333 | + return -EINVAL; |
---|
| 334 | + } |
---|
| 335 | + |
---|
| 336 | + return 0; |
---|
| 337 | + } |
---|
| 338 | + |
---|
| 339 | + power_model_node = of_get_child_by_name(pdev->dev.of_node, |
---|
| 340 | + "power_model"); |
---|
| 341 | + if (!power_model_node) { |
---|
| 342 | + dev_err(&pdev->dev, "could not find power_model node\n"); |
---|
| 343 | + return -ENODEV; |
---|
| 344 | + } |
---|
| 345 | + if (!of_device_is_compatible(power_model_node, |
---|
| 346 | + "arm,mali-simple-power-model")) { |
---|
| 347 | + dev_err(&pdev->dev, "power_model incompatible with simple power model\n"); |
---|
| 348 | + return -ENODEV; |
---|
| 349 | + } |
---|
| 350 | + |
---|
| 351 | + if (of_property_read_string(power_model_node, "thermal-zone", |
---|
| 352 | + &tz_name)) { |
---|
| 353 | + dev_err(&pdev->dev, "ts in power_model not available\n"); |
---|
| 354 | + return -EINVAL; |
---|
| 355 | + } |
---|
| 356 | + |
---|
| 357 | + gpu_tz = thermal_zone_get_zone_by_name(tz_name); |
---|
| 358 | + if (IS_ERR(gpu_tz)) { |
---|
| 359 | + pr_warn_ratelimited("Error getting gpu thermal zone '%s'(%ld), not yet ready?\n", |
---|
| 360 | + tz_name, |
---|
| 361 | + PTR_ERR(gpu_tz)); |
---|
| 362 | + gpu_tz = NULL; |
---|
| 363 | + } |
---|
| 364 | + |
---|
| 365 | + if (of_property_read_u32(power_model_node, "static-power", |
---|
| 366 | + &static_power)) { |
---|
| 367 | + dev_err(&pdev->dev, "static-power in power_model not available\n"); |
---|
| 368 | + return -EINVAL; |
---|
| 369 | + } |
---|
| 370 | + if (of_property_read_u32(power_model_node, "dynamic-power", |
---|
| 371 | + &dynamic_power)) { |
---|
| 372 | + dev_err(&pdev->dev, "dynamic-power in power_model not available\n"); |
---|
| 373 | + return -EINVAL; |
---|
| 374 | + } |
---|
| 375 | + if (of_property_read_u32(power_model_node, "voltage", |
---|
| 376 | + &voltage)) { |
---|
| 377 | + dev_err(&pdev->dev, "voltage in power_model not available\n"); |
---|
| 378 | + return -EINVAL; |
---|
| 379 | + } |
---|
| 380 | + if (of_property_read_u32(power_model_node, "frequency", |
---|
| 381 | + &frequency)) { |
---|
| 382 | + dev_err(&pdev->dev, "frequency in power_model not available\n"); |
---|
| 383 | + return -EINVAL; |
---|
| 384 | + } |
---|
| 385 | + voltage_squared = (voltage * voltage) / 1000; |
---|
| 386 | + voltage_cubed = voltage * voltage * voltage; |
---|
| 387 | + static_coefficient = (static_power << 20) / (voltage_cubed >> 10); |
---|
| 388 | + dynamic_coefficient = (((dynamic_power * 1000) / voltage_squared) |
---|
| 389 | + * 1000) / frequency; |
---|
| 390 | + |
---|
| 391 | + if (of_property_read_u32_array(power_model_node, "ts", (u32 *)ts, 4)) { |
---|
| 392 | + dev_err(&pdev->dev, "ts in power_model not available\n"); |
---|
| 393 | + return -EINVAL; |
---|
| 394 | + } |
---|
| 395 | + |
---|
| 396 | + return 0; |
---|
| 397 | +} |
---|
| 398 | + |
---|
367 | 399 | #endif |
---|
368 | 400 | |
---|
369 | 401 | /*---------------------------------------------------------------------------*/ |
---|
.. | .. |
---|
376 | 408 | #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK) |
---|
377 | 409 | struct mali_device *mdev = dev_get_drvdata(dev); |
---|
378 | 410 | |
---|
379 | | - if (mdev->clock) |
---|
380 | | - ret = clk_enable(mdev->clock); |
---|
| 411 | + ret = clk_bulk_enable(mdev->num_clks, mdev->clks); |
---|
381 | 412 | #endif |
---|
382 | 413 | return ret; |
---|
383 | 414 | } |
---|
.. | .. |
---|
387 | 418 | #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK) |
---|
388 | 419 | struct mali_device *mdev = dev_get_drvdata(dev); |
---|
389 | 420 | |
---|
390 | | - if (mdev->clock) |
---|
391 | | - clk_disable(mdev->clock); |
---|
| 421 | + clk_bulk_disable(mdev->num_clks, mdev->clks); |
---|
392 | 422 | #endif |
---|
393 | 423 | } |
---|
394 | 424 | |
---|
.. | .. |
---|
432 | 462 | goto fail_to_enable_regulator; |
---|
433 | 463 | } |
---|
434 | 464 | |
---|
| 465 | + if (cpu_is_rk3528()) { |
---|
| 466 | +#if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK) |
---|
| 467 | + struct mali_device *mdev = dev_get_drvdata(dev); |
---|
| 468 | + |
---|
| 469 | + clk_set_rate(mdev->clock, mdev->current_freq); |
---|
| 470 | +#endif |
---|
| 471 | + } |
---|
435 | 472 | platform->is_powered = true; |
---|
436 | 473 | } |
---|
437 | 474 | |
---|
.. | .. |
---|
449 | 486 | struct rk_context *platform = s_rk_context; |
---|
450 | 487 | |
---|
451 | 488 | if (platform->is_powered) { |
---|
| 489 | + if (cpu_is_rk3528()) { |
---|
| 490 | +#if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK) |
---|
| 491 | + struct mali_device *mdev = dev_get_drvdata(dev); |
---|
| 492 | + |
---|
| 493 | + //use normal pll 200M for gpu when suspend |
---|
| 494 | + clk_set_rate(mdev->clock, 200000000); |
---|
| 495 | +#endif |
---|
| 496 | + } |
---|
452 | 497 | rk_platform_disable_clk_gpu(dev); |
---|
453 | 498 | rk_platform_disable_gpu_regulator(dev); |
---|
454 | 499 | |
---|