1 // SPDX-License-Identifier: BSD-3-Clause 2 /* 3 * Clock drivers for Qualcomm APQ8096 4 * 5 * (C) Copyright 2017 Jorge Ramirez Ortiz <jorge.ramirez-ortiz@linaro.org> 6 * 7 * Based on Little Kernel driver, simplified 8 */ 9 10 #include <common.h> 11 #include <clk-uclass.h> 12 #include <dm.h> 13 #include <errno.h> 14 #include <asm/io.h> 15 #include <linux/bitops.h> 16 #include "clock-snapdragon.h" 17 18 /* GPLL0 clock control registers */ 19 #define GPLL0_STATUS_ACTIVE BIT(30) 20 #define APCS_GPLL_ENA_VOTE_GPLL0 BIT(0) 21 22 static const struct bcr_regs sdc_regs = { 23 .cfg_rcgr = SDCC2_CFG_RCGR, 24 .cmd_rcgr = SDCC2_CMD_RCGR, 25 .M = SDCC2_M, 26 .N = SDCC2_N, 27 .D = SDCC2_D, 28 }; 29 30 static const struct pll_vote_clk gpll0_vote_clk = { 31 .status = GPLL0_STATUS, 32 .status_bit = GPLL0_STATUS_ACTIVE, 33 .ena_vote = APCS_GPLL_ENA_VOTE, 34 .vote_bit = APCS_GPLL_ENA_VOTE_GPLL0, 35 }; 36 37 static struct vote_clk gcc_blsp2_ahb_clk = { 38 .cbcr_reg = BLSP2_AHB_CBCR, 39 .ena_vote = APCS_CLOCK_BRANCH_ENA_VOTE, 40 .vote_bit = BIT(15), 41 }; 42 43 static int clk_init_sdc(struct msm_clk_priv *priv, uint rate) 44 { 45 int div = 3; 46 47 clk_enable_cbc(priv->base + SDCC2_AHB_CBCR); 48 clk_rcg_set_rate_mnd(priv->base, &sdc_regs, div, 0, 0, 49 CFG_CLK_SRC_GPLL0); 50 clk_enable_gpll0(priv->base, &gpll0_vote_clk); 51 clk_enable_cbc(priv->base + SDCC2_APPS_CBCR); 52 53 return rate; 54 } 55 56 static const struct bcr_regs uart2_regs = { 57 .cfg_rcgr = BLSP2_UART2_APPS_CFG_RCGR, 58 .cmd_rcgr = BLSP2_UART2_APPS_CMD_RCGR, 59 .M = BLSP2_UART2_APPS_M, 60 .N = BLSP2_UART2_APPS_N, 61 .D = BLSP2_UART2_APPS_D, 62 }; 63 64 static int clk_init_uart(struct msm_clk_priv *priv) 65 { 66 /* Enable AHB clock */ 67 clk_enable_vote_clk(priv->base, &gcc_blsp2_ahb_clk); 68 69 /* 7372800 uart block clock @ GPLL0 */ 70 clk_rcg_set_rate_mnd(priv->base, &uart2_regs, 1, 192, 15625, 71 CFG_CLK_SRC_GPLL0); 72 73 /* Vote for gpll0 clock */ 74 clk_enable_gpll0(priv->base, &gpll0_vote_clk); 75 76 /* Enable core clk */ 77 clk_enable_cbc(priv->base + BLSP2_UART2_APPS_CBCR); 78 79 return 0; 80 } 81 82 ulong msm_set_rate(struct clk *clk, ulong rate) 83 { 84 struct msm_clk_priv *priv = dev_get_priv(clk->dev); 85 86 switch (clk->id) { 87 case 0: /* SDC1 */ 88 return clk_init_sdc(priv, rate); 89 break; 90 case 4: /*UART2*/ 91 return clk_init_uart(priv); 92 default: 93 return 0; 94 } 95 } 96