| .. | .. |
|---|
| 31 | 31 | #include <linux/clk.h> |
|---|
| 32 | 32 | #include <linux/regulator/consumer.h> |
|---|
| 33 | 33 | #include <linux/mali/mali_utgard.h> |
|---|
| 34 | +#include <linux/pm_runtime.h> |
|---|
| 34 | 35 | #include <soc/rockchip/rockchip_opp_select.h> |
|---|
| 35 | 36 | |
|---|
| 36 | 37 | #include "mali_kernel_common.h" |
|---|
| .. | .. |
|---|
| 177 | 178 | |
|---|
| 178 | 179 | static int mali_open(struct inode *inode, struct file *filp); |
|---|
| 179 | 180 | static int mali_release(struct inode *inode, struct file *filp); |
|---|
| 180 | | -#ifdef HAVE_UNLOCKED_IOCTL |
|---|
| 181 | 181 | static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); |
|---|
| 182 | | -#else |
|---|
| 183 | | -static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); |
|---|
| 184 | | -#endif |
|---|
| 185 | 182 | |
|---|
| 186 | 183 | static int mali_probe(struct platform_device *pdev); |
|---|
| 187 | 184 | static int mali_remove(struct platform_device *pdev); |
|---|
| .. | .. |
|---|
| 275 | 272 | .owner = THIS_MODULE, |
|---|
| 276 | 273 | .open = mali_open, |
|---|
| 277 | 274 | .release = mali_release, |
|---|
| 278 | | -#ifdef HAVE_UNLOCKED_IOCTL |
|---|
| 279 | 275 | .unlocked_ioctl = mali_ioctl, |
|---|
| 280 | | -#else |
|---|
| 281 | | - .ioctl = mali_ioctl, |
|---|
| 282 | | -#endif |
|---|
| 283 | 276 | .compat_ioctl = mali_ioctl, |
|---|
| 284 | 277 | .mmap = mali_mmap |
|---|
| 285 | 278 | }; |
|---|
| .. | .. |
|---|
| 521 | 514 | int err; |
|---|
| 522 | 515 | #ifdef CONFIG_MALI_DEVFREQ |
|---|
| 523 | 516 | struct mali_device *mdev; |
|---|
| 517 | + const char *name = "mali"; |
|---|
| 524 | 518 | #endif |
|---|
| 525 | 519 | |
|---|
| 526 | 520 | MALI_DEBUG_PRINT(2, ("mali_probe(): Called for platform device %s\n", pdev->name)); |
|---|
| .. | .. |
|---|
| 575 | 569 | mdev->regulator = NULL; |
|---|
| 576 | 570 | /* Allow probe to continue without regulator */ |
|---|
| 577 | 571 | } |
|---|
| 572 | + if (mdev->regulator) { |
|---|
| 573 | + mdev->opp_table = dev_pm_opp_set_regulators(mdev->dev, &name, 1); |
|---|
| 574 | + if (IS_ERR(mdev->opp_table)) { |
|---|
| 575 | + mdev->opp_table = NULL; |
|---|
| 576 | + MALI_DEBUG_PRINT(2, ("Continuing without opp regulator\n")); |
|---|
| 577 | + } |
|---|
| 578 | + } |
|---|
| 578 | 579 | #endif /* LINUX_VERSION_CODE >= 3, 12, 0 */ |
|---|
| 580 | + |
|---|
| 581 | + mdev->num_clks = devm_clk_bulk_get_all(mdev->dev, &mdev->clks); |
|---|
| 582 | + if (mdev->num_clks < 1) { |
|---|
| 583 | + MALI_DEBUG_PRINT(2, ("Continuing without Mali clock control\n")); |
|---|
| 584 | + mdev->num_clks = 0; |
|---|
| 585 | + mdev->clock = NULL; |
|---|
| 586 | + } else { |
|---|
| 587 | + /* Get "clk_mali" in the device tree for gpu dvfs */ |
|---|
| 588 | + mdev->clock = clk_get(mdev->dev, "clk_mali"); |
|---|
| 589 | + if (IS_ERR_OR_NULL(mdev->clock)) { |
|---|
| 590 | + MALI_DEBUG_PRINT(2, ("Continuing without Mali dvfs clock\n")); |
|---|
| 591 | + /* Allow probe to continue without clock. */ |
|---|
| 592 | + mdev->clock = NULL; |
|---|
| 593 | + } |
|---|
| 594 | + } |
|---|
| 595 | + err = clk_bulk_prepare_enable(mdev->num_clks, mdev->clks); |
|---|
| 596 | + if (err) { |
|---|
| 597 | + MALI_PRINT_ERROR(("Failed to prepare clock (%d)\n", err)); |
|---|
| 598 | + goto clock_prepare_failed; |
|---|
| 599 | + } |
|---|
| 579 | 600 | |
|---|
| 580 | 601 | err = rk_platform_init_opp_table(mdev->dev); |
|---|
| 581 | 602 | if (err) |
|---|
| 582 | 603 | MALI_DEBUG_PRINT(3, ("Failed to init_opp_table\n")); |
|---|
| 583 | | - |
|---|
| 584 | | - /* Need to name the gpu clock "clk_mali" in the device tree */ |
|---|
| 585 | | - mdev->clock = clk_get(mdev->dev, "clk_mali"); |
|---|
| 586 | | - if (IS_ERR_OR_NULL(mdev->clock)) { |
|---|
| 587 | | - MALI_DEBUG_PRINT(2, ("Continuing without Mali clock control\n")); |
|---|
| 588 | | - mdev->clock = NULL; |
|---|
| 589 | | - /* Allow probe to continue without clock. */ |
|---|
| 590 | | - } else { |
|---|
| 591 | | - err = clk_prepare(mdev->clock); |
|---|
| 592 | | - if (err) { |
|---|
| 593 | | - MALI_PRINT_ERROR(("Failed to prepare clock (%d)\n", err)); |
|---|
| 594 | | - goto clock_prepare_failed; |
|---|
| 595 | | - } |
|---|
| 596 | | - } |
|---|
| 597 | 604 | |
|---|
| 598 | 605 | /* initilize pm metrics related */ |
|---|
| 599 | 606 | if (mali_pm_metrics_init(mdev) < 0) { |
|---|
| .. | .. |
|---|
| 605 | 612 | MALI_DEBUG_PRINT(2, ("mali devfreq init failed\n")); |
|---|
| 606 | 613 | goto devfreq_init_failed; |
|---|
| 607 | 614 | } |
|---|
| 615 | + clk_bulk_disable(mdev->num_clks, mdev->clks); |
|---|
| 608 | 616 | #endif |
|---|
| 609 | 617 | |
|---|
| 610 | 618 | |
|---|
| .. | .. |
|---|
| 640 | 648 | devfreq_init_failed: |
|---|
| 641 | 649 | mali_pm_metrics_term(mdev); |
|---|
| 642 | 650 | pm_metrics_init_failed: |
|---|
| 643 | | - clk_unprepare(mdev->clock); |
|---|
| 651 | + clk_bulk_disable_unprepare(mdev->num_clks, mdev->clks); |
|---|
| 644 | 652 | clock_prepare_failed: |
|---|
| 653 | + clk_bulk_put(mdev->num_clks, mdev->clks); |
|---|
| 645 | 654 | clk_put(mdev->clock); |
|---|
| 646 | 655 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && defined(CONFIG_OF) \ |
|---|
| 647 | 656 | && defined(CONFIG_PM_OPP) |
|---|
| .. | .. |
|---|
| 651 | 660 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) && defined(CONFIG_OF) \ |
|---|
| 652 | 661 | && defined(CONFIG_REGULATOR) |
|---|
| 653 | 662 | regulator_put(mdev->regulator); |
|---|
| 663 | + dev_pm_opp_put_regulators(mdev->opp_table); |
|---|
| 654 | 664 | #endif /* LINUX_VERSION_CODE >= 3, 12, 0 */ |
|---|
| 655 | 665 | mali_device_free(mdev); |
|---|
| 656 | 666 | #endif |
|---|
| .. | .. |
|---|
| 680 | 690 | mali_pm_metrics_term(mdev); |
|---|
| 681 | 691 | |
|---|
| 682 | 692 | if (mdev->clock) { |
|---|
| 683 | | - clk_unprepare(mdev->clock); |
|---|
| 684 | 693 | clk_put(mdev->clock); |
|---|
| 685 | 694 | mdev->clock = NULL; |
|---|
| 686 | 695 | } |
|---|
| 696 | + clk_bulk_unprepare(mdev->num_clks, mdev->clks); |
|---|
| 697 | + clk_bulk_put(mdev->num_clks, mdev->clks); |
|---|
| 698 | + |
|---|
| 687 | 699 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && defined(CONFIG_OF) \ |
|---|
| 688 | 700 | && defined(CONFIG_PM_OPP) |
|---|
| 689 | 701 | dev_pm_opp_of_remove_table(mdev->dev); |
|---|
| .. | .. |
|---|
| 692 | 704 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) && defined(CONFIG_OF) \ |
|---|
| 693 | 705 | && defined(CONFIG_REGULATOR) |
|---|
| 694 | 706 | regulator_put(mdev->regulator); |
|---|
| 707 | + dev_pm_opp_put_regulators(mdev->opp_table); |
|---|
| 695 | 708 | #endif /* LINUX_VERSION_CODE >= 3, 12, 0 */ |
|---|
| 696 | 709 | mali_device_free(mdev); |
|---|
| 697 | 710 | #endif |
|---|
| .. | .. |
|---|
| 733 | 746 | return -ENODEV; |
|---|
| 734 | 747 | #endif |
|---|
| 735 | 748 | |
|---|
| 749 | + pm_runtime_force_suspend(dev); |
|---|
| 736 | 750 | #if defined(CONFIG_MALI_DEVFREQ) && \ |
|---|
| 737 | 751 | (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) |
|---|
| 738 | 752 | devfreq_suspend_device(mdev->devfreq); |
|---|
| .. | .. |
|---|
| 777 | 791 | (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) |
|---|
| 778 | 792 | devfreq_resume_device(mdev->devfreq); |
|---|
| 779 | 793 | #endif |
|---|
| 794 | + pm_runtime_force_resume(dev); |
|---|
| 780 | 795 | |
|---|
| 781 | 796 | return 0; |
|---|
| 782 | 797 | } |
|---|
| .. | .. |
|---|
| 917 | 932 | } |
|---|
| 918 | 933 | } |
|---|
| 919 | 934 | |
|---|
| 920 | | -#ifdef HAVE_UNLOCKED_IOCTL |
|---|
| 921 | 935 | static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
|---|
| 922 | | -#else |
|---|
| 923 | | -static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) |
|---|
| 924 | | -#endif |
|---|
| 925 | 936 | { |
|---|
| 926 | 937 | int err; |
|---|
| 927 | 938 | struct mali_session_data *session_data; |
|---|
| 928 | | - |
|---|
| 929 | | -#ifndef HAVE_UNLOCKED_IOCTL |
|---|
| 930 | | - /* inode not used */ |
|---|
| 931 | | - (void)inode; |
|---|
| 932 | | -#endif |
|---|
| 933 | 939 | |
|---|
| 934 | 940 | MALI_DEBUG_PRINT(7, ("Ioctl received 0x%08X 0x%08lX\n", cmd, arg)); |
|---|
| 935 | 941 | |
|---|