183d290c5STom Rini // SPDX-License-Identifier: BSD-3-Clause
208592136SMateusz Kulikowski /*
308592136SMateusz Kulikowski  * Clock drivers for Qualcomm APQ8016
408592136SMateusz Kulikowski  *
508592136SMateusz Kulikowski  * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
608592136SMateusz Kulikowski  *
708592136SMateusz Kulikowski  * Based on Little Kernel driver, simplified
808592136SMateusz Kulikowski  */
908592136SMateusz Kulikowski 
1008592136SMateusz Kulikowski #include <common.h>
11135aa950SStephen Warren #include <clk-uclass.h>
1208592136SMateusz Kulikowski #include <dm.h>
1308592136SMateusz Kulikowski #include <errno.h>
1408592136SMateusz Kulikowski #include <asm/io.h>
1508592136SMateusz Kulikowski #include <linux/bitops.h>
167c75f7f1SJorge Ramirez-Ortiz #include "clock-snapdragon.h"
1708592136SMateusz Kulikowski 
1808592136SMateusz Kulikowski /* GPLL0 clock control registers */
1908592136SMateusz Kulikowski #define GPLL0_STATUS_ACTIVE BIT(17)
2008592136SMateusz Kulikowski 
2108592136SMateusz Kulikowski static const struct bcr_regs sdc_regs[] = {
2208592136SMateusz Kulikowski 	{
2308592136SMateusz Kulikowski 	.cfg_rcgr = SDCC_CFG_RCGR(1),
2408592136SMateusz Kulikowski 	.cmd_rcgr = SDCC_CMD_RCGR(1),
2508592136SMateusz Kulikowski 	.M = SDCC_M(1),
2608592136SMateusz Kulikowski 	.N = SDCC_N(1),
2708592136SMateusz Kulikowski 	.D = SDCC_D(1),
2808592136SMateusz Kulikowski 	},
2908592136SMateusz Kulikowski 	{
3008592136SMateusz Kulikowski 	.cfg_rcgr = SDCC_CFG_RCGR(2),
3108592136SMateusz Kulikowski 	.cmd_rcgr = SDCC_CMD_RCGR(2),
3208592136SMateusz Kulikowski 	.M = SDCC_M(2),
3308592136SMateusz Kulikowski 	.N = SDCC_N(2),
3408592136SMateusz Kulikowski 	.D = SDCC_D(2),
3508592136SMateusz Kulikowski 	}
3608592136SMateusz Kulikowski };
3708592136SMateusz Kulikowski 
38*640dc349SRamon Fried static struct pll_vote_clk gpll0_vote_clk = {
397c75f7f1SJorge Ramirez-Ortiz 	.status = GPLL0_STATUS,
407c75f7f1SJorge Ramirez-Ortiz 	.status_bit = GPLL0_STATUS_ACTIVE,
417c75f7f1SJorge Ramirez-Ortiz 	.ena_vote = APCS_GPLL_ENA_VOTE,
42*640dc349SRamon Fried 	.vote_bit = BIT(0),
43*640dc349SRamon Fried };
44*640dc349SRamon Fried 
45*640dc349SRamon Fried static struct vote_clk gcc_blsp1_ahb_clk = {
46*640dc349SRamon Fried 	.cbcr_reg = BLSP1_AHB_CBCR,
47*640dc349SRamon Fried 	.ena_vote = APCS_CLOCK_BRANCH_ENA_VOTE,
48*640dc349SRamon Fried 	.vote_bit = BIT(10),
497c75f7f1SJorge Ramirez-Ortiz };
507c75f7f1SJorge Ramirez-Ortiz 
517c75f7f1SJorge Ramirez-Ortiz /* SDHCI */
clk_init_sdc(struct msm_clk_priv * priv,int slot,uint rate)5208592136SMateusz Kulikowski static int clk_init_sdc(struct msm_clk_priv *priv, int slot, uint rate)
5308592136SMateusz Kulikowski {
5408592136SMateusz Kulikowski 	int div = 8; /* 100MHz default */
5508592136SMateusz Kulikowski 
5608592136SMateusz Kulikowski 	if (rate == 200000000)
5708592136SMateusz Kulikowski 		div = 4;
5808592136SMateusz Kulikowski 
5908592136SMateusz Kulikowski 	clk_enable_cbc(priv->base + SDCC_AHB_CBCR(slot));
6008592136SMateusz Kulikowski 	/* 800Mhz/div, gpll0 */
6108592136SMateusz Kulikowski 	clk_rcg_set_rate_mnd(priv->base, &sdc_regs[slot], div, 0, 0,
6208592136SMateusz Kulikowski 			     CFG_CLK_SRC_GPLL0);
63*640dc349SRamon Fried 	clk_enable_gpll0(priv->base, &gpll0_vote_clk);
6408592136SMateusz Kulikowski 	clk_enable_cbc(priv->base + SDCC_APPS_CBCR(slot));
6508592136SMateusz Kulikowski 
6608592136SMateusz Kulikowski 	return rate;
6708592136SMateusz Kulikowski }
6808592136SMateusz Kulikowski 
6908592136SMateusz Kulikowski static const struct bcr_regs uart2_regs = {
7008592136SMateusz Kulikowski 	.cfg_rcgr = BLSP1_UART2_APPS_CFG_RCGR,
7108592136SMateusz Kulikowski 	.cmd_rcgr = BLSP1_UART2_APPS_CMD_RCGR,
7208592136SMateusz Kulikowski 	.M = BLSP1_UART2_APPS_M,
7308592136SMateusz Kulikowski 	.N = BLSP1_UART2_APPS_N,
7408592136SMateusz Kulikowski 	.D = BLSP1_UART2_APPS_D,
7508592136SMateusz Kulikowski };
7608592136SMateusz Kulikowski 
777c75f7f1SJorge Ramirez-Ortiz /* UART: 115200 */
clk_init_uart(struct msm_clk_priv * priv)7808592136SMateusz Kulikowski static int clk_init_uart(struct msm_clk_priv *priv)
7908592136SMateusz Kulikowski {
80*640dc349SRamon Fried 	/* Enable AHB clock */
81*640dc349SRamon Fried 	clk_enable_vote_clk(priv->base, &gcc_blsp1_ahb_clk);
82*640dc349SRamon Fried 
8308592136SMateusz Kulikowski 	/* 7372800 uart block clock @ GPLL0 */
8408592136SMateusz Kulikowski 	clk_rcg_set_rate_mnd(priv->base, &uart2_regs, 1, 144, 15625,
8508592136SMateusz Kulikowski 			     CFG_CLK_SRC_GPLL0);
86*640dc349SRamon Fried 
87*640dc349SRamon Fried 	/* Vote for gpll0 clock */
88*640dc349SRamon Fried 	clk_enable_gpll0(priv->base, &gpll0_vote_clk);
89*640dc349SRamon Fried 
9008592136SMateusz Kulikowski 	/* Enable core clk */
9108592136SMateusz Kulikowski 	clk_enable_cbc(priv->base + BLSP1_UART2_APPS_CBCR);
9208592136SMateusz Kulikowski 
9308592136SMateusz Kulikowski 	return 0;
9408592136SMateusz Kulikowski }
9508592136SMateusz Kulikowski 
msm_set_rate(struct clk * clk,ulong rate)96135aa950SStephen Warren ulong msm_set_rate(struct clk *clk, ulong rate)
9708592136SMateusz Kulikowski {
98135aa950SStephen Warren 	struct msm_clk_priv *priv = dev_get_priv(clk->dev);
9908592136SMateusz Kulikowski 
100135aa950SStephen Warren 	switch (clk->id) {
10108592136SMateusz Kulikowski 	case 0: /* SDC1 */
10208592136SMateusz Kulikowski 		return clk_init_sdc(priv, 0, rate);
10308592136SMateusz Kulikowski 		break;
10408592136SMateusz Kulikowski 	case 1: /* SDC2 */
10508592136SMateusz Kulikowski 		return clk_init_sdc(priv, 1, rate);
10608592136SMateusz Kulikowski 		break;
10708592136SMateusz Kulikowski 	case 4: /* UART2 */
10808592136SMateusz Kulikowski 		return clk_init_uart(priv);
10908592136SMateusz Kulikowski 		break;
11008592136SMateusz Kulikowski 	default:
11108592136SMateusz Kulikowski 		return 0;
11208592136SMateusz Kulikowski 	}
11308592136SMateusz Kulikowski }
114