// SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2012-2015, 2017-2018, The Linux Foundation. * All rights reserved. */ #include #include #include #include #include #include #include "dp_clk_util.h" void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk) { int i; for (i = num_clk - 1; i >= 0; i--) { if (clk_arry[i].clk) clk_put(clk_arry[i].clk); clk_arry[i].clk = NULL; } } int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk) { int i, rc = 0; for (i = 0; i < num_clk; i++) { clk_arry[i].clk = clk_get(dev, clk_arry[i].clk_name); rc = PTR_ERR_OR_ZERO(clk_arry[i].clk); if (rc) { DEV_ERR("%pS->%s: '%s' get failed. rc=%d\n", __builtin_return_address(0), __func__, clk_arry[i].clk_name, rc); goto error; } } return rc; error: for (i--; i >= 0; i--) { if (clk_arry[i].clk) clk_put(clk_arry[i].clk); clk_arry[i].clk = NULL; } return rc; } int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk) { int i, rc = 0; for (i = 0; i < num_clk; i++) { if (clk_arry[i].clk) { if (clk_arry[i].type != DSS_CLK_AHB) { DEV_DBG("%pS->%s: '%s' rate %ld\n", __builtin_return_address(0), __func__, clk_arry[i].clk_name, clk_arry[i].rate); rc = clk_set_rate(clk_arry[i].clk, clk_arry[i].rate); if (rc) { DEV_ERR("%pS->%s: %s failed. rc=%d\n", __builtin_return_address(0), __func__, clk_arry[i].clk_name, rc); break; } } } else { DEV_ERR("%pS->%s: '%s' is not available\n", __builtin_return_address(0), __func__, clk_arry[i].clk_name); rc = -EPERM; break; } } return rc; } int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable) { int i, rc = 0; if (enable) { for (i = 0; i < num_clk; i++) { DEV_DBG("%pS->%s: enable '%s'\n", __builtin_return_address(0), __func__, clk_arry[i].clk_name); rc = clk_prepare_enable(clk_arry[i].clk); if (rc) DEV_ERR("%pS->%s: %s en fail. rc=%d\n", __builtin_return_address(0), __func__, clk_arry[i].clk_name, rc); if (rc && i) { msm_dss_enable_clk(&clk_arry[i - 1], i - 1, false); break; } } } else { for (i = num_clk - 1; i >= 0; i--) { DEV_DBG("%pS->%s: disable '%s'\n", __builtin_return_address(0), __func__, clk_arry[i].clk_name); clk_disable_unprepare(clk_arry[i].clk); } } return rc; }