1c5e7fca9SKai Chieh Chuang /* 2c5e7fca9SKai Chieh Chuang * mt6797-afe-clk.c -- Mediatek 6797 afe clock ctrl 3c5e7fca9SKai Chieh Chuang * 4c5e7fca9SKai Chieh Chuang * Copyright (c) 2018 MediaTek Inc. 5c5e7fca9SKai Chieh Chuang * Author: KaiChieh Chuang <kaichieh.chuang@mediatek.com> 6c5e7fca9SKai Chieh Chuang * 7c5e7fca9SKai Chieh Chuang * This program is free software; you can redistribute it and/or modify 8c5e7fca9SKai Chieh Chuang * it under the terms of the GNU General Public License version 2 and 9c5e7fca9SKai Chieh Chuang * only version 2 as published by the Free Software Foundation. 10c5e7fca9SKai Chieh Chuang * 11c5e7fca9SKai Chieh Chuang * This program is distributed in the hope that it will be useful, 12c5e7fca9SKai Chieh Chuang * but WITHOUT ANY WARRANTY; without even the implied warranty of 13c5e7fca9SKai Chieh Chuang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14c5e7fca9SKai Chieh Chuang * GNU General Public License for more details. 15c5e7fca9SKai Chieh Chuang */ 16c5e7fca9SKai Chieh Chuang 17c5e7fca9SKai Chieh Chuang #include <linux/clk.h> 18c5e7fca9SKai Chieh Chuang 19c5e7fca9SKai Chieh Chuang #include "mt6797-afe-common.h" 20c5e7fca9SKai Chieh Chuang #include "mt6797-afe-clk.h" 21c5e7fca9SKai Chieh Chuang 22c5e7fca9SKai Chieh Chuang enum { 23c5e7fca9SKai Chieh Chuang CLK_INFRA_SYS_AUD, 24c5e7fca9SKai Chieh Chuang CLK_INFRA_SYS_AUD_26M, 25c5e7fca9SKai Chieh Chuang CLK_TOP_MUX_AUD, 26c5e7fca9SKai Chieh Chuang CLK_TOP_MUX_AUD_BUS, 27c5e7fca9SKai Chieh Chuang CLK_TOP_SYSPLL3_D4, 28c5e7fca9SKai Chieh Chuang CLK_TOP_SYSPLL1_D4, 29c5e7fca9SKai Chieh Chuang CLK_CLK26M, 30c5e7fca9SKai Chieh Chuang CLK_NUM 31c5e7fca9SKai Chieh Chuang }; 32c5e7fca9SKai Chieh Chuang 33c5e7fca9SKai Chieh Chuang static const char *aud_clks[CLK_NUM] = { 34c5e7fca9SKai Chieh Chuang [CLK_INFRA_SYS_AUD] = "infra_sys_audio_clk", 35c5e7fca9SKai Chieh Chuang [CLK_INFRA_SYS_AUD_26M] = "infra_sys_audio_26m", 36c5e7fca9SKai Chieh Chuang [CLK_TOP_MUX_AUD] = "top_mux_audio", 37c5e7fca9SKai Chieh Chuang [CLK_TOP_MUX_AUD_BUS] = "top_mux_aud_intbus", 38c5e7fca9SKai Chieh Chuang [CLK_TOP_SYSPLL3_D4] = "top_sys_pll3_d4", 39c5e7fca9SKai Chieh Chuang [CLK_TOP_SYSPLL1_D4] = "top_sys_pll1_d4", 40c5e7fca9SKai Chieh Chuang [CLK_CLK26M] = "top_clk26m_clk", 41c5e7fca9SKai Chieh Chuang }; 42c5e7fca9SKai Chieh Chuang 43c5e7fca9SKai Chieh Chuang int mt6797_init_clock(struct mtk_base_afe *afe) 44c5e7fca9SKai Chieh Chuang { 45c5e7fca9SKai Chieh Chuang struct mt6797_afe_private *afe_priv = afe->platform_priv; 46c5e7fca9SKai Chieh Chuang int i; 47c5e7fca9SKai Chieh Chuang 48c5e7fca9SKai Chieh Chuang afe_priv->clk = devm_kcalloc(afe->dev, CLK_NUM, sizeof(*afe_priv->clk), 49c5e7fca9SKai Chieh Chuang GFP_KERNEL); 50c5e7fca9SKai Chieh Chuang if (!afe_priv->clk) 51c5e7fca9SKai Chieh Chuang return -ENOMEM; 52c5e7fca9SKai Chieh Chuang 53c5e7fca9SKai Chieh Chuang for (i = 0; i < CLK_NUM; i++) { 54c5e7fca9SKai Chieh Chuang afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]); 55c5e7fca9SKai Chieh Chuang if (IS_ERR(afe_priv->clk[i])) { 56c5e7fca9SKai Chieh Chuang dev_err(afe->dev, "%s(), devm_clk_get %s fail, ret %ld\n", 57c5e7fca9SKai Chieh Chuang __func__, aud_clks[i], 58c5e7fca9SKai Chieh Chuang PTR_ERR(afe_priv->clk[i])); 59c5e7fca9SKai Chieh Chuang return PTR_ERR(afe_priv->clk[i]); 60c5e7fca9SKai Chieh Chuang } 61c5e7fca9SKai Chieh Chuang } 62c5e7fca9SKai Chieh Chuang 63c5e7fca9SKai Chieh Chuang return 0; 64c5e7fca9SKai Chieh Chuang } 65c5e7fca9SKai Chieh Chuang 66c5e7fca9SKai Chieh Chuang int mt6797_afe_enable_clock(struct mtk_base_afe *afe) 67c5e7fca9SKai Chieh Chuang { 68c5e7fca9SKai Chieh Chuang struct mt6797_afe_private *afe_priv = afe->platform_priv; 69c5e7fca9SKai Chieh Chuang int ret; 70c5e7fca9SKai Chieh Chuang 71c5e7fca9SKai Chieh Chuang ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_SYS_AUD]); 72c5e7fca9SKai Chieh Chuang if (ret) { 73c5e7fca9SKai Chieh Chuang dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n", 74c5e7fca9SKai Chieh Chuang __func__, aud_clks[CLK_INFRA_SYS_AUD], ret); 75c5e7fca9SKai Chieh Chuang goto CLK_INFRA_SYS_AUDIO_ERR; 76c5e7fca9SKai Chieh Chuang } 77c5e7fca9SKai Chieh Chuang 78c5e7fca9SKai Chieh Chuang ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_SYS_AUD_26M]); 79c5e7fca9SKai Chieh Chuang if (ret) { 80c5e7fca9SKai Chieh Chuang dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n", 81c5e7fca9SKai Chieh Chuang __func__, aud_clks[CLK_INFRA_SYS_AUD_26M], ret); 82c5e7fca9SKai Chieh Chuang goto CLK_INFRA_SYS_AUD_26M_ERR; 83c5e7fca9SKai Chieh Chuang } 84c5e7fca9SKai Chieh Chuang 85c5e7fca9SKai Chieh Chuang ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD]); 86c5e7fca9SKai Chieh Chuang if (ret) { 87c5e7fca9SKai Chieh Chuang dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n", 88c5e7fca9SKai Chieh Chuang __func__, aud_clks[CLK_TOP_MUX_AUD], ret); 89c5e7fca9SKai Chieh Chuang goto CLK_MUX_AUDIO_ERR; 90c5e7fca9SKai Chieh Chuang } 91c5e7fca9SKai Chieh Chuang 92c5e7fca9SKai Chieh Chuang ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD], 93c5e7fca9SKai Chieh Chuang afe_priv->clk[CLK_CLK26M]); 94c5e7fca9SKai Chieh Chuang if (ret) { 95c5e7fca9SKai Chieh Chuang dev_err(afe->dev, "%s(), clk_set_parent %s-%s fail %d\n", 96c5e7fca9SKai Chieh Chuang __func__, aud_clks[CLK_TOP_MUX_AUD], 97c5e7fca9SKai Chieh Chuang aud_clks[CLK_CLK26M], ret); 98c5e7fca9SKai Chieh Chuang goto CLK_MUX_AUDIO_ERR; 99c5e7fca9SKai Chieh Chuang } 100c5e7fca9SKai Chieh Chuang 101c5e7fca9SKai Chieh Chuang ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_BUS]); 102c5e7fca9SKai Chieh Chuang if (ret) { 103c5e7fca9SKai Chieh Chuang dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n", 104c5e7fca9SKai Chieh Chuang __func__, aud_clks[CLK_TOP_MUX_AUD_BUS], ret); 105c5e7fca9SKai Chieh Chuang goto CLK_MUX_AUDIO_INTBUS_ERR; 106c5e7fca9SKai Chieh Chuang } 107c5e7fca9SKai Chieh Chuang 108c5e7fca9SKai Chieh Chuang return ret; 109c5e7fca9SKai Chieh Chuang 110c5e7fca9SKai Chieh Chuang CLK_MUX_AUDIO_INTBUS_ERR: 111c5e7fca9SKai Chieh Chuang clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_BUS]); 112c5e7fca9SKai Chieh Chuang CLK_MUX_AUDIO_ERR: 113c5e7fca9SKai Chieh Chuang clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD]); 114c5e7fca9SKai Chieh Chuang CLK_INFRA_SYS_AUD_26M_ERR: 115c5e7fca9SKai Chieh Chuang clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUD_26M]); 116c5e7fca9SKai Chieh Chuang CLK_INFRA_SYS_AUDIO_ERR: 117c5e7fca9SKai Chieh Chuang clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUD]); 118c5e7fca9SKai Chieh Chuang 119c5e7fca9SKai Chieh Chuang return 0; 120c5e7fca9SKai Chieh Chuang } 121c5e7fca9SKai Chieh Chuang 122c5e7fca9SKai Chieh Chuang int mt6797_afe_disable_clock(struct mtk_base_afe *afe) 123c5e7fca9SKai Chieh Chuang { 124c5e7fca9SKai Chieh Chuang struct mt6797_afe_private *afe_priv = afe->platform_priv; 125c5e7fca9SKai Chieh Chuang 126c5e7fca9SKai Chieh Chuang clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_BUS]); 127c5e7fca9SKai Chieh Chuang clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD]); 128c5e7fca9SKai Chieh Chuang clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUD_26M]); 129c5e7fca9SKai Chieh Chuang clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUD]); 130c5e7fca9SKai Chieh Chuang 131c5e7fca9SKai Chieh Chuang return 0; 132c5e7fca9SKai Chieh Chuang } 133