123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
- */
- #define pr_fmt(fmt) "%s: " fmt, __func__
- #include <linux/kernel.h>
- #include <linux/err.h>
- #include <linux/delay.h>
- #include <linux/clk/msm-clk-provider.h>
- #include <linux/clk/msm-clk.h>
- #include <linux/workqueue.h>
- #include <linux/clk/msm-clock-generic.h>
- #include <dt-bindings/clock/msm-clocks-8996.h>
- #include "pll_drv.h"
- #include "dsi_pll.h"
- #include "dsi_pll_8996.h"
- #define VCO_DELAY_USEC 1
- static struct dsi_pll_db pll_db[DSI_PLL_NUM];
- static const struct clk_ops n2_clk_src_ops;
- static const struct clk_ops shadow_n2_clk_src_ops;
- static const struct clk_ops byte_clk_src_ops;
- static const struct clk_ops post_n1_div_clk_src_ops;
- static const struct clk_ops shadow_post_n1_div_clk_src_ops;
- static const struct clk_ops clk_ops_gen_mux_dsi;
- /* Op structures */
- static const struct clk_ops clk_ops_dsi_vco = {
- .set_rate = pll_vco_set_rate_8996,
- .round_rate = pll_vco_round_rate_8996,
- .handoff = pll_vco_handoff_8996,
- .prepare = pll_vco_prepare_8996,
- .unprepare = pll_vco_unprepare_8996,
- };
- static struct clk_div_ops post_n1_div_ops = {
- .set_div = post_n1_div_set_div,
- .get_div = post_n1_div_get_div,
- };
- static struct clk_div_ops n2_div_ops = { /* hr_oclk3 */
- .set_div = n2_div_set_div,
- .get_div = n2_div_get_div,
- };
- static struct clk_mux_ops mdss_byte_mux_ops = {
- .set_mux_sel = set_mdss_byte_mux_sel_8996,
- .get_mux_sel = get_mdss_byte_mux_sel_8996,
- };
- static struct clk_mux_ops mdss_pixel_mux_ops = {
- .set_mux_sel = set_mdss_pixel_mux_sel_8996,
- .get_mux_sel = get_mdss_pixel_mux_sel_8996,
- };
- /* Shadow ops for dynamic refresh */
- static const struct clk_ops clk_ops_shadow_dsi_vco = {
- .set_rate = shadow_pll_vco_set_rate_8996,
- .round_rate = pll_vco_round_rate_8996,
- .handoff = shadow_pll_vco_handoff_8996,
- };
- static struct clk_div_ops shadow_post_n1_div_ops = {
- .set_div = post_n1_div_set_div,
- };
- static struct clk_div_ops shadow_n2_div_ops = {
- .set_div = shadow_n2_div_set_div,
- };
- static struct dsi_pll_vco_clk dsi0pll_vco_clk = {
- .ref_clk_rate = 19200000UL,
- .min_rate = 1300000000UL,
- .max_rate = 2600000000UL,
- .pll_en_seq_cnt = 1,
- .pll_enable_seqs[0] = dsi_pll_enable_seq_8996,
- .c = {
- .dbg_name = "dsi0pll_vco_clk_8996",
- .ops = &clk_ops_dsi_vco,
- CLK_INIT(dsi0pll_vco_clk.c),
- },
- };
- static struct dsi_pll_vco_clk dsi0pll_shadow_vco_clk = {
- .ref_clk_rate = 19200000u,
- .min_rate = 1300000000u,
- .max_rate = 2600000000u,
- .c = {
- .dbg_name = "dsi0pll_shadow_vco_clk",
- .ops = &clk_ops_shadow_dsi_vco,
- CLK_INIT(dsi0pll_shadow_vco_clk.c),
- },
- };
- static struct dsi_pll_vco_clk dsi1pll_vco_clk = {
- .ref_clk_rate = 19200000UL,
- .min_rate = 1300000000UL,
- .max_rate = 2600000000UL,
- .pll_en_seq_cnt = 1,
- .pll_enable_seqs[0] = dsi_pll_enable_seq_8996,
- .c = {
- .dbg_name = "dsi1pll_vco_clk_8996",
- .ops = &clk_ops_dsi_vco,
- CLK_INIT(dsi1pll_vco_clk.c),
- },
- };
- static struct dsi_pll_vco_clk dsi1pll_shadow_vco_clk = {
- .ref_clk_rate = 19200000u,
- .min_rate = 1300000000u,
- .max_rate = 2600000000u,
- .pll_en_seq_cnt = 1,
- .pll_enable_seqs[0] = dsi_pll_enable_seq_8996,
- .c = {
- .dbg_name = "dsi1pll_shadow_vco_clk",
- .ops = &clk_ops_shadow_dsi_vco,
- CLK_INIT(dsi1pll_shadow_vco_clk.c),
- },
- };
- static struct div_clk dsi0pll_post_n1_div_clk = {
- .data = {
- .max_div = 15,
- .min_div = 1,
- },
- .ops = &post_n1_div_ops,
- .c = {
- .parent = &dsi0pll_vco_clk.c,
- .dbg_name = "dsi0pll_post_n1_div_clk",
- .ops = &post_n1_div_clk_src_ops,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi0pll_post_n1_div_clk.c),
- },
- };
- static struct div_clk dsi0pll_shadow_post_n1_div_clk = {
- .data = {
- .max_div = 15,
- .min_div = 1,
- },
- .ops = &shadow_post_n1_div_ops,
- .c = {
- .parent = &dsi0pll_shadow_vco_clk.c,
- .dbg_name = "dsi0pll_shadow_post_n1_div_clk",
- .ops = &shadow_post_n1_div_clk_src_ops,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi0pll_shadow_post_n1_div_clk.c),
- },
- };
- static struct div_clk dsi1pll_post_n1_div_clk = {
- .data = {
- .max_div = 15,
- .min_div = 1,
- },
- .ops = &post_n1_div_ops,
- .c = {
- .parent = &dsi1pll_vco_clk.c,
- .dbg_name = "dsi1pll_post_n1_div_clk",
- .ops = &post_n1_div_clk_src_ops,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi1pll_post_n1_div_clk.c),
- },
- };
- static struct div_clk dsi1pll_shadow_post_n1_div_clk = {
- .data = {
- .max_div = 15,
- .min_div = 1,
- },
- .ops = &shadow_post_n1_div_ops,
- .c = {
- .parent = &dsi1pll_shadow_vco_clk.c,
- .dbg_name = "dsi1pll_shadow_post_n1_div_clk",
- .ops = &shadow_post_n1_div_clk_src_ops,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi1pll_shadow_post_n1_div_clk.c),
- },
- };
- static struct div_clk dsi0pll_n2_div_clk = {
- .data = {
- .max_div = 15,
- .min_div = 1,
- },
- .ops = &n2_div_ops,
- .c = {
- .parent = &dsi0pll_post_n1_div_clk.c,
- .dbg_name = "dsi0pll_n2_div_clk",
- .ops = &n2_clk_src_ops,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi0pll_n2_div_clk.c),
- },
- };
- static struct div_clk dsi0pll_shadow_n2_div_clk = {
- .data = {
- .max_div = 15,
- .min_div = 1,
- },
- .ops = &shadow_n2_div_ops,
- .c = {
- .parent = &dsi0pll_shadow_post_n1_div_clk.c,
- .dbg_name = "dsi0pll_shadow_n2_div_clk",
- .ops = &shadow_n2_clk_src_ops,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi0pll_shadow_n2_div_clk.c),
- },
- };
- static struct div_clk dsi1pll_n2_div_clk = {
- .data = {
- .max_div = 15,
- .min_div = 1,
- },
- .ops = &n2_div_ops,
- .c = {
- .parent = &dsi1pll_post_n1_div_clk.c,
- .dbg_name = "dsi1pll_n2_div_clk",
- .ops = &n2_clk_src_ops,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi1pll_n2_div_clk.c),
- },
- };
- static struct div_clk dsi1pll_shadow_n2_div_clk = {
- .data = {
- .max_div = 15,
- .min_div = 1,
- },
- .ops = &shadow_n2_div_ops,
- .c = {
- .parent = &dsi1pll_shadow_post_n1_div_clk.c,
- .dbg_name = "dsi1pll_shadow_n2_div_clk",
- .ops = &shadow_n2_clk_src_ops,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi1pll_shadow_n2_div_clk.c),
- },
- };
- static struct div_clk dsi0pll_pixel_clk_src = {
- .data = {
- .div = 2,
- .min_div = 2,
- .max_div = 2,
- },
- .c = {
- .parent = &dsi0pll_n2_div_clk.c,
- .dbg_name = "dsi0pll_pixel_clk_src",
- .ops = &clk_ops_div,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi0pll_pixel_clk_src.c),
- },
- };
- static struct div_clk dsi0pll_shadow_pixel_clk_src = {
- .data = {
- .div = 2,
- .min_div = 2,
- .max_div = 2,
- },
- .c = {
- .parent = &dsi0pll_shadow_n2_div_clk.c,
- .dbg_name = "dsi0pll_shadow_pixel_clk_src",
- .ops = &clk_ops_div,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi0pll_shadow_pixel_clk_src.c),
- },
- };
- static struct div_clk dsi1pll_pixel_clk_src = {
- .data = {
- .div = 2,
- .min_div = 2,
- .max_div = 2,
- },
- .c = {
- .parent = &dsi1pll_n2_div_clk.c,
- .dbg_name = "dsi1pll_pixel_clk_src",
- .ops = &clk_ops_div,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi1pll_pixel_clk_src.c),
- },
- };
- static struct div_clk dsi1pll_shadow_pixel_clk_src = {
- .data = {
- .div = 2,
- .min_div = 2,
- .max_div = 2,
- },
- .c = {
- .parent = &dsi1pll_shadow_n2_div_clk.c,
- .dbg_name = "dsi1pll_shadow_pixel_clk_src",
- .ops = &clk_ops_div,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi1pll_shadow_pixel_clk_src.c),
- },
- };
- static struct mux_clk dsi0pll_pixel_clk_mux = {
- .num_parents = 2,
- .parents = (struct clk_src[]) {
- {&dsi0pll_pixel_clk_src.c, 0},
- {&dsi0pll_shadow_pixel_clk_src.c, 1},
- },
- .ops = &mdss_pixel_mux_ops,
- .c = {
- .parent = &dsi0pll_pixel_clk_src.c,
- .dbg_name = "dsi0pll_pixel_clk_mux",
- .ops = &clk_ops_gen_mux_dsi,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi0pll_pixel_clk_mux.c),
- }
- };
- static struct mux_clk dsi1pll_pixel_clk_mux = {
- .num_parents = 2,
- .parents = (struct clk_src[]) {
- {&dsi1pll_pixel_clk_src.c, 0},
- {&dsi1pll_shadow_pixel_clk_src.c, 1},
- },
- .ops = &mdss_pixel_mux_ops,
- .c = {
- .parent = &dsi1pll_pixel_clk_src.c,
- .dbg_name = "dsi1pll_pixel_clk_mux",
- .ops = &clk_ops_gen_mux_dsi,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi1pll_pixel_clk_mux.c),
- }
- };
- static struct div_clk dsi0pll_byte_clk_src = {
- .data = {
- .div = 8,
- .min_div = 8,
- .max_div = 8,
- },
- .c = {
- .parent = &dsi0pll_post_n1_div_clk.c,
- .dbg_name = "dsi0pll_byte_clk_src",
- .ops = &clk_ops_div,
- CLK_INIT(dsi0pll_byte_clk_src.c),
- },
- };
- static struct div_clk dsi0pll_shadow_byte_clk_src = {
- .data = {
- .div = 8,
- .min_div = 8,
- .max_div = 8,
- },
- .c = {
- .parent = &dsi0pll_shadow_post_n1_div_clk.c,
- .dbg_name = "dsi0pll_shadow_byte_clk_src",
- .ops = &clk_ops_div,
- CLK_INIT(dsi0pll_shadow_byte_clk_src.c),
- },
- };
- static struct div_clk dsi1pll_byte_clk_src = {
- .data = {
- .div = 8,
- .min_div = 8,
- .max_div = 8,
- },
- .c = {
- .parent = &dsi1pll_post_n1_div_clk.c,
- .dbg_name = "dsi1pll_byte_clk_src",
- .ops = &clk_ops_div,
- CLK_INIT(dsi1pll_byte_clk_src.c),
- },
- };
- static struct div_clk dsi1pll_shadow_byte_clk_src = {
- .data = {
- .div = 8,
- .min_div = 8,
- .max_div = 8,
- },
- .c = {
- .parent = &dsi1pll_shadow_post_n1_div_clk.c,
- .dbg_name = "dsi1pll_shadow_byte_clk_src",
- .ops = &clk_ops_div,
- CLK_INIT(dsi1pll_shadow_byte_clk_src.c),
- },
- };
- static struct mux_clk dsi0pll_byte_clk_mux = {
- .num_parents = 2,
- .parents = (struct clk_src[]) {
- {&dsi0pll_byte_clk_src.c, 0},
- {&dsi0pll_shadow_byte_clk_src.c, 1},
- },
- .ops = &mdss_byte_mux_ops,
- .c = {
- .parent = &dsi0pll_byte_clk_src.c,
- .dbg_name = "dsi0pll_byte_clk_mux",
- .ops = &clk_ops_gen_mux_dsi,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi0pll_byte_clk_mux.c),
- }
- };
- static struct mux_clk dsi1pll_byte_clk_mux = {
- .num_parents = 2,
- .parents = (struct clk_src[]) {
- {&dsi1pll_byte_clk_src.c, 0},
- {&dsi1pll_shadow_byte_clk_src.c, 1},
- },
- .ops = &mdss_byte_mux_ops,
- .c = {
- .parent = &dsi1pll_byte_clk_src.c,
- .dbg_name = "dsi1pll_byte_clk_mux",
- .ops = &clk_ops_gen_mux_dsi,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi1pll_byte_clk_mux.c),
- }
- };
- static struct clk_lookup mdss_dsi_pllcc_8996[] = {
- CLK_LIST(dsi0pll_byte_clk_mux),
- CLK_LIST(dsi0pll_byte_clk_src),
- CLK_LIST(dsi0pll_pixel_clk_mux),
- CLK_LIST(dsi0pll_pixel_clk_src),
- CLK_LIST(dsi0pll_n2_div_clk),
- CLK_LIST(dsi0pll_post_n1_div_clk),
- CLK_LIST(dsi0pll_vco_clk),
- CLK_LIST(dsi0pll_shadow_byte_clk_src),
- CLK_LIST(dsi0pll_shadow_pixel_clk_src),
- CLK_LIST(dsi0pll_shadow_n2_div_clk),
- CLK_LIST(dsi0pll_shadow_post_n1_div_clk),
- CLK_LIST(dsi0pll_shadow_vco_clk),
- };
- static struct clk_lookup mdss_dsi_pllcc_8996_1[] = {
- CLK_LIST(dsi1pll_byte_clk_mux),
- CLK_LIST(dsi1pll_byte_clk_src),
- CLK_LIST(dsi1pll_pixel_clk_mux),
- CLK_LIST(dsi1pll_pixel_clk_src),
- CLK_LIST(dsi1pll_n2_div_clk),
- CLK_LIST(dsi1pll_post_n1_div_clk),
- CLK_LIST(dsi1pll_vco_clk),
- CLK_LIST(dsi1pll_shadow_byte_clk_src),
- CLK_LIST(dsi1pll_shadow_pixel_clk_src),
- CLK_LIST(dsi1pll_shadow_n2_div_clk),
- CLK_LIST(dsi1pll_shadow_post_n1_div_clk),
- CLK_LIST(dsi1pll_shadow_vco_clk),
- };
- int dsi_pll_clock_register_8996(struct platform_device *pdev,
- struct mdss_pll_resources *pll_res)
- {
- int rc = 0, ndx;
- int const ssc_freq_default = 31500; /* default h/w recommended value */
- int const ssc_ppm_default = 5000; /* default h/w recommended value */
- struct dsi_pll_db *pdb;
- if (pll_res->index >= DSI_PLL_NUM) {
- pr_err("pll ndx=%d is NOT supported\n", pll_res->index);
- return -EINVAL;
- }
- ndx = pll_res->index;
- pdb = &pll_db[ndx];
- pll_res->priv = pdb;
- pdb->pll = pll_res;
- ndx++;
- ndx %= DSI_PLL_NUM;
- pdb->next = &pll_db[ndx];
- /* Set clock source operations */
- /* hr_oclk3, pixel */
- n2_clk_src_ops = clk_ops_slave_div;
- n2_clk_src_ops.prepare = mdss_pll_div_prepare;
- shadow_n2_clk_src_ops = clk_ops_slave_div;
- /* hr_ockl2, byte, vco pll */
- post_n1_div_clk_src_ops = clk_ops_div;
- post_n1_div_clk_src_ops.prepare = mdss_pll_div_prepare;
- shadow_post_n1_div_clk_src_ops = clk_ops_div;
- byte_clk_src_ops = clk_ops_div;
- byte_clk_src_ops.prepare = mdss_pll_div_prepare;
- clk_ops_gen_mux_dsi = clk_ops_gen_mux;
- clk_ops_gen_mux_dsi.round_rate = parent_round_rate;
- clk_ops_gen_mux_dsi.set_rate = parent_set_rate;
- if (pll_res->ssc_en) {
- if (!pll_res->ssc_freq)
- pll_res->ssc_freq = ssc_freq_default;
- if (!pll_res->ssc_ppm)
- pll_res->ssc_ppm = ssc_ppm_default;
- }
- /* Set client data to mux, div and vco clocks. */
- if (pll_res->index == DSI_PLL_1) {
- dsi1pll_byte_clk_src.priv = pll_res;
- dsi1pll_pixel_clk_src.priv = pll_res;
- dsi1pll_post_n1_div_clk.priv = pll_res;
- dsi1pll_n2_div_clk.priv = pll_res;
- dsi1pll_vco_clk.priv = pll_res;
- dsi1pll_shadow_byte_clk_src.priv = pll_res;
- dsi1pll_shadow_pixel_clk_src.priv = pll_res;
- dsi1pll_shadow_post_n1_div_clk.priv = pll_res;
- dsi1pll_shadow_n2_div_clk.priv = pll_res;
- dsi1pll_shadow_vco_clk.priv = pll_res;
- pll_res->vco_delay = VCO_DELAY_USEC;
- rc = of_msm_clock_register(pdev->dev.of_node,
- mdss_dsi_pllcc_8996_1,
- ARRAY_SIZE(mdss_dsi_pllcc_8996_1));
- } else {
- dsi0pll_byte_clk_src.priv = pll_res;
- dsi0pll_pixel_clk_src.priv = pll_res;
- dsi0pll_post_n1_div_clk.priv = pll_res;
- dsi0pll_n2_div_clk.priv = pll_res;
- dsi0pll_vco_clk.priv = pll_res;
- dsi0pll_shadow_byte_clk_src.priv = pll_res;
- dsi0pll_shadow_pixel_clk_src.priv = pll_res;
- dsi0pll_shadow_post_n1_div_clk.priv = pll_res;
- dsi0pll_shadow_n2_div_clk.priv = pll_res;
- dsi0pll_shadow_vco_clk.priv = pll_res;
- pll_res->vco_delay = VCO_DELAY_USEC;
- rc = of_msm_clock_register(pdev->dev.of_node,
- mdss_dsi_pllcc_8996,
- ARRAY_SIZE(mdss_dsi_pllcc_8996));
- }
- if (!rc) {
- pr_info("Registered DSI PLL ndx=%d clocks successfully\n",
- pll_res->index);
- }
- return rc;
- }
|