blob: 0af7191cff52175681ad7aee3a6c5aa208ee6f5b [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: BSD-3-Clause
Mateusz Kulikowski2507d822016-03-31 23:12:32 +02002/*
3 * Clock drivers for Qualcomm APQ8016
4 *
5 * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
6 *
7 * Based on Little Kernel driver, simplified
Mateusz Kulikowski2507d822016-03-31 23:12:32 +02008 */
9
10#include <common.h>
Stephen Warrena9622432016-06-17 09:44:00 -060011#include <clk-uclass.h>
Mateusz Kulikowski2507d822016-03-31 23:12:32 +020012#include <dm.h>
13#include <errno.h>
14#include <asm/io.h>
15#include <linux/bitops.h>
Konrad Dybcio6c0b8442023-11-07 12:41:01 +000016
Caleb Connolly878b26a2023-11-07 12:40:59 +000017#include "clock-qcom.h"
Mateusz Kulikowski2507d822016-03-31 23:12:32 +020018
Caleb Connolly10a0abb2023-11-07 12:41:03 +000019/* Clocks: (from CLK_CTL_BASE) */
20#define GPLL0_STATUS (0x2101C)
21#define APCS_GPLL_ENA_VOTE (0x45000)
22#define APCS_CLOCK_BRANCH_ENA_VOTE (0x45004)
23
24#define SDCC_BCR(n) ((n * 0x1000) + 0x41000)
25#define SDCC_CMD_RCGR(n) ((n * 0x1000) + 0x41004)
26#define SDCC_CFG_RCGR(n) ((n * 0x1000) + 0x41008)
27#define SDCC_M(n) ((n * 0x1000) + 0x4100C)
28#define SDCC_N(n) ((n * 0x1000) + 0x41010)
29#define SDCC_D(n) ((n * 0x1000) + 0x41014)
30#define SDCC_APPS_CBCR(n) ((n * 0x1000) + 0x41018)
31#define SDCC_AHB_CBCR(n) ((n * 0x1000) + 0x4101C)
32
33/* BLSP1 AHB clock (root clock for BLSP) */
34#define BLSP1_AHB_CBCR 0x1008
35
36/* Uart clock control registers */
37#define BLSP1_UART2_BCR (0x3028)
38#define BLSP1_UART2_APPS_CBCR (0x302C)
39#define BLSP1_UART2_APPS_CMD_RCGR (0x3034)
40#define BLSP1_UART2_APPS_CFG_RCGR (0x3038)
41#define BLSP1_UART2_APPS_M (0x303C)
42#define BLSP1_UART2_APPS_N (0x3040)
43#define BLSP1_UART2_APPS_D (0x3044)
44
Mateusz Kulikowski2507d822016-03-31 23:12:32 +020045/* GPLL0 clock control registers */
Mateusz Kulikowski2507d822016-03-31 23:12:32 +020046#define GPLL0_STATUS_ACTIVE BIT(17)
Mateusz Kulikowski2507d822016-03-31 23:12:32 +020047
Mateusz Kulikowski2507d822016-03-31 23:12:32 +020048static const struct bcr_regs sdc_regs[] = {
49 {
50 .cfg_rcgr = SDCC_CFG_RCGR(1),
51 .cmd_rcgr = SDCC_CMD_RCGR(1),
52 .M = SDCC_M(1),
53 .N = SDCC_N(1),
54 .D = SDCC_D(1),
55 },
56 {
57 .cfg_rcgr = SDCC_CFG_RCGR(2),
58 .cmd_rcgr = SDCC_CMD_RCGR(2),
59 .M = SDCC_M(2),
60 .N = SDCC_N(2),
61 .D = SDCC_D(2),
62 }
63};
64
Ramon Friedae299772018-05-16 12:13:39 +030065static struct pll_vote_clk gpll0_vote_clk = {
Jorge Ramirez-Ortiz92c1eff2018-01-10 11:33:49 +010066 .status = GPLL0_STATUS,
67 .status_bit = GPLL0_STATUS_ACTIVE,
68 .ena_vote = APCS_GPLL_ENA_VOTE,
Ramon Friedae299772018-05-16 12:13:39 +030069 .vote_bit = BIT(0),
Jorge Ramirez-Ortiz92c1eff2018-01-10 11:33:49 +010070};
71
Ramon Friedae299772018-05-16 12:13:39 +030072static struct vote_clk gcc_blsp1_ahb_clk = {
73 .cbcr_reg = BLSP1_AHB_CBCR,
74 .ena_vote = APCS_CLOCK_BRANCH_ENA_VOTE,
75 .vote_bit = BIT(10),
76};
77
Jorge Ramirez-Ortiz92c1eff2018-01-10 11:33:49 +010078/* SDHCI */
Mateusz Kulikowski2507d822016-03-31 23:12:32 +020079static int clk_init_sdc(struct msm_clk_priv *priv, int slot, uint rate)
80{
Caleb Connolly397c84f2023-11-07 12:41:05 +000081 int div = 15; /* 100MHz default */
Mateusz Kulikowski2507d822016-03-31 23:12:32 +020082
83 if (rate == 200000000)
84 div = 4;
85
86 clk_enable_cbc(priv->base + SDCC_AHB_CBCR(slot));
87 /* 800Mhz/div, gpll0 */
88 clk_rcg_set_rate_mnd(priv->base, &sdc_regs[slot], div, 0, 0,
Caleb Connollyfbacc672023-11-07 12:41:04 +000089 CFG_CLK_SRC_GPLL0, 8);
Ramon Friedae299772018-05-16 12:13:39 +030090 clk_enable_gpll0(priv->base, &gpll0_vote_clk);
Mateusz Kulikowski2507d822016-03-31 23:12:32 +020091 clk_enable_cbc(priv->base + SDCC_APPS_CBCR(slot));
92
93 return rate;
94}
95
96static const struct bcr_regs uart2_regs = {
97 .cfg_rcgr = BLSP1_UART2_APPS_CFG_RCGR,
98 .cmd_rcgr = BLSP1_UART2_APPS_CMD_RCGR,
99 .M = BLSP1_UART2_APPS_M,
100 .N = BLSP1_UART2_APPS_N,
101 .D = BLSP1_UART2_APPS_D,
102};
103
Jorge Ramirez-Ortiz92c1eff2018-01-10 11:33:49 +0100104/* UART: 115200 */
Mateusz Kulikowski2507d822016-03-31 23:12:32 +0200105static int clk_init_uart(struct msm_clk_priv *priv)
106{
Ramon Friedae299772018-05-16 12:13:39 +0300107 /* Enable AHB clock */
108 clk_enable_vote_clk(priv->base, &gcc_blsp1_ahb_clk);
109
Mateusz Kulikowski2507d822016-03-31 23:12:32 +0200110 /* 7372800 uart block clock @ GPLL0 */
111 clk_rcg_set_rate_mnd(priv->base, &uart2_regs, 1, 144, 15625,
Caleb Connollyfbacc672023-11-07 12:41:04 +0000112 CFG_CLK_SRC_GPLL0, 16);
Ramon Friedae299772018-05-16 12:13:39 +0300113
114 /* Vote for gpll0 clock */
115 clk_enable_gpll0(priv->base, &gpll0_vote_clk);
116
Mateusz Kulikowski2507d822016-03-31 23:12:32 +0200117 /* Enable core clk */
118 clk_enable_cbc(priv->base + BLSP1_UART2_APPS_CBCR);
119
120 return 0;
121}
122
Caleb Connolly10a0abb2023-11-07 12:41:03 +0000123static ulong apq8016_clk_set_rate(struct clk *clk, ulong rate)
Mateusz Kulikowski2507d822016-03-31 23:12:32 +0200124{
Stephen Warrena9622432016-06-17 09:44:00 -0600125 struct msm_clk_priv *priv = dev_get_priv(clk->dev);
Mateusz Kulikowski2507d822016-03-31 23:12:32 +0200126
Stephen Warrena9622432016-06-17 09:44:00 -0600127 switch (clk->id) {
Mateusz Kulikowski2507d822016-03-31 23:12:32 +0200128 case 0: /* SDC1 */
129 return clk_init_sdc(priv, 0, rate);
130 break;
131 case 1: /* SDC2 */
132 return clk_init_sdc(priv, 1, rate);
133 break;
134 case 4: /* UART2 */
135 return clk_init_uart(priv);
136 break;
137 default:
138 return 0;
139 }
140}
Sumit Garg1d1ca6e2022-08-04 19:57:14 +0530141
Caleb Connolly10a0abb2023-11-07 12:41:03 +0000142static struct msm_clk_data apq8016_clk_data = {
143 .set_rate = apq8016_clk_set_rate,
144};
Konrad Dybcio6c0b8442023-11-07 12:41:01 +0000145
146static const struct udevice_id gcc_apq8016_of_match[] = {
147 {
Caleb Connolly3e88e6e2024-02-26 17:26:09 +0000148 .compatible = "qcom,gcc-msm8916",
Caleb Connolly10a0abb2023-11-07 12:41:03 +0000149 .data = (ulong)&apq8016_clk_data,
Konrad Dybcio6c0b8442023-11-07 12:41:01 +0000150 },
151 { }
152};
153
154U_BOOT_DRIVER(gcc_apq8016) = {
155 .name = "gcc_apq8016",
156 .id = UCLASS_NOP,
157 .of_match = gcc_apq8016_of_match,
158 .bind = qcom_cc_bind,
159 .flags = DM_FLAG_PRE_RELOC,
160};