diff options
Diffstat (limited to 'drivers/clk/clk.c')
-rw-r--r-- | drivers/clk/clk.c | 222 |
1 files changed, 218 insertions, 4 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index fb74dc1f7520..d584004f7af7 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
@@ -574,6 +574,9 @@ static void clk_core_unprepare(struct clk_core *core) | |||
574 | if (WARN_ON(core->prepare_count == 0)) | 574 | if (WARN_ON(core->prepare_count == 0)) |
575 | return; | 575 | return; |
576 | 576 | ||
577 | if (WARN_ON(core->prepare_count == 1 && core->flags & CLK_IS_CRITICAL)) | ||
578 | return; | ||
579 | |||
577 | if (--core->prepare_count > 0) | 580 | if (--core->prepare_count > 0) |
578 | return; | 581 | return; |
579 | 582 | ||
@@ -679,6 +682,9 @@ static void clk_core_disable(struct clk_core *core) | |||
679 | if (WARN_ON(core->enable_count == 0)) | 682 | if (WARN_ON(core->enable_count == 0)) |
680 | return; | 683 | return; |
681 | 684 | ||
685 | if (WARN_ON(core->enable_count == 1 && core->flags & CLK_IS_CRITICAL)) | ||
686 | return; | ||
687 | |||
682 | if (--core->enable_count > 0) | 688 | if (--core->enable_count > 0) |
683 | return; | 689 | return; |
684 | 690 | ||
@@ -2397,6 +2403,16 @@ static int __clk_core_init(struct clk_core *core) | |||
2397 | if (core->ops->init) | 2403 | if (core->ops->init) |
2398 | core->ops->init(core->hw); | 2404 | core->ops->init(core->hw); |
2399 | 2405 | ||
2406 | if (core->flags & CLK_IS_CRITICAL) { | ||
2407 | unsigned long flags; | ||
2408 | |||
2409 | clk_core_prepare(core); | ||
2410 | |||
2411 | flags = clk_enable_lock(); | ||
2412 | clk_core_enable(core); | ||
2413 | clk_enable_unlock(flags); | ||
2414 | } | ||
2415 | |||
2400 | kref_init(&core->ref); | 2416 | kref_init(&core->ref); |
2401 | out: | 2417 | out: |
2402 | clk_prepare_unlock(); | 2418 | clk_prepare_unlock(); |
@@ -2536,6 +2552,22 @@ fail_out: | |||
2536 | } | 2552 | } |
2537 | EXPORT_SYMBOL_GPL(clk_register); | 2553 | EXPORT_SYMBOL_GPL(clk_register); |
2538 | 2554 | ||
2555 | /** | ||
2556 | * clk_hw_register - register a clk_hw and return an error code | ||
2557 | * @dev: device that is registering this clock | ||
2558 | * @hw: link to hardware-specific clock data | ||
2559 | * | ||
2560 | * clk_hw_register is the primary interface for populating the clock tree with | ||
2561 | * new clock nodes. It returns an integer equal to zero indicating success or | ||
2562 | * less than zero indicating failure. Drivers must test for an error code after | ||
2563 | * calling clk_hw_register(). | ||
2564 | */ | ||
2565 | int clk_hw_register(struct device *dev, struct clk_hw *hw) | ||
2566 | { | ||
2567 | return PTR_ERR_OR_ZERO(clk_register(dev, hw)); | ||
2568 | } | ||
2569 | EXPORT_SYMBOL_GPL(clk_hw_register); | ||
2570 | |||
2539 | /* Free memory allocated for a clock. */ | 2571 | /* Free memory allocated for a clock. */ |
2540 | static void __clk_release(struct kref *ref) | 2572 | static void __clk_release(struct kref *ref) |
2541 | { | 2573 | { |
@@ -2637,11 +2669,26 @@ unlock: | |||
2637 | } | 2669 | } |
2638 | EXPORT_SYMBOL_GPL(clk_unregister); | 2670 | EXPORT_SYMBOL_GPL(clk_unregister); |
2639 | 2671 | ||
2672 | /** | ||
2673 | * clk_hw_unregister - unregister a currently registered clk_hw | ||
2674 | * @hw: hardware-specific clock data to unregister | ||
2675 | */ | ||
2676 | void clk_hw_unregister(struct clk_hw *hw) | ||
2677 | { | ||
2678 | clk_unregister(hw->clk); | ||
2679 | } | ||
2680 | EXPORT_SYMBOL_GPL(clk_hw_unregister); | ||
2681 | |||
2640 | static void devm_clk_release(struct device *dev, void *res) | 2682 | static void devm_clk_release(struct device *dev, void *res) |
2641 | { | 2683 | { |
2642 | clk_unregister(*(struct clk **)res); | 2684 | clk_unregister(*(struct clk **)res); |
2643 | } | 2685 | } |
2644 | 2686 | ||
2687 | static void devm_clk_hw_release(struct device *dev, void *res) | ||
2688 | { | ||
2689 | clk_hw_unregister(*(struct clk_hw **)res); | ||
2690 | } | ||
2691 | |||
2645 | /** | 2692 | /** |
2646 | * devm_clk_register - resource managed clk_register() | 2693 | * devm_clk_register - resource managed clk_register() |
2647 | * @dev: device that is registering this clock | 2694 | * @dev: device that is registering this clock |
@@ -2672,6 +2719,36 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw) | |||
2672 | } | 2719 | } |
2673 | EXPORT_SYMBOL_GPL(devm_clk_register); | 2720 | EXPORT_SYMBOL_GPL(devm_clk_register); |
2674 | 2721 | ||
2722 | /** | ||
2723 | * devm_clk_hw_register - resource managed clk_hw_register() | ||
2724 | * @dev: device that is registering this clock | ||
2725 | * @hw: link to hardware-specific clock data | ||
2726 | * | ||
2727 | * Managed clk_hw_register(). Clocks registered by this function are | ||
2728 | * automatically clk_hw_unregister()ed on driver detach. See clk_hw_register() | ||
2729 | * for more information. | ||
2730 | */ | ||
2731 | int devm_clk_hw_register(struct device *dev, struct clk_hw *hw) | ||
2732 | { | ||
2733 | struct clk_hw **hwp; | ||
2734 | int ret; | ||
2735 | |||
2736 | hwp = devres_alloc(devm_clk_hw_release, sizeof(*hwp), GFP_KERNEL); | ||
2737 | if (!hwp) | ||
2738 | return -ENOMEM; | ||
2739 | |||
2740 | ret = clk_hw_register(dev, hw); | ||
2741 | if (!ret) { | ||
2742 | *hwp = hw; | ||
2743 | devres_add(dev, hwp); | ||
2744 | } else { | ||
2745 | devres_free(hwp); | ||
2746 | } | ||
2747 | |||
2748 | return ret; | ||
2749 | } | ||
2750 | EXPORT_SYMBOL_GPL(devm_clk_hw_register); | ||
2751 | |||
2675 | static int devm_clk_match(struct device *dev, void *res, void *data) | 2752 | static int devm_clk_match(struct device *dev, void *res, void *data) |
2676 | { | 2753 | { |
2677 | struct clk *c = res; | 2754 | struct clk *c = res; |
@@ -2680,6 +2757,15 @@ static int devm_clk_match(struct device *dev, void *res, void *data) | |||
2680 | return c == data; | 2757 | return c == data; |
2681 | } | 2758 | } |
2682 | 2759 | ||
2760 | static int devm_clk_hw_match(struct device *dev, void *res, void *data) | ||
2761 | { | ||
2762 | struct clk_hw *hw = res; | ||
2763 | |||
2764 | if (WARN_ON(!hw)) | ||
2765 | return 0; | ||
2766 | return hw == data; | ||
2767 | } | ||
2768 | |||
2683 | /** | 2769 | /** |
2684 | * devm_clk_unregister - resource managed clk_unregister() | 2770 | * devm_clk_unregister - resource managed clk_unregister() |
2685 | * @clk: clock to unregister | 2771 | * @clk: clock to unregister |
@@ -2694,6 +2780,22 @@ void devm_clk_unregister(struct device *dev, struct clk *clk) | |||
2694 | } | 2780 | } |
2695 | EXPORT_SYMBOL_GPL(devm_clk_unregister); | 2781 | EXPORT_SYMBOL_GPL(devm_clk_unregister); |
2696 | 2782 | ||
2783 | /** | ||
2784 | * devm_clk_hw_unregister - resource managed clk_hw_unregister() | ||
2785 | * @dev: device that is unregistering the hardware-specific clock data | ||
2786 | * @hw: link to hardware-specific clock data | ||
2787 | * | ||
2788 | * Unregister a clk_hw registered with devm_clk_hw_register(). Normally | ||
2789 | * this function will not need to be called and the resource management | ||
2790 | * code will ensure that the resource is freed. | ||
2791 | */ | ||
2792 | void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw) | ||
2793 | { | ||
2794 | WARN_ON(devres_release(dev, devm_clk_hw_release, devm_clk_hw_match, | ||
2795 | hw)); | ||
2796 | } | ||
2797 | EXPORT_SYMBOL_GPL(devm_clk_hw_unregister); | ||
2798 | |||
2697 | /* | 2799 | /* |
2698 | * clkdev helpers | 2800 | * clkdev helpers |
2699 | */ | 2801 | */ |
@@ -2855,6 +2957,7 @@ struct of_clk_provider { | |||
2855 | 2957 | ||
2856 | struct device_node *node; | 2958 | struct device_node *node; |
2857 | struct clk *(*get)(struct of_phandle_args *clkspec, void *data); | 2959 | struct clk *(*get)(struct of_phandle_args *clkspec, void *data); |
2960 | struct clk_hw *(*get_hw)(struct of_phandle_args *clkspec, void *data); | ||
2858 | void *data; | 2961 | void *data; |
2859 | }; | 2962 | }; |
2860 | 2963 | ||
@@ -2871,6 +2974,12 @@ struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, | |||
2871 | } | 2974 | } |
2872 | EXPORT_SYMBOL_GPL(of_clk_src_simple_get); | 2975 | EXPORT_SYMBOL_GPL(of_clk_src_simple_get); |
2873 | 2976 | ||
2977 | struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data) | ||
2978 | { | ||
2979 | return data; | ||
2980 | } | ||
2981 | EXPORT_SYMBOL_GPL(of_clk_hw_simple_get); | ||
2982 | |||
2874 | struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data) | 2983 | struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data) |
2875 | { | 2984 | { |
2876 | struct clk_onecell_data *clk_data = data; | 2985 | struct clk_onecell_data *clk_data = data; |
@@ -2885,6 +2994,21 @@ struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data) | |||
2885 | } | 2994 | } |
2886 | EXPORT_SYMBOL_GPL(of_clk_src_onecell_get); | 2995 | EXPORT_SYMBOL_GPL(of_clk_src_onecell_get); |
2887 | 2996 | ||
2997 | struct clk_hw * | ||
2998 | of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data) | ||
2999 | { | ||
3000 | struct clk_hw_onecell_data *hw_data = data; | ||
3001 | unsigned int idx = clkspec->args[0]; | ||
3002 | |||
3003 | if (idx >= hw_data->num) { | ||
3004 | pr_err("%s: invalid index %u\n", __func__, idx); | ||
3005 | return ERR_PTR(-EINVAL); | ||
3006 | } | ||
3007 | |||
3008 | return hw_data->hws[idx]; | ||
3009 | } | ||
3010 | EXPORT_SYMBOL_GPL(of_clk_hw_onecell_get); | ||
3011 | |||
2888 | /** | 3012 | /** |
2889 | * of_clk_add_provider() - Register a clock provider for a node | 3013 | * of_clk_add_provider() - Register a clock provider for a node |
2890 | * @np: Device node pointer associated with clock provider | 3014 | * @np: Device node pointer associated with clock provider |
@@ -2921,6 +3045,41 @@ int of_clk_add_provider(struct device_node *np, | |||
2921 | EXPORT_SYMBOL_GPL(of_clk_add_provider); | 3045 | EXPORT_SYMBOL_GPL(of_clk_add_provider); |
2922 | 3046 | ||
2923 | /** | 3047 | /** |
3048 | * of_clk_add_hw_provider() - Register a clock provider for a node | ||
3049 | * @np: Device node pointer associated with clock provider | ||
3050 | * @get: callback for decoding clk_hw | ||
3051 | * @data: context pointer for @get callback. | ||
3052 | */ | ||
3053 | int of_clk_add_hw_provider(struct device_node *np, | ||
3054 | struct clk_hw *(*get)(struct of_phandle_args *clkspec, | ||
3055 | void *data), | ||
3056 | void *data) | ||
3057 | { | ||
3058 | struct of_clk_provider *cp; | ||
3059 | int ret; | ||
3060 | |||
3061 | cp = kzalloc(sizeof(*cp), GFP_KERNEL); | ||
3062 | if (!cp) | ||
3063 | return -ENOMEM; | ||
3064 | |||
3065 | cp->node = of_node_get(np); | ||
3066 | cp->data = data; | ||
3067 | cp->get_hw = get; | ||
3068 | |||
3069 | mutex_lock(&of_clk_mutex); | ||
3070 | list_add(&cp->link, &of_clk_providers); | ||
3071 | mutex_unlock(&of_clk_mutex); | ||
3072 | pr_debug("Added clk_hw provider from %s\n", np->full_name); | ||
3073 | |||
3074 | ret = of_clk_set_defaults(np, true); | ||
3075 | if (ret < 0) | ||
3076 | of_clk_del_provider(np); | ||
3077 | |||
3078 | return ret; | ||
3079 | } | ||
3080 | EXPORT_SYMBOL_GPL(of_clk_add_hw_provider); | ||
3081 | |||
3082 | /** | ||
2924 | * of_clk_del_provider() - Remove a previously registered clock provider | 3083 | * of_clk_del_provider() - Remove a previously registered clock provider |
2925 | * @np: Device node pointer associated with clock provider | 3084 | * @np: Device node pointer associated with clock provider |
2926 | */ | 3085 | */ |
@@ -2941,11 +3100,32 @@ void of_clk_del_provider(struct device_node *np) | |||
2941 | } | 3100 | } |
2942 | EXPORT_SYMBOL_GPL(of_clk_del_provider); | 3101 | EXPORT_SYMBOL_GPL(of_clk_del_provider); |
2943 | 3102 | ||
3103 | static struct clk_hw * | ||
3104 | __of_clk_get_hw_from_provider(struct of_clk_provider *provider, | ||
3105 | struct of_phandle_args *clkspec) | ||
3106 | { | ||
3107 | struct clk *clk; | ||
3108 | struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); | ||
3109 | |||
3110 | if (provider->get_hw) { | ||
3111 | hw = provider->get_hw(clkspec, provider->data); | ||
3112 | } else if (provider->get) { | ||
3113 | clk = provider->get(clkspec, provider->data); | ||
3114 | if (!IS_ERR(clk)) | ||
3115 | hw = __clk_get_hw(clk); | ||
3116 | else | ||
3117 | hw = ERR_CAST(clk); | ||
3118 | } | ||
3119 | |||
3120 | return hw; | ||
3121 | } | ||
3122 | |||
2944 | struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, | 3123 | struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, |
2945 | const char *dev_id, const char *con_id) | 3124 | const char *dev_id, const char *con_id) |
2946 | { | 3125 | { |
2947 | struct of_clk_provider *provider; | 3126 | struct of_clk_provider *provider; |
2948 | struct clk *clk = ERR_PTR(-EPROBE_DEFER); | 3127 | struct clk *clk = ERR_PTR(-EPROBE_DEFER); |
3128 | struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); | ||
2949 | 3129 | ||
2950 | if (!clkspec) | 3130 | if (!clkspec) |
2951 | return ERR_PTR(-EINVAL); | 3131 | return ERR_PTR(-EINVAL); |
@@ -2954,10 +3134,9 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, | |||
2954 | mutex_lock(&of_clk_mutex); | 3134 | mutex_lock(&of_clk_mutex); |
2955 | list_for_each_entry(provider, &of_clk_providers, link) { | 3135 | list_for_each_entry(provider, &of_clk_providers, link) { |
2956 | if (provider->node == clkspec->np) | 3136 | if (provider->node == clkspec->np) |
2957 | clk = provider->get(clkspec, provider->data); | 3137 | hw = __of_clk_get_hw_from_provider(provider, clkspec); |
2958 | if (!IS_ERR(clk)) { | 3138 | if (!IS_ERR(hw)) { |
2959 | clk = __clk_create_clk(__clk_get_hw(clk), dev_id, | 3139 | clk = __clk_create_clk(hw, dev_id, con_id); |
2960 | con_id); | ||
2961 | 3140 | ||
2962 | if (!IS_ERR(clk) && !__clk_get(clk)) { | 3141 | if (!IS_ERR(clk) && !__clk_get(clk)) { |
2963 | __clk_free_clk(clk); | 3142 | __clk_free_clk(clk); |
@@ -3127,6 +3306,41 @@ static int parent_ready(struct device_node *np) | |||
3127 | } | 3306 | } |
3128 | 3307 | ||
3129 | /** | 3308 | /** |
3309 | * of_clk_detect_critical() - set CLK_IS_CRITICAL flag from Device Tree | ||
3310 | * @np: Device node pointer associated with clock provider | ||
3311 | * @index: clock index | ||
3312 | * @flags: pointer to clk_core->flags | ||
3313 | * | ||
3314 | * Detects if the clock-critical property exists and, if so, sets the | ||
3315 | * corresponding CLK_IS_CRITICAL flag. | ||
3316 | * | ||
3317 | * Do not use this function. It exists only for legacy Device Tree | ||
3318 | * bindings, such as the one-clock-per-node style that are outdated. | ||
3319 | * Those bindings typically put all clock data into .dts and the Linux | ||
3320 | * driver has no clock data, thus making it impossible to set this flag | ||
3321 | * correctly from the driver. Only those drivers may call | ||
3322 | * of_clk_detect_critical from their setup functions. | ||
3323 | * | ||
3324 | * Return: error code or zero on success | ||
3325 | */ | ||
3326 | int of_clk_detect_critical(struct device_node *np, | ||
3327 | int index, unsigned long *flags) | ||
3328 | { | ||
3329 | struct property *prop; | ||
3330 | const __be32 *cur; | ||
3331 | uint32_t idx; | ||
3332 | |||
3333 | if (!np || !flags) | ||
3334 | return -EINVAL; | ||
3335 | |||
3336 | of_property_for_each_u32(np, "clock-critical", prop, cur, idx) | ||
3337 | if (index == idx) | ||
3338 | *flags |= CLK_IS_CRITICAL; | ||
3339 | |||
3340 | return 0; | ||
3341 | } | ||
3342 | |||
3343 | /** | ||
3130 | * of_clk_init() - Scan and init clock providers from the DT | 3344 | * of_clk_init() - Scan and init clock providers from the DT |
3131 | * @matches: array of compatible values and init functions for providers. | 3345 | * @matches: array of compatible values and init functions for providers. |
3132 | * | 3346 | * |